mlx-bun 0.0.11 → 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.
Files changed (81) hide show
  1. package/README.md +43 -13
  2. package/THIRD_PARTY_LICENSES.md +9 -0
  3. package/docs/design/colibri-glm52-port.md +1479 -0
  4. package/docs/design/pre-colibri-stabilization.md +329 -0
  5. package/docs/investigations/colibri-oracle-pin.md +1284 -0
  6. package/docs/investigations/indexshare-performance-spike.md +357 -0
  7. package/docs/planning/release-notes-v0.0.12.md +80 -0
  8. package/docs/reference/cli.md +28 -2
  9. package/docs/reference/distribution.md +25 -1
  10. package/docs/reference/embedding.md +5 -2
  11. package/docs/reference/features-matrix.md +4 -2
  12. package/docs/reference/library-api.md +41 -13
  13. package/docs/reference/models.md +49 -2
  14. package/docs/reference/server-api.md +90 -9
  15. package/docs/reference/server-config.md +21 -14
  16. package/docs/reference/training.md +10 -1
  17. package/package.json +1 -1
  18. package/src/anthropic.ts +54 -44
  19. package/src/chat-template.ts +155 -10
  20. package/src/cli.ts +127 -8
  21. package/src/config.ts +71 -26
  22. package/src/diffusion/diffusion-generate.ts +14 -8
  23. package/src/download.ts +103 -12
  24. package/src/eval/ifeval.ts +63 -120
  25. package/src/eval/runner.ts +14 -5
  26. package/src/eval/tasks/ifeval.ts +167 -31
  27. package/src/expert-io.ts +391 -0
  28. package/src/expert-residency.ts +1134 -0
  29. package/src/expert-usage.ts +415 -0
  30. package/src/generate.ts +114 -17
  31. package/src/hf-push.ts +1 -1
  32. package/src/index.ts +14 -2
  33. package/src/jobs/runner.ts +37 -18
  34. package/src/kv-store.ts +147 -8
  35. package/src/lora.ts +77 -14
  36. package/src/media-fetch.ts +198 -56
  37. package/src/mlx/array.ts +43 -0
  38. package/src/mlx/autograd.ts +51 -14
  39. package/src/mlx/checkpoint.ts +46 -13
  40. package/src/mlx/custom-vjp.ts +83 -35
  41. package/src/model/factory.ts +96 -5
  42. package/src/model/gemma4-base.ts +32 -0
  43. package/src/model/glm52-atlas.ts +511 -0
  44. package/src/model/glm52-cache.ts +706 -0
  45. package/src/model/glm52-config.ts +262 -0
  46. package/src/model/glm52-container.ts +305 -0
  47. package/src/model/glm52-coupling.ts +388 -0
  48. package/src/model/glm52-dsa.ts +602 -0
  49. package/src/model/glm52-expert-layout.ts +253 -0
  50. package/src/model/glm52-layout.ts +152 -0
  51. package/src/model/glm52-memory.ts +473 -0
  52. package/src/model/glm52-mla.ts +786 -0
  53. package/src/model/glm52-moe.ts +223 -0
  54. package/src/model/glm52-pilot.ts +537 -0
  55. package/src/model/glm52-reference.ts +445 -0
  56. package/src/model/glm52-residency.ts +557 -0
  57. package/src/model/glm52-resident-weights.ts +135 -0
  58. package/src/model/glm52-streamed-experts.ts +453 -0
  59. package/src/model/glm52-streamed-metal.ts +610 -0
  60. package/src/model/glm52-weights.ts +503 -0
  61. package/src/model/glm52.ts +1153 -0
  62. package/src/model/support.ts +8 -1
  63. package/src/native/expert_io.c +523 -0
  64. package/src/native-pack.ts +6 -4
  65. package/src/responses.ts +62 -49
  66. package/src/serve/batch-scheduler.ts +95 -16
  67. package/src/serve/generation-gateway.ts +41 -16
  68. package/src/server.ts +362 -81
  69. package/src/spec/glm52-mtp-source.ts +392 -0
  70. package/src/spec/serve-loop.ts +99 -18
  71. package/src/spec/source.ts +31 -6
  72. package/src/ssd-cache.ts +6 -2
  73. package/src/tool-call.ts +30 -2
  74. package/src/train/job.ts +0 -10
  75. package/src/train/lora-params.ts +17 -6
  76. package/src/train/trainer.ts +59 -26
  77. package/src/web/app.html +13 -2
  78. package/src/web/app.js +30 -3
  79. package/src/web/src/status.ts +51 -3
  80. package/src/web-tools.ts +54 -2
  81. package/src/weights.ts +82 -19
