@genai-fi/nanogpt 1.1.4 → 1.2.1

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.
@@ -9,6 +9,7 @@ import { ModelMode, TransformersMetadata } from './loader/types';
9
9
  import { default as Responses } from './api/responses';
10
10
  import { default as Training } from './api/training';
11
11
  import { GPUOptions } from './patches/webgpu_base';
12
+ import { default as BeamAPI } from './api/beamer';
12
13
  type TeachableLLMStatus = 'warmup' | 'awaitingTokens' | 'ready' | 'training' | 'loading' | 'busy' | 'error';
13
14
  export default class TeachableLLM {
14
15
  static instances: Set<TeachableLLM>;
@@ -20,6 +21,7 @@ export default class TeachableLLM {
20
21
  private _memoryRequirements?;
21
22
  private _responses;
22
23
  private _training;
24
+ private _beaming;
23
25
  meta: TransformersMetadata;
24
26
  static selectBackend(backend: 'cpu' | 'webgl' | 'webgpu', options?: GPUOptions): Promise<void>;
25
27
  constructor(tokeniser?: ITokeniser, model?: Model<ModelForwardAttributes, GPTConfig>);
@@ -53,6 +55,7 @@ export default class TeachableLLM {
53
55
  getNumParams(): number;
54
56
  trainTokeniser(text: ConversationStream[]): Promise<number>;
55
57
  get responses(): Responses;
58
+ get beaming(): BeamAPI;
56
59
  get training(): Training;
57
60
  dispose(): void;
58
61
  on(event: 'status', listener: (status: TeachableLLMStatus) => void): void;
@@ -11,8 +11,9 @@ import l from "./api/responses.js";
11
11
  import u from "./api/training.js";
12
12
  import { selectBackend as d } from "./backend.js";
13
13
  import { getBackendDevice as f } from "./patches/webgpu_base.js";
14
+ import p from "./api/beamer.js";
14
15
  //#region lib/TeachableLLM.ts
15
- var p = class p {
16
+ var m = class m {
16
17
  static instances = /* @__PURE__ */ new Set();
17
18
  ee = new e();
18
19
  _config;
@@ -22,6 +23,7 @@ var p = class p {
22
23
  _memoryRequirements;
23
24
  _responses = null;
24
25
  _training = null;
26
+ _beaming = null;
25
27
  meta = {
26
28
  version: 2,
27
29
  application: "@genai-fi/nanogpt"
@@ -30,14 +32,14 @@ var p = class p {
30
32
  if (await d(e, t), e === "webgpu") {
31
33
  let e = f();
32
34
  e && e.lost.then(() => {
33
- console.warn("WebGPU device lost"), p.instances.forEach((e) => {
35
+ console.warn("WebGPU device lost"), m.instances.forEach((e) => {
34
36
  e.setStatus("error"), e.ee.emit("lost");
35
37
  });
36
38
  });
37
39
  }
38
40
  }
39
41
  constructor(e, t) {
40
- this._config = t?.config, this._tokeniser = e, this._model = t, t?.metaData && (this.meta = t.metaData), p.instances.add(this);
42
+ this._config = t?.config, this._tokeniser = e, this._model = t, t?.metaData && (this.meta = t.metaData), m.instances.add(this);
41
43
  }
42
44
  get vocab() {
43
45
  return this._tokeniser?.getVocab() || [];
@@ -124,7 +126,7 @@ var p = class p {
124
126
  } : void 0);
125
127
  }
126
128
  static loadModel(e, t) {
127
- let n = new p();
129
+ let n = new m();
128
130
  return o(e, t).then(({ model: e, tokeniser: t, metaData: a, optimizer: o, log: s }) => {
129
131
  r(e.config), n._model = e, n._tokeniser = t, n._config = e.config, a && (n.meta = a), n.setStatus("warmup"), i(e).then((t) => {
130
132
  n._memoryRequirements = t, o && e.metaData.pretrainingSettings && e.metaData.pretrainingData && n.training.restore(e.metaData.pretrainingSettings, s || [], o, e.metaData.pretrainingData), n.setStatus("ready"), n.ee.emit("loaded"), n.ee.emit("mode", n.mode);
@@ -137,7 +139,7 @@ var p = class p {
137
139
  }
138
140
  static create(e, o) {
139
141
  r(o);
140
- let s = o, c = e === "char" ? new t(s.vocabSize) : e === "bpe" ? new n(s.vocabSize) : e, l = a(s), u = new p(c, l);
142
+ let s = o, c = e === "char" ? new t(s.vocabSize) : e === "bpe" ? new n(s.vocabSize) : e, l = a(s), u = new m(c, l);
141
143
  return u.setStatus("warmup"), i(l).then((e) => {
142
144
  u._memoryRequirements = e, u.tokeniser.trained ? (u.setStatus("ready"), u.ee.emit("loaded"), u.ee.emit("mode", u.mode)) : (u.setStatus("awaitingTokens"), u.ee.emit("loaded"), u.ee.emit("mode", u.mode), u.tokeniser.once("trainStatus", (e) => {
143
145
  e === "trained" && u.setStatus("ready");
@@ -177,6 +179,17 @@ var p = class p {
177
179
  }
178
180
  return this._responses;
179
181
  }
182
+ get beaming() {
183
+ if (!this._beaming) {
184
+ if (!this._model || !this._tokeniser) throw Error("model_or_tokeniser_not_initialized.");
185
+ this._beaming = new p(this._model, this._tokeniser), this._beaming.on("error", (e) => {
186
+ this.setStatus("error"), this.ee.emit("error", e);
187
+ }), this._beaming.on("status", (e) => {
188
+ e === "busy" ? this.setStatus("busy") : e === "ready" && this.setStatus("ready");
189
+ });
190
+ }
191
+ return this._beaming;
192
+ }
180
193
  get training() {
181
194
  if (!this._training) {
182
195
  if (!this._model || !this._tokeniser) throw Error("model_or_tokeniser_not_initialized.");
@@ -193,7 +206,7 @@ var p = class p {
193
206
  return this._training;
194
207
  }
195
208
  dispose() {
196
- this._responses &&= (this._responses.dispose(), null), this._training &&= (this._training.dispose(), null), this._model?.dispose(), this.ee.removeAllListeners(), p.instances.delete(this);
209
+ this._responses &&= (this._responses.dispose(), null), this._training &&= (this._training.dispose(), null), this._model?.dispose(), this.ee.removeAllListeners(), m.instances.delete(this);
197
210
  }
198
211
  on(e, t) {
199
212
  if (e === "loaded" && this.loaded) {
@@ -207,4 +220,4 @@ var p = class p {
207
220
  }
208
221
  };
209
222
  //#endregion
210
- export { p as default };
223
+ export { m as default };
@@ -0,0 +1,25 @@
1
+ import { Conversation, ITokeniser } from '../../tokeniser/type';
2
+ import { default as Model, ModelForwardAttributes } from '../../models/model';
3
+ import { GPTConfig } from '../../models/config';
4
+ import { BeamerOptions, IBeam } from '../../inference/types';
5
+ interface BeamEvents {
6
+ error: (error: Error) => void;
7
+ status: (status: 'busy' | 'ready') => void;
8
+ progress: (id: string, beams: IBeam[]) => void;
9
+ done: (id: string, beams: IBeam[]) => void;
10
+ }
11
+ export default class BeamAPI {
12
+ private ee;
13
+ private _model;
14
+ private _tokeniser;
15
+ private _busyCount;
16
+ private _jobs;
17
+ private _queue;
18
+ constructor(model: Model<ModelForwardAttributes, GPTConfig>, tokeniser: ITokeniser);
19
+ on<E extends keyof BeamEvents>(event: E, listener: BeamEvents[E]): void;
20
+ off<E extends keyof BeamEvents>(event: E, listener: BeamEvents[E]): void;
21
+ cancel(id?: string): void;
22
+ private startJob;
23
+ create(conversation: Conversation[], options: BeamerOptions): string;
24
+ }
25
+ export {};
@@ -0,0 +1,52 @@
1
+ import { t as e } from "../eventemitter3-D_qV3Lof.js";
2
+ import { t } from "../v4-BK7K-jy_.js";
3
+ import n from "../inference/Beamer.js";
4
+ //#region lib/api/beamer.ts
5
+ var r = class {
6
+ ee;
7
+ _model;
8
+ _tokeniser;
9
+ _busyCount = 0;
10
+ _jobs = /* @__PURE__ */ new Map();
11
+ _queue = [];
12
+ constructor(t, n) {
13
+ this._model = t, this._tokeniser = n, this.ee = new e();
14
+ }
15
+ on(e, t) {
16
+ this.ee.on(e, t);
17
+ }
18
+ off(e, t) {
19
+ this.ee.off(e, t);
20
+ }
21
+ cancel(e) {
22
+ if (e) {
23
+ let t = this._jobs.get(e);
24
+ t && (t.canceled = !0, t.beamer.cancel());
25
+ } else for (let e of this._jobs.values()) e.canceled = !0, e.beamer.cancel();
26
+ }
27
+ startJob(e) {
28
+ this._busyCount++, this.ee.emit("status", "busy"), e.beamer.beam(e.conversation, e.options, (t) => {
29
+ this.ee.emit("progress", e.id, t);
30
+ }).then((t) => {
31
+ this._busyCount--, this._busyCount === 0 && this.ee.emit("status", "ready"), this.ee.emit("done", e.id, t), this._jobs.delete(e.id);
32
+ let n = this._queue.shift();
33
+ n && this.startJob(n);
34
+ }).catch((t) => {
35
+ this._busyCount--, this._busyCount === 0 && this.ee.emit("status", "ready"), this.ee.emit("error", t), this._jobs.delete(e.id);
36
+ let n = this._queue.shift();
37
+ n && this.startJob(n);
38
+ });
39
+ }
40
+ create(e, r) {
41
+ let i = t(), a = {
42
+ id: i,
43
+ beamer: new n(this._model, this._tokeniser),
44
+ canceled: !1,
45
+ conversation: e,
46
+ options: r
47
+ };
48
+ return this._jobs.set(i, a), this._busyCount > 0 ? (this._queue.push(a), i) : (this.startJob(a), i);
49
+ }
50
+ };
51
+ //#endregion
52
+ export { r as default };
@@ -0,0 +1,18 @@
1
+ import { Conversation, ITokeniser } from '../tokeniser/type';
2
+ import { default as Model, ModelForwardAttributes } from '../models/model';
3
+ import { BeamerOptions, IBeam } from './types';
4
+ export default class Beamer {
5
+ private readonly model;
6
+ private readonly tokeniser;
7
+ private actualTokeniser;
8
+ private active;
9
+ constructor(model: Model<ModelForwardAttributes>, tokeniser: ITokeniser);
10
+ private shouldTerminate;
11
+ private initialise;
12
+ private tokeniseConversation;
13
+ private createInitialContext;
14
+ private appendTokenToContext;
15
+ private batchedNextProbabilities;
16
+ cancel(): void;
17
+ beam(conversation: Conversation[], options: BeamerOptions, onStep?: (beams: IBeam[]) => void): Promise<IBeam[]>;
18
+ }
@@ -0,0 +1,133 @@
1
+ import e from "../tokeniser/CharTokeniser.js";
2
+ import { L as t, V as n, Y as r, _n as i, _r as a, di as o, xt as s } from "../dist-Da20xy8E.js";
3
+ import c from "../utilities/topP.js";
4
+ import { CHARS as l, padArray as u } from "./utilities.js";
5
+ //#region lib/inference/Beamer.ts
6
+ function d(e, t) {
7
+ return e.map((e, t) => ({
8
+ token: t,
9
+ prob: e
10
+ })).filter((e) => e.prob > 0).sort((e, t) => t.prob - e.prob).slice(0, Math.max(1, t));
11
+ }
12
+ var f = class {
13
+ model;
14
+ tokeniser;
15
+ actualTokeniser;
16
+ active = !1;
17
+ constructor(e, t) {
18
+ this.model = e, this.tokeniser = t, this.actualTokeniser = t;
19
+ }
20
+ shouldTerminate(e, t) {
21
+ if (e) return !1;
22
+ let n = this.tokeniser.getSpecialTokenIndex("<|assistant_end|>");
23
+ return t === this.actualTokeniser.eosToken || t === n;
24
+ }
25
+ initialise(t) {
26
+ let n = this.tokeniser.trained ? this.tokeniser : new e(u(l, this.tokeniser.vocabSize));
27
+ this.actualTokeniser = n, t?.loraName ? this.model.attachLoRA(t.loraName) : this.model.hasLoRA() && this.model.detachLoRA();
28
+ }
29
+ async tokeniseConversation(e) {
30
+ let t = this.actualTokeniser.encodeConversation(e, !1);
31
+ for (; t.length > 0 && (t[t.length - 1] === this.actualTokeniser.eosToken || t[t.length - 1] === this.actualTokeniser.getSpecialTokenIndex("<|assistant_end|>"));) t.pop();
32
+ return t;
33
+ }
34
+ createInitialContext(e) {
35
+ let n = this.model.config.blockSize, r = e.length > n ? e.slice(-n) : e.slice();
36
+ return {
37
+ context: t(r.concat(Array(n - r.length).fill(0)), "int32"),
38
+ contextLength: r.length
39
+ };
40
+ }
41
+ appendTokenToContext(e, n, r) {
42
+ let c = this.model.config.blockSize;
43
+ return n < c ? {
44
+ context: o(() => {
45
+ let t = s([n], c).squeeze([0]).asType("int32"), a = i(1, "int32").sub(t), o = t.mul(i(r, "int32"));
46
+ return e.mul(a).add(o);
47
+ }),
48
+ contextLength: n + 1
49
+ } : {
50
+ context: o(() => a([e.slice([1], [c - 1]), t([r], "int32")], 0)),
51
+ contextLength: c
52
+ };
53
+ }
54
+ async batchedNextProbabilities(e, t, i) {
55
+ if (e.length === 0) return [];
56
+ let a = e[0], l = e.slice();
57
+ for (; l.length < t;) l.push(a);
58
+ let u = n(l.map((e) => e.context)), d = this.model.forward({
59
+ training: !1,
60
+ mixedPrecision: !0
61
+ }, u), f = l.map((e) => Math.max(0, e.contextLength - 1)), p = o(() => {
62
+ let e = s(f, this.model.config.blockSize).expandDims(2);
63
+ return r(d.mul(e).sum(1));
64
+ }), m = e.length, h = m < t ? p.slice([0, 0], [m, this.model.config.vocabSize]) : p, g = await h.array();
65
+ h !== p && h.dispose(), p.dispose(), d.dispose(), u.dispose();
66
+ let _ = i.topP ?? 1;
67
+ return g.map((e) => c(e, _));
68
+ }
69
+ cancel() {
70
+ this.active = !1;
71
+ }
72
+ async beam(e, t, n) {
73
+ if (!t || t.beams < 1 || t.maxBeamLength < 1) return [];
74
+ let r = Math.max(8, t.beams);
75
+ this.initialise(t), this.active = !0;
76
+ let i = await this.tokeniseConversation(e), a = this.createInitialContext(i), o = [{
77
+ tokens: [],
78
+ score: 1,
79
+ text: "",
80
+ terminated: !1,
81
+ context: a.context,
82
+ contextLength: a.contextLength
83
+ }], s = t.maxBeamLength, c = t.endOnWhiteSpace === !0 ? Math.max(s, t.maxLength ?? s + this.model.config.blockSize) : s, l = Date.now();
84
+ for (let e = 0; e < c && this.active; e++) {
85
+ let e = o.filter((e) => !e.terminated);
86
+ if (e.length === 0) break;
87
+ let i = await this.batchedNextProbabilities(e, r, t), a = [];
88
+ for (let n = 0; n < e.length; n++) {
89
+ let o = e[n], c = i[n], l = d(c, t.topK ? Math.min(t.topK, r) : Math.max(1, r));
90
+ for (let e of l) {
91
+ let n = this.actualTokeniser.decode([e.token]), r = this.shouldTerminate(t.allowSpecial ?? !1, e.token), i = o.tokens.length + 1 >= Math.max(2, s), c = t.endOnWhiteSpace === !0 && i && /\s/.test(n), l = c && o.tokens.length > 0 && /^\s/.test(n);
92
+ a.push({
93
+ parent: o,
94
+ token: e.token,
95
+ tokenText: n,
96
+ score: o.score * e.prob,
97
+ terminatedByToken: r,
98
+ terminatedByWhitespace: c,
99
+ dropLeadingWhitespaceTerminator: l
100
+ });
101
+ }
102
+ }
103
+ let c = o.filter((e) => e.terminated).slice();
104
+ a.sort((e, t) => t.score - e.score);
105
+ for (let e of a) {
106
+ if (c.length >= r) break;
107
+ let t = e.terminatedByToken || e.terminatedByWhitespace, n = !e.dropLeadingWhitespaceTerminator, i = n ? e.parent.tokens.concat(e.token) : e.parent.tokens.slice(), a = e.terminatedByToken || e.dropLeadingWhitespaceTerminator ? e.parent.text : e.parent.text + e.tokenText, o = n ? this.appendTokenToContext(e.parent.context, e.parent.contextLength, e.token) : {
108
+ context: e.parent.context.clone(),
109
+ contextLength: e.parent.contextLength
110
+ };
111
+ c.push({
112
+ tokens: i,
113
+ score: e.score,
114
+ text: a,
115
+ terminated: t,
116
+ context: o.context,
117
+ contextLength: o.contextLength
118
+ });
119
+ }
120
+ if (o.forEach((e) => e.context.dispose()), c.length === 0) break;
121
+ o = c, n && Date.now() - l >= 40 && (n(o.slice(0, t.beams)), l = Date.now());
122
+ }
123
+ this.active = !1;
124
+ let u = o.slice().sort((e, t) => t.score - e.score), f = [], p = /* @__PURE__ */ new Set();
125
+ for (let e of u) {
126
+ let n = e.text.trim();
127
+ if (p.has(n) || (p.add(n), f.push(e)), f.length >= t.beams) break;
128
+ }
129
+ return o.forEach((e) => e.context.dispose()), f;
130
+ }
131
+ };
132
+ //#endregion
133
+ export { f as default };
@@ -1,28 +1,16 @@
1
1
  import { t as e } from "../eventemitter3-D_qV3Lof.js";
2
- import { SPECIALS as t } from "../tokeniser/BaseTokeniser.js";
3
- import n from "../tokeniser/CharTokeniser.js";
4
- import { A as r, Ct as i, I as a, Y as o, _r as s, an as c, di as l, oi as u, yt as d } from "../dist-Da20xy8E.js";
5
- import f from "../utilities/multinomialCPU.js";
6
- import p from "../utilities/topP.js";
7
- import { sparseSoftmaxCrossEntropy as m } from "../training/sparseCrossEntropy.js";
8
- import h from "./tokenisePrompt.js";
9
- import { getTokenConfidence as g } from "./utilities.js";
2
+ import t from "../tokeniser/CharTokeniser.js";
3
+ import { A as n, Ct as r, I as i, Y as a, _r as o, an as s, di as c, oi as l, yt as u } from "../dist-Da20xy8E.js";
4
+ import d from "../utilities/multinomialCPU.js";
5
+ import f from "../utilities/topP.js";
6
+ import { sparseSoftmaxCrossEntropy as p } from "../training/sparseCrossEntropy.js";
7
+ import m from "./tokenisePrompt.js";
8
+ import { CHARS as h, getTokenConfidence as g, padArray as _ } from "./utilities.js";
10
9
  //#region lib/inference/Generator.ts
11
- function _(e) {
10
+ function v(e) {
12
11
  return Array.isArray(e);
13
12
  }
14
- var v = [
15
- ...t,
16
- ...Array.from({ length: 95 }, (e, t) => String.fromCharCode(t + 32)),
17
- ..."áéíóúüñ¿¡",
18
- ..."äöÄÖÅå",
19
- ..."αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ",
20
- ..."абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
21
- ];
22
- function y(e, t) {
23
- return e.length === t ? e : e.length > t ? e.slice(0, t) : e.concat(Array(t - e.length).fill(""));
24
- }
25
- var b = class extends e {
13
+ var y = class extends e {
26
14
  model;
27
15
  tokeniser;
28
16
  active = !1;
@@ -45,56 +33,56 @@ var b = class extends e {
45
33
  let n = this.tokeniser.getSpecialTokenIndex("<|assistant_end|>");
46
34
  return t === this.actualTokeniser.eosToken || t === n;
47
35
  }
48
- async _generateToken(e, t, n) {
49
- let s = n?.temperature ?? 1, h = n?.topK, _ = n?.topP, v = n?.usePadding ?? !1, y = {
36
+ async _generateToken(e, t, o) {
37
+ let m = o?.temperature ?? 1, h = o?.topK, _ = o?.topP, v = o?.usePadding ?? !1, y = {
50
38
  training: !1,
51
- attentionScores: n?.outputAttention ? { attentionOut: [] } : void 0,
39
+ attentionScores: o?.outputAttention ? { attentionOut: [] } : void 0,
52
40
  cache: t,
53
- outputEmbeddings: !!n?.outputHiddenStates
54
- }, [b, x] = l(() => {
55
- let t = e, r = t.shape[1], i = r <= this.model.config.blockSize ? t : t.slice([0, r - this.model.config.blockSize], [t.shape[0], this.model.config.blockSize]), o = v ? this.model.config.blockSize - i.shape[1] : 0, c = o > 0 ? d(i, [[0, 0], [0, o]]) : i, l = this.model.forward(y, c), f = l.shape[1] - 1 - o, p = l.slice([
41
+ outputEmbeddings: !!o?.outputHiddenStates
42
+ }, [b, x] = c(() => {
43
+ let t = e, n = t.shape[1], r = n <= this.model.config.blockSize ? t : t.slice([0, n - this.model.config.blockSize], [t.shape[0], this.model.config.blockSize]), a = v ? this.model.config.blockSize - r.shape[1] : 0, s = a > 0 ? u(r, [[0, 0], [0, a]]) : r, c = this.model.forward(y, s), d = c.shape[1] - 1 - a, f = c.slice([
56
44
  0,
57
- f,
45
+ d,
58
46
  0
59
47
  ], [
60
- l.shape[0],
48
+ c.shape[0],
61
49
  1,
62
- l.shape[2]
50
+ c.shape[2]
63
51
  ]), h;
64
- if (n?.targets) {
65
- let e = n.targets.shift();
52
+ if (o?.targets) {
53
+ let e = o.targets.shift();
66
54
  if (e !== void 0) {
67
- let t = a([[e]], [1, 1], "int32"), n = m(p, t);
55
+ let t = i([[e]], [1, 1], "int32"), n = p(f, t);
68
56
  h = n.mean(), t.dispose(), n.dispose();
69
57
  }
70
58
  }
71
59
  return y.attentionScores?.attentionOut && y.attentionScores.attentionOut.forEach((e, t) => {
72
- e.shape[1] !== 1 && (y.attentionScores.attentionOut[t] = u(e.slice([
60
+ e.shape[1] !== 1 && (y.attentionScores.attentionOut[t] = l(e.slice([
73
61
  0,
74
- f,
62
+ d,
75
63
  0
76
64
  ], [
77
65
  e.shape[0],
78
66
  1,
79
67
  e.shape[2]
80
68
  ])), e.dispose());
81
- }), l.dispose(), [p.div(s).squeeze([1]), h];
69
+ }), c.dispose(), [f.div(m).squeeze([1]), h];
82
70
  }), S, C, w, T = Math.random();
83
71
  if (_) {
84
- let e = o(b), t = await e.array();
72
+ let e = a(b), t = await e.array();
85
73
  e.dispose();
86
- let r = p(t, _);
87
- (n?.outputScores || n?.outputConfidence) && (C = t), S = f(r, T);
74
+ let n = f(t, _);
75
+ (o?.outputScores || o?.outputConfidence) && (C = t), S = d(n, T);
88
76
  } else if (h) {
89
- let { values: e, indices: t } = r(b, h), n = i(e, 1);
90
- S = c(t, n, 1), e.dispose(), t.dispose(), n.dispose();
91
- } else if (S = i(b, 1), n?.outputScores || n?.outputConfidence) {
92
- let e = o(b);
77
+ let { values: e, indices: t } = n(b, h), i = r(e, 1);
78
+ S = s(t, i, 1), e.dispose(), t.dispose(), i.dispose();
79
+ } else if (S = r(b, 1), o?.outputScores || o?.outputConfidence) {
80
+ let e = a(b);
93
81
  C = await e.array(), e.dispose();
94
82
  }
95
83
  if (y.embeddings) {
96
- let e = (n?.outputHiddenStates === "all" ? y.embeddings : y.embeddings.filter((e) => e.name.startsWith("block_output_"))).map(async (e) => {
97
- let t = e.tensor.shape[1], r = e.tensor.slice([
84
+ let e = (o?.outputHiddenStates === "all" ? y.embeddings : y.embeddings.filter((e) => e.name.startsWith("block_output_"))).map(async (e) => {
85
+ let t = e.tensor.shape[1], n = e.tensor.slice([
98
86
  0,
99
87
  t - 1,
100
88
  0
@@ -104,28 +92,28 @@ var b = class extends e {
104
92
  e.tensor.shape[2]
105
93
  ]);
106
94
  e.tensor.dispose();
107
- let i = r.squeeze([1]);
108
- if (r.dispose(), n?.outputHiddenStates === "softmax") {
109
- let t = this.model.project(i);
110
- i.dispose();
111
- let n = o(t, -1);
95
+ let r = n.squeeze([1]);
96
+ if (n.dispose(), o?.outputHiddenStates === "softmax") {
97
+ let t = this.model.project(r);
98
+ r.dispose();
99
+ let n = a(t, -1);
112
100
  t.dispose();
113
- let r = {
101
+ let i = {
114
102
  name: e.name,
115
103
  tensor: await n.array()
116
104
  };
117
- return n.dispose(), r;
118
- } else if (n?.outputHiddenStates === "logits") {
119
- let t = this.model.project(i);
120
- i.dispose();
105
+ return n.dispose(), i;
106
+ } else if (o?.outputHiddenStates === "logits") {
107
+ let t = this.model.project(r);
108
+ r.dispose();
121
109
  let n = {
122
110
  name: e.name,
123
111
  tensor: await t.array()
124
112
  };
125
113
  return t.dispose(), n;
126
114
  } else {
127
- let t = await i.array();
128
- return i.dispose(), {
115
+ let t = await r.array();
116
+ return r.dispose(), {
129
117
  name: e.name,
130
118
  tensor: t
131
119
  };
@@ -137,16 +125,16 @@ var b = class extends e {
137
125
  S.dispose(), S = E;
138
126
  let D = (await S.array())[0][0], O = this.actualTokeniser.decode([D]);
139
127
  this.lastToken = D;
140
- let k = this.shouldTerminate(n?.allowSpecial ?? !1, D), A = {
128
+ let k = this.shouldTerminate(o?.allowSpecial ?? !1, D), A = {
141
129
  outputTensor: S,
142
130
  token: D,
143
131
  text: O,
144
- confidence: n?.outputConfidence && C ? g(C[0]) : null,
145
- score: n?.outputScore && C ? C[0][D] : null,
146
- logits: n?.outputLogits ? (await b.array())[0] : null,
147
- scores: n?.outputScores && C ? C[0] : null,
132
+ confidence: o?.outputConfidence && C ? g(C[0]) : null,
133
+ score: o?.outputScore && C ? C[0][D] : null,
134
+ logits: o?.outputLogits ? (await b.array())[0] : null,
135
+ scores: o?.outputScores && C ? C[0] : null,
148
136
  hiddenStates: w ? w.map((e) => e.tensor[0]) : null,
149
- attention: n?.outputAttention ? await Promise.all(y.attentionScores?.attentionOut?.map((e) => e.array()) ?? []) : null,
137
+ attention: o?.outputAttention ? await Promise.all(y.attentionScores?.attentionOut?.map((e) => e.array()) ?? []) : null,
150
138
  loss: this.lastLoss,
151
139
  multinomialRand: T,
152
140
  terminated: k
@@ -155,7 +143,7 @@ var b = class extends e {
155
143
  let e = await x.array();
156
144
  x.dispose(), A.loss = e;
157
145
  }
158
- return this.rawOutput.push(A), (!n?.chunkSize || this.tokenCount++ % n.chunkSize === 0) && (this.emit("tokens", A), n?._onChunk && await n._onChunk(A)), A;
146
+ return this.rawOutput.push(A), (!o?.chunkSize || this.tokenCount++ % o.chunkSize === 0) && (this.emit("tokens", A), o?._onChunk && await o._onChunk(A)), A;
159
147
  }
160
148
  async _generate(e, t) {
161
149
  let n = !1;
@@ -164,8 +152,8 @@ var b = class extends e {
164
152
  content: "",
165
153
  _timestamp: Date.now()
166
154
  }), n = !0, this.resetCache(!e?.noCache)) : (this.lastToken < 0 || t) && this.resetCache(!e?.noCache);
167
- let r = this.lastToken >= 0 && this.cache ? a([this.lastToken], [1, 1], "int32") : await h(this.actualTokeniser, this.model.config.blockSize, t ? n ? this.outputConversation.slice(0, -1) : this.outputConversation : void 0, e), i = e?.maxLength ?? 1e3;
168
- for (let t = 0; t < i && this.active; t++) {
155
+ let r = this.lastToken >= 0 && this.cache ? i([this.lastToken], [1, 1], "int32") : await m(this.actualTokeniser, this.model.config.blockSize, t ? n ? this.outputConversation.slice(0, -1) : this.outputConversation : void 0, e), a = e?.maxLength ?? 1e3;
156
+ for (let t = 0; t < a && this.active; t++) {
169
157
  let n = await this._generateToken(r, this.cache ? this.cache : void 0, {
170
158
  ...e,
171
159
  usePadding: !this.cache
@@ -173,14 +161,14 @@ var b = class extends e {
173
161
  if (this.cache) r.dispose(), r = n.outputTensor;
174
162
  else {
175
163
  let e = r;
176
- r = s([r, n.outputTensor], 1), e.dispose();
164
+ r = o([r, n.outputTensor], 1), e.dispose();
177
165
  }
178
- let a = this.outputConversation[this.outputConversation.length - 1];
166
+ let i = this.outputConversation[this.outputConversation.length - 1];
179
167
  if (this.cache || n.outputTensor.dispose(), n.terminated) {
180
- a._completed = !0;
168
+ i._completed = !0;
181
169
  break;
182
170
  }
183
- t === i - 1 && i > 1 && (a._completed = !0, n.terminated = !0), a.content += n.text, a._output ||= [], a._output.push(n);
171
+ t === a - 1 && a > 1 && (i._completed = !0, n.terminated = !0), i.content += n.text, i._output ||= [], i._output.push(n);
184
172
  }
185
173
  return r.dispose(), this.outputConversation;
186
174
  }
@@ -195,8 +183,8 @@ var b = class extends e {
195
183
  dispose() {
196
184
  this.reset();
197
185
  }
198
- initialise(e, t) {
199
- if (this.cache && t?.noCache && this.reset(), this.initialPrompt = e || null, this.lastToken === -1 ? this.outputConversation = (this.initialPrompt || []).slice() : e && e.length > this.outputConversation.length && (this.outputConversation = (this.initialPrompt || []).slice(), this.resetCache()), !this.cache && !t?.noCache && (this.model.config.modelType !== "GenAI_NanoGPT_v1" || this.model.config.useRope)) {
186
+ initialise(e, n) {
187
+ if (this.cache && n?.noCache && this.reset(), this.initialPrompt = e || null, this.lastToken === -1 ? this.outputConversation = (this.initialPrompt || []).slice() : e && e.length > this.outputConversation.length && (this.outputConversation = (this.initialPrompt || []).slice(), this.resetCache()), !this.cache && !n?.noCache && (this.model.config.modelType !== "GenAI_NanoGPT_v1" || this.model.config.useRope)) {
200
188
  let e = Array(this.model.config.nLayer);
201
189
  for (let t = 0; t < this.model.config.nLayer; t++) e[t] = {
202
190
  k: void 0,
@@ -206,15 +194,15 @@ var b = class extends e {
206
194
  };
207
195
  this.cache = e, this.lastToken = -1;
208
196
  }
209
- let r = this.tokeniser.trained ? this.tokeniser : new n(y(v, this.tokeniser.vocabSize));
210
- this.actualTokeniser = r, t?.loraName ? this.model.attachLoRA(t.loraName) : this.model.hasLoRA() && this.model.detachLoRA();
197
+ let r = this.tokeniser.trained ? this.tokeniser : new t(_(h, this.tokeniser.vocabSize));
198
+ this.actualTokeniser = r, n?.loraName ? this.model.attachLoRA(n.loraName) : this.model.hasLoRA() && this.model.detachLoRA();
211
199
  }
212
200
  async step(e, t) {
213
201
  let n = {
214
202
  ...t,
215
203
  maxLength: 1
216
204
  };
217
- return _(e) ? this.generate(e, n) : this.generate({
205
+ return v(e) ? this.generate(e, n) : this.generate({
218
206
  ...e,
219
207
  ...n
220
208
  });
@@ -247,17 +235,7 @@ var b = class extends e {
247
235
  async startJob(e, t) {
248
236
  this.initialise(e, t), this.active = !0, this.model.metaData.generationSettings = t, t?.maxLength !== 1 && this.emit("start");
249
237
  let n = await this._generate(t, !!e);
250
- if (this.active = !1, this.startTime !== null) {
251
- let e = Date.now(), n = e - this.startTime;
252
- this.startTime = null, this.model.metaData.actionLog = this.model.metaData.actionLog || [], this.model.metaData.actionLog.push({
253
- action: "generate",
254
- timestamp: e,
255
- duration: n,
256
- tokensProcessed: this.rawOutput.length,
257
- options: t || {}
258
- });
259
- }
260
- return this.emit("stop"), n;
238
+ return this.active = !1, this.startTime !== null && (this.startTime = null), this.emit("stop"), n;
261
239
  }
262
240
  getQueueLength() {
263
241
  return this.jobQueue.length;
@@ -273,4 +251,4 @@ var b = class extends e {
273
251
  }
274
252
  };
275
253
  //#endregion
276
- export { b as default, _ as isConversation };
254
+ export { y as default, v as isConversation };
@@ -50,3 +50,13 @@ export interface IGeneratorResponse {
50
50
  id: string;
51
51
  done: boolean;
52
52
  }
53
+ export interface BeamerOptions extends IGenerateOptions {
54
+ maxBeamLength: number;
55
+ beams: number;
56
+ endOnWhiteSpace?: boolean;
57
+ }
58
+ export interface IBeam {
59
+ tokens: number[];
60
+ score: number;
61
+ text: string;
62
+ }
@@ -7,3 +7,5 @@ import { IGeneratorOutput } from './types';
7
7
  export declare function getTokenConfidence(probabilities: number[]): number;
8
8
  export declare function getAttention(output: IGeneratorOutput, layer: number, head: number): number[] | null;
9
9
  export declare function getHiddenState(output: IGeneratorOutput, layer: number): number[] | null;
10
+ export declare const CHARS: string[];
11
+ export declare function padArray(arr: string[], length: number): string[];
@@ -1,5 +1,6 @@
1
+ import { SPECIALS as e } from "../tokeniser/BaseTokeniser.js";
1
2
  //#region lib/inference/utilities.ts
2
- function e(e) {
3
+ function t(e) {
3
4
  if (!e.length) return 0;
4
5
  let t = 0;
5
6
  for (let n of e) n > 0 && (t -= n * Math.log(n));
@@ -8,13 +9,24 @@ function e(e) {
8
9
  let r = t / n;
9
10
  return Math.min(1, Math.max(0, 1 - r));
10
11
  }
11
- function t(e, t, n) {
12
+ function n(e, t, n) {
12
13
  if (!e.attention || !e.attention[t] || !e.attention[t][n]) return null;
13
14
  let r = e.attention[t][n].length;
14
15
  return e.attention[t][n][r - 1];
15
16
  }
16
- function n(e, t) {
17
+ function r(e, t) {
17
18
  return !e.hiddenStates || !e.hiddenStates[t] ? null : e.hiddenStates[t];
18
19
  }
20
+ var i = [
21
+ ...e,
22
+ ...Array.from({ length: 95 }, (e, t) => String.fromCharCode(t + 32)),
23
+ ..."áéíóúüñ¿¡",
24
+ ..."äöÄÖÅå",
25
+ ..."αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ",
26
+ ..."абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
27
+ ];
28
+ function a(e, t) {
29
+ return e.length === t ? e : e.length > t ? e.slice(0, t) : e.concat(Array(t - e.length).fill(""));
30
+ }
19
31
  //#endregion
20
- export { t as getAttention, n as getHiddenState, e as getTokenConfidence };
32
+ export { i as CHARS, n as getAttention, r as getHiddenState, t as getTokenConfidence, a as padArray };
@@ -23,7 +23,9 @@ async function d(e, t) {
23
23
  let n = e.file("config.json");
24
24
  if (!n) return;
25
25
  let r = await n.async("string"), i = JSON.parse(r);
26
- if (i.loraName) {
26
+ if (i.loraConfig && Object.entries(i.loraConfig).forEach(([e, n]) => {
27
+ t.hasLoRA(e) || t.createLoRA(e, n);
28
+ }), i.loraName) {
27
29
  if (t.hasLoRA()) throw Error("Model already has LoRA attached");
28
30
  t.attachLoRA(i.loraName);
29
31
  }
package/dist/main.d.ts CHANGED
@@ -16,7 +16,7 @@ export type { DatasetMetadata, ModelMode } from './loader/types';
16
16
  export * as models from './models';
17
17
  export type { GPTConfig } from './models/config';
18
18
  export type { ModelForwardAttributes } from './models/model';
19
- export type { IGenerateOptions, IGeneratorResponse, IGeneratorOutput, GeneratorConversation } from './inference/types';
19
+ export type { IGenerateOptions, IGeneratorResponse, IGeneratorOutput, GeneratorConversation, IBeam, BeamerOptions, } from './inference/types';
20
20
  export type { TrainingOptions, TrainingLogEntry } from './training/types';
21
21
  export type { ITrainingJob } from './api/training';
22
22
  export declare const training: {
@@ -1 +1 @@
1
- export default function topP(probs: number[][], tP: number): number[];
1
+ export default function topP(probs: number[][] | number[], tP: number): number[];
@@ -1,18 +1,18 @@
1
1
  //#region lib/utilities/topP.ts
2
2
  function e(e, t) {
3
- let n = e[0].map((e, t) => ({
3
+ let n = Array.isArray(e[0]) ? e[0] : e, r = n.map((e, t) => ({
4
4
  prob: e,
5
5
  index: t
6
- })).sort((e, t) => t.prob - e.prob), r = 0, i = Array(n.length).fill(0);
7
- for (let e of n) if (r += e.prob, i[e.index] = e.prob, r >= t) break;
8
- let a = i.reduce((e, t) => e + t, 0);
9
- if (a === 0) {
10
- let t = e[0], n = t.reduce((e, t) => e + t, 0);
11
- if (n > 0) return t.map((e) => e / n);
12
- let r = 1 / t.length;
13
- return t.map(() => r);
6
+ })).sort((e, t) => t.prob - e.prob), i = 0, a = Array(r.length).fill(0);
7
+ for (let e of r) if (i += e.prob, a[e.index] = e.prob, i >= t) break;
8
+ let o = a.reduce((e, t) => e + t, 0);
9
+ if (o === 0) {
10
+ let e = n, t = e.reduce((e, t) => e + t, 0);
11
+ if (t > 0) return e.map((e) => e / t);
12
+ let r = 1 / e.length;
13
+ return e.map(() => r);
14
14
  }
15
- return i.map((e) => e / a);
15
+ return a.map((e) => e / o);
16
16
  }
17
17
  //#endregion
18
18
  export { e as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genai-fi/nanogpt",
3
- "version": "1.1.4",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",