mlx-bun 0.3.0 → 0.5.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.
- package/README.md +57 -32
- package/docs/README.md +58 -42
- package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +3617 -0
- package/docs/archive/investigations/openjarvis-fit.md +198 -0
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
- package/docs/archive/planning/release-notes-v0.4.0.md +45 -0
- package/docs/archive/planning/release-notes-v0.5.0.md +37 -0
- package/docs/design/batching.md +1535 -50
- package/docs/design/decode-speed-program.md +394 -1171
- package/docs/design/generic-model-support.md +195 -3
- package/docs/design/kv-cache.md +538 -225
- package/docs/design/speculative-decoding.md +552 -50
- package/docs/design/turboquant.md +140 -17
- package/docs/design/unified-engine-frontier-plan.md +259 -150
- package/docs/planning/PRODUCT_ROADMAP.md +21 -6
- package/docs/planning/public-readiness-handoff.md +244 -0
- package/docs/planning/public-readiness.md +149 -0
- package/docs/reference/benchmarks.md +3537 -1112
- package/docs/reference/cli.md +102 -2
- package/docs/reference/distribution.md +45 -13
- package/docs/reference/environment.md +159 -13
- package/docs/reference/library-api.md +18 -4
- package/docs/reference/memory.md +1 -1
- package/docs/reference/models.md +28 -7
- package/docs/reference/server-api.md +257 -33
- package/docs/reference/server-config.md +372 -151
- package/docs/reference/troubleshooting.md +13 -21
- package/package.json +2 -2
- package/src/audio/audiotoolbox.ts +112 -0
- package/src/audio/conformer.ts +8 -0
- package/src/audio/mic-capture.ts +98 -0
- package/src/audio/silero-vad.ts +379 -0
- package/src/audio/whisper-decode.ts +774 -0
- package/src/audio/whisper-fast.ts +732 -0
- package/src/audio/whisper-format.ts +73 -0
- package/src/audio/whisper-mel.ts +185 -0
- package/src/audio/whisper-timing.ts +274 -0
- package/src/audio/whisper-tokenizer.ts +239 -0
- package/src/audio/whisper-transcribe.ts +410 -0
- package/src/backends/mlx/assistant-target.ts +46 -0
- package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
- package/src/backends/mlx/autoregressive.ts +22 -1
- package/src/backends/mlx/batch-group.ts +464 -236
- package/src/backends/mlx/cache-attachment.ts +67 -0
- package/src/backends/mlx/cache-layout.ts +31 -0
- package/src/backends/mlx/checkpoint-state.ts +53 -0
- package/src/backends/mlx/continuation-persistence.ts +107 -0
- package/src/backends/mlx/continuation-request.ts +43 -0
- package/src/backends/mlx/continuation.ts +77 -0
- package/src/backends/mlx/draft-target.ts +7 -22
- package/src/backends/mlx/encoder-cache.ts +25 -0
- package/src/backends/mlx/fill-append.ts +21 -8
- package/src/backends/mlx/fill-group.ts +497 -0
- package/src/backends/mlx/full-kv-row-append.ts +32 -0
- package/src/backends/mlx/full-kv-row-donor.ts +54 -0
- package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
- package/src/backends/mlx/gateway-binding.ts +122 -19
- package/src/backends/mlx/kv-codec.ts +9 -0
- package/src/backends/mlx/kv-maintenance.ts +161 -0
- package/src/backends/mlx/kv-tensor-rows.ts +212 -0
- package/src/backends/mlx/mixed-iteration.ts +62 -0
- package/src/backends/mlx/model-prompt.ts +46 -32
- package/src/backends/mlx/model-serving.ts +5 -4
- package/src/backends/mlx/paged-cache-codec.ts +27 -0
- package/src/backends/mlx/prefill-cohort.ts +100 -0
- package/src/backends/mlx/prefill-policy.ts +26 -0
- package/src/backends/mlx/prefill-rows.ts +244 -0
- package/src/backends/mlx/prefill.ts +1 -1
- package/src/backends/mlx/projected-context-rows.ts +72 -0
- package/src/backends/mlx/prompt-input.ts +29 -0
- package/src/backends/mlx/qwen-prompt-input.ts +40 -0
- package/src/backends/mlx/request-state-policy.ts +54 -0
- package/src/backends/mlx/rollback.ts +45 -4
- package/src/backends/mlx/row-sampling.ts +49 -0
- package/src/backends/mlx/serial-executor.ts +51 -73
- package/src/backends/mlx/speculative-group.ts +438 -0
- package/src/backends/mlx/speculative-round.ts +161 -0
- package/src/backends/mlx/speculative.ts +24 -7
- package/src/backends/mlx/state-rows.ts +104 -0
- package/src/backends/mlx/state-views.ts +21 -1
- package/src/backends/mlx/target-layout-capability.ts +35 -0
- package/src/backends/mlx/transitioning-kv-rows.ts +173 -0
- package/src/cli.ts +333 -36
- package/src/contracts/execution.ts +21 -0
- package/src/contracts/object-cache.ts +8 -0
- package/src/contracts/pi-provider.ts +1 -1
- package/src/contracts/pi.ts +3 -1
- package/src/contracts/prefix-cache.ts +33 -0
- package/src/contracts/resources.ts +7 -0
- package/src/contracts/sampling.ts +23 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/engine/execution-plan.ts +38 -25
- package/src/engine/execution-tasks.ts +44 -0
- package/src/engine/namespaced-cache.ts +13 -0
- package/src/engine/resources.ts +12 -1
- package/src/engine/scheduler.ts +32 -7
- package/src/fill/fill-session.ts +14 -3
- package/src/fit.ts +29 -15
- package/src/generate.ts +105 -195
- package/src/grammar.ts +13 -0
- package/src/inference/draft-acceptance.ts +41 -0
- package/src/inference/draft-output.ts +49 -0
- package/src/inference/prefill.ts +6 -0
- package/src/inference/rollback.ts +2 -2
- package/src/kv-scheme.ts +92 -12
- package/src/kv-store.ts +183 -93
- package/src/lab/README.md +5 -1
- package/src/lab/paged-kv/paged-attention.ts +117 -0
- package/src/lab/paged-kv/paged-kv-rows.ts +111 -0
- package/src/lab/paged-kv/paged-kv.ts +126 -46
- package/src/md-modules.d.ts +5 -0
- package/src/mlx/array.ts +39 -1
- package/src/mlx/ffi.ts +19 -0
- package/src/mlx/normalized-argmax.ts +116 -0
- package/src/mlx/ops.ts +97 -10
- package/src/model/artifact-identity.ts +73 -0
- package/src/model/batched-kv.ts +235 -0
- package/src/model/batched-mask.ts +12 -4
- package/src/model/batched-quant.ts +8 -2
- package/src/model/batched-quantized-kv.ts +144 -0
- package/src/model/batched-rotating-quant.ts +76 -15
- package/src/model/batched-rotating-state.ts +76 -0
- package/src/model/batched-rotating.ts +64 -22
- package/src/model/batched-row-storage.ts +52 -0
- package/src/model/batched-ssm.ts +52 -0
- package/src/model/batched-turboquant-kv.ts +94 -0
- package/src/model/compiled-decode.ts +7 -1
- package/src/model/decoded-kv-donor.ts +12 -0
- package/src/model/delayed-quantized-kv.ts +72 -0
- package/src/model/delayed-rotating-quantized-kv.ts +93 -0
- package/src/model/delayed-turboquant-kv.ts +57 -0
- package/src/model/factory.ts +26 -0
- package/src/model/fingerprint.ts +12 -0
- package/src/model/full-prefill-padding.ts +56 -0
- package/src/model/full-prefill-row.ts +105 -0
- package/src/model/gemma4-base.ts +183 -82
- package/src/model/gemma4.ts +116 -28
- package/src/model/generated/gemma4-12b.ts +4 -1
- package/src/model/generated/gemma4-26b.ts +4 -1
- package/src/model/generated/gemma4-e4b.ts +4 -1
- package/src/model/glm52-cache.ts +80 -4
- package/src/model/glm52-mla.ts +12 -6
- package/src/model/glm52.ts +19 -40
- package/src/model/kv-attention-view.ts +70 -0
- package/src/model/minicpm5.ts +11 -7
- package/src/model/profile.ts +29 -4
- package/src/model/quantized-append-attention.ts +31 -0
- package/src/model/qwen3-delta-state.ts +74 -0
- package/src/model/qwen3-delta.ts +59 -36
- package/src/model/qwen3-mrope.ts +7 -9
- package/src/model/qwen3_5.ts +177 -75
- package/src/model/rotating-kv-donor.ts +35 -0
- package/src/model/rotating-kv-layout.ts +262 -0
- package/src/model/rotating-row-transaction.ts +35 -0
- package/src/model/speculative-rotating-kv.ts +101 -0
- package/src/model/ssm-prefill-padding.ts +39 -0
- package/src/model/support.ts +8 -0
- package/src/model/token-groups.ts +66 -0
- package/src/model/trellis-linear.ts +4 -4
- package/src/model/turboquant-codec.ts +89 -0
- package/src/model/universal/dense.ts +14 -13
- package/src/model/whisper.ts +435 -0
- package/src/native/mic_capture.swift +92 -0
- package/src/native-pack.ts +6 -5
- package/src/pi-web.ts +9 -1
- package/src/preflight.ts +31 -15
- package/src/prompt-cache.ts +306 -86
- package/src/runtime-config.ts +1 -5
- package/src/safetensors.ts +9 -2
- package/src/sampler.ts +37 -25
- package/src/serve/audio-routes.ts +323 -0
- package/src/serve/chat-request.ts +2 -0
- package/src/serve/chat-stage.ts +19 -14
- package/src/serve/completion-executor.ts +9 -1
- package/src/serve/discovery-routes.ts +17 -1
- package/src/serve/generated-token-history.ts +57 -0
- package/src/serve/generation-gateway.ts +88 -38
- package/src/serve/model-binding.ts +7 -1
- package/src/serve/model-host.ts +3 -4
- package/src/serve/preparation.ts +3 -3
- package/src/serve/prompt-response-trace.ts +14 -0
- package/src/serve/request-plan.ts +6 -3
- package/src/serve/request-prep.ts +40 -25
- package/src/serve/text-completion-stage.ts +2 -2
- package/src/serve/transcription-server.ts +64 -0
- package/src/serve/transcription-service.ts +502 -0
- package/src/server.ts +185 -261
- package/src/spec/assistant-rows.ts +93 -0
- package/src/spec/assistant-source.ts +28 -18
- package/src/spec/cache-identity.ts +22 -0
- package/src/spec/deepspec-rows.ts +29 -0
- package/src/spec/deepspec-source.ts +12 -10
- package/src/spec/dflash-source.ts +28 -4
- package/src/spec/drafter.ts +153 -142
- package/src/spec/dspark/deepspec-module.ts +95 -120
- package/src/spec/dspark/module-dflash.ts +126 -170
- package/src/spec/glm52-mtp-graph.ts +29 -0
- package/src/spec/glm52-mtp-rows.ts +132 -0
- package/src/spec/glm52-mtp-source.ts +54 -136
- package/src/spec/glm52-mtp-state.ts +33 -0
- package/src/spec/ngram-source.ts +115 -21
- package/src/spec/projected-draft-rows.ts +73 -0
- package/src/spec/qwen-mtp-module.ts +171 -0
- package/src/spec/qwen-mtp-rows.ts +230 -0
- package/src/spec/qwen-mtp-source.ts +84 -226
- package/src/spec/qwen-mtp-state.ts +30 -0
- package/src/spec/serve-loop.ts +73 -69
- package/src/spec/source.ts +93 -15
- package/src/spec/two-model-rows.ts +62 -0
- package/src/spec/two-model.ts +45 -103
- package/src/ssd-cache.ts +107 -36
- package/src/ssd-durability.ts +29 -27
- package/src/storage/host-buffer.ts +24 -0
- package/src/storage/kv-writer.ts +83 -0
- package/src/storage/kv-writer.worker.js +264 -0
- package/src/storage/retention-policy.ts +37 -0
- package/src/tiered-prompt-cache.ts +45 -0
- package/src/vision/embedder.ts +8 -0
- package/src/vision/prompt.ts +101 -65
- package/src/vision/qwen3vl-prompt.ts +101 -64
- package/src/vision/qwen3vl-tower.ts +11 -0
- package/src/vision/siglip.ts +8 -0
- package/src/web/app.html +12 -0
- package/src/web/app.js +217 -57
- package/src/web/src/chat.ts +4 -1
- package/src/web/src/composer.ts +3 -0
- package/src/web/src/voice.ts +141 -0
- package/src/web/sw.js +1 -1
- package/src/backends/mlx/memory-guard.ts +0 -40
- package/src/spec/prefix-state.ts +0 -45
- /package/docs/{planning → archive/planning}/release-notes-v0.3.0.md +0 -0
package/src/model/qwen3-delta.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// default (use_kernel = not training), and its float accumulation / simd_sum
|
|
6
6
|
// reduction order differ from the pure-ops fallback — so BIT-EXACT parity with
|
|
7
7
|
// mlx-lm requires the SAME kernel, dispatched with the SAME grid/threadgroup.
|
|
8
|
-
// We port the non-vectorized
|
|
9
|
-
//
|
|
8
|
+
// We port the non-vectorized variant (g.ndim == 3). Padded prefill selects
|
|
9
|
+
// the oracle masked specialization; unpadded execution retains its kernel.
|
|
10
10
|
//
|
|
11
11
|
// Numerics (must match the reference dtypes exactly — mlx infers the kernel's
|
|
12
12
|
// pointer element types from the input arrays):
|
|
@@ -20,10 +20,12 @@
|
|
|
20
20
|
// GQA is handled inside the kernel (hk_idx = hv_idx / (Hv/Hk)); q/k stay at Hk.
|
|
21
21
|
|
|
22
22
|
import { MlxArray } from "../mlx/array";
|
|
23
|
+
import { materializeCopy } from "../mlx/materialize";
|
|
23
24
|
import { Dtype } from "../mlx/ffi";
|
|
24
25
|
import { MetalKernel } from "../mlx/metal-kernel";
|
|
25
26
|
import { CompiledFunction } from "../mlx/compile";
|
|
26
27
|
import * as ops from "../mlx/ops";
|
|
28
|
+
import type { SsmPrefillPadding } from "./ssm-prefill-padding";
|
|
27
29
|
import type { Cache, Mask } from "./gemma4-base";
|
|
28
30
|
|
|
29
31
|
// Verbatim body of mlx-lm's gated_delta_step (has_mask=False, vectorized=False),
|
|
@@ -104,7 +106,15 @@ const SOURCE = String.raw`
|
|
|
104
106
|
`;
|
|
105
107
|
|
|
106
108
|
let kernel: MetalKernel | null = null;
|
|
107
|
-
|
|
109
|
+
let maskedKernel: MetalKernel | null = null;
|
|
110
|
+
function getKernel(masked = false): MetalKernel {
|
|
111
|
+
if (masked) return maskedKernel ??= new MetalKernel({
|
|
112
|
+
name: "gated_delta_step_mask",
|
|
113
|
+
inputNames: ["q", "k", "v", "g", "beta", "state_in", "Tin", "mask"],
|
|
114
|
+
outputNames: ["y", "state_out"],
|
|
115
|
+
source: SOURCE.replace("if (true)", "if (mask[b_idx * T + t])"),
|
|
116
|
+
ensureRowContiguous: true,
|
|
117
|
+
});
|
|
108
118
|
if (!kernel)
|
|
109
119
|
kernel = new MetalKernel({
|
|
110
120
|
name: "gated_delta_step",
|
|
@@ -154,7 +164,7 @@ export function computeG(aLog: MlxArray, a: MlxArray, dtBias: MlxArray): MlxArra
|
|
|
154
164
|
* state: [B, Hv, Dv, Dk] f32 (or null → zeros) */
|
|
155
165
|
export function gatedDeltaUpdate(
|
|
156
166
|
q: MlxArray, k: MlxArray, v: MlxArray, a: MlxArray, b: MlxArray,
|
|
157
|
-
aLog: MlxArray, dtBias: MlxArray, state: MlxArray | null,
|
|
167
|
+
aLog: MlxArray, dtBias: MlxArray, state: MlxArray | null, mask: MlxArray | null = null,
|
|
158
168
|
): [MlxArray, MlxArray] {
|
|
159
169
|
const [B, , Hk, Dk] = q.shape as [number, number, number, number];
|
|
160
170
|
const [, , Hv, Dv] = v.shape as [number, number, number, number];
|
|
@@ -171,7 +181,9 @@ export function gatedDeltaUpdate(
|
|
|
171
181
|
|
|
172
182
|
const T = q.shape[1]!;
|
|
173
183
|
const tArr = MlxArray.fromInt32(new Int32Array([T]), [1]);
|
|
174
|
-
const
|
|
184
|
+
const inputs = [q, k, v, g, beta, stateIn, tArr];
|
|
185
|
+
if (mask) inputs.push(mask);
|
|
186
|
+
const [y, stateOut] = getKernel(mask !== null).apply(inputs, {
|
|
175
187
|
outputs: [
|
|
176
188
|
{ shape: [B, T, Hv, Dv], dtype: q.dtype },
|
|
177
189
|
{ shape: [B, Hv, Dv, Dk], dtype: Dtype.float32 },
|
|
@@ -207,6 +219,7 @@ export interface SsmSpecRound {
|
|
|
207
219
|
prevConv: MlxArray | null;
|
|
208
220
|
prevRecurrent: MlxArray | null;
|
|
209
221
|
prevOffset: number;
|
|
222
|
+
prevOffsets: number[] | null;
|
|
210
223
|
/** Pre-conv in_proj output [B,S,convDim] — position-local. */
|
|
211
224
|
qkv: MlxArray | null;
|
|
212
225
|
/** Gate/beta projections [B,S,Hv] — position-local. */
|
|
@@ -216,14 +229,15 @@ export interface SsmSpecRound {
|
|
|
216
229
|
S: number;
|
|
217
230
|
/** Layer-bound prefix replay: called AFTER the snapshot is restored onto
|
|
218
231
|
* the cache; advances conv/recurrent/offset by `keep` tokens. */
|
|
219
|
-
replay: ((cache: SSMCache, keep: number) => void) | null;
|
|
232
|
+
replay: ((cache: SSMCache, keep: number | readonly number[]) => void) | null;
|
|
220
233
|
}
|
|
221
234
|
|
|
222
235
|
export class SSMCache implements Cache {
|
|
223
236
|
conv: MlxArray | null = null;
|
|
224
237
|
recurrent: MlxArray | null = null;
|
|
225
238
|
offset = 0;
|
|
226
|
-
|
|
239
|
+
prefillPadding: SsmPrefillPadding | null = null;
|
|
240
|
+
/** Live speculative verify round; null outside a verify transaction. */
|
|
227
241
|
specRound: SsmSpecRound | null = null;
|
|
228
242
|
/** Per-row token coverage (batch lane only; null on serial B=1 caches,
|
|
229
243
|
* where `offset` IS the row's count). mlx-lm's ArraysCache tracks no
|
|
@@ -248,15 +262,13 @@ export class SSMCache implements Cache {
|
|
|
248
262
|
throw new Error("SSMCache has no KV updateAndFetch (gated-DeltaNet layer)");
|
|
249
263
|
}
|
|
250
264
|
|
|
251
|
-
makeMask(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// batched decode feeds one real token per row — so unlike mlx-lm's
|
|
255
|
-
// left-padded batch-prefill there is never a pad position to mask.
|
|
256
|
-
return { mode: "", arr: null };
|
|
265
|
+
makeMask(N: number, _windowSize: number | null): Mask {
|
|
266
|
+
const arr = this.prefillPadding?.makeMask(N) ?? null;
|
|
267
|
+
return { mode: arr ? "array" : "", arr };
|
|
257
268
|
}
|
|
258
269
|
|
|
259
270
|
advance(n: number): void {
|
|
271
|
+
if (this.prefillPadding) { this.advanceRows(this.prefillPadding.advance(n)); return; }
|
|
260
272
|
this.offset += n;
|
|
261
273
|
// Batched rows step together (one forward advances every row), so the
|
|
262
274
|
// per-row counts move in lockstep; they DIFFER only in their merge-time
|
|
@@ -264,6 +276,13 @@ export class SSMCache implements Cache {
|
|
|
264
276
|
if (this.offsets) for (let i = 0; i < this.offsets.length; i++) this.offsets[i]! += n;
|
|
265
277
|
}
|
|
266
278
|
|
|
279
|
+
/** Methods may retain different verified prefixes for each active request. */
|
|
280
|
+
advanceRows(counts: readonly number[]): void {
|
|
281
|
+
if (!this.offsets) { this.offset += counts[0]!; return; }
|
|
282
|
+
for (let row = 0; row < this.offsets.length; row++) this.offsets[row]! += counts[row]!;
|
|
283
|
+
this.offset = Math.max(...this.offsets);
|
|
284
|
+
}
|
|
285
|
+
|
|
267
286
|
state(): MlxArray[] {
|
|
268
287
|
const out: MlxArray[] = [];
|
|
269
288
|
if (this.conv) out.push(this.conv);
|
|
@@ -279,7 +298,7 @@ export class SSMCache implements Cache {
|
|
|
279
298
|
throw new Error("SSMCache is not trimmable");
|
|
280
299
|
}
|
|
281
300
|
|
|
282
|
-
// --- speculative verify-round support
|
|
301
|
+
// --- speculative verify-round support -----------------------------------
|
|
283
302
|
// The serve loop arms a round before the verify forward and resolves it
|
|
284
303
|
// after the accept walk. The layer's forward, seeing an armed round, hands
|
|
285
304
|
// its replaced state slots to the round instead of disposing them, records
|
|
@@ -294,6 +313,7 @@ export class SSMCache implements Cache {
|
|
|
294
313
|
prevConv: null,
|
|
295
314
|
prevRecurrent: null,
|
|
296
315
|
prevOffset: this.offset,
|
|
316
|
+
prevOffsets: this.offsets ? [...this.offsets] : null,
|
|
297
317
|
qkv: null,
|
|
298
318
|
a: null,
|
|
299
319
|
b: null,
|
|
@@ -306,12 +326,12 @@ export class SSMCache implements Cache {
|
|
|
306
326
|
this.#dropSpecRound();
|
|
307
327
|
}
|
|
308
328
|
|
|
309
|
-
specRoundRollback(keep: number): void {
|
|
329
|
+
specRoundRollback(keep: number | readonly number[]): void {
|
|
310
330
|
const r = this.specRound;
|
|
311
331
|
if (!r) throw new Error("SSMCache.specRoundRollback without an armed round");
|
|
312
332
|
if (r.armed)
|
|
313
333
|
throw new Error("SSMCache.specRoundRollback before the verify forward recorded");
|
|
314
|
-
if (keep < 0 || keep > r.S)
|
|
334
|
+
if (typeof keep === "number" ? keep < 0 || keep > r.S : keep.some(count => count < 0 || count > r.S))
|
|
315
335
|
throw new Error(`SSMCache.specRoundRollback keep=${keep} outside window S=${r.S}`);
|
|
316
336
|
// Restore the pre-round snapshot (ownership moves back to the cache).
|
|
317
337
|
this.conv?.dispose();
|
|
@@ -321,9 +341,8 @@ export class SSMCache implements Cache {
|
|
|
321
341
|
r.prevConv = null;
|
|
322
342
|
r.prevRecurrent = null;
|
|
323
343
|
this.offset = r.prevOffset;
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (keep > 0) {
|
|
344
|
+
this.offsets = r.prevOffsets;
|
|
345
|
+
if (typeof keep === "number" ? keep > 0 : keep.some(count => count > 0)) {
|
|
327
346
|
if (!r.replay) throw new Error("SSMCache.specRoundRollback with no recorded replay");
|
|
328
347
|
r.replay(this, keep); // advances conv/recurrent/offset by `keep`
|
|
329
348
|
}
|
|
@@ -347,6 +366,7 @@ export class SSMCache implements Cache {
|
|
|
347
366
|
this.recurrent?.dispose();
|
|
348
367
|
this.conv = null;
|
|
349
368
|
this.recurrent = null;
|
|
369
|
+
this.prefillPadding = null;
|
|
350
370
|
}
|
|
351
371
|
|
|
352
372
|
// --- batch-lane dynamic-B ops (BatchScheduler only) ----------------------
|
|
@@ -386,25 +406,30 @@ export class SSMCache implements Cache {
|
|
|
386
406
|
|
|
387
407
|
/** Evict rows not in `keep` (ascending row indices), in place. */
|
|
388
408
|
filter(keep: number[]): void {
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
409
|
+
if (this.conv && this.recurrent) {
|
|
410
|
+
const idx = ops.fromInt32(keep, [keep.length]);
|
|
411
|
+
const conv = ops.takeAxis(this.conv, idx, 0);
|
|
412
|
+
const recurrent = ops.takeAxis(this.recurrent, idx, 0);
|
|
413
|
+
idx.dispose();
|
|
414
|
+
this.conv.dispose();
|
|
415
|
+
this.recurrent.dispose();
|
|
416
|
+
this.conv = conv;
|
|
417
|
+
this.recurrent = recurrent;
|
|
418
|
+
}
|
|
419
|
+
this.prefillPadding?.filter(keep);
|
|
420
|
+
if (this.offsets) {
|
|
421
|
+
this.offsets = keep.map((i) => this.offsets![i]!);
|
|
422
|
+
this.offset = Math.max(0, ...this.offsets);
|
|
423
|
+
}
|
|
399
424
|
}
|
|
400
425
|
|
|
401
426
|
filterRows(keep: readonly number[]): void { this.filter([...keep]); }
|
|
402
427
|
|
|
403
428
|
/** Row `i` as a fresh SERIAL cache — port of mlx-lm ArraysCache.extract
|
|
404
429
|
* (cache.py:673-676: `cache.cache = [c[idx : idx + 1] for c in self.cache]`,
|
|
405
|
-
* a B-axis slice of every state slot).
|
|
406
|
-
*
|
|
407
|
-
*
|
|
430
|
+
* a B-axis slice of every state slot). A proper subset gets compact storage
|
|
431
|
+
* so retaining one row does not pin the other rows. A singleton retains an
|
|
432
|
+
* independent handle over its complete allocation. Offset =
|
|
408
433
|
* the row's OWN coverage, not the shared max. */
|
|
409
434
|
extractRow(i: number): SSMCache {
|
|
410
435
|
if (!this.conv || !this.recurrent)
|
|
@@ -414,10 +439,8 @@ export class SSMCache implements Cache {
|
|
|
414
439
|
lo[0] = i;
|
|
415
440
|
const hi = [...a.shape];
|
|
416
441
|
hi[0] = i + 1;
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
view.dispose();
|
|
420
|
-
return own;
|
|
442
|
+
using view = a.slice(lo, hi);
|
|
443
|
+
return a.shape[0] === 1 ? ops.contiguous(view) : materializeCopy(view);
|
|
421
444
|
};
|
|
422
445
|
const out = new SSMCache();
|
|
423
446
|
out.conv = cut(this.conv);
|
package/src/model/qwen3-mrope.ts
CHANGED
|
@@ -30,20 +30,13 @@ export interface MropeRequestState {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export interface MropeForwardState {
|
|
33
|
-
/** Effective positions [3,
|
|
33
|
+
/** Effective positions [3, B, L] int32 for the current forward window. */
|
|
34
34
|
posIds: MlxArray;
|
|
35
35
|
/** Borrowed model-owned f32 inv_freq (mropeInvFreq) — not disposed here. */
|
|
36
36
|
invFreq: MlxArray;
|
|
37
37
|
rotaryDims: number;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
/** Active per-forward mRoPE cos/sin, read by Qwen3Attention.forward. Null on
|
|
41
|
-
* the text-only path (serial lane only — vision requests never batch). */
|
|
42
|
-
export let activeMrope: MropeForwardState | null = null;
|
|
43
|
-
export function setActiveMrope(s: MropeForwardState | null): void {
|
|
44
|
-
activeMrope = s;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
40
|
const MROPE_SECTION = [11, 11, 10] as const;
|
|
48
41
|
|
|
49
42
|
/** Interleaved frequency→stream selector (rope_utils
|
|
@@ -85,6 +78,11 @@ export function buildMropePositions(
|
|
|
85
78
|
state: MropeRequestState, offset: number, L: number,
|
|
86
79
|
invFreq: MlxArray, rotaryDims: number,
|
|
87
80
|
): MropeForwardState {
|
|
81
|
+
return { posIds: mropePositionIds(state, offset, L), invFreq, rotaryDims };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Request-owned prompt positions; the returned native array belongs to the caller. */
|
|
85
|
+
export function mropePositionIds(state: MropeRequestState, offset: number, L: number): MlxArray {
|
|
88
86
|
const P = state.positions;
|
|
89
87
|
const promptLen = P[0].length;
|
|
90
88
|
const joint = new Int32Array(3 * L);
|
|
@@ -94,7 +92,7 @@ export function buildMropePositions(
|
|
|
94
92
|
joint[axis * L + l] = idx < promptLen ? P[axis]![idx]! : idx + state.delta;
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
|
-
return
|
|
95
|
+
return MlxArray.fromInt32(joint, [3, 1, L]);
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
// The reference language-side apply is a CUSTOM METAL KERNEL (rope_utils
|