mlx-bun 0.0.10 → 0.0.12
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 +107 -32
- package/THIRD_PARTY_LICENSES.md +10 -0
- package/docs/archive/mlx-bun-lab-report.html +275 -0
- package/docs/archive/wwdc-mlx-bun.html +848 -0
- package/docs/design/audio-input-plan.md +356 -0
- package/docs/design/batching-perf-path.md +58 -35
- package/docs/design/batching-v2-plan.md +23 -9
- package/docs/design/bucketing-stage.md +2 -1
- package/docs/design/colibri-glm52-port.md +1479 -0
- package/docs/design/compat-cli-surface-design.md +4 -3
- package/docs/design/decode-speed-program.md +172 -0
- package/docs/design/docs-reorg-plan.md +1 -1
- package/docs/design/dspark-serving-program.md +371 -0
- package/docs/design/dspark-speculative-decoding.md +167 -5
- package/docs/design/faithful-l1-consolidation.md +310 -0
- package/docs/design/generic-model-support.md +8 -5
- package/docs/design/grammar-spec-batching-integration.md +301 -0
- package/docs/design/minicpm5-decode-megakernel.md +16 -11
- package/docs/design/mlx-lm-tool-parity-plan.md +11 -1
- package/docs/design/omlx-adoption-map.md +14 -6
- package/docs/design/orpo-training.md +34 -30
- package/docs/design/paged-kv-cache.md +214 -0
- package/docs/design/parallel-slots.md +82 -49
- package/docs/design/parity-tier-dag.md +43 -33
- package/docs/design/pre-colibri-stabilization.md +329 -0
- package/docs/design/repo-cleanup-plan.md +189 -0
- package/docs/design/runtime-isolation.md +19 -3
- package/docs/design/segmented-backward-training.md +3 -2
- package/docs/design/ssd-kv-cold-tier.md +130 -0
- package/docs/design/structured-output.md +484 -0
- package/docs/design/the-dreaming-master-plan.md +2 -3
- package/docs/design/turboquant-kv.md +235 -0
- package/docs/design/unified-engine-frontier-plan.md +774 -0
- package/docs/design/web-chat-beat-matrix.md +315 -0
- package/docs/design/web-chat-redesign.md +1112 -0
- package/docs/investigations/colibri-oracle-pin.md +1284 -0
- package/docs/investigations/dspark-handoff.md +182 -16
- package/docs/investigations/indexshare-performance-spike.md +357 -0
- package/docs/investigations/lab-build-journal.md +2 -2
- package/docs/investigations/openwiki-evaluation.md +249 -0
- package/docs/planning/IDEAS.md +14 -0
- package/docs/planning/PRODUCT_ROADMAP.md +2 -3
- package/docs/planning/chat-ui-vision-memory-first.md +199 -0
- package/docs/planning/chat-ui-vision.md +50 -0
- package/docs/planning/memory-docs-and-dag-plan.md +15 -6
- package/docs/planning/release-notes-v0.0.11.md +239 -0
- package/docs/planning/release-notes-v0.0.12.md +80 -0
- package/docs/reference/cli.md +63 -18
- package/docs/reference/distribution.md +37 -6
- package/docs/reference/embedding.md +40 -16
- package/docs/reference/features-matrix.md +99 -0
- package/docs/reference/library-api.md +69 -20
- package/docs/reference/memory.md +26 -6
- package/docs/reference/models.md +60 -3
- package/docs/reference/orpo-quickstart.md +3 -4
- package/docs/reference/server-api.md +717 -24
- package/docs/reference/server-config.md +265 -129
- package/docs/reference/training.md +24 -16
- package/package.json +5 -3
- package/src/anthropic.ts +67 -44
- package/src/audio/conformer.ts +647 -0
- package/src/audio/decode.ts +133 -0
- package/src/audio/features.ts +202 -0
- package/src/audio/transcode.ts +67 -0
- package/src/chat-template.ts +155 -10
- package/src/cli.ts +483 -113
- package/src/config.ts +116 -24
- package/src/diffusion/diffusion-generate.ts +14 -8
- package/src/download.ts +143 -12
- package/src/eval/README.md +7 -6
- package/src/eval/ifeval.ts +63 -120
- package/src/eval/kl.ts +59 -3
- package/src/eval/quality-db.ts +2 -2
- package/src/eval/runner.ts +17 -8
- package/src/eval/tasks/ifeval.ts +167 -31
- package/src/expert-io.ts +391 -0
- package/src/expert-offload.ts +15 -2
- package/src/expert-residency.ts +1134 -0
- package/src/expert-usage.ts +415 -0
- package/src/flags.ts +13 -0
- package/src/generate.ts +438 -35
- package/src/grammar.ts +585 -0
- package/src/hf-push.ts +1 -1
- package/src/hub-rest.ts +242 -0
- package/src/index.ts +14 -2
- package/src/jobs/runner.ts +37 -18
- package/src/kv-store.ts +586 -93
- package/src/lora.ts +85 -14
- package/src/md-modules.d.ts +42 -0
- package/src/media-fetch.ts +426 -0
- package/src/memory/rest.ts +245 -0
- package/src/memory/vault.ts +74 -0
- package/src/mlx/array.ts +149 -19
- package/src/mlx/autograd.ts +53 -16
- package/src/mlx/checkpoint.ts +46 -13
- package/src/mlx/custom-vjp.ts +83 -35
- package/src/mlx/ffi.ts +27 -3
- package/src/mlx/metal-kernel.ts +7 -4
- package/src/mlx/ops.ts +153 -23
- package/src/mlx/turboquant-ops.ts +831 -0
- package/src/mlx/turboquant-tables.ts +237 -0
- package/src/model/batched-mask.ts +62 -1
- package/src/model/batched-quant.ts +206 -0
- package/src/model/batched-rotating-quant.ts +346 -0
- package/src/model/batched-rotating.ts +46 -1
- package/src/model/compiled-decode.ts +4 -15
- package/src/model/factory.ts +103 -6
- package/src/model/gemma4-base.ts +395 -39
- package/src/model/gemma4.ts +122 -33
- package/src/model/generated/gemma4-12b.ts +9 -13
- package/src/model/generated/gemma4-26b.ts +10 -5
- package/src/model/generated/gemma4-e4b.ts +14 -9
- package/src/model/glm52-atlas.ts +511 -0
- package/src/model/glm52-cache.ts +706 -0
- package/src/model/glm52-config.ts +262 -0
- package/src/model/glm52-container.ts +305 -0
- package/src/model/glm52-coupling.ts +388 -0
- package/src/model/glm52-dsa.ts +602 -0
- package/src/model/glm52-expert-layout.ts +253 -0
- package/src/model/glm52-layout.ts +152 -0
- package/src/model/glm52-memory.ts +473 -0
- package/src/model/glm52-mla.ts +786 -0
- package/src/model/glm52-moe.ts +223 -0
- package/src/model/glm52-pilot.ts +537 -0
- package/src/model/glm52-reference.ts +445 -0
- package/src/model/glm52-residency.ts +557 -0
- package/src/model/glm52-resident-weights.ts +135 -0
- package/src/model/glm52-streamed-experts.ts +453 -0
- package/src/model/glm52-streamed-metal.ts +610 -0
- package/src/model/glm52-weights.ts +503 -0
- package/src/model/glm52.ts +1153 -0
- package/src/model/minicpm5.ts +58 -102
- package/src/model/paged-kv.ts +253 -0
- package/src/model/qwen3-delta.ts +76 -15
- package/src/model/qwen3-moe.ts +404 -0
- package/src/model/qwen3.ts +9 -8
- package/src/model/qwen3_5.ts +88 -23
- package/src/model/support.ts +19 -1
- package/src/model/universal/dense.ts +40 -5
- package/src/model/universal/rope.ts +36 -21
- package/src/native/expert_io.c +523 -0
- package/src/native-pack.ts +6 -4
- package/src/pi-web.ts +1299 -82
- package/src/preflight.ts +27 -8
- package/src/prompt-cache.ts +293 -33
- package/src/quantize/quantizer.ts +16 -1
- package/src/registry.ts +57 -2
- package/src/responses.ts +62 -49
- package/src/serve/batch-scheduler.ts +1050 -78
- package/src/serve/generation-gateway.ts +252 -24
- package/src/serve/isolate.ts +417 -0
- package/src/serve/lane-registry.ts +44 -0
- package/src/serve/session-search.ts +326 -0
- package/src/server.ts +1701 -175
- package/src/spec/assistant-source.ts +150 -0
- package/src/spec/deepspec-source.ts +143 -0
- package/src/spec/dflash-source.ts +124 -0
- package/src/spec/dspark/ab-stats.ts +136 -0
- package/src/spec/dspark/calibration.ts +112 -0
- package/src/spec/dspark/deepspec-module.ts +801 -0
- package/src/spec/dspark/generate-dflash.ts +72 -20
- package/src/spec/dspark/loader.ts +23 -0
- package/src/spec/dspark/module-dflash.ts +278 -36
- package/src/spec/dspark/quantize-drafter.ts +91 -0
- package/src/spec/generate.ts +59 -25
- package/src/spec/glm52-mtp-source.ts +392 -0
- package/src/spec/ngram-source.ts +132 -0
- package/src/spec/serve-loop.ts +617 -0
- package/src/spec/source.ts +118 -0
- package/src/spec/two-model.ts +171 -0
- package/src/ssd-cache.ts +111 -35
- package/src/tokenizer.ts +288 -2
- package/src/tool-approvals.ts +131 -0
- package/src/tool-call.ts +438 -22
- package/src/train/flash-cce.ts +2 -2
- package/src/train/job.ts +0 -12
- package/src/train/lora-params.ts +17 -6
- package/src/train/trainer.ts +60 -30
- package/src/vision/prompt.ts +217 -48
- package/src/web/app.html +1197 -1791
- package/src/web/app.js +5694 -0
- package/src/web/icon.svg +13 -0
- package/src/web/manifest.webmanifest +24 -0
- package/src/web/src/adapters-panel.ts +288 -0
- package/src/web/src/api.ts +57 -0
- package/src/web/src/assistant.ts +485 -0
- package/src/web/src/chat.ts +1050 -0
- package/src/web/src/composer.ts +959 -0
- package/src/web/src/dataset.ts +132 -0
- package/src/web/src/finetune.ts +267 -0
- package/src/web/src/hub.ts +428 -0
- package/src/web/src/main.ts +98 -0
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +572 -0
- package/src/web/src/model-picker.ts +159 -0
- package/src/web/src/palette.ts +346 -0
- package/src/web/src/protocol.ts +62 -0
- package/src/web/src/quantize.ts +167 -0
- package/src/web/src/rag.ts +274 -0
- package/src/web/src/sessions.ts +469 -0
- package/src/web/src/shell.ts +804 -0
- package/src/web/src/status.ts +300 -0
- package/src/web/src/ui-catalog.ts +92 -0
- package/src/web/sw.js +71 -0
- package/src/web/vendor/README.md +61 -0
- package/src/web/vendor/hljs-LICENSE +29 -0
- package/src/web/vendor/hljs-theme.css +59 -0
- package/src/web/vendor/hljs.js +26 -0
- package/src/web-tools.ts +54 -2
- package/src/weights.ts +82 -19
- package/src/model/fused-decode-kernel.ts +0 -312
- package/src/model/fused-geglu-kernel.ts +0 -198
- package/src/model/fused-mlp-kernel.ts +0 -169
- package/src/model/fused-swiglu-kernel.ts +0 -240
- package/src/model/steel-linear-kernel.ts +0 -96
- package/src/status-page.html +0 -497
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
Ship local inference inside a Mac app (Tauri, Electron, or anything
|
|
9
9
|
that can spawn a process) with zero user-visible dependencies: one
|
|
10
|
-
executable +
|
|
10
|
+
executable + four native libraries, dropped into your app's resources.
|
|
11
11
|
|
|
12
12
|
## Build the bundle
|
|
13
13
|
|
|
@@ -19,18 +19,35 @@ Produces a relocatable directory:
|
|
|
19
19
|
|
|
20
20
|
| file | what | size (arm64) |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| `mlx-bun` | the CLI/server, compiled with `bun build --compile` | ~
|
|
22
|
+
| `mlx-bun` | the CLI/server, compiled with `bun build --compile` | ~70-75 MB |
|
|
23
23
|
| `libmlxc.dylib` | mlx-c, rewritten to load `@loader_path/libmlx.dylib` | ~0.7 MB |
|
|
24
24
|
| `libmlx.dylib` | mlx core (+`@loader_path` rpath added for libjaccl) | ~15 MB |
|
|
25
25
|
| `libjaccl.dylib` | mlx's distributed-comm dependency | ~0.6 MB |
|
|
26
|
+
| `libmlx_bun_expert_io.dylib` | bounded streamed-expert I/O used by direct Colibri GLM-5.2 | ~0.03 MB |
|
|
26
27
|
| `mlx.metallib` | Metal kernels — libmlx loads it from its own directory | ~150 MB |
|
|
27
28
|
| `photon_rs_bg.wasm` | pi image codec — only the web chat's `read`-on-image path; resolved next to the executable | ~1.8 MB |
|
|
28
29
|
|
|
30
|
+
`build-binary.sh` also sidecars a second set of assets for the embedded
|
|
31
|
+
pi **terminal** (`mlx-bun pi`, `src/pi-terminal.ts` → `InteractiveMode`),
|
|
32
|
+
none of which the headless web chat touches:
|
|
33
|
+
|
|
34
|
+
| file | what |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `theme/*.json` | TUI color themes (built-in dark/light fallback exists in code; shipped so custom theme reads and the schema resolve) |
|
|
37
|
+
| `assets/*.png` | TUI startup art |
|
|
38
|
+
| `export-html/template.html`, `export-html/vendor/*.js` | the `/export` command's HTML template + vendor JS |
|
|
39
|
+
| `package.json`, `CHANGELOG.md` | version banner + startup changelog |
|
|
40
|
+
| `native/darwin/prebuilds/<arch>/darwin-modifiers.node` | pi-tui's native modifier-key detection (degrades gracefully if absent) |
|
|
41
|
+
|
|
29
42
|
Library resolution order (src/mlx/ffi.ts): `MLX_BUN_LIBMLXC` env var →
|
|
30
|
-
`libmlxc.dylib` next to the executable →
|
|
43
|
+
`libmlxc.dylib` next to the executable → the downloaded native-pack
|
|
44
|
+
cache (`~/Library/Caches/mlx-bun/native-v<ver>-<arch>/`, populated on
|
|
45
|
+
first run when no sidecar or homebrew install is found) → homebrew
|
|
31
46
|
(`/opt/homebrew/lib`, `/usr/local/lib`). The whole directory can be
|
|
32
47
|
renamed/moved; nothing references absolute paths after the build
|
|
33
|
-
script's `install_name_tool` fixups.
|
|
48
|
+
script's `install_name_tool` fixups. The expert helper independently resolves
|
|
49
|
+
`MLX_BUN_EXPERT_IO_DYLIB`, then the executable directory, then the same
|
|
50
|
+
native-pack cache.
|
|
34
51
|
|
|
35
52
|
## Embedded pi web chat (`/ws/chat`)
|
|
36
53
|
|
|
@@ -60,21 +77,28 @@ crashing), so it is best-effort, not load-bearing.
|
|
|
60
77
|
> The web chat itself is unaffected (its provider is text-only), and the
|
|
61
78
|
> wasm is shipped so it will work once Bun's support lands.
|
|
62
79
|
|
|
63
|
-
|
|
64
|
-
|
|
80
|
+
## Embedded pi terminal (`mlx-bun pi`)
|
|
81
|
+
|
|
82
|
+
The compiled binary also embeds pi's full interactive TUI
|
|
83
|
+
(`src/pi-terminal.ts` → `InteractiveMode`), reachable via `mlx-bun pi`.
|
|
84
|
+
Unlike the headless web chat, the terminal *does* resolve theme JSON,
|
|
85
|
+
startup art, the `/export` template, the version banner, and the
|
|
86
|
+
pi-tui native modifier-key helper by path — the second table above is
|
|
87
|
+
sidecar'd for exactly this mode. `src/pi-web.ts`'s session (the web
|
|
88
|
+
chat) still builds with `noThemes`/`noSkills`/`noExtensions`/
|
|
89
|
+
`noPromptTemplates`/`noContextFiles`, so none of that table is reached
|
|
90
|
+
from `/ws/chat` — only `mlx-bun pi` uses it.
|
|
91
|
+
|
|
92
|
+
**Omitted** (upstream pi ships these beside its own binary; neither
|
|
93
|
+
mlx-bun mode reaches them):
|
|
65
94
|
|
|
66
95
|
| omitted asset | what it's for |
|
|
67
96
|
|---|---|
|
|
68
|
-
| `
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
These are gated behind TUI code paths and the explicit `exportToHtml()`
|
|
74
|
-
method; `createAgentSession`'s import graph (`core/sdk.js`) pulls in no
|
|
75
|
-
theme/asset/export-html loaders, and `src/pi-web.ts` builds the session
|
|
76
|
-
with `noThemes`/`noSkills`/`noExtensions`/`noPromptTemplates`/
|
|
77
|
-
`noContextFiles`.
|
|
97
|
+
| `docs/`, `examples/`, `README.md` | upstream's own help/doc browsing, not exposed by either mlx-bun entry point |
|
|
98
|
+
|
|
99
|
+
`createAgentSession`'s import graph (`core/sdk.js`) pulls in no loaders
|
|
100
|
+
for these; both `src/pi-web.ts` and `src/pi-terminal.ts` build sessions
|
|
101
|
+
that never reference them.
|
|
78
102
|
|
|
79
103
|
**Verifying it.** `build-binary.sh` runs `scripts/verify-binary-pi.ts` as
|
|
80
104
|
a sibling compiled binary inside the bundle (so `process.execPath` points
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Features matrix — everything mlx-bun serves, in one table
|
|
2
|
+
|
|
3
|
+
The complete option inventory: every serving feature, its default, which
|
|
4
|
+
execution lane it runs on, which fidelity tier verifies it, and its knob.
|
|
5
|
+
This is the *what-exists* view; per-flag detail lives in
|
|
6
|
+
[server-config.md](server-config.md), wire formats in
|
|
7
|
+
[server-api.md](server-api.md), CLI verbs in [cli.md](cli.md).
|
|
8
|
+
|
|
9
|
+
**Lanes:** `serial` = the default single-queue path; `batch` = the
|
|
10
|
+
`--batch N` continuous-batching engine (bf16 compat mode, mlx-lm B=N
|
|
11
|
+
parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
|
|
12
|
+
· Lab = no external oracle; KL/eval-gated experiments (see
|
|
13
|
+
[server-config.md → Fidelity tiers](server-config.md#fidelity-tiers-and-the-decode-route---l1----l2)).
|
|
14
|
+
|
|
15
|
+
## Serving & performance
|
|
16
|
+
|
|
17
|
+
| Feature | Default | Lane | Tier | Knob |
|
|
18
|
+
| --- | --- | --- | --- | --- |
|
|
19
|
+
| OpenAI chat completions (`/v1/chat/completions`, SSE) | on | both | — | — |
|
|
20
|
+
| Raw text completions (`/v1/completions`) | on | both | — | — |
|
|
21
|
+
| Anthropic Messages (`/v1/messages`) | on | both | — | — |
|
|
22
|
+
| OpenAI Responses shim (`/v1/responses`) | on | both | — | — |
|
|
23
|
+
| Continuous batching (mlx-lm B=N parity) | **on** — cap 8 (default flipped 2026-07-05; a lone request runs the exact serial engine, so the cap engages only under real concurrency; `--batch 1` pins serial) | batch | L1 | `--batch <n>` |
|
|
24
|
+
| Prompt cache (prefix KV reuse) | on, 8 GB | both | — | `--prompt-cache <GB>` (0 = off) |
|
|
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
|
+
| **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` |
|
|
27
|
+
| **Model pool** (with `--isolate`: LRU-capped RESIDENT model engines; over the cap the least-recently-used engine demotes its cache to the SSD tier and exits, respawning on the next request) | 1 resident engine | both | — | `--model-pool <n>` (requires `--isolate`) |
|
|
28
|
+
| Mixed-precision KV (`kv_config.json`, optiq's scheme) | **off** — opt-in (default flipped to bf16 2026-07-05; quantized KV trades 5–20% decode for memory headroom) | serial + **batch** (per-layer configs batch on every shipped model — full-attention layers Phase 3.1, rotating layers milestone 2; uniform bits stay serial) | L2 | `--kv-quant config\|off\|4\|8`, `--l2` |
|
|
29
|
+
| **TurboQuant KV** (rotation-based: affine keys + FWHT/Lloyd-Max values) | off — opt-in ([turboquant-kv.md](../design/turboquant-kv.md); v1 dequantize-on-fetch, full-attention layers only, no speed claim) | serial only (solo-only, unconditionally) | Lab (codec is oracle-backed vs vllm-metal; the cache class is unvalidated) | `--kv-quant turbo[:k<bits>v<bits>]` (default `k8v3`) |
|
|
30
|
+
| Compiled decode (bit-exact graph replay) | on, every tier | serial | L1/L2 | `--compiled-decode on\|off` |
|
|
31
|
+
| Compiled activations (faithful geglu/swiglu — mlx-lm's `@mx.compile`) | **on**, every tier | both | L1 | `--compiled-activations on\|off` |
|
|
32
|
+
| Fused SDPA (optiq-exact quantized-KV attention) | follows `--kv-quant`: on for `config`, off for uniform/bf16 | serial | L2 | `--fused-sdpa on\|off` |
|
|
33
|
+
| **Paged KV** (vLLM-style block pool: host-side block table + gather before the stock SDPA, no fused kernel in v1 — [paged-kv-cache.md](../design/paged-kv-cache.md)) | off | serial (pins `--batch 1` unless `--batch` given) | gated bit-exact vs the plain `KVCache` (`tests/paged-kv-parity.test.ts`) | `--paged-kv`, `--paged-kv-block-size <n>` (default 256) — v1 scope Gemma4-family bf16; refuses `--batch N>1`, `--kv-quant`, `--draft-model` |
|
|
34
|
+
| **Speculative decoding** (auto-detected drafter: two-model = mlx-lm parity/L1, Gemma `-assistant` = optiq/L2, DSpark local = Lab, DeepSpec released = DeepSpec-reference oracle) | off | serial (forces all-serial) | per-drafter oracle | `--draft-model <path\|query>`, `--draft-kind`, `--num-draft-tokens` |
|
|
35
|
+
| **GLM-5.2 checkpoint-native MTP** (bounded auxiliary expert tier, exact verify) | **on** for GLM-5.2 | serial (`usage.lane: serial+spec`) | Colibri/oracle trajectory + synthetic HTTP gate | `--mtp on\|off` (`off` enables ordinary GLM batching) |
|
|
36
|
+
| Speculative decoding, **model-free prompt lookup** (drafts copied from the request's own context; port of prompt-lookup decoding / vLLM `ngram`; zero weights) | off | serial (forces all-serial) | lossless by verify (gated vs non-spec greedy, tests/spec-ngram.test.ts) | `--draft-kind ngram` (no `--draft-model`), `--ngram-max`, `--ngram-min`, `--num-draft-tokens` (default 10) |
|
|
37
|
+
| Memory admission (refuse what can't fit; never GPU-OOM) | on (RAM × 0.75) | both | — | `--memory-budget <GB>` |
|
|
38
|
+
| Aggregate KV admission for batch rows (queue, don't OOM) | off | batch | — | `--kv-budget <GB>` |
|
|
39
|
+
| Expert offload (MoE cold experts on mmap) | off | serial | Lab | `--expert-offload` |
|
|
40
|
+
| Extend-join (O(1) batch admission) | on | batch | L1 (own oracle) | `MLX_BUN_BATCH_EXTEND=0` |
|
|
41
|
+
| Vectorized greedy batch sampling | on | batch | bit-equal A/B | `MLX_BUN_BATCH_VEC_SAMPLE=0` |
|
|
42
|
+
|
|
43
|
+
## Request features
|
|
44
|
+
|
|
45
|
+
| Feature | Default | Lane | Tier | Knob |
|
|
46
|
+
| --- | --- | --- | --- | --- |
|
|
47
|
+
| **Structured output** (`response_format` json_object/json_schema) | on | both | L2 (oMLX) | request field; `MLX_BUN_GRAMMAR=0` kills |
|
|
48
|
+
| Structured output **jump-forward** (grammar-forced spans emitted without per-token forwards; SGLang technique via xgrammar) | **off** | serial only | Lab (string-lossless + validity gates, tests/grammar-jump.test.ts; token stream may differ — no oracle) | `MLX_BUN_GRAMMAR_JUMP=1` |
|
|
49
|
+
| `guided_grammar` (EBNF) / `guided_regex`¹ / `guided_choice` / `structured_outputs` | on | both | L2 | request fields |
|
|
50
|
+
| Structured output × speculative decoding | on (when both active) | serial | Lab (validity+equivalence) | — |
|
|
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
|
+
| Tool calling (Gemma sentinel / CPM+Qwen XML / GLM `arg_key`+`arg_value`) + `role:"tool"` loops | on | both | — | request `tools` |
|
|
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
|
+
| **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
|
+
| LoRA adapters (mount at start / hot-swap at runtime) | off | serial | — | `--adapter <dir>`, `POST /v1/adapters` |
|
|
56
|
+
| 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 |
|
|
57
|
+
| `logprobs` / `top_logprobs` (mlx-lm semantics) | off | serial | L1 | request fields |
|
|
58
|
+
| Fixed `seed` reproducibility | off | serial (routes solo) | — | request field |
|
|
59
|
+
| Thinking-mode control (hybrid-reasoning models) | model default | both | — | `--thinking`, `chat_template_kwargs` |
|
|
60
|
+
| Stop sequences / streaming / usage accounting | on | both | — | request fields |
|
|
61
|
+
| HLG tone-curve sampling | off | serial | Lab | `--hlg-sampling on` |
|
|
62
|
+
| Spec-decode telemetry (`usage.speculation`) | on with a draft | serial | — | — |
|
|
63
|
+
| Per-turn lane telemetry (`usage.lane`: serial / serial+spec / batched) | on | both | — | — |
|
|
64
|
+
|
|
65
|
+
## Model coverage (per-model validated cells — no generic path is trusted untested)
|
|
66
|
+
|
|
67
|
+
| Family | Serial | Batch | Notes |
|
|
68
|
+
| --- | --- | --- | --- |
|
|
69
|
+
| MiniCPM5 (cpm5) | ✅ L1/L2 | ✅ | the starter model |
|
|
70
|
+
| Gemma 4 (1B/e4b/12B/26B, + vision e4b/12B, + audio e4b) | ✅ L1/L2 | ✅ | sliding+full interleaved; MoE 26B |
|
|
71
|
+
| Qwen3.5 (gated-DeltaNet hybrid) | ✅ L1/L2 | ✅ (SSM path) | `MLX_BUN_BATCH_SSM=0` reverts |
|
|
72
|
+
| 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
|
+
| DiffusionGemma-26B (non-autoregressive) | ✅ (own engine) | — serial always | first bit-exact non-AR port |
|
|
74
|
+
| Tier-0 universal (llama/qwen2/qwen3/olmo2/…, 11 archs) | ✅ L1 | ✅ plain full-attention archs² | gemma2-family/sliding universal → serial |
|
|
75
|
+
|
|
76
|
+
## Beyond serving (the same binary)
|
|
77
|
+
|
|
78
|
+
Training (`mlx-bun train`: ORPO/DPO/SFT, flash-CCE, segmented backward) ·
|
|
79
|
+
quantization (`convert`, `fuse`, `--target-bpw`) · embeddings · local
|
|
80
|
+
memory/wiki (`mlx-bun memory`) · pi agent integration (`mlx-bun pi`) ·
|
|
81
|
+
model registry + `fit` planner + `gc` · HF `upload` · web chat Model Hub
|
|
82
|
+
(`/api/hub/local` + `/search` + `/download`, per-row `/fit` verdict;
|
|
83
|
+
`/api/hub/serve` is `restart_required`-only today — no in-process model-swap
|
|
84
|
+
seam reaches `/ws/chat`, see [server-api.md](server-api.md#model-hub-apihub))
|
|
85
|
+
· **PWA installability** (manifest + shell-only service worker —
|
|
86
|
+
installable, instant static-shell paint; explicitly not offline chat, see
|
|
87
|
+
[server-api.md](server-api.md#web-app-static-routes--pwa-installability)).
|
|
88
|
+
See [cli.md](cli.md) and the per-topic reference docs.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
¹ `guided_regex` accepts the regex∩EBNF subset today (no `\d`/anchors — those degrade to prompt injection); real regex support is tracked.
|
|
92
|
+
² Gated token-exact vs mlx-lm B=2 (static + dynamic join/leave) on Llama-3.2-3B.
|
|
93
|
+
³ Audio is a capability neither ancestor SERVES: mlx-lm strips the audio tower at load and 400s non-text parts; optiq ships the full machinery but never wires it into its serve frontend — mlx-bun exposes it. Serial lane by design (embeddings prefill; batched audio has no oracle → novel-territory gates would apply), prompt cache skipped.
|
|
94
|
+
|
|
95
|
+
Composition rules and exclusions (what combines with what):
|
|
96
|
+
[server-config.md → Compatibility matrix](server-config.md#compatibility-matrix).
|
|
97
|
+
Performance per mode: `scripts/bench-modes.ts` (TTFT / prefill / decode /
|
|
98
|
+
peak-memory across every cell above); feature-composition perf:
|
|
99
|
+
`scripts/bench-feature-matrix.ts`.
|
|
@@ -3,33 +3,37 @@
|
|
|
3
3
|
The HTTP server is one consumer of a library-first API. Everything it
|
|
4
4
|
does — generation, sampling, KV schemes, LoRA, vision, caching, memory
|
|
5
5
|
admission — is importable directly into a Bun process. Published as
|
|
6
|
-
`mlx-bun` on npm
|
|
6
|
+
`mlx-bun` on npm; `bunx mlx-bun` works out of the box, or
|
|
7
7
|
`import … from "mlx-bun"` for programmatic use.
|
|
8
8
|
|
|
9
|
-
One rule everywhere: **one generation at a time per process** (one GPU
|
|
10
|
-
|
|
9
|
+
One rule everywhere: **one generation at a time per process** (one GPU).
|
|
10
|
+
The server serializes through a queue (or, under `--batch N`, its
|
|
11
|
+
continuous-batching scheduler — a server-lane feature, not a library
|
|
12
|
+
surface); direct library callers must do the same.
|
|
11
13
|
|
|
12
14
|
## Quick start
|
|
13
15
|
|
|
14
16
|
```ts
|
|
15
17
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
createModel, // dispatches to Gemma4Model / MiniCPM5Model / Qwen35Model
|
|
18
|
+
ensureNativeRuntime,
|
|
19
|
+
openModel, // artifact-aware dispatch, including bounded GLM-5.2
|
|
19
20
|
loadTokenizer,
|
|
20
21
|
ChatTemplate,
|
|
21
22
|
generate,
|
|
22
23
|
} from "mlx-bun"; // or "./src/index" in-repo
|
|
23
24
|
|
|
25
|
+
await ensureNativeRuntime();
|
|
24
26
|
const dir = "/path/to/hf-snapshot"; // mlx-bun ls prints these
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
+
const model = await openModel(dir, {
|
|
28
|
+
// Used only by the direct Colibri GLM-5.2 artifact; other models ignore it.
|
|
29
|
+
contextTokens: 4096, maxGenerationTokens: 256, enableMtp: false,
|
|
30
|
+
});
|
|
27
31
|
const tok = await loadTokenizer(dir);
|
|
28
32
|
const template = await ChatTemplate.load(dir);
|
|
29
33
|
// Gemma4Model and MiniCPM5Model can still be imported directly from "mlx-bun"
|
|
30
34
|
// if you need the concrete type. Qwen35Model is NOT exported from the public
|
|
31
|
-
// package — use
|
|
32
|
-
// "./src/model/
|
|
35
|
+
// package — use openModel/RuntimeModel (preferred artifact-aware dispatch), or import from
|
|
36
|
+
// "./src/model/qwen3_5" in-repo.
|
|
33
37
|
|
|
34
38
|
const ids = tok.encode(template.render([{ role: "user", content: "hi" }]));
|
|
35
39
|
const promptIds = ids[0] === ids[1] && ids[0] === tok.bosTokenId ? ids.slice(1) : ids;
|
|
@@ -41,8 +45,18 @@ console.log(tok.decode(out, true));
|
|
|
41
45
|
console.log(gen.stats); // set once iteration ends
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
Ordinary safetensors loading is lazy (mmap + mlx native loader). GLM-5.2 first
|
|
49
|
+
runs its header-only exact process equation, then opens the bounded Colibri
|
|
50
|
+
resident/expert tiers; impossible plans fail before either tier is committed.
|
|
51
|
+
|
|
52
|
+
> **First run:** library consumers bypass the CLI's first-run step, so
|
|
53
|
+
> call `await ensureNativeRuntime()` once before constructing a model on
|
|
54
|
+
> a machine that may not have the MLX native runtime yet — it downloads
|
|
55
|
+
> the sha256-verified native pack (MLX plus the direct-Colibri expert-I/O
|
|
56
|
+
> helper) to `~/Library/Caches/mlx-bun/` and is
|
|
57
|
+
> a no-op when the runtime is already present (beside the executable,
|
|
58
|
+
> already cached, or installed via homebrew). `nativeRuntimeDir()`
|
|
59
|
+
> returns the resolved directory, or `null` on a fresh machine.
|
|
46
60
|
|
|
47
61
|
## generate(model, promptTokens, options) → Generation
|
|
48
62
|
|
|
@@ -64,13 +78,20 @@ after an early `break`, which cleanly cancels the in-flight step).
|
|
|
64
78
|
| `kvConfig` | off | per-layer mixed precision from `kv_config.json` (`config.kvQuant`); overrides `kvBits`, start 0 — optiq serve semantics |
|
|
65
79
|
| `adapters` | none | mounted LoRA adapter ids, applied for exactly this generation |
|
|
66
80
|
| `promptEmbeddings` / `imageMask` | — | vision path (see `src/vision/`) |
|
|
81
|
+
| `logprobs` / `topLogprobs` | off | per-token logprob capture (mlx_lm.server parity): `logprobs` captures the emitted token's log-probability, `topLogprobs` (0/unset = off) captures the top-k (id, logprob) pairs — same full-vocab log-softmax distribution mlx-lm's generate_step samples from, taken after logits processors and before the sampler |
|
|
82
|
+
| `grammar` | off | a compiled `GrammarController` (`src/grammar.ts`) for structured output — masks invalid tokens to `-inf` each step (L2-class, oMLX oracle) |
|
|
83
|
+
| `turboQuant` | off | TurboQuant KV scheme (docs/design/turboquant-kv.md), a rotation-based alternative to uniform `kvBits`; mutually exclusive with `kvBits`/`kvConfig` |
|
|
84
|
+
| `pagedKv` | off | `{ blockSize? }` — OPTIONAL paged KV cache (docs/design/paged-kv-cache.md); v1 scope is serial batch=1 Gemma4-family bf16, mutually exclusive with `kvBits`/`kvConfig`/`turboQuant`/draft/compiled decode |
|
|
67
85
|
|
|
68
86
|
`GenerateStats`: `promptTokens`, `cachedTokens`, `generatedTokens`,
|
|
69
87
|
`prefillTps` / `prefillMs`, `decodeTps` / `decodeMs`, `cacheTokens`
|
|
70
88
|
(the exact token sequence whose KV is in the cache — feed it to
|
|
71
89
|
`PromptCache.put`). Timing semantics match mlx-lm: the prompt clock
|
|
72
90
|
runs until the first token arrives (the prefill→decode boundary is
|
|
73
|
-
prompt time), the decode clock from there.
|
|
91
|
+
prompt time), the decode clock from there. An optional `spec` field
|
|
92
|
+
carries speculative-decoding telemetry (serve `--draft-model` path
|
|
93
|
+
only): `drafted`, `accepted`, `targetCalls`, and per-draft-position
|
|
94
|
+
`draftedByPos` / `acceptedByPos` counts.
|
|
74
95
|
|
|
75
96
|
## Serving pieces
|
|
76
97
|
|
|
@@ -80,7 +101,7 @@ import { loadContext, createServer } from "mlx-bun";
|
|
|
80
101
|
const ctx = await loadContext(dir, "my-model", { memoryBudgetBytes: 12e9 });
|
|
81
102
|
const server = createServer(ctx, 8080, {
|
|
82
103
|
promptCacheBytes: 2e9, // byte-capped LRU (never count-capped)
|
|
83
|
-
kvQuant: undefined, // default: kv_config.json; "off" | bits
|
|
104
|
+
kvQuant: undefined, // default: kv_config.json; "off" | "config" | bits
|
|
84
105
|
memoryBudgetBytes: 12e9, // admission control — the only OOM defense
|
|
85
106
|
});
|
|
86
107
|
```
|
|
@@ -90,6 +111,24 @@ budget (pre-GPU, mmap-only check). The server exposes OpenAI chat
|
|
|
90
111
|
completions, Anthropic `/v1/messages`, OpenAI Responses, embeddings,
|
|
91
112
|
adapters, and `/stats` — [server-api.md](./server-api.md).
|
|
92
113
|
|
|
114
|
+
For GLM-5.2, pass its load-only resource controls under `glm`:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const ctx = await loadContext(dir, "glm-5.2", {
|
|
118
|
+
glm: {
|
|
119
|
+
contextTokens: 4096,
|
|
120
|
+
maxGenerationTokens: 128,
|
|
121
|
+
batchSize: 8,
|
|
122
|
+
enableMtp: true, // default; native MTP routes requests serial+spec
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`openModel()` and `loadContext()` both select the streamed Colibri runtime;
|
|
128
|
+
callers do not use `Weights.open()` or `createModel()` for this artifact.
|
|
129
|
+
Direct `generate()` supports the full sampling/grammar/logprobs contract but
|
|
130
|
+
does not itself mount a drafter; native MTP is a serving-context feature.
|
|
131
|
+
|
|
93
132
|
## Text embeddings
|
|
94
133
|
|
|
95
134
|
```ts
|
|
@@ -135,14 +174,24 @@ under one adapter must not seed another's prefill).
|
|
|
135
174
|
```ts
|
|
136
175
|
import { saveKvCache, loadKvCache } from "./src/kv-store";
|
|
137
176
|
saveKvCache("/tmp/prefix.kv", tokens, caches); // page-aligned file
|
|
138
|
-
const { tokens, caches
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
//
|
|
177
|
+
const { tokens, caches } = loadKvCache("/tmp/prefix.kv", model, {
|
|
178
|
+
modelId, configFingerprint, tokenizerHash, verify: true,
|
|
179
|
+
});
|
|
180
|
+
// Restore streams one tensor at a time from a read-only mmap into MLX-owned
|
|
181
|
+
// storage, drops each clean file-page range, and unmaps before returning.
|
|
182
|
+
// Note: loadKvCache accepts anything with makeCache(): Cache[] — it validates
|
|
183
|
+
// the entry count against the cache list makeCache() returns (not
|
|
184
|
+
// model.layers.length, which is wrong for KV-shared models like e4b, whose
|
|
185
|
+
// makeCache() returns donors only). RuntimeModel qualifies directly, no cast.
|
|
143
186
|
```
|
|
144
187
|
|
|
145
|
-
|
|
188
|
+
Format v3 supports plain, rotating, quantized, TurboQuant, SSM, and GLM-5.2
|
|
189
|
+
checkpoint-native caches. GLM rows use `mla`, `mla-dsa`, and `mtp-mla` kinds and
|
|
190
|
+
store only compressed latent/RoPE/DSA state—never reconstructed full K/V.
|
|
191
|
+
`Glm52NativeMtpSource.clonePersistentCache()` returns an owned MTP snapshot;
|
|
192
|
+
`restorePersistentCache()` adopts a validated restored `mtp-mla` row. Writes
|
|
193
|
+
are page-aligned, hashed, atomic (`.tmp` + fsync + rename), and available in
|
|
194
|
+
both synchronous and event-loop-yielding `saveKvCacheAsync` forms.
|
|
146
195
|
|
|
147
196
|
## Registry + fit (model discovery and memory math)
|
|
148
197
|
|
package/docs/reference/memory.md
CHANGED
|
@@ -42,18 +42,38 @@ mlx-bun memory unschedule
|
|
|
42
42
|
|
|
43
43
|
## Agent tools
|
|
44
44
|
|
|
45
|
-
Both `mlx-bun pi` and the web chat expose these read-only tools:
|
|
45
|
+
Both `mlx-bun pi` and the web chat expose these read-only tools, in the recommended call order — FIND the article, READ it small, follow the graph, fall back to reference docs and utilities, search only as a last resort:
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
- `
|
|
49
|
-
- `
|
|
50
|
-
|
|
51
|
-
-
|
|
47
|
+
**FIND** (deterministic lookup, never a vector search):
|
|
48
|
+
- `memory_resolve` — name/alias → the article
|
|
49
|
+
- `memory_category` — category/type/series → members
|
|
50
|
+
|
|
51
|
+
**READ** (TOC → one section, not a full-article dump):
|
|
52
|
+
- `memory_read` — TOC + lead by default; `force=true` for the full article
|
|
53
|
+
- `memory_section` — one section's body (the default granularity)
|
|
54
|
+
|
|
55
|
+
**Follow the graph**:
|
|
56
|
+
- `memory_links` — outbound/inbound wikilinks
|
|
57
|
+
- `memory_infobox` — read an article's infobox fields (there is no infobox *query* tool — the infobox is content the model reads, not a filter)
|
|
58
|
+
|
|
59
|
+
**Reference docs** (mlx-bun's own docs, mirrored read-only into the vault):
|
|
60
|
+
- `reference_search`
|
|
61
|
+
- `reference_read`
|
|
62
|
+
- `reference_list`
|
|
63
|
+
|
|
64
|
+
**Utility**:
|
|
52
65
|
- `memory_list` — user articles plus read-only `Reference/*` docs
|
|
53
66
|
- `memory_status` — vault path, setup state, article count, git state, last synthesis run (from the vault's git log), schedule state, recent changed articles
|
|
54
67
|
|
|
68
|
+
**Last resort**:
|
|
69
|
+
- `memory_search` — substring fallback when FIND failed
|
|
70
|
+
|
|
55
71
|
The tools are always registered. If no vault exists, they return a setup message instead of disappearing. Search/read results prefixed with `Reference/` are mlx-bun docs, not user memory articles.
|
|
56
72
|
|
|
73
|
+
## Web chat REST surface
|
|
74
|
+
|
|
75
|
+
The web chat's Memory panel talks to a separate, HTTP-only `/api/memory/*` route surface (status/list/search/article/links/history/diff + a `POST /api/memory/init` consent-card endpoint) — thin wrappers over the same vault read path above, documented in [server-api.md](server-api.md#get-apimemory--post-apimemoryinit). The agent-tool surface above is unaffected by it.
|
|
76
|
+
|
|
57
77
|
## Obsidian
|
|
58
78
|
|
|
59
79
|
```bash
|
package/docs/reference/models.md
CHANGED
|
@@ -35,6 +35,11 @@ mlx-bun get <substring> # no "/" = registry query, re-gets the match
|
|
|
35
35
|
- Plain HTTPS resolve/CDN (no Xet), sequential files, `Range`-resume of
|
|
36
36
|
partial blobs (`<blob>.incomplete`). Auth: `HF_TOKEN` env, then the
|
|
37
37
|
token `hf auth login` writes. 401/403 answers get a "gated repo" hint.
|
|
38
|
+
- Before the first payload request, mlx-bun totals the bytes still absent,
|
|
39
|
+
credits complete shared blobs and valid `.incomplete` prefixes, and checks
|
|
40
|
+
the target volume for that remainder plus a fixed 1 GiB safety reserve. An
|
|
41
|
+
impossible acquisition fails immediately with required/available GiB and a
|
|
42
|
+
rerun/resume instruction rather than filling the disk halfway through.
|
|
38
43
|
- A substring argument (no `/`) resolves against already-downloaded
|
|
39
44
|
repos — `mlx-bun get 12B` refreshes the 12B to upstream's latest. An
|
|
40
45
|
unknown substring errors with a pointer to `mlx-bun ls <q>`.
|
|
@@ -51,14 +56,56 @@ mlx-bun get <substring> # no "/" = registry query, re-gets the match
|
|
|
51
56
|
Every blob is checksummed **while streaming** (a resume re-hashes the
|
|
52
57
|
existing prefix in chunks — no whole-file allocation):
|
|
53
58
|
|
|
54
|
-
- **LFS files** (weights): sha256 must equal the API's `lfs.
|
|
55
|
-
is also
|
|
59
|
+
- **LFS files** (weights): sha256 must equal the API's current `lfs.sha256`
|
|
60
|
+
field (the older `lfs.oid` spelling is also accepted) — which is also the
|
|
61
|
+
blob's filename.
|
|
56
62
|
- **Small files** (configs, tokenizer): git blob identity,
|
|
57
63
|
`sha1("blob <size>\0" + content)`, must equal the API's `blobId`.
|
|
58
64
|
|
|
59
65
|
A mismatch deletes the partial (never resume corrupt bytes); a short
|
|
60
66
|
read keeps the `.incomplete` for resume.
|
|
61
67
|
|
|
68
|
+
## GLM-5.2 on a 32 GB Mac
|
|
69
|
+
|
|
70
|
+
The validated direct-container artifact is
|
|
71
|
+
`mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp` at revision
|
|
72
|
+
`3cc8db99b1b13fc79325d987ba3c1c430766b3b8`. It is approximately 384 GB
|
|
73
|
+
decimal / 357 GiB on disk, so choose the Hugging Face cache volume before the
|
|
74
|
+
download. Fast internal NVMe is strongly preferred; an external volume also
|
|
75
|
+
needs to sustain the expert-streaming workload after acquisition.
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
# Optional: choose a large fast volume before downloading.
|
|
79
|
+
export HF_HUB_CACHE=/Volumes/FastSSD/huggingface/hub
|
|
80
|
+
|
|
81
|
+
mlx-bun get mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp \
|
|
82
|
+
--revision 3cc8db99b1b13fc79325d987ba3c1c430766b3b8
|
|
83
|
+
mlx-bun scan
|
|
84
|
+
mlx-bun serve GLM-5.2-colibri \
|
|
85
|
+
--memory-budget 26.8435456 \
|
|
86
|
+
--context-length 4096 \
|
|
87
|
+
--max-tokens 128 \
|
|
88
|
+
--mtp on
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`26.8435456` decimal GB is exactly 25 GiB. The validated plan reserves about
|
|
92
|
+
19.9 GiB for the process and leaves the rest of the 32 GiB machine to macOS.
|
|
93
|
+
Startup runs the exact header-only resource equation before opening resident
|
|
94
|
+
weights or expert slabs. The server reports the resulting plan at
|
|
95
|
+
`GET /stats` under `glm52`.
|
|
96
|
+
|
|
97
|
+
If acquisition is interrupted, rerun the identical `get` command: mlx-bun
|
|
98
|
+
rehashes each existing prefix in bounded chunks, sends a Range request for the
|
|
99
|
+
remainder, and verifies the complete blob before publishing it. If the disk
|
|
100
|
+
preflight refuses, free space or point `HF_HUB_CACHE` at another volume and
|
|
101
|
+
rerun. No Python environment and no converted copy inside the mlx-bun checkout
|
|
102
|
+
are involved.
|
|
103
|
+
|
|
104
|
+
The artifact is an external MIT-licensed derivative of
|
|
105
|
+
`zai-org/GLM-5.2-FP8`, converted with Colibri and extended with int8 MTP
|
|
106
|
+
weights. Model weights are not bundled with mlx-bun; review the artifact model
|
|
107
|
+
card before redistribution.
|
|
108
|
+
|
|
62
109
|
## scan + the registry
|
|
63
110
|
|
|
64
111
|
`mlx-bun scan` walks `models--*/snapshots/*` reading only `config.json`
|
|
@@ -79,6 +126,8 @@ Schema (table `models`, one row **per snapshot**, keyed on `path`):
|
|
|
79
126
|
| `quant_bits`, `quant_group_size`, `quant_mode` | quantization |
|
|
80
127
|
| `has_vision_sidecar` | sidecar file present |
|
|
81
128
|
| `vision_config_type` | `config.json`'s `vision_config.model_type` when it names a vision tower (`*_vision`) |
|
|
129
|
+
| `has_audio_config` | `config.json` declares an `audio_config` block |
|
|
130
|
+
| `has_audio_tower` | sidecar header names `audio_tower.*` tensors |
|
|
82
131
|
| `has_kv_config`, `has_tool_template`, `license` | capabilities/terms |
|
|
83
132
|
| `scanned_at` | freshness (canonical tie-break) |
|
|
84
133
|
|
|
@@ -89,6 +138,14 @@ Schema (table `models`, one row **per snapshot**, keyed on `path`):
|
|
|
89
138
|
Presence of a `vision_config` key alone is **not** a signal — Qwen3.5
|
|
90
139
|
nests a copy of its own text config there.
|
|
91
140
|
|
|
141
|
+
**Audio capability** is `has_audio_config AND has_audio_tower`: both
|
|
142
|
+
legs are required because the 12B OptiQ snapshot carries an
|
|
143
|
+
`audio_config` but a stub sidecar whose only audio entry is
|
|
144
|
+
`embed_audio.embedding_projection.weight` (no `audio_tower.*` Conformer
|
|
145
|
+
tensors) — config presence alone would advertise audio that fails at
|
|
146
|
+
request time. The check reads only the sidecar's safetensors header,
|
|
147
|
+
never tensor bytes.
|
|
148
|
+
|
|
92
149
|
## Query resolution rules (per verb)
|
|
93
150
|
|
|
94
151
|
Every verb resolves fuzzy queries the same way, with revision collapsing
|
|
@@ -98,7 +155,7 @@ so a stale snapshot never makes a repo "ambiguous":
|
|
|
98
155
|
row per repo** (the canonical revision). `--all-revisions` shows the
|
|
99
156
|
per-snapshot truth with the canonical marked `*`. Capabilities column
|
|
100
157
|
labels the support tier: `supported (targeted)` (dedicated forward,
|
|
101
|
-
L2/
|
|
158
|
+
L2/opt-in paths) vs `supported (generic)` (Tier-0 universal module).
|
|
102
159
|
- **`fit` / `serve` / `train` / … (single-model verbs)** — `resolve()`:
|
|
103
160
|
the query must match exactly one **repo**; multiple cached revisions of
|
|
104
161
|
that repo collapse to the canonical snapshot (refs/main, else most
|
|
@@ -14,9 +14,9 @@ mlx-bun train <model> --data <dir>
|
|
|
14
14
|
- `<model>` is a query or snapshot path (e.g. `e4b`, `MiniCPM5`); omit it to auto-pick.
|
|
15
15
|
- `--data <dir>` is a directory with `train.jsonl` (+ optional `valid.jsonl`); rows are
|
|
16
16
|
`{"prompt": "...", "chosen": "...", "rejected": "..."}`.
|
|
17
|
-
- The
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
- The full stack (flash head + prefix-share + segmented) is on by default. No env-flag
|
|
18
|
+
setup is needed for any model (the old Gemma training-flag requirement is gone —
|
|
19
|
+
the no-vjp kernels were deleted 2026-07-05).
|
|
20
20
|
- It prints a plan box (dataset counts, format, the resolved knobs), streams per-step loss
|
|
21
21
|
+ peak memory, and saves a **mountable** adapter (`mlx-bun serve <model> --adapter <dir>`).
|
|
22
22
|
- `--dry-run` inspects the dataset and prints the plan without training. `mlx-bun help train`
|
|
@@ -59,7 +59,6 @@ mlx-bun train e4b --data ./prefs --resume ~/.cache/mlx-bun/mlx-bun-finetunes/orp
|
|
|
59
59
|
MODEL=/path/to/snapshot DATA=/path/to/datadir bun scripts/train-orpo.ts
|
|
60
60
|
```
|
|
61
61
|
- `DATA` is a directory with `train.jsonl` (+ optional `valid.jsonl`).
|
|
62
|
-
- Auto-detects e4b/Gemma and sets the training env flags, same as the CLI.
|
|
63
62
|
|
|
64
63
|
### Preconfigured defaults (override via env)
|
|
65
64
|
| env | default | meaning |
|