mlx-bun 0.0.8 → 0.0.10
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/README.md +112 -20
- package/docs/design/batching-perf-path.md +232 -0
- package/docs/design/batching-v2-plan.md +515 -0
- package/docs/design/bucketing-stage.md +196 -0
- package/docs/design/compat-cli-surface-design.md +11 -11
- package/docs/design/docs-reorg-plan.md +1 -1
- package/docs/design/dreaming-nightly-pipeline.md +291 -0
- package/docs/design/dspark-speculative-decoding.md +106 -0
- package/docs/design/generic-model-support.md +381 -0
- package/docs/design/memory-inference-path.md +422 -0
- package/docs/design/memory-synthesis.md +287 -0
- package/docs/design/minicpm5-decode-megakernel.md +484 -0
- package/docs/design/mlx-lm-tool-parity-plan.md +535 -0
- package/docs/design/omlx-adoption-map.md +90 -0
- package/docs/design/orpo-dynamic-lambda.md +41 -0
- package/docs/design/orpo-training.md +35 -5
- package/docs/design/parallel-slots.md +12 -1
- package/docs/design/parity-tier-dag.md +13 -5
- package/docs/design/segmented-backward-training.md +15 -0
- package/docs/design/spec-decode-larger-targets.md +229 -0
- package/docs/design/ssd-kv-cold-tier.md +158 -0
- package/docs/design/tauri-desktop-app.md +2 -2
- package/docs/design/the-dreaming-handoff.md +141 -0
- package/docs/design/the-dreaming-master-plan.md +446 -0
- package/docs/design/write-pipeline-entity.md +468 -0
- package/docs/investigations/curve-bisector-routing.md +1 -1
- package/docs/investigations/decode-roofline-lookagain.md +348 -0
- package/docs/investigations/dspark-handoff.md +58 -0
- package/docs/investigations/kernel-perf-review-2026-07.md +171 -0
- package/docs/planning/PRODUCT_ROADMAP.md +2 -2
- package/docs/planning/curve-sampler-research-plan.md +331 -0
- package/docs/planning/memory-docs-and-dag-plan.md +185 -0
- package/docs/planning/pi-integration-review.md +178 -0
- package/docs/planning/release-notes-v0.0.10.md +57 -0
- package/docs/planning/release-notes-v0.0.9.md +122 -0
- package/docs/planning/web-ui-pass-plan.md +213 -0
- package/docs/planning/website-readme-pass-plan.md +224 -0
- package/docs/reference/cli.md +255 -0
- package/docs/reference/embedding.md +7 -2
- package/docs/reference/library-api.md +22 -3
- package/docs/reference/memory.md +5 -5
- package/docs/reference/models.md +137 -0
- package/docs/reference/orpo-quickstart.md +6 -0
- package/docs/reference/server-api.md +187 -9
- package/docs/reference/server-config.md +43 -9
- package/docs/reference/training.md +31 -12
- package/package.json +1 -1
- package/src/anthropic.ts +22 -0
- package/src/assets/curve-designer.html +1 -1
- package/src/chat-template.ts +25 -7
- package/src/cli.ts +1077 -90
- package/src/config.ts +4 -1
- package/src/download.ts +99 -8
- package/src/embed.ts +77 -0
- package/src/eval/perplexity.ts +164 -0
- package/src/eval/runner.ts +15 -6
- package/src/eval/tasks/bfcl.ts +1 -1
- package/src/generate.ts +149 -18
- package/src/harness-pi.ts +43 -17
- package/src/index.ts +2 -0
- package/src/kv-store.ts +240 -98
- package/src/lora.ts +2 -2
- package/src/memory/article.ts +558 -0
- package/src/memory/chunk-validation.ts +150 -0
- package/src/memory/chunk.ts +305 -12
- package/src/memory/cluster.ts +344 -17
- package/src/memory/coverage.ts +134 -0
- package/src/memory/crosslink.ts +0 -0
- package/src/memory/db.ts +184 -45
- package/src/memory/entity.ts +203 -0
- package/src/memory/gate.ts +187 -0
- package/src/memory/history.ts +152 -0
- package/src/memory/ingest.ts +324 -11
- package/src/memory/model.ts +321 -0
- package/src/memory/normalize.ts +671 -0
- package/src/memory/parse.ts +22 -0
- package/src/memory/pipeline.ts +242 -30
- package/src/memory/prompts.ts +42 -0
- package/src/memory/query.ts +334 -0
- package/src/memory/reconcile.ts +734 -0
- package/src/memory/redirect.ts +108 -0
- package/src/memory/reindex.ts +325 -0
- package/src/memory/resolve.ts +307 -0
- package/src/memory/route.ts +272 -0
- package/src/memory/schedule.ts +6 -4
- package/src/memory/stages.ts +774 -0
- package/src/memory/synthesize.ts +1629 -20
- package/src/memory/tools.ts +446 -96
- package/src/memory/vault.ts +462 -35
- package/src/memory/wikify.ts +1057 -16
- package/src/mlx/array.ts +21 -0
- package/src/mlx/ffi.ts +3 -0
- package/src/mlx/ops.ts +72 -0
- package/src/model/compiled-decode.ts +43 -8
- package/src/model/factory.ts +29 -8
- package/src/model/flash-attention.ts +4 -2
- package/src/model/fused-decode-kernel.ts +14 -7
- package/src/model/fused-mlp-kernel.ts +169 -0
- package/src/model/fused-swiglu-kernel.ts +240 -0
- package/src/model/gemma4-base.ts +96 -7
- package/src/model/gemma4.ts +33 -2
- package/src/model/minicpm5.ts +106 -8
- package/src/model/qwen3-delta.ts +48 -1
- package/src/model/qwen3.ts +276 -0
- package/src/model/qwen3_5.ts +11 -2
- package/src/model/steel-linear-kernel.ts +96 -0
- package/src/model/support.ts +38 -8
- package/src/model/universal/archs.ts +332 -0
- package/src/model/universal/dense.ts +576 -0
- package/src/model/universal/modules.ts +163 -0
- package/src/model/universal/rope.ts +366 -0
- package/src/pi-provider.ts +1 -1
- package/src/pi-terminal.ts +29 -8
- package/src/pi-web.ts +19 -2
- package/src/prompt-cache.ts +55 -9
- package/src/quantize/config-writer.ts +1 -1
- package/src/registry.ts +219 -8
- package/src/responses.ts +23 -0
- package/src/sampler.ts +220 -9
- package/src/serve/batch-scheduler.ts +307 -83
- package/src/serve/generation-gateway.ts +156 -29
- package/src/server.ts +746 -73
- package/src/spec/drafter.ts +81 -49
- package/src/spec/dspark/data-dflash.ts +156 -0
- package/src/spec/dspark/data.ts +201 -0
- package/src/spec/dspark/generate-dflash.ts +193 -0
- package/src/spec/dspark/generate.ts +290 -0
- package/src/spec/dspark/loss.ts +213 -0
- package/src/spec/dspark/module-dflash.ts +361 -0
- package/src/spec/dspark/module.ts +540 -0
- package/src/spec/dspark/sample.ts +112 -0
- package/src/spec/generate.ts +40 -19
- package/src/ssd-cache.ts +213 -0
- package/src/status-page.html +1 -1
- package/src/tokenizer.ts +7 -0
- package/src/train/flash-cce.ts +81 -23
- package/src/train/fuse.ts +243 -0
- package/src/train/index.ts +3 -0
- package/src/train/job.ts +8 -0
- package/src/train/loss.ts +341 -40
- package/src/train/prefix-shared.ts +62 -11
- package/src/train/segmented.ts +215 -55
- package/src/train/trainer.ts +112 -38
- package/src/web/skills/memory/SKILL.md +40 -17
|
@@ -28,7 +28,7 @@ import * as ops from "../mlx/ops";
|
|
|
28
28
|
import { createCausalMask, type Cache, type Mask } from "../model/gemma4-base";
|
|
29
29
|
import { MiniCPM5Model, setMiniCpmPrefixPlan } from "../model/minicpm5";
|
|
30
30
|
import { Gemma4Model, setGemmaPrefixPlan } from "../model/gemma4";
|
|
31
|
-
import { orpoLossFromLogps, fusedRespLogpMean, type ChunkCtx } from "./loss";
|
|
31
|
+
import { orpoLossFromLogps, fusedRespLogpMean, combineFullNll, logitsFromHiddenPadM, type ChunkCtx, type SftScope } from "./loss";
|
|
32
32
|
import type { DpoBatch } from "./dataset";
|
|
33
33
|
|
|
34
34
|
/** A model that can project final-norm hidden states to vocab logits — the only
|
|
@@ -63,17 +63,40 @@ export function blockSparseMask(P: number, Rc: number, Rr: number): MlxArray {
|
|
|
63
63
|
* MiniCPM5's runLayerRange calls makeMask once and disposes the returned arr. */
|
|
64
64
|
export class PrefixSharedCache implements Cache {
|
|
65
65
|
offset = 0;
|
|
66
|
-
constructor(
|
|
66
|
+
constructor(
|
|
67
|
+
private readonly P: number, private readonly Rc: number, private readonly Rr: number,
|
|
68
|
+
// Step-shared mask memo (kernel-review backlog #9): the [T,T] block-sparse
|
|
69
|
+
// mask is IDENTICAL for every layer, segment forward, and backward
|
|
70
|
+
// recompute of a step, but each runLayerRange call rebuilt it from its
|
|
71
|
+
// elementwise ops (2·nSeg+ rebuilds per step in the segmented prefix
|
|
72
|
+
// class). With a memo it is built once; makeMask hands out cheap slice
|
|
73
|
+
// VIEWS (consumers dispose their view — runLayerRange does), and the
|
|
74
|
+
// first cache disposed frees the memo. Use prefixSharedCaches() to build
|
|
75
|
+
// a memo-sharing batch.
|
|
76
|
+
private readonly memo?: { mask: MlxArray | null },
|
|
77
|
+
) {}
|
|
67
78
|
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
|
68
79
|
return [k.slice([0, 0, 0, 0], k.shape), v.slice([0, 0, 0, 0], v.shape)];
|
|
69
80
|
}
|
|
70
81
|
makeMask(_N: number, _windowSize: number | null): Mask {
|
|
71
|
-
return { mode: "array", arr: blockSparseMask(this.P, this.Rc, this.Rr) };
|
|
82
|
+
if (!this.memo) return { mode: "array", arr: blockSparseMask(this.P, this.Rc, this.Rr) };
|
|
83
|
+
if (!this.memo.mask) this.memo.mask = blockSparseMask(this.P, this.Rc, this.Rr);
|
|
84
|
+
const m = this.memo.mask;
|
|
85
|
+
return { mode: "array", arr: m.slice([0, 0], m.shape) };
|
|
72
86
|
}
|
|
73
87
|
state(): MlxArray[] { return []; }
|
|
74
88
|
isTrimmable(): boolean { return true; }
|
|
75
89
|
trim(_n: number): void { /* offset pinned at 0 */ }
|
|
76
|
-
dispose(): void {
|
|
90
|
+
dispose(): void {
|
|
91
|
+
if (this.memo?.mask) { this.memo.mask.dispose(); this.memo.mask = null; }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** One PrefixSharedCache per layer, all sharing a single block-sparse-mask
|
|
96
|
+
* memo for the step (see the constructor note). */
|
|
97
|
+
export function prefixSharedCaches(nLayers: number, P: number, Rc: number, Rr: number): Cache[] {
|
|
98
|
+
const memo: { mask: MlxArray | null } = { mask: null };
|
|
99
|
+
return Array.from({ length: nLayers }, () => new PrefixSharedCache(P, Rc, Rr, memo));
|
|
77
100
|
}
|
|
78
101
|
|
|
79
102
|
/** Length-normalized mean log-prob over the predictions at hidden positions
|
|
@@ -87,7 +110,7 @@ function gatheredLogpMean(model: LogitProjector, h: MlxArray, gatherIdx: number[
|
|
|
87
110
|
const hSel = ops.takeAxis(h, idxArr, 1); // [1, M, hidden]
|
|
88
111
|
idxArr.dispose();
|
|
89
112
|
if (hSel.shape[2] !== hidden) throw new Error("gatheredLogpMean: hidden mismatch");
|
|
90
|
-
const logits = model
|
|
113
|
+
const logits = logitsFromHiddenPadM(model, hSel); // [1, M, V] (M in {2,3} padded — mlx qmm bug)
|
|
91
114
|
hSel.dispose();
|
|
92
115
|
const V = logits.shape[2]!;
|
|
93
116
|
const logits2d = ops.reshape(logits, [M, V]);
|
|
@@ -147,6 +170,26 @@ export function prefixGatherIdx(P: number, Rc: number, Rr: number): { chosenIdx:
|
|
|
147
170
|
return { chosenIdx, rejectedIdx };
|
|
148
171
|
}
|
|
149
172
|
|
|
173
|
+
/** sft_scope:"full" over the prefix-shared concat: the full-scope chosen NLL
|
|
174
|
+
* gathers the PROMPT predictions too — hidden position t (t = 0..P-2) predicts
|
|
175
|
+
* prompt token t+1 — and combines them with the response mean ℓw:
|
|
176
|
+
* NLL_full = -((P-1)·promptMean + Rc·ℓw) / (P-1+Rc). The prompt head routes
|
|
177
|
+
* through the same branchLogpMeanGathered tier as the responses (whole-vocab /
|
|
178
|
+
* fused / flash), sharing the one concat forward's hiddens. Returns [1]
|
|
179
|
+
* (caller owns); lw is NOT disposed. P=1 (no prompt predictions) → -ℓw. */
|
|
180
|
+
export function prefixFullNll(
|
|
181
|
+
model: LogitProjector, h: MlxArray, promptIds: number[], lw: MlxArray, Rc: number, chunk?: ChunkCtx,
|
|
182
|
+
): MlxArray {
|
|
183
|
+
const P = promptIds.length;
|
|
184
|
+
if (P <= 1) return combineFullNll(null, lw, 0, Rc);
|
|
185
|
+
const promptIdx = Array.from({ length: P - 1 }, (_, k) => k); // H[k] predicts promptIds[k+1]
|
|
186
|
+
const promptTargets = promptIds.slice(1);
|
|
187
|
+
const pm = branchLogpMeanGathered(model, h, promptIdx, promptTargets, chunk); // [1]
|
|
188
|
+
const nllFull = combineFullNll(pm, lw, P - 1, Rc);
|
|
189
|
+
pm.dispose();
|
|
190
|
+
return nllFull;
|
|
191
|
+
}
|
|
192
|
+
|
|
150
193
|
/** ORPO loss via the shared prompt-prefix single forward (MiniCPM5, B=1).
|
|
151
194
|
* `promptIds` is the shared prefix; `chosenResp`/`rejectedResp` are the response
|
|
152
195
|
* continuations. Returns the scalar loss (caller owns). Differentiable through
|
|
@@ -155,7 +198,7 @@ export function prefixGatherIdx(P: number, Rc: number, Rr: number): { chosenIdx:
|
|
|
155
198
|
export function orpoLossPrefixShared(
|
|
156
199
|
model: MiniCPM5Model,
|
|
157
200
|
promptIds: number[], chosenResp: number[], rejectedResp: number[],
|
|
158
|
-
lambda: number, chunk?: ChunkCtx,
|
|
201
|
+
lambda: number, chunk?: ChunkCtx, sftScope: SftScope = "response",
|
|
159
202
|
): MlxArray {
|
|
160
203
|
const P = promptIds.length, Rc = chosenResp.length, Rr = rejectedResp.length;
|
|
161
204
|
if (P < 1 || Rc < 1 || Rr < 1) throw new Error("orpoLossPrefixShared: need P,Rc,Rr >= 1");
|
|
@@ -165,7 +208,7 @@ export function orpoLossPrefixShared(
|
|
|
165
208
|
concat.set(chosenResp, P);
|
|
166
209
|
concat.set(rejectedResp, P + Rc);
|
|
167
210
|
const ids = MlxArray.fromInt32(concat, [1, T]);
|
|
168
|
-
const caches: Cache[] = model.layers.
|
|
211
|
+
const caches: Cache[] = prefixSharedCaches(model.layers.length, P, Rc, Rr);
|
|
169
212
|
|
|
170
213
|
let h: MlxArray;
|
|
171
214
|
setMiniCpmPrefixPlan({ P, Rc, Rr });
|
|
@@ -188,10 +231,14 @@ export function orpoLossPrefixShared(
|
|
|
188
231
|
if (keepForBwd) chunk!.sink.push(h);
|
|
189
232
|
const lw = branchLogpMeanGathered(model, h, chosenIdx, chosenResp, chunk);
|
|
190
233
|
const lr = branchLogpMeanGathered(model, h, rejectedIdx, rejectedResp, chunk);
|
|
234
|
+
// sft_scope:"full": add the prompt predictions (H[0..P-2] → promptIds[1..P-1])
|
|
235
|
+
// from the SAME concat forward; ℓw/ℓr stay response-only for the odds ratio.
|
|
236
|
+
const nllFull = sftScope === "full" ? prefixFullNll(model, h, promptIds, lw, Rc, chunk) : null;
|
|
191
237
|
if (!keepForBwd) h.dispose();
|
|
192
|
-
const loss = orpoLossFromLogps(lw, lr, lambda);
|
|
238
|
+
const loss = orpoLossFromLogps(lw, lr, lambda, nllFull ?? undefined);
|
|
193
239
|
lw.dispose();
|
|
194
240
|
lr.dispose();
|
|
241
|
+
nllFull?.dispose();
|
|
195
242
|
return loss;
|
|
196
243
|
}
|
|
197
244
|
|
|
@@ -206,7 +253,7 @@ export function prefixSharedLogps(
|
|
|
206
253
|
const concat = new Int32Array(T);
|
|
207
254
|
concat.set(promptIds, 0); concat.set(chosenResp, P); concat.set(rejectedResp, P + Rc);
|
|
208
255
|
const ids = MlxArray.fromInt32(concat, [1, T]);
|
|
209
|
-
const caches: Cache[] = model.layers.
|
|
256
|
+
const caches: Cache[] = prefixSharedCaches(model.layers.length, P, Rc, Rr);
|
|
210
257
|
setMiniCpmPrefixPlan({ P, Rc, Rr });
|
|
211
258
|
let h: MlxArray;
|
|
212
259
|
try { h = model.forwardHidden(ids, caches); }
|
|
@@ -349,7 +396,7 @@ class Gemma4PrefixSharedCache implements Cache {
|
|
|
349
396
|
export function orpoLossPrefixSharedGemma(
|
|
350
397
|
model: Gemma4Model,
|
|
351
398
|
promptIds: number[], chosenResp: number[], rejectedResp: number[],
|
|
352
|
-
lambda: number, chunk?: ChunkCtx,
|
|
399
|
+
lambda: number, chunk?: ChunkCtx, sftScope: SftScope = "response",
|
|
353
400
|
): MlxArray {
|
|
354
401
|
const P = promptIds.length, Rc = chosenResp.length, Rr = rejectedResp.length;
|
|
355
402
|
if (P < 1 || Rc < 1 || Rr < 1) throw new Error("orpoLossPrefixSharedGemma: need P,Rc,Rr >= 1");
|
|
@@ -384,10 +431,14 @@ export function orpoLossPrefixSharedGemma(
|
|
|
384
431
|
if (keepForBwd) chunk!.sink.push(h);
|
|
385
432
|
const lw = branchLogpMeanGathered(model, h, chosenIdx, chosenResp, chunk);
|
|
386
433
|
const lr = branchLogpMeanGathered(model, h, rejectedIdx, rejectedResp, chunk);
|
|
434
|
+
// sft_scope:"full": prompt predictions from the same concat forward (see
|
|
435
|
+
// orpoLossPrefixShared); ℓw/ℓr stay response-only for the odds ratio.
|
|
436
|
+
const nllFull = sftScope === "full" ? prefixFullNll(model, h, promptIds, lw, Rc, chunk) : null;
|
|
387
437
|
if (!keepForBwd) h.dispose();
|
|
388
|
-
const loss = orpoLossFromLogps(lw, lr, lambda);
|
|
438
|
+
const loss = orpoLossFromLogps(lw, lr, lambda, nllFull ?? undefined);
|
|
389
439
|
lw.dispose();
|
|
390
440
|
lr.dispose();
|
|
441
|
+
nllFull?.dispose();
|
|
391
442
|
return loss;
|
|
392
443
|
}
|
|
393
444
|
|