@genai-fi/nanogpt 1.2.0 → 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.
@@ -13,9 +13,13 @@ export default class BeamAPI {
13
13
  private _model;
14
14
  private _tokeniser;
15
15
  private _busyCount;
16
+ private _jobs;
17
+ private _queue;
16
18
  constructor(model: Model<ModelForwardAttributes, GPTConfig>, tokeniser: ITokeniser);
17
19
  on<E extends keyof BeamEvents>(event: E, listener: BeamEvents[E]): void;
18
20
  off<E extends keyof BeamEvents>(event: E, listener: BeamEvents[E]): void;
21
+ cancel(id?: string): void;
22
+ private startJob;
19
23
  create(conversation: Conversation[], options: BeamerOptions): string;
20
24
  }
21
25
  export {};
@@ -7,6 +7,8 @@ var r = class {
7
7
  _model;
8
8
  _tokeniser;
9
9
  _busyCount = 0;
10
+ _jobs = /* @__PURE__ */ new Map();
11
+ _queue = [];
10
12
  constructor(t, n) {
11
13
  this._model = t, this._tokeniser = n, this.ee = new e();
12
14
  }
@@ -16,15 +18,34 @@ var r = class {
16
18
  off(e, t) {
17
19
  this.ee.off(e, t);
18
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
+ }
19
40
  create(e, r) {
20
- let i = t();
21
- return this._busyCount++, this.ee.emit("status", "busy"), new n(this._model, this._tokeniser).beam(e, r, (e) => {
22
- this.ee.emit("progress", i, e);
23
- }).then((e) => {
24
- this._busyCount--, this._busyCount === 0 && this.ee.emit("status", "ready"), this.ee.emit("done", i, e);
25
- }).catch((e) => {
26
- this._busyCount--, this._busyCount === 0 && this.ee.emit("status", "ready"), this.ee.emit("error", e);
27
- }), i;
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);
28
49
  }
29
50
  };
30
51
  //#endregion
@@ -1,11 +1,11 @@
1
1
  import { Conversation, ITokeniser } from '../tokeniser/type';
2
2
  import { default as Model, ModelForwardAttributes } from '../models/model';
3
- import { default as EE } from 'eventemitter3';
4
3
  import { BeamerOptions, IBeam } from './types';
5
- export default class Beamer extends EE {
4
+ export default class Beamer {
6
5
  private readonly model;
7
6
  private readonly tokeniser;
8
7
  private actualTokeniser;
8
+ private active;
9
9
  constructor(model: Model<ModelForwardAttributes>, tokeniser: ITokeniser);
10
10
  private shouldTerminate;
11
11
  private initialise;
@@ -13,5 +13,6 @@ export default class Beamer extends EE {
13
13
  private createInitialContext;
14
14
  private appendTokenToContext;
15
15
  private batchedNextProbabilities;
16
+ cancel(): void;
16
17
  beam(conversation: Conversation[], options: BeamerOptions, onStep?: (beams: IBeam[]) => void): Promise<IBeam[]>;
17
18
  }
@@ -1,30 +1,30 @@
1
- import { t as e } from "../eventemitter3-D_qV3Lof.js";
2
- import t from "../tokeniser/CharTokeniser.js";
3
- import { L as n, V as r, Y as i, _n as a, _r as o, di as s, xt as c } from "../dist-Da20xy8E.js";
4
- import l from "../utilities/topP.js";
5
- import { CHARS as u, padArray as d } from "./utilities.js";
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";
6
5
  //#region lib/inference/Beamer.ts
7
- function f(e, t) {
6
+ function d(e, t) {
8
7
  return e.map((e, t) => ({
9
8
  token: t,
10
9
  prob: e
11
10
  })).filter((e) => e.prob > 0).sort((e, t) => t.prob - e.prob).slice(0, Math.max(1, t));
12
11
  }
13
- var p = class extends e {
12
+ var f = class {
14
13
  model;
15
14
  tokeniser;
16
15
  actualTokeniser;
16
+ active = !1;
17
17
  constructor(e, t) {
18
- super(), this.model = e, this.tokeniser = t, this.actualTokeniser = t;
18
+ this.model = e, this.tokeniser = t, this.actualTokeniser = t;
19
19
  }
20
20
  shouldTerminate(e, t) {
21
21
  if (e) return !1;
22
22
  let n = this.tokeniser.getSpecialTokenIndex("<|assistant_end|>");
23
23
  return t === this.actualTokeniser.eosToken || t === n;
24
24
  }
25
- initialise(e) {
26
- let n = this.tokeniser.trained ? this.tokeniser : new t(d(u, this.tokeniser.vocabSize));
27
- this.actualTokeniser = n, e?.loraName ? this.model.attachLoRA(e.loraName) : this.model.hasLoRA() && this.model.detachLoRA();
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
28
  }
29
29
  async tokeniseConversation(e) {
30
30
  let t = this.actualTokeniser.encodeConversation(e, !1);
@@ -32,65 +32,68 @@ var p = class extends e {
32
32
  return t;
33
33
  }
34
34
  createInitialContext(e) {
35
- let t = this.model.config.blockSize, r = e.length > t ? e.slice(-t) : e.slice();
35
+ let n = this.model.config.blockSize, r = e.length > n ? e.slice(-n) : e.slice();
36
36
  return {
37
- context: n(r.concat(Array(t - r.length).fill(0)), "int32"),
37
+ context: t(r.concat(Array(n - r.length).fill(0)), "int32"),
38
38
  contextLength: r.length
39
39
  };
40
40
  }
41
- appendTokenToContext(e, t, r) {
42
- let i = this.model.config.blockSize;
43
- return t < i ? {
44
- context: s(() => {
45
- let n = c([t], i).squeeze([0]).asType("int32"), o = a(1, "int32").sub(n), s = n.mul(a(r, "int32"));
46
- return e.mul(o).add(s);
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
47
  }),
48
- contextLength: t + 1
48
+ contextLength: n + 1
49
49
  } : {
50
- context: s(() => o([e.slice([1], [i - 1]), n([r], "int32")], 0)),
51
- contextLength: i
50
+ context: o(() => a([e.slice([1], [c - 1]), t([r], "int32")], 0)),
51
+ contextLength: c
52
52
  };
53
53
  }
54
- async batchedNextProbabilities(e, t, n) {
54
+ async batchedNextProbabilities(e, t, i) {
55
55
  if (e.length === 0) return [];
56
- let a = e[0], o = e.slice();
57
- for (; o.length < t;) o.push(a);
58
- let u = r(o.map((e) => e.context)), d = this.model.forward({
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
59
  training: !1,
60
60
  mixedPrecision: !0
61
- }, u), f = o.map((e) => Math.max(0, e.contextLength - 1)), p = s(() => {
62
- let e = c(f, this.model.config.blockSize).expandDims(2);
63
- return i(d.mul(e).sum(1));
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
64
  }), m = e.length, h = m < t ? p.slice([0, 0], [m, this.model.config.vocabSize]) : p, g = await h.array();
65
65
  h !== p && h.dispose(), p.dispose(), d.dispose(), u.dispose();
66
- let _ = n.topP ?? 1;
67
- return g.map((e) => l(e, _));
66
+ let _ = i.topP ?? 1;
67
+ return g.map((e) => c(e, _));
68
+ }
69
+ cancel() {
70
+ this.active = !1;
68
71
  }
69
72
  async beam(e, t, n) {
70
73
  if (!t || t.beams < 1 || t.maxBeamLength < 1) return [];
71
74
  let r = Math.max(8, t.beams);
72
- this.initialise(t);
75
+ this.initialise(t), this.active = !0;
73
76
  let i = await this.tokeniseConversation(e), a = this.createInitialContext(i), o = [{
74
77
  tokens: [],
75
- score: 0,
78
+ score: 1,
76
79
  text: "",
77
80
  terminated: !1,
78
81
  context: a.context,
79
82
  contextLength: a.contextLength
80
83
  }], s = t.maxBeamLength, c = t.endOnWhiteSpace === !0 ? Math.max(s, t.maxLength ?? s + this.model.config.blockSize) : s, l = Date.now();
81
- for (let e = 0; e < c; e++) {
84
+ for (let e = 0; e < c && this.active; e++) {
82
85
  let e = o.filter((e) => !e.terminated);
83
86
  if (e.length === 0) break;
84
87
  let i = await this.batchedNextProbabilities(e, r, t), a = [];
85
88
  for (let n = 0; n < e.length; n++) {
86
- let o = e[n], c = i[n], l = f(c, t.topK ? Math.min(t.topK, r) : Math.max(1, r));
89
+ let o = e[n], c = i[n], l = d(c, t.topK ? Math.min(t.topK, r) : Math.max(1, r));
87
90
  for (let e of l) {
88
- let n = this.actualTokeniser.decode([e.token]), r = this.shouldTerminate(t.allowSpecial ?? !1, e.token), i = o.tokens.length + 1 >= s, c = t.endOnWhiteSpace === !0 && i && /\s/.test(n), l = c && o.tokens.length > 0 && /^\s/.test(n);
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);
89
92
  a.push({
90
93
  parent: o,
91
94
  token: e.token,
92
95
  tokenText: n,
93
- score: o.score + Math.log(Math.max(e.prob, 1e-12)),
96
+ score: o.score * e.prob,
94
97
  terminatedByToken: r,
95
98
  terminatedByWhitespace: c,
96
99
  dropLeadingWhitespaceTerminator: l
@@ -117,16 +120,14 @@ var p = class extends e {
117
120
  if (o.forEach((e) => e.context.dispose()), c.length === 0) break;
118
121
  o = c, n && Date.now() - l >= 40 && (n(o.slice(0, t.beams)), l = Date.now());
119
122
  }
120
- o.forEach((e) => {
121
- e.score /= Math.max(1, e.text.length);
122
- });
123
- let u = o.slice().sort((e, t) => t.score - e.score), d = [], p = /* @__PURE__ */ new Set();
123
+ this.active = !1;
124
+ let u = o.slice().sort((e, t) => t.score - e.score), f = [], p = /* @__PURE__ */ new Set();
124
125
  for (let e of u) {
125
126
  let n = e.text.trim();
126
- if (p.has(n) || (p.add(n), d.push(e)), d.length >= t.beams) break;
127
+ if (p.has(n) || (p.add(n), f.push(e)), f.length >= t.beams) break;
127
128
  }
128
- return o.forEach((e) => e.context.dispose()), d;
129
+ return o.forEach((e) => e.context.dispose()), f;
129
130
  }
130
131
  };
131
132
  //#endregion
132
- export { p as default };
133
+ export { f as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genai-fi/nanogpt",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",