@@ -0,0 +1,357 @@
1
+ # IndexShare / IndexCache performance spike
2
+
3
+ **Date:** 2026-08-16
4
+ **Status:** accepted research spike; paper/code audit complete; implementation and
5
+ full-model measurement not started
6
+ **Target:** GLM-5.2 DSA on the M1 Max 32 GB Colibri path
7
+
8
+ ## Recommendation
9
+
10
+ Run the spike, but do not treat it as a new model feature. The GLM-5.2 path
11
+ already implements the checkpoint's cross-layer IndexShare schedule: retained
12
+ `full` layers run the DSA indexer and intervening `shared` layers reuse the most
13
+ recent selection. The useful work is to make that correctness path production
14
+ shaped, prove long-context parity, and measure whether the saved indexer work is
15
+ visible behind expert I/O on Apple Silicon.
16
+
17
+ The first prerequisite is the exact stock indexer overlay. The pinned public
18
+ Colibri artifact has no `out-idx-*` files, so every full-model result recorded
19
+ to date is DSA-off. The second prerequisite is a scalable indexer path: current
20
+ code materializes a large `[heads, context, head_dim]` product, copies every
21
+ score to the host, sorts the full score vector in JavaScript, and supports
22
+ sparse DSA only for single-token decode. Those choices are good correctness
23
+ scaffolding but cannot test the paper's long-prefill result.
24
+
25
+ This spike must not change the trained `full`/`shared` pattern or expose it as a
26
+ normal user knob. GLM-5.2 ships IndexShare as checkpoint architecture, not as an
27
+ optional quality/performance preset.
28
+
29
+ ## Naming and source claims
30
+
31
+ The linked paper calls the method **IndexCache**. The GLM-5.2 model card calls
32
+ the deployed architecture **IndexShare**. They use the same core mechanism:
33
+ cache the top-k positions produced by a retained DSA indexer and reuse them in
34
+ subsequent shared layers.
35
+
36
+ Primary sources:
37
+
38
+ - [IndexCache paper, arXiv:2603.12201v1](https://arxiv.org/abs/2603.12201v1)
39
+ - [authors' SGLang/vLLM reference patches](https://github.com/THUDM/IndexCache)
40
+ - [pinned GLM-5.2 model card](https://huggingface.co/zai-org/GLM-5.2/blob/f6142f127a14b58dc602592e996cd7d8ff139351/README.md)
41
+ - [pinned GLM-5.2 configuration](https://huggingface.co/zai-org/GLM-5.2/blob/f6142f127a14b58dc602592e996cd7d8ff139351/config.json)
42
+
43
+ The sources establish three different claims that must not be blended:
44
+
45
+ | Claim | Published evidence | What mlx-bun may say before local measurement |
46
+ |---|---|---|
47
+ | Cross-layer reuse | F layers compute top-k; S layers reuse the nearest preceding F layer | Implemented semantics, once parity is gated |
48
+ | IndexCache speed | On a 30B DSA model on an 8x H100 node, 1/4 retention reached up to 1.82x prefill and 1.48x per-request decode at 200K context | Paper result only; not a Mac prediction |
49
+ | GLM-5.2 IndexShare | The model card says one retained indexer per four sparse-attention layers reduces per-token FLOPs by 2.9x at 1M context | Vendor FLOP claim only; not end-to-end speed |
50
+
51
+ The paper also reports that uniform 1/4 retention hurts a frozen 30B model's
52
+ long-context average (50.2 to 43.0), while a loss-searched pattern recovers it
53
+ to 49.9. Training-aware IndexCache makes uniform interleaving viable. Therefore
54
+ mlx-bun must preserve GLM-5.2's trained schedule rather than search a new one
55
+ during this spike.
56
+
57
+ ## GLM-5.2 schedule
58
+
59
+ The pinned GLM-5.2 config has 78 layers, `index_topk=2048`,
60
+ `index_topk_freq=4`, and `index_skip_topk_offset=3`. Its explicit schedule has
61
+ 21 full and 57 shared layers:
62
+
63
+ ```text
64
+ FFFSSSFSSSFSSSF...FSSS
65
+ ```
66
+
67
+ Relative to an all-full counterfactual, the checkpoint omits 57/78 = 73.1% of
68
+ layer indexer invocations. It does not ship the missing shared-layer indexer
69
+ weights, so a true same-checkpoint `IndexShare off` A/B is impossible. Any
70
+ estimated all-full number must be labeled a component counterfactual, not an
71
+ end-to-end model benchmark.
72
+
73
+ `index_share_for_mtp_iteration` is a second, orthogonal optimization: reuse
74
+ indices across speculative draft iterations. mlx-bun parses that field but does
75
+ not currently consume it in the MTP runtime. Keep its measurement separate so
76
+ cross-layer IndexShare and MTP-iteration sharing each receive an attributable
77
+ result.
78
+
79
+ ## Current mlx-bun state
80
+
81
+ Already present:
82
+
83
+ - [`src/model/glm52-config.ts`](../../src/model/glm52-config.ts) parses explicit
84
+ `indexer_types` and the frequency/offset fallback.
85
+ - [`src/model/glm52.ts`](../../src/model/glm52.ts) constructs DSA indexers only
86
+ for full layers and passes one request-local selection state through the
87
+ decoder stack.
88
+ - [`src/model/glm52-dsa.ts`](../../src/model/glm52-dsa.ts) records a full
89
+ layer's exact dense/sparse selection and serves it to shared layers.
90
+ - [`tests/glm52-config-container.test.ts`](../../tests/glm52-config-container.test.ts)
91
+ and [`tests/glm52-dsa.test.ts`](../../tests/glm52-dsa.test.ts) cover schedule
92
+ parsing, missing-owner refusal, context consistency, and exact reuse.
93
+
94
+ Known blockers and likely bottlenecks:
95
+
96
+ 1. **No production DSA overlay.** The public Colibri artifact deliberately
97
+ disables DSA because every full-layer indexer tensor is absent. Producing the
98
+ exact overlay requires selective reads from 20 pinned source shards (about
99
+ 99.90 GiB input, about 197 MB output). This is a Josh-run acquisition step,
100
+ not an agent-session download.
101
+ 2. **No sparse long prefill.** `Glm52DsaIndexer.projectAndSelect()` rejects a
102
+ multi-token prefill once context exceeds `index_topk`. The paper's prefill
103
+ headline is therefore out of scope until chunked/sparse DSA prefill exists.
104
+ 3. **Quadratic transient shape.** `glm52DsaScoresMlx()` forms the broadcast
105
+ product before reduction. At production geometry this scales as
106
+ `32 * context * 128` float elements rather than streaming/tiled score
107
+ accumulation.
108
+ 4. **GPU-to-host top-k.** The full score vector crosses to a `Float32Array`,
109
+ then `selectDsaThresholdTiesF32()` clones and sorts all positions. This is
110
+ `O(context log context)` host work in each full layer, unlike the production
111
+ GPU top-k assumed by the paper.
112
+ 5. **Shared-index copies.** Shared layers clone the 2,048-element JavaScript
113
+ positions list, and absorbed MLA uploads it again before each gather. The
114
+ paper's temporary index tensor is reused in place. Measure this separately;
115
+ remove copies only after ownership and asynchronous lifetime are gated.
116
+ 6. **The current short-context bottleneck is elsewhere.** At 128 tokens the
117
+ full model is limited by streamed expert delivery, and DSA cannot prune a
118
+ prefix smaller than 2,048. No short-context speedup should be expected.
119
+
120
+ ## Hypotheses
121
+
122
+ - **H1 - component cost:** at the longest context that fits the 32 GB contract,
123
+ retained-indexer time is material and grows roughly linearly per decode token
124
+ with context length.
125
+ - **H2 - sharing value:** avoiding 57 of 78 indexer invocations removes a
126
+ measurable amount of counterfactual work even after a tiled score/top-k
127
+ kernel is used.
128
+ - **H3 - product value:** DSA plus the shipped IndexShare schedule improves
129
+ end-to-end long-context decode over DSA-off full attention, without token
130
+ drift from the official DSA runtime. This comparison measures the combined
131
+ sparse-attention product, not IndexShare in isolation.
132
+ - **H4 - MTP interaction:** any win remains a win with native MTP enabled. A
133
+ decode-only win that disappears under the product MTP path is not a default
134
+ performance claim.
135
+
136
+ ## Bounded experiment
137
+
138
+ ### Stage 0 - artifact and parity gate
139
+
140
+ 1. Generate the immutable `out-idx-*` overlay from the pinned
141
+ `zai-org/GLM-5.2-FP8` revision. Record source revision, selected shard list,
142
+ tensor inventory, byte count, and SHA-256 values. Do not mutate the 357 GiB
143
+ serving snapshot.
144
+ 2. Header-validate exactly the 21 full-layer indexers required by the shipped
145
+ schedule and prove that shared-layer indexers are neither required nor
146
+ silently loaded.
147
+ 3. Add an official-runtime oracle at contexts above 2,048. Gate selected
148
+ positions, logits on tie-free rows, and greedy token IDs before taking any
149
+ performance number.
150
+
151
+ #### Stage 0 result — pass (2026-08-17)
152
+
153
+ The stock overlay was generated outside mlx-bun from
154
+ `zai-org/GLM-5.2-FP8@ba978f7d347eaf65d22f1a86833408afdb953541`
155
+ with `colibri@ecade075cfc2eae684097ea7de5570c3786ce199`. It contains 20
156
+ `out-idx-*` files totaling 197,202,400 bytes. The existing header validator
157
+ finds 118,646 tensors, 59,066 quantized tensors, 19,456 routed experts,
158
+ complete DSA and MTP families, all 21 required full-layer indexers, and no
159
+ shared-layer indexer requirement.
160
+
161
+ The first-sparse gate prefills exactly 2,048 deterministic tokens, then sends
162
+ one greedy token at context 2,049 with MTP off. The mlx-bun probe observes the
163
+ 21 configured full layers and exactly 2,048 selected positions per layer. A
164
+ detached pinned Colibri build captures each official score row, selection,
165
+ float32 logit vector, and token trajectory. Replaying the captured scores with
166
+ `Glm52DsaSelectionState` gives:
167
+
168
+ - 21/21 exact ordered position vectors;
169
+ - 21/21 exact float32 thresholds;
170
+ - 21/21 tie-free boundaries, minimum boundary gap 0.025123596;
171
+ - exact greedy trajectory `[264, 264]` and the same sparse-step top-1 token;
172
+ - 154,880-logit cosine 0.997645, RMSE 0.200109, maximum absolute drift
173
+ 0.947218, with wide top-1 margins in both runtimes (9.571914 / 9.567580).
174
+
175
+ The direct full-runtime selections are 10/21 ordered-exact and 14/21
176
+ set-exact. Each of the seven set differences swaps only the single excluded
177
+ position at this top-2,048-of-2,049 boundary. This is upstream numerical drift
178
+ from the runtimes' different quantized-matmul accumulation before DSA, not a
179
+ selector mismatch; replaying identical official scores proves the isolated
180
+ DSA threshold/tie contract exactly. No performance claim is made from either
181
+ correctness run.
182
+
183
+ Reproduction is split between
184
+ `scripts/probe-colibri-glm52-dsa-long.ts` and
185
+ `scripts/check-colibri-glm52-dsa-long.ts`. The raw capture, external Colibri
186
+ instrumentation patch, and SHA-256 inventory are machine-local at
187
+ `~/.cache/mlx-bun/evidence/glm52-dsa-stage0-2026-08-17/`; manifest SHA-256 is
188
+ `6ecb88d944b055146dd700a1714af97b61845d4218527282fcbea009663fe3b4`.
189
+
190
+ ### Stage 1 - production-shaped indexer kernel
191
+
192
+ Build a model-free benchmark at exact geometry (`32` heads, head dimension
193
+ `128`, top-k `2048`) for contexts `2,048`, `8,192`, and `32,768`:
194
+
195
+ - tiled score accumulation that never materializes `[H,L,D]`;
196
+ - on-device/native deterministic top-k with the current threshold and
197
+ lower-position tie contract;
198
+ - one compact index buffer retained across F -> S layers;
199
+ - direct gather consumption without a score-vector host copy or per-shared-
200
+ layer index re-upload.
201
+
202
+ Compare the candidate against the existing reference composition for exact
203
+ selected positions on random, tied, all-equal, and production-captured rows.
204
+ Record kernel time, synchronization time, peak MLX allocation, process
205
+ footprint, and bytes copied to/from the host. Negative results count.
206
+
207
+ #### Stage 1 result — pass (2026-08-17)
208
+
209
+ The production path now computes `[H,D] @ [D,L] -> [H,L]` and never forms the
210
+ old `[H,L,D]` broadcast product. Deterministic device selection encodes the
211
+ lexicographic `(score descending, position ascending)` rank into `uint64`, uses
212
+ MLX `argpartition`, and then restores Colibri's observable two-scan ordering
213
+ (strictly above threshold first, threshold ties second). A FULL layer retains
214
+ only the resulting 2,048-entry, 8 KiB index buffer; SHARED layers borrow that
215
+ same device array and MLA gathers from it directly. Normal inference performs
216
+ no score/index host readback or per-SHARED-layer upload. The probe observer is
217
+ the explicit diagnostic exception.
218
+
219
+ Correctness gates pass for deterministic random rows, threshold ties,
220
+ all-equal rows, the exact 2,049/2,048 boundary, borrowed MLA consumption, and
221
+ all 21 production-captured Colibri score rows. The latter reproduce exact
222
+ ordered positions and float32 thresholds on device. A fresh full-model run
223
+ also reproduced all 21 prior mlx-bun position vectors and both greedy tokens;
224
+ its complete 154,880-float decode-logit payload is byte-identical (SHA-256
225
+ `d1f62be2de4877d2fc8ae8feab88e522958210252b50ef96eb786cb22581ba18`).
226
+ Tiled accumulation moved nine diagnostic thresholds by at most
227
+ `3.0517578125e-5`, but no selection boundary moved.
228
+
229
+ The exact-geometry, warm synchronized component benchmark (seven repeats) is:
230
+
231
+ | Context | Production behavior | Score median | Score + top-k median | Timed host copies | MLX peak |
232
+ |---:|---|---:|---:|---:|---:|
233
+ | 2,048 | dense boundary; production skips score/top-k | 0.448 ms (diagnostic only) | — | 0 B | 1.27 MiB |
234
+ | 8,192 | sparse | 0.473 ms | 0.929 ms | 0 B | 5.41 MiB |
235
+ | 32,768 | sparse | 0.748 ms | 1.269 ms | 0 B | 21.35 MiB |
236
+
237
+ At those contexts the removed broadcast product would have been 32, 128, and
238
+ 512 MiB respectively; the tiled dot output is 0.25, 1, and 4 MiB. These are
239
+ model-free component measurements, not end-to-end inference claims. The
240
+ benchmark is `scripts/bench-glm52-dsa-indexer.ts`. Machine-local evidence is
241
+ under `~/.cache/mlx-bun/evidence/glm52-dsa-stage1-2026-08-17/`; manifest
242
+ SHA-256 is
243
+ `600ec92c41d4c66735e1834a678a09f2ae55ecdddfab31c3dd1bf31ee9709fef`.
244
+
245
+ ### Stage 2 - decode matrix
246
+
247
+ Use direct library inference, not a server. Run separate fresh processes and
248
+ the standard quiet-machine preflight.
249
+
250
+ | Axis | Cells |
251
+ |---|---|
252
+ | Context | 2,048; 8,192; 32,768; 64K only if the exact planner remains inside the 25 GiB process ceiling |
253
+ | DSA | off/full attention; on with the checkpoint's 21F/57S schedule |
254
+ | MTP | off to isolate DSA; on for the product decision |
255
+ | Residency | the same fixed expert policy and seed profile in every paired arm |
256
+ | Repeats | three fresh processes per default-eligible cell; cold and warm turn in each process |
257
+
258
+ For each turn record TTFT, prefill wall time, decode tok/s, total wall time,
259
+ DSA projection/score/top-k/gather time, MLA time, expert disk service/wait,
260
+ target forwards, MTP acceptance, physical footprint, compression, swap, and
261
+ exact token IDs.
262
+
263
+ The DSA-off versus DSA-on result combines sparse core attention with
264
+ IndexShare. To estimate IndexShare's isolated contribution, report the measured
265
+ retained-indexer total and a clearly labeled all-full component counterfactual
266
+ derived from the same per-layer exact-geometry benchmark. Do not present that
267
+ counterfactual as a runnable checkpoint.
268
+
269
+ #### Stage 2 result — pass, negative product-performance decision (2026-08-17)
270
+
271
+ The fresh-process runner planned 36 cells. Twenty-four were eligible under the
272
+ G5 25 GiB process ceiling and completed: contexts 2,048 and 8,192, four DSA/MTP
273
+ arms, and three repeats. Every process ran cold and warm turns. Cold/warm,
274
+ cross-repeat, and MTP-off/on greedy token vectors were exact; all emitted
275
+ sixteen token IDs equal to `264`. The twelve 32K combinations were not run:
276
+ the exact planner reports 29,334,150,784 bytes (27.320 GiB) MTP-off and
277
+ 30,644,281,216 bytes (28.540 GiB) MTP-on, both above the unchanged 25 GiB
278
+ process limit. The initial refusal is retained in the evidence as an attempt
279
+ record. This is contract ineligibility, not an allocation crash.
280
+
281
+ Long prompts use an explicitly bounded benchmark seam: dense batched prompt
282
+ construction ends at the exact prompt boundary, and every subsequent decode or
283
+ MTP verification row uses exact DSA. These numbers characterize decode and
284
+ whole-turn wall time only. They are not sparse-prefill measurements.
285
+
286
+ Warm medians across three fresh processes are:
287
+
288
+ | Context | DSA | MTP | Decode tok/s | Total wall |
289
+ |---:|---|---|---:|---:|
290
+ | 2,048 | off | off | 0.1363 | 260.9 s |
291
+ | 2,048 | on | off | 0.1318 | 271.5 s |
292
+ | 2,048 | off | on | 0.1312 | 281.7 s |
293
+ | 2,048 | on | on | 0.0880 | 338.7 s |
294
+ | 8,192 | off | off | 0.1292 | 722.1 s |
295
+ | 8,192 | on | off | 0.1420 | 711.8 s |
296
+ | 8,192 | off | on | 0.1587 | 711.8 s |
297
+ | 8,192 | on | on | 0.1042 | 770.1 s |
298
+
299
+ At 8K without MTP, the paired median DSA delta is +12.38% decode throughput
300
+ and -1.89% total wall time. Expert I/O and prompt work hide most of the decode
301
+ gain, leaving the whole-turn result below the required 5%. With MTP enabled,
302
+ the paired median delta reverses to -34.33% decode throughput and +8.19% total
303
+ wall time. The exact MTP trace explains part of the product result: DSA-off
304
+ accepted ten drafts in five rounds (3.2 tokens/target forward, six target
305
+ calls), whereas DSA-on accepted eight drafts in seven rounds (2.286
306
+ tokens/target forward, eight target calls). Small verify batches now keep
307
+ residual/MLP/expert work batched, but exact causal sparse attention still runs
308
+ per verification row. Two of the three 8K DSA+MTP cells observed net swap
309
+ growth, so the memory side of the win gate also does not close.
310
+
311
+ The immutable external overlay retains 197,202,400 bytes of indexers. As a
312
+ clearly labeled non-runnable component counterfactual, Stage 1's 8K
313
+ score+top-k median implies 19.51 ms for the shipped 21 FULL layers versus
314
+ 72.48 ms for hypothetical 78 FULL layers, so IndexShare avoids about 52.97 ms
315
+ of selection work per target row. At 32K the corresponding component-only
316
+ figures are 26.64 ms, 98.95 ms, and 72.31 ms avoided. The checkpoint lacks the
317
+ 57 missing indexers, and these sums exclude the rest of model execution.
318
+
319
+ The product decision is negative: retain the exact 21F/57S implementation as
320
+ model semantics and land its correctness/scalability work, but make no local
321
+ end-to-end speed claim. Decode is conclusive, so Stage 3 remains a separate
322
+ deferred prefill experiment rather than a G6R exit requirement. Evidence is
323
+ under `~/.cache/mlx-bun/evidence/glm52-dsa-stage2-2026-08-17/`; manifest
324
+ SHA-256 is
325
+ `90b3fe4ed53714604b7a747991b3bb1b87aedbf57a139915065f5b4be42cda38`.
326
+
327
+ ### Stage 3 - deferred prefill follow-up
328
+
329
+ Only after decode is characterized, implement chunked sparse prefill with exact
330
+ causal selection semantics and run the same context ladder. This is the stage
331
+ that can test whether the paper's growing prefill benefit translates to MLX;
332
+ the existing single-token path cannot support that claim.
333
+
334
+ ## Decision rules
335
+
336
+ - Preserve the shipped 21F/57S schedule regardless of outcome; it is model
337
+ semantics.
338
+ - Call the work a local performance win only when three fresh MTP-on processes
339
+ are token-identical and the paired median end-to-end wall time improves by at
340
+ least 5% at a context that fits the 32 GB contract, without new swap or a
341
+ footprint regression outside the existing G5 bounds.
342
+ - If the kernel saves DSA time but expert I/O hides the wall win, land only the
343
+ correctness/scalability work and record the negative end-to-end result.
344
+ - Do not quote the paper's H100 speedups or GLM-5.2's 1M-token FLOP reduction as
345
+ mlx-bun speed. Curated claims require this machine's `benchmark.sh`-quality
346
+ evidence and belong in `benchmarks/RESULTS.md` only after the gate passes.
347
+ - Evaluate MTP-iteration index sharing as a separate follow-up with its own
348
+ on/off control and acceptance trace.
349
+
350
+ ## Exit
351
+
352
+ The spike closes when the DSA overlay is provenance-pinned, long-context
353
+ IndexShare matches an official runtime, the production-shaped score/top-k path
354
+ has exact model-free gates, and the paired MTP-off/on decode matrix has a
355
+ written decision. Prefill may remain a separately tracked follow-up only if the
356
+ decode result is already conclusive; otherwise sparse long prefill is required
357
+ before closure.
@@ -0,0 +1,80 @@
1
+ # v0.0.12 release notes
2
+
3
+ mlx-bun 0.0.12 completes the native Colibri/GLM-5.2 program: a Python-free,
4
+ direct-container runtime that can serve the approximately 357 GiB artifact on
5
+ a 32 GiB Apple Silicon Mac by keeping a bounded working set in memory and
6
+ streaming routed experts from fast storage.
7
+
8
+ ## GLM-5.2 direct-container serving
9
+
10
+ - Loads `mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp` directly. No converted
11
+ copy and no Python process are involved in the serving path.
12
+ - Preserves checkpoint precision and true top-8 routing. The port is gated
13
+ against pinned Colibri at tiny, production-component, real-model, MTP, cache,
14
+ and first-sparse DSA boundaries.
15
+ - Native int8 MTP is enabled by default and uses the serial speculative lane.
16
+ It produced a measured 1.306x warm end-to-end win over MTP-off on the 32 GiB
17
+ reference machine while preserving all target tokens.
18
+ - Compressed MLA/DSA/MTP cache persistence, restart restore, compressed-byte
19
+ admission, ordinary continuous batching, mixed-length join/leave/cancel, and
20
+ cross-row expert union are included. Per-row batched MTP remains a later
21
+ feature; MTP requests truthfully report `serial+spec`.
22
+ - Chat completions, text completions, Anthropic Messages, OpenAI Responses,
23
+ SSE, tools, structured output, stops, sampling, usage, and serial logprobs
24
+ are supported. Embeddings, vision/audio, LoRA, and training are explicitly
25
+ reported unsupported for this model instead of being emulated.
26
+
27
+ ## Memory and acquisition contract
28
+
29
+ - `mlx-bun get` now computes the exact remaining payload before the first
30
+ payload request, credits verified shared blobs and resumable prefixes, and
31
+ refuses an acquisition that cannot leave a fixed 1 GiB safety reserve.
32
+ - The GLM header-only preflight runs before resident weights or expert slabs
33
+ open. With the stock DSA overlay installed, 4,096 context / 128 generation
34
+ tokens and MTP on produce a 19.89 GiB plan under a 25 GiB process ceiling,
35
+ leaving 5.11 GiB of process/macOS headroom on a 32 GiB machine.
36
+ - `fit`, `/fit`, `/stats`, and the status page now distinguish the complete
37
+ artifact on disk from resident weights, main/MTP slabs, compressed KV, and
38
+ reserves. They also expose main/MTP residency, hit rate, SSD bytes, policy
39
+ telemetry, and repin events.
40
+
41
+ ## Performance: measured, not predicted
42
+
43
+ - Warm quality-preserving throughput on the M1 Max 32 GiB reference machine is
44
+ 0.1577 decode tok/s / 0.1487 end-to-end tok/s with MTP on. The same-machine
45
+ direct-Colibri control is approximately 0.27 tok/s.
46
+ - The 2 tok/s figure remains an aspiration, not a release gate or `fit`
47
+ prediction. The measured warm end-to-end result is 13.45x below it.
48
+ - Replicated telemetry measured 1,974,949,363,712 logical expert bytes per
49
+ 128-token warm turn (15.429 decimal GB/token) and a 1.66% cache hit rate.
50
+ Startup auto-pin, live LFRU, PILOT hints, two-step prediction, and coupling
51
+ did not improve paired end-to-end performance and remain off by default.
52
+ - The checkpoint's 21-full/57-shared DSA schedule is implemented and exact.
53
+ Paired 2K/8K tests did not establish an MTP-on product-speed win, so this
54
+ release makes no DSA speed claim. The public Colibri artifact does not ship
55
+ the stock DSA indexer overlay; without it the runtime follows the artifact's
56
+ available attention path.
57
+
58
+ ## Distribution and operator experience
59
+
60
+ - First-run native pack v0.2.0 adds the bounded native expert-I/O helper. The
61
+ npm/bunx fresh-cache path downloads, verifies, and extracts all five runtime
62
+ files; the signed/Homebrew bundle includes the same helper beside the binary.
63
+ - The pinned 32 GiB quickstart, volume selection, interrupted-download recovery,
64
+ model lineage, licenses, resource plan, measured performance, and limitations
65
+ are documented in README and the reference guides.
66
+ - The interactive Atlas report reproduces Colibri's expert topic-affinity
67
+ result: 29/30 leave-one-prompt-out classifications (96.7%) and 1,065 strong
68
+ specialists among 13,236 replicated experts.
69
+
70
+ ## Stability fixes since v0.0.11
71
+
72
+ - Closed pre-Colibri correctness and lifecycle findings, including expert-slab
73
+ post-close and lazy-graph reuse hazards, with forced native/MLX churn gates.
74
+ - Fixed selected-logprob readback stalling and revalidated the audio splice
75
+ boundary against the oracle.
76
+ - Corrected current Hugging Face LFS checksum-field handling and retained the
77
+ older spelling for compatibility.
78
+
79
+ Full provenance and exact numbers are in `benchmarks/RESULTS.md`, `STATUS.md`,
80
+ and `docs/design/colibri-glm52-port.md`.
@@ -26,6 +26,7 @@ mlx-bun serve # default model, http://localhost:808
26
26
  mlx-bun serve e4b # pick a model by substring
27
27
  mlx-bun serve gemma --memory-budget 18 # ...with admission control (GB)
28
28
  mlx-bun serve e4b --no-open # don't open the browser chat UI
29
+ mlx-bun serve GLM-5.2 --context-length 4096 # bounded Colibri runtime, native MTP
29
30
  ```
30
31
 
31
32
  Common flags (full list in [server-config.md](server-config.md)):
@@ -51,8 +52,10 @@ Common flags (full list in [server-config.md](server-config.md)):
51
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
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) |
53
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
+ | `--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
+ | `--context-length <n>` | GLM-5.2 context reserved by the header-only resource equation (default 4096) |
54
57
  | `--batch <n>` | Continuous-batched serving cap, mlx-lm B=N parity (default 8; `--batch 1` pins the serial path) |
55
- | `--temperature` / `--top-p` / `--top-k` / `--max-tokens` | Server-wide sampling defaults (per-request fields still win) |
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) |
56
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). |
57
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) |
58
61
  | `--no-open` | Don't auto-open the chat UI |
@@ -96,6 +99,7 @@ decode-path levers mirror `serve` (`--temperature`, `--seed`, `--l1/--l2`,
96
99
  ```sh
97
100
  mlx-bun generate gemma "a haiku about metal shaders"
98
101
  mlx-bun gen e4b --prompt "…" --max-tokens 512 --seed 42
102
+ mlx-bun generate GLM-5.2 --prompt "Explain DSA" --max-tokens 128
99
103
  ```
100
104
 
101
105
  ### `embed` — text embeddings
@@ -118,13 +122,21 @@ Full guide: [models.md](models.md).
118
122
  ### `get` — download a model
119
123
 
120
124
  Resumable, checksum-verified download into the standard Hugging Face cache
121
- (plain HTTPS, no Xet — no 0% stalls).
125
+ (plain HTTPS, no Xet — no 0% stalls). Before payload transfer, the downloader
126
+ credits complete blobs and partial prefixes, then requires enough free space
127
+ for the exact remainder plus a fixed 1 GiB reserve.
122
128
 
123
129
  ```sh
124
130
  mlx-bun get mlx-community/gemma-4-12B-it-OptiQ-4bit
125
131
  mlx-bun get 12B # no "/" = registry query; re-gets/refreshes the match
132
+ mlx-bun get mateogrgic/GLM-5.2-colibri-int4-with-int8-mtp \
133
+ --revision 3cc8db99b1b13fc79325d987ba3c1c430766b3b8
126
134
  ```
127
135
 
136
+ The GLM artifact is roughly 357 GiB; select `HF_HUB_CACHE` on a sufficiently
137
+ large fast volume before starting. Rerunning the same command resumes verified
138
+ `.incomplete` prefixes. See the [32 GB GLM quickstart](models.md#glm-52-on-a-32-gb-mac).
139
+
128
140
  ### `scan` — index your cache
129
141
 
130
142
  Re-index the HF cache into the registry (config + safetensors headers only,
@@ -165,6 +177,20 @@ mlx-bun fit gemma --ctx 32768 # for this machine
165
177
  mlx-bun fit gemma --ctx 8192 --skus # across the Apple Silicon lineup
166
178
  ```
167
179
 
180
+ The direct Colibri GLM-5.2 artifact is handled by its streamed-runtime
181
+ contract, not by the generic resident-weights estimator. `fit GLM-5.2`
182
+ defaults to the supported 4,096-token / 128-generation-token plan and reports
183
+ the artifact's disk footprint separately from resident weights, the main and
184
+ MTP expert slabs, KV, reserves, and the 25 GiB process ceiling. Its throughput
185
+ line is the measured warm quality-preserving result; the direct Colibri oracle
186
+ and the 2 tok/s aspiration are labeled separately. `--skus` explains that the
187
+ generic resident-model matrix does not apply to this streamed artifact.
188
+
189
+ ```sh
190
+ mlx-bun fit GLM-5.2
191
+ mlx-bun fit GLM-5.2 --ctx 4096
192
+ ```
193
+
168
194
  ## Training & model creation
169
195
 
170
196
  Full reference: [training.md](training.md); guided walkthrough:
@@ -14,6 +14,7 @@ tarball (~73 MB compressed, ~228 MB installed):
14
14
  |---|---|
15
15
  | `mlx-bun` | the CLI/server (`bun build --compile`), ~61 MB |
16
16
  | `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib` | MLX native runtime |
17
+ | `libmlx_bun_expert_io.dylib` | bounded native expert-streaming helper required by direct Colibri GLM-5.2 |
17
18
  | `mlx.metallib` | Metal kernels (~150 MB — the bulk) |
18
19
  | pi assets | `photon_rs_bg.wasm`, `theme/`, `assets/`, `export-html/`, `native/`, `package.json`, `CHANGELOG.md` |
19
20
 
@@ -171,7 +172,8 @@ mlx-bun --version
171
172
  The npm package is a thin launcher (no postinstall hook): it imports
172
173
  `src/cli.ts` under Bun, which fetches the small (~52 MB compressed,
173
174
  sha256-verified) native runtime pack — `libmlxc`/`libmlx`/`libjaccl`/
174
- `mlx.metallib` — into `~/Library/Caches/mlx-bun/` on first invocation if
175
+ `mlx.metallib` plus `libmlx_bun_expert_io.dylib` — into
176
+ `~/Library/Caches/mlx-bun/` on first invocation if
175
177
  no copy is already resolvable (env / beside the binary / cache /
176
178
  Homebrew). This is the same npm/sidecar mechanism described above, not
177
179
  the signed/notarized Homebrew bundle. `bun publish` is already run
@@ -182,3 +184,25 @@ fallback/retry:
182
184
  ```sh
183
185
  bun publish # manual retry; package.json version must already be bumped
184
186
  ```
187
+
188
+ ### Publishing the first-run native pack
189
+
190
+ The npm/bunx path has an independent, versioned release asset. Whenever its
191
+ file manifest changes, build and publish it before shipping code that names the
192
+ new `NATIVE_PACK_VERSION`:
193
+
194
+ ```sh
195
+ sh scripts/build-native-pack.sh 0.2.0 dist-native
196
+ gh release create native-v0.2.0 \
197
+ dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz \
198
+ dist-native/mlx-bun-native-v0.2.0-arm64.tar.gz.sha256 \
199
+ --title "mlx-bun native runtime v0.2.0" \
200
+ --notes "Adds the bounded native expert-I/O helper required by direct Colibri GLM-5.2."
201
+ ```
202
+
203
+ For v0.2.0 the arm64 archive is 52,307,647 bytes with SHA-256
204
+ `9bd3795c5ea8f52b18413501f2d68c32c264a20751302300a08dc04cd67df97c`.
205
+ It contains `libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib`,
206
+ `mlx.metallib`, and `libmlx_bun_expert_io.dylib`. These values must match
207
+ `src/native-pack.ts`; a fresh-cache extraction plus real MLX dlopen and native
208
+ expert read is the pre-publish smoke.
@@ -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 + three native libraries, dropped into your app's resources.
10
+ executable + four native libraries, dropped into your app's resources.
11
11
 
12
12
  ## Build the bundle
13
13
 
@@ -23,6 +23,7 @@ Produces a relocatable directory:
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
 
@@ -44,7 +45,9 @@ cache (`~/Library/Caches/mlx-bun/native-v<ver>-<arch>/`, populated on
44
45
  first run when no sidecar or homebrew install is found) → homebrew
45
46
  (`/opt/homebrew/lib`, `/usr/local/lib`). The whole directory can be
46
47
  renamed/moved; nothing references absolute paths after the build
47
- 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.
48
51
 
49
52
  ## Embedded pi web chat (`/ws/chat`)
50
53
 
@@ -22,7 +22,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
22
22
  | OpenAI Responses shim (`/v1/responses`) | on | both | — | — |
23
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
24
  | Prompt cache (prefix KV reuse) | on, 8 GB | both | — | `--prompt-cache <GB>` (0 = off) |
25
- | **SSD KV cold tier** (cache survives eviction + restarts) | off | both | — | `--ssd-cache <dir>` (+ `-max`, `-verify`, `-demote-idle <sec>` — default 300s once `--ssd-cache` is on, `0` disables) |
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` |
27
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
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` |
@@ -32,6 +32,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
32
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
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
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) |
35
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) |
36
37
  | Memory admission (refuse what can't fit; never GPU-OOM) | on (RAM × 0.75) | both | — | `--memory-budget <GB>` |
37
38
  | Aggregate KV admission for batch rows (queue, don't OOM) | off | batch | — | `--kv-budget <GB>` |
@@ -48,7 +49,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
48
49
  | `guided_grammar` (EBNF) / `guided_regex`¹ / `guided_choice` / `structured_outputs` | on | both | L2 | request fields |
49
50
  | Structured output × speculative decoding | on (when both active) | serial | Lab (validity+equivalence) | — |
50
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 |
51
- | Tool calling (Gemma sentinel / CPM+Qwen XML) + `role:"tool"` loops | on | both | — | request `tools` |
52
+ | Tool calling (Gemma sentinel / CPM+Qwen XML / GLM `arg_key`+`arg_value`) + `role:"tool"` loops | on | both | — | request `tools` |
52
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 |
53
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 |
54
55
  | LoRA adapters (mount at start / hot-swap at runtime) | off | serial | — | `--adapter <dir>`, `POST /v1/adapters` |
@@ -68,6 +69,7 @@ parity). **Tiers:** L1 = bit-exact vs mlx-lm · L2 = bit-exact vs mlx-optiq
68
69
  | MiniCPM5 (cpm5) | ✅ L1/L2 | ✅ | the starter model |
69
70
  | Gemma 4 (1B/e4b/12B/26B, + vision e4b/12B, + audio e4b) | ✅ L1/L2 | ✅ | sliding+full interleaved; MoE 26B |
70
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 |
71
73
  | DiffusionGemma-26B (non-autoregressive) | ✅ (own engine) | — serial always | first bit-exact non-AR port |
72
74
  | Tier-0 universal (llama/qwen2/qwen3/olmo2/…, 11 archs) | ✅ L1 | ✅ plain full-attention archs² | gemma2-family/sliding universal → serial |
73
75