@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.
- package/dist/TeachableLLM.d.ts +3 -0
- package/dist/TeachableLLM.js +20 -7
- package/dist/api/beamer.d.ts +25 -0
- package/dist/api/beamer.js +52 -0
- package/dist/inference/Beamer.d.ts +18 -0
- package/dist/inference/Beamer.js +133 -0
- package/dist/inference/Generator.js +65 -87
- package/dist/inference/types.d.ts +10 -0
- package/dist/inference/utilities.d.ts +2 -0
- package/dist/inference/utilities.js +16 -4
- package/dist/loader/load.js +3 -1
- package/dist/main.d.ts +1 -1
- package/dist/utilities/topP.d.ts +1 -1
- package/dist/utilities/topP.js +10 -10
- package/package.json +1 -1
package/dist/TeachableLLM.d.ts
CHANGED
|
@@ -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;
|
package/dist/TeachableLLM.js
CHANGED
|
@@ -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
|
|
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"),
|
|
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),
|
|
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
|
|
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
|
|
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(),
|
|
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 {
|
|
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
|
|
3
|
-
import n from "../
|
|
4
|
-
import
|
|
5
|
-
import f from "../utilities/
|
|
6
|
-
import p from "../
|
|
7
|
-
import
|
|
8
|
-
import h from "./
|
|
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
|
|
10
|
+
function v(e) {
|
|
12
11
|
return Array.isArray(e);
|
|
13
12
|
}
|
|
14
|
-
var
|
|
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,
|
|
49
|
-
let
|
|
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:
|
|
39
|
+
attentionScores: o?.outputAttention ? { attentionOut: [] } : void 0,
|
|
52
40
|
cache: t,
|
|
53
|
-
outputEmbeddings: !!
|
|
54
|
-
}, [b, x] =
|
|
55
|
-
let t = e,
|
|
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
|
-
|
|
45
|
+
d,
|
|
58
46
|
0
|
|
59
47
|
], [
|
|
60
|
-
|
|
48
|
+
c.shape[0],
|
|
61
49
|
1,
|
|
62
|
-
|
|
50
|
+
c.shape[2]
|
|
63
51
|
]), h;
|
|
64
|
-
if (
|
|
65
|
-
let e =
|
|
52
|
+
if (o?.targets) {
|
|
53
|
+
let e = o.targets.shift();
|
|
66
54
|
if (e !== void 0) {
|
|
67
|
-
let 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] =
|
|
60
|
+
e.shape[1] !== 1 && (y.attentionScores.attentionOut[t] = l(e.slice([
|
|
73
61
|
0,
|
|
74
|
-
|
|
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
|
-
}),
|
|
69
|
+
}), c.dispose(), [f.div(m).squeeze([1]), h];
|
|
82
70
|
}), S, C, w, T = Math.random();
|
|
83
71
|
if (_) {
|
|
84
|
-
let e =
|
|
72
|
+
let e = a(b), t = await e.array();
|
|
85
73
|
e.dispose();
|
|
86
|
-
let
|
|
87
|
-
(
|
|
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 } =
|
|
90
|
-
S =
|
|
91
|
-
} else if (S =
|
|
92
|
-
let e =
|
|
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 = (
|
|
97
|
-
let t = e.tensor.shape[1],
|
|
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
|
|
108
|
-
if (
|
|
109
|
-
let t = this.model.project(
|
|
110
|
-
|
|
111
|
-
let n =
|
|
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
|
|
101
|
+
let i = {
|
|
114
102
|
name: e.name,
|
|
115
103
|
tensor: await n.array()
|
|
116
104
|
};
|
|
117
|
-
return n.dispose(),
|
|
118
|
-
} else if (
|
|
119
|
-
let t = this.model.project(
|
|
120
|
-
|
|
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
|
|
128
|
-
return
|
|
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(
|
|
128
|
+
let k = this.shouldTerminate(o?.allowSpecial ?? !1, D), A = {
|
|
141
129
|
outputTensor: S,
|
|
142
130
|
token: D,
|
|
143
131
|
text: O,
|
|
144
|
-
confidence:
|
|
145
|
-
score:
|
|
146
|
-
logits:
|
|
147
|
-
scores:
|
|
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:
|
|
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), (!
|
|
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 ?
|
|
168
|
-
for (let t = 0; 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 =
|
|
164
|
+
r = o([r, n.outputTensor], 1), e.dispose();
|
|
177
165
|
}
|
|
178
|
-
let
|
|
166
|
+
let i = this.outputConversation[this.outputConversation.length - 1];
|
|
179
167
|
if (this.cache || n.outputTensor.dispose(), n.terminated) {
|
|
180
|
-
|
|
168
|
+
i._completed = !0;
|
|
181
169
|
break;
|
|
182
170
|
}
|
|
183
|
-
t ===
|
|
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,
|
|
199
|
-
if (this.cache &&
|
|
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
|
|
210
|
-
this.actualTokeniser = r,
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
32
|
+
export { i as CHARS, n as getAttention, r as getHiddenState, t as getTokenConfidence, a as padArray };
|
package/dist/loader/load.js
CHANGED
|
@@ -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.
|
|
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: {
|
package/dist/utilities/topP.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function topP(probs: number[][], tP: number): number[];
|
|
1
|
+
export default function topP(probs: number[][] | number[], tP: number): number[];
|
package/dist/utilities/topP.js
CHANGED
|
@@ -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),
|
|
7
|
-
for (let e of
|
|
8
|
-
let
|
|
9
|
-
if (
|
|
10
|
-
let
|
|
11
|
-
if (
|
|
12
|
-
let r = 1 /
|
|
13
|
-
return
|
|
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
|
|
15
|
+
return a.map((e) => e / o);
|
|
16
16
|
}
|
|
17
17
|
//#endregion
|
|
18
18
|
export { e as default };
|