@genai-fi/nanogpt 0.24.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -281
- package/dist/{RealDiv-CNsvC4AU.js → RealDiv-CSnvtN2E.js} +20 -20
- package/dist/{Reshape-dnm9bO3B.js → Reshape-BlylqwWy.js} +12 -12
- package/dist/TeachableLLM.d.ts +10 -14
- package/dist/TeachableLLM.js +201 -2
- package/dist/api/responses.d.ts +81 -0
- package/dist/api/responses.js +169 -0
- package/dist/api/training.d.ts +70 -0
- package/dist/api/training.js +205 -0
- package/dist/data/docx.js +9 -3036
- package/dist/data/stream.d.ts +2 -2
- package/dist/data/textLoader.d.ts +1 -1
- package/dist/data/textLoader.js +1 -1
- package/dist/data.d.ts +3 -0
- package/dist/data.js +12 -0
- package/dist/{dist-BqAU9-yi.js → dist-CwK5S7Ls.js} +2168 -2168
- package/dist/{gpgpu_math-DBYEAAdI.js → gpgpu_math-20tPK8LM.js} +458 -458
- package/dist/{Generator.d.ts → inference/Generator.d.ts} +16 -44
- package/dist/inference/Generator.js +271 -0
- package/dist/inference/tokenisePrompt.d.ts +4 -0
- package/dist/inference/tokenisePrompt.js +13 -0
- package/dist/inference/types.d.ts +44 -8
- package/dist/inference/utilities.d.ts +9 -0
- package/dist/inference/utilities.js +20 -0
- package/dist/jszip.min-DKa1Rjyn.js +3033 -0
- package/dist/{kernel_funcs_utils-D-mATnGR.js → kernel_funcs_utils-ql8Y8qPn.js} +96 -93
- package/dist/layers/MLP.d.ts +1 -1
- package/dist/layers/PositionEmbedding.d.ts +2 -1
- package/dist/layers/PositionEmbedding.js +1 -1
- package/dist/layers/RMSNorm.d.ts +1 -1
- package/dist/layers/TiedEmbedding.js +1 -1
- package/dist/layers.d.ts +4 -0
- package/dist/layers.js +14 -0
- package/dist/loader/load.js +58 -2
- package/dist/loader/loadHF.d.ts +1 -1
- package/dist/loader/loadHF.js +17 -2
- package/dist/loader/loadTransformers.js +46 -2
- package/dist/loader/newZipLoad.js +25 -2
- package/dist/loader/oldZipLoad.d.ts +1 -1
- package/dist/loader/oldZipLoad.js +37 -2
- package/dist/loader/save.js +75 -2
- package/dist/loader/types.d.ts +3 -3
- package/dist/main.d.ts +34 -35
- package/dist/main.js +12327 -20
- package/dist/{matMulGelu-BAIgQaRx.js → matMulGelu-CBoqTZM7.js} +2 -2
- package/dist/models/NanoGPTV1.js +95 -2
- package/dist/models/NanoGPTV2.js +86 -2
- package/dist/models/factory.js +13 -2
- package/dist/models/model.js +76 -2
- package/dist/models.d.ts +4 -0
- package/dist/models.js +14 -0
- package/dist/ops/dot16.js +1 -1
- package/dist/ops/matMulGelu.js +1 -1
- package/dist/ops/webgl/adamAdjust.js +1 -1
- package/dist/ops/webgl/fusedSoftmax.js +2 -2
- package/dist/ops/webgl/gelu.js +2 -2
- package/dist/ops/webgl/log.js +5 -5
- package/dist/ops/webgl/matMulGelu.js +1 -1
- package/dist/ops/webgl/matMulMul.js +1 -1
- package/dist/{tfjs_backend-CydPRQTc.js → tfjs_backend-h5weiy1O.js} +36 -36
- package/dist/tokenise.d.ts +4 -0
- package/dist/tokenise.js +15 -0
- package/dist/training/BasicTrainer.d.ts +5 -10
- package/dist/training/BasicTrainer.js +80 -88
- package/dist/training/configure.d.ts +3 -0
- package/dist/training/configure.js +32 -0
- package/dist/training/factory.d.ts +6 -0
- package/dist/training/factory.js +8 -0
- package/dist/training/prepareData.d.ts +22 -0
- package/dist/training/prepareData.js +49 -0
- package/dist/training/tasks/tokenStream.d.ts +2 -1
- package/dist/training/types.d.ts +14 -1
- package/dist/training/validateOptions.d.ts +2 -0
- package/dist/training/validateOptions.js +19 -0
- package/dist/utilities/arrayShape.d.ts +1 -0
- package/dist/utilities/arrayShape.js +8 -0
- package/dist/utilities/waitForModel.d.ts +1 -1
- package/dist/v4-BK7K-jy_.js +30 -0
- package/package.json +8 -2
- package/dist/Generator.js +0 -2
- package/dist/Trainer-Cr7csbTD.js +0 -228
- package/dist/Trainer.d.ts +0 -45
- package/dist/Trainer.js +0 -2
- package/dist/main-Dz72vadm.js +0 -13267
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { _n as e, di as t, kt as n, ni as r, oi as i, qt as a } from "../dist-Da20xy8E.js";
|
|
2
2
|
import { AdamWOptimizer as o } from "./AdamW.js";
|
|
3
|
-
import
|
|
4
|
-
import l from "./
|
|
5
|
-
import u from "
|
|
3
|
+
import s from "../utilities/profile.js";
|
|
4
|
+
import { calculateAccuracy as c, calculateLoss as l } from "./loss.js";
|
|
5
|
+
import u from "./Evaluator.js";
|
|
6
6
|
import { createTensorStatistics as d } from "../checks/weights.js";
|
|
7
|
+
import f from "./configure.js";
|
|
7
8
|
//#region lib/training/BasicTrainer.ts
|
|
8
|
-
var
|
|
9
|
+
var p = {
|
|
9
10
|
logInterval: 1,
|
|
10
11
|
maxEpochs: 100,
|
|
11
|
-
|
|
12
|
+
method: { type: "pretraining" },
|
|
12
13
|
batchSize: 32
|
|
13
|
-
},
|
|
14
|
+
}, m = {
|
|
14
15
|
learningRate: 3e-4,
|
|
15
16
|
beta1: .9,
|
|
16
17
|
beta2: .99,
|
|
@@ -21,10 +22,11 @@ var f = {
|
|
|
21
22
|
epochSteps: 1e4,
|
|
22
23
|
minLearningRate: 1e-5,
|
|
23
24
|
lossScaling: 1
|
|
24
|
-
},
|
|
25
|
+
}, h = class {
|
|
25
26
|
tokenizer;
|
|
26
27
|
model;
|
|
27
28
|
optimizer;
|
|
29
|
+
log = [];
|
|
28
30
|
running = !1;
|
|
29
31
|
lastState;
|
|
30
32
|
_gradientCheckpointing = !1;
|
|
@@ -35,9 +37,10 @@ var f = {
|
|
|
35
37
|
_labelSmoothing = 0;
|
|
36
38
|
_layerDrop = 0;
|
|
37
39
|
_dropout = 0;
|
|
40
|
+
_tokensProcessed = 0;
|
|
38
41
|
constructor(e, t, n, r) {
|
|
39
42
|
this.tokenizer = t, this.model = e, this.optimizerConfig = {
|
|
40
|
-
...
|
|
43
|
+
...m,
|
|
41
44
|
...n,
|
|
42
45
|
lossScaling: n?.lossScaling ?? e.lossScaling
|
|
43
46
|
};
|
|
@@ -68,8 +71,11 @@ var f = {
|
|
|
68
71
|
setMetrics(e) {
|
|
69
72
|
this.metrics = new Set(e);
|
|
70
73
|
}
|
|
74
|
+
configure(e) {
|
|
75
|
+
this.setGradientCheckpointing(e?.gradientCheckpointing || !1), this.setMixedPrecision(e?.mixedPrecision || !1), this.setLabelSmoothing(e?.labelSmoothing || 0), this.setDropout(e?.dropout || 0), this.setLayerDrop(e?.layerDrop || 0), this.lastState || this.setLearningRate(e?.learningRate || .001), f(this.model, e);
|
|
76
|
+
}
|
|
71
77
|
reset() {
|
|
72
|
-
this.lastState = void 0, this.running = !1;
|
|
78
|
+
this.lastState = void 0, this.running = !1, this.log = [];
|
|
73
79
|
}
|
|
74
80
|
stop() {
|
|
75
81
|
this.running = !1;
|
|
@@ -77,6 +83,9 @@ var f = {
|
|
|
77
83
|
get isRunning() {
|
|
78
84
|
return this.running;
|
|
79
85
|
}
|
|
86
|
+
get tokensProcessed() {
|
|
87
|
+
return this._tokensProcessed;
|
|
88
|
+
}
|
|
80
89
|
getOptimizer() {
|
|
81
90
|
return this.optimizer;
|
|
82
91
|
}
|
|
@@ -97,7 +106,7 @@ var f = {
|
|
|
97
106
|
trainingDuration: e.duration
|
|
98
107
|
});
|
|
99
108
|
}
|
|
100
|
-
trainStep(n, o,
|
|
109
|
+
trainStep(n, o, s = !1, u = !1) {
|
|
101
110
|
return t(() => {
|
|
102
111
|
this.model.getProfiler()?.startMemory();
|
|
103
112
|
let { xs: t, ys: d } = o, { value: f, grads: p } = a(() => {
|
|
@@ -108,12 +117,12 @@ var f = {
|
|
|
108
117
|
dropout: this._dropout,
|
|
109
118
|
layerDrop: this._layerDrop,
|
|
110
119
|
ropePositionOffset: 0
|
|
111
|
-
}, t), a =
|
|
112
|
-
this.metrics.has("accuracy") && (n.accuracy =
|
|
120
|
+
}, t), a = l(r, d, this.maskedLoss, !1, this._labelSmoothing);
|
|
121
|
+
this.metrics.has("accuracy") && (n.accuracy = c(r, d), i(n.accuracy)), r.dispose();
|
|
113
122
|
let o = a.mul(e(this.optimizerConfig.lossScaling));
|
|
114
123
|
return a.dispose(), o;
|
|
115
124
|
});
|
|
116
|
-
if (
|
|
125
|
+
if (s) this.model.getProfiler()?.endMemory("Training");
|
|
117
126
|
else {
|
|
118
127
|
let e = this.optimizer.applyGradients(p);
|
|
119
128
|
this.metrics.has("gradientNorm") ? (n.gradientNorm = e, i(e)) : (n.gradientNorm = void 0, e.dispose());
|
|
@@ -152,76 +161,47 @@ var f = {
|
|
|
152
161
|
...this.lastState || {}
|
|
153
162
|
};
|
|
154
163
|
}
|
|
155
|
-
async stepDataset(e, t, n) {
|
|
156
|
-
let { logInterval: i = 10 } = {
|
|
157
|
-
...f,
|
|
158
|
-
...t
|
|
159
|
-
};
|
|
160
|
-
t.metrics && this.setMetrics(t.metrics);
|
|
161
|
-
let a = Date.now(), o = this.createEmptyState();
|
|
162
|
-
this.lastState = o, await this.dummyPass(), this.metrics.has("memoryUsage") && (this.model.getProfiler() || this.model.setProfiler(new u())), this.running = !0, o.logStartTime = a;
|
|
163
|
-
let s = n ? new l(this.model, n, this.maskedLoss) : void 0, c = await e.iterator();
|
|
164
|
-
try {
|
|
165
|
-
for (; this.running;) {
|
|
166
|
-
let e = await c.next();
|
|
167
|
-
if (e.done) break;
|
|
168
|
-
let n = e.value, r = this.trainStep(o, n, !1);
|
|
169
|
-
if (t.debug) {
|
|
170
|
-
let e = (await r.data())[0];
|
|
171
|
-
if (isNaN(e) || !isFinite(e)) throw console.error("Invalid loss value:", e), console.error("Batch xs:", n.xs.toString()), console.error("Batch ys:", n.ys.toString()), console.error("State:", o), Error("Loss is NaN or Infinity");
|
|
172
|
-
console.log(`Step ${o.step}: Loss = ${e}`);
|
|
173
|
-
}
|
|
174
|
-
n.xs.dispose(), n.ys.dispose(), o.step++, o.totalSteps++, o.step % i === 0 ? await this.performLogging(r, n.xs.shape[0], t, s) : (o.gradientNorm &&= (o.gradientNorm.dispose(), void 0), o.accuracy &&= (o.accuracy.dispose(), void 0)), r.dispose();
|
|
175
|
-
}
|
|
176
|
-
} catch (e) {
|
|
177
|
-
throw console.error("Training error:", e), e;
|
|
178
|
-
}
|
|
179
|
-
throw this.model.trainingState = {
|
|
180
|
-
steps: o.totalSteps,
|
|
181
|
-
learningRate: this.optimizer.lr,
|
|
182
|
-
batchSize: t.batchSize || 32,
|
|
183
|
-
loss: o.lastLoss,
|
|
184
|
-
tokensProcessed: o.totalSteps * (t.batchSize || 32) * this.model.config.blockSize,
|
|
185
|
-
duration: o.trainingDuration
|
|
186
|
-
}, r(), this.running = !1, Error("No log returned before training stopped.");
|
|
187
|
-
}
|
|
188
164
|
async performLogging(e, t, n, r) {
|
|
189
|
-
let i =
|
|
190
|
-
|
|
191
|
-
let
|
|
165
|
+
let i = this.metrics.has("gradientStatistics"), a = this.lastState, o = [];
|
|
166
|
+
o.push(e.data()), o.push(a.accuracy ? a.accuracy.data() : null), o.push(a.gradientNorm ? a.gradientNorm.data() : null);
|
|
167
|
+
let s = await Promise.all(o), c = s[0]?.[0] ?? 0, l = s[1] ? s[1][0] : void 0, u = s[2] ? s[2][1] : void 0;
|
|
168
|
+
a.lastLoss = c, a.trainingDuration += Date.now() - a.logStartTime;
|
|
169
|
+
let f = a.totalSteps * t * this.model.config.blockSize;
|
|
170
|
+
this._tokensProcessed = f;
|
|
171
|
+
let p = {
|
|
192
172
|
trainingMetrics: {
|
|
193
|
-
loss:
|
|
194
|
-
perplexity: this.metrics.has("perplexity") ? Math.exp(
|
|
195
|
-
accuracy:
|
|
173
|
+
loss: a.lastLoss,
|
|
174
|
+
perplexity: this.metrics.has("perplexity") ? Math.exp(a.lastLoss) : void 0,
|
|
175
|
+
accuracy: l
|
|
196
176
|
},
|
|
197
|
-
step:
|
|
198
|
-
time: Date.now() -
|
|
199
|
-
gradientNorm:
|
|
177
|
+
step: a.step,
|
|
178
|
+
time: Date.now() - a.logStartTime,
|
|
179
|
+
gradientNorm: u,
|
|
200
180
|
batchSize: t,
|
|
201
181
|
learningRate: this.metrics.has("learningRate") ? this.optimizer.lr : void 0,
|
|
202
|
-
duration:
|
|
203
|
-
totalTokens:
|
|
204
|
-
tokensPerSecond:
|
|
182
|
+
duration: a.trainingDuration,
|
|
183
|
+
totalTokens: f,
|
|
184
|
+
tokensPerSecond: f / (a.trainingDuration / 1e3),
|
|
205
185
|
memoryUsage: this.metrics.has("memoryUsage") ? this.model.getProfiler()?.getPeakMemory() || 0 : void 0
|
|
206
186
|
};
|
|
207
|
-
if (
|
|
208
|
-
steps:
|
|
187
|
+
if (a.gradientNorm &&= (a.gradientNorm.dispose(), void 0), a.accuracy &&= (a.accuracy.dispose(), void 0), this.model.trainingState = {
|
|
188
|
+
steps: a.totalSteps,
|
|
209
189
|
learningRate: this.optimizer.lr,
|
|
210
190
|
batchSize: t,
|
|
211
|
-
loss:
|
|
212
|
-
tokensProcessed:
|
|
213
|
-
duration:
|
|
214
|
-
},
|
|
191
|
+
loss: a.lastLoss,
|
|
192
|
+
tokensProcessed: f,
|
|
193
|
+
duration: a.trainingDuration
|
|
194
|
+
}, i && a.gradients) {
|
|
215
195
|
let e = /* @__PURE__ */ new Map();
|
|
216
|
-
for (let [t, n] of Object.entries(
|
|
217
|
-
|
|
196
|
+
for (let [t, n] of Object.entries(a.gradients)) e.set(t, await d(n)), n.dispose();
|
|
197
|
+
p.gradientMetrics = e;
|
|
218
198
|
}
|
|
219
|
-
if (
|
|
220
|
-
let e = await
|
|
221
|
-
Array.isArray(e) ?
|
|
199
|
+
if (n) try {
|
|
200
|
+
let e = await n.evaluate(5);
|
|
201
|
+
Array.isArray(e) ? p.validationMetrics = {
|
|
222
202
|
loss: e[0].loss,
|
|
223
203
|
accuracy: e[0].accuracy
|
|
224
|
-
} : (
|
|
204
|
+
} : (a.validationLosses.push(e.loss), p.validationMetrics = {
|
|
225
205
|
accuracy: e.accuracy,
|
|
226
206
|
loss: e.loss,
|
|
227
207
|
perplexity: this.metrics.has("perplexity") ? Math.exp(e.loss) : void 0
|
|
@@ -229,37 +209,49 @@ var f = {
|
|
|
229
209
|
} catch (e) {
|
|
230
210
|
console.error("Validation error:", e);
|
|
231
211
|
}
|
|
232
|
-
|
|
212
|
+
this.log.push(p), r && r(p), a.logStartTime = Date.now();
|
|
233
213
|
}
|
|
234
|
-
async trainOnDataset(e, t, n) {
|
|
235
|
-
let { logInterval:
|
|
236
|
-
...
|
|
214
|
+
async trainOnDataset(e, t, n, i) {
|
|
215
|
+
let { logInterval: a = 10, maxEpochs: o = Infinity } = {
|
|
216
|
+
...p,
|
|
237
217
|
...t
|
|
238
|
-
}
|
|
218
|
+
};
|
|
219
|
+
this.log.length > 0 && this.resumeFromLog(this.log[this.log.length - 1]);
|
|
220
|
+
let c = o * (t?.epochSteps || 1e3);
|
|
239
221
|
t.metrics && this.setMetrics(t.metrics);
|
|
240
|
-
let
|
|
241
|
-
this.lastState =
|
|
242
|
-
let d =
|
|
222
|
+
let l = this.createEmptyState();
|
|
223
|
+
this.lastState = l, await this.dummyPass(), t?.metrics?.includes("memoryUsage") && (this.model.getProfiler() || this.model.setProfiler(new s()));
|
|
224
|
+
let d = Date.now();
|
|
225
|
+
this.running = !0, l.logStartTime = d;
|
|
226
|
+
let f = n ? new u(this.model, n, this.maskedLoss) : void 0, m = await e.iterator(), h = m.next();
|
|
243
227
|
try {
|
|
244
228
|
for (; this.running;) {
|
|
245
|
-
let e = await
|
|
246
|
-
if (e.done) break;
|
|
247
|
-
let n = e.value, r =
|
|
229
|
+
let e = await h;
|
|
230
|
+
if (h = m.next(), e.done) break;
|
|
231
|
+
let n = e.value, r = l.step % a === 0, o = (t?.metrics?.includes("gradientStatistics") || !1) && r, s = this.trainStep(l, n, !1, o);
|
|
248
232
|
if (t.debug) {
|
|
249
233
|
let e = (await s.data())[0];
|
|
250
|
-
if (isNaN(e) || !isFinite(e)) throw console.error("Invalid loss value:", e), console.error("Batch xs:", await n.xs.array()), console.error("Batch ys:", await n.ys.array()), console.error("State:",
|
|
251
|
-
console.log(`Step ${
|
|
234
|
+
if (isNaN(e) || !isFinite(e)) throw console.error("Invalid loss value:", e), console.error("Batch xs:", await n.xs.array()), console.error("Batch ys:", await n.ys.array()), console.error("State:", l), Error("Loss is NaN or Infinity");
|
|
235
|
+
console.log(`Step ${l.step}: Loss = ${e}`);
|
|
252
236
|
}
|
|
253
|
-
n.xs.dispose(), n.ys.dispose(),
|
|
237
|
+
n.xs.dispose(), n.ys.dispose(), l.step++, l.totalSteps++, r ? await this.performLogging(s, n.xs.shape[0], f, i) : (l.gradientNorm &&= (l.gradientNorm.dispose(), void 0), l.accuracy &&= (l.accuracy.dispose(), void 0)), s.dispose(), l.step >= c && this.stop();
|
|
254
238
|
}
|
|
255
239
|
} catch (e) {
|
|
256
240
|
throw console.error("Training error:", e), r(), e;
|
|
257
241
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
242
|
+
r(), this.running = !1, this.model.metaData.actionLog = this.model.metaData.actionLog || [];
|
|
243
|
+
let g = Date.now();
|
|
244
|
+
return this.model.metaData.actionLog.push({
|
|
245
|
+
action: "pretrain",
|
|
246
|
+
timestamp: g,
|
|
247
|
+
duration: g - d,
|
|
248
|
+
tokensProcessed: this.tokensProcessed,
|
|
249
|
+
options: t
|
|
250
|
+
}), {
|
|
251
|
+
losses: l.losses,
|
|
252
|
+
validationLosses: l.validationLosses
|
|
261
253
|
};
|
|
262
254
|
}
|
|
263
255
|
};
|
|
264
256
|
//#endregion
|
|
265
|
-
export {
|
|
257
|
+
export { h as default };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { t as e } from "../v4-BK7K-jy_.js";
|
|
2
|
+
//#region lib/training/configure.ts
|
|
3
|
+
function t(t, n) {
|
|
4
|
+
let r = n?.method.supervised || "full", i = n?.method.type || "pretraining";
|
|
5
|
+
if (i === "pretraining" && (t.hasLoRA() && t.detachLoRA(), t.weightStore.setTrainable(["*"]), n && (t.metaData.pretrainingSettings = n)), i === "supervised") {
|
|
6
|
+
if (r === "lora") {
|
|
7
|
+
if (n?.loraName) {
|
|
8
|
+
if (!t.hasLoRA(n.loraName)) if (n.loraConfig) t.createLoRA(n.loraName, n.loraConfig), t.attachLoRA(n.loraName);
|
|
9
|
+
else throw Error(`LoRA configuration must be provided to create LoRA with name ${n.loraName}`);
|
|
10
|
+
else if (t.attachLoRA(n.loraName), n.loraConfig) {
|
|
11
|
+
let e = t.lora;
|
|
12
|
+
(e.alpha !== n.loraConfig.alpha || e.rank !== n.loraConfig.rank) && (t.detachLoRA(), t.deleteLoRA(n.loraName), t.createLoRA(n.loraName, n.loraConfig), t.attachLoRA(n.loraName), console.warn("Resetting LoRA with new configuration."));
|
|
13
|
+
}
|
|
14
|
+
} else if (n?.loraConfig) if (t.hasLoRA()) {
|
|
15
|
+
let r = t.lora;
|
|
16
|
+
if (r.alpha !== n.loraConfig.alpha || r.rank !== n.loraConfig.rank) {
|
|
17
|
+
t.detachLoRA();
|
|
18
|
+
let r = n.loraName || e();
|
|
19
|
+
t.createLoRA(r, n.loraConfig), t.attachLoRA(r);
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
let r = n.loraName || e();
|
|
23
|
+
t.createLoRA(r, n.loraConfig), t.attachLoRA(r);
|
|
24
|
+
}
|
|
25
|
+
else if (!t.hasLoRA()) throw Error("LoRA configuration must be provided for lora SFT mode");
|
|
26
|
+
} else t.hasLoRA() && t.detachLoRA();
|
|
27
|
+
r === "last-layer" ? t.weightStore.setTrainable([`block_${t.config.nLayer - 1}_*`, "token_embedding"]) : r === "full" && t.weightStore.setTrainable(["*"]);
|
|
28
|
+
}
|
|
29
|
+
n?.trainableWeights && t.weightStore.setTrainable(n.trainableWeights);
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { t as default };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ModelForwardAttributes, default as Model } from '../../models/model';
|
|
2
|
+
import { TrainingOptions } from '../../training/types';
|
|
3
|
+
import { default as BasicTrainer } from '../../training/BasicTrainer';
|
|
4
|
+
import { ITokeniser } from '../../tokeniser/type';
|
|
5
|
+
import { AdamWOptimizer } from './AdamW';
|
|
6
|
+
export default function createTrainer(model: Model<ModelForwardAttributes>, tokenizer: ITokeniser, options?: TrainingOptions, optimizer?: AdamWOptimizer): BasicTrainer;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { default as Model, ModelForwardAttributes } from '../../models/model';
|
|
2
|
+
import { TrainingOptions } from './types';
|
|
3
|
+
import { TokenStore } from './tasks/TokenStore';
|
|
4
|
+
import { DatasetMetadata } from '../../loader/types';
|
|
5
|
+
import { ConversationStream } from '../../data/stream';
|
|
6
|
+
import { ITokeniser } from '../../tokeniser/type';
|
|
7
|
+
import { Dataset } from '@tensorflow/tfjs-data';
|
|
8
|
+
import { Tensor } from '@tensorflow/tfjs-core';
|
|
9
|
+
interface PrepareDataResult {
|
|
10
|
+
trainDataset: Dataset<{
|
|
11
|
+
xs: Tensor;
|
|
12
|
+
ys: Tensor;
|
|
13
|
+
}>;
|
|
14
|
+
validationDataset?: Dataset<{
|
|
15
|
+
xs: Tensor;
|
|
16
|
+
ys: Tensor;
|
|
17
|
+
}>;
|
|
18
|
+
totalTokens: number;
|
|
19
|
+
}
|
|
20
|
+
/** Take our training options, model, tokeniser, and tasks, and prepare the training and validation datasets in Tensorflow format. */
|
|
21
|
+
export default function prepareData(options: TrainingOptions, model: Model<ModelForwardAttributes>, tokeniser: ITokeniser, tasks: ConversationStream[] | Uint16Array[] | TokenStore, validation?: Uint16Array[] | TokenStore, datasets?: DatasetMetadata[]): Promise<PrepareDataResult>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TokenStore as e } from "./tasks/TokenStore.js";
|
|
2
|
+
import { tokensFromStreams as t } from "./tasks/tokenStream.js";
|
|
3
|
+
import { t as n } from "../DatasetBuilder-DU1G1OKX.js";
|
|
4
|
+
import { createTrainValidationDatasets as r, storeFromArray as i } from "./validation.js";
|
|
5
|
+
//#region lib/training/prepareData.ts
|
|
6
|
+
async function a(a, o, s, c, l, u) {
|
|
7
|
+
let d = a.loraName || a.loraConfig;
|
|
8
|
+
if (u && d) throw Error("Cannot specify datasets when using LoRA fine-tuning");
|
|
9
|
+
if (!u && !d) throw Error("Must specify datasets for non-LoRA training");
|
|
10
|
+
if (u) {
|
|
11
|
+
let e = o.metaData.pretrainingData || [], t = [...e], n = !1;
|
|
12
|
+
for (let r of u) e.some((e) => e.id === r.id) || t.push({
|
|
13
|
+
id: r.id,
|
|
14
|
+
name: r.name,
|
|
15
|
+
conversational: r.conversational
|
|
16
|
+
}), r.conversational && (n = !0);
|
|
17
|
+
o.metaData.pretrainingData = t, n ? o.metaData.mode = "conversational" : o.metaData.mode !== "conversational" && (o.metaData.mode = "completion");
|
|
18
|
+
} else o.metaData.mode !== "conversational" && (o.metaData.mode = "completion");
|
|
19
|
+
let f = a.maskedLoss ?? a.method.type === "supervised", p, m = l;
|
|
20
|
+
if (Array.isArray(c)) if (c[0] instanceof Uint16Array) p = c;
|
|
21
|
+
else {
|
|
22
|
+
let e = await t(c, s, {
|
|
23
|
+
masking: f,
|
|
24
|
+
validationSplit: a.validationSplit
|
|
25
|
+
});
|
|
26
|
+
p = e.trainingTokens, l || (m = e.validationTokens);
|
|
27
|
+
}
|
|
28
|
+
else p = c;
|
|
29
|
+
let h = p instanceof e ? p.getTokenCount() : p.reduce((e, t) => e + t.length, 0);
|
|
30
|
+
a.epochSteps = Math.ceil(h / ((a?.batchSize || 32) * o.config.blockSize));
|
|
31
|
+
let g = new n(s, o.config.blockSize);
|
|
32
|
+
if (m) {
|
|
33
|
+
let { trainDataset: e, validationDataset: t } = await r(p, m, s, g, a?.batchSize || 32);
|
|
34
|
+
return {
|
|
35
|
+
trainDataset: e,
|
|
36
|
+
validationDataset: t,
|
|
37
|
+
totalTokens: h
|
|
38
|
+
};
|
|
39
|
+
} else {
|
|
40
|
+
let t = p instanceof e ? p : await i(p, s);
|
|
41
|
+
return {
|
|
42
|
+
trainDataset: (await g.createTextDataset(t, a)).dataset,
|
|
43
|
+
validationDataset: void 0,
|
|
44
|
+
totalTokens: h
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { a as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ITokeniser } from '../../../tokeniser/type';
|
|
2
|
+
import { ConversationStream } from '../../../data/stream';
|
|
2
3
|
import { TokenStore } from './TokenStore';
|
|
3
4
|
interface TokensFromTasksOptions {
|
|
4
5
|
masking?: boolean;
|
package/dist/training/types.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { TensorStatistics } from '../../checks/weights';
|
|
2
2
|
import { LoRAConfig } from '../../models/config';
|
|
3
3
|
import { NamedTensorMap, Tensor } from '@tensorflow/tfjs-core';
|
|
4
|
+
import { TokenStore } from './tasks/TokenStore';
|
|
5
|
+
import { ConversationStream } from '../../data/stream';
|
|
6
|
+
import { DatasetMetadata } from '../../loader/types';
|
|
4
7
|
export interface Metrics {
|
|
5
8
|
accuracy?: number;
|
|
6
9
|
perplexity?: number;
|
|
@@ -43,7 +46,13 @@ export interface AdamWOptimizerConfig extends LRSchedulerConfig {
|
|
|
43
46
|
orthoGrad?: boolean;
|
|
44
47
|
}
|
|
45
48
|
export type TrainingMetrics = 'accuracy' | 'perplexity' | 'gradientNorm' | 'gradientStatistics' | 'weightNorm' | 'weightStatistics' | 'memoryUsage' | 'tokensPerSecond' | 'learningRate';
|
|
49
|
+
export interface TrainingMethod {
|
|
50
|
+
type: 'pretraining' | 'supervised';
|
|
51
|
+
supervised?: 'full' | 'lora' | 'last-layer';
|
|
52
|
+
}
|
|
46
53
|
export interface TrainingOptions extends Partial<AdamWOptimizerConfig> {
|
|
54
|
+
previous_job_id?: string;
|
|
55
|
+
method: TrainingMethod;
|
|
47
56
|
batchSize: number;
|
|
48
57
|
maxEpochs?: number;
|
|
49
58
|
logInterval?: number;
|
|
@@ -54,7 +63,6 @@ export interface TrainingOptions extends Partial<AdamWOptimizerConfig> {
|
|
|
54
63
|
trainableWeights?: string[];
|
|
55
64
|
loraConfig?: LoRAConfig;
|
|
56
65
|
loraName?: string;
|
|
57
|
-
sftMode: 'full' | 'lora' | 'last-layer';
|
|
58
66
|
maskedLoss?: boolean;
|
|
59
67
|
metrics?: TrainingMetrics[];
|
|
60
68
|
contextScaling?: number;
|
|
@@ -62,6 +70,11 @@ export interface TrainingOptions extends Partial<AdamWOptimizerConfig> {
|
|
|
62
70
|
dropout?: number;
|
|
63
71
|
layerDrop?: number;
|
|
64
72
|
debug?: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface TrainingContext {
|
|
75
|
+
training_data: ConversationStream[] | Uint16Array[] | TokenStore;
|
|
76
|
+
validation_data?: Uint16Array[] | TokenStore;
|
|
77
|
+
datasets?: DatasetMetadata[];
|
|
65
78
|
onStep?: (log: TrainingLogEntry) => void;
|
|
66
79
|
}
|
|
67
80
|
export interface TrainingState {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region lib/training/validateOptions.ts
|
|
2
|
+
function e(e, t, n) {
|
|
3
|
+
let r = new Set(Object.keys(e).filter((t) => e[t] !== n?.[t]));
|
|
4
|
+
if (t) {
|
|
5
|
+
if (r.has("batchSize")) throw Error("Cannot change batch size during training");
|
|
6
|
+
if (r.has("sftMode")) throw Error("Cannot change SFT mode during training");
|
|
7
|
+
if (r.has("loraConfig")) throw Error("Cannot change LoRA configuration during training");
|
|
8
|
+
if (r.has("validationSplit")) throw Error("Cannot change validation split during training");
|
|
9
|
+
if (r.has("trainableWeights")) throw Error("Cannot change trainable weights during training");
|
|
10
|
+
if (r.has("mixedPrecision")) throw Error("Cannot change mixed precision setting during training");
|
|
11
|
+
if (r.has("gradientCheckpointing")) throw Error("Cannot change gradient checkpointing setting during training");
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
...n,
|
|
15
|
+
...e
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { e as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function arrayShape(arr: unknown[]): number[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TeachableLLM } from '../../
|
|
1
|
+
import { default as TeachableLLM } from '../../TeachableLLM';
|
|
2
2
|
export default function waitForModel(model: TeachableLLM): Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region node_modules/uuid/dist/stringify.js
|
|
2
|
+
var e = [];
|
|
3
|
+
for (let t = 0; t < 256; ++t) e.push((t + 256).toString(16).slice(1));
|
|
4
|
+
function t(t, n = 0) {
|
|
5
|
+
return (e[t[n + 0]] + e[t[n + 1]] + e[t[n + 2]] + e[t[n + 3]] + "-" + e[t[n + 4]] + e[t[n + 5]] + "-" + e[t[n + 6]] + e[t[n + 7]] + "-" + e[t[n + 8]] + e[t[n + 9]] + "-" + e[t[n + 10]] + e[t[n + 11]] + e[t[n + 12]] + e[t[n + 13]] + e[t[n + 14]] + e[t[n + 15]]).toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region node_modules/uuid/dist/rng.js
|
|
9
|
+
var n = new Uint8Array(16);
|
|
10
|
+
function r() {
|
|
11
|
+
return crypto.getRandomValues(n);
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region node_modules/uuid/dist/v4.js
|
|
15
|
+
function i(e, t, n) {
|
|
16
|
+
return !t && !e && crypto.randomUUID ? crypto.randomUUID() : a(e, t, n);
|
|
17
|
+
}
|
|
18
|
+
function a(e, n, i) {
|
|
19
|
+
e ||= {};
|
|
20
|
+
let a = e.random ?? e.rng?.() ?? r();
|
|
21
|
+
if (a.length < 16) throw Error("Random bytes length must be >= 16");
|
|
22
|
+
if (a[6] = a[6] & 15 | 64, a[8] = a[8] & 63 | 128, n) {
|
|
23
|
+
if (i ||= 0, i < 0 || i + 16 > n.length) throw RangeError(`UUID byte range ${i}:${i + 15} is out of buffer bounds`);
|
|
24
|
+
for (let e = 0; e < 16; ++e) n[i + e] = a[e];
|
|
25
|
+
return n;
|
|
26
|
+
}
|
|
27
|
+
return t(a);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { i as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genai-fi/nanogpt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"types": "dist/main.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@eslint/js": "^10.0.1",
|
|
31
31
|
"@playwright/test": "^1.55.0",
|
|
32
|
-
"@types/node": "^
|
|
32
|
+
"@types/node": "^26.2.0",
|
|
33
33
|
"@types/papaparse": "^5.3.16",
|
|
34
34
|
"@types/picomatch": "^4.0.2",
|
|
35
35
|
"@types/yargs": "^17.0.33",
|
|
@@ -60,5 +60,11 @@
|
|
|
60
60
|
"pdfjs-dist": "^5.4.149",
|
|
61
61
|
"picomatch": "^4.0.3",
|
|
62
62
|
"uuid": "^14.0.0"
|
|
63
|
+
},
|
|
64
|
+
"allowScripts": {
|
|
65
|
+
"webgpu@0.4.0": true,
|
|
66
|
+
"esbuild@0.28.1": true,
|
|
67
|
+
"core-js@3.29.1": true,
|
|
68
|
+
"patch-package@8.0.1": true
|
|
63
69
|
}
|
|
64
70
|
}
|
package/dist/Generator.js
DELETED