@genai-fi/nanogpt 0.23.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.
Files changed (109) hide show
  1. package/README.md +78 -281
  2. package/dist/{DatasetBuilder-C0iJT29K.js → DatasetBuilder-DU1G1OKX.js} +20 -23
  3. package/dist/{RealDiv-CNsvC4AU.js → RealDiv-CSnvtN2E.js} +20 -20
  4. package/dist/{Reshape-dnm9bO3B.js → Reshape-BlylqwWy.js} +12 -12
  5. package/dist/TeachableLLM.d.ts +10 -15
  6. package/dist/TeachableLLM.js +201 -2
  7. package/dist/api/responses.d.ts +81 -0
  8. package/dist/api/responses.js +169 -0
  9. package/dist/api/training.d.ts +70 -0
  10. package/dist/api/training.js +205 -0
  11. package/dist/data/docx.js +9 -3036
  12. package/dist/data/stream.d.ts +8 -8
  13. package/dist/data/stream.js +1 -1
  14. package/dist/data/textLoader.d.ts +1 -1
  15. package/dist/data/textLoader.js +2 -2
  16. package/dist/data.d.ts +3 -0
  17. package/dist/data.js +12 -0
  18. package/dist/{dist-BqAU9-yi.js → dist-CwK5S7Ls.js} +2168 -2168
  19. package/dist/{gpgpu_math-DBYEAAdI.js → gpgpu_math-20tPK8LM.js} +458 -458
  20. package/dist/{Generator.d.ts → inference/Generator.d.ts} +16 -44
  21. package/dist/inference/Generator.js +271 -0
  22. package/dist/inference/tokenisePrompt.d.ts +4 -0
  23. package/dist/inference/tokenisePrompt.js +13 -0
  24. package/dist/inference/types.d.ts +44 -8
  25. package/dist/inference/utilities.d.ts +9 -0
  26. package/dist/inference/utilities.js +20 -0
  27. package/dist/jszip.min-DKa1Rjyn.js +3033 -0
  28. package/dist/{kernel_funcs_utils-D-mATnGR.js → kernel_funcs_utils-ql8Y8qPn.js} +96 -93
  29. package/dist/layers/MLP.d.ts +1 -1
  30. package/dist/layers/PositionEmbedding.d.ts +2 -1
  31. package/dist/layers/PositionEmbedding.js +1 -1
  32. package/dist/layers/RMSNorm.d.ts +1 -1
  33. package/dist/layers/TiedEmbedding.js +1 -1
  34. package/dist/layers.d.ts +4 -0
  35. package/dist/layers.js +14 -0
  36. package/dist/loader/load.js +58 -2
  37. package/dist/loader/loadHF.d.ts +1 -1
  38. package/dist/loader/loadHF.js +17 -2
  39. package/dist/loader/loadTransformers.js +46 -2
  40. package/dist/loader/newZipLoad.js +25 -2
  41. package/dist/loader/oldZipLoad.d.ts +1 -1
  42. package/dist/loader/oldZipLoad.js +37 -2
  43. package/dist/loader/save.js +75 -2
  44. package/dist/loader/types.d.ts +3 -3
  45. package/dist/main.d.ts +34 -43
  46. package/dist/main.js +12327 -20
  47. package/dist/{matMulGelu-BAIgQaRx.js → matMulGelu-CBoqTZM7.js} +2 -2
  48. package/dist/models/NanoGPTV1.js +95 -2
  49. package/dist/models/NanoGPTV2.js +86 -2
  50. package/dist/models/factory.js +13 -2
  51. package/dist/models/model.js +76 -2
  52. package/dist/models.d.ts +4 -0
  53. package/dist/models.js +14 -0
  54. package/dist/ops/dot16.js +1 -1
  55. package/dist/ops/matMulGelu.js +1 -1
  56. package/dist/ops/webgl/adamAdjust.js +1 -1
  57. package/dist/ops/webgl/fusedSoftmax.js +2 -2
  58. package/dist/ops/webgl/gelu.js +2 -2
  59. package/dist/ops/webgl/log.js +5 -5
  60. package/dist/ops/webgl/matMulGelu.js +1 -1
  61. package/dist/ops/webgl/matMulMul.js +1 -1
  62. package/dist/{stream-BjdpSNqB.js → stream-BpAwcvHz.js} +565 -561
  63. package/dist/{tfjs_backend-CydPRQTc.js → tfjs_backend-h5weiy1O.js} +36 -36
  64. package/dist/tokenise.d.ts +4 -0
  65. package/dist/tokenise.js +15 -0
  66. package/dist/tokeniser/CharTokeniser.js +18 -20
  67. package/dist/tokeniser/bpe.js +18 -22
  68. package/dist/training/BasicTrainer.d.ts +5 -10
  69. package/dist/training/BasicTrainer.js +80 -88
  70. package/dist/training/DatasetBuilder.d.ts +4 -4
  71. package/dist/training/DatasetBuilder.js +1 -1
  72. package/dist/training/PreTrainer.js +1 -1
  73. package/dist/training/SFTTrainer.js +1 -1
  74. package/dist/training/configure.d.ts +3 -0
  75. package/dist/training/configure.js +32 -0
  76. package/dist/training/factory.d.ts +6 -0
  77. package/dist/training/factory.js +8 -0
  78. package/dist/training/prepareData.d.ts +22 -0
  79. package/dist/training/prepareData.js +49 -0
  80. package/dist/training/tasks/TokenStore.d.ts +2 -1
  81. package/dist/training/tasks/TokenStore.js +8 -5
  82. package/dist/training/tasks/tokenStream.d.ts +17 -0
  83. package/dist/training/tasks/tokenStream.js +46 -0
  84. package/dist/training/types.d.ts +14 -1
  85. package/dist/training/validateOptions.d.ts +2 -0
  86. package/dist/training/validateOptions.js +19 -0
  87. package/dist/training/validation.js +4 -2
  88. package/dist/utilities/arrayShape.d.ts +1 -0
  89. package/dist/utilities/arrayShape.js +8 -0
  90. package/dist/utilities/random.d.ts +1 -0
  91. package/dist/utilities/random.js +19 -0
  92. package/dist/utilities/waitForModel.d.ts +1 -1
  93. package/dist/v4-BK7K-jy_.js +30 -0
  94. package/package.json +8 -2
  95. package/dist/Generator.js +0 -2
  96. package/dist/Trainer-DBsyWJ4s.js +0 -228
  97. package/dist/Trainer.d.ts +0 -45
  98. package/dist/Trainer.js +0 -2
  99. package/dist/main-BSaDGH7I.js +0 -13274
  100. package/dist/training/tasks/ConversationTask.d.ts +0 -17
  101. package/dist/training/tasks/ConversationTask.js +0 -29
  102. package/dist/training/tasks/PretrainingTask.d.ts +0 -17
  103. package/dist/training/tasks/PretrainingTask.js +0 -42
  104. package/dist/training/tasks/StartSentenceTask.d.ts +0 -18
  105. package/dist/training/tasks/StartSentenceTask.js +0 -45
  106. package/dist/training/tasks/Task.d.ts +0 -29
  107. package/dist/training/tasks/Task.js +0 -50
  108. package/dist/training/tasks/splitter.d.ts +0 -5
  109. package/dist/training/tasks/splitter.js +0 -18
@@ -7,11 +7,11 @@ export declare function flattenTokensWithMask(textData: Conversation[][], tokeni
7
7
  tokens: Uint16Array;
8
8
  mask: Uint8Array;
9
9
  };
10
- export declare function shuffle(array: Uint32Array): Uint32Array;
10
+ export declare function shuffle(array: Uint32Array | Uint16Array): Uint32Array | Uint16Array;
11
11
  export interface DatasetState {
12
- shuffledShards: Uint32Array;
13
- shuffledIndexes: Uint32Array;
14
- lastShardIndexes: Uint32Array;
12
+ shuffledShards: Uint16Array;
13
+ shuffledIndexes: Uint16Array;
14
+ lastShardIndexes: Uint16Array;
15
15
  currentShard: Uint16Array | null;
16
16
  nextShard: Uint16Array | null;
17
17
  currentMask: Uint8Array | null;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "../DatasetBuilder-C0iJT29K.js";
1
+ import { a as e, i as t, n, r, t as i } from "../DatasetBuilder-DU1G1OKX.js";
2
2
  export { i as DatasetBuilder, n as flattenTokens, r as flattenTokensWithMask, t as moveToNext, e as shuffle };
@@ -1,4 +1,4 @@
1
- import { t as e } from "../DatasetBuilder-C0iJT29K.js";
1
+ import { t as e } from "../DatasetBuilder-DU1G1OKX.js";
2
2
  import t from "./BasicTrainer.js";
3
3
  //#region lib/training/PreTrainer.ts
4
4
  var n = {
@@ -1,4 +1,4 @@
1
- import { t as e } from "../DatasetBuilder-C0iJT29K.js";
1
+ import { t as e } from "../DatasetBuilder-DU1G1OKX.js";
2
2
  import t from "./BasicTrainer.js";
3
3
  //#region lib/training/SFTTrainer.ts
4
4
  var n = {
@@ -0,0 +1,3 @@
1
+ import { TrainingOptions } from './types';
2
+ import { default as Model, ModelForwardAttributes } from '../../models/model';
3
+ export default function configureModel(model: Model<ModelForwardAttributes>, options?: TrainingOptions): void;
@@ -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,8 @@
1
+ import e from "./SFTTrainer.js";
2
+ import t from "./PreTrainer.js";
3
+ //#region lib/training/factory.ts
4
+ function n(n, r, i, a) {
5
+ return i?.method.type === "supervised" ? new e(n, r, i, a) : new t(n, r, i, a);
6
+ }
7
+ //#endregion
8
+ export { n as default };
@@ -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 };
@@ -31,7 +31,8 @@ export declare class TokenStore {
31
31
  getMask(index: number): Promise<Uint8Array | undefined>;
32
32
  getShardCount(): number;
33
33
  getTokenCount(): number;
34
- appendShard(shard: Uint16Array, mask?: Uint8Array): Promise<void>;
34
+ finish(): Promise<void>;
35
+ appendShard(shard: Uint16Array, mask?: Uint8Array): void;
35
36
  dispose(): Promise<void>;
36
37
  clear(): Promise<void>;
37
38
  }
@@ -7,12 +7,12 @@ var e = "llm-tokenstore", t = class {
7
7
  masks;
8
8
  shardCount = 0;
9
9
  lastShardLength = -1;
10
- _shardSize = 4e3 * 1024;
10
+ _shardSize = 8e3 * 1024;
11
11
  dirHandle = null;
12
12
  opfsAvailable = !1;
13
13
  lru = /* @__PURE__ */ new Map();
14
14
  maxCachedShards;
15
- constructor(t, n, r, i = 8, a = 4e3 * 1024) {
15
+ constructor(t, n, r, i = 2, a = 8e3 * 1024) {
16
16
  this.tokeniserId = t, this.datasetId = n, this.maxCachedShards = Math.max(1, Math.trunc(i)), this._shardSize = Math.max(1, Math.trunc(a)), this.name = r ?? e;
17
17
  }
18
18
  get shardSize() {
@@ -148,12 +148,15 @@ var e = "llm-tokenstore", t = class {
148
148
  getTokenCount() {
149
149
  return this.shardCount === 0 ? 0 : (this.shardCount - 1) * this._shardSize + this.lastShardLength;
150
150
  }
151
- async appendShard(e, t) {
151
+ async finish() {
152
+ await this.writeManifest();
153
+ }
154
+ appendShard(e, t) {
152
155
  if (this.lastShardLength >= 0 && this.lastShardLength < this._shardSize) throw Error("Previous shard was not full");
153
156
  let n = this.shards.length;
154
157
  this.shards.push(e), !this.masks && t && (this.masks = Array(n).fill(null)), this.masks && this.masks.push(t ?? null), this.shardCount = this.shards.length, this.lastShardLength = e.length, this.touchLRU(n);
155
158
  try {
156
- this.opfsAvailable && this.dirHandle && (await this.writeShardToOPFS(n, e), t && await this.writeMaskToOPFS(n, t), await this.writeManifest());
159
+ this.opfsAvailable && this.dirHandle && (this.writeShardToOPFS(n, e), t && this.writeMaskToOPFS(n, t));
157
160
  } catch (e) {
158
161
  console.error(e), this.maxCachedShards = 2 ** 53 - 1;
159
162
  }
@@ -208,7 +211,7 @@ async function a(e, r, i, a) {
208
211
  let o = n.get(e);
209
212
  if (o && o.tokeniserId === r && o.datasetId === i) return o;
210
213
  o && (await o.dispose(), n.delete(e));
211
- let s = new t(r, i, e, a?.maxCachedShards ?? 8, a?.shardSize ?? 4e3 * 1024);
214
+ let s = new t(r, i, e, a?.maxCachedShards, a?.shardSize);
212
215
  return a?.noOPFS || await s.init(), n.set(e, s), s;
213
216
  }
214
217
  //#endregion
@@ -0,0 +1,17 @@
1
+ import { ITokeniser } from '../../../tokeniser/type';
2
+ import { ConversationStream } from '../../../data/stream';
3
+ import { TokenStore } from './TokenStore';
4
+ interface TokensFromTasksOptions {
5
+ masking?: boolean;
6
+ maxCachedShards?: number;
7
+ noOPFS?: boolean;
8
+ shardSize?: number;
9
+ validationSplit?: number;
10
+ validationSeed?: string | number;
11
+ cb?: (tokens: number) => void;
12
+ }
13
+ export declare function tokensFromStreams(tasks: ConversationStream[], tokenizer: ITokeniser, options?: TokensFromTasksOptions): Promise<{
14
+ trainingTokens: TokenStore;
15
+ validationTokens?: TokenStore;
16
+ }>;
17
+ export {};
@@ -0,0 +1,46 @@
1
+ import { createTokenStore as e, deleteTokenStore as t } from "./TokenStore.js";
2
+ import { seededRng as n } from "../../utilities/random.js";
3
+ //#region lib/training/tasks/tokenStream.ts
4
+ function r(e, t, n, r, i, a) {
5
+ let o = n.encodeConversation(e, !1, !!a);
6
+ if (o) {
7
+ let e = Array.isArray(o) ? o : o.tokens;
8
+ r.total += e.length;
9
+ let n = t[t.length - 1], s = a ? a[a.length - 1] : null;
10
+ if (r.offset + e.length > n.length) {
11
+ let c = n.length - r.offset;
12
+ n.set(e.slice(0, c), r.offset);
13
+ let l = e.length - c;
14
+ if (l > i) throw Error(`Estimated tokens (${i}) is too small for the next batch of tokens (${l}).`);
15
+ let u = new Uint16Array(i);
16
+ if (u.set(e.slice(c), 0), t.push(u), a && s && !Array.isArray(o)) {
17
+ s.set(o.mask.slice(0, c).map((e) => +!!e), r.offset);
18
+ let e = new Uint8Array(u.length);
19
+ e.set(o.mask.slice(c).map((e) => +!!e), 0), a.push(e);
20
+ }
21
+ r.offset = e.length - c;
22
+ } else n.set(e, r.offset), s && !Array.isArray(o) && s.set(o.mask.map((e) => +!!e), r.offset), r.offset += e.length;
23
+ }
24
+ }
25
+ async function i(i, a, o) {
26
+ await t("training-tokens");
27
+ let s = await e("training-tokens", a.id, a.datasetID ?? "", o);
28
+ await t("validation-tokens");
29
+ let c = o?.validationSplit && o.validationSplit > 0 ? await e("validation-tokens", a.id, a.datasetID ?? "", o) : void 0, l = [new Uint16Array(s.shardSize)], u = o?.masking ? [new Uint8Array(s.shardSize)] : null, d = {
30
+ offset: 0,
31
+ total: 0
32
+ }, f = o?.validationSplit && o.validationSplit > 0 ? [new Uint16Array(c.shardSize)] : void 0, p = o?.masking && f ? [new Uint8Array(c.shardSize)] : null, m = {
33
+ offset: 0,
34
+ total: 0
35
+ }, h = 0, g = o?.cb, _ = o?.validationSeed === void 0 ? Math.random : n(o.validationSeed);
36
+ for (; h < i.length;) await i[h++].begin((e) => {
37
+ let t = o?.validationSplit && o.validationSplit > 0 && _() < o.validationSplit, n = t ? f : l, i = t ? m : d, h = t ? p : u, g = t ? c : s;
38
+ r(e, n, a, i, g.shardSize, h || void 0), n.length > 1 && (g.appendShard(n[0], h ? h[0] : void 0), n.shift(), h && h.shift());
39
+ }, g ? () => g(d.total) : void 0);
40
+ return l.length === 1 && (l[0] = l[0].subarray(0, d.offset), s.appendShard(l[0], u ? u[0].subarray(0, d.offset) : void 0)), f && f.length === 1 && (f[0] = f[0].subarray(0, m.offset), c.appendShard(f[0], p ? p[0].subarray(0, m.offset) : void 0)), await s.finish(), c && await c.finish(), {
41
+ trainingTokens: s,
42
+ validationTokens: f ? c : void 0
43
+ };
44
+ }
45
+ //#endregion
46
+ export { i as tokensFromStreams };
@@ -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,2 @@
1
+ import { TrainingOptions } from './types';
2
+ export default function validateOptions(options: TrainingOptions, training: boolean, oldOptions?: TrainingOptions): TrainingOptions;
@@ -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 };
@@ -1,8 +1,10 @@
1
1
  import { TokenStore as e, createTokenStore as t } from "./tasks/TokenStore.js";
2
2
  //#region lib/training/validation.ts
3
3
  async function n(e, n) {
4
- let r = await t("training-tokens", n.id, n.datasetID ?? ""), i = e.map((e) => r.appendShard(e));
5
- return await Promise.all(i), r;
4
+ let r = await t("training-tokens", n.id, n.datasetID ?? "");
5
+ return e.forEach((e) => {
6
+ r.appendShard(e);
7
+ }), await r.finish(), r;
6
8
  }
7
9
  async function r(t, r, i, a, o) {
8
10
  let s = t instanceof e ? t : await n(t, i), c = r instanceof e ? r : await n(r, i), l = s.getTokenCount(), { dataset: u, state: d } = await a.createTextDataset(s, { batchSize: o }), { dataset: f, state: p } = await a.createTextDataset(c, {
@@ -0,0 +1 @@
1
+ export default function arrayShape(arr: unknown[]): number[];
@@ -0,0 +1,8 @@
1
+ //#region lib/utilities/arrayShape.ts
2
+ function e(e) {
3
+ let t = [], n = e;
4
+ for (; Array.isArray(n);) t.push(n.length), n = n[n.length - 1];
5
+ return t;
6
+ }
7
+ //#endregion
8
+ export { e as default };
@@ -0,0 +1 @@
1
+ export declare function seededRng(seed: string | number): () => number;
@@ -0,0 +1,19 @@
1
+ //#region lib/utilities/random.ts
2
+ function e(e) {
3
+ let t = 1779033703 ^ e.length;
4
+ for (let n = 0; n < e.length; n++) t = Math.imul(t ^ e.charCodeAt(n), 3432918353), t = t << 13 | t >>> 19;
5
+ return () => (t = Math.imul(t ^ t >>> 16, 2246822507), t = Math.imul(t ^ t >>> 13, 3266489909), (t ^= t >>> 16) >>> 0);
6
+ }
7
+ function t(e) {
8
+ let t = e >>> 0;
9
+ return () => {
10
+ t += 1831565813;
11
+ let e = Math.imul(t ^ t >>> 15, t | 1);
12
+ return e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296;
13
+ };
14
+ }
15
+ function n(n) {
16
+ return t(typeof n == "number" ? n >>> 0 : e(n)());
17
+ }
18
+ //#endregion
19
+ export { n as seededRng };
@@ -1,2 +1,2 @@
1
- import { TeachableLLM } from '../../main';
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.23.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": "^22.13.14",
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
@@ -1,2 +0,0 @@
1
- import { a as e, o as t } from "./main-BSaDGH7I.js";
2
- export { e as default, t as isConversation };