@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
@@ -0,0 +1,276 @@
1
+ /** Runs the same validation, selection, and packaging pipeline as the CLI. */
2
+ export declare function train(target: string, options?: {
3
+ onProgress?: (epoch: number, loss: number) => void;
4
+ }): Promise<{
5
+ evaluation: {
6
+ examples: number;
7
+ invalidOutputRate: number;
8
+ exactAccuracy: number;
9
+ accepted: number;
10
+ acceptedAccuracy: number | null;
11
+ abstentionRate: number;
12
+ correctAbstentions: number;
13
+ failures: {
14
+ input: string;
15
+ expected: unknown;
16
+ actual: unknown;
17
+ }[];
18
+ };
19
+ report?: never;
20
+ output?: never;
21
+ } | {
22
+ evaluation?: never;
23
+ report: {
24
+ formatVersion: number;
25
+ architecture: "embedding-window-mlp";
26
+ backend: string;
27
+ seed: number;
28
+ artifactSha256: string;
29
+ bytes: number;
30
+ parameters: number;
31
+ datasetSha256: {
32
+ source: string;
33
+ sha256: string;
34
+ }[];
35
+ examples: {
36
+ train: number;
37
+ validation: number;
38
+ eval: number;
39
+ };
40
+ shuffledLabelsUngated: {
41
+ examples: number;
42
+ invalidOutputRate: number;
43
+ exactAccuracy: number;
44
+ accepted: number;
45
+ acceptedAccuracy: number | null;
46
+ abstentionRate: number;
47
+ correctAbstentions: number;
48
+ failures: {
49
+ input: string;
50
+ expected: unknown;
51
+ actual: unknown;
52
+ }[];
53
+ } | null;
54
+ supervisedTokens: number;
55
+ loss: number[];
56
+ exportParity: {
57
+ examples: number;
58
+ maxConfidenceError: number;
59
+ labelDisagreements: number;
60
+ };
61
+ validation: {
62
+ examples: number;
63
+ invalidOutputRate: number;
64
+ exactAccuracy: number;
65
+ accepted: number;
66
+ acceptedAccuracy: number | null;
67
+ abstentionRate: number;
68
+ correctAbstentions: number;
69
+ failures: {
70
+ input: string;
71
+ expected: unknown;
72
+ actual: unknown;
73
+ }[];
74
+ };
75
+ untrainedUngated: {
76
+ examples: number;
77
+ invalidOutputRate: number;
78
+ exactAccuracy: number;
79
+ accepted: number;
80
+ acceptedAccuracy: number | null;
81
+ abstentionRate: number;
82
+ correctAbstentions: number;
83
+ failures: {
84
+ input: string;
85
+ expected: unknown;
86
+ actual: unknown;
87
+ }[];
88
+ };
89
+ untrained: {
90
+ examples: number;
91
+ invalidOutputRate: number;
92
+ exactAccuracy: number;
93
+ accepted: number;
94
+ acceptedAccuracy: number | null;
95
+ abstentionRate: number;
96
+ correctAbstentions: number;
97
+ failures: {
98
+ input: string;
99
+ expected: unknown;
100
+ actual: unknown;
101
+ }[];
102
+ };
103
+ float: {
104
+ examples: number;
105
+ invalidOutputRate: number;
106
+ exactAccuracy: number;
107
+ accepted: number;
108
+ acceptedAccuracy: number | null;
109
+ abstentionRate: number;
110
+ correctAbstentions: number;
111
+ failures: {
112
+ input: string;
113
+ expected: unknown;
114
+ actual: unknown;
115
+ }[];
116
+ };
117
+ quantized: {
118
+ examples: number;
119
+ invalidOutputRate: number;
120
+ exactAccuracy: number;
121
+ accepted: number;
122
+ acceptedAccuracy: number | null;
123
+ abstentionRate: number;
124
+ correctAbstentions: number;
125
+ failures: {
126
+ input: string;
127
+ expected: unknown;
128
+ actual: unknown;
129
+ }[];
130
+ };
131
+ challenges: {
132
+ examples: number;
133
+ invalidOutputRate: number;
134
+ exactAccuracy: number;
135
+ accepted: number;
136
+ acceptedAccuracy: number | null;
137
+ abstentionRate: number;
138
+ correctAbstentions: number;
139
+ failures: {
140
+ input: string;
141
+ expected: unknown;
142
+ actual: unknown;
143
+ }[];
144
+ } | null;
145
+ baseline: {
146
+ examples: number;
147
+ invalidOutputRate: number;
148
+ exactAccuracy: number;
149
+ accepted: number;
150
+ acceptedAccuracy: number | null;
151
+ abstentionRate: number;
152
+ correctAbstentions: number;
153
+ failures: {
154
+ input: string;
155
+ expected: unknown;
156
+ actual: unknown;
157
+ }[];
158
+ } | null;
159
+ trainingMs: number;
160
+ notes: string;
161
+ };
162
+ output: string;
163
+ } | {
164
+ report: {
165
+ formatVersion: number;
166
+ architecture: "bag-of-words-mlp";
167
+ backend: string;
168
+ seed: number;
169
+ artifactSha256: string;
170
+ bytes: number;
171
+ parameters: number;
172
+ datasetSha256: {
173
+ source: string;
174
+ sha256: string;
175
+ }[];
176
+ examples: {
177
+ train: number;
178
+ validation: number;
179
+ eval: number;
180
+ };
181
+ loss: number[];
182
+ exportParity: {
183
+ examples: number;
184
+ labelDisagreements: number;
185
+ maxConfidenceError: number;
186
+ };
187
+ validation: {
188
+ examples: number;
189
+ invalidOutputRate: number;
190
+ exactAccuracy: number;
191
+ accepted: number;
192
+ acceptedAccuracy: number | null;
193
+ abstentionRate: number;
194
+ correctAbstentions: number;
195
+ failures: {
196
+ input: string;
197
+ expected: unknown;
198
+ actual: unknown;
199
+ }[];
200
+ };
201
+ quantized: {
202
+ examples: number;
203
+ invalidOutputRate: number;
204
+ exactAccuracy: number;
205
+ accepted: number;
206
+ acceptedAccuracy: number | null;
207
+ abstentionRate: number;
208
+ correctAbstentions: number;
209
+ failures: {
210
+ input: string;
211
+ expected: unknown;
212
+ actual: unknown;
213
+ }[];
214
+ };
215
+ float: {
216
+ examples: number;
217
+ invalidOutputRate: number;
218
+ exactAccuracy: number;
219
+ accepted: number;
220
+ acceptedAccuracy: number | null;
221
+ abstentionRate: number;
222
+ correctAbstentions: number;
223
+ failures: {
224
+ input: string;
225
+ expected: unknown;
226
+ actual: unknown;
227
+ }[];
228
+ };
229
+ untrained: {
230
+ examples: number;
231
+ invalidOutputRate: number;
232
+ exactAccuracy: number;
233
+ accepted: number;
234
+ acceptedAccuracy: number | null;
235
+ abstentionRate: number;
236
+ correctAbstentions: number;
237
+ failures: {
238
+ input: string;
239
+ expected: unknown;
240
+ actual: unknown;
241
+ }[];
242
+ };
243
+ untrainedUngated: {
244
+ examples: number;
245
+ invalidOutputRate: number;
246
+ exactAccuracy: number;
247
+ accepted: number;
248
+ acceptedAccuracy: number | null;
249
+ abstentionRate: number;
250
+ correctAbstentions: number;
251
+ failures: {
252
+ input: string;
253
+ expected: unknown;
254
+ actual: unknown;
255
+ }[];
256
+ };
257
+ baseline: {
258
+ examples: number;
259
+ invalidOutputRate: number;
260
+ exactAccuracy: number;
261
+ accepted: number;
262
+ acceptedAccuracy: number | null;
263
+ abstentionRate: number;
264
+ correctAbstentions: number;
265
+ failures: {
266
+ input: string;
267
+ expected: unknown;
268
+ actual: unknown;
269
+ }[];
270
+ } | null;
271
+ trainingMs: number;
272
+ notes: string;
273
+ };
274
+ output: string;
275
+ }>;
276
+ //# sourceMappingURL=train.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"train.d.ts","sourceRoot":"","sources":["../src/train.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAKrE"}
@@ -0,0 +1,17 @@
1
+ export interface TrainingConfig {
2
+ formatVersion?: 1;
3
+ challenges?: string;
4
+ sequence?: {
5
+ recipe: string;
6
+ decoder: string;
7
+ };
8
+ baseline?: string;
9
+ task?: string;
10
+ train?: string;
11
+ validation?: string;
12
+ eval?: string;
13
+ output?: string;
14
+ minAccuracy?: number;
15
+ maxBytes?: number;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
package/docs/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Matchbox documentation
2
+
3
+ Start with [getting started](getting-started.md), then read [project structure](project-structure.md), [pipelines](pipelines.md), and [evaluation](evaluation.md).
4
+
5
+ The [primitive reference](primitives/README.md) describes supported authoring choices. [React](react.md), [browser runtime](runtime-backends.md), and [CLI](cli.md) cover application integration and local development. [Repository design](repository-design.md) is for contributors.
6
+
7
+ These docs ship in all three packages under node_modules/@matchbox-ai/{core,train}/docs and node_modules/matchbox-ai/docs. Use the installed version when assisting an application author. The bundled agent-skill.md provides the corresponding coding-agent workflow.
8
+
9
+ See [Releases](releases.md) for Changesets, package versions, and npm publishing.
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: matchbox
3
+ description: Author, train, evaluate, and integrate tiny browser-local Matchbox parsers using explicit TypeScript primitives.
4
+ ---
5
+
6
+ # Matchbox
7
+
8
+ Read the installed package docs/README.md first, then project-structure.md, pipelines.md, evaluation.md, and primitives/README.md. In the framework repository, use root docs/. Match examples to the installed version.
9
+
10
+ 1. Inspect parser.ts, pipeline.ts, data/train.jsonl, and independent evals before changing behavior.
11
+ 2. Keep the output schema focused on valid application values. Make representation and supervision choices explicit in pipeline.ts or imported helpers.
12
+ 3. Use fieldClassifier for finite output domains and tokenClassifier for explicitly supervised token recognition. Explain their limits; do not promise unseen numeric outputs from a finite classifier.
13
+ 4. Keep domain dictionaries and normalizers application-owned and visible. Never insert one silently to make an evaluation pass.
14
+ 5. Fit preprocessing only on training data. Put data generators in project-level scripts/ and preserve validation/test fixtures. Add meaningful held-out compositions and negative cases independently of model fitting.
15
+ 6. Use the CLI from matchbox-ai or programmatic train from @matchbox-ai/train to apply validation gates, measure results, and package weights. Report failures honestly. Never fabricate benchmark figures.
16
+ 7. Distinguish uncertain interpretation from invalid user input. Confidence is currently uncalibrated; inspect diagnostics before attributing uncertainty to one cause.
17
+ 8. Import generated artifacts in the app and use @matchbox-ai/core/react when needed. Keep @matchbox-ai/train and native TensorFlow outside browser code.
18
+ 9. Let TensorFlow serialize, load, and execute models. Do not implement custom inference kernels or a backend-selection framework. Verify native-to-browser export parity and benchmark the shipped TensorFlow runtime. Label emulated mobile measurements accurately.
19
+
20
+ Scope changes to existing, documented primitives. Propose a new primitive separately with its contract, limitations, and evaluation evidence. Preserve authored code and tests when reorganizing folders.
21
+
22
+ Matchbox owns authoring, workflows, evals, packaging, validation, and typed results. TensorFlow owns model execution. A schema must never silently select numeric encodings or domain normalizers.
package/docs/cli.md ADDED
@@ -0,0 +1,54 @@
1
+ # CLI
2
+
3
+ Run Matchbox inside an existing React, Next.js, or other JavaScript application. Your application keeps its own dev server and framework configuration. The command is provided by the matchbox-ai development dependency. Pipeline authoring and training APIs remain in @matchbox-ai/train. The CLI uses Commander for commands and Ink for interactive setup and status.
4
+
5
+ ## Add a task
6
+
7
+ ```sh
8
+ matchbox-ai init
9
+ matchbox-ai init money --template money
10
+ matchbox-ai init intent --template blank
11
+ ```
12
+
13
+ Interactive setup offers the money example or a blank task. In scripts, specify `--template`. `--directory <path>` selects an existing application directory containing package.json. Matchbox preserves existing scripts, adds `matchbox:dev`, `matchbox:train`, and `matchbox:eval` if absent, and ignores `.matchbox/`. It refuses to replace an existing task directory. It installs dependencies automatically using the app’s package-manager declaration or lockfile, including workspace ancestors. With neither, it uses the invoking package manager, then Bun as a fallback. Use `--skip-install` to handle installation yourself. Installer logs go to stderr so `--json` stays machine-readable. If installation fails, the scaffold remains and the CLI prints the command to retry.
14
+
15
+ Package-manager build-script policies still apply. With pnpm, run `pnpm approve-builds` and select `@tensorflow/tfjs-node` before training.
16
+
17
+ The money template has an explicit token model, supervision, and decoder. The blank template has an editable label schema, an explicit word-feature classifier, and empty datasets. Write examples and independent evals before training it. Names do not select learning strategies.
18
+
19
+ ## Open the workbench
20
+
21
+ ```sh
22
+ matchbox-ai dev money
23
+ matchbox-ai dev money --port 4191 --no-open
24
+ ```
25
+
26
+ The browser workbench runs on loopback, alongside your app. Try inputs, inspect recognition, save explicit corrections, train, evaluate, and measure browser inference. Source changes mark the model as stale. Training remains an explicit action. A successful training run reloads the model.
27
+
28
+ Predictions and timing run through TensorFlow.js CPU in the browser. Training and evaluation run in local child processes with fresh task modules. The speed measurement repeats the current input 100 times after 20 warmups; it excludes model loading and does not measure accuracy.
29
+
30
+ Saving validates output and rejects held-out inputs. It only changes training data. Token pipelines also need matching supervision from their authored recipe; the save result points to that file. Matchbox does not infer labels or normalization rules from a correction.
31
+
32
+ ## Train and evaluate
33
+
34
+ ```sh
35
+ matchbox-ai train money
36
+ matchbox-ai train money --verbose
37
+ matchbox-ai eval money
38
+ matchbox-ai eval money --json
39
+ ```
40
+
41
+ Training validates datasets, fits the model, checks validation requirements, and exports a model plus a report. Failing validation stops export. The separate test set measures the selected model without influencing training. `eval` exits with status 1 if exact accuracy is below the configured threshold and includes expected/actual failures. `--verbose` reveals epoch loss. JSON output stays on stdout; diagnostics go to stderr.
42
+
43
+ ## Inspect and script
44
+
45
+ ```sh
46
+ matchbox-ai parse money "fifteen euros" --json
47
+ matchbox-ai inspect money "eleven grand" --json
48
+ matchbox-ai info money
49
+ matchbox-ai save money "twenty euros please" '{"amount":20,"currency":"EUR","approximate":false}'
50
+ ```
51
+
52
+ A task argument can be a name, task directory, or config file. Omit the name when discovery finds exactly one task. Interactive `dev` offers a picker for multiple tasks; scripts require a name. `--config` selects an explicit path and cannot be combined with a task argument. Each command has its own `--help`.
53
+
54
+ Bare `matchbox-ai` shows available tasks and next actions. It does not create files. Use the one-shot commands for machine-readable results.
@@ -0,0 +1,58 @@
1
+ # Dataset format
2
+
3
+ Matchbox dataset format version 1 uses separate local `train.jsonl` and `evals.jsonl` files. Each nonblank line is one JSON object with exactly two properties: `input` and `output`.
4
+
5
+ ```jsonl
6
+ {"input":"Swedish customers","output":{"country":"SE"}}
7
+ {"input":"German customers","output":{"country":"DE"}}
8
+ ```
9
+
10
+ `input` must satisfy the task's string schema. `output` must satisfy its structured output schema. There are no row headers, split labels, IDs, or metadata properties in version 1. Application-specific fields belong inside `output` and must be declared by the task.
11
+
12
+ ## Authoring rules
13
+
14
+ Write UTF-8 text without a byte-order mark, with LF or CRLF line endings. Empty and whitespace-only lines are ignored. Diagnostics still count those physical lines. Each split must contain at least one example. A final newline is optional.
15
+
16
+ Use `JSON.stringify({ input, output })` to generate each row. Newlines within an input string must be JSON escapes, rather than physical line breaks. Pretty-printed multiline objects and comments are rejected. Input whitespace, row order, and duplicate examples are preserved. Use unique object property names; parsing uses standard `JSON.parse` semantics, which retain the last occurrence of duplicate keys.
17
+
18
+ ## Validation API
19
+
20
+ ```ts
21
+ import { defineParser, parseDatasets } from "@matchbox-ai/core";
22
+ import { z } from "zod";
23
+
24
+ const task = defineParser({
25
+ input: z.string().min(1),
26
+ output: z.strictObject({ country: z.enum(["SE", "DE"]) }),
27
+ });
28
+
29
+ // File loading is the caller's responsibility. This example runs in Bun.
30
+ const result = parseDatasets(task, {
31
+ formatVersion: 1,
32
+ train: { source: "train.jsonl", text: await Bun.file("train.jsonl").text() },
33
+ eval: { source: "evals.jsonl", text: await Bun.file("evals.jsonl").text() },
34
+ });
35
+
36
+ if (result.success) {
37
+ const trainingExamples = result.data.train;
38
+ const heldOutExamples = result.data.eval;
39
+ // Both collections infer output.country as "SE" | "DE".
40
+ console.log(trainingExamples.length, heldOutExamples.length);
41
+ } else {
42
+ for (const issue of result.issues) {
43
+ console.error(issue.source, issue.line, issue.path, issue.message);
44
+ }
45
+ }
46
+ ```
47
+
48
+ The function accepts text and performs no filesystem access, network requests, or model inference. `source` is a diagnostic label, normally the filename. Validation collects issues from both splits and returns no partial dataset on failure. Each issue includes its split, source, one-based physical line number, code, schema path, and message. Empty sources report line 1. Schema paths begin with `input` or `output`; syntax and envelope errors use an empty path.
49
+
50
+ ## Train and eval separation
51
+
52
+ Both splits are explicit and required. Matchbox does not shuffle, merge, deduplicate, or automatically split them. Keep held-out examples separate from training and synthetic expansion. Authors are responsible for preventing overlap and paraphrase leakage; validation establishes structural correctness, not evaluation independence. Automatic holdout selection and leakage diagnostics can be designed with the training ticket.
53
+
54
+ ## Versioning
55
+
56
+ The required `formatVersion: 1` in the dataset configuration describes both sources. Keep that configuration under version control alongside the JSONL files and task definition. Raw JSONL files are not self-describing; preserve their configuration when sharing them. No implicit version is assumed. Missing or unsupported versions throw a `RangeError` before rows are read. Invalid rows return validation issues instead.
57
+
58
+ Breaking changes to row structure or interpretation require a new format version and explicit migration. Do not silently reinterpret existing files. Dataset format versions are independent of package versions and the task metadata's format version. Business-schema changes require revalidation of both datasets against the updated task. Artifact hashes and provenance belong to the build metadata ticket.
@@ -0,0 +1,3 @@
1
+ # End-to-end workflow
2
+
3
+ See [getting started](getting-started.md), [explicit pipelines](pipelines.md), [evaluation](evaluation.md), and [runtime backends](runtime-backends.md). The filters task now lives in examples/filters/matchbox/filters; its browser UI lives in apps/playground.
@@ -0,0 +1,9 @@
1
+ # Evaluation
2
+
3
+ Training fits vocabulary, field domains, and weights using data/train.jsonl only. Validation in evals/validation.jsonl gates artifact export. Independent evals/test.jsonl measures the selected model. Input overlap across these splits is rejected.
4
+
5
+ Run matchbox-ai eval money to evaluate saved artifacts without retraining or requiring the training data. A failing accuracy threshold produces a nonzero exit code. Optional evals/baseline.ts exports a parser with the same parse contract. Optional evals/challenges.json contains abstention cases with input and output: null. Other research formats must have distinct filenames and explicit runners.
6
+
7
+ Reports include accuracy, abstention, invalid-output rate, artifact bytes, loss, export parity, dataset hashes, and control-model results where supported. Confidence is uncalibrated. Zero confidence for unfamiliar vocabulary means the current model declines to answer; it does not prove the input is invalid or diagnose the only cause.
8
+
9
+ When evaluating new numeric representations, withhold complete output values and meaningful input compositions. Never teach test answers through a dictionary or rewrite evals to make training pass. Schema validity establishes output shape, not semantic correctness.
@@ -0,0 +1,63 @@
1
+ # Historical filter proof findings
2
+
3
+ This document records BOO-46 before the TensorFlow migration. BOO-47 removes these handwritten trainers and routes filters through the shared neural training path. Current results and limitations are in the [neural training guide](neural-training.md).
4
+
5
+ The first full toolchain works: examples train a small local model, validation selects a candidate, packaging generates a typed file import, and React uses it to filter a table. This experiment does not yet establish a compelling advantage over a reasonable deterministic parser.
6
+
7
+ ## Reproduction and data
8
+
9
+ Run `bun run train`, `bun run eval`, `bun run research`, and `bun run test:browser`. The artifact report is generated beside `examples/filters/.matchbox/filters/model.matchbox`; challenge results are in `challenges.report.json`. Browser results are written under `test-results/` and uploaded by CI.
10
+
11
+ The fixed corpus contains 176 single-clause training examples, 32 validation examples, and 32 evaluation examples across 13 output classes. These cover three statuses, churn exclusion, four countries, five numeric operators, and explicit AND/OR combinations. Examples contain no missing labels and must satisfy the application schema before fitting. All three splits are separate files. Exact input overlap across splits is rejected.
12
+
13
+ The corpus was assembled locally from a small set of controlled phrase variations. Validation and evaluation contain distinct inputs and unseen combinations/amounts, but share vocabulary and phrase families with training. This is a software integration benchmark, not an independent linguistic generalization study. BOO-35's broader requirement for independent eval templates, dates, ownership, ranges, and adversarial coverage remains open.
14
+
15
+ The eight additional challenge queries are diagnostic examples, not a second hidden test set. We used them to discover and fix mixed-field partial parses and unsupported negation. They cannot be used as unbiased evidence of the resulting parser's generalization.
16
+
17
+ ## Models and selection
18
+
19
+ Both candidates use 212 normalized word/bigram features and 13 predicate classes, giving 2,756 weights. Numeric spans are replaced by a shared feature during fitting; their actual values are normalized after recognition. Field-exclusive tokens learned from training reject detected mixed-field clauses. That guard is a heuristic, not a proof that all input semantics were consumed.
20
+
21
+ Nearest centroid averages and normalizes feature vectors by label. The linear model uses deterministic full-batch softmax regression, zero initialization, 300 training iterations, and a small L2 penalty. Each candidate is quantized to signed int8 values with a shared scale before scoring. The artifact currently stores those integers as JSON, rather than a binary tensor format.
22
+
23
+ Selection uses validation exact match and serialized artifact size. The initial exploratory 80% requirement chose the centroid model. We raised the example's requirement to 95% after inspecting validation failures, selecting linear regression at a modest size increase. The held-out report is now visible during development, so these results should not be treated as preregistered research.
24
+
25
+ | Approach | Validation exact | Eval exact | Eval abstention | Invalid output | Serialized artifact |
26
+ | ---------------- | ---------------------: | ---------: | --------------: | -------------: | ------------------: |
27
+ | Nearest centroid | 81.25% | 84.375% | 15.625% | 0% | 14,597 bytes |
28
+ | Linear softmax | 100% | 100% | 0% | 0% | 17,090 bytes |
29
+ | Rules | Not used for selection | 100% | 0% | 0% | No model weights |
30
+
31
+ The selected artifact SHA-256 is `03ef341142e8b2779a48d1033f58f08ded5e036101bcf72a2a36277f40027cfb`. The generated report records the corresponding data hashes. Package changes or project paths can change the artifact hash; rerun the commands to obtain current results.
32
+
33
+ Zero invalid output is enforced by deterministic validation. It does not establish semantic accuracy. Confidence bins and individual failures are included in the report. The score uses classification margin and vocabulary coverage; it has not been calibrated as a probability.
34
+
35
+ ## Browser measurements
36
+
37
+ A local macOS arm64 run used Playwright Chromium, 20 warm-up parses followed by 300 measured parses over three fixed queries per approach. All 300 parses were accepted for each candidate. The desktop result was:
38
+
39
+ | Approach | Warm p50 | Warm p95 | Module load and initialization |
40
+ | -------------------------- | ---------------------: | -------: | -----------------------------: |
41
+ | Nearest centroid | 0.1 ms | 0.2 ms | 7.3 ms |
42
+ | Linear comparison artifact | 0.1 ms | 0.2 ms | 9.2 ms |
43
+ | Rules | Below timer resolution | 0.1 ms | 7.4 ms |
44
+
45
+ The selected parser's initial lazy module load took 39.5 ms; its warm p50/p95 were 0.1/0.2 ms. The mobile viewport run reported 41.3 ms initial loading and the same warm quantiles. Mobile emulation uses the same host CPU and is not a phone hardware benchmark. Comparison modules load later with shared dependencies already warm, so their load times are not directly comparable to initial application loading. Timings include local static asset delivery and are affected by timer precision, JIT, and concurrent test workers.
46
+
47
+ The Vite build emits the selected model module at about 3.16 KB gzip, with shared runtime and application code separately. The application entry is about 109.4 KB gzip and includes React, Zod, the task definition, and UI code. The raw artifact size is not the total runtime cost. A 64,000-byte artifact limit and a generous 50 ms selected-parser browser p95 limit are enforced as regression budgets.
48
+
49
+ ## The rule comparison matters
50
+
51
+ The baseline has three anchored recognition regexes after common-word normalization: status, country, and numeric comparison. It uses explicit country/operator maps, three recognition branches, and the same boolean compiler and schema validation as the learned parser. Its current implementation is under 100 lines. It was expanded to cover the authored training language rather than left as a weak straw baseline.
52
+
53
+ The baseline matches the model's supported eval accuracy and runs faster. On the challenge set it also handles `not active customers`, which the model abstains on because only churn exclusion was trained. Both approaches abstain on the implicit multi-field flagship query. The linear model's successful import and tiny weights do not by themselves demonstrate that it should replace these rules.
54
+
55
+ ## What this establishes
56
+
57
+ A developer can define a typed task, edit ordinary JSONL examples, run one Bun command, and import a local learned parser without handling tensors, model architecture, or runtime prompts. Quantized learned inference is fast enough here that adding WebGPU has no demonstrated payoff. The API and file-import packaging are ready to support a better parser without changing application call sites.
58
+
59
+ The next substantive research step is independently authored language data and semantic span classification. It should target implicit conjunctions, operator/value attachment, negation, ranges, dates, and ownership, and measure false acceptance as well as exact match. We should compare that against this clause model and the rule baseline before generalizing the framework or claiming a regex replacement advantage.
60
+
61
+ ## Ticket coverage
62
+
63
+ BOO-46 delivers this integration proof. It implements the bounded AST, rule baseline, two learned candidates, local runtime, generated wrapper/import, React integration, and training command. It also establishes initial eval and report commands. It leaves BOO-35's independent broad dataset, BOO-37's span-versus-generation comparison, BOO-38's proper calibration, and BOO-43/44's unified component/latency reporting unfinished. The broader tickets should remain open where their acceptance criteria exceed this proof.
@@ -0,0 +1,88 @@
1
+ # Getting started
2
+
3
+ Matchbox is a TypeScript framework for building small models that run in the browser. Start with the money example inside your existing application, train it locally, and import the result.
4
+
5
+ The CLI requires Bun 1.4.2 or newer and Node 24 or newer for the local training toolchain.
6
+
7
+ ## Add Matchbox to your app
8
+
9
+ Once the first release is published, run this inside your existing React or Next.js app:
10
+
11
+ ```sh
12
+ bunx matchbox-ai init money --template money
13
+ bunx matchbox-ai dev money
14
+ ```
15
+
16
+ The CLI installs `@matchbox-ai/core` as an application dependency and `@matchbox-ai/train` and `matchbox-ai` as development dependencies, using your package manager. It preserves existing scripts and framework configuration. Run your app's dev server separately. Use `--skip-install` to defer installation.
17
+
18
+ When developing Matchbox itself, run `bun install` and `bun run build:packages` in this repository. Run `bun run matchbox init money --template money --directory /path/to/app --skip-install` to inspect a scaffold before the packages are published. It writes registry versions; it does not vendor a copy of the checkout.
19
+
20
+ ## Train in the workbench
21
+
22
+ Choose **Train model**. Once training finishes, try `$15` or `around twenty six grand in euros`. Predictions run in your browser. Choose **Evaluate** to check independent test examples, or **Measure browser speed** to time the current input.
23
+
24
+ The same operations are available in the terminal:
25
+
26
+ ```sh
27
+ bunx matchbox-ai train money
28
+ bunx matchbox-ai eval money
29
+ ```
30
+
31
+ ## Understand the authored task
32
+
33
+ ```text
34
+ matchbox/money/
35
+ parser.ts
36
+ pipeline.ts
37
+ lib/recipe.ts
38
+ lib/decode.ts
39
+ data/train.jsonl
40
+ data/train-spans.json
41
+ evals/validation.jsonl
42
+ evals/test.jsonl
43
+ .matchbox/money/
44
+ model.matchbox
45
+ model.ts
46
+ report.json
47
+ ```
48
+
49
+ The parser defines valid output. The pipeline explicitly selects a token model. The recipe supplies supervised token labels; the decoder normalizes recognized spans. New training examples may need new token annotations. Read the generated task README before extending it.
50
+
51
+ Use `matchbox-ai init my-task --template blank` to author another task. The blank starter explicitly uses word features and finite field classification; replace that pipeline if it does not suit your task. Schemas do not automatically select numeric encodings or transformations.
52
+
53
+ ## Import into React or Next.js
54
+
55
+ The generated TypeScript wrapper needs no bundler plugin. This example assumes a component at your application root; adjust the relative path for your component's location. In Next.js, use a client component:
56
+
57
+ ```tsx
58
+ "use client";
59
+
60
+ import { useMatchbox } from "@matchbox-ai/core/react";
61
+
62
+ const loadMoney = () => import("./.matchbox/money/model");
63
+
64
+ export function MoneyButton() {
65
+ const { parse, status } = useMatchbox(loadMoney);
66
+
67
+ return (
68
+ <button
69
+ disabled={status !== "ready"}
70
+ onClick={async () => {
71
+ const result = await parse("twenty dollars");
72
+ if (result.status === "ok") console.log(result.value.amount);
73
+ else console.log(result.reason);
74
+ }}
75
+ >
76
+ Parse an amount
77
+ </button>
78
+ );
79
+ }
80
+ ```
81
+
82
+ Train before your application build. Generated artifacts remain ignored, so CI needs to train or restore a previously evaluated artifact. Import training helpers only in the authored pipeline and training scripts, never in client components. For `.matchbox` imports with Vite, the optional [Vite integration](react.md) remains available.
83
+
84
+ ## Run the repository showcase
85
+
86
+ From the Matchbox checkout, `bun run dev` trains the examples and starts the showcase. The home page demonstrates customer filtering; `/training` demonstrates money parsing and the parity training check.
87
+
88
+ Continue with [CLI](cli.md), [Evaluation](evaluation.md), [Training pipelines](pipelines.md), or [Project structure](project-structure.md).
@@ -0,0 +1,3 @@
1
+ # Neural training
2
+
3
+ See [pipelines](pipelines.md) for the supported native TensorFlow trainers and [evaluation](evaluation.md) for dataset separation and export checks. Examples use explicit pipeline.ts declarations; recipes and decoders are application-owned.