@matchbox-ai/train 0.1.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +3 -0
  4. package/THIRD-PARTY-NOTICES.md +17 -0
  5. package/dist/codecs/index.d.ts +2 -0
  6. package/dist/codecs/index.d.ts.map +1 -0
  7. package/dist/define-pipeline-Colvwt7u.js +32 -0
  8. package/dist/define-pipeline-Colvwt7u.js.map +1 -0
  9. package/dist/encoders/index.d.ts +3 -0
  10. package/dist/encoders/index.d.ts.map +1 -0
  11. package/dist/encoders/word-tokens.d.ts +5 -0
  12. package/dist/encoders/word-tokens.d.ts.map +1 -0
  13. package/dist/evaluate-sequence-ZCwyomzQ.js +42 -0
  14. package/dist/evaluate-sequence-ZCwyomzQ.js.map +1 -0
  15. package/dist/evaluation/evaluate-sequence.d.ts +17 -0
  16. package/dist/evaluation/evaluate-sequence.d.ts.map +1 -0
  17. package/dist/evaluation/same-output.d.ts +2 -0
  18. package/dist/evaluation/same-output.d.ts.map +1 -0
  19. package/dist/index.d.ts +10 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +33 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/load-project.d.ts +34 -0
  24. package/dist/load-project.d.ts.map +1 -0
  25. package/dist/models/index.d.ts +2 -0
  26. package/dist/models/index.d.ts.map +1 -0
  27. package/dist/models/presets.d.ts +14 -0
  28. package/dist/models/presets.d.ts.map +1 -0
  29. package/dist/models/record/fit.d.ts +124 -0
  30. package/dist/models/record/fit.d.ts.map +1 -0
  31. package/dist/models/record/index.d.ts +2 -0
  32. package/dist/models/record/index.d.ts.map +1 -0
  33. package/dist/models/record/run.d.ts +115 -0
  34. package/dist/models/record/run.d.ts.map +1 -0
  35. package/dist/models/record/verify-export.d.ts +8 -0
  36. package/dist/models/record/verify-export.d.ts.map +1 -0
  37. package/dist/models/sequence/create-network.d.ts +3 -0
  38. package/dist/models/sequence/create-network.d.ts.map +1 -0
  39. package/dist/models/sequence/fit-sequence.d.ts +139 -0
  40. package/dist/models/sequence/fit-sequence.d.ts.map +1 -0
  41. package/dist/models/sequence/index.d.ts +3 -0
  42. package/dist/models/sequence/index.d.ts.map +1 -0
  43. package/dist/models/sequence/run-sequence.d.ts +162 -0
  44. package/dist/models/sequence/run-sequence.d.ts.map +1 -0
  45. package/dist/models/sequence/types.d.ts +10 -0
  46. package/dist/models/sequence/types.d.ts.map +1 -0
  47. package/dist/package-model-CPj0qnQs.js +18 -0
  48. package/dist/package-model-CPj0qnQs.js.map +1 -0
  49. package/dist/packaging/package-model.d.ts +3 -0
  50. package/dist/packaging/package-model.d.ts.map +1 -0
  51. package/dist/pipeline/define-pipeline.d.ts +20 -0
  52. package/dist/pipeline/define-pipeline.d.ts.map +1 -0
  53. package/dist/pipeline/index.d.ts +3 -0
  54. package/dist/pipeline/index.d.ts.map +1 -0
  55. package/dist/project/artifact.d.ts +129 -0
  56. package/dist/project/artifact.d.ts.map +1 -0
  57. package/dist/project/config.d.ts +37 -0
  58. package/dist/project/config.d.ts.map +1 -0
  59. package/dist/project/discover.d.ts +2 -0
  60. package/dist/project/discover.d.ts.map +1 -0
  61. package/dist/project/index.d.ts +4 -0
  62. package/dist/project/index.d.ts.map +1 -0
  63. package/dist/project/index.js +2 -0
  64. package/dist/project-BP331m20.js +125 -0
  65. package/dist/project-BP331m20.js.map +1 -0
  66. package/dist/record-BTZ5LWHF.js +205 -0
  67. package/dist/record-BTZ5LWHF.js.map +1 -0
  68. package/dist/run-Cwa7vD_T.js +72 -0
  69. package/dist/run-Cwa7vD_T.js.map +1 -0
  70. package/dist/run.d.ts +273 -0
  71. package/dist/run.d.ts.map +1 -0
  72. package/dist/sequence-C_WfVGO1.js +251 -0
  73. package/dist/sequence-C_WfVGO1.js.map +1 -0
  74. package/dist/train.d.ts +276 -0
  75. package/dist/train.d.ts.map +1 -0
  76. package/dist/types.d.ts +17 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/docs/README.md +9 -0
  79. package/docs/agent-skill.md +22 -0
  80. package/docs/cli.md +54 -0
  81. package/docs/dataset-format.md +58 -0
  82. package/docs/end-to-end.md +3 -0
  83. package/docs/evaluation.md +9 -0
  84. package/docs/filter-research.md +63 -0
  85. package/docs/getting-started.md +88 -0
  86. package/docs/neural-training.md +3 -0
  87. package/docs/parser-api.md +86 -0
  88. package/docs/pipelines.md +30 -0
  89. package/docs/primitives/README.md +19 -0
  90. package/docs/project-structure.md +41 -0
  91. package/docs/react.md +16 -0
  92. package/docs/releases.md +50 -0
  93. package/docs/repository-design.md +11 -0
  94. package/docs/runtime-backends.md +18 -0
  95. package/package.json +57 -0
package/dist/run.d.ts ADDED
@@ -0,0 +1,273 @@
1
+ export declare function run(command: "train" | "eval", path: string, progress?: (epoch: number, loss: number) => void): Promise<{
2
+ evaluation: {
3
+ examples: number;
4
+ invalidOutputRate: number;
5
+ exactAccuracy: number;
6
+ accepted: number;
7
+ acceptedAccuracy: number | null;
8
+ abstentionRate: number;
9
+ correctAbstentions: number;
10
+ failures: {
11
+ input: string;
12
+ expected: unknown;
13
+ actual: unknown;
14
+ }[];
15
+ };
16
+ report?: never;
17
+ output?: never;
18
+ } | {
19
+ evaluation?: never;
20
+ report: {
21
+ formatVersion: number;
22
+ architecture: "embedding-window-mlp";
23
+ backend: string;
24
+ seed: number;
25
+ artifactSha256: string;
26
+ bytes: number;
27
+ parameters: number;
28
+ datasetSha256: {
29
+ source: string;
30
+ sha256: string;
31
+ }[];
32
+ examples: {
33
+ train: number;
34
+ validation: number;
35
+ eval: number;
36
+ };
37
+ shuffledLabelsUngated: {
38
+ examples: number;
39
+ invalidOutputRate: number;
40
+ exactAccuracy: number;
41
+ accepted: number;
42
+ acceptedAccuracy: number | null;
43
+ abstentionRate: number;
44
+ correctAbstentions: number;
45
+ failures: {
46
+ input: string;
47
+ expected: unknown;
48
+ actual: unknown;
49
+ }[];
50
+ } | null;
51
+ supervisedTokens: number;
52
+ loss: number[];
53
+ exportParity: {
54
+ examples: number;
55
+ maxConfidenceError: number;
56
+ labelDisagreements: number;
57
+ };
58
+ validation: {
59
+ examples: number;
60
+ invalidOutputRate: number;
61
+ exactAccuracy: number;
62
+ accepted: number;
63
+ acceptedAccuracy: number | null;
64
+ abstentionRate: number;
65
+ correctAbstentions: number;
66
+ failures: {
67
+ input: string;
68
+ expected: unknown;
69
+ actual: unknown;
70
+ }[];
71
+ };
72
+ untrainedUngated: {
73
+ examples: number;
74
+ invalidOutputRate: number;
75
+ exactAccuracy: number;
76
+ accepted: number;
77
+ acceptedAccuracy: number | null;
78
+ abstentionRate: number;
79
+ correctAbstentions: number;
80
+ failures: {
81
+ input: string;
82
+ expected: unknown;
83
+ actual: unknown;
84
+ }[];
85
+ };
86
+ untrained: {
87
+ examples: number;
88
+ invalidOutputRate: number;
89
+ exactAccuracy: number;
90
+ accepted: number;
91
+ acceptedAccuracy: number | null;
92
+ abstentionRate: number;
93
+ correctAbstentions: number;
94
+ failures: {
95
+ input: string;
96
+ expected: unknown;
97
+ actual: unknown;
98
+ }[];
99
+ };
100
+ float: {
101
+ examples: number;
102
+ invalidOutputRate: number;
103
+ exactAccuracy: number;
104
+ accepted: number;
105
+ acceptedAccuracy: number | null;
106
+ abstentionRate: number;
107
+ correctAbstentions: number;
108
+ failures: {
109
+ input: string;
110
+ expected: unknown;
111
+ actual: unknown;
112
+ }[];
113
+ };
114
+ quantized: {
115
+ examples: number;
116
+ invalidOutputRate: number;
117
+ exactAccuracy: number;
118
+ accepted: number;
119
+ acceptedAccuracy: number | null;
120
+ abstentionRate: number;
121
+ correctAbstentions: number;
122
+ failures: {
123
+ input: string;
124
+ expected: unknown;
125
+ actual: unknown;
126
+ }[];
127
+ };
128
+ challenges: {
129
+ examples: number;
130
+ invalidOutputRate: number;
131
+ exactAccuracy: number;
132
+ accepted: number;
133
+ acceptedAccuracy: number | null;
134
+ abstentionRate: number;
135
+ correctAbstentions: number;
136
+ failures: {
137
+ input: string;
138
+ expected: unknown;
139
+ actual: unknown;
140
+ }[];
141
+ } | null;
142
+ baseline: {
143
+ examples: number;
144
+ invalidOutputRate: number;
145
+ exactAccuracy: number;
146
+ accepted: number;
147
+ acceptedAccuracy: number | null;
148
+ abstentionRate: number;
149
+ correctAbstentions: number;
150
+ failures: {
151
+ input: string;
152
+ expected: unknown;
153
+ actual: unknown;
154
+ }[];
155
+ } | null;
156
+ trainingMs: number;
157
+ notes: string;
158
+ };
159
+ output: string;
160
+ } | {
161
+ report: {
162
+ formatVersion: number;
163
+ architecture: "bag-of-words-mlp";
164
+ backend: string;
165
+ seed: number;
166
+ artifactSha256: string;
167
+ bytes: number;
168
+ parameters: number;
169
+ datasetSha256: {
170
+ source: string;
171
+ sha256: string;
172
+ }[];
173
+ examples: {
174
+ train: number;
175
+ validation: number;
176
+ eval: number;
177
+ };
178
+ loss: number[];
179
+ exportParity: {
180
+ examples: number;
181
+ labelDisagreements: number;
182
+ maxConfidenceError: number;
183
+ };
184
+ validation: {
185
+ examples: number;
186
+ invalidOutputRate: number;
187
+ exactAccuracy: number;
188
+ accepted: number;
189
+ acceptedAccuracy: number | null;
190
+ abstentionRate: number;
191
+ correctAbstentions: number;
192
+ failures: {
193
+ input: string;
194
+ expected: unknown;
195
+ actual: unknown;
196
+ }[];
197
+ };
198
+ quantized: {
199
+ examples: number;
200
+ invalidOutputRate: number;
201
+ exactAccuracy: number;
202
+ accepted: number;
203
+ acceptedAccuracy: number | null;
204
+ abstentionRate: number;
205
+ correctAbstentions: number;
206
+ failures: {
207
+ input: string;
208
+ expected: unknown;
209
+ actual: unknown;
210
+ }[];
211
+ };
212
+ float: {
213
+ examples: number;
214
+ invalidOutputRate: number;
215
+ exactAccuracy: number;
216
+ accepted: number;
217
+ acceptedAccuracy: number | null;
218
+ abstentionRate: number;
219
+ correctAbstentions: number;
220
+ failures: {
221
+ input: string;
222
+ expected: unknown;
223
+ actual: unknown;
224
+ }[];
225
+ };
226
+ untrained: {
227
+ examples: number;
228
+ invalidOutputRate: number;
229
+ exactAccuracy: number;
230
+ accepted: number;
231
+ acceptedAccuracy: number | null;
232
+ abstentionRate: number;
233
+ correctAbstentions: number;
234
+ failures: {
235
+ input: string;
236
+ expected: unknown;
237
+ actual: unknown;
238
+ }[];
239
+ };
240
+ untrainedUngated: {
241
+ examples: number;
242
+ invalidOutputRate: number;
243
+ exactAccuracy: number;
244
+ accepted: number;
245
+ acceptedAccuracy: number | null;
246
+ abstentionRate: number;
247
+ correctAbstentions: number;
248
+ failures: {
249
+ input: string;
250
+ expected: unknown;
251
+ actual: unknown;
252
+ }[];
253
+ };
254
+ baseline: {
255
+ examples: number;
256
+ invalidOutputRate: number;
257
+ exactAccuracy: number;
258
+ accepted: number;
259
+ acceptedAccuracy: number | null;
260
+ abstentionRate: number;
261
+ correctAbstentions: number;
262
+ failures: {
263
+ input: string;
264
+ expected: unknown;
265
+ actual: unknown;
266
+ }[];
267
+ } | null;
268
+ trainingMs: number;
269
+ notes: string;
270
+ };
271
+ output: string;
272
+ }>;
273
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AACA,wBAAsB,GAAG,CACvB,OAAO,EAAE,OAAO,GAAG,MAAM,EACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWjD"}
@@ -0,0 +1,251 @@
1
+ import { n as sameOutput, t as evaluateSequence } from "./evaluate-sequence-ZCwyomzQ.js";
2
+ import { t as packageModel } from "./package-model-CPj0qnQs.js";
3
+ import { z } from "zod";
4
+ import { readSequenceArtifact, tensorPredictor, tokenize, windows } from "@matchbox-ai/core/internal";
5
+ import { readFile } from "node:fs/promises";
6
+ import { dirname, relative, resolve } from "node:path";
7
+ import { pathToFileURL } from "node:url";
8
+ import { createParser } from "@matchbox-ai/core/runtime";
9
+ import { createHash } from "node:crypto";
10
+ import * as tf from "@tensorflow/tfjs-node";
11
+ //#region src/models/sequence/create-network.ts
12
+ function createNetwork(vocabularySize, labelCount) {
13
+ return tf.sequential({ layers: [
14
+ tf.layers.embedding({
15
+ inputDim: vocabularySize + 2,
16
+ outputDim: 8,
17
+ inputLength: 3,
18
+ embeddingsInitializer: tf.initializers.randomUniform({
19
+ minval: -.1,
20
+ maxval: .1,
21
+ seed: 42
22
+ })
23
+ }),
24
+ tf.layers.flatten(),
25
+ tf.layers.dense({
26
+ units: 16,
27
+ activation: "tanh",
28
+ kernelInitializer: tf.initializers.glorotUniform({ seed: 43 })
29
+ }),
30
+ tf.layers.dense({
31
+ units: labelCount,
32
+ activation: "softmax",
33
+ kernelInitializer: tf.initializers.glorotUniform({ seed: 44 })
34
+ })
35
+ ] });
36
+ }
37
+ //#endregion
38
+ //#region src/models/sequence/fit-sequence.ts
39
+ async function fitSequence(examples, recipe, metadata, probes = [], shuffleLabels = false, progress) {
40
+ await tf.setBackend("tensorflow");
41
+ await tf.ready();
42
+ const vocabulary = [...new Set(examples.flatMap((row) => tokenize(row.input, recipe.tokenizer).map((token) => token.key)))].sort();
43
+ const radius = 1;
44
+ const inputs = [];
45
+ const labels = [];
46
+ for (const example of examples) {
47
+ const tokens = tokenize(example.input, recipe.tokenizer);
48
+ const annotations = recipe.annotate(example, tokens);
49
+ if (annotations.length !== tokens.length) throw new Error(`Annotation length mismatch: ${example.input}`);
50
+ windows(tokens, vocabulary, radius).forEach((window, position) => {
51
+ const label = annotations[position];
52
+ if (label === null) return;
53
+ const id = recipe.labels.indexOf(label);
54
+ if (id < 0) throw new Error(`Unknown annotation ${label}: ${example.input}`);
55
+ inputs.push(window);
56
+ labels.push(id);
57
+ });
58
+ }
59
+ if (recipe.labels.some((_, id) => !labels.includes(id))) throw new Error("Every label needs supervised training examples.");
60
+ if (shuffleLabels) {
61
+ let state = 173;
62
+ for (let index = labels.length - 1; index > 0; index--) {
63
+ state = Math.imul(state, 1664525) + 1013904223 >>> 0;
64
+ const other = state % (index + 1);
65
+ [labels[index], labels[other]] = [labels[other], labels[index]];
66
+ }
67
+ }
68
+ const model = createNetwork(vocabulary.length, recipe.labels.length);
69
+ const optimizer = tf.train.adam(.02);
70
+ model.compile({
71
+ optimizer,
72
+ loss: "categoricalCrossentropy"
73
+ });
74
+ const x = tf.tensor2d(inputs, [inputs.length, 3], "int32");
75
+ const y = tf.tidy(() => tf.oneHot(tf.tensor1d(labels, "int32"), recipe.labels.length));
76
+ function exportModel(precision) {
77
+ const weights = model.getWeights().map((tensor, index) => {
78
+ const values = Array.from(tensor.dataSync());
79
+ const scale = precision === "int8" ? Math.max(...values.map(Math.abs)) / 127 || 1 : 1;
80
+ return {
81
+ name: model.weights[index].originalName,
82
+ shape: tensor.shape,
83
+ scale,
84
+ values: precision === "int8" ? values.map((value) => Math.round(value / scale)) : values
85
+ };
86
+ });
87
+ return {
88
+ formatVersion: 2,
89
+ kind: "sequence-parser",
90
+ architecture: "embedding-window-mlp",
91
+ ...metadata,
92
+ modelTopology: JSON.parse(model.toJSON()),
93
+ tokenizer: recipe.tokenizer,
94
+ readout: recipe.readout,
95
+ vocabulary,
96
+ labels: [...recipe.labels],
97
+ radius,
98
+ threshold: .75,
99
+ precision,
100
+ weights
101
+ };
102
+ }
103
+ const untrained = exportModel("float32");
104
+ const history = [];
105
+ try {
106
+ await model.fit(x, y, {
107
+ epochs: 55,
108
+ batchSize: 128,
109
+ shuffle: false,
110
+ verbose: 0,
111
+ callbacks: { onEpochEnd(epoch, logs) {
112
+ history.push(Number(logs?.loss));
113
+ progress?.(epoch + 1, Number(logs?.loss));
114
+ } }
115
+ });
116
+ const float = exportModel("float32");
117
+ const quantized = exportModel("int8");
118
+ let maxConfidenceError = 0;
119
+ let labelDisagreements = 0;
120
+ const checkedInputs = [...examples.slice(0, 16).map((row) => row.input), ...probes];
121
+ const nativeProbabilities = checkedInputs.map((inputText) => tf.tidy(() => {
122
+ const tokens = tokenize(inputText, recipe.tokenizer);
123
+ const input = tf.tensor2d(windows(tokens, vocabulary, radius), [tokens.length, 3], "int32");
124
+ return model.predict(input).arraySync();
125
+ }));
126
+ const portable = await tensorPredictor(float);
127
+ try {
128
+ checkedInputs.forEach((inputText, probeIndex) => {
129
+ portable.sequence(inputText).forEach((token, index) => {
130
+ const scores = nativeProbabilities[probeIndex][index];
131
+ const maximum = Math.max(...scores);
132
+ maxConfidenceError = Math.max(maxConfidenceError, Math.abs(maximum - token.confidence));
133
+ if (recipe.labels[scores.indexOf(maximum)] !== token.label) labelDisagreements++;
134
+ });
135
+ });
136
+ } finally {
137
+ portable.dispose();
138
+ await tf.setBackend("tensorflow");
139
+ }
140
+ if (labelDisagreements || maxConfidenceError > 1e-5) throw new Error("Exported runtime disagrees with TensorFlow.js.");
141
+ return {
142
+ untrained,
143
+ float,
144
+ quantized,
145
+ history,
146
+ parity: {
147
+ examples: checkedInputs.length,
148
+ maxConfidenceError,
149
+ labelDisagreements
150
+ },
151
+ supervisedTokens: inputs.length
152
+ };
153
+ } finally {
154
+ x.dispose();
155
+ y.dispose();
156
+ model.dispose();
157
+ optimizer.dispose();
158
+ }
159
+ }
160
+ //#endregion
161
+ //#region src/models/sequence/run-sequence.ts
162
+ const hash = (value) => createHash("sha256").update(value).digest("hex");
163
+ async function runSequence(command, project, progress) {
164
+ const { task, config } = project;
165
+ const root = project.root;
166
+ const sequence = config.sequence;
167
+ if (!sequence) throw new Error("A sequence pipeline needs both recipe and decoder modules.");
168
+ const savedArtifact = command === "eval" ? readSequenceArtifact(JSON.parse(await readFile(project.output, "utf8"))) : null;
169
+ const decoderPath = savedArtifact ? resolve(dirname(project.output), savedArtifact.decoderModule) : resolve(root, sequence.decoder);
170
+ const decode = (await import(pathToFileURL(decoderPath).href)).default;
171
+ const evaluateSequence$1 = (parser, examples) => evaluateSequence(parser, examples, (value) => task.validateOutput(value).success).finally(() => {
172
+ if ("dispose" in parser && typeof parser.dispose === "function") parser.dispose();
173
+ });
174
+ const parser = (artifact) => createParser(artifact, task, decode);
175
+ if (savedArtifact) return { evaluation: await evaluateSequence$1(parser(savedArtifact), project.evaluation) };
176
+ const recipe = (await import(pathToFileURL(resolve(root, sequence.recipe)).href)).default;
177
+ const modulePath = (path) => {
178
+ const value = relative(dirname(project.output), path).replaceAll("\\", "/");
179
+ return value.startsWith(".") ? value : `./${value}`;
180
+ };
181
+ for (const example of project.train) {
182
+ const tokens = tokenize(example.input, recipe.tokenizer);
183
+ const labels = recipe.annotate(example, tokens);
184
+ const value = decode(tokens.map((token, index) => ({
185
+ ...token,
186
+ label: labels[index] ?? "O",
187
+ confidence: 1
188
+ })), example.input);
189
+ if (!sameOutput(value, example.output)) throw new Error(`Training annotations do not decode to the supplied output: ${example.input}`);
190
+ }
191
+ const started = performance.now();
192
+ const fit = await fitSequence(project.train, recipe, {
193
+ taskMetadata: task.toJSON(),
194
+ taskModule: modulePath(project.taskPath),
195
+ decoderModule: modulePath(resolve(root, sequence.decoder))
196
+ }, project.validation.map((row) => row.input), false, progress);
197
+ const validation = await evaluateSequence$1(parser(fit.quantized), project.validation);
198
+ const bytes = Buffer.byteLength(JSON.stringify(fit.quantized));
199
+ if (validation.exactAccuracy < config.minAccuracy || bytes > config.maxBytes) throw new Error(`Sequence model failed validation/size requirements (${validation.exactAccuracy}, ${bytes} bytes). ${JSON.stringify(validation.failures.slice(0, 10))}`);
200
+ const shuffledControl = recipe.readout === "last" ? await fitSequence(project.train, recipe, fit.quantized, [], true) : null;
201
+ const challenges = config.challenges ? z.array(z.strictObject({
202
+ input: z.string(),
203
+ output: z.null()
204
+ })).min(1).parse(JSON.parse(await readFile(resolve(root, config.challenges), "utf8"))) : null;
205
+ const report = {
206
+ formatVersion: 1,
207
+ architecture: fit.quantized.architecture,
208
+ backend: "TensorFlow native CPU",
209
+ seed: 42,
210
+ artifactSha256: hash(JSON.stringify(fit.quantized)),
211
+ bytes,
212
+ parameters: fit.quantized.weights.reduce((sum, weight) => sum + weight.values.length, 0),
213
+ datasetSha256: project.sources.map((source) => ({
214
+ source: source.source,
215
+ sha256: hash(source.text)
216
+ })),
217
+ examples: {
218
+ train: project.train.length,
219
+ validation: project.validation.length,
220
+ eval: project.evaluation.length
221
+ },
222
+ shuffledLabelsUngated: shuffledControl ? await evaluateSequence$1(parser({
223
+ ...shuffledControl.quantized,
224
+ threshold: 0
225
+ }), project.evaluation) : null,
226
+ supervisedTokens: fit.supervisedTokens,
227
+ loss: fit.history,
228
+ exportParity: fit.parity,
229
+ validation,
230
+ untrainedUngated: await evaluateSequence$1(parser({
231
+ ...fit.untrained,
232
+ threshold: 0
233
+ }), project.evaluation),
234
+ untrained: await evaluateSequence$1(parser(fit.untrained), project.evaluation),
235
+ float: await evaluateSequence$1(parser(fit.float), project.evaluation),
236
+ quantized: await evaluateSequence$1(parser(fit.quantized), project.evaluation),
237
+ challenges: challenges ? await evaluateSequence$1(parser(fit.quantized), challenges) : null,
238
+ baseline: project.baseline ? await evaluateSequence$1(project.baseline, project.evaluation) : null,
239
+ trainingMs: performance.now() - started,
240
+ notes: "Validation gates export. Eval labels do not influence selection. Scores are uncalibrated. Unknown tokens abstain. JSON int8 arrays are portable but not a packed binary format."
241
+ };
242
+ await packageModel(project.output, fit.quantized, report);
243
+ return {
244
+ report,
245
+ output: project.output
246
+ };
247
+ }
248
+ //#endregion
249
+ export { runSequence };
250
+
251
+ //# sourceMappingURL=sequence-C_WfVGO1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence-C_WfVGO1.js","names":["evaluateSequence","evaluate"],"sources":["../src/models/sequence/create-network.ts","../src/models/sequence/fit-sequence.ts","../src/models/sequence/run-sequence.ts"],"sourcesContent":["import * as tf from \"@tensorflow/tfjs-node\";\nexport function createNetwork(vocabularySize: number, labelCount: number) {\n return tf.sequential({\n layers: [\n tf.layers.embedding({\n inputDim: vocabularySize + 2,\n outputDim: 8,\n inputLength: 3,\n embeddingsInitializer: tf.initializers.randomUniform({\n minval: -0.1,\n maxval: 0.1,\n seed: 42,\n }),\n }),\n tf.layers.flatten(),\n tf.layers.dense({\n units: 16,\n activation: \"tanh\",\n kernelInitializer: tf.initializers.glorotUniform({ seed: 43 }),\n }),\n tf.layers.dense({\n units: labelCount,\n activation: \"softmax\",\n kernelInitializer: tf.initializers.glorotUniform({ seed: 44 }),\n }),\n ],\n });\n}\n","import { createNetwork } from \"./create-network.js\";\nimport * as tf from \"@tensorflow/tfjs-node\";\nimport { tensorPredictor, tokenize, windows } from \"@matchbox-ai/core/internal\";\nimport type { SequenceArtifact } from \"@matchbox-ai/core/internal\";\nimport type { DatasetExample } from \"@matchbox-ai/core\";\nimport type { SequenceRecipe } from \"./types.js\";\nexport async function fitSequence(\n examples: readonly DatasetExample<unknown>[],\n recipe: SequenceRecipe,\n metadata: Pick<SequenceArtifact, \"taskModule\" | \"taskMetadata\" | \"decoderModule\">,\n probes: readonly string[] = [],\n shuffleLabels = false,\n progress?: (epoch: number, loss: number) => void,\n) {\n await tf.setBackend(\"tensorflow\");\n await tf.ready();\n const vocabulary = [\n ...new Set(\n examples.flatMap((row) => tokenize(row.input, recipe.tokenizer).map((token) => token.key)),\n ),\n ].sort();\n const radius = 1;\n const inputs: number[][] = [];\n const labels: number[] = [];\n for (const example of examples) {\n const tokens = tokenize(example.input, recipe.tokenizer);\n const annotations = recipe.annotate(example, tokens);\n if (annotations.length !== tokens.length)\n throw new Error(`Annotation length mismatch: ${example.input}`);\n windows(tokens, vocabulary, radius).forEach((window, position) => {\n const label = annotations[position];\n if (label === null) return;\n const id = recipe.labels.indexOf(label!);\n if (id < 0) throw new Error(`Unknown annotation ${label}: ${example.input}`);\n inputs.push(window);\n labels.push(id);\n });\n }\n if (recipe.labels.some((_, id) => !labels.includes(id)))\n throw new Error(\"Every label needs supervised training examples.\");\n if (shuffleLabels) {\n let state = 173;\n for (let index = labels.length - 1; index > 0; index--) {\n state = (Math.imul(state, 1664525) + 1013904223) >>> 0;\n const other = state % (index + 1);\n [labels[index], labels[other]] = [labels[other]!, labels[index]!];\n }\n }\n const model = createNetwork(vocabulary.length, recipe.labels.length);\n const optimizer = tf.train.adam(0.02);\n model.compile({ optimizer, loss: \"categoricalCrossentropy\" });\n const x = tf.tensor2d(inputs, [inputs.length, 3], \"int32\");\n const y = tf.tidy(() => tf.oneHot(tf.tensor1d(labels, \"int32\"), recipe.labels.length));\n function exportModel(precision: \"float32\" | \"int8\"): SequenceArtifact {\n const weights = model.getWeights().map((tensor, index) => {\n const values = Array.from(tensor.dataSync());\n const scale = precision === \"int8\" ? Math.max(...values.map(Math.abs)) / 127 || 1 : 1;\n return {\n name: model.weights[index]!.originalName,\n shape: tensor.shape,\n scale,\n values: precision === \"int8\" ? values.map((value) => Math.round(value / scale)) : values,\n };\n }) as SequenceArtifact[\"weights\"];\n return {\n formatVersion: 2,\n kind: \"sequence-parser\",\n architecture: \"embedding-window-mlp\",\n ...metadata,\n modelTopology: JSON.parse(model.toJSON() as string),\n tokenizer: recipe.tokenizer,\n readout: recipe.readout,\n vocabulary,\n labels: [...recipe.labels],\n radius,\n threshold: 0.75,\n precision,\n weights,\n };\n }\n const untrained = exportModel(\"float32\");\n const history: number[] = [];\n try {\n await model.fit(x, y, {\n epochs: 55,\n batchSize: 128,\n shuffle: false,\n verbose: 0,\n callbacks: {\n onEpochEnd(epoch, logs) {\n history.push(Number(logs?.loss));\n progress?.(epoch + 1, Number(logs?.loss));\n },\n },\n });\n const float = exportModel(\"float32\");\n const quantized = exportModel(\"int8\");\n let maxConfidenceError = 0;\n let labelDisagreements = 0;\n const checkedInputs = [...examples.slice(0, 16).map((row) => row.input), ...probes];\n const nativeProbabilities = checkedInputs.map((inputText) =>\n tf.tidy(() => {\n const tokens = tokenize(inputText, recipe.tokenizer);\n const input = tf.tensor2d(windows(tokens, vocabulary, radius), [tokens.length, 3], \"int32\");\n return (model.predict(input) as tf.Tensor).arraySync() as number[][];\n }),\n );\n const portable = await tensorPredictor(float);\n try {\n checkedInputs.forEach((inputText, probeIndex) => {\n portable.sequence(inputText).forEach((token, index) => {\n const scores = nativeProbabilities[probeIndex]![index]!;\n const maximum = Math.max(...scores);\n maxConfidenceError = Math.max(maxConfidenceError, Math.abs(maximum - token.confidence));\n if (recipe.labels[scores.indexOf(maximum)] !== token.label) labelDisagreements++;\n });\n });\n } finally {\n portable.dispose();\n await tf.setBackend(\"tensorflow\");\n }\n if (labelDisagreements || maxConfidenceError > 1e-5)\n throw new Error(\"Exported runtime disagrees with TensorFlow.js.\");\n return {\n untrained,\n float,\n quantized,\n history,\n parity: { examples: checkedInputs.length, maxConfidenceError, labelDisagreements },\n supervisedTokens: inputs.length,\n };\n } finally {\n x.dispose();\n y.dispose();\n model.dispose();\n optimizer.dispose();\n }\n}\n","import { sameOutput } from \"../../evaluation/same-output.js\";\nimport { z } from \"zod\";\nimport { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createParser } from \"@matchbox-ai/core/runtime\";\nimport { readSequenceArtifact, tokenize } from \"@matchbox-ai/core/internal\";\nimport type { DatasetExample } from \"@matchbox-ai/core\";\nimport type { MatchboxParser, SequenceDecoder } from \"@matchbox-ai/core/runtime\";\nimport type { loadProject } from \"../../load-project.js\";\nimport { packageModel } from \"../../packaging/package-model.js\";\nimport { fitSequence } from \"./fit-sequence.js\";\nimport { evaluateSequence as evaluate } from \"../../evaluation/evaluate-sequence.js\";\nimport type { SequenceRecipe } from \"./types.js\";\nconst hash = (value: string) => createHash(\"sha256\").update(value).digest(\"hex\");\nexport async function runSequence(\n command: \"train\" | \"eval\",\n project: Awaited<ReturnType<typeof loadProject>>,\n progress?: (epoch: number, loss: number) => void,\n) {\n const { task, config } = project;\n const root = project.root;\n const sequence = config.sequence;\n if (!sequence) throw new Error(\"A sequence pipeline needs both recipe and decoder modules.\");\n const savedArtifact =\n command === \"eval\"\n ? readSequenceArtifact(JSON.parse(await readFile(project.output, \"utf8\")))\n : null;\n const decoderPath = savedArtifact\n ? resolve(dirname(project.output), savedArtifact.decoderModule)\n : resolve(root, sequence.decoder);\n const decode: SequenceDecoder = (await import(pathToFileURL(decoderPath).href)).default;\n const evaluateSequence = (\n parser: MatchboxParser<unknown>,\n examples: readonly DatasetExample<unknown>[],\n ) =>\n evaluate(parser, examples, (value) => task.validateOutput(value).success).finally(() => {\n if (\"dispose\" in parser && typeof parser.dispose === \"function\") parser.dispose();\n });\n const parser = (artifact: unknown) => createParser(artifact, task, decode);\n if (savedArtifact) {\n return { evaluation: await evaluateSequence(parser(savedArtifact), project.evaluation) };\n }\n const recipe: SequenceRecipe = (await import(pathToFileURL(resolve(root, sequence.recipe)).href))\n .default;\n const modulePath = (path: string) => {\n const value = relative(dirname(project.output), path).replaceAll(\"\\\\\", \"/\");\n return value.startsWith(\".\") ? value : `./${value}`;\n };\n for (const example of project.train) {\n const tokens = tokenize(example.input, recipe.tokenizer);\n const labels = recipe.annotate(example, tokens);\n const value = decode(\n tokens.map((token, index) => ({ ...token, label: labels[index] ?? \"O\", confidence: 1 })),\n example.input,\n );\n if (!sameOutput(value, example.output))\n throw new Error(\n `Training annotations do not decode to the supplied output: ${example.input}`,\n );\n }\n const started = performance.now();\n const fit = await fitSequence(\n project.train,\n recipe,\n {\n taskMetadata: task.toJSON(),\n taskModule: modulePath(project.taskPath),\n decoderModule: modulePath(resolve(root, sequence.decoder)),\n },\n project.validation.map((row) => row.input),\n false,\n progress,\n );\n const validation = await evaluateSequence(parser(fit.quantized), project.validation);\n const bytes = Buffer.byteLength(JSON.stringify(fit.quantized));\n if (validation.exactAccuracy < config.minAccuracy || bytes > config.maxBytes)\n throw new Error(\n `Sequence model failed validation/size requirements (${validation.exactAccuracy}, ${bytes} bytes). ${JSON.stringify(validation.failures.slice(0, 10))}`,\n );\n const shuffledControl =\n recipe.readout === \"last\"\n ? await fitSequence(project.train, recipe, fit.quantized, [], true)\n : null;\n const challenges = config.challenges\n ? z\n .array(z.strictObject({ input: z.string(), output: z.null() }))\n .min(1)\n .parse(JSON.parse(await readFile(resolve(root, config.challenges), \"utf8\")))\n : null;\n const report = {\n formatVersion: 1,\n architecture: fit.quantized.architecture,\n backend: \"TensorFlow native CPU\",\n seed: 42,\n artifactSha256: hash(JSON.stringify(fit.quantized)),\n bytes,\n parameters: fit.quantized.weights.reduce((sum, weight) => sum + weight.values.length, 0),\n datasetSha256: project.sources.map((source) => ({\n source: source.source,\n sha256: hash(source.text),\n })),\n examples: {\n train: project.train.length,\n validation: project.validation.length,\n eval: project.evaluation.length,\n },\n shuffledLabelsUngated: shuffledControl\n ? await evaluateSequence(\n parser({ ...shuffledControl.quantized, threshold: 0 }),\n project.evaluation,\n )\n : null,\n supervisedTokens: fit.supervisedTokens,\n loss: fit.history,\n exportParity: fit.parity,\n validation,\n untrainedUngated: await evaluateSequence(\n parser({ ...fit.untrained, threshold: 0 }),\n project.evaluation,\n ),\n untrained: await evaluateSequence(parser(fit.untrained), project.evaluation),\n float: await evaluateSequence(parser(fit.float), project.evaluation),\n quantized: await evaluateSequence(parser(fit.quantized), project.evaluation),\n challenges: challenges ? await evaluateSequence(parser(fit.quantized), challenges) : null,\n baseline: project.baseline\n ? await evaluateSequence(project.baseline, project.evaluation)\n : null,\n trainingMs: performance.now() - started,\n notes:\n \"Validation gates export. Eval labels do not influence selection. Scores are uncalibrated. Unknown tokens abstain. JSON int8 arrays are portable but not a packed binary format.\",\n };\n await packageModel(project.output, fit.quantized, report);\n return { report, output: project.output };\n}\n"],"mappings":"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"}