mlx-bun 0.0.12 → 0.2.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 +40 -24
- package/bin/mlx-bun.mjs +1 -1
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/archive/planning/release-notes-v0.0.13.md +77 -0
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/colibri-glm52-port.md +8 -1
- package/docs/design/compat-cli-surface-design.md +1 -1
- package/docs/design/decode-speed-program.md +1 -1
- package/docs/design/docs-reorg-plan.md +1 -1
- package/docs/design/dspark-serving-program.md +1 -1
- package/docs/design/dspark-speculative-decoding.md +53 -3
- package/docs/design/grammar-spec-batching-integration.md +1 -1
- package/docs/design/mlx-lm-serving-execution-seam.md +81 -0
- package/docs/design/orpo-dynamic-lambda.md +1 -1
- package/docs/design/orpo-future-enhancements.md +1 -1
- package/docs/design/orpo-training.md +2 -2
- package/docs/design/parity-tier-dag.md +1 -1
- package/docs/design/repo-cleanup-plan.md +46 -4
- package/docs/design/segmented-backward-training.md +2 -2
- package/docs/design/ssd-kv-cold-tier.md +127 -0
- package/docs/design/turboquant-weights.md +467 -0
- package/docs/design/w4a16-compute-precision-spike.md +1 -1
- package/docs/design/web-chat-redesign.md +5 -5
- package/docs/planning/chunk-task-roadmap.md +1 -1
- package/docs/planning/curve-sampler-research-plan.md +4 -4
- package/docs/planning/memory-docs-and-dag-plan.md +1 -1
- package/docs/planning/release-notes-v0.2.0.md +49 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/cli.md +15 -4
- package/docs/reference/distribution.md +1 -0
- package/docs/reference/features-matrix.md +3 -1
- package/docs/reference/library-api.md +41 -1
- package/docs/reference/models.md +33 -0
- package/docs/reference/server-api.md +86 -19
- package/docs/reference/server-config.md +57 -33
- package/package.json +2 -2
- package/src/anthropic.ts +92 -3
- package/src/chat-template.ts +34 -1
- package/src/cli.ts +131 -36
- package/src/config.ts +10 -0
- package/src/eval/kl.ts +27 -20
- package/src/eval/runner.ts +23 -4
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/expert-trace.ts +3 -1
- package/src/fit.ts +24 -43
- package/src/flags.ts +7 -9
- package/src/generate.ts +107 -92
- package/src/grammar.ts +2 -1
- package/src/harness-pi.ts +1 -1
- package/src/index.ts +20 -0
- package/src/jobs/job-entry.ts +3 -2
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +370 -205
- package/src/media-fetch.ts +19 -3
- package/src/memory/model.ts +2 -1
- package/src/memory/vault.ts +2 -1
- package/src/memory-plan.ts +18 -0
- package/src/mlx/ffi.ts +8 -11
- package/src/mlx/ops.ts +31 -6
- package/src/model/batched-mask.ts +1 -1
- package/src/model/batched-quant.ts +1 -1
- package/src/model/batched-rotating-quant.ts +43 -97
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +56 -105
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +3 -2
- package/src/model/factory.ts +44 -49
- package/src/model/gemma4-base.ts +163 -10
- package/src/model/generated/gemma4-12b.ts +50 -146
- package/src/model/generated/gemma4-26b.ts +32 -92
- package/src/model/generated/gemma4-e4b.ts +26 -74
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/minicpm5.ts +2 -1
- package/src/model/profile.ts +433 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5.ts +217 -25
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +13 -6
- package/src/pi-web.ts +6 -5
- package/src/prompt-cache.ts +2 -2
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +6 -0
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +102 -2
- package/src/runtime-config.ts +67 -0
- package/src/sampler.ts +272 -0
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +200 -87
- package/src/serve/completion-executor.ts +346 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +205 -0
- package/src/serve/generation-gateway.ts +116 -109
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +338 -0
- package/src/serve/model-admin-routes.ts +153 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +158 -0
- package/src/serve/static-routes.ts +101 -0
- package/src/server.ts +768 -1367
- package/src/spec/dflash-source.ts +2 -1
- package/src/spec/dspark/module-dflash.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +8 -0
- package/src/spec/qwen-mtp-source.ts +431 -0
- package/src/spec/serve-loop.ts +36 -68
- package/src/ssd-cache.ts +17 -14
- package/src/ssd-durability.ts +195 -0
- package/src/train/flash-cce.ts +12 -11
- package/src/train/forward.ts +32 -1
- package/src/train/loss.ts +2 -1
- package/src/train/segmented.ts +4 -3
- package/src/train/trainer.ts +3 -2
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +47 -1
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +513 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.js +10 -3
- package/src/web/src/chat.ts +12 -5
- package/src/weights.ts +81 -26
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-runs/bisector-route.json +0 -0
- /package/docs/{investigations → archive/investigations}/curve-runs/bisector-trace.json +0 -0
- /package/docs/{investigations → archive/investigations}/curve-runs/curve-terrain.json +0 -0
- /package/docs/{investigations → archive/investigations}/curve-runs/curve-terrain.svg +0 -0
- /package/docs/{investigations → archive/investigations}/curve-terrain.html +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-ab.html +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-explorer.html +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/cliff.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/cross.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/edges.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/k20-grids.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/k20-peaks.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/lw-curve.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-figs/terrain.svg +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-report.html +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-ab.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-blind-prompts.md +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-blind.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-cliff.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-cross.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-edge.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-eval1.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-frontier.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-grid.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-grid2.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-lw-coarse.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-map.json +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/run0-original.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runA-recommended.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAA-cliff-cpm5.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAB-grid2-e4b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAC-peak-e4b-partial.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAD-ab-samples.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAE-edge-e4b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAF-logit-calibration.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runAG-eval-config2.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runB-gain-variants.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runC-pivots.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runD-oetf.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runE-eotf.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runF-shaper-working.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runG-shaper-sweep.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runH-wsweep.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runI-asweep.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runJ-knobmap.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runK-frontier.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runL-widemap.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runM-frontier-emb.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runN-verify.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runO-frontier-seed5000.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runP-grid-AxSm.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runQ-grid-tgW.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runR-blind-transcript.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runS-cross-coherence.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runT-cross-cpm5.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runU-cross-12b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runV-lw-e4b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runW-lw-12b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runX-lw-cpm5.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runY-cliff-e4b.log +0 -0
- /package/docs/{investigations → archive/investigations}/hlg-runs/runZ-cliff-12b.log +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# mlx-bun video series
|
|
2
|
+
|
|
3
|
+
## Episode 1: local AI on a Mac without the setup ritual
|
|
4
|
+
|
|
5
|
+
### Production brief
|
|
6
|
+
|
|
7
|
+
- **Working title:** Running a 27B Model Locally on a Mac, Without Python
|
|
8
|
+
- **Thumbnail text:** 27B. LOCAL. NO PYTHON.
|
|
9
|
+
- **Target length:** 8 minutes
|
|
10
|
+
- **Audience:** developers who know what local models are but have not used MLX
|
|
11
|
+
- **Machine:** whichever machine is used for the final recorded benchmark; show
|
|
12
|
+
its chip and memory alongside the results
|
|
13
|
+
- **Demo model:** `mlx-community/Qwen3.8-27B-OptiQ-4bit`, already downloaded
|
|
14
|
+
- **Presentation:** calm, direct, mostly terminal and browser capture with short
|
|
15
|
+
pieces to camera
|
|
16
|
+
- **Question the episode answers:** Can local AI on a Mac feel like installed
|
|
17
|
+
software instead of an ML engineering project?
|
|
18
|
+
|
|
19
|
+
This episode proves the product before explaining the implementation. It does
|
|
20
|
+
not tour every feature. Memory, training, model ports, Bun FFI, and the failed
|
|
21
|
+
experiments belong in later episodes.
|
|
22
|
+
|
|
23
|
+
### Recording setup
|
|
24
|
+
|
|
25
|
+
Prepare two terminal profiles:
|
|
26
|
+
|
|
27
|
+
1. A clean profile for the installation shot. Do not begin the model download
|
|
28
|
+
during the take unless the download duration is known and useful on camera.
|
|
29
|
+
2. The normal development profile with Qwen3.8-27B already downloaded. Use
|
|
30
|
+
this for the live server and API demonstrations.
|
|
31
|
+
|
|
32
|
+
Before recording, confirm the exact model selector accepted on the machine:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
mlx-bun ls
|
|
36
|
+
mlx-bun fit Qwen3.8-27B --ctx 8192
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Start the demo server shortly before the live take if model loading or browser
|
|
40
|
+
placement would interrupt the opening. The visible command should still be the
|
|
41
|
+
real command:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
mlx-bun serve Qwen3.8-27B
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use a fresh chat and disable notifications. Set the terminal to at least 18 pt.
|
|
48
|
+
Keep the browser and terminal at the same zoom level throughout.
|
|
49
|
+
|
|
50
|
+
### Shot-by-shot script
|
|
51
|
+
|
|
52
|
+
#### 0:00 to 0:12, cold open
|
|
53
|
+
|
|
54
|
+
**Picture**
|
|
55
|
+
|
|
56
|
+
Close shot of an empty terminal. Type `mlx-bun serve Qwen3.8-27B`. Cut directly
|
|
57
|
+
to the browser as the chat opens. Ask a short question whose answer starts
|
|
58
|
+
quickly.
|
|
59
|
+
|
|
60
|
+
Suggested prompt:
|
|
61
|
+
|
|
62
|
+
> Why can a 27-billion-parameter model fit on this 32 GB Mac? Answer in three
|
|
63
|
+
> sentences and show the memory arithmetic.
|
|
64
|
+
|
|
65
|
+
Do not wait for the full answer. Once several words appear, cut to camera.
|
|
66
|
+
|
|
67
|
+
**Voiceover**
|
|
68
|
+
|
|
69
|
+
> That is a 27-billion-parameter Qwen model running locally on a Mac. There is no
|
|
70
|
+
> Python server behind it, no API key, and no request leaving the machine. One
|
|
71
|
+
> command started the model, the chat interface, and an API that existing tools
|
|
72
|
+
> can use. This is mlx-bun.
|
|
73
|
+
|
|
74
|
+
**On-screen text**
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
<machine> · Qwen3.8-27B · 20.4 GB weights
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### 0:12 to 0:35, state the problem
|
|
81
|
+
|
|
82
|
+
**Picture**
|
|
83
|
+
|
|
84
|
+
Piece to camera. Brief cuts to a deliberately restrained list of familiar setup
|
|
85
|
+
artifacts: a Python environment, package installation, a server command, and a
|
|
86
|
+
model configuration file. Do not use fake error messages.
|
|
87
|
+
|
|
88
|
+
**Dialogue**
|
|
89
|
+
|
|
90
|
+
> Local AI already works on a Mac. The rough part is everything around the
|
|
91
|
+
> model. You choose a model that might fit, assemble a Python environment,
|
|
92
|
+
> start a server, and then configure the application that was supposed to use
|
|
93
|
+
> it.
|
|
94
|
+
>
|
|
95
|
+
> I wanted the default path to feel like installing software. Run one command,
|
|
96
|
+
> get a useful local assistant, and keep the controls available when you
|
|
97
|
+
> actually need them.
|
|
98
|
+
|
|
99
|
+
#### 0:35 to 1:10, show the real first-run path
|
|
100
|
+
|
|
101
|
+
**Picture**
|
|
102
|
+
|
|
103
|
+
Show the installation command in the clean terminal. Use a pre-recorded,
|
|
104
|
+
time-compressed capture of the first run beside it. Label the time compression.
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
curl -fsSL https://mlx-bun.dev/install.sh | sh
|
|
108
|
+
mlx-bun
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Show the starter model becoming ready. Then cut to the explicit Qwen download
|
|
112
|
+
command used before the main recording:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
mlx-bun get mlx-community/Qwen3.8-27B-OptiQ-4bit
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Voiceover**
|
|
119
|
+
|
|
120
|
+
> The installer downloads a signed, notarized executable. On a fresh machine,
|
|
121
|
+
> bare `mlx-bun` downloads a sub-gigabyte MiniCPM5 starter so the first chat can
|
|
122
|
+
> begin quickly.
|
|
123
|
+
>
|
|
124
|
+
> This episode is about a much larger model, Qwen3.8-27B. Its quantized weights
|
|
125
|
+
> are 20.4 gigabytes, so I downloaded them before recording. I do not think
|
|
126
|
+
> watching a twenty-gigabyte progress bar would improve the video.
|
|
127
|
+
|
|
128
|
+
**Verification note**
|
|
129
|
+
|
|
130
|
+
Capture this section again if first-run behavior changes. Do not narrate the
|
|
131
|
+
device-aware model selection described in the product roadmap until that lookup
|
|
132
|
+
is implemented.
|
|
133
|
+
|
|
134
|
+
#### 1:10 to 1:55, one process with three ways in
|
|
135
|
+
|
|
136
|
+
**Picture**
|
|
137
|
+
|
|
138
|
+
Use a simple screen composition with the running `mlx-bun` process in the
|
|
139
|
+
center. Reveal the chat UI, an HTTP request, and a TypeScript file around it.
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
Chat UI
|
|
143
|
+
\
|
|
144
|
+
mlx-bun + MLX + Metal
|
|
145
|
+
/ \
|
|
146
|
+
OpenAI-compatible API TypeScript library
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Dialogue**
|
|
150
|
+
|
|
151
|
+
> The visible chat is only one way into the runtime. The same process exposes an
|
|
152
|
+
> OpenAI-compatible API, so applications that already speak that protocol can
|
|
153
|
+
> point at localhost. A Bun application can also call the generation library
|
|
154
|
+
> directly without running a sidecar server.
|
|
155
|
+
>
|
|
156
|
+
> Those are different entry points into the same native runtime. The model
|
|
157
|
+
> weights stay on the Mac, and MLX runs the computation through Metal on the
|
|
158
|
+
> Apple Silicon GPU.
|
|
159
|
+
|
|
160
|
+
#### 1:55 to 2:35, prove the API claim
|
|
161
|
+
|
|
162
|
+
**Picture**
|
|
163
|
+
|
|
164
|
+
Keep the server log visible on the left. Run this request on the right:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
curl http://localhost:8080/v1/chat/completions \
|
|
168
|
+
-H 'Content-Type: application/json' \
|
|
169
|
+
-d '{
|
|
170
|
+
"messages": [{
|
|
171
|
+
"role": "user",
|
|
172
|
+
"content": "Name two reasons unified memory helps local inference."
|
|
173
|
+
}],
|
|
174
|
+
"max_tokens": 96,
|
|
175
|
+
"temperature": 0
|
|
176
|
+
}'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Format or crop the JSON response so the answer and usage fields remain legible.
|
|
180
|
+
|
|
181
|
+
**Voiceover**
|
|
182
|
+
|
|
183
|
+
> This is a normal chat-completions request. Change an OpenAI client base URL to
|
|
184
|
+
> `localhost:8080`, and the request goes to the model loaded by mlx-bun. There
|
|
185
|
+
> is no translation service on the internet and no account involved.
|
|
186
|
+
|
|
187
|
+
Do not say every OpenAI feature is implemented. The claim is protocol
|
|
188
|
+
compatibility for the documented API, not the entirety of OpenAI's platform.
|
|
189
|
+
|
|
190
|
+
#### 2:35 to 3:25, explain why Bun matters
|
|
191
|
+
|
|
192
|
+
**Picture**
|
|
193
|
+
|
|
194
|
+
Piece to camera, followed by a clean runtime diagram. Avoid scrolling through
|
|
195
|
+
large source files here.
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
TypeScript application
|
|
199
|
+
↓
|
|
200
|
+
Bun
|
|
201
|
+
↓
|
|
202
|
+
mlx-bun native bindings
|
|
203
|
+
↓
|
|
204
|
+
MLX
|
|
205
|
+
↓
|
|
206
|
+
Apple Silicon GPU
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Dialogue**
|
|
210
|
+
|
|
211
|
+
> Most MLX applications are written in Python. mlx-bun calls MLX's native C API
|
|
212
|
+
> from Bun instead.
|
|
213
|
+
>
|
|
214
|
+
> It loads safetensors weights, builds the model graph, manages the attention
|
|
215
|
+
> cache, samples tokens, and serves requests from TypeScript. It does not start
|
|
216
|
+
> Python in the background.
|
|
217
|
+
>
|
|
218
|
+
> That does not make GPU matrix multiplication faster because it passed through
|
|
219
|
+
> JavaScript. The GPU still sets that limit. It does make the application easier
|
|
220
|
+
> to distribute, and it gives the server less work to do around each model step.
|
|
221
|
+
|
|
222
|
+
#### 3:25 to 4:15, show the finite-matrix idea
|
|
223
|
+
|
|
224
|
+
**Picture**
|
|
225
|
+
|
|
226
|
+
Run the fit command. Hold on the result long enough to read memory use, safe
|
|
227
|
+
context, and predicted speed. Use the exact live output rather than rebuilding
|
|
228
|
+
it for the edit.
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
mlx-bun fit Qwen3.8-27B --ctx 8192
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Dialogue**
|
|
235
|
+
|
|
236
|
+
> The project makes one opinionated bet. Local AI on a Mac is a finite problem.
|
|
237
|
+
> Apple ships a known set of chips and memory sizes. mlx-bun supports a curated
|
|
238
|
+
> set of model families. We can measure those combinations instead of asking
|
|
239
|
+
> every user to become a model-serving specialist.
|
|
240
|
+
>
|
|
241
|
+
> The `fit` command estimates whether a model and context length are safe before
|
|
242
|
+
> loading the weights. The default path can be simple because the measurements
|
|
243
|
+
> and the failure checks live underneath it.
|
|
244
|
+
|
|
245
|
+
Do not claim that automatic device-specific recommendation is complete. Today,
|
|
246
|
+
the fit contract is the concrete proof of this idea.
|
|
247
|
+
|
|
248
|
+
#### 4:15 to 5:20, correctness before speed
|
|
249
|
+
|
|
250
|
+
**Picture**
|
|
251
|
+
|
|
252
|
+
Show a two-column comparison titled `Python oracle` and `mlx-bun`. Animate two
|
|
253
|
+
small arrays of identical hexadecimal or decimal values. Follow with a quick
|
|
254
|
+
shot of a parity test name from the repository.
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
same model + same input
|
|
258
|
+
|
|
259
|
+
mlx-lm logits = mlx-bun logits
|
|
260
|
+
bit-exact
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Dialogue**
|
|
264
|
+
|
|
265
|
+
> Reimplementing a model runtime creates a nasty testing problem. Wrong models
|
|
266
|
+
> still write convincing sentences.
|
|
267
|
+
>
|
|
268
|
+
> So I do not use "the answer looked reasonable" as the correctness test. For
|
|
269
|
+
> the compatibility path, the Python MLX implementation is the oracle. The same
|
|
270
|
+
> weights and inputs go through both runtimes, and the tests compare the logits
|
|
271
|
+
> before a token is selected.
|
|
272
|
+
>
|
|
273
|
+
> On the validated paths, those logits match bit for bit. That catches errors in
|
|
274
|
+
> attention masks, normalization, position encoding, cache updates, and model
|
|
275
|
+
> loading that a chat demo can easily hide.
|
|
276
|
+
>
|
|
277
|
+
> Compatibility work has a strict order here. Match the reference first. Then
|
|
278
|
+
> measure any optimization against that baseline.
|
|
279
|
+
|
|
280
|
+
#### 5:20 to 6:20, measured performance
|
|
281
|
+
|
|
282
|
+
**Picture**
|
|
283
|
+
|
|
284
|
+
Display one benchmark card. Do not show the entire results table.
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
Qwen3.8-27B · <machine> · warm HTTP serving
|
|
288
|
+
Preflight-gated run · 2026-08-22 · Bun 1.4.0
|
|
289
|
+
|
|
290
|
+
short decode decode at 15.8k warm TTFT aggregate ×4
|
|
291
|
+
mlx-bun 18.6 tok/s 17.0 tok/s 116 ms 19.5 tok/s
|
|
292
|
+
mlx-lm 16.5 tok/s 14.8 tok/s 284 ms 18.6 tok/s
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Add a small source line: `benchmarks/RESULTS.md`.
|
|
296
|
+
|
|
297
|
+
**Dialogue**
|
|
298
|
+
|
|
299
|
+
> Here is a measured comparison on this Mac. Same Qwen model snapshot, same
|
|
300
|
+
> machine state, warm HTTP serving.
|
|
301
|
+
>
|
|
302
|
+
> On the short request, mlx-bun generated 18.6 tokens per second. mlx-lm
|
|
303
|
+
> generated 16.5. At about 15,800 tokens of context, the result was 17.0 versus
|
|
304
|
+
> 14.8. Warm time to first token was 116 milliseconds for mlx-bun and 284 for
|
|
305
|
+
> mlx-lm.
|
|
306
|
+
>
|
|
307
|
+
> This is the kind of comparison I care about. It uses the server path an
|
|
308
|
+
> application actually hits, the same weights, and a machine that passed the
|
|
309
|
+
> benchmark preflight. The GPU sets the speed limit, but the runtime still has
|
|
310
|
+
> to reach that limit without wasting memory or time around each token.
|
|
311
|
+
|
|
312
|
+
**Editorial note**
|
|
313
|
+
|
|
314
|
+
These are controlled same-machine results. Put the run date and Bun version on screen.
|
|
315
|
+
If a fresh cleared-machine benchmark is available before publication, replace
|
|
316
|
+
the full card and narration together. Never mix live numbers with this table.
|
|
317
|
+
|
|
318
|
+
#### 6:20 to 7:05, show the larger project without losing focus
|
|
319
|
+
|
|
320
|
+
**Picture**
|
|
321
|
+
|
|
322
|
+
Use four quick clips, about three seconds each:
|
|
323
|
+
|
|
324
|
+
1. An image input in chat.
|
|
325
|
+
2. The Markdown memory directory.
|
|
326
|
+
3. A training progress display.
|
|
327
|
+
4. A benchmark or parity result from the lab.
|
|
328
|
+
|
|
329
|
+
Return to camera before naming more features.
|
|
330
|
+
|
|
331
|
+
**Dialogue**
|
|
332
|
+
|
|
333
|
+
> Serving is the base of the project, not its boundary. The same binary also has
|
|
334
|
+
> image and video input on supported Qwen models, a local Markdown memory, LoRA
|
|
335
|
+
> training, and a lab for decoding and quantization experiments.
|
|
336
|
+
>
|
|
337
|
+
> I am not going to explain those in a thirty-second feature list. Each one has
|
|
338
|
+
> an implementation story, measurements, and a few failures worth discussing.
|
|
339
|
+
> Those will be separate videos.
|
|
340
|
+
|
|
341
|
+
#### 7:05 to 7:50, close and set up episode 2
|
|
342
|
+
|
|
343
|
+
**Picture**
|
|
344
|
+
|
|
345
|
+
Return to the original chat. Show the local URL, server process, and activity
|
|
346
|
+
monitor GPU history in quick succession. End on the repository and site URLs.
|
|
347
|
+
|
|
348
|
+
**Dialogue**
|
|
349
|
+
|
|
350
|
+
> mlx-bun is my attempt to make local AI on Apple Silicon behave like software
|
|
351
|
+
> you can install, use, and build on.
|
|
352
|
+
>
|
|
353
|
+
> The short version is one command. Underneath it is a TypeScript model runtime,
|
|
354
|
+
> native bindings, model-family ports, memory accounting, and a lot of parity
|
|
355
|
+
> tests.
|
|
356
|
+
>
|
|
357
|
+
> In the next video, I am going to trace one generated token through that whole
|
|
358
|
+
> path, from the TypeScript call to MLX and the GPU, then back to the response.
|
|
359
|
+
> That is where the project gets strange.
|
|
360
|
+
|
|
361
|
+
**On-screen text**
|
|
362
|
+
|
|
363
|
+
```text
|
|
364
|
+
mlx-bun.dev
|
|
365
|
+
github.com/joshuarossi/mlx-bun
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Required captures
|
|
369
|
+
|
|
370
|
+
- Clean installer command.
|
|
371
|
+
- Time-compressed first run with MiniCPM5 becoming ready.
|
|
372
|
+
- The explicit Qwen3.8-27B download command or a short time-compressed capture.
|
|
373
|
+
- `mlx-bun serve Qwen3.8-27B` startup and automatic browser open.
|
|
374
|
+
- A short streamed chat response.
|
|
375
|
+
- A successful `/v1/chat/completions` curl request.
|
|
376
|
+
- Live `mlx-bun fit Qwen3.8-27B --ctx 8192` output.
|
|
377
|
+
- One real parity test or stored oracle comparison.
|
|
378
|
+
- Four brief clips for vision, memory, training, and benchmark evidence.
|
|
379
|
+
- Repository and website closing shot.
|
|
380
|
+
|
|
381
|
+
### Graphics to prepare
|
|
382
|
+
|
|
383
|
+
Only three graphics are needed:
|
|
384
|
+
|
|
385
|
+
1. The three-entry-point runtime diagram.
|
|
386
|
+
2. The bit-exact oracle comparison.
|
|
387
|
+
3. The dated Qwen3.8-27B benchmark card.
|
|
388
|
+
|
|
389
|
+
Keep them monochrome except for one mlx-bun accent color. Use the same terminal
|
|
390
|
+
font in the diagrams and screen recordings.
|
|
391
|
+
|
|
392
|
+
### Recording-day checks
|
|
393
|
+
|
|
394
|
+
- Confirm the current release installation command.
|
|
395
|
+
- Confirm the Qwen3.8-27B selector and exact displayed model name.
|
|
396
|
+
- Confirm port 8080 is unused before the take.
|
|
397
|
+
- Confirm no private paths, tokens, conversations, or model-cache usernames are
|
|
398
|
+
visible.
|
|
399
|
+
- Confirm first-run behavior still matches the narration.
|
|
400
|
+
- Confirm the API request and response fields against the current reference
|
|
401
|
+
docs.
|
|
402
|
+
- Confirm the benchmark card still matches `benchmarks/RESULTS.md`.
|
|
403
|
+
- Record room tone and five seconds of clean terminal footage for edits.
|
|
404
|
+
- Capture every important terminal action twice.
|
|
405
|
+
|
|
406
|
+
### Episode 2 handoff
|
|
407
|
+
|
|
408
|
+
The promised follow-up is: **What happens when mlx-bun generates one token?**
|
|
409
|
+
|
|
410
|
+
Trace this path without turning the episode into a source-tree tour:
|
|
411
|
+
|
|
412
|
+
```text
|
|
413
|
+
request
|
|
414
|
+
→ tokenizer
|
|
415
|
+
→ model forward pass
|
|
416
|
+
→ MLX lazy graph evaluation
|
|
417
|
+
→ Metal execution
|
|
418
|
+
→ GPU sampling
|
|
419
|
+
→ one token returned to Bun
|
|
420
|
+
→ streamed protocol event
|
|
421
|
+
```
|
package/docs/reference/cli.md
CHANGED
|
@@ -35,7 +35,7 @@ Common flags (full list in [server-config.md](server-config.md)):
|
|
|
35
35
|
|---|---|
|
|
36
36
|
| `--host <addr>` | Interface to bind (default `127.0.0.1`, loopback only; `0.0.0.0` to expose) |
|
|
37
37
|
| `--port <n>` | Listen port (default 8080) |
|
|
38
|
-
| `--memory-budget <GB>` |
|
|
38
|
+
| `--memory-budget <GB>` | Admission ceiling for requests (bills the active `--kv-quant` scheme; clamps `max_tokens`, 400s only prompts that leave no room — never refuses to start) |
|
|
39
39
|
| `--kv-budget <GB>` | Aggregate KV budget across concurrent batch rows: over-budget joiners queue until rows finish; a request over the budget alone is rejected (off unless set) |
|
|
40
40
|
| `--prompt-cache <GB>` | RAM prefix-KV cache, byte-capped LRU (default 8; `0` disables). Non-consuming prefix sharing: a hit clones instead of consuming the donor entry |
|
|
41
41
|
| `--isolate` | Run the inference engine as a crash-isolated child process on a unix socket; this process becomes a pure reverse-proxy (instant under GPU load, auto-respawns on engine crash) — default off ([runtime-isolation.md](../design/runtime-isolation.md)) |
|
|
@@ -49,12 +49,12 @@ Common flags (full list in [server-config.md](server-config.md)):
|
|
|
49
49
|
| `--paged-kv-block-size <n>` | Tokens per KV block (default 256 = the plain cache's growth step; `--paged-kv` only) |
|
|
50
50
|
| `--adapter <dir>` | Mount a LoRA adapter at startup (`--adapter-path` accepted as the mlx_lm.server alias) |
|
|
51
51
|
| `--draft-model <path\|query>` | Speculative decoding: a drafter proposes, the main model verifies — exact results, faster decode when drafts land. The artifact's kind is auto-detected: a full same-tokenizer model (mlx_lm.server parity), a Gemma `-assistant` KV-borrowing drafter, a DSpark checkpoint trained here, or one of DeepSeek's released DSpark drafters (DeepSpec `Gemma4DSparkModel`, e.g. `dspark_gemma4_12b_block7`). Serial lane only: with `--batch N` a mounted draft routes every request serial |
|
|
52
|
-
| `--draft-kind <kind>` | Override draft-artifact detection: `two-model` \| `assistant` \| `dspark` \| `deepspec` \| `ngram` (default: auto). `ngram` is MODEL-FREE prompt lookup — no `--draft-model` (mounting one alongside it is refused): drafts are copied from the request's own prompt+generation whenever its trailing tokens have occurred earlier in that stream, verified by the target like any other draft, so results stay exact at any temperature. Zero weights, zero memory; best on agentic/RAG/code-edit traffic that re-emits spans already in context (prior art: prompt-lookup decoding / vLLM's `ngram` proposer) |
|
|
52
|
+
| `--draft-kind <kind>` | Override draft-artifact detection: `two-model` \| `assistant` \| `dspark` \| `deepspec` \| `mtp` \| `ngram` (default: auto). `mtp` is a NATIVE multi-token-prediction head split from the target's own release (e.g. `mlx-community/Qwen3.8-27B-MTP-bf16`; auto-detected from a `*_mtp` `model_type`) — it binds the target's embeddings/lm-head and taps its pre-final-norm hiddens, and the serve loop rolls the target's recurrent DeltaNet caches back across rejected drafts via bit-exact snapshot/replay. `--draft-kind mtp` WITHOUT `--draft-model` resolves the companion from the artifact's own `mtp/` subfolder (single-repo bundles, e.g. the TQ releases) and refuses with a clear error when the model bundles none. `ngram` is MODEL-FREE prompt lookup — no `--draft-model` (mounting one alongside it is refused): drafts are copied from the request's own prompt+generation whenever its trailing tokens have occurred earlier in that stream, verified by the target like any other draft, so results stay exact at any temperature. Zero weights, zero memory; best on agentic/RAG/code-edit traffic that re-emits spans already in context (prior art: prompt-lookup decoding / vLLM's `ngram` proposer) |
|
|
53
53
|
| `--num-draft-tokens <n>` | Drafts per verify round (default 3; `ngram` defaults to 10 — drafting is free; a DSpark draft pins to its trained block width) |
|
|
54
54
|
| `--ngram-max <k>` / `--ngram-min <k>` | Prompt-lookup match-window bounds, `--draft-kind ngram` only: the longest/shortest trailing k-gram searched (defaults 3 / 1, the reference values) |
|
|
55
55
|
| `--mtp on\|off` | GLM-5.2 checkpoint-native MTP (default on). Native MTP uses the exact serial verify lane; `off` enables ordinary continuous batching (batched per-row MTP is post-release) |
|
|
56
56
|
| `--context-length <n>` | GLM-5.2 context reserved by the header-only resource equation (default 4096) |
|
|
57
|
-
| `--batch <n>` | Continuous-
|
|
57
|
+
| `--batch <n>` | Continuous-scheduler concurrency cap, mlx-lm parity at the same B (default 8; a lone admitted request uses the gated B=1 fast path, while `--batch 1` pins the preserved strict serial executor) |
|
|
58
58
|
| `--temperature` / `--top-p` / `--top-k` / `--max-tokens` | Server-wide sampling defaults (per-request fields still win; GLM-5.2 defaults to the planned 128 generated tokens) |
|
|
59
59
|
| `--l1` / `--l2` | Parity tier alias: bit-exact to mlx-lm / bit-exact to mlx-optiq. **No tier = `--l1`** (the default since 2026-07-05 — output-changing levers are opt-in until they beat the L1 baseline in a paired A/B). Each expands to per-fork flags (`--compiled-decode`, `--compiled-activations`, `--fused-sdpa`, `--kv-quant`); a fork flag overrides one. `--l3` was removed 2026-07-05 and now errors (the Lab replaces it — [unified-engine-frontier-plan.md](../design/unified-engine-frontier-plan.md)). See [server-config.md](server-config.md#fidelity-tiers-and-the-decode-route---l1----l2). |
|
|
60
60
|
| `--allow-private-media` | Let `image_url`/`audio_url` parts fetch from private/loopback/link-local hosts (blocked by default — SSRF guard; the 10 s timeout and 64 MB cap on remote media apply either way) |
|
|
@@ -170,11 +170,15 @@ mlx-bun gc --yes # delete
|
|
|
170
170
|
|
|
171
171
|
Deterministic memory assessment: does it fit, what's the max context, predicted
|
|
172
172
|
tok/s. Weights bytes from safetensors headers, KV bytes/token from the config,
|
|
173
|
-
calibrated prefill transient, wired-memory ceiling.
|
|
173
|
+
calibrated prefill transient, wired-memory ceiling. `--kv-quant` mirrors serve's
|
|
174
|
+
flag: it bills the quantized cache at its true bytes/element, so the reported
|
|
175
|
+
window matches what serving with the same flag admits (a 4-bit cache holds
|
|
176
|
+
~3.5× the context of bf16 in the same budget).
|
|
174
177
|
|
|
175
178
|
```sh
|
|
176
179
|
mlx-bun fit gemma --ctx 32768 # for this machine
|
|
177
180
|
mlx-bun fit gemma --ctx 8192 --skus # across the Apple Silicon lineup
|
|
181
|
+
mlx-bun fit qwen --kv-quant 4 # window with a 4-bit-quantized KV cache
|
|
178
182
|
```
|
|
179
183
|
|
|
180
184
|
The direct Colibri GLM-5.2 artifact is handled by its streamed-runtime
|
|
@@ -235,8 +239,15 @@ MLX snapshot — uniform 4/8-bit, or mixed-precision via `--target-bpw`
|
|
|
235
239
|
```sh
|
|
236
240
|
mlx-bun convert Qwen/Qwen3-4B -q # uniform 4-bit
|
|
237
241
|
mlx-bun convert Qwen/Qwen3-4B --target-bpw 4.5 # mixed precision
|
|
242
|
+
mlx-bun convert ./qwen3.5-bf16 -q --rotate-weights # fold then quantize
|
|
238
243
|
```
|
|
239
244
|
|
|
245
|
+
`--rotate-weights` makes the offline rotation part of the same conversion
|
|
246
|
+
pipeline and records its recipe in `optiq_metadata.json`. The adapter is
|
|
247
|
+
selected from the model/tensor schema (Llama, Qwen3.5 trunk, or Qwen MTP);
|
|
248
|
+
`--rotation-seed` defaults to `42`. Folding requires full-precision source
|
|
249
|
+
weights and an MTP companion must use the same seed as its trunk.
|
|
250
|
+
|
|
240
251
|
### `upload` — push to the Hugging Face Hub
|
|
241
252
|
|
|
242
253
|
Native push-to-hub, no Python: creates the repo if needed, uploads via the
|
|
@@ -15,6 +15,7 @@ tarball (~73 MB compressed, ~228 MB installed):
|
|
|
15
15
|
| `mlx-bun` | the CLI/server (`bun build --compile`), ~61 MB |
|
|
16
16
|
| `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib` | MLX native runtime |
|
|
17
17
|
| `libmlx_bun_expert_io.dylib` | bounded native expert-streaming helper required by direct Colibri GLM-5.2 |
|
|
18
|
+
| `mlx-bun-frame-extract` | AVFoundation frame-extraction sidecar for video input (darwin-native codecs, the afconvert doctrine) |
|
|
18
19
|
| `mlx.metallib` | Metal kernels (~150 MB — the bulk) |
|
|
19
20
|
| pi assets | `photon_rs_bg.wasm`, `theme/`, `assets/`, `export-html/`, `native/`, `package.json`, `CHANGELOG.md` |
|
|
20
21
|
|
|
@@ -20,7 +20,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
|
|
|
20
20
|
| Raw text completions (`/v1/completions`) | on | both | — | — |
|
|
21
21
|
| Anthropic Messages (`/v1/messages`) | on | both | — | — |
|
|
22
22
|
| OpenAI Responses shim (`/v1/responses`) | on | both | — | — |
|
|
23
|
-
| Continuous batching (mlx-lm B
|
|
23
|
+
| Continuous batching (mlx-lm parity at the same B) | **on** — cap 8 (default flipped 2026-07-05; a lone admitted request uses the gated B=1 fast path and concurrent requests can form B=N; `--batch 1` pins the strict serial executor) | batch | L1 | `--batch <n>` |
|
|
24
24
|
| Prompt cache (prefix KV reuse) | on, 8 GB | both | — | `--prompt-cache <GB>` (0 = off) |
|
|
25
25
|
| **SSD KV cold tier** (cache survives eviction + restarts; v3 includes GLM compressed MLA/DSA state without full-K/V reconstruction) | off | both | — | `--ssd-cache <dir>` (+ `-max`, `-verify`, `-demote-idle <sec>` — default 300s once `--ssd-cache` is on, `0` disables) |
|
|
26
26
|
| **Runtime isolation** (engine runs as a crash-isolated CHILD process behind a reverse-proxy parent; UI stays instant under GPU load and survives engine crashes — [runtime-isolation.md](../design/runtime-isolation.md)) | off | both | — | `--isolate` |
|
|
@@ -51,6 +51,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
|
|
|
51
51
|
| Quantized KV × speculative decoding (any axis: uniform / config / turbo) | KV scheme wins — drafted requests decode serially WITHOUT speculation (spec lane is bf16-KV-only in v1; startup warning) | serial | — | omit `--kv-quant` to speculate |
|
|
52
52
|
| Tool calling (Gemma sentinel / CPM+Qwen XML / GLM `arg_key`+`arg_value`) + `role:"tool"` loops | on | both | — | request `tools` |
|
|
53
53
|
| Vision (`image_url` parts; PNG/JPEG/HEIC/AVIF/WebP/TIFF/GIF/BMP) | on (models with a tower); remote fetches refuse private/loopback/link-local hosts by default (SSRF guard) | serial | L1/L2 | `--allow-private-media` / `MLX_BUN_ALLOW_PRIVATE_MEDIA=1` re-permits LAN hosts |
|
|
54
|
+
| **Video input** (`video_url`/`video` parts; mp4/mov H.264/HEVC/ProRes/… via the AVFoundation sidecar `mlx-bun-frame-extract`; 2 fps sampling, ≤768 frames, 256 MB body cap; never combines with audio) | on (Qwen3.5-family models); same SSRF guard | serial | mlx-vlm oracle (frames pipeline bit-exact; tests/qwen38-vision.test.ts) | `--allow-private-media` for LAN hosts |
|
|
54
55
|
| **Audio input** (`input_audio`/`audio`/`audio_url` parts; WAV native, mp3/m4a/flac/ogg/aiff via CoreAudio; ≤30 s / 750 tokens per clip; mixes with images) | on (models with `audio_config` + sidecar tower: e4b); remote fetches refuse private/loopback/link-local hosts by default (SSRF guard) | serial³ | L2 (greedy stream EXACT vs the optiq internal model) | `--allow-private-media` / `MLX_BUN_ALLOW_PRIVATE_MEDIA=1` re-permits LAN hosts |
|
|
55
56
|
| LoRA adapters (mount at start / hot-swap at runtime) | off | serial | — | `--adapter <dir>`, `POST /v1/adapters` |
|
|
56
57
|
| Sampling: temperature / top-p / top-k / min-p / XTC / logit_bias / presence+frequency+repetition penalties | per-request | both | L1 (mlx-lm-faithful) | request fields / server defaults |
|
|
@@ -69,6 +70,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
|
|
|
69
70
|
| MiniCPM5 (cpm5) | ✅ L1/L2 | ✅ | the starter model |
|
|
70
71
|
| Gemma 4 (1B/e4b/12B/26B, + vision e4b/12B, + audio e4b) | ✅ L1/L2 | ✅ | sliding+full interleaved; MoE 26B |
|
|
71
72
|
| Qwen3.5 (gated-DeltaNet hybrid) | ✅ L1/L2 | ✅ (SSM path) | `MLX_BUN_BATCH_SSM=0` reverts |
|
|
73
|
+
| Qwen3.8-27B (same qwen3_5 graph) | ✅ L1 (no L2 oracle) | ✅ (SSM path) | thinking depths + preserve_thinking; native MTP head mounts via `--draft-model` (DeltaNet spec rollback = snapshot/replay, lossless-gated; quiet-box A/B: 0.82× — correct but slower, opt-in); **vision (images) AND video SERVE** — bf16 tower sidecar + mRoPE + embed splice, oracle = mlx-vlm on pinned mlx (preprocessor/tower/positions bit-exact, e2e token-exact on 2/3 fixtures, serve smokes green; tests/qwen38-vision.test.ts); video files decode via the shipped AVFoundation sidecar (`mlx-bun-frame-extract`, src/native/frame_extract.swift — 2 fps, ≤768 frames, temporal pairs, per-frame-group attention) |
|
|
72
74
|
| GLM-5.2 / Colibri (pre-release port gate) | ✅ chat/text, Messages, Responses, SSE, tools, grammar, logprobs, library/CLI | ✅ compressed MLA/DSA scheduler | native MTP defaults to serial+spec; `--mtp off` enables ordinary batching; artifact-aware CLI/API/status `fit` and live main/MTP expert-tier telemetry; embeddings, vision/audio, adapters, and training are explicitly unsupported; per-row batched MTP is post-release |
|
|
73
75
|
| DiffusionGemma-26B (non-autoregressive) | ✅ (own engine) | — serial always | first bit-exact non-AR port |
|
|
74
76
|
| Tier-0 universal (llama/qwen2/qwen3/olmo2/…, 11 archs) | ✅ L1 | ✅ plain full-attention archs² | gemma2-family/sliding universal → serial |
|
|
@@ -8,7 +8,7 @@ admission — is importable directly into a Bun process. Published as
|
|
|
8
8
|
|
|
9
9
|
One rule everywhere: **one generation at a time per process** (one GPU).
|
|
10
10
|
The server serializes through a queue (or, under `--batch N`, its
|
|
11
|
-
continuous
|
|
11
|
+
continuous scheduler — a server scheduling mechanism, not a library
|
|
12
12
|
surface); direct library callers must do the same.
|
|
13
13
|
|
|
14
14
|
## Quick start
|
|
@@ -49,6 +49,46 @@ Ordinary safetensors loading is lazy (mmap + mlx native loader). GLM-5.2 first
|
|
|
49
49
|
runs its header-only exact process equation, then opens the bounded Colibri
|
|
50
50
|
resident/expert tiers; impossible plans fail before either tier is committed.
|
|
51
51
|
|
|
52
|
+
## Model profiles
|
|
53
|
+
|
|
54
|
+
`openModel()` and `loadContext()` resolve a declared model profile before they
|
|
55
|
+
open weights. `loadContext()` exposes that decision as `ctx.profile`, including
|
|
56
|
+
the exact external fingerprint when the path is an immutable Hugging Face
|
|
57
|
+
snapshot:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const ctx = await loadContext(dir);
|
|
61
|
+
console.log(ctx.profile.profile.id);
|
|
62
|
+
console.log(ctx.profile.artifact.fingerprint); // hf:<org>/<repo>@<revision> or null
|
|
63
|
+
console.log(ctx.profile.profile.fidelity);
|
|
64
|
+
console.log(ctx.profile.profile.execution); // loader + graph + loop + specialization
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Direct library construction can resolve and pass the same immutable value:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { loadModelConfig, Weights, resolveModelProfile, createModel } from "mlx-bun";
|
|
71
|
+
|
|
72
|
+
const config = await loadModelConfig(dir);
|
|
73
|
+
const profile = resolveModelProfile(config);
|
|
74
|
+
const model = createModel(await Weights.open(dir), config, profile);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For a local artifact that is not stored under an immutable HF snapshot path, an
|
|
78
|
+
application may supply its own provenance fingerprint and exact declaration via
|
|
79
|
+
`resolveModelProfile(config, { artifactFingerprint, artifactProfiles })`.
|
|
80
|
+
Declarations use the exported `ArtifactModelProfile`, `FidelityTarget`,
|
|
81
|
+
`EngineCapability`, and `ModelExecutionComposition` types. The resolver checks
|
|
82
|
+
the declared config fingerprint (compute it with exported
|
|
83
|
+
`configFingerprint(config)`) and required engine capabilities. An exact match
|
|
84
|
+
that fails either check refuses instead of taking the family or generic
|
|
85
|
+
fallback.
|
|
86
|
+
|
|
87
|
+
Profile selection is limited to model construction. Generation options remain
|
|
88
|
+
authoritative: passing mixed `kvConfig`, TurboQuant KV, adapters, grammar,
|
|
89
|
+
sampling, or an explicitly configured draft method is not rewritten by the
|
|
90
|
+
profile.
|
|
91
|
+
|
|
52
92
|
> **First run:** library consumers bypass the CLI's first-run step, so
|
|
53
93
|
> call `await ensureNativeRuntime()` once before constructing a model on
|
|
54
94
|
> a machine that may not have the MLX native runtime yet — it downloads
|
package/docs/reference/models.md
CHANGED
|
@@ -106,6 +106,39 @@ The artifact is an external MIT-licensed derivative of
|
|
|
106
106
|
weights. Model weights are not bundled with mlx-bun; review the artifact model
|
|
107
107
|
card before redistribution.
|
|
108
108
|
|
|
109
|
+
## Declared model profiles
|
|
110
|
+
|
|
111
|
+
Model loading resolves one immutable profile before weights are opened. A
|
|
112
|
+
profile names four things: the external artifact fingerprint when one is
|
|
113
|
+
known, its fidelity target, the engine capabilities it requires, and the
|
|
114
|
+
composed loader/model-graph/generation-loop path.
|
|
115
|
+
|
|
116
|
+
Exact artifact profiles outrank family profiles. The current exact declarations
|
|
117
|
+
are:
|
|
118
|
+
|
|
119
|
+
| profile | external artifact | fidelity | execution |
|
|
120
|
+
| --- | --- | --- | --- |
|
|
121
|
+
| `qwen3.8-27b-optiq-4bit` | `mlx-community/Qwen3.8-27B-OptiQ-4bit` revision `b04599de95d7a9bfbd7f208d347c0f10d9432a42` | L1: bit-exact mlx-lm | safetensors + dedicated Qwen3.5/3.8 graph + autoregressive loop |
|
|
122
|
+
| `glm5.2-colibri-int4-int8-mtp` | `mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp` revision `3cc8db99b1b13fc79325d987ba3c1c430766b3b8` | L3: measured, no matching tier oracle | Colibri container + dedicated GLM-5.2 graph + autoregressive loop |
|
|
123
|
+
|
|
124
|
+
The fingerprint is the Hugging Face repo plus immutable snapshot revision, so
|
|
125
|
+
moving the cache does not change it. A mutable alias such as `snapshots/staged`
|
|
126
|
+
or an arbitrary local directory is not treated as exact. Those artifacts use
|
|
127
|
+
the dedicated model-family profile when one matches, then the universal dense
|
|
128
|
+
profile when that architecture is supported. Unsupported architectures still
|
|
129
|
+
refuse with the existing targeted/generic support list.
|
|
130
|
+
|
|
131
|
+
Profiles select construction only. They do not enable, disable, or replace MTP,
|
|
132
|
+
mixed-precision KV from `kv_config.json`, TurboQuant KV, adapters, grammar, or
|
|
133
|
+
sampling. Those methods remain explicit flags/request fields or documented
|
|
134
|
+
defaults. If an exact profile requires a capability the running engine does not
|
|
135
|
+
have, loading refuses; it never downgrades to another model path.
|
|
136
|
+
|
|
137
|
+
Fidelity labels mean L1 = bit-exact mlx-lm, L2 = bit-exact mlx-optiq, and L3 =
|
|
138
|
+
measured evidence without a matching oracle. Model profiles do not imply that a
|
|
139
|
+
quantized artifact retains the base model's benchmark score; quality evidence
|
|
140
|
+
belongs to that exact artifact.
|
|
141
|
+
|
|
109
142
|
## scan + the registry
|
|
110
143
|
|
|
111
144
|
`mlx-bun scan` walks `models--*/snapshots/*` reading only `config.json`
|