@genai-fi/nanogpt 0.16.1 → 0.17.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/dist/Trainer.js CHANGED
@@ -1,9 +1,29 @@
1
- import { E as g } from "./index-DvYrXKkX.js";
2
- import o from "./training/PreTrainer.js";
3
- import { createTrainValidationSplit as d } from "./training/validation.js";
4
- import h from "./training/SFTTrainer.js";
5
- import p from "./training/tasks/splitter.js";
6
- class l extends g {
1
+ import { E as f } from "./index-DvYrXKkX.js";
2
+ import l from "./training/PreTrainer.js";
3
+ import { createTrainValidationSplit as p } from "./training/validation.js";
4
+ import g from "./training/SFTTrainer.js";
5
+ import m from "./training/tasks/splitter.js";
6
+ const n = [];
7
+ for (let a = 0; a < 256; ++a)
8
+ n.push((a + 256).toString(16).slice(1));
9
+ function u(a, t = 0) {
10
+ return (n[a[t + 0]] + n[a[t + 1]] + n[a[t + 2]] + n[a[t + 3]] + "-" + n[a[t + 4]] + n[a[t + 5]] + "-" + n[a[t + 6]] + n[a[t + 7]] + "-" + n[a[t + 8]] + n[a[t + 9]] + "-" + n[a[t + 10]] + n[a[t + 11]] + n[a[t + 12]] + n[a[t + 13]] + n[a[t + 14]] + n[a[t + 15]]).toLowerCase();
11
+ }
12
+ const w = new Uint8Array(16);
13
+ function S() {
14
+ return crypto.getRandomValues(w);
15
+ }
16
+ function c(a, t, i) {
17
+ return crypto.randomUUID ? crypto.randomUUID() : D(a);
18
+ }
19
+ function D(a, t, i) {
20
+ a = a || {};
21
+ const e = a.random ?? a.rng?.() ?? S();
22
+ if (e.length < 16)
23
+ throw new Error("Random bytes length must be >= 16");
24
+ return e[6] = e[6] & 15 | 64, e[8] = e[8] & 63 | 128, u(e);
25
+ }
26
+ class d extends f {
7
27
  trainer;
8
28
  trainingType = "pretraining";
9
29
  hasTrained = !1;
@@ -18,21 +38,21 @@ class l extends g {
18
38
  logInterval: 10
19
39
  };
20
40
  tokenizer;
21
- constructor(t, i, e = "pretraining", a) {
22
- if (super(), t instanceof l) {
23
- const r = i || t.options, n = t.options;
24
- let s = !1;
25
- t.trainingType === "sft" && r.sftMode !== n.sftMode && (s = !0), e !== t.trainingType && (s = !0), s ? (t.trainingType === "sft" ? this.trainer = new h(t.model, t.tokenizer, r) : this.trainer = new o(t.model, t.tokenizer, r), this.trainingType = e, this.options = r, this.tokenizer = t.tokenizer) : (this.trainer = t.trainer, this.trainingType = e, this.options = r, this.trainer.updateOptimizer(this.options), this.log = t.log, this.progress = t.progress, this.totalSamples = t.totalSamples, this.tokenizer = t.tokenizer, r.batchSize === n.batchSize && (this.trainDataset = t.trainDataset, this.validationDataset = t.validationDataset));
41
+ constructor(t, i, e = "pretraining", r) {
42
+ if (super(), t instanceof d) {
43
+ const s = i || t.options, h = t.options;
44
+ let o = !1;
45
+ t.trainingType === "sft" && s.sftMode !== h.sftMode && (o = !0), e !== t.trainingType && (o = !0), o ? (t.trainingType === "sft" ? this.trainer = new g(t.model, t.tokenizer, s) : this.trainer = new l(t.model, t.tokenizer, s), this.trainingType = e, this.options = s, this.tokenizer = t.tokenizer) : (this.trainer = t.trainer, this.trainingType = e, this.options = s, this.trainer.updateOptimizer(this.options), this.log = t.log, this.progress = t.progress, this.totalSamples = t.totalSamples, this.tokenizer = t.tokenizer, s.batchSize === h.batchSize && (this.trainDataset = t.trainDataset, this.validationDataset = t.validationDataset));
26
46
  return;
27
47
  }
28
48
  if (!i)
29
49
  throw new Error("Tokeniser must be provided when initializing Trainer with a model");
30
50
  if (!t)
31
51
  throw new Error("Model must be provided when initializing Trainer");
32
- this.options = a || {
52
+ this.options = r || {
33
53
  batchSize: 32,
34
54
  sftMode: "full"
35
- }, e === "sft" ? this.trainer = new h(t, i, a) : this.trainer = new o(t, i, a), this.trainingType = e, this.tokenizer = i;
55
+ }, e === "sft" ? this.trainer = new g(t, i, r) : this.trainer = new l(t, i, r), this.trainingType = e, this.tokenizer = i;
36
56
  }
37
57
  get model() {
38
58
  return this.trainer.model;
@@ -81,41 +101,70 @@ class l extends g {
81
101
  }
82
102
  async prepare(t = []) {
83
103
  const i = this.options;
84
- if (this.trainingType === "pretraining" && this.trainer instanceof o) {
85
- const { trainDataset: e, validationDataset: a, size: r, trainState: n } = await d(
104
+ if (this.trainingType === "pretraining" && this.trainer instanceof l) {
105
+ const { trainDataset: e, validationDataset: r, size: s, trainState: h } = await p(
86
106
  t,
87
107
  this.trainer.tokenizer,
88
108
  this.trainer.datasetBuilder,
89
109
  i?.batchSize || 32,
90
110
  i?.validationSplit || 0.1
91
- ), s = r * (1 - (i?.validationSplit || 0));
92
- this.trainDataset = e, this.validationDataset = a, this.totalSamples = s, this.options.epochSteps = Math.ceil(n.shuffledIndexes.length / (i?.batchSize || 32)), this.trainer.updateOptimizer(this.options);
93
- } else if (this.trainingType === "sft" && this.trainer instanceof h) {
111
+ ), o = s * (1 - (i?.validationSplit || 0));
112
+ this.trainDataset = e, this.validationDataset = r, this.totalSamples = o, this.options.epochSteps = Math.ceil(h.shuffledIndexes.length / (i?.batchSize || 32)), this.trainer.updateOptimizer(this.options);
113
+ } else if (this.trainingType === "sft" && this.trainer instanceof g) {
94
114
  if (t instanceof Uint16Array)
95
115
  throw new Error("SFT training requires Task[] input");
96
- const e = p(t, i?.validationSplit || 0.1), a = await this.trainer.datasetBuilder.createSFTDataset(
97
- [e.training],
98
- i?.batchSize || 32,
99
- -100
100
- ), r = await this.trainer.datasetBuilder.createSFTDataset(
101
- [e.validation],
102
- i?.batchSize || 32,
103
- -100
104
- );
105
- this.validationDataset = r, this.trainDataset = a, this.totalSamples = t.reduce((n, s) => n + s.length, 0), this.options.epochSteps = Math.ceil(this.totalSamples / (i?.batchSize || 32)), this.trainer.updateOptimizer(this.options);
116
+ if (i?.validationSplit && i.validationSplit > 0) {
117
+ const e = m(t, i?.validationSplit), r = await this.trainer.datasetBuilder.createSFTDataset(
118
+ [e.training],
119
+ i?.batchSize || 32,
120
+ -100
121
+ ), s = await this.trainer.datasetBuilder.createSFTDataset(
122
+ [e.validation],
123
+ i?.batchSize || 32,
124
+ -100
125
+ );
126
+ this.validationDataset = s, this.trainDataset = r;
127
+ } else {
128
+ const e = await this.trainer.datasetBuilder.createSFTDataset(
129
+ t,
130
+ i?.batchSize || 32,
131
+ -100
132
+ );
133
+ this.trainDataset = e;
134
+ }
135
+ this.totalSamples = t.reduce((e, r) => e + r.length, 0), this.options.epochSteps = Math.ceil(this.totalSamples / (i?.batchSize || 32)), this.trainer.updateOptimizer(this.options);
106
136
  }
107
137
  }
108
138
  configureModel(t) {
109
139
  const i = t?.sftMode || "full";
110
140
  if (this.trainingType === "pretraining" && (this.trainer.model.hasLoRA() && this.trainer.model.detachLoRA(), this.trainer.model.weightStore.setTrainable(["*"])), this.trainingType === "sft") {
111
141
  if (i === "lora") {
112
- if (!t?.loraConfig)
113
- throw new Error("LoRA configuration must be provided for lora mode");
114
- if (this.trainer.model.hasLoRA()) {
115
- const e = this.trainer.model.lora;
116
- (e.alpha !== t.loraConfig.alpha || e.rank !== t.loraConfig.rank) && (this.trainer.model.detachLoRA(), this.trainer.model.attachLoRA(t.loraConfig));
117
- } else
118
- this.trainer.model.attachLoRA(t.loraConfig);
142
+ const e = this.trainer.model;
143
+ if (t?.loraName)
144
+ if (e.hasLoRA(t.loraName)) {
145
+ if (e.attachLoRA(t.loraName), t.loraConfig) {
146
+ const r = e.lora;
147
+ (r.alpha !== t.loraConfig.alpha || r.rank !== t.loraConfig.rank) && (e.detachLoRA(), e.deleteLoRA(t.loraName), e.createLoRA(t.loraName, t.loraConfig), e.attachLoRA(t.loraName), console.warn("Resetting LoRA with new configuration."));
148
+ }
149
+ } else if (t.loraConfig)
150
+ e.createLoRA(t.loraName, t.loraConfig), e.attachLoRA(t.loraName);
151
+ else
152
+ throw new Error(
153
+ `LoRA configuration must be provided to create LoRA with name ${t.loraName}`
154
+ );
155
+ else if (t?.loraConfig)
156
+ if (e.hasLoRA()) {
157
+ const r = e.lora;
158
+ if (r.alpha !== t.loraConfig.alpha || r.rank !== t.loraConfig.rank) {
159
+ e.detachLoRA();
160
+ const s = t.loraName || c();
161
+ e.createLoRA(s, t.loraConfig), e.attachLoRA(s);
162
+ }
163
+ } else {
164
+ const r = t.loraName || c();
165
+ e.createLoRA(r, t.loraConfig), e.attachLoRA(r);
166
+ }
167
+ else if (!e.hasLoRA()) throw new Error("LoRA configuration must be provided for lora SFT mode");
119
168
  } else
120
169
  this.trainer.model.hasLoRA() && this.trainer.model.detachLoRA();
121
170
  i === "last-layer" ? this.trainer.model.weightStore.setTrainable([
@@ -143,8 +192,8 @@ class l extends g {
143
192
  )
144
193
  };
145
194
  const e = this.listeners("log");
146
- for (const a of e)
147
- await a(i, this.progress);
195
+ for (const r of e)
196
+ await r(i, this.progress);
148
197
  }
149
198
  },
150
199
  this.validationDataset
@@ -155,8 +204,8 @@ class l extends g {
155
204
  throw new Error("Dataset not prepared");
156
205
  this.hasTrained || this.trainer.setLearningRate(t?.learningRate || 1e-3), this.hasTrained = !0, this.emit("start");
157
206
  const { log: i } = await this.trainer.stepDataset(this.trainDataset, t || {}, this.validationDataset), e = this.listeners("log");
158
- for (const a of e)
159
- await a(i, {
207
+ for (const r of e)
208
+ await r(i, {
160
209
  lastLog: i,
161
210
  progress: i.totalSamples / this.totalSamples,
162
211
  remaining: Math.max(0, (this.totalSamples - i.totalSamples) / i.totalSamples * i.duration)
@@ -174,5 +223,5 @@ class l extends g {
174
223
  }
175
224
  }
176
225
  export {
177
- l as default
226
+ d as default
178
227
  };
@@ -3,10 +3,12 @@ export default class LoRA {
3
3
  private weightStore;
4
4
  readonly alpha: number;
5
5
  readonly rank: number;
6
- private variables;
6
+ readonly variables: Set<string>;
7
7
  private scale;
8
- constructor(weightStore: WeightStore, alpha: number, rank: number, variables: string[]);
8
+ readonly name: string;
9
+ constructor(name: string, weightStore: WeightStore, alpha: number, rank: number, variables: string[]);
10
+ attach(): void;
9
11
  merge(): void;
10
- detach(merge?: boolean): void;
12
+ detach(): void;
11
13
  dispose(): void;
12
14
  }
@@ -1,52 +1,58 @@
1
- import { a as b, t as c } from "../index-CUXkjxiT.js";
1
+ import { a as m, t as n } from "../index-CUXkjxiT.js";
2
2
  import { p } from "../index-DmeWGGmS.js";
3
- import { v as w } from "../variable-Ck482e3n.js";
3
+ import { v as g } from "../variable-Ck482e3n.js";
4
4
  import { r as S } from "../random_normal-IBRrha8a.js";
5
- import { z as m } from "../zeros-DvZpK8s6.js";
6
- class $ {
5
+ import { z as _ } from "../zeros-DvZpK8s6.js";
6
+ class B {
7
7
  weightStore;
8
8
  alpha;
9
9
  rank;
10
10
  variables;
11
11
  scale;
12
- constructor(e, a, i, r) {
13
- this.weightStore = e, this.alpha = a, this.rank = i;
14
- const o = p(r), d = e.variableNames.filter((t) => o(t));
15
- if (this.variables = new Set(d), this.scale = b(a / i), this.weightStore.onWeightRead)
16
- throw new Error("LoRA cannot be applied to a WeightStore that already has a onWeightRead hook.");
17
- this.variables.forEach((t) => {
18
- const s = this.weightStore.getRawVariable(t), [h, l] = s.shape, g = `${t}_loraA`, n = `${t}_loraB`;
19
- if (s.shape.length !== 2) {
12
+ name;
13
+ constructor(t, e, a, s, r) {
14
+ this.name = t, this.weightStore = e, this.alpha = a, this.rank = s;
15
+ const c = p(r), w = e.variableNames.filter(
16
+ (i) => c(i) && !i.endsWith("_loraA") && !i.endsWith("_loraB")
17
+ );
18
+ this.variables = new Set(w), this.scale = m(a / s), this.variables.forEach((i) => {
19
+ const o = this.weightStore.getRawVariable(i), [d, b] = o.shape, h = `${i}_${this.name}_loraA`, l = `${i}_${this.name}_loraB`;
20
+ if (o.shape.length !== 2) {
20
21
  console.warn(
21
- `LoRA currently only supports 2D weight matrices. Variable ${t} has shape ${s.shape}`
22
- ), this.variables.delete(t);
22
+ `LoRA currently only supports 2D weight matrices. Variable ${i} has shape ${o.shape}`
23
+ ), this.variables.delete(i);
23
24
  return;
24
25
  }
25
- this.weightStore.hasVariable(g) || this.weightStore.hasVariable(n) || (this.weightStore.addVariable(
26
- g,
27
- w(S([h, this.rank], 0, 0.02), !0, g)
28
- ), this.weightStore.addVariable(n, w(m([this.rank, l]), !0, n)));
29
- }), this.weightStore.onWeightRead = (t, s) => this.variables.has(t) ? c(() => {
30
- const h = this.weightStore.getRawVariable(`${t}_loraA`), l = this.weightStore.getRawVariable(`${t}_loraB`);
31
- return s.add(h.matMul(l).mul(this.scale));
32
- }) : s, this.weightStore.setTrainable(["*_loraA", "*_loraB"]);
26
+ this.weightStore.hasVariable(h) || this.weightStore.hasVariable(l) || (this.weightStore.addVariable(
27
+ h,
28
+ g(S([d, this.rank], 0, 0.02), !0, h)
29
+ ), this.weightStore.addVariable(l, g(_([this.rank, b]), !0, l)));
30
+ });
31
+ }
32
+ attach() {
33
+ if (this.weightStore.onWeightRead)
34
+ throw new Error("LoRA cannot be applied to a WeightStore that already has a onWeightRead hook.");
35
+ this.weightStore.onWeightRead = (t, e) => this.variables.has(t) ? n(() => {
36
+ const a = this.weightStore.getRawVariable(`${t}_${this.name}_loraA`), s = this.weightStore.getRawVariable(`${t}_${this.name}_loraB`);
37
+ return e.add(a.matMul(s).mul(this.scale));
38
+ }) : e, this.weightStore.setTrainable([`*_${this.name}_loraA`, `*_${this.name}_loraB`]);
33
39
  }
34
40
  merge() {
35
- this.variables.forEach((e) => {
36
- const a = this.weightStore.getRawVariable(e), i = this.weightStore.getRawVariable(`${e}_loraA`), r = this.weightStore.getRawVariable(`${e}_loraB`), o = c(() => a.add(i.matMul(r).mul(this.scale)));
37
- a.assign(o), o.dispose();
41
+ this.variables.forEach((t) => {
42
+ const e = this.weightStore.getRawVariable(t), a = this.weightStore.getRawVariable(`${t}_${this.name}_loraA`), s = this.weightStore.getRawVariable(`${t}_${this.name}_loraB`), r = n(() => e.add(a.matMul(s).mul(this.scale)));
43
+ e.assign(r), r.dispose();
38
44
  });
39
45
  }
40
- detach(e = !1) {
41
- e && this.merge(), this.variables.forEach((a) => {
42
- const i = `${a}_loraA`, r = `${a}_loraB`;
43
- this.weightStore.getRawVariable(i).dispose(), this.weightStore.getRawVariable(r).dispose(), this.weightStore.deleteVariable(i), this.weightStore.deleteVariable(r);
44
- }), this.weightStore.onWeightRead = void 0, this.weightStore.setTrainable(["*"]), this.variables.clear();
46
+ detach() {
47
+ this.weightStore.onWeightRead = void 0, this.weightStore.setTrainable(["*"]);
45
48
  }
46
49
  dispose() {
47
- this.detach(), this.scale.dispose();
50
+ this.detach(), this.scale.dispose(), this.variables.forEach((t) => {
51
+ const e = `${t}_${this.name}_loraA`, a = `${t}_${this.name}_loraB`;
52
+ this.weightStore.getRawVariable(e).dispose(), this.weightStore.getRawVariable(a).dispose(), this.weightStore.deleteVariable(e), this.weightStore.deleteVariable(a);
53
+ }), this.variables.clear();
48
54
  }
49
55
  }
50
56
  export {
51
- $ as default
57
+ B as default
52
58
  };
@@ -1,68 +1,68 @@
1
1
  import { z as i } from "../jszip.min-BZhlzntC.js";
2
2
  import u from "./oldZipLoad.js";
3
- import m from "./newZipLoad.js";
4
- import d from "./loadHF.js";
3
+ import d from "./newZipLoad.js";
4
+ import w from "./loadHF.js";
5
5
  import { loadZipMeta as s } from "./loadZipMeta.js";
6
- import { load_safetensors as w } from "../utilities/safetensors.js";
6
+ import { load_safetensors as g } from "../utilities/safetensors.js";
7
7
  const j = 2;
8
- async function h(t) {
9
- const e = await fetch(t);
10
- if (!e.ok)
11
- throw new Error(`Failed to fetch ${t}: ${e.statusText}`);
12
- return e.arrayBuffer();
8
+ async function h(e) {
9
+ const t = await fetch(e);
10
+ if (!t.ok)
11
+ throw new Error(`Failed to fetch ${e}: ${t.statusText}`);
12
+ return t.arrayBuffer();
13
13
  }
14
- async function p(t, e, o) {
15
- const r = t.file("model.safetensors");
16
- if (!r)
14
+ async function p(e, t, o) {
15
+ const a = e.file("model.safetensors");
16
+ if (!a)
17
17
  return;
18
- const n = await r.async("arraybuffer"), c = await w(n), a = /* @__PURE__ */ new Map();
19
- for (const [l, g] of Object.entries(c))
20
- a.set(l, [g]);
21
- e.weightStore.loadWeights(a, o);
18
+ const r = await a.async("arraybuffer"), c = await g(r), n = /* @__PURE__ */ new Map();
19
+ for (const [l, m] of Object.entries(c))
20
+ n.set(l, [m]);
21
+ t.weightStore.loadWeights(n, o);
22
22
  }
23
- async function y(t, e) {
24
- const o = t.file("config.json");
23
+ async function y(e, t) {
24
+ const o = e.file("config.json");
25
25
  if (!o)
26
26
  return;
27
- const r = await o.async("string"), n = JSON.parse(r);
28
- if (n.loraConfig) {
29
- if (e.hasLoRA())
27
+ const a = await o.async("string"), r = JSON.parse(a);
28
+ if (r.loraName) {
29
+ if (t.hasLoRA())
30
30
  throw new Error("Model already has LoRA attached");
31
- e.attachLoRA(n.loraConfig);
31
+ t.attachLoRA(r.loraName);
32
32
  }
33
33
  }
34
- async function f(t, e) {
35
- if (e.reference) {
36
- const o = await C(e.reference);
37
- return await p(t, o.model, !!e.url), await y(t, o.model), o.model.config.loraConfig && o.model.attachLoRA(o.model.config.loraConfig), {
34
+ async function f(e, t) {
35
+ if (t.reference) {
36
+ const o = await L(t.reference);
37
+ return await p(e, o.model, !!t.url), await y(e, o.model), o.model.config.loraName && o.model.attachLoRA(o.model.config.loraName), {
38
38
  ...o,
39
39
  metaData: {
40
40
  ...o.metaData,
41
- ...e
41
+ ...t
42
42
  }
43
43
  };
44
44
  } else {
45
- if (t.file("manifest.json"))
46
- return u(t, e);
45
+ if (e.file("manifest.json"))
46
+ return u(e, t);
47
47
  {
48
- const o = await m(t, e);
49
- return o.model.config.loraConfig && o.model.attachLoRA(o.model.config.loraConfig), o;
48
+ const o = await d(e, t);
49
+ return o.model.config.loraName && o.model.attachLoRA(o.model.config.loraName), o;
50
50
  }
51
51
  }
52
52
  }
53
- async function C(t, e) {
54
- if (typeof t == "string")
55
- if (t.startsWith("http://") || t.startsWith("https://")) {
56
- const o = await h(t), r = await i.loadAsync(o), n = await s(r);
57
- return n.url = t, f(r, n);
53
+ async function L(e, t) {
54
+ if (typeof e == "string")
55
+ if (e.startsWith("http://") || e.startsWith("https://")) {
56
+ const o = await h(e), a = await i.loadAsync(o), r = await s(a);
57
+ return r.url = e, f(a, r);
58
58
  } else
59
- return d(t);
59
+ return w(e);
60
60
  else {
61
- const o = await i.loadAsync(t), r = await s(o);
62
- return r.url = e?.sourceURL || void 0, f(o, r);
61
+ const o = await i.loadAsync(e), a = await s(o);
62
+ return a.url = t?.sourceURL || void 0, f(o, a);
63
63
  }
64
64
  }
65
65
  export {
66
66
  j as VERSION,
67
- C as loadModel
67
+ L as loadModel
68
68
  };
@@ -1,8 +1,8 @@
1
1
  import p from "../tokeniser/CharTokeniser.js";
2
2
  import _ from "../tokeniser/bpe.js";
3
- import { load_safetensors as c } from "../utilities/safetensors.js";
4
- import { aa as u } from "../index-CUXkjxiT.js";
5
- import { dummyPassAsync as b } from "../utilities/dummy.js";
3
+ import { load_safetensors as b } from "../utilities/safetensors.js";
4
+ import { aa as c } from "../index-CUXkjxiT.js";
5
+ import { dummyPassAsync as u } from "../utilities/dummy.js";
6
6
  import y from "../models/factory.js";
7
7
  function h(e) {
8
8
  let o;
@@ -23,19 +23,20 @@ function h(e) {
23
23
  nHead: e.num_attention_heads,
24
24
  nEmbed: e.hidden_size,
25
25
  mlpFactor: e.mlpFactor,
26
- loraConfig: e.loraConfig,
26
+ loraConfig: e.loraConfig ? new Map(Object.entries(e.loraConfig)) : void 0,
27
+ loraName: e.loraName,
27
28
  windowSize: e.windowSize
28
29
  }, o;
29
30
  }
30
- async function G(e, o, r, t) {
31
- const n = h(e), m = (o.type ?? "char") === "char" ? new p(o.vocab) : new _(o.vocab, o.merges), i = await c(t), s = /* @__PURE__ */ new Map();
31
+ async function S(e, o, r, s) {
32
+ const n = h(e), m = (o.type ?? "char") === "char" ? new p(o.vocab) : new _(o.vocab, o.merges), i = await b(s), t = /* @__PURE__ */ new Map();
32
33
  for (const [l, d] of Object.entries(i))
33
- s.set(l, [d]);
34
- u();
34
+ t.set(l, [d]);
35
+ c();
35
36
  const a = y(n);
36
- return a.metaData = r, await b(a), a.weightStore.loadWeights(s, !!r.url), { model: a, tokeniser: m, metaData: r };
37
+ return a.metaData = r, await u(a), a.weightStore.loadWeights(t, !!r.url), { model: a, tokeniser: m, metaData: r };
37
38
  }
38
39
  export {
39
- G as default,
40
+ S as default,
40
41
  h as mapTransformersConfigToGPTConfig
41
42
  };
@@ -1,19 +1,19 @@
1
1
  import { z as p } from "../jszip.min-BZhlzntC.js";
2
- import _ from "../tokeniser/CharTokeniser.js";
3
- import { save_safetensors as l } from "../utilities/safetensors.js";
2
+ import l from "../tokeniser/CharTokeniser.js";
3
+ import { save_safetensors as _ } from "../utilities/safetensors.js";
4
4
  import { VERSION as b } from "./load.js";
5
5
  async function z(e, i, a) {
6
- const s = /* @__PURE__ */ new Map();
7
- e.weightStore.saveWeights(s);
8
- const n = new p(), r = {};
9
- s.forEach((t, f) => {
10
- t.length === 1 && (r[f] = t[0]);
6
+ const r = /* @__PURE__ */ new Map();
7
+ e.weightStore.saveWeights(r);
8
+ const n = new p(), s = {};
9
+ r.forEach((o, f) => {
10
+ o.length === 1 && (s[f] = o[0]);
11
11
  });
12
- const c = await l(r);
12
+ const c = await _(s);
13
13
  n.file("model.safetensors", c, { binary: !0 });
14
14
  const g = e.config.modelType;
15
- let o;
16
- if (g === "GenAI_NanoGPT_v1" ? o = {
15
+ let t;
16
+ if (g === "GenAI_NanoGPT_v1" ? t = {
17
17
  model_type: "GenAI_NanoGPT_v1",
18
18
  vocab_size: i.getVocab().length,
19
19
  hidden_size: e.config.nEmbed,
@@ -22,7 +22,7 @@ async function z(e, i, a) {
22
22
  block_size: e.config.blockSize,
23
23
  mlpFactor: e.config.mlpFactor,
24
24
  useRope: e.config.useRope
25
- } : o = {
25
+ } : t = {
26
26
  model_type: "GenAI_NanoGPT_v2",
27
27
  vocab_size: i.getVocab().length,
28
28
  hidden_size: e.config.nEmbed,
@@ -30,9 +30,10 @@ async function z(e, i, a) {
30
30
  num_attention_heads: e.config.nHead,
31
31
  block_size: e.config.blockSize,
32
32
  mlpFactor: e.config.mlpFactor,
33
- loraConfig: e.config.loraConfig,
33
+ loraConfig: e.config.loraConfig ? Object.fromEntries(e.config.loraConfig) : void 0,
34
+ loraName: e.config.loraName,
34
35
  windowSize: e.config.windowSize
35
- }, n.file("config.json", JSON.stringify(o, void 0, 4), {
36
+ }, n.file("config.json", JSON.stringify(t, void 0, 4), {
36
37
  binary: !1
37
38
  }), n.file(
38
39
  "meta.json",
@@ -55,7 +56,7 @@ async function z(e, i, a) {
55
56
  ), n.file(
56
57
  "tokeniser.json",
57
58
  JSON.stringify({
58
- type: i instanceof _ ? "char" : "bpe",
59
+ type: i instanceof l ? "char" : "bpe",
59
60
  vocab: i.getVocab(),
60
61
  merges: await i.getMerges()
61
62
  }),
@@ -63,8 +64,8 @@ async function z(e, i, a) {
63
64
  binary: !1
64
65
  }
65
66
  ), a?.files)
66
- for (const [t, f] of Object.entries(a.files))
67
- n.file(t, JSON.stringify(f), { binary: !1 });
67
+ for (const [o, f] of Object.entries(a.files))
68
+ n.file(o, JSON.stringify(f), { binary: !1 });
68
69
  return n.generateAsync({ type: "blob" });
69
70
  }
70
71
  export {
@@ -8,7 +8,8 @@ export interface TransformersConfigBase {
8
8
  num_attention_heads: number;
9
9
  block_size: number;
10
10
  mlpFactor: number;
11
- loraConfig?: LoRAConfig;
11
+ loraConfig?: Record<string, LoRAConfig>;
12
+ loraName?: string;
12
13
  }
13
14
  export interface TransformersConfigV1 extends TransformersConfigBase {
14
15
  model_type: 'GenAI_NanoGPT_v1';
@@ -11,7 +11,8 @@ export interface GPTConfigBase {
11
11
  nHead: number;
12
12
  nEmbed: number;
13
13
  mlpFactor: number;
14
- loraConfig?: LoRAConfig;
14
+ loraConfig?: Map<string, LoRAConfig>;
15
+ loraName?: string;
15
16
  }
16
17
  export interface GPTConfigV1 extends GPTConfigBase {
17
18
  modelType: 'GenAI_NanoGPT_v1';
@@ -1,4 +1,4 @@
1
- const a = {
1
+ const t = {
2
2
  modelType: "GenAI_NanoGPT_v2",
3
3
  vocabSize: 2e3,
4
4
  blockSize: 128,
@@ -11,33 +11,40 @@ const a = {
11
11
  // Embedding dimension
12
12
  mlpFactor: 4
13
13
  };
14
- function e(r, o) {
15
- if (typeof r[o] != "number" || Number.isNaN(r[o]))
16
- throw new Error(`Invalid config: "${o}" must be a number.`);
14
+ function n(e, a) {
15
+ if (typeof e[a] != "number" || Number.isNaN(e[a]))
16
+ throw new Error(`Invalid config: "${a}" must be a number.`);
17
17
  }
18
- function i(r) {
19
- const o = (n) => typeof n == "object" && n !== null && !Array.isArray(n);
20
- if (!o(r))
18
+ function l(e) {
19
+ const a = (o) => typeof o == "object" && o !== null && !Array.isArray(o);
20
+ if (!a(e))
21
21
  throw new Error("Invalid config: expected an object.");
22
- if (e(r, "vocabSize"), e(r, "blockSize"), e(r, "nLayer"), e(r, "nHead"), e(r, "nEmbed"), e(r, "mlpFactor"), r.loraConfig !== void 0) {
23
- if (!o(r.loraConfig))
22
+ if (n(e, "vocabSize"), n(e, "blockSize"), n(e, "nLayer"), n(e, "nHead"), n(e, "nEmbed"), n(e, "mlpFactor"), e.loraConfig !== void 0) {
23
+ if (!a(e.loraConfig))
24
24
  throw new Error('Invalid config: "loraConfig" must be an object.');
25
- if (e(r.loraConfig, "rank"), e(r.loraConfig, "alpha"), !Array.isArray(r.loraConfig.variables) || !r.loraConfig.variables.every((n) => typeof n == "string"))
26
- throw new Error('Invalid config: "loraConfig.variables" must be a string array.');
25
+ const o = Object.values(e.loraConfig);
26
+ if (!o.every((r) => a(r)))
27
+ throw new Error('Invalid config: each entry in "loraConfig" must be an object.');
28
+ if (!o.every((r) => "rank" in r && "alpha" in r && "variables" in r))
29
+ throw new Error('Invalid config: each LoRA config must have "rank", "alpha", and "variables" fields.');
30
+ o.forEach((r) => {
31
+ if (n(r, "rank"), n(r, "alpha"), !Array.isArray(r.variables) || !r.variables.every((i) => typeof i == "string"))
32
+ throw new Error('Invalid config: "variables" must be a string array.');
33
+ });
27
34
  }
28
- if (r.modelType === "GenAI_NanoGPT_v1") {
29
- if (typeof r.useRope != "boolean")
35
+ if (e.modelType === "GenAI_NanoGPT_v1") {
36
+ if (typeof e.useRope != "boolean")
30
37
  throw new Error('Invalid config: "useRope" must be a boolean for GenAI_NanoGPT_v1.');
31
38
  return;
32
39
  }
33
- if (r.modelType === "GenAI_NanoGPT_v2") {
34
- if (r.windowSize !== void 0 && typeof r.windowSize != "string")
40
+ if (e.modelType === "GenAI_NanoGPT_v2") {
41
+ if (e.windowSize !== void 0 && typeof e.windowSize != "string")
35
42
  throw new Error('Invalid config: "windowSize" must be a string for GenAI_NanoGPT_v2.');
36
43
  return;
37
44
  }
38
45
  throw new Error('Invalid config: "modelType" must be "GenAI_NanoGPT_v1" or "GenAI_NanoGPT_v2".');
39
46
  }
40
47
  export {
41
- a as defaultConfig,
42
- i as validateConfig
48
+ t as defaultConfig,
49
+ l as validateConfig
43
50
  };
@@ -21,9 +21,16 @@ export default abstract class Model<T extends ModelForwardAttributes, C extends
21
21
  trainingState: TrainingState | null;
22
22
  metaData: TransformersMetadata;
23
23
  private loraLayer?;
24
- attachLoRA(loraConfig: LoRAConfig): void;
24
+ private loraMap;
25
+ constructor(config: C);
26
+ createLoRA(name: string, loraConfig: LoRAConfig): void;
27
+ deleteLoRA(name: string): void;
28
+ renameLoRA(oldName: string, newName: string): void;
29
+ mergeLoRA(name: string): void;
30
+ attachLoRA(name: string): void;
25
31
  detachLoRA(): void;
26
- hasLoRA(): boolean;
32
+ hasLoRA(name?: string): boolean;
33
+ listLoRAs(): string[];
27
34
  get lora(): LoRA | null;
28
35
  abstract getClassName(): string;
29
36
  abstract forward(attrs: T, idx: Tensor): Tensor;