@genai-fi/nanogpt 0.17.0 → 0.17.2

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.
@@ -1,4 +1,4 @@
1
- import { GPTConfig } from './models/config';
1
+ import { GPTConfig, LoRAConfig } from './models/config';
2
2
  import { Conversation, ITokeniser } from './tokeniser/type';
3
3
  import { SaveOptions } from './loader/save';
4
4
  import { LoadModelOptions } from './loader/load';
@@ -38,6 +38,13 @@ export default class TeachableLLM {
38
38
  /** Model is both ready and not busy */
39
39
  get ready(): boolean;
40
40
  get busy(): boolean;
41
+ createLoRA(name: string, loraConfig: LoRAConfig): void;
42
+ deleteLoRA(name: string): void;
43
+ renameLoRA(oldName: string, newName: string): void;
44
+ attachLoRA(name: string): void;
45
+ detachLoRA(): void;
46
+ hasLoRA(name?: string): boolean;
47
+ listLoRAs(): string[];
41
48
  estimateTrainingMemoryUsage(batchSize: number): number;
42
49
  private setStatus;
43
50
  saveModel(options?: SaveOptions): Promise<Blob>;
@@ -58,11 +65,11 @@ export default class TeachableLLM {
58
65
  on(event: 'phase', listener: (phase: ModelPhase) => void): void;
59
66
  on(event: 'error', listener: (error: Error) => void): void;
60
67
  on(event: 'trainStep', listener: (step: TrainingLogEntry) => void): void;
61
- on(event: 'loaded', listener: () => void): void;
68
+ on(event: 'loaded' | 'changeLoRA', listener: () => void): void;
62
69
  off(event: 'status', listener: (status: TeachableLLMStatus) => void): void;
63
70
  off(event: 'phase', listener: (phase: ModelPhase) => void): void;
64
71
  off(event: 'error', listener: (error: Error) => void): void;
65
72
  off(event: 'trainStep', listener: (step: TrainingLogEntry) => void): void;
66
- off(event: 'loaded', listener: () => void): void;
73
+ off(event: 'loaded' | 'changeLoRA', listener: () => void): void;
67
74
  }
68
75
  export {};
@@ -1,7 +1,7 @@
1
1
  import { validateConfig as m } from "./models/config.js";
2
2
  import { saveModel as d } from "./loader/save.js";
3
- import { loadModel as p } from "./loader/load.js";
4
- import u from "./Generator.js";
3
+ import { loadModel as u } from "./loader/load.js";
4
+ import p from "./Generator.js";
5
5
  import h from "./Trainer.js";
6
6
  import { E as f } from "./index-DvYrXKkX.js";
7
7
  import { dummyPassTrainAsync as l } from "./utilities/dummy.js";
@@ -66,8 +66,8 @@ class a {
66
66
  _memoryRequirements;
67
67
  meta = {};
68
68
  _trainer = null;
69
- constructor(t, r) {
70
- this._config = r?.config, this._tokeniser = t, this._model = r;
69
+ constructor(t, i) {
70
+ this._config = i?.config, this._tokeniser = t, this._model = i;
71
71
  }
72
72
  get vocab() {
73
73
  return this._tokeniser?.getVocab() || [];
@@ -109,8 +109,43 @@ class a {
109
109
  get busy() {
110
110
  return this._status === "busy" || this._status === "training";
111
111
  }
112
+ createLoRA(t, i) {
113
+ if (!this._model)
114
+ throw new Error("model_not_initialized.");
115
+ this._model.createLoRA(t, i), this.ee.emit("changeLoRA");
116
+ }
117
+ deleteLoRA(t) {
118
+ if (!this._model)
119
+ throw new Error("model_not_initialized.");
120
+ this._model.deleteLoRA(t), this.ee.emit("changeLoRA");
121
+ }
122
+ renameLoRA(t, i) {
123
+ if (!this._model)
124
+ throw new Error("model_not_initialized.");
125
+ this._model.renameLoRA(t, i), this.ee.emit("changeLoRA");
126
+ }
127
+ attachLoRA(t) {
128
+ if (!this._model)
129
+ throw new Error("model_not_initialized.");
130
+ this._model.attachLoRA(t), this.ee.emit("changeLoRA");
131
+ }
132
+ detachLoRA() {
133
+ if (!this._model)
134
+ throw new Error("model_not_initialized.");
135
+ this._model.detachLoRA(), this.ee.emit("changeLoRA");
136
+ }
137
+ hasLoRA(t) {
138
+ if (!this._model)
139
+ throw new Error("model_not_initialized.");
140
+ return this._model.hasLoRA(t);
141
+ }
142
+ listLoRAs() {
143
+ if (!this._model)
144
+ throw new Error("model_not_initialized.");
145
+ return this._model.listLoRAs();
146
+ }
112
147
  estimateTrainingMemoryUsage(t) {
113
- const r = this._memoryRequirements ?? { perBatch: 0, gradients: 0 }, e = r.perBatch * t, o = r.gradients;
148
+ const i = this._memoryRequirements ?? { perBatch: 0, gradients: 0 }, e = i.perBatch * t, o = i.gradients;
114
149
  return e * 0.66 + o * 4;
115
150
  }
116
151
  setStatus(t) {
@@ -124,10 +159,10 @@ class a {
124
159
  name: t?.name || this.meta.name
125
160
  });
126
161
  }
127
- static loadModel(t, r) {
162
+ static loadModel(t, i) {
128
163
  const e = new a();
129
- return p(t, r).then(({ model: o, tokeniser: n, metaData: i }) => {
130
- m(o.config), e._model = o, e._tokeniser = n, e._config = o.config, i?.name && (e.meta.name = i.name), e.setStatus("warmup"), l(o).then((s) => {
164
+ return u(t, i).then(({ model: o, tokeniser: n, metaData: r }) => {
165
+ m(o.config), e._model = o, e._tokeniser = n, e._config = o.config, r?.name && (e.meta.name = r.name), e.setStatus("warmup"), l(o).then((s) => {
131
166
  e._memoryRequirements = s, e.setStatus("ready"), e.ee.emit("loaded"), e.ee.emit("phase", e.phase);
132
167
  }).catch((s) => {
133
168
  e.setStatus("error"), e.ee.emit("error", s), console.error("Error during warmup:", s);
@@ -136,16 +171,16 @@ class a {
136
171
  e.setStatus("error"), e.ee.emit("error", o), console.error("Error loading model:", o);
137
172
  }), e;
138
173
  }
139
- static create(t, r) {
140
- m(r);
141
- const e = r, o = t === "char" ? new c(e.vocabSize) : new g(e.vocabSize), n = k(e), i = new a(o, n);
142
- return i.setStatus("warmup"), l(n).then((s) => {
143
- i._memoryRequirements = s, i.tokeniser.trained ? (i.setStatus("ready"), i.ee.emit("loaded"), i.ee.emit("phase", i.phase)) : (i.setStatus("awaitingTokens"), i.ee.emit("loaded"), i.ee.emit("phase", i.phase), i.tokeniser.once("trainStatus", (_) => {
144
- _ === "trained" && i.setStatus("ready");
174
+ static create(t, i) {
175
+ m(i);
176
+ const e = i, o = t === "char" ? new c(e.vocabSize) : new g(e.vocabSize), n = k(e), r = new a(o, n);
177
+ return r.setStatus("warmup"), l(n).then((s) => {
178
+ r._memoryRequirements = s, r.tokeniser.trained ? (r.setStatus("ready"), r.ee.emit("loaded"), r.ee.emit("phase", r.phase)) : (r.setStatus("awaitingTokens"), r.ee.emit("loaded"), r.ee.emit("phase", r.phase), r.tokeniser.once("trainStatus", (_) => {
179
+ _ === "trained" && r.setStatus("ready");
145
180
  }));
146
181
  }).catch((s) => {
147
- i.setStatus("error"), i.ee.emit("error", s), console.error("Error during warmup:", s);
148
- }), i;
182
+ r.setStatus("error"), r.ee.emit("error", s), console.error("Error during warmup:", s);
183
+ }), r;
149
184
  }
150
185
  getProfiler() {
151
186
  return this._model?.getProfiler();
@@ -164,56 +199,56 @@ class a {
164
199
  getNumParams() {
165
200
  return this._model ? this._model.getNumParams() : 0;
166
201
  }
167
- trainer(t, r) {
202
+ trainer(t, i) {
168
203
  if (!this._model || !this._tokeniser)
169
204
  throw new Error("model_or_tokeniser_not_initialized.");
170
205
  this._trainer && t && this._trainer.trainingType !== t && (this._trainer.dispose(), this._trainer = null);
171
- const e = this._trainer === null ? new h(this._model, this._tokeniser, t, r) : new h(this._trainer, r);
206
+ const e = this._trainer === null ? new h(this._model, this._tokeniser, t, i) : new h(this._trainer, i);
172
207
  return e.on("start", () => {
173
208
  this.setStatus("training"), this.phase = t === "sft" ? "finetuned" : "pretrained";
174
209
  }), e.on("stop", () => this.setStatus("ready")), e.on("log", async (o) => {
175
210
  const n = this.ee.listeners("trainStep");
176
- for (const i of n)
177
- await i(o);
211
+ for (const r of n)
212
+ await r(o);
178
213
  }), this._trainer && this._trainer !== e && this._trainer.removeAllListeners(), this._trainer = e, e;
179
214
  }
180
- async train(t, r, e) {
181
- const o = this.trainer(e, r);
215
+ async train(t, i, e) {
216
+ const o = this.trainer(e, i);
182
217
  await o.prepare(t), await o.train();
183
218
  }
184
219
  async trainTokeniser(t) {
185
220
  if (!this._tokeniser)
186
221
  throw new Error("tokeniser_not_initialized.");
187
- const r = await this._tokeniser.train(t);
188
- return this._status === "awaitingTokens" && this.setStatus("ready"), r;
222
+ const i = await this._tokeniser.train(t);
223
+ return this._status === "awaitingTokens" && this.setStatus("ready"), i;
189
224
  }
190
225
  generator() {
191
226
  if (!this._model || !this._tokeniser)
192
227
  throw new Error("model_or_tokeniser_not_initialized.");
193
- const t = new u(this._model, this._tokeniser);
228
+ const t = new p(this._model, this._tokeniser);
194
229
  return t.on("start", () => {
195
230
  this.status === "ready" && this.setStatus("busy");
196
231
  }), t.on("stop", () => {
197
232
  this.status === "busy" && this.setStatus("ready");
198
233
  }), t;
199
234
  }
200
- generateText(t, r) {
201
- return Array.isArray(t) ? this.generator().generate(t, r) : this.generator().generate([], r);
235
+ generateText(t, i) {
236
+ return Array.isArray(t) ? this.generator().generate(t, i) : this.generator().generate([], i);
202
237
  }
203
238
  dispose() {
204
239
  this._trainer && (this._trainer.dispose(), this._trainer = null), this._model?.dispose(), this.ee.removeAllListeners();
205
240
  }
206
241
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
207
- on(t, r) {
242
+ on(t, i) {
208
243
  if (t === "loaded" && this.loaded) {
209
- setTimeout(() => r(), 0);
244
+ setTimeout(() => i(), 0);
210
245
  return;
211
246
  }
212
- this.ee.on(t, r);
247
+ this.ee.on(t, i);
213
248
  }
214
249
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
215
- off(t, r) {
216
- this.ee.off(t, r);
250
+ off(t, i) {
251
+ this.ee.off(t, i);
217
252
  }
218
253
  }
219
254
  export {
@@ -58,15 +58,15 @@ class st extends i {
58
58
  loraLayer;
59
59
  loraMap = /* @__PURE__ */ new Map();
60
60
  constructor(t) {
61
- super(t), t.loraConfig && (console.log(t.loraConfig), t.loraConfig.forEach((r, o) => {
61
+ super(t), t.loraConfig && t.loraConfig.forEach((r, o) => {
62
62
  this.createLoRA(o, r);
63
- }));
63
+ });
64
64
  }
65
65
  createLoRA(t, r) {
66
66
  if (this.loraMap.has(t))
67
67
  return;
68
68
  const o = new e(t, this.weightStore, r.alpha, r.rank, r.variables);
69
- this.loraMap.set(t, o), this.config.loraConfig = this.config.loraConfig || /* @__PURE__ */ new Map(), this.config.loraConfig.set(t, r), console.log(`Created LoRA ${t} with rank ${r.rank} and alpha ${r.alpha}`);
69
+ this.loraMap.set(t, o), this.config.loraConfig = this.config.loraConfig || /* @__PURE__ */ new Map(), this.config.loraConfig.set(t, r);
70
70
  }
71
71
  deleteLoRA(t) {
72
72
  const r = this.loraMap.get(t);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genai-fi/nanogpt",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "type": "module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",