mlx-bun 0.4.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 +55 -42
- package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +3617 -0
- package/docs/archive/planning/release-notes-v0.5.0.md +37 -0
- package/docs/design/batching.md +220 -7
- package/docs/design/decode-speed-program.md +121 -66
- package/docs/design/generic-model-support.md +116 -0
- package/docs/design/kv-cache.md +380 -211
- package/docs/design/speculative-decoding.md +165 -26
- package/docs/design/turboquant.md +20 -7
- package/docs/design/unified-engine-frontier-plan.md +120 -13
- package/docs/planning/PRODUCT_ROADMAP.md +5 -6
- package/docs/planning/public-readiness-handoff.md +244 -0
- package/docs/planning/public-readiness.md +149 -0
- package/docs/reference/benchmarks.md +3463 -3489
- package/docs/reference/cli.md +62 -1
- package/docs/reference/distribution.md +29 -4
- package/docs/reference/environment.md +104 -8
- package/docs/reference/library-api.md +18 -4
- package/docs/reference/memory.md +1 -1
- package/docs/reference/models.md +17 -5
- package/docs/reference/server-api.md +181 -11
- package/docs/reference/server-config.md +232 -105
- 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/autoregressive.ts +22 -1
- package/src/backends/mlx/batch-group.ts +111 -27
- package/src/backends/mlx/cache-layout.ts +3 -3
- package/src/backends/mlx/continuation-persistence.ts +5 -4
- 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/gateway-binding.ts +56 -12
- package/src/backends/mlx/kv-maintenance.ts +30 -2
- 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 +4 -3
- package/src/backends/mlx/paged-cache-codec.ts +27 -0
- package/src/backends/mlx/prefill-cohort.ts +15 -4
- package/src/backends/mlx/prefill-policy.ts +26 -0
- package/src/backends/mlx/prefill-rows.ts +57 -13
- 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 +18 -5
- package/src/backends/mlx/rollback.ts +6 -3
- package/src/backends/mlx/serial-executor.ts +16 -7
- package/src/backends/mlx/speculative-group.ts +105 -26
- package/src/backends/mlx/speculative.ts +24 -7
- package/src/backends/mlx/target-layout-capability.ts +1 -1
- package/src/backends/mlx/transitioning-kv-rows.ts +8 -0
- package/src/cli.ts +322 -0
- package/src/contracts/execution.ts +10 -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 +13 -3
- package/src/contracts/scheduling.ts +9 -0
- package/src/engine/execution-plan.ts +23 -12
- package/src/engine/execution-tasks.ts +44 -0
- package/src/engine/namespaced-cache.ts +13 -0
- package/src/engine/scheduler.ts +22 -2
- package/src/fill/fill-session.ts +14 -3
- package/src/generate.ts +28 -22
- package/src/grammar.ts +13 -0
- package/src/inference/prefill.ts +6 -0
- package/src/kv-scheme.ts +22 -0
- package/src/kv-store.ts +115 -79
- 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 +33 -5
- package/src/lab/paged-kv/paged-kv.ts +108 -42
- package/src/md-modules.d.ts +5 -0
- package/src/mlx/array.ts +37 -0
- 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/batched-turboquant-kv.ts +6 -5
- package/src/model/delayed-quantized-kv.ts +3 -3
- package/src/model/delayed-rotating-quantized-kv.ts +1 -1
- package/src/model/delayed-turboquant-kv.ts +6 -4
- package/src/model/factory.ts +26 -0
- package/src/model/fingerprint.ts +12 -0
- package/src/model/full-prefill-row.ts +1 -1
- package/src/model/gemma4-base.ts +25 -6
- package/src/model/gemma4.ts +82 -2
- package/src/model/kv-attention-view.ts +4 -1
- package/src/model/profile.ts +29 -4
- package/src/model/quantized-append-attention.ts +31 -0
- package/src/model/qwen3-mrope.ts +7 -9
- package/src/model/qwen3_5.ts +99 -37
- package/src/model/support.ts +8 -0
- package/src/model/token-groups.ts +66 -0
- package/src/model/trellis-linear.ts +2 -2
- package/src/model/turboquant-codec.ts +6 -0
- 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/prompt-cache.ts +265 -43
- package/src/runtime-config.ts +1 -5
- package/src/safetensors.ts +9 -2
- package/src/sampler.ts +5 -4
- package/src/serve/audio-routes.ts +323 -0
- package/src/serve/chat-request.ts +2 -0
- package/src/serve/chat-stage.ts +17 -12
- 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 +52 -11
- package/src/serve/model-binding.ts +7 -1
- package/src/serve/preparation.ts +3 -3
- package/src/serve/prompt-response-trace.ts +14 -0
- package/src/serve/request-plan.ts +2 -0
- package/src/serve/request-prep.ts +38 -21
- package/src/serve/transcription-server.ts +64 -0
- package/src/serve/transcription-service.ts +502 -0
- package/src/server.ts +132 -164
- package/src/spec/assistant-rows.ts +1 -0
- package/src/spec/deepspec-rows.ts +1 -1
- package/src/spec/dflash-source.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +1 -0
- package/src/spec/ngram-source.ts +27 -5
- package/src/spec/projected-draft-rows.ts +2 -2
- package/src/spec/qwen-mtp-rows.ts +11 -0
- package/src/spec/qwen-mtp-source.ts +3 -0
- package/src/spec/serve-loop.ts +5 -3
- package/src/spec/source.ts +14 -1
- package/src/spec/two-model-rows.ts +1 -0
- package/src/spec/two-model.ts +2 -2
- package/src/ssd-cache.ts +76 -17
- package/src/ssd-durability.ts +20 -22
- 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 +160 -0
- 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/docs/{planning → archive/planning}/release-notes-v0.4.0.md +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# mlx-bun v0.5.0
|
|
2
|
+
|
|
3
|
+
Whisper speech-to-text: transcription, dictation and voice input, bit-exact
|
|
4
|
+
against mlx-whisper and faster than both mlx-whisper and whisper.cpp on the
|
|
5
|
+
same clips.
|
|
6
|
+
|
|
7
|
+
- `mlx-community/whisper-large-v3-turbo` (any fp16 `mlx-community/whisper-*`)
|
|
8
|
+
loads as a new encoder-decoder family. The oracle-parity graph matches
|
|
9
|
+
mlx-whisper 0.4.3 bit-exactly on the mel spectrogram, the encoder output and
|
|
10
|
+
every decoder logit; the default fast path (fused attention, fused cross-K/V,
|
|
11
|
+
a compiled decoder step with device-side logit filters, pipelined greedy,
|
|
12
|
+
in-graph beam top-k) is held to at most two differing tokens per clip. M1 Max,
|
|
13
|
+
11 s clip: 340 ms greedy (mlx-whisper 371), 424 ms beam-5 (whisper.cpp 499).
|
|
14
|
+
- Decoding: greedy, sampling with the temperature fallback ladder, beam search
|
|
15
|
+
(mlx-whisper has none; matches whisper.cpp's beam-5 transcripts), prompts and
|
|
16
|
+
vocabulary hints fitted to the 223-token budget, language detection,
|
|
17
|
+
translation, >30 s seek loop, word-level timestamps.
|
|
18
|
+
- `POST /v1/audio/transcriptions` and `/v1/audio/translations` (OpenAI shape,
|
|
19
|
+
multipart or JSON, json/verbose_json/text/srt/vtt, SSE streaming) on every
|
|
20
|
+
server, with Whisper loaded per take beside the chat model and released right
|
|
21
|
+
after it; `mlx-bun serve <whisper model>` runs a transcription-only server.
|
|
22
|
+
- Streaming sessions (`/v1/audio/sessions`): audio uploaded while recording,
|
|
23
|
+
every finished 30 s window transcribed during capture — a 62 s take returns
|
|
24
|
+
327 ms after its last chunk.
|
|
25
|
+
- Silero VAD v6.2 gate (ported from the reference graph, verified against the
|
|
26
|
+
pip package): silence returns an empty transcript without running Whisper;
|
|
27
|
+
runs on the stream inside sessions.
|
|
28
|
+
- In-process audio decoding through AudioToolbox (3.7 ms for an 11 s mp3 vs
|
|
29
|
+
72 ms via afconvert); any CoreAudio-readable container.
|
|
30
|
+
- `mlx-bun transcribe <file>` and `mlx-bun dictate` (push-to-talk from the
|
|
31
|
+
microphone, print / clipboard / typed keystrokes; new `mlx-bun-mic-capture`
|
|
32
|
+
sidecar), and a hold-to-talk mic in the web composer for any chat model.
|
|
33
|
+
- Measured and shelved: a Core ML encoder on the Neural Engine (3.3× slower
|
|
34
|
+
than the GPU on the M1 Max); whisper.cpp-style encoder context truncation
|
|
35
|
+
ships as an off-by-default Lab option.
|
|
36
|
+
|
|
37
|
+
Native pack `native-v0.5.0` adds the `mlx-bun-mic-capture` helper.
|
package/docs/design/batching.md
CHANGED
|
@@ -136,7 +136,7 @@ continuous iff
|
|
|
136
136
|
model is not DiffusionGemmaModel (non-autoregressive)
|
|
137
137
|
AND batch > 1
|
|
138
138
|
AND #modelCachesBatchable() (cache-capability gate, below)
|
|
139
|
-
AND !hasVision
|
|
139
|
+
AND (!hasVision OR model supports prepared media input)
|
|
140
140
|
AND adapter state supports compatible groups (when adapters are selected)
|
|
141
141
|
AND KV scheme supports the loaded cache layouts
|
|
142
142
|
AND selected method has a grouped implementation
|
|
@@ -546,13 +546,68 @@ They do not require repeating completed checks or withholding the current defaul
|
|
|
546
546
|
| Scheduling and ordinary decode | Default cap eight uses shared execution at B1/B>1; explicit `--batch 1` retains serial | Keep the batched default using existing measurements; address specific regressions separately. Serial removal is deferred |
|
|
547
547
|
| Speculative decode | Qwen MTP, prompt lookup, standalone, assistant, DeepSpec and seeded DSpark/DFlash providers are integrated through shared B1/B>1 interfaces, with the native/HTTP/cache checks recorded below | Finish specific unsupported combinations and measured regressions; GLM artifact testing is deferred and no trained DSpark/DFlash checkpoint exists |
|
|
548
548
|
| Sampling and logprobs | Shared sampler contract; ordinary groups capture logprobs and accept explicit seeds | Extend same-B oracle/feature compositions and matched performance; preserve per-request RNG/history |
|
|
549
|
-
| Grammar and fill |
|
|
550
|
-
| Adapters and media | Compatible adapter groups use shared execution;
|
|
551
|
-
| KV layout | Full and rotating affine/TurboQuant layouts, delayed/per-layer transitions, speculative donors and ordinary paged storage are integrated and tested below |
|
|
552
|
-
| Prefix and output reuse | Ordinary
|
|
549
|
+
| Grammar and fill | Shared grammar proposals use grouped verification. Shared strict fill composes prefill, rows, sampling and committed append; native and HTTP/cache/timing gates pass | Shared echo uses grouped verification and row rollback; Qwen MTP consumes verified echo through the provider interface. Asserted fill with speculation, other providers and other named combinations remain. Keep grammar proposals opt-in after mixed timing results |
|
|
550
|
+
| Adapters and media | Compatible adapter groups use shared execution; Gemma4 image/audio and Qwen image/video inputs, encoder caching and generated media-prefix reuse pass native/HTTP and M4 comparisons | Chunked media prefill, lone-media latency costs, adapter performance and broader compositions |
|
|
551
|
+
| KV layout | Full and rotating affine/TurboQuant layouts, delayed/per-layer transitions, speculative donors and ordinary paged storage are integrated and tested below | C1–C5 add shared SSD blocks and optional direct bf16/affine paged attention with native/HTTP evidence. TQ pages and paged speculation remain extensions; reuse completed row-layout gates |
|
|
552
|
+
| Prefix and output reuse | Ordinary and grouped methods publish generated target/companion state to one RAM/SSD cache | Native/HTTP and full Kanban retention/durability acceptance are complete; investigate new regressions without reopening unchanged gates |
|
|
553
553
|
| Generation resume | Shared ordinary resume is integrated after both-machine native/HTTP compiled, quantized/delayed and mixed-grammar checks, combined suites and eight M4 timing arms. The packed-model fixture now owns fresh weights per server | Adapter resume is integrated through the same policy; native/HTTP composition checks accompany it. Reuse the completed ordinary resume evidence |
|
|
554
554
|
| Usage and cleanup | The gateway forwards timing/rates; the missing first-token timestamp in ordinary batch admission is now fixed | Consistent events/accounting, row cancellation, failure cleanup and persistence on shutdown |
|
|
555
|
-
| Configuration |
|
|
555
|
+
| Configuration | Bound configuration reaches each owner, including delayed KV conversion, copied codecs and paged cache identity; the flag-owner inventory is complete | Preserve the contract when adding settings; completed policy tests and fixed-settings performance remain accepted |
|
|
556
|
+
|
|
557
|
+
### Prepared media and execution tasks
|
|
558
|
+
|
|
559
|
+
`MlxPromptInput` lets the model binding consume prepared embeddings and return
|
|
560
|
+
an owned final hidden row. `MlxPrefillCohort` retains initialization, precision
|
|
561
|
+
maintenance, projection and completion. An indivisible media attention span
|
|
562
|
+
declines prefill joins and mixed token packing; it processes the whole prompt
|
|
563
|
+
before entering ordinary shared decode. Sampling, row merging, retirement and
|
|
564
|
+
cancellation remain in their existing owners. Prepared media producers supply
|
|
565
|
+
an opaque identity for their exact media, encoder and preceding token prefix.
|
|
566
|
+
The ordinary cache combines this with the adapter namespace to retain generated
|
|
567
|
+
conversation state in RAM/SSD. Inputs without that identity remain uncached;
|
|
568
|
+
token IDs alone do not identify media contents. The input binding resumes
|
|
569
|
+
positioned text from the retained offset. Cache ownership and precision boundaries
|
|
570
|
+
are described in [kv-cache](kv-cache.md#514-prepared-media-prefix-identity).
|
|
571
|
+
|
|
572
|
+
Native preparation uses `ExecutionTasks` through the portable scheduler's
|
|
573
|
+
optional task boundary. The queue owns cancellation and failure settlement;
|
|
574
|
+
the scheduler owns when to advance it under the existing execution lease.
|
|
575
|
+
A task cannot replace model state. Exclusive mutations retain drain priority,
|
|
576
|
+
including a waiter arriving while preparation is running. Started work settles
|
|
577
|
+
before its owner releases native resources. The queue uses the portable
|
|
578
|
+
cancellation contract; the MLX binding adapts request AbortSignals.
|
|
579
|
+
`ModelPromptBuilder` receives a `PromptNativeWork` callback. Media downloads
|
|
580
|
+
and container transcoding finish outside that callback; lazy tower loading
|
|
581
|
+
and native prompt construction enter it. Encoder-local preprocessing remains
|
|
582
|
+
part of prompt construction. Grammar compilation enters the same execution
|
|
583
|
+
domain without putting template rendering or tokenization on the queue.
|
|
584
|
+
|
|
585
|
+
Gemma4 binds image/audio embeddings to this input interface. Qwen binds
|
|
586
|
+
image/video embeddings and a `MlxDecodeState` carrying each request's position
|
|
587
|
+
delta. The backend passes the current row order to that state after joins and
|
|
588
|
+
retirement. Its forward uses the cache's logical position array on device;
|
|
589
|
+
attention receives explicit positions without a module-global variable.
|
|
590
|
+
Input-state compatibility remains separate from cache-layout compatibility.
|
|
591
|
+
Media forwards with additional position state decline mixed-token packing.
|
|
592
|
+
Qwen image/video preprocessing completes outside the native execution lease.
|
|
593
|
+
Exact encoder features now use the shared cache object port; SSD reads finish
|
|
594
|
+
before native preparation. Cache placement remains independent of batching.
|
|
595
|
+
Diffusion retains its separate method. Qwen's source-controlled native comparison
|
|
596
|
+
and padded B1/B2/B4 affine/TurboQuant checks pass on both Macs, as do real image
|
|
597
|
+
HTTP checks on the packed 27B. The M4 image/video ABBA comparison preserves full
|
|
598
|
+
usage with faster concurrent completion; different batch geometries change some
|
|
599
|
+
responses. See [Qwen media evidence](../reference/benchmarks.md#shared-qwen-image-and-video-execution-2026-09-13)
|
|
600
|
+
for the source identity checks, probe correction and latency costs.
|
|
601
|
+
The input and task tests cover atomic boundaries, final projection geometry,
|
|
602
|
+
full same-machine Gemma logits/cache/continuation, active B1/B2 logit identity,
|
|
603
|
+
cancellation and mutation priority. Both-machine audio HTTP checks preserve the existing
|
|
604
|
+
transcription golden, exercise actual B2 decode and complete text generation
|
|
605
|
+
while an audio download is held open. The complete model-free suite and all
|
|
606
|
+
three TypeScript projects pass. The M4 ABBA media comparison preserves every
|
|
607
|
+
response and token count; concurrent completion improves with documented lone-
|
|
608
|
+
request and first-submitted-request costs in [benchmarks.md](../reference/benchmarks.md#shared-gemma-media-execution-2026-09-13);
|
|
609
|
+
see `tests/parity/shared-media-input.test.ts` and
|
|
610
|
+
`reports/prefill-observation/shared-media-*`.
|
|
556
611
|
|
|
557
612
|
Tests must exercise actual B>1 work, not requests routed back to serial.
|
|
558
613
|
Completed checks remain evidence for their recorded source and settings. A new
|
|
@@ -1818,11 +1873,19 @@ Both-machine tiny-model controls cover exact B1 proposals/absorption, zero-propo
|
|
|
1818
1873
|
|
|
1819
1874
|
### Paged storage through shared row and request-state interfaces
|
|
1820
1875
|
|
|
1821
|
-
`PagedKvRows` owns per-request block pools, immutable snapshots, gathering, masks, offsets and row membership. The existing executor binds it through the cache-layout interface. `MlxRequestStatePolicy` supplies compatible state construction and a prompt-cache port; paging selects no prefix store. Switching back to ordinary requests restores their cache port. The same paging constructor serves the compatibility entry point and shared prefill. B1 keeps the existing paged numerical graph; B>1 gathers padded attention inputs while retaining separate persistent pools. Gemma12 full sampled logits and HTTP choices match the ordinary same-B controls, including seeded sampling, logprobs and grammar. Both-machine model-free, SSD and typechecks pass. The native storage comparison fixes cohort membership and snapshot boundaries on both sides, covering small blocks and the default block boundary; otherwise cache publication changes the numerical prefill graph. The matched M4 source comparison is effectively flat, and shared paging improves concurrent throughput versus serial while retaining effectively equal B1 decode. Concurrent text can differ across batch geometries; the exact storage oracle compares the same geometry. Timing and limitations live in benchmarks.md; evidence is `reports/qwen38-closeout/composition-baseline/paged-rows/`.
|
|
1876
|
+
`PagedKvRows` owns per-request block pools, immutable snapshots, gathering, masks, offsets and row membership. The existing executor binds it through the cache-layout interface. `MlxRequestStatePolicy` supplies compatible state construction and a prompt-cache port; paging selects no prefix store. Switching back to ordinary requests restores their cache port. The same paging constructor serves the compatibility entry point and shared prefill. B1 keeps the existing paged numerical graph; B>1 gathers padded attention inputs while retaining separate persistent pools. Gemma12 full sampled logits and HTTP choices match the ordinary same-B controls, including seeded sampling, logprobs and grammar. Both-machine model-free, SSD and typechecks pass. The native storage comparison fixes cohort membership and snapshot boundaries on both sides, covering small blocks and the default block boundary; otherwise cache publication changes the numerical prefill graph. The matched M4 source comparison is effectively flat, and shared paging improves concurrent throughput versus serial while retaining effectively equal B1 decode. Concurrent text can differ across batch geometries; the exact storage oracle compares the same geometry. Timing and limitations live in benchmarks.md; evidence is `reports/qwen38-closeout/composition-baseline/paged-rows/`. Subsequent C1–C5 work adds shared SSD blocks and optional direct bf16/affine paged attention; its measured results are recorded in benchmarks.md. TQ pages and paged speculation remain separate extensions.
|
|
1822
1877
|
|
|
1823
1878
|
The sampler now exposes an optional stateless operation for compatible independent score rows. Ordinary decode and speculative verification share normalized-score argmax. Verification can sample a rectangle in one device operation and readback; acceptance still consumes only each request's valid positions. Grammar, processors, stochastic sampling, logprob capture and custom sampler functions retain their request-local operation. Same-shape numerical tests include rounding-created ties and large vocabularies; both-machine native/generated RAM/SSD and suites pass. Twelve matched M4 arms preserve ordinary throughput and improve lookup aggregate throughput; startup and trajectory limits are recorded in benchmarks.md. Lookup defaults remain unchanged. Evidence: `reports/qwen38-closeout/composition-baseline/independent-sampling/`.
|
|
1824
1879
|
|
|
1825
1880
|
|
|
1881
|
+
The affine same-B oracle now covers full-attention and rotating mixed-precision
|
|
1882
|
+
rows, including unequal lengths, window crossing, reordering and retirement.
|
|
1883
|
+
Equal-length rotating storage uses the pinned OptiQ implementation. Padded
|
|
1884
|
+
rotating cases compose it with stock mlx-lm batch positions and masks; they do
|
|
1885
|
+
not substitute solo-row logits for the batch oracle. The test-only reference
|
|
1886
|
+
and its limits are described in [benchmarks.md](../reference/benchmarks.md#same-batch-rotating-affine-oracle).
|
|
1887
|
+
Existing delayed-conversion, provider and lifecycle tests remain separate evidence.
|
|
1888
|
+
|
|
1826
1889
|
### Campaign checkout consolidation
|
|
1827
1890
|
|
|
1828
1891
|
The PR incorporates the accepted implementations from the M1 and M4 campaign
|
|
@@ -1839,3 +1902,153 @@ after their source files and reports were verified in a content-addressed local
|
|
|
1839
1902
|
`reports/pr-closeout/checkout-archive/`, with per-checkout manifests, SHA-256
|
|
1840
1903
|
objects and the recorded base commit. The PR retains the implementation and
|
|
1841
1904
|
findings; bulky raw experiment data stays local under the repository policy.
|
|
1905
|
+
|
|
1906
|
+
|
|
1907
|
+
### Scheduling reference algorithms and request observations
|
|
1908
|
+
|
|
1909
|
+
The next scheduling baseline is an iteration token budget, following the
|
|
1910
|
+
upstream implementations below. Review date: 2026-09-12. Read implementation
|
|
1911
|
+
order as well as configuration docs; scheduling first does not necessarily
|
|
1912
|
+
mean delivering output before the iteration's other GPU work finishes.
|
|
1913
|
+
|
|
1914
|
+
| Reference | Algorithm and ownership | Application here |
|
|
1915
|
+
|---|---|---|
|
|
1916
|
+
| [vLLM V1 scheduler, `dff76bc`](https://github.com/vllm-project/vllm/blob/dff76bc3e8d702901e6dda5971f9506a6c1bc00f/vllm/v1/core/sched/scheduler.py#L562) | Tracks computed tokens against required tokens, including speculative positions. Allocates the iteration budget to running requests before waiting requests. Prefill chunks and decode tokens can enter the same execution batch. | Represent remaining work through the scheduling interface; methods supply valid token work and the backend owns batch packing and kernels. |
|
|
1917
|
+
| [llama.cpp server, `3057bb6`](https://github.com/ggml-org/llama.cpp/blob/3057bb66c86c46d5781e50e85462a760ba7d1feb/tools/server/server-context.cpp#L2974) | Adds generating/drafting slots before filling the remaining batch capacity with compatible prompt tokens. Logical batch and physical microbatch capacities are distinct. HTTP workers own parsing, templates and streaming; one inference thread owns slots. | Preserve execution ownership while allowing request preparation and response transport to progress independently. A shared request count is insufficient; account for token work too. |
|
|
1918
|
+
| [mlx-lm generator, `dcbcf78`](https://github.com/ml-explore/mlx-lm/blob/dcbcf786c0cf56f9a12fabe9468c887781431ae2/mlx_lm/generate.py#L1783) | Advances generation first, admits/splits prompt rows, then processes bounded prompt chunks. Prompt and generation batches remain separate. Responses return after prompt processing, whose cache evaluation synchronizes. The pinned oracle has the same order. | This is the closest numerical/backend reference, but its response timing is not evidence that output is immediately flushed. Compare its actual request timeline. |
|
|
1919
|
+
| [LangChain streaming](https://docs.langchain.com/oss/python/langchain/streaming) | Routes model-provided text, reasoning and tool-call chunks through the agent application. | Reference for stream semantics; this layer does not select GPU prefill/decode work. |
|
|
1920
|
+
|
|
1921
|
+
[vLLM's tuning guidance](https://docs.vllm.ai/en/latest/configuration/optimization/#chunked-prefill)
|
|
1922
|
+
explicitly treats token budget as a latency/throughput tradeoff. Its GPU-specific
|
|
1923
|
+
budget recommendations are not Apple Silicon defaults. Start with the established
|
|
1924
|
+
algorithm, measure the same submitted work on M4, and retain deviations only
|
|
1925
|
+
with recorded benefits and costs. No framework guarantees one universally best
|
|
1926
|
+
chunk size or latency policy.
|
|
1927
|
+
|
|
1928
|
+
The established backend exposes `advance()` and `advancePreparation()`
|
|
1929
|
+
operations. `MlxPrefillRows` groups prompt rows, while ordinary and speculative
|
|
1930
|
+
methods advance decoding rows separately. The existing preparation budget limits
|
|
1931
|
+
cohort admission; it is not vLLM's combined per-iteration token budget. True mixed
|
|
1932
|
+
execution therefore needs backend work as well as scheduling policy. Padding a
|
|
1933
|
+
single decode token to a long prompt's width would defeat the intended saving.
|
|
1934
|
+
|
|
1935
|
+
Phase 18 S1b adds bounded mixed work. The method retains request identity,
|
|
1936
|
+
computed/required positions and candidate state. Scheduling allocates
|
|
1937
|
+
bounded work to active requests and then queued requests; the backend executes
|
|
1938
|
+
compatible selections. Sampling and cache ownership remain unchanged. Acceptance
|
|
1939
|
+
covers lone requests, arrivals during prefill and decode, unequal lengths,
|
|
1940
|
+
cancellation/retirement, speculative work and quantized state. Compare first
|
|
1941
|
+
semantic output, inter-output gaps, total workload time, occupancy, padding and
|
|
1942
|
+
memory alongside aggregate throughput. Same-B numerical contracts remain binding.
|
|
1943
|
+
|
|
1944
|
+
The P2R observer now separates row preparation, forward, remaining cache
|
|
1945
|
+
execution, maintenance, checkpoint capture, projection, completion and companion
|
|
1946
|
+
work. Shared work IDs and process-local time origins allow cross-request
|
|
1947
|
+
attribution without counting shared GPU work several times. Bounded initial
|
|
1948
|
+
routing spans expose hidden control tokens. Measurement semantics and the report
|
|
1949
|
+
command live in [server-config](../reference/server-config.md); measured results
|
|
1950
|
+
live in [benchmarks](../reference/benchmarks.md#prefill-observation-and-scheduling-screen).
|
|
1951
|
+
The simple active-before-prefill experiment remains an unadopted patch in the
|
|
1952
|
+
local report directory; it is not the mixed execution design above.
|
|
1953
|
+
|
|
1954
|
+
A second bounded screen submits shared prefill evaluation asynchronously and
|
|
1955
|
+
polls MLX completion while allowing Bun to service I/O. MLX's
|
|
1956
|
+
[`array::is_available`](https://github.com/ml-explore/mlx/blob/main/mlx/array.cpp)
|
|
1957
|
+
checks the completion event, not merely graph submission; the pinned native
|
|
1958
|
+
pack exports mlx-c's `_mlx_array_is_available`. This avoids holding the host
|
|
1959
|
+
thread during the GPU wait, but changes when requests become visible to the
|
|
1960
|
+
existing scheduler. Both M1 MiniCPM arm orders delay the first staggered
|
|
1961
|
+
request substantially; aggregate results are inconsistent. The candidate is
|
|
1962
|
+
removed. [Measurements](../reference/benchmarks.md#nonblocking-prefill-completion-screen)
|
|
1963
|
+
retain the excluded patch. Host responsiveness and request scheduling must be
|
|
1964
|
+
measured together before retaining a different completion boundary.
|
|
1965
|
+
|
|
1966
|
+
|
|
1967
|
+
#### Mixed token execution
|
|
1968
|
+
|
|
1969
|
+
The Lab Gemma and Qwen3.5/3.8 paths execute running decode and queued prompt work together.
|
|
1970
|
+
`ExecutionGroup.mixedPreparation` reports running-token demand and the minimum
|
|
1971
|
+
prompt work needed for progress. The scheduler reserves that demand and assigns
|
|
1972
|
+
the remaining iteration budget to preparation. Existing cohort admission still
|
|
1973
|
+
accounts for total prompt work. Removing that limit was measured and rejected:
|
|
1974
|
+
on this M4 workload, larger cohorts lost throughput and delayed later first
|
|
1975
|
+
outputs. Both variants execute the same bounded mixed-token model port.
|
|
1976
|
+
|
|
1977
|
+
`MlxPreparationWork` carries a token allowance and forward operation into the
|
|
1978
|
+
shared preparation driver. It limits actual tokens across rows while preserving
|
|
1979
|
+
planned precision conversions and checkpoint endpoints. `runMixedTokenIteration`
|
|
1980
|
+
collects the preparation and decode forward inputs. The model's `MixedTokenModel`
|
|
1981
|
+
port receives independent `TokenGroup` inputs with their existing row geometry
|
|
1982
|
+
and caches. Decode finishes sampling, publication and retirement before a
|
|
1983
|
+
completed preparation can join the active rows. A restored or cancelled
|
|
1984
|
+
preparation can finish without producing model work; an exhausted decode can
|
|
1985
|
+
publish its pending token without another forward.
|
|
1986
|
+
|
|
1987
|
+
Gemma reuses its existing attention and feed-forward layer interfaces. Attention
|
|
1988
|
+
retains each group's RoPE positions, masks, SDPA shape and cache operations.
|
|
1989
|
+
`mapPackedTokens` concatenates only real tokens for the feed-forward block and
|
|
1990
|
+
restores each group's output shape afterwards. It adds no padding or host
|
|
1991
|
+
readback. This is shared feed-forward execution, not a fully packed attention
|
|
1992
|
+
kernel. The unpacked control keeps the same scheduler budget to isolate the
|
|
1993
|
+
packing benefit. The original single-group model call remains unchanged.
|
|
1994
|
+
|
|
1995
|
+
Packing can change GEMV/GEMM dispatch relative to solo generation. The numerical
|
|
1996
|
+
contract therefore uses the pinned oracle with the same packed feed-forward
|
|
1997
|
+
geometry and independent attention shapes. The real-model test passes on M4 for
|
|
1998
|
+
Gemma e4b, 12B and 26B with bf16 and uniform affine KV4, continuation, and unequal
|
|
1999
|
+
decode/prefill row counts. The
|
|
2000
|
+
uniform-KV oracle explicitly uses stock quantized SDPA on both sides. Native
|
|
2001
|
+
state tests also cover bounded preparation with immediate and delayed affine
|
|
2002
|
+
and TurboQuant conversion. Failure, cancellation and retirement tests exercise
|
|
2003
|
+
the shared execution group and the work coordinator.
|
|
2004
|
+
|
|
2005
|
+
Qwen reuses its attention/DeltaNet and feed-forward blocks through the same
|
|
2006
|
+
model port. Masks, convolution tails and recurrent state remain per group;
|
|
2007
|
+
layer evaluation materializes both residual and cache outputs to bound prefill
|
|
2008
|
+
memory. Each `TokenGroup` can supply a borrowed layer-capture callback and
|
|
2009
|
+
request preservation of its matmul geometry. Speculative methods use those
|
|
2010
|
+
options for target verification, including pending tokens and draft candidates,
|
|
2011
|
+
and keep provider companion updates in their preparation/verification adapters.
|
|
2012
|
+
The scheduler sees the method’s target-token demand, not its draft algorithm.
|
|
2013
|
+
Hidden captures belong to each work item instead of a shared mutable model tap.
|
|
2014
|
+
|
|
2015
|
+
The measured default decision is to retain mixed execution as opt-in. Gemma
|
|
2016
|
+
first-output latency improves with an aggregate-throughput cost; Qwen MTP has
|
|
2017
|
+
no first-output win and loses aggregate throughput, despite a shorter worst
|
|
2018
|
+
streaming pause. This closes the bounded S1b comparison. Trace phase
|
|
2019
|
+
`engine.mixed_forward` records the model-call construction span and real token
|
|
2020
|
+
counts; GPU waits remain at the existing evaluation/readback boundaries. The
|
|
2021
|
+
[measured comparison](../reference/benchmarks.md#mixed-prefill-and-decode-token-work)
|
|
2022
|
+
records latency, throughput, streaming gaps and the unpacked control. Runtime
|
|
2023
|
+
settings live in [server-config](../reference/server-config.md).
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
### Grammar candidates through the shared verifier
|
|
2027
|
+
|
|
2028
|
+
`GrammarController.proposeTokens` reads xgrammar's forced continuation without
|
|
2029
|
+
advancing the matcher. It joins the existing WASM queue so concurrent requests
|
|
2030
|
+
cannot overlap calls into the single WASM instance. A request-owned constraint
|
|
2031
|
+
port supplies candidates to the same grouped verifier used by learned drafts
|
|
2032
|
+
and prompt lookup. The sampler applies each request's mask and commits its
|
|
2033
|
+
accepted tokens; scheduling only sees method work. Target graph binding no
|
|
2034
|
+
longer requires a serial draft constructor.
|
|
2035
|
+
|
|
2036
|
+
The constraint provider reuses prompt lookup's committed-history ownership and
|
|
2037
|
+
checkpoint format. It never searches history and has no serial draft method.
|
|
2038
|
+
Empty candidate lists use the verifier's existing one-token step. Candidate
|
|
2039
|
+
rejection and row retirement keep target and companion state aligned through
|
|
2040
|
+
the existing transaction and output interfaces.
|
|
2041
|
+
|
|
2042
|
+
`MLX_BUN_GRAMMAR_JUMP=1` selects this method for eligible shared structured-output
|
|
2043
|
+
requests without a configured drafter; `MLX_BUN_GRAMMAR_DRAFT_TOKENS` controls
|
|
2044
|
+
depth separately from batching. Shared logprobs remain available because every
|
|
2045
|
+
output is sampled. Explicit serial retains direct retokenized jump-forward.
|
|
2046
|
+
That algorithm skips target sampling for forced spans; the shared proposal
|
|
2047
|
+
algorithm verifies them. Both remain opt-in and must be compared separately.
|
|
2048
|
+
|
|
2049
|
+
The focused MiniCPM and packed-Qwen checks cover nonmutating proposals, B1 and
|
|
2050
|
+
concurrent requests, independent stopping/cancellation, affine/TurboQuant and
|
|
2051
|
+
logprob delivery. Fixed bf16 MiniCPM outputs match ordinary decoding. Affine
|
|
2052
|
+
MiniCPM can choose different valid tokenizations across verification widths;
|
|
2053
|
+
repeated fixed-configuration outputs match. Same-geometry verifier/KV oracles
|
|
2054
|
+
remain the numerical contract. Performance is recorded in benchmarks.md.
|