mlx-bun 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/README.md +1453 -88
  2. package/THIRD_PARTY_NOTICES.md +882 -0
  3. package/bin/mlx-bun.convert.mjs +4 -0
  4. package/bin/mlx-bun.fuse.mjs +4 -0
  5. package/bin/mlx-bun.generate.mjs +4 -0
  6. package/bin/mlx-bun.lora.mjs +4 -0
  7. package/bin/mlx-bun.mjs +13 -21
  8. package/bin/mlx-bun.server.mjs +4 -0
  9. package/bin/mlx-bun.upload.mjs +4 -0
  10. package/dist/web/app.js +9584 -0
  11. package/package.json +50 -53
  12. package/src/cli/ane-install.ts +76 -0
  13. package/src/cli/args.ts +179 -0
  14. package/src/cli/engine-entry.ts +68 -0
  15. package/src/cli/inference.ts +214 -0
  16. package/src/cli/job-entry.ts +97 -0
  17. package/src/cli/library-host.ts +117 -0
  18. package/src/cli/main.ts +57 -0
  19. package/src/cli/memory-engine.ts +163 -0
  20. package/src/cli/memory.ts +36 -0
  21. package/src/cli/mlx-lm-aliases.ts +309 -0
  22. package/src/cli/model-choice.ts +33 -0
  23. package/src/cli/model-selection.ts +84 -0
  24. package/src/cli/module-host.ts +11 -0
  25. package/src/cli/module-verbs.ts +50 -0
  26. package/src/cli/numerical-policy.ts +12 -0
  27. package/src/cli/perplexity.ts +89 -0
  28. package/src/cli/serve-host.ts +423 -0
  29. package/src/cli/serve-isolated.ts +217 -0
  30. package/src/cli/serve-options.ts +106 -0
  31. package/src/cli/serve-state.ts +205 -0
  32. package/src/cli/serve.ts +500 -0
  33. package/src/cli/served-model-host.ts +102 -0
  34. package/src/cli/server-entry.ts +148 -0
  35. package/src/cli/serving-unit.ts +177 -0
  36. package/src/{tui.ts → cli/terminal.ts} +13 -8
  37. package/src/cli/worker-adapters.ts +34 -0
  38. package/src/cli/worker-entry.ts +272 -0
  39. package/src/cli/worker-unit.ts +179 -0
  40. package/src/engine/adapter-operation.ts +26 -0
  41. package/src/engine/cache-services.ts +114 -0
  42. package/src/engine/completion.ts +39 -0
  43. package/src/engine/generation-gateway.ts +358 -0
  44. package/src/engine/index.ts +59 -0
  45. package/src/engine/kv-budget.ts +120 -0
  46. package/src/engine/media-preparation.ts +232 -0
  47. package/src/engine/model-binding.ts +24 -0
  48. package/src/engine/model-host.ts +513 -0
  49. package/src/engine/model-serving.ts +89 -0
  50. package/src/{serve → engine}/preparation.ts +10 -8
  51. package/src/{serve → engine}/session-completion-engine.ts +6 -6
  52. package/src/engine/telemetry.ts +109 -0
  53. package/src/hub/downloads.ts +116 -0
  54. package/src/jobs/db.ts +16 -7
  55. package/src/jobs/events.ts +29 -0
  56. package/src/jobs/executable.ts +5 -0
  57. package/src/jobs/host.ts +51 -0
  58. package/src/jobs/in-process.ts +55 -0
  59. package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
  60. package/src/jobs/runner.ts +150 -231
  61. package/src/jobs/service.ts +75 -0
  62. package/src/jobs/sse.ts +59 -23
  63. package/src/jobs/worker-memory.ts +46 -0
  64. package/src/jobs/worker-process.ts +163 -0
  65. package/src/jobs/worker-supervisor.ts +258 -0
  66. package/src/modules.ts +58 -0
  67. package/src/publishing/catalog-hub.ts +18 -0
  68. package/src/publishing/credentials.ts +31 -0
  69. package/src/publishing/upload.ts +37 -0
  70. package/src/residency/leased-adapters.ts +21 -0
  71. package/src/residency/local-records.ts +16 -0
  72. package/src/residency/model-residency.ts +405 -0
  73. package/src/residency/record-index.ts +28 -0
  74. package/src/residency/resident-estimate.ts +50 -0
  75. package/src/{anthropic.ts → server/anthropic.ts} +3 -81
  76. package/src/server/cache-routes.ts +36 -0
  77. package/src/{serve → server}/chat-request.ts +12 -10
  78. package/src/{serve → server}/chat-stage.ts +27 -22
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +42 -42
  81. package/src/server/decision-body.ts +55 -0
  82. package/src/server/decision-routes.ts +134 -0
  83. package/src/server/decision-wire.ts +228 -0
  84. package/src/{serve → server}/discovery-routes.ts +42 -83
  85. package/src/server/generated-token-history.ts +57 -0
  86. package/src/{serve → server}/http.ts +25 -13
  87. package/src/{serve → server}/inference-request.ts +5 -5
  88. package/src/server/job-routes.ts +20 -0
  89. package/src/server/media-prompt.ts +63 -0
  90. package/src/server/memory-completion-client.ts +46 -0
  91. package/src/server/model-routes.ts +192 -0
  92. package/src/{serve → server}/openai-wire.ts +3 -2
  93. package/src/{serve → server}/pipeline.ts +1 -1
  94. package/src/server/prompt-builder.ts +13 -0
  95. package/src/server/prompt-contracts.ts +17 -0
  96. package/src/server/proxy-routes.ts +187 -0
  97. package/src/server/publishing-routes.ts +41 -0
  98. package/src/{serve → server}/request-plan.ts +8 -8
  99. package/src/{serve → server}/request-prep.ts +82 -68
  100. package/src/{serve → server}/responses-client.ts +30 -13
  101. package/src/{responses.ts → server/responses.ts} +12 -93
  102. package/src/server/routes.ts +205 -0
  103. package/src/server/start.ts +72 -0
  104. package/src/server/status-routes.ts +108 -0
  105. package/src/{serve → server}/text-completion-stage.ts +25 -4
  106. package/src/server/text-prompt.ts +12 -0
  107. package/src/{serve → server}/token-streams.ts +36 -38
  108. package/src/server/worker-routes.ts +311 -0
  109. package/src/storage/paths.ts +61 -0
  110. package/src/web/assets.ts +37 -0
  111. package/src/web/{src → browser}/api.ts +5 -23
  112. package/src/web/browser/chat-host.ts +17 -0
  113. package/src/web/browser/installed-panels.ts +6 -0
  114. package/src/web/browser/main.ts +55 -0
  115. package/src/web/browser/markdown.ts +279 -0
  116. package/src/web/browser/memory-panel.ts +9 -0
  117. package/src/web/browser/palette.ts +64 -0
  118. package/src/web/browser/protocol.ts +13 -0
  119. package/src/web/browser/shell.ts +467 -0
  120. package/src/web/{src → browser}/status.ts +32 -36
  121. package/src/web/build.ts +51 -0
  122. package/src/web/public/app.html +1054 -0
  123. package/src/web/{sw.js → public/sw.js} +4 -3
  124. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  125. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  126. package/THIRD_PARTY_LICENSES.md +0 -51
  127. package/docs/README.md +0 -94
  128. package/docs/archive/hlg-sampling.md +0 -350
  129. package/docs/archive/investigations/audio-input-plan.md +0 -356
  130. package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
  131. package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
  132. package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
  133. package/docs/archive/investigations/curve-bisector-routing.md +0 -123
  134. package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
  135. package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
  136. package/docs/archive/investigations/dspark-handoff.md +0 -224
  137. package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
  138. package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
  139. package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
  140. package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
  141. package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
  142. package/docs/archive/investigations/lab-build-journal.md +0 -157
  143. package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
  144. package/docs/archive/investigations/openjarvis-fit.md +0 -198
  145. package/docs/archive/investigations/openwiki-evaluation.md +0 -249
  146. package/docs/archive/investigations/optimization_plan.md +0 -346
  147. package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
  148. package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
  149. package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
  150. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
  151. package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
  152. package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
  153. package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
  154. package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
  155. package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
  156. package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
  157. package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
  158. package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
  159. package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
  160. package/docs/archive/planning/chat-ui-vision.md +0 -50
  161. package/docs/archive/planning/chunk-task-roadmap.md +0 -77
  162. package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
  163. package/docs/archive/planning/journal.md +0 -316
  164. package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
  165. package/docs/archive/planning/pi-integration-review.md +0 -178
  166. package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
  167. package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
  168. package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
  169. package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
  170. package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
  171. package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
  172. package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
  173. package/docs/archive/planning/web-ui-pass-plan.md +0 -213
  174. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  175. package/docs/design/batching.md +0 -1841
  176. package/docs/design/decode-speed-program.md +0 -2349
  177. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  178. package/docs/design/generic-model-support.md +0 -705
  179. package/docs/design/kv-cache.md +0 -824
  180. package/docs/design/orpo-training.md +0 -680
  181. package/docs/design/speculative-decoding.md +0 -1990
  182. package/docs/design/turboquant.md +0 -2212
  183. package/docs/design/unified-engine-frontier-plan.md +0 -1880
  184. package/docs/design/web-chat-redesign.md +0 -695
  185. package/docs/planning/PRODUCT_ROADMAP.md +0 -594
  186. package/docs/planning/ResearchTopics.md +0 -119
  187. package/docs/planning/release-notes-v0.4.0.md +0 -45
  188. package/docs/planning/video-series.md +0 -421
  189. package/docs/reference/benchmarks.md +0 -3613
  190. package/docs/reference/cli.md +0 -585
  191. package/docs/reference/distribution.md +0 -355
  192. package/docs/reference/environment.md +0 -398
  193. package/docs/reference/glossary.md +0 -39
  194. package/docs/reference/library-api.md +0 -674
  195. package/docs/reference/memory.md +0 -260
  196. package/docs/reference/models.md +0 -334
  197. package/docs/reference/server-api.md +0 -1775
  198. package/docs/reference/server-config.md +0 -846
  199. package/docs/reference/training.md +0 -462
  200. package/docs/reference/troubleshooting.md +0 -158
  201. package/src/admission-plan.ts +0 -18
  202. package/src/audio/conformer.ts +0 -647
  203. package/src/audio/decode.ts +0 -133
  204. package/src/audio/features.ts +0 -202
  205. package/src/audio/transcode.ts +0 -67
  206. package/src/backends/mlx/assistant-target.ts +0 -46
  207. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  208. package/src/backends/mlx/autoregressive.ts +0 -108
  209. package/src/backends/mlx/batch-group.ts +0 -1790
  210. package/src/backends/mlx/cache-attachment.ts +0 -67
  211. package/src/backends/mlx/cache-layout.ts +0 -31
  212. package/src/backends/mlx/checkpoint-state.ts +0 -53
  213. package/src/backends/mlx/continuation-persistence.ts +0 -106
  214. package/src/backends/mlx/continuation-request.ts +0 -43
  215. package/src/backends/mlx/continuation.ts +0 -77
  216. package/src/backends/mlx/diffusion.ts +0 -39
  217. package/src/backends/mlx/draft-target.ts +0 -32
  218. package/src/backends/mlx/evaluation.ts +0 -105
  219. package/src/backends/mlx/fill-append.ts +0 -45
  220. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  221. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  222. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  223. package/src/backends/mlx/gateway-binding.ts +0 -130
  224. package/src/backends/mlx/graph.ts +0 -38
  225. package/src/backends/mlx/kv-codec.ts +0 -9
  226. package/src/backends/mlx/kv-maintenance.ts +0 -133
  227. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  228. package/src/backends/mlx/memory-client.ts +0 -189
  229. package/src/backends/mlx/methods.ts +0 -90
  230. package/src/backends/mlx/model-prompt.ts +0 -164
  231. package/src/backends/mlx/model-serving.ts +0 -79
  232. package/src/backends/mlx/prefill-cohort.ts +0 -89
  233. package/src/backends/mlx/prefill-rows.ts +0 -200
  234. package/src/backends/mlx/prefill.ts +0 -33
  235. package/src/backends/mlx/projected-context-rows.ts +0 -72
  236. package/src/backends/mlx/request-policy.ts +0 -20
  237. package/src/backends/mlx/request-state-policy.ts +0 -41
  238. package/src/backends/mlx/rollback.ts +0 -89
  239. package/src/backends/mlx/row-sampling.ts +0 -49
  240. package/src/backends/mlx/serial-executor.ts +0 -242
  241. package/src/backends/mlx/speculative-group.ts +0 -359
  242. package/src/backends/mlx/speculative-round.ts +0 -161
  243. package/src/backends/mlx/speculative.ts +0 -114
  244. package/src/backends/mlx/state-rows.ts +0 -104
  245. package/src/backends/mlx/state-views.ts +0 -46
  246. package/src/backends/mlx/target-layout-capability.ts +0 -35
  247. package/src/backends/mlx/text-engine.ts +0 -73
  248. package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
  249. package/src/chat-template.ts +0 -382
  250. package/src/cli.ts +0 -3168
  251. package/src/config.ts +0 -399
  252. package/src/contracts/completion.ts +0 -16
  253. package/src/contracts/execution.ts +0 -60
  254. package/src/contracts/generation.ts +0 -103
  255. package/src/contracts/host.ts +0 -7
  256. package/src/contracts/pi-provider.ts +0 -30
  257. package/src/contracts/pi.ts +0 -259
  258. package/src/contracts/prefix-cache.ts +0 -23
  259. package/src/contracts/resources.ts +0 -25
  260. package/src/contracts/sampling.ts +0 -23
  261. package/src/contracts/scheduling.ts +0 -45
  262. package/src/contracts/tsconfig.json +0 -14
  263. package/src/dataset/generators.ts +0 -1087
  264. package/src/dataset/index.ts +0 -12
  265. package/src/dataset/job.ts +0 -81
  266. package/src/dataset/llm.ts +0 -71
  267. package/src/dataset/registry.ts +0 -528
  268. package/src/diffusion/diffusion-generate.ts +0 -507
  269. package/src/download.ts +0 -505
  270. package/src/embed.ts +0 -77
  271. package/src/engine/admission.ts +0 -59
  272. package/src/engine/cancellation.ts +0 -38
  273. package/src/engine/engine.ts +0 -56
  274. package/src/engine/execution-coordinator.ts +0 -70
  275. package/src/engine/execution-plan.ts +0 -53
  276. package/src/engine/resources.ts +0 -53
  277. package/src/engine/scheduler.ts +0 -72
  278. package/src/engine/session.ts +0 -247
  279. package/src/eval/README.md +0 -130
  280. package/src/eval/ifeval.ts +0 -81
  281. package/src/eval/kl-prompts.ts +0 -29
  282. package/src/eval/kl.ts +0 -590
  283. package/src/eval/perplexity.ts +0 -164
  284. package/src/eval/quality-db.ts +0 -92
  285. package/src/eval/reference-logits.ts +0 -207
  286. package/src/eval/runner.ts +0 -124
  287. package/src/eval/score.ts +0 -49
  288. package/src/eval/tasks/bfcl.ts +0 -535
  289. package/src/eval/tasks/gsm8k.ts +0 -98
  290. package/src/eval/tasks/hashhop.ts +0 -139
  291. package/src/eval/tasks/humaneval.ts +0 -275
  292. package/src/eval/tasks/ifeval.ts +0 -525
  293. package/src/eval/tasks/mmlu.ts +0 -157
  294. package/src/eval/ultrafeedback.ts +0 -60
  295. package/src/evaldb.ts +0 -199
  296. package/src/expert-io.ts +0 -393
  297. package/src/expert-offload-build.ts +0 -77
  298. package/src/expert-offload.ts +0 -76
  299. package/src/expert-residency.ts +0 -1134
  300. package/src/expert-usage.ts +0 -415
  301. package/src/fill/echo-index.ts +0 -188
  302. package/src/fill/fill-session.ts +0 -452
  303. package/src/fill/proposal.ts +0 -68
  304. package/src/fill/schema-rows.ts +0 -506
  305. package/src/fill/tool-boundary.ts +0 -103
  306. package/src/fit.ts +0 -249
  307. package/src/generate.ts +0 -1346
  308. package/src/grammar.ts +0 -591
  309. package/src/harness-pi.ts +0 -184
  310. package/src/hf-push.ts +0 -628
  311. package/src/hub-rest.ts +0 -242
  312. package/src/index.ts +0 -63
  313. package/src/inference/denoising.ts +0 -17
  314. package/src/inference/draft-acceptance.ts +0 -41
  315. package/src/inference/draft-output.ts +0 -49
  316. package/src/inference/graph.ts +0 -33
  317. package/src/inference/prefill.ts +0 -39
  318. package/src/inference/rollback.ts +0 -7
  319. package/src/jobs/index.ts +0 -31
  320. package/src/jobs/job-entry.ts +0 -107
  321. package/src/jobs/task-client.ts +0 -19
  322. package/src/jobs/types.ts +0 -2
  323. package/src/kv-scheme.ts +0 -257
  324. package/src/kv-store.ts +0 -1099
  325. package/src/lab/README.md +0 -18
  326. package/src/lab/curve/curve-designer.html +0 -303
  327. package/src/lab/curve/curve-sampler.ts +0 -122
  328. package/src/lab/expert-trace/expert-trace.ts +0 -69
  329. package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
  330. package/src/lab/paged-kv/paged-kv.ts +0 -270
  331. package/src/library.ts +0 -40
  332. package/src/lora.ts +0 -408
  333. package/src/md-modules.d.ts +0 -49
  334. package/src/media-fetch.ts +0 -442
  335. package/src/memory/article.ts +0 -558
  336. package/src/memory/chunk-validation.ts +0 -150
  337. package/src/memory/chunk.ts +0 -318
  338. package/src/memory/cluster.ts +0 -351
  339. package/src/memory/coverage.ts +0 -134
  340. package/src/memory/crosslink.ts +0 -0
  341. package/src/memory/db.ts +0 -253
  342. package/src/memory/entity.ts +0 -203
  343. package/src/memory/gate.ts +0 -187
  344. package/src/memory/history.ts +0 -152
  345. package/src/memory/ingest.ts +0 -335
  346. package/src/memory/model.ts +0 -183
  347. package/src/memory/normalize.ts +0 -671
  348. package/src/memory/parse.ts +0 -22
  349. package/src/memory/pipeline.ts +0 -275
  350. package/src/memory/prompts.ts +0 -65
  351. package/src/memory/query.ts +0 -334
  352. package/src/memory/reconcile.ts +0 -734
  353. package/src/memory/redirect.ts +0 -108
  354. package/src/memory/reindex.ts +0 -325
  355. package/src/memory/resolve.ts +0 -307
  356. package/src/memory/rest.ts +0 -245
  357. package/src/memory/route.ts +0 -272
  358. package/src/memory/schedule.ts +0 -165
  359. package/src/memory/stages.ts +0 -777
  360. package/src/memory/synthesize.ts +0 -1638
  361. package/src/memory/tools.ts +0 -749
  362. package/src/memory/vault.ts +0 -1194
  363. package/src/memory/wikify.ts +0 -1064
  364. package/src/mlx/array.ts +0 -388
  365. package/src/mlx/autograd.ts +0 -304
  366. package/src/mlx/checkpoint.ts +0 -149
  367. package/src/mlx/compile.ts +0 -168
  368. package/src/mlx/custom-vjp.ts +0 -188
  369. package/src/mlx/ffi.ts +0 -512
  370. package/src/mlx/materialize.ts +0 -23
  371. package/src/mlx/metal-kernel.ts +0 -159
  372. package/src/mlx/ops.ts +0 -1021
  373. package/src/mlx/quantized-rows.ts +0 -36
  374. package/src/mlx/token-bitmask.ts +0 -52
  375. package/src/mlx/turboquant-kv-decode.ts +0 -82
  376. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  377. package/src/mlx/turboquant-ops.ts +0 -861
  378. package/src/mlx/turboquant-tables.ts +0 -237
  379. package/src/mmap.ts +0 -90
  380. package/src/model/artifact-identity.ts +0 -73
  381. package/src/model/batched-kv.ts +0 -235
  382. package/src/model/batched-mask.ts +0 -279
  383. package/src/model/batched-quant.ts +0 -212
  384. package/src/model/batched-quantized-kv.ts +0 -144
  385. package/src/model/batched-rotating-quant.ts +0 -353
  386. package/src/model/batched-rotating-state.ts +0 -149
  387. package/src/model/batched-rotating.ts +0 -338
  388. package/src/model/batched-row-storage.ts +0 -179
  389. package/src/model/batched-ssm.ts +0 -52
  390. package/src/model/batched-turboquant-kv.ts +0 -93
  391. package/src/model/compiled-decode.ts +0 -712
  392. package/src/model/decoded-kv-donor.ts +0 -12
  393. package/src/model/delayed-quantized-kv.ts +0 -72
  394. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  395. package/src/model/delayed-turboquant-kv.ts +0 -55
  396. package/src/model/diffusion-gemma.ts +0 -1026
  397. package/src/model/factory.ts +0 -189
  398. package/src/model/fingerprint.ts +0 -33
  399. package/src/model/flash-attention.ts +0 -694
  400. package/src/model/full-prefill-padding.ts +0 -56
  401. package/src/model/full-prefill-row.ts +0 -105
  402. package/src/model/gemma4-base.ts +0 -2351
  403. package/src/model/gemma4.ts +0 -1315
  404. package/src/model/generated/gemma4-12b.ts +0 -429
  405. package/src/model/generated/gemma4-26b.ts +0 -448
  406. package/src/model/generated/gemma4-e4b.ts +0 -717
  407. package/src/model/generated/index.ts +0 -18
  408. package/src/model/glm52-atlas.ts +0 -511
  409. package/src/model/glm52-cache.ts +0 -792
  410. package/src/model/glm52-config.ts +0 -262
  411. package/src/model/glm52-container.ts +0 -305
  412. package/src/model/glm52-coupling.ts +0 -388
  413. package/src/model/glm52-dsa.ts +0 -606
  414. package/src/model/glm52-expert-layout.ts +0 -253
  415. package/src/model/glm52-layout.ts +0 -152
  416. package/src/model/glm52-memory.ts +0 -500
  417. package/src/model/glm52-mla.ts +0 -792
  418. package/src/model/glm52-moe.ts +0 -223
  419. package/src/model/glm52-pilot.ts +0 -537
  420. package/src/model/glm52-reference.ts +0 -445
  421. package/src/model/glm52-residency.ts +0 -557
  422. package/src/model/glm52-resident-weights.ts +0 -135
  423. package/src/model/glm52-streamed-experts.ts +0 -453
  424. package/src/model/glm52-streamed-metal.ts +0 -610
  425. package/src/model/glm52-weights.ts +0 -503
  426. package/src/model/glm52.ts +0 -1132
  427. package/src/model/implementation.ts +0 -69
  428. package/src/model/kv-attention-view.ts +0 -67
  429. package/src/model/minicpm5.ts +0 -376
  430. package/src/model/profile.ts +0 -443
  431. package/src/model/qwen-append.ts +0 -12
  432. package/src/model/qwen-conv.ts +0 -52
  433. package/src/model/qwen3-delta-state.ts +0 -74
  434. package/src/model/qwen3-delta.ts +0 -451
  435. package/src/model/qwen3-moe.ts +0 -404
  436. package/src/model/qwen3-mrope.ts +0 -252
  437. package/src/model/qwen3.ts +0 -277
  438. package/src/model/qwen3_5-checkpoint.ts +0 -164
  439. package/src/model/qwen3_5.ts +0 -819
  440. package/src/model/rotating-kv-donor.ts +0 -35
  441. package/src/model/rotating-kv-layout.ts +0 -262
  442. package/src/model/rotating-row-transaction.ts +0 -35
  443. package/src/model/speculative-rotating-kv.ts +0 -101
  444. package/src/model/ssm-prefill-padding.ts +0 -39
  445. package/src/model/support.ts +0 -102
  446. package/src/model/trellis-balanced-scatter.ts +0 -51
  447. package/src/model/trellis-linear.ts +0 -672
  448. package/src/model/trellis-shared-m.ts +0 -151
  449. package/src/model/trellis-shared-scatter.ts +0 -144
  450. package/src/model/trellis-splitk-prefill.ts +0 -158
  451. package/src/model/trellis-tiled-prefill.ts +0 -136
  452. package/src/model/trellis-vector-expand.ts +0 -62
  453. package/src/model/trellis-wide-prefill.ts +0 -94
  454. package/src/model/turboquant-codec.ts +0 -83
  455. package/src/model/universal/archs.ts +0 -332
  456. package/src/model/universal/dense.ts +0 -612
  457. package/src/model/universal/modules.ts +0 -170
  458. package/src/model/universal/rope.ts +0 -381
  459. package/src/native/expert_io.c +0 -523
  460. package/src/native/frame_extract.swift +0 -140
  461. package/src/native-pack.ts +0 -162
  462. package/src/pi-provider.ts +0 -53
  463. package/src/pi-session.ts +0 -81
  464. package/src/pi-terminal.ts +0 -274
  465. package/src/pi-web.ts +0 -1932
  466. package/src/preflight.ts +0 -158
  467. package/src/prompt-cache.ts +0 -460
  468. package/src/quantize/allocator.ts +0 -627
  469. package/src/quantize/atomic-output.ts +0 -38
  470. package/src/quantize/calibration.ts +0 -181
  471. package/src/quantize/config-writer.ts +0 -145
  472. package/src/quantize/index.ts +0 -84
  473. package/src/quantize/job.ts +0 -162
  474. package/src/quantize/quantizer.ts +0 -666
  475. package/src/quantize/rotate.ts +0 -603
  476. package/src/quantize/safetensors-writer.ts +0 -249
  477. package/src/quantize/sensitivity.ts +0 -216
  478. package/src/quantize/trellis.ts +0 -586
  479. package/src/quantize/weight-transform.ts +0 -292
  480. package/src/registry.ts +0 -602
  481. package/src/runtime-config.ts +0 -81
  482. package/src/safetensors.ts +0 -158
  483. package/src/sampler.ts +0 -1011
  484. package/src/serve/admin-routes.ts +0 -184
  485. package/src/serve/assets/curve-terrain.html +0 -105
  486. package/src/serve/assets/training-inference-map.html +0 -575
  487. package/src/serve/aux-routes.ts +0 -132
  488. package/src/serve/batch-scheduler.ts +0 -8
  489. package/src/serve/checkpoint-identity.ts +0 -64
  490. package/src/serve/generation-gateway.ts +0 -496
  491. package/src/serve/isolate.ts +0 -609
  492. package/src/serve/kv-budget.ts +0 -14
  493. package/src/serve/lab-routes.ts +0 -341
  494. package/src/serve/lane-registry.ts +0 -45
  495. package/src/serve/model-admin-routes.ts +0 -155
  496. package/src/serve/model-binding.ts +0 -43
  497. package/src/serve/model-host.ts +0 -511
  498. package/src/serve/parent-application.ts +0 -56
  499. package/src/serve/prompt-response-trace.ts +0 -147
  500. package/src/serve/response-lease.ts +0 -24
  501. package/src/serve/session-search.ts +0 -326
  502. package/src/serve/static-routes.ts +0 -101
  503. package/src/server.ts +0 -1314
  504. package/src/spec/assistant-rows.ts +0 -92
  505. package/src/spec/assistant-source.ts +0 -126
  506. package/src/spec/cache-identity.ts +0 -22
  507. package/src/spec/deepspec-rows.ts +0 -29
  508. package/src/spec/deepspec-source.ts +0 -145
  509. package/src/spec/dflash-source.ts +0 -149
  510. package/src/spec/drafter.ts +0 -304
  511. package/src/spec/dspark/ab-stats.ts +0 -136
  512. package/src/spec/dspark/calibration.ts +0 -112
  513. package/src/spec/dspark/data-dflash.ts +0 -156
  514. package/src/spec/dspark/data.ts +0 -201
  515. package/src/spec/dspark/deepspec-module.ts +0 -776
  516. package/src/spec/dspark/generate-dflash.ts +0 -245
  517. package/src/spec/dspark/generate.ts +0 -290
  518. package/src/spec/dspark/loader.ts +0 -23
  519. package/src/spec/dspark/loss.ts +0 -213
  520. package/src/spec/dspark/module-dflash.ts +0 -560
  521. package/src/spec/dspark/module.ts +0 -540
  522. package/src/spec/dspark/quantize-drafter.ts +0 -91
  523. package/src/spec/dspark/sample.ts +0 -112
  524. package/src/spec/generate.ts +0 -276
  525. package/src/spec/glm52-mtp-graph.ts +0 -29
  526. package/src/spec/glm52-mtp-rows.ts +0 -132
  527. package/src/spec/glm52-mtp-source.ts +0 -317
  528. package/src/spec/glm52-mtp-state.ts +0 -33
  529. package/src/spec/ngram-source.ts +0 -204
  530. package/src/spec/projected-draft-rows.ts +0 -73
  531. package/src/spec/qwen-mtp-module.ts +0 -171
  532. package/src/spec/qwen-mtp-rows.ts +0 -219
  533. package/src/spec/qwen-mtp-source.ts +0 -383
  534. package/src/spec/qwen-mtp-state.ts +0 -30
  535. package/src/spec/serve-loop.ts +0 -585
  536. package/src/spec/source.ts +0 -215
  537. package/src/spec/two-model-rows.ts +0 -61
  538. package/src/spec/two-model.ts +0 -113
  539. package/src/ssd-cache.ts +0 -372
  540. package/src/ssd-durability.ts +0 -211
  541. package/src/tokenizer.ts +0 -335
  542. package/src/tool-approvals.ts +0 -131
  543. package/src/tool-call.ts +0 -695
  544. package/src/train/dataset.ts +0 -484
  545. package/src/train/diffusion-lora.ts +0 -216
  546. package/src/train/export.ts +0 -32
  547. package/src/train/flash-cce.ts +0 -1234
  548. package/src/train/forward.ts +0 -266
  549. package/src/train/fuse.ts +0 -243
  550. package/src/train/index.ts +0 -46
  551. package/src/train/job.ts +0 -205
  552. package/src/train/lora-params.ts +0 -254
  553. package/src/train/loss.ts +0 -1591
  554. package/src/train/merge.ts +0 -195
  555. package/src/train/optimizer.ts +0 -183
  556. package/src/train/prefix-shared.ts +0 -490
  557. package/src/train/rank.ts +0 -137
  558. package/src/train/segmented.ts +0 -1828
  559. package/src/train/steel-qmm-header.ts +0 -1461
  560. package/src/train/trainer.ts +0 -1221
  561. package/src/train/watch.ts +0 -542
  562. package/src/vision/diffusion-vision.ts +0 -620
  563. package/src/vision/embedder.ts +0 -168
  564. package/src/vision/preprocess.ts +0 -247
  565. package/src/vision/prompt.ts +0 -373
  566. package/src/vision/qwen3vl-preprocess.ts +0 -409
  567. package/src/vision/qwen3vl-prompt.ts +0 -196
  568. package/src/vision/qwen3vl-tower.ts +0 -555
  569. package/src/vision/siglip.ts +0 -599
  570. package/src/vision/video-frames.ts +0 -148
  571. package/src/web/app.html +0 -2143
  572. package/src/web/app.js +0 -5703
  573. package/src/web/skills/memory/SKILL.md +0 -120
  574. package/src/web/skills/web-research/SKILL.md +0 -46
  575. package/src/web/skills.ts +0 -97
  576. package/src/web/src/adapters-panel.ts +0 -288
  577. package/src/web/src/assistant.ts +0 -451
  578. package/src/web/src/chat.ts +0 -1057
  579. package/src/web/src/composer.ts +0 -959
  580. package/src/web/src/dataset.ts +0 -132
  581. package/src/web/src/finetune.ts +0 -267
  582. package/src/web/src/hub.ts +0 -428
  583. package/src/web/src/main.ts +0 -98
  584. package/src/web/src/markdown.ts +0 -0
  585. package/src/web/src/memory-panel.ts +0 -572
  586. package/src/web/src/model-picker.ts +0 -159
  587. package/src/web/src/palette.ts +0 -346
  588. package/src/web/src/protocol.ts +0 -26
  589. package/src/web/src/quantize.ts +0 -167
  590. package/src/web/src/rag.ts +0 -274
  591. package/src/web/src/sessions.ts +0 -469
  592. package/src/web/src/shell.ts +0 -804
  593. package/src/web/src/ui-catalog.ts +0 -78
  594. package/src/web/vendor/README.md +0 -61
  595. package/src/web-assets.ts +0 -47
  596. package/src/web-tools.ts +0 -478
  597. package/src/weights.ts +0 -255
  598. /package/src/{serve → server}/completion-sink.ts +0 -0
  599. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  600. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  601. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
@@ -1,846 +0,0 @@
1
- # Server configuration
2
-
3
- The canonical reference for **every start flag, every `MLX_BUN_*`
4
- environment variable, and every serving feature** of `mlx-bun serve` (and
5
- `mlx-bun pi`, which shares the flag set). Each default here is read from
6
- the code, not from memory: flags are parsed by `serverRuntimeFlags()` /
7
- `applyDecodeRoute()` in [src/cli.ts](../../src/cli.ts) (the `SERVER_FLAGS`
8
- help block is the same list), runtime knobs land in `ServerOptions`
9
- ([src/server.ts](../../src/server.ts)), environment reads go through
10
- [src/runtime-config.ts](../../src/runtime-config.ts), and the `--isolate`
11
- proxy lives in [src/serve/isolate.ts](../../src/serve/isolate.ts). For the
12
- request/response wire format see [server-api.md](./server-api.md); for
13
- CLI verbs see [cli.md](./cli.md).
14
-
15
- The server runs generation through method-neutral sessions. A model binding
16
- supplies execution planning, its supported methods, media preparation and
17
- diagnostics. Stop/tool parsing runs directly in session delivery, so it can stop
18
- generation before another token is produced. This adds no architecture flag.
19
-
20
- Sections: [Start flags](#start-flags) · [`--isolate` semantics](#--isolate-semantics)
21
- · [Per-request overrides](#per-request-overrides) · [Environment variables](#environment-variables)
22
- · [Execution modes](#execution-modes-serial-vs---batch-n) · [Compatibility matrix](#compatibility-matrix)
23
- · [Fidelity tiers](#fidelity-tiers-and-the-decode-route---l1----l2) · [Feature matrix](#feature-matrix)
24
- · [Performance & recipes](#performance-characteristics--recipes) · [`GET /stats`](#observability--get-stats).
25
-
26
- ## Start flags
27
-
28
- How flags are parsed (`src/cli.ts` `opt`/`flag`/`positional`):
29
-
30
- - A value flag is `--name value` (space-separated; `--name=value` is not
31
- recognized). A value flag with no following token takes its default.
32
- - **Unknown flags are silently ignored** — there is no unknown-flag error.
33
- mlx_lm.server's `--kv-group-size` and `--quantized-kv-start` are in this
34
- class: `src/serve/isolate.ts` lists them as value-taking so the engine
35
- argv builder does not mistake their value for a model positional, but
36
- `serve` never reads them (uniform `--kv-quant 4|8` is fixed at group
37
- size 64, start 0).
38
- - Aliases: `--adapter-path` = `--adapter`; `--temp` = `--temperature`
39
- (explicit `--temperature` wins); `--decode-concurrency` = `--batch`
40
- (`--batch` wins); `--query`/`-q` = the positional model query.
41
- - `mlx-bun pi` consumes the same flag set; when it attaches to an
42
- already-running server every server-shaping flag except `--port` is
43
- reported as ignored (the running server keeps its configuration).
44
-
45
- **Lane/tier column:** `serial` = the strict single-queue executor;
46
- `batch` = the continuous scheduler (`--batch N`); `both` = lane-independent.
47
- L1 = bit-exact vs mlx-lm, L2 = bit-exact vs mlx-optiq, Lab = no external
48
- oracle. See [Fidelity tiers](#fidelity-tiers-and-the-decode-route---l1----l2).
49
-
50
- ### Model selection
51
-
52
- | Flag | Arg | Default | Lane/tier | What it does |
53
- | --- | --- | --- | --- | --- |
54
- | `[query]` (positional) | registry query | auto-pick | both | First non-flag token after `serve`: a registry query (`"12B"`, `"e4b"`, a repo substring). Omitted: serves e4b when downloaded, else the largest downloaded model that fits; a fresh install downloads a small starter model first, then e4b in the background. |
55
- | `--model` | path \| query | none | both | mlx_lm.server's spelling, and the **highest-precedence** selector: a directory containing `config.json` loads straight from that path (`scanSnapshot`, no registry lookup — the bench/CI shape; an HF-cache path recovers its repo id from `models--org--name/snapshots/`); anything else resolves like the positional query. Precedence: `--model` > positional > `--query` > auto-pick. Under `--isolate`, the parent resolves the model and pins `--model <path>` on the engine child. |
56
- | `--query` / `-q` | registry query | none | both | Same as the positional query (lowest-precedence explicit selector). `-q` is the `mlx-bun pi` spelling. |
57
-
58
- ### Network
59
-
60
- | Flag | Arg | Default | Lane/tier | What it does |
61
- | --- | --- | --- | --- | --- |
62
- | `--host` | addr | `127.0.0.1` | both | Interface to bind. Loopback-only by default (mlx_lm.server parity); `--host 0.0.0.0` exposes the server on your network. The browser-open uses `localhost` when the bind is `0.0.0.0`/`::`. |
63
- | `--port` | n | `8080` | both | Listen port. Before loading weights the CLI probes `http://localhost:<port>/v1` and refuses to start if something is already serving there (skipped under `--unix`). |
64
- | `--unix` | socket path | none | both | **Internal.** Listen on a unix domain socket instead of TCP — the engine half of `--isolate` (`ServerOptions.unixSocket`; `hostname`/port are ignored, stale socket files are unlinked before bind). Usable directly for socket-level integration. |
65
-
66
- ### Memory, admission, and caches
67
-
68
- Memory estimates are advisory by default. The server attempts requests without
69
- rejecting a prompt or shortening `max_tokens` based on predicted GPU headroom.
70
- `fit` and `/stats.admission.max_safe_context` remain estimates; they do not
71
- set the default execution limit. Explicit `--memory-budget`, `--kv-budget`,
72
- and context caps remain opt-in restrictions. GLM-5.2's allocated context
73
- layout retains its configured capacity.
74
-
75
- When batch rows finish, full-attention caches drop padding shared by every
76
- surviving row, matching MLX-LM while preserving each row's absolute position.
77
-
78
- Qwen prefills longer than four tokens materialize each layer and its cache
79
- state before continuing, bounding deferred buffer lifetimes. Execution has
80
- no reservation checks between layers or during decode. Serial requests
81
- finish outstanding SSD snapshots before generation. The RAM prefix-cache
82
- cap controls retained entries; it does not promise that every workload fits.
83
- Actual allocation failures use the ordinary error path when recoverable;
84
- a native Metal allocation failure can terminate the process.
85
- With `--ssd-cache`, an exact recurrent-cache hit persists its boundary before
86
- transferring the live state to the request. This keeps that boundary reusable
87
- after the recurrent state advances. Already-durable boundaries need no write;
88
- a failed required store retains the cache entry and refuses the transfer.
89
-
90
- | Flag | Arg | Default | Lane/tier | What it does |
91
- | --- | --- | --- | --- | --- |
92
- | `--memory-budget` | GB (decimal, ×10⁹) | unset; memory estimates are advisory | both (per request) | Explicit opt-in budget. Sets the allocator limit and enforces the fit estimate: a prompt leaving no generation slot gets **400** (`type: memory_admission`); a broader completion cap is reduced to the remaining context. Estimates account for active KV quantization and prefill temporaries. Not an aggregate batch cap — see `--kv-budget`. GLM-5.2 also uses this value in its resource plan before loading. |
93
- | `--kv-budget` | GB (decimal) | off | batch | Aggregate KV budget across concurrently admitted batch rows: a joiner whose projected KV (prompt + `max_tokens`, window-capped) would exceed it **queues** until rows finish; a request over the budget alone is rejected. Without it, N large-context rows can collectively exceed memory. Reported in `/stats.batch.kv_budget_bytes`. |
94
- | `--prompt-cache` | GB (binary GiB) | `8` | both | RAM prefix-KV cache (byte-capped LRU). `--prompt-cache 0` disables it. RAM hits lend zero-copy views and leave the donor intact, including recurrent Qwen and method state. SSD persistence runs in the background; RAM reuse never waits for a write. Explicit cache flush and graceful shutdown wait for durability. Batch-lane joiners `take()` the longest usable prefix at admission; a row that finishes without ever merging `put()`s its caches back (merged rows' entries age out). |
95
- | `--ssd-cache` | dir | off | both | SSD cold tier under the prompt cache ([docs/design/kv-cache.md](../design/kv-cache.md)): prefix KV spills to disk on RAM eviction and idle demotion, is snapshotted after requests settle (debounced, each tensor step owns the generation lock so it cannot overlap inference; `MLX_BUN_SSD_WRITEBEHIND=0` disables), and **survives restarts**. Entries are keyed by model fingerprint + effective KV scheme + backend numerical identity + tokenizer hash + adapter namespace. MLX includes its runtime version and GPU architecture; older numerical identities use separate directories. `SIGINT`/`SIGTERM` drains active requests and flushes dirty snapshots before exit (`MLX_BUN_SHUTDOWN_TIMEOUT_MS`); `POST /admin/cache/flush` is the explicit boundary. Requires the RAM cache. |
96
- | `--ssd-cache-max` | GB (binary GiB; `0` = unlimited) | unlimited | both | Optional SSD tier byte cap; oldest-mtime entries are evicted only when a positive cap is configured. Warns and is ignored without `--ssd-cache`. |
97
- | `--ssd-cache-verify` | (bool) | off | both | Verify every tensor hash on restore (reads all bytes eagerly, defeating lazy fault-in) — integrity paranoia only; the header hash is always verified. Warns and is ignored without `--ssd-cache`. |
98
- | `--ssd-demote-idle` | seconds | `300` with `--ssd-cache`, else off | both | Prompt-cache entries unused this long spill to the SSD tier and free their GPU memory; the next hit restores them. Swept only when the engine is fully idle. `0` disables. Warns and is ignored without `--ssd-cache`. |
99
- | `--generation-checkpoint` | output tokens | off | qualified requests | Queues an owned in-flight generation snapshot every N emitted tokens. Repeating the identical request after a restart replays the saved assistant prefix and continues from its already-sampled next token. Requires `--ssd-cache`. Shared execution qualifies ordinary requests with supported row-cache layouts, including Qwen, Llama, MiniCPM and Gemma4, with or without adapters, excluding media, grammar, fill, paging, logprobs or speculative methods; existing serial qualification remains available. Explicit cache flush drains queued writes. Completed generations remove their checkpoint, while client cancellation preserves the latest checkpoint. |
100
-
101
- Generation checkpoint identity includes stop strings, sampling/KV policy, the
102
- resolved execution method, compiled/grammar policy, and artifact/implementation
103
- identity. Changing any of these starts a new completion. Version-2/3 generation keys are not
104
- selected for automatic resume. Prefix-cache files retain their state codec
105
- format, but automatic reuse also requires the model binding's numerical
106
- identity. MLX runtime or GPU architecture changes select a fresh cache
107
- directory and leave the previous directory intact. A different backend codec
108
- identity refuses incompatible files. Adapter namespaces include the mounted weight contents and
109
- scale, so a changed adapter starts with a fresh prefix and checkpoint.
110
- Native media and grammar preparation waits for the generation execution lease
111
- and retains a reservation through completion. At most one media preparation and
112
- `--batch` grammar preparations can be retained. Generation and preparation
113
- queues each allow 64 waiting requests; overflow returns `429` before a response
114
- stream opens, or a terminal stream error after it opens. Disconnects release
115
- queued reservations and completed preparation resources.
116
-
117
- Ordinary requests in the continuous scheduler can join an ongoing prefill
118
- between chunks when their execution context is compatible and batch capacity
119
- is available. Scheduling also budgets the initial prefill work in a cohort, so
120
- long prompts can be prepared one at a time through the continuous executor
121
- while decode remains batched. Subsequent forwards process real-token chunks from admitted requests
122
- together. Each request keeps its own cache-maintenance and checkpoint boundaries.
123
- Arrival timing can change batch geometry and near-tie generated text. Qwen MTP,
124
- prompt lookup and standalone drafting use the same target prefill driver.
125
- Their providers prepare companion state through a separate interface;
126
- scheduling determines admission and work budgets.
127
-
128
- Disconnected serial requests leave the admission queue immediately. Active AR
129
- requests check cancellation between prefill chunks and decode steps; a native
130
- operation already running completes before that boundary.
131
-
132
- ### Runtime isolation
133
-
134
- | Flag | Arg | Default | Lane/tier | What it does |
135
- | --- | --- | --- | --- | --- |
136
- | `--isolate` | (bool) | off | both | Run the inference engine as a **child process** on a unix socket while this process owns CPU application routes and proxies inference — instant under any GPU load, survives engine crashes (auto-respawn). Full semantics in [`--isolate` semantics](#--isolate-semantics). |
137
- | `--model-pool` | n (≥1) | `1` | both | With `--isolate`: max **resident** model engines. A request whose `model` field is an **exact** `/v1/models` id spawns/routes to that model's own engine child (spawn-overlap: the new model loads while the old keeps serving). Over the cap the least-recently-used engine is drained (`POST /admin/drain` over its socket), demotes its prompt cache to the SSD tier, and exits; switching back respawns it with state restored from disk. Without `--isolate` the flag warns and is ignored. |
138
-
139
- ### Scheduling
140
-
141
- | Flag | Arg | Default | Lane/tier | What it does |
142
- | --- | --- | --- | --- | --- |
143
- | `--batch` | n (integer ≥ 1) | `8` | batch / L1 | Max concurrent requests decoded together. A lone admitted request uses the B=1 fast path (adopted serial-class caches, compiled decode, prompt cache + SSD restore — byte-identical to serial); a batch layout only exists once a second request arrives. `--batch 1` pins the strict serial executor (arrival-independent numerics — use it for golden regeneration). `--decode-concurrency` is accepted as the mlx_lm.server alias, but its semantics differ there (per-`BatchGenerator` decode parallelism, default 32). See [Execution modes](#execution-modes-serial-vs---batch-n). |
144
-
145
- ### KV cache
146
-
147
- | Flag | Arg | Default | Lane/tier | What it does |
148
- | --- | --- | --- | --- | --- |
149
- | `--kv-quant` | `config` \| `off` \| `4` \| `8` \| `turbo[:k<bits>v<bits>]` | `off` (bf16) | see row | KV-cache quantization. `off` = bf16 (the L1 default: quantized KV measured 5–20% slower decode than bf16 at ≤16k on both stacks, so it is an opt-in that buys **memory headroom**). `4`/`8` = **uniform** bits (group 64, start 0 — mlx-lm's `--kv-bits` scheme); with fused-sdpa off (the default for uniform) our unfused quantized SDPA is op-for-op mlx-lm's `quantized_scaled_dot_product_attention`, so uniform is **bit-exact L1**; uniform requests use shared B=1/B>1 execution where the loaded cache layout supports affine conversion. `config` = **per-layer mixed precision** from the model's `kv_config.json` — optiq-only → **L2**; per-layer configs **batch** on every shipped model (full-attention and rotating layers; gated bit-exact per row vs the serial composition). `turbo[:k<bits>v<bits>]` = **TurboQuant** ([docs/design/turboquant.md](../design/turboquant.md)): rotation-based KV quantization, default `k8v3`; `kBits` ∈ {2,4,5,8}, `vBits` ∈ {2,3,4,5,8}; a separate axis (mutually exclusive with `config`/`4`/`8`), uses the existing decoded or deferred rotated-value attention path, **full-attention layers only** (sliding-window layers stay bf16 with a one-time warning), refuses head dims outside `TURBOQUANT_HEAD_DIMS`, and supports shared ordinary and grouped drafting execution at B=1/B>1 including positive library conversion thresholds when the cache layout qualifies. Any explicit `--kv-quant` overrides the tier preset. |
150
- | `--paged-kv` | (bool) | off | shared / gated bit-exact | **Optional vLLM-style paged KV cache** ([docs/design/kv-cache.md](../design/kv-cache.md)): full-attention layers store K/V in fixed-size block pools (host-side block table, gather back to contiguous before the stock SDPA; no new attention math). Env mirror `MLX_BUN_PAGED_KV=1`. Paging retains the configured batch size; request state owns independent block pools through the shared cache-layout interface. `createServer` **refuses** any `--kv-quant` (incl. turbo), `--draft-model`, and non-Gemma4 models. Media and adapter requests run the plain cache path per request. Paged requests bypass the prompt cache and run uncompiled decode; pool exhaustion is a typed error, never truncation. Gated bit-exact vs the plain path (`tests/parity/paged-kv-parity.test.ts`). |
151
- | `--paged-kv-block-size` | n | `256` | shared | Tokens per KV block (`--paged-kv` only); 256 = the plain cache's growth step. |
152
-
153
- ### Adapters and speculative decoding
154
-
155
- In the current unreleased source, Qwen MTP publishes aligned target/draft
156
- prefill snapshots through the shared prompt cache by default. The RAM budget
157
- includes the draft KV and pending hidden row; configured SSD persistence
158
- queues those tensors with the target state and supports reuse after restart.
159
- RAM hits retain immutable snapshots for later requests. Target, draft-weight,
160
- adapter-revision and KV-policy identities separate incompatible state.
161
- `usage.cached_tokens` reports the reused target prefix.
162
- `MLX_BUN_MTP_PROMPT_CACHE=0` disables this reuse. Generated-output snapshots
163
- remain unfinished.
164
-
165
- In the current unreleased source, Qwen uniform affine KV4 with
166
- `quantizedKvStart=0` supports configured speculative execution by default.
167
- `MLX_BUN_QWEN_SPEC_KV4=0` restores the ordinary-decode compatibility control. Recurrent state and draft KV keep their original precision. Shared Qwen MTP
168
- also supports bf16, uniform KV8 and TurboQuant at start zero; per-layer mixed
169
- KV remains incompatible. Strict legacy serial speculation retains bf16/KV4.
170
- The KV4 control does not disable bf16, KV8 or TQ shared speculation. Six paired M4 Pro combined suites and two completed Kanban tasks support
171
- this default. Configuring a drafter and selecting KV4 remain explicit choices.
172
-
173
- For controlled experiments, `MLX_BUN_RD_PREFILL_CHUNK` sets the prefill chunk,
174
- default 2048. Shared ordinary and speculative methods use the group's captured
175
- default; an explicit group option overrides the environment and a library
176
- request's `prefillChunkSize` overrides that default for its request.
177
- `MLX_BUN_RD_CONTEXT_LIMIT` sets an explicit request context cap
178
- without enlarging it. Both require positive integers; the context cap is unset
179
- by default. These are benchmark controls, not changes to the published model
180
- profile or sampling policy.
181
-
182
- | Flag | Arg | Default | Lane/tier | What it does |
183
- | --- | --- | --- | --- | --- |
184
- | `--adapter` | dir | none | compatible adapter groups | Mount a LoRA adapter at startup (same machinery as `POST /v1/adapters`; the id is the directory basename) and make it the default for requests without an `adapter` field. A request's explicit `adapter` — including `"none"` — wins; hot-swap via `/v1/adapters` is unchanged. A bad adapter fails startup. Alias `--adapter-path`. |
185
- | `--draft-model` | path \| query | none | shared Qwen methods; full-attention/rotating lookup/standalone and Gemma assistant/DeepSpec/DSpark; other combinations serial | **Speculative decoding**: a drafter proposes tokens the target verifies in one forward — exact results, faster decode when drafts land. Resolves like the main model. Kind is auto-detected: a full same-tokenizer model (mlx_lm.server parity, L1 token-for-token; tokenizer-family mismatch fails startup), a Gemma `-assistant` KV-borrowing drafter (L2 vs optiq `spec_generate`), a locally trained **DSpark** checkpoint (`dspark.json`), or a released DeepSpec `Gemma4DSparkModel` drafter. Qwen MTP, prompt lookup and standalone drafting use the shared executor at one or several active rows, including logprobs. Supported full-attention and rotating targets, including Llama, MiniCPM and Gemma, also share bf16, uniform KV4/KV8 or per-layer affine KV or TurboQuant prompt lookup and standalone drafting. Rotating target transactions retain different accepted lengths across the sliding window and publish paired RAM/SSD state. Gemma assistant drafting shares the same execution at B1/B>1 with bf16, uniform KV4/KV8 or per-layer affine KV or TurboQuant target storage. Its hidden-state companion and target KV use the RAM/SSD cache; donor attention owns row validity while the assistant graph stays independent of storage. DeepSpec and DSpark share bf16, uniform KV4/KV8 or per-layer affine KV or TurboQuant target execution and projected-context RAM/SSD companions. DeepSpec supports bf16 or affine-quantized draft weights; DSpark supports its Markov/RNN heads. Confidence selects each row's proposal length independently. Other provider/target combinations still run serial. Unsupported speculative compositions use ordinary execution when their own features support it. Composes with structured output; Qwen MTP, prompt lookup, standalone, Gemma assistant, DeepSpec and DSpark drafting use the shared RAM/SSD prefix cache by default (`MLX_BUN_MTP_PROMPT_CACHE=0` disables); other speculative sources start fresh. Telemetry: `usage.speculation`. |
186
- | `--draft-kind` | `two-model` \| `assistant` \| `dspark` \| `deepspec` \| `mtp` \| `ngram` | auto | shared Qwen methods; full-attention/rotating lookup/standalone and Gemma assistant/DeepSpec/DSpark; other combinations serial | Override drafter detection. `mtp` = a native multi-token-prediction head split from the target's release (`*_mtp` model_type; shares the target's embeddings/lm-head, defaults `--num-draft-tokens` to its trained `block_size − 1`, rolls DeltaNet caches back by snapshot/replay on partial rejects); `mtp` alone mounts the companion bundled at `<model>/mtp/` when present. Qwen MTP companions accept dense or affine-quantized projections using their checkpoint metadata; changing the draft can change acceptance and speed. `ngram` = **model-free prompt lookup** (drafts copied from the request's own prompt+generation; port of prompt-lookup decoding / vLLM's `ngram` proposer) — mount it **alone** (`--draft-kind ngram` with a `--draft-model` is refused, as is any other kind without one); lossless by the same verify, a no-match round degrades to one plain target step. Any other value fails startup. |
187
- | `--num-draft-tokens` | n (integer ≥ 1) | `3` (`ngram`: `10`; DSpark: pinned ≤ its trained `gamma`) | method-dependent | Drafts per verify round (mlx_lm.server's default; `mlx_lm.generate`'s is 2). |
188
- | `--ngram-max` / `--ngram-min` | k (integer ≥ 1) | `3` / `1` | Qwen and full-attention targets shared / other models serial | `--draft-kind ngram` only: longest/shortest trailing k-gram searched (longest first, first occurrence wins). `--ngram-min` > `--ngram-max` fails startup; either flag without `ngram` warns and is ignored. |
189
- | `--mtp` | `on` \| `off` | `on` for GLM-5.2 | serial+spec | GLM-5.2 checkpoint-native MTP row as the server's drafter, using the bounded auxiliary expert tier and the exact serial verify loop (`usage.lane: "serial+spec"`). `off` removes the draft so ordinary GLM requests can use continuous batching. Other model families ignore it. |
190
- | `--context-length` | tokens (integer ≥ 1) | `4096` (GLM-5.2) | both | Context reserved by GLM-5.2's header-only resource equation; also the request-admission ceiling, reported in `/stats.glm52`. An impossible plan fails before committing model memory. Ignored by other families. |
191
-
192
- ### Sampling and template defaults
193
-
194
- | Flag | Arg | Default | Lane/tier | What it does |
195
- | --- | --- | --- | --- | --- |
196
- | `--thinking` | `true`\|`false` (also `on`/`off`/`1`/`0`) | model's own (`false` for MiniCPM5) | both | Server-wide default for the chat template's `enable_thinking`. Precedence (`resolveEnableThinking`): explicit request `chat_template_kwargs.enable_thinking` → request `reasoning_effort` (`"none"` = off, any other level = on) → this flag → the model's default. With no explicit temperature, a no-think turn is capped at 0.7 while a think turn keeps the model's configured temperature. |
197
- | `--temperature` | n ∈ [0, 5] | `generation_config.json`, else `0.7` | both | Server-wide sampling default; a per-request `temperature` wins; the browser chat (sends none) inherits it. Alias `--temp` (mlx_lm.server spelling — note its *default* there is `0.0`; pass `--temp 0` for that behavior). |
198
- | `--top-p` | n ∈ [0, 1] | `generation_config.json`, else `0` (off) | both | Server-wide top-p default (per-request `top_p` wins). |
199
- | `--top-k` | n ∈ [0, 1e6] | `generation_config.json`, else `0` (off) | both | Server-wide top-k default (per-request `top_k` wins). |
200
- | `--max-tokens` | n ∈ [1, 1e7] | GLM-5.2: `128` (memory-plan reservation); otherwise none — an omitted cap generates until EOS/stop or an explicitly configured limit | both | Completion cap when a request omits `max_tokens` (mlx_lm.server flag). DEVIATION when unset: `mlx_lm.server` stops a defaulted request at 512 — `--max-tokens 512` reproduces it. For GLM-5.2 the value is also reserved by the pre-open resource equation and must fit inside `--context-length`. Note: `max_tokens` also feeds `--kv-budget` row projections (prompt + cap), so an uncapped request cannot fit a finite explicit KV budget; set `--max-tokens` or send a request cap when using that budget. |
201
- | `--hlg-sampling` | `on`\|`off` | off | serial / Lab | Piecewise tone-curve (HLG) sampling: rolls off the top-token region, boosts the mids, gentles the tail; the gain folds from `--temperature`. Design: [docs/archive/hlg-sampling.md](../archive/hlg-sampling.md). |
202
- | `--hlg-width` | nats ∈ [0, 100] | `4` | serial | HLG mid-region half-width. Only with `--hlg-sampling on`. |
203
- | `--hlg-shoulder` | nats ∈ [0, 100] | `4` | serial | HLG highlight rolloff scale. Only with `--hlg-sampling on`. |
204
- | `--hlg-toe` | nats ∈ [0, 100] | `6` | serial | HLG shadow rolloff scale. Only with `--hlg-sampling on`. |
205
- | `--hlg-pivot-offset` | nats ∈ [0, 100] | `6` | serial | HLG pivot: nats below the top token. Only with `--hlg-sampling on`. |
206
-
207
- ### Media and UX
208
-
209
- | Flag | Arg | Default | Lane/tier | What it does |
210
- | --- | --- | --- | --- | --- |
211
- | `--allow-private-media` | (bool) | off | serial (media requests) | Let `image_url`/`audio_url`/`video_url` parts fetch from **private/loopback/link-local** hosts. Off by default: a request's URL is attacker-controlled, so `src/media-fetch.ts` refuses non-http(s) schemes and private/loopback/link-local/CGNAT destinations — including hosts that *resolve* there and every redirect hop (SSRF guard). Independent of the flag, every remote fetch has a 10 s timeout and a 64 MB streaming-enforced cap; violations are clean `400`s. `data:` URLs are never policy-checked. Env mirror `MLX_BUN_ALLOW_PRIVATE_MEDIA=1`. |
212
- | `--no-open` | (bool) | off | both | Skip the automatic browser open. By default an interactive TTY opens `http://<host>:<port>/#/chat` once the server is ready; non-TTY runs never open. Parent-only under `--isolate`. |
213
-
214
- ### Parity tier and kill switches
215
-
216
- | Flag | Arg | Default | Lane/tier | What it does |
217
- | --- | --- | --- | --- | --- |
218
- | `--l1` | (bool) | **the default** | serial route / L1 | Tier alias: bit-for-bit identical to mlx-lm — bf16 KV, compiled decode, compiled activations, fused-sdpa off. No tier flag ⇒ `--l1` (decision 2026-07-05). Any per-fork flag below overrides one preset value. |
219
- | `--l2` | (bool) | — | serial route / L2 | Tier alias: bit-for-bit identical to mlx-optiq — `--kv-quant config` + fused N-tiled prefill SDPA + stock unfused decode (the composition the optiq goldens track). |
220
- | `--l3` | — | — | — | **Removed 2026-07-05.** Passing it exits with a pointer to `--l2` / the Lab. |
221
- | `--compiled-decode` | `on`\|`off` | on | serial, and batch at B=1 / L1 | Replay the per-step decode graph in C++ (`MLX_BUN_COMPILED_DECODE`). Bit-exact A/B lever. Gemma4-dense only; LoRA, MoE, and other families run eager, and an unsupported step falls back to eager for the rest of that generation. |
222
- | `--compiled-activations` | `on`\|`off` | on | both / L1 | Route geglu/swiglu through mlx-lm's `@mx.compile` closure (`MLX_BUN_COMPILED_GEGLU` + `MLX_BUN_COMPILED_SWIGLU`). MiniCPM5 uses compiled SwiGLU for decode and prefill. `off` selects the uncompiled composition and can change prefill numerics on MLX 0.32.2. Toggles gemma geglu + MiniCPM5 swiglu; qwen3/qwen3.5/universal compile unconditionally. |
223
- | `--fused-sdpa` | `on`\|`off` | follows `--kv-quant`: on for `config`, off for `4`/`8` and bf16 | serial / L2 | Fused SDPA for quantized-KV prefill/continuation (inverted env `MLX_BUN_NO_FUSED_SDPA`). Defaults to the composition its oracle uses. No-op on bf16. |
224
- | `--force-wire` | (bool) | off | serial | Wire weights into memory for the whole generation (`MLX_BUN_FORCE_WIRE=1`). Near-ceiling models need it. The batch scheduler bypasses `generate()`'s wired scope. |
225
- | `--expert-offload` | (bool) | off | serial / Lab | **MoE only.** Serve experts from a page-aligned file mmap (`<model>/.mlx-bun-offload`, built on first use) — physical footprint ≈ active params. Dense models log "ignored". Bit-exact with the resident path. Env mirror: `MLX_BUN_EXPERT_OFFLOAD=<dir>`. |
226
-
227
- The default host/port (`127.0.0.1:8080`) match `mlx_lm.server`, so running
228
- mlx-bun alongside the Python reference needs an explicit `--port`.
229
-
230
- ## Reproducing mlx_lm.server
231
-
232
- Numeric parity (same tokens in → same logits, bit-for-bit) is unconditional
233
- — no flag buys it back and none is needed. **Behavior policy** (defaults,
234
- caps, sampling fallbacks) is mlx-bun's own; mlx_lm.server's policy is one
235
- configuration of it:
236
-
237
- ```sh
238
- mlx-bun serve <model> --temp 0 --top-p 0 --top-k 0 --max-tokens 512 --batch 1
239
- ```
240
-
241
- - `--temp 0 --top-p 0 --top-k 0` — mlx_lm.server does not read
242
- `generation_config.json` (we inject its sampling defaults, optiq-style);
243
- its unset-request defaults are temperature 0.0, top-p/top-k off.
244
- - `--max-tokens 512` — its cap when a request omits `max_tokens` (ours is
245
- none: run to EOS/stop or an explicit operator limit). The cap changes the stopping
246
- point and `finish_reason`.
247
- - `--batch 1` — strict serial, arrival-independent numerics. (`--batch N`
248
- is itself bit-parity with mlx-lm at B=N; pin 1 for golden regeneration.)
249
- - Already matching without flags: host/port, bf16 KV (`--kv-quant off`),
250
- the L1 kernel preset (`--l1` is the default), logprobs caps, error text.
251
-
252
- These flags align sampling and caps. Exact generated trajectories also need
253
- matching prefill and cache boundaries. Stock MLX-LM HTTP splits system and
254
- thinking segments before reserving the final token. Different forward shapes
255
- can change near-tie greedy choices even inside the same Python model.
256
- The benchmark's explicit `--reference-prefill unsplit` control and the saved
257
- MiniCPM/Qwen investigation are documented in [benchmarks.md](benchmarks.md).
258
-
259
- The kill switches are bit-exact A/B levers; **the naked default is the L1
260
- set** (2026-07-05: an output-changing lever earns a default only by beating
261
- the L1 baseline in a paired A/B, and none did — the losing kernels were
262
- deleted, Phase 1 of
263
- [unified-engine-frontier-plan.md](../design/unified-engine-frontier-plan.md)).
264
- They are installed as `MLX_BUN_*` runtime values before the model loads,
265
- so they apply to `mlx-bun pi` too. They affect the **serial** decode path;
266
- the batch scheduler drives `model.forwardHidden` directly and is unaffected
267
- except by `--compiled-decode` at B=1 — see
268
- [Levers that don't reach the batched lane](#--batch-n-is-compat-mode--perf-flags-dont-apply-by-design).
269
-
270
- ## `--isolate` semantics
271
-
272
- Design and measurements: [docs/reference/server-config.md](./server-config.md)
273
- (P1 single engine and P2 model pool landed). What the flag does, from
274
- `src/serve/isolate.ts` and the `serve` handler in `src/cli.ts`:
275
-
276
- - **Process layout.** The parent binds the TCP `--host`/`--port` and makes
277
- zero MLX calls. It re-execs itself as `serve` with the same argv minus
278
- the **parent-only flags** (`--isolate`, `--port`, `--host`, `--model-pool`,
279
- `--no-open`), the model selectors replaced by a pinned `--model <path>`,
280
- plus `--unix <socket>` (socket under the OS temp dir, named by parent
281
- pid). Every other flag and every exported `MLX_BUN_*` variable reaches
282
- the engine child unchanged (`env: process.env`); the child's stdout/stderr
283
- are inherited, so load progress prints in your terminal.
284
- - **Readiness.** The parent polls the child's `/health` over the socket
285
- (up to 15 minutes — large models take a while) and prints "engine ready
286
- pid N". Requests arriving earlier wait on that readiness.
287
- - **Application state.** The web shell, job submissions, records, progress streams, settings and
288
- Responses conversation history live in the CPU-only parent, so worker death or model eviction does not remove
289
- them. Native inspection/merge/export and generation still execute in workers.
290
- WebSocket chat retains its existing unsupported status under isolation.
291
- - **Proxying.** Remaining HTTP requests are forwarded over the unix
292
- socket (hop-by-hop headers stripped, SSE streams through, a client
293
- abort aborts the proxied fetch so the engine sees the disconnect).
294
- `GET /engine` answers from the parent:
295
- `{ isolated: true, pid, restarts, socket, response_store, pool?: { resident, default } }`.
296
- Worker fields describe the currently resident default worker and are `null`
297
- while it is evicted; inspection does not load a model. A recreated worker has
298
- its own restart count.
299
- `/ws/chat` is **not proxied** — `501` with a pointer to run without
300
- `--isolate` for the web chat UI.
301
- - **Crashes.** A child exit (uncatchable Metal OOM/SIGTRAP included) is
302
- respawned automatically (`restarts` increments), with at most three restarts
303
- in a rolling 60-second window. Exhausting that budget leaves the host
304
- unavailable until restarted. An engine that dies within 10 s of spawning
305
- waits 5 s before the retry. In-flight requests
306
- get `502 { error: { type: "engine_unavailable" } }`; bodyless `GET`/`HEAD`
307
- requests are retried once after the respawn. A request whose client
308
- disconnected answers `499`.
309
- - **Model pool (`--model-pool n`).** `POST` bodies on `/v1/chat/completions`,
310
- `/v1/completions`, `/v1/messages`, `/v1/responses`, `/v1/embeddings` are
311
- buffered to read `model`. An **exact** registry id (`/v1/models` id)
312
- spawns/routes to that model's own child; anything else — empty, fuzzy,
313
- `"gpt-4"`-style — rides the default engine (mlx-lm's ignored-field
314
- semantics). Eviction over the cap: `POST /admin/drain` on the victim's
315
- socket (gateway quiesce + demote its prompt cache to the SSD tier),
316
- then stop; `/admin/drain` is unix-socket-only, never on the TCP
317
- listener. Cold model starts are serialized through a bounded queue while the
318
- resident model keeps serving; concurrent switches cannot evict a newly loaded
319
- worker before its pending request is returned. `--model-pool` is clamped to ≥ 1.
320
- - **Managed GPU jobs.** A FIFO parent coordinator waits for active worker
321
- responses, then holds a native execution lease inside every resident worker
322
- before spawning a quantization/finetuning job. Startup, restart and eviction
323
- participate in admission too. Job exit releases those leases. Dataset jobs use
324
- the same loopback completion API and keep their progress in the parent.
325
- - **Shutdown.** `SIGINT`/`SIGTERM` cancels queued jobs, stops the active GPU job,
326
- waits for in-process task cleanup, then closes workers and unlinks sockets.
327
- Worker close also waits for pending startup admission and failed startup
328
- attempts to release their execution leases, including before a child exists.
329
-
330
- ## Near-ceiling models on small machines (24 GB)
331
-
332
- A model whose weights approach the default macOS GPU wired ceiling (~75%
333
- of RAM) loads and serves short prompts, but a long prefill can exceed the
334
- ceiling and die with an **uncatchable** Metal OOM. `mlx-bun serve` checks
335
- this at startup (model bytes > 80% of `maxRecommendedWorkingSetSize` while
336
- `iogpu.wired_limit_mb` is at its default) and prints the remedy:
337
-
338
- ```
339
- sudo sysctl iogpu.wired_limit_mb=<RAM_MB - ~2500> # resets on reboot
340
- ```
341
-
342
- For very long contexts on such machines, additionally prefer `--kv-quant`
343
- (e.g. `turbo`) — the prefill transient scales with chunk size × context.
344
-
345
- ## Per-request overrides
346
-
347
- Most quality knobs can be set per request in the chat body and override
348
- the server-wide default. Precedence, highest first:
349
-
350
- 1. explicit request field (`temperature`, `top_p`, `top_k`, `seed`,
351
- `min_p`, `xtc_probability`/`xtc_threshold`, `logit_bias`,
352
- `repetition_penalty`, `presence_penalty`/`frequency_penalty` (+ their
353
- `*_context_size` windows), `max_tokens`/`max_completion_tokens`, `stop`,
354
- `chat_template_kwargs.enable_thinking`, `reasoning_effort`, `adapter`,
355
- `tools`)
356
- 2. the matching `--temperature`/`--top-p`/`--top-k`/`--thinking`/`--max-tokens`
357
- server default
358
- 3. the model's `generation_config.json`
359
- 4. the built-in fallback (temperature 0.7, top-p/top-k 0 = off)
360
-
361
- These ride all three protocol surfaces (`/v1/chat/completions`,
362
- `/v1/messages`, `/v1/responses`) because each funnels through one
363
- chat stage (`src/serve/chat-stage.ts`). Full field list: [server-api.md](./server-api.md).
364
-
365
- ## Environment variables
366
-
367
- All `MLX_BUN_*` variables are captured once at process start into an
368
- immutable snapshot (`src/runtime-config.ts`); CLI flags install overrides
369
- into the same snapshot before the model loads. Boolean levers read the
370
- literal strings `"1"`/`"0"` — `flagOn` treats any other value as unset.
371
- Under `--isolate` the whole environment is inherited by the engine child.
372
-
373
- ### Serving levers (flag-backed and lane kill switches)
374
-
375
- | Env var | CLI flag | Default | Effect |
376
- | --- | --- | --- | --- |
377
- | `MLX_BUN_COMPILED_DECODE` | `--compiled-decode` | on (`"0"` disables) | Compiled decode graph replay (serial lane; batch lane at B=1). |
378
- | `MLX_BUN_EARLY_FIRST_TOKEN` | — | off (`=1`) | Serial/native generation yields token zero before constructing the next decode step. This can reduce first visible output latency when token zero contains visible text. Later decode remains pipelined. Serial fill, grammar, checkpoint resume and single-token budgets retain their existing order. When a native consumer stops at the first yield and retains caller-owned caches, a non-aborted return completes that token’s M=1 forward before returning the cache. This preserves the ordinary pipeline’s boundary for later prefix reuse. Aborted requests do not start another forward; caches owned and disposed by the generation need no alignment. Native M1 packed-Qwen/MiniCPM/Gemma continuation gates pass; M4 packed/affine and serving acceptance remain. The continuous scheduler also yields after preparation creates its first active row when no other request is queued, allowing prepared output to flush before decode. It then rechecks cancellation, admission and shutdown; queued short admissions still group together. The setting is captured by generation and the batch runtime. Experimental pending broader cached/pressure and quiet-machine acceptance. |
379
- | `MLX_BUN_TURBOQUANT_FUSED_DECODE` | — | off (`=1`) | Experimental packed K/V decode fusion for an existing `--kv-quant turbo:...` cache, captured when each cache is created. A shared Metal operation unpacks keys and values, applies the existing key zero/scale and Lloyd-Max value scale, and preserves the codec's eager or deferred inverse rotation. It accepts supported bit widths, head dimensions 64/128/256/512 and 32/64-element groups with fp16/bf16/f32 metadata. Eager k8v3 with B1/H4, head dimension 256, fp16 metadata, group32 and at least 8192 cached tokens also fuses inverse rotation; other shapes keep the existing rotation path. Unsupported inputs, CPU streams and shapeless traces retain ordinary operations. Quantization, stored cache format and serving eligibility are unchanged. Joint-decoder Qwen native/serial and repeated long-context HTTP gates pass. The inverse operation passes both integrated Qwen model gates and six HTTP pairs per quant. MiniCPM/Gemma deferred-consumer serving gates also pass. The unreleased shared codec/layout supports ordinary and supported drafting groups without changing this kernel selection. Gemma now owns pre-write row positions across cache appends; the fix passes native checks on both Macs. Combined settings, pressure and strict M4 Pro acceptance remain. |
380
- | `MLX_BUN_NO_FUSED_SDPA` | `--fused-sdpa` (inverted) | follows `--kv-quant` | `=1` forces the stock unfused SDPA everywhere. |
381
- | `MLX_BUN_COMPILED_GEGLU` | `--compiled-activations` | on (`"0"` disables) | Gemma geglu via mlx-lm's `@mx.compile` closure. `=0` → uncompiled composition (same parity, slower). |
382
- | `MLX_BUN_COMPILED_SWIGLU` | `--compiled-activations` | on (`!== "0"`) | Compiled SwiGLU on MiniCPM5 decode and prefill, matching mlx-lm. An enclosing compiled graph owns its own fusion. qwen3/qwen3.5/universal compile unconditionally. |
383
- | `MLX_BUN_FORCE_WIRE` | `--force-wire` | off (`=1`) | Wire weights for the generation. |
384
- | `MLX_BUN_TRELLIS` | — | `kernel` (`=expand`) | Packed trellis-coded weights (`mode: "trellis"` modules, Q2b — design: `docs/design/turboquant.md`). `kernel` serves them through the Metal decode kernels (M≤4 matvec; larger M expands one tensor to bf16 and runs a stock matmul). `=expand` decodes every trellis tensor at LOAD into 8-bit g64 affine (+~4 GiB at 27B, the eval-carrier numerics) and serves it through the stock quantized path — the fallback for a machine where the kernels lose. |
385
- | `MLX_BUN_TRELLIS_VARIANT` | — | `13` | Trellis kernel variant (see [Q2b experiments](../design/turboquant.md)): `6` = code computed inline × reciprocal, weight served as f32 code×scale; `1` adds a residual step and bf16 rounding to reproduce the fake-quant artifact's weights. `0`/`2`/`3`/`4`/`5` are bench-only decoder variants. Variants `7`–`13` retain variant-6 decode values; `13` is the measured default. These variants tune work assignment; `11` tiles eligible short axis-1 prefills, `12` adds split-K axis-0 prefill at M=5..8, and `13` also vectorizes remaining bf16 expansion for k2/k3/k4, T=256, L=12. On MLX 0.32.2/M3+ the axis-1 M5..15 path instead uses direct packed decoding with native wide-matvec arithmetic when Qwen's RMSNorm establishes aligned row-contiguous inputs; callers without that layout proof use native expansion/matmul. Qwen27B additionally selects an integer codebook for its interleaved k3 down projection at M=3/4 with bf16 activations; other calls retain the computed decoder. Prefill rounds weights to the activation dtype. |
386
- | `MLX_BUN_TRELLIS_ASYNC_EXPAND` | — | off (`=1`) | Experimental variant-13 expansion scheduling. Submit an expanded projection asynchronously while MLX active allocation is below 75% of the device's recommended working set; retain blocking evaluation above it. Other variants are unchanged. Uses the execution's runtime-policy snapshot and preserves the caller's layer barriers. The threshold is not a total-memory cap. Qwen27B integrated native, repeated serial/continuous HTTP and both saved-agent pressure gates pass on M4 Pro 24 GB. Broader-model, combined-optimization and quiet M4 Pro acceptance remain. |
387
- | `MLX_BUN_PAGED_KV` | `--paged-kv` | off (`=1`) | Paged KV cache; the same refusals and prompt-cache bypass as the flag. |
388
- | `MLX_BUN_ALLOW_PRIVATE_MEDIA` | `--allow-private-media` | off (`=1`) | Permit media fetches to private/loopback/link-local hosts (timeout + size cap still apply). |
389
- | `MLX_BUN_EXPERT_OFFLOAD` | `--expert-offload` | off | `=<dir>` — the path of a built expert-offload file, activated at module load (`src/expert-offload.ts`) for scripts and library runs that never parse serve flags. The CLI flag builds the file and activates it itself. |
390
- | `MLX_BUN_PREFILL_TAIL_SPLIT` | — | on (`"0"` disables) | Oracle prefill convention: drain the prompt to len−1, then compute step-0 logits from a separate L=1 forward of the last prompt token (mlx-lm `generate_step` and its batched engine). Both lanes. The spec lane follows its own oracle's shape under the same flag (mlx-lm `speculative_generate_step`: target and draft drain to len−1, no separate step 0). `=0` restores the full-final-chunk convention everywhere — ulp-different at step 0, flips near-tie greedy streams vs mlx-lm. |
391
- | `MLX_BUN_GRAMMAR` | — | on (`"0"` disables) | `=0` disables structured-output mask compilation; requested constraints take the graceful-degrade route (chat prompt injection + a `Warning` header; raw completions header only). |
392
- | `MLX_BUN_TOKEN_MASK` | `host` \| `metal` | `host` | Experimental grammar-mask implementation. `metal` uploads packed bits and applies the same additive mask in a compiled shared Metal kernel. Captured when the grammar controller is created; serving performance gates remain open. |
393
- | `MLX_BUN_GRAMMAR_JUMP` | — | **off** (`=1`) | Jump-forward decoding for structured output (SGLang's technique via xgrammar's `findJumpForwardString`): when the grammar forces a unique continuation, the **serial** lane emits its retokenized ids with one multi-token forward. Lossless in string space and always grammar-valid, but the token stream can legally differ from an unjumped run — no oracle, hence opt-in. Skipped when `logprobs`/`top_logprobs` is requested; SentencePiece-family tokenizers that can't reproduce a mid-stream span never jump. The batch lane does not jump. |
394
- | `MLX_BUN_FILL` | — | **off** (`=strict` \| `=echo`) | **Token fast-forwarding** — lookup, not speculation. Spans of the assistant turn that the request's `tools` + the chat template already DETERMINE (tool-call open scaffold, the rest of a tool name after its first disambiguating token, a sole-required-key skeleton) are appended as committed context in bounded model forwards, and sampling resumes after them. No draft, no verify, no rollback — an injected token is context, indistinguishable to the model from one it sampled. Rows are compiled per request by diffing probe renderings of the model's OWN template, always sliced from a rendering carrying the REAL tool names and schema keys (so a span can never split a merged token such as Qwen3.5's `=get`), so a template that does not render `tool_calls` yields no rows and no fill. Key and call-close assertions require a closed object schema with exactly one required property and no pattern properties; optional/additional arguments stay available. If no property is required, the compiler preserves the empty-argument choice. Template-derived rows require a fresh request-local parser context. Tool-only output after closed reasoning qualifies; quoted/fenced examples, incomplete delimiters and ambiguous literals decline. Requests with more than 32 tools decline template-derived fills. Held-out identity coverage remains open. **Serial lane only** (it never forces a request off the batch lane) and refused for: fixed `seed`, `logprobs`/`top_logprobs`, structured output (grammar owns forced tokens), image/audio/video prompts, a mounted draft model, quantized/TurboQuant KV, and sliding-window models (one warning). Injection bypasses the sampler — a behavior-policy deviation at `temperature > 0` — hence opt-in. `=echo` additionally arms the **echo index** (Lab tier): spans copied from earlier in the same session, held under policy `verify` — the engine appends them in the same single forward, reads the argmax already in that forward's logits at every span position (free, no extra pass), keeps the prefix the model agrees with, and rewinds the rest through the same cache contract the spec lane's rounds use. A wrong echo costs a rewound forward, never a wrong token. Strict rows stay policy `assert` (no readback, no checkpoint). Telemetry: `usage.fill`. |
395
- | `MLX_BUN_FILL_MAX_SPAN` | — | `32` (floor 2) | Hard cap on one injected span. |
396
- | `MLX_BUN_FILL_APPEND_CHUNK_SIZE` | — | `0` (model limit) | Execution chunk cap for assert-policy fill, captured by each FillSession. Zero selects the model's qualified limit; a positive value can lower that limit. The Qwen 27B text path on `applegpu_g16s`, validated on the M4 Pro, supports up to four positions with supported affine projections and optional Trellis MLPs. It rechecks the limit after each chunk and splits at MLX's attention arithmetic boundaries to preserve one-token numerics. Other configurations use one position per forward. The engine commits the complete span before emission and resumes sampling after it, with no intermediate vocabulary heads or verification. Verify-policy proposals keep a single forward for recurrent rollback. The injected-token cap is unchanged. Library callers can set `FillSession`'s `appendChunkSize` option. Held-out, broader-model and quiet M4 Pro acceptance remain. |
397
- | `MLX_BUN_FILL_K` | — | `8` (floor 2) | Echo anchor length: the k-gram that must match before a copied span is proposed (the corpus study's token-level threshold). |
398
- | `MLX_BUN_FILL_CANDIDATES` | — | `24` | Echo bucket-scan cap — the NEAREST occurrences of the anchor win. A span extends only while every one of them agrees; the first disagreement (a **branch point**) ends it. |
399
- | `MLX_BUN_FILL_INDEX_MAX` | — | `131072` (floor 1024) | Token cap on the growing echo index; past it the index freezes rather than growing. |
400
- | `MLX_BUN_FILL_TRACE` | — | off (`=1` \| `=<file.jsonl>`) | `=1`: assert the fill cache-alignment invariant (`cache offset == prompt + forwarded`) on both sides of every append, and log each event. `=<file.jsonl>`: additionally append one record per proposal — proposed ids/text next to what the model's own logits said at every span position (position 0 = the in-flight sample, then argmax), for both policies; under `assert` that readback is trace-only. `bun scripts/fill.ts trace <file>` prints the list and per-position agreement. |
401
- | `MLX_BUN_GRAMMAR_BATCH` | — | on (`"0"` forces serial) | `=0` routes grammar requests to the serial lane instead of per-row batch matchers (A/B + kill switch). |
402
- | `MLX_BUN_BATCH_SSM` | — | on (`"0"` forces serial) | `=0` excludes SSMCache (Qwen3.5 gated-DeltaNet hybrids) from the batch capability gate → those models route serial. |
403
- | `MLX_BUN_BATCH_EXTEND` | — | on (`"0"` reverts) | Joining rows append to the running batch's KV in one pad+concat (mlx-lm `BatchKVCache.extend`). `=0` reverts to whole-batch re-merge (numerically equivalent, O(B·S)). |
404
- | `MLX_BUN_BATCH_VEC_SAMPLE` | — | on (`"0"` reverts) | Vectorized greedy batch sampling; `=0` falls back to per-row sampling (bit-equal A/B). |
405
- | `MLX_BUN_BATCH_NO_PIPELINE` | — | off (`=1`) | Read each batch step's tokens synchronously instead of pipelined (A/B lever; numerically equivalent, slower). Read once at module load. |
406
- | `MLX_BUN_SSD_WRITEBEHIND` | — | on (`"0"` disables) | `--ssd-cache`'s debounced write-behind snapshot (restart survival). Each tensor write waits for an idle engine, then owns the generation lock for that step. Pending writes do not drain active batches or delay request admission for a full flush. `=0` disables it; eviction and demotion spills still write. |
407
- | `MLX_BUN_SSD_SPILL_QUEUE_GB` | — | `2` (GiB; any finite value ≥ 0) | Byte cap on pending write-behind spill clones (they pin evicted entries' GPU memory until the generation-locked flush runs). Over cap the oldest queued spill drops and frees immediately; the durability coordinator keeps its snapshot dirty so an explicit or shutdown flush can retry. `=0` keeps only the newest + in-flight clone pinned. Counters in `/stats.ssd_cache`. |
408
- | `MLX_BUN_SHUTDOWN_TIMEOUT_MS` | — | `120000` (any finite value > 0) | Maximum time `serve` gives active requests plus the SSD durability flush after `SIGINT`/`SIGTERM`; on timeout it logs the remaining snapshot/spill counters and exits. |
409
- | `MLX_BUN_DSPARK_MINCONF` | — | checkpoint-driven | Overrides the DSpark/DeepSpec draft scheduler's minimum-confidence threshold (draft-length pruning). Spec lane only ([docs/design/speculative-decoding.md](../design/speculative-decoding.md)). |
410
- | `MLX_BUN_MEMORY_BATCH` | — | `1` (integer ≥ 1) | Row width for `mlx-bun memory` model calls. 1 = serial (batching measured 1.7–1.9× slower on the heterogeneous extract/chunk workload — [docs/design/dreaming-nightly-pipeline.md](../design/dreaming-nightly-pipeline.md)). |
411
-
412
- ### Paths and tooling
413
-
414
- | Env var | Default | Effect |
415
- | --- | --- | --- |
416
- | `MLX_BUN_LIBMLXC` | resolved: beside the executable → native-pack cache (`~/Library/Caches/mlx-bun/native-v<ver>-<arch>/`) → Homebrew | Explicit path to `libmlxc.dylib`; its directory is then the native runtime dir (`src/mlx/ffi.ts`, `src/native-pack.ts`). |
417
- | `MLX_BUN_NATIVE_PACK_URL` | the GitHub release asset for `NATIVE_PACK_VERSION` | Override the native runtime pack download URL (first-run fetch, sha256-verified). |
418
- | `MLX_BUN_FRAME_EXTRACT` | resolved: beside the executable → native-pack cache → `dist-native/` → compile from `src/native` | Explicit path to the `mlx-bun-frame-extract` AVFoundation sidecar used for video input. |
419
- | `MLX_BUN_EXPERT_IO_DYLIB` | resolved: beside the executable → native-pack cache → `dist-native/` | Explicit path to `libmlx_bun_expert_io.dylib` (GLM-5.2 streamed expert I/O). |
420
- | `MLX_BUN_WIKI` | `~/.mlx-bun/wiki` | Root of the memory vault (`~` expands). |
421
- | `MLX_BUN_JOBS_DB` / `MLX_BUN_JOBS_DIR` | the `JobStore` defaults | Job-store SQLite path and logs dir. The job runner sets both on the subprocess it spawns so the child opens the same store; override for tests. |
422
- | `MLX_BUN_CALIBRATION_JSONL` | bundled optiq mix in the oracle venv | Explicit calibration corpus for `mlx-bun convert`/quantize. |
423
- | `MLX_BUN_ORACLE_PYTHON` | `/Users/joshrossi/Code/mlx-lm/.venv/bin/python` (the reference box; machine-specific, never re-commit) | Oracle venv interpreter for evals that shell out to Python (HumanEval). |
424
- | `MLX_BUN_EVAL_DATA` | `~/.cache/mlx-bun/eval-data` | Directory of exported eval `.jsonl` datasets. |
425
-
426
- ### Diagnostics and tracing (off unless set)
427
-
428
- | Env var | Value | Effect |
429
- | --- | --- | --- |
430
- | `MLX_BUN_P2R_TRACE` | `=1` | Per-request prompt→response phase trace (admission wait, prefill, token-zero, …) for `/v1/chat/completions` and `/v1/completions`; records print to stderr as JSON lines. The trace id is `x-mlx-bun-trace-id` when the request sends it. |
431
- | `MLX_BUN_P2R_SYNC` | `=1` (with `MLX_BUN_P2R_TRACE`) | Attribution mode: synchronizes the GPU at phase boundaries so each phase is charged its own work (MLX is lazy — without it, unsubmitted work lands in the next phase). Slows the traced request. |
432
- | `MLX_BUN_LANE_DEBUG` | `=1` | Logs each request's scheduling placement (`mechanism` + shape) to stderr. |
433
- | `MLX_BUN_BATCH_STEP_TRACE` | `=1` | Per-step phase timing in the batch scheduler (build / read / emit / gap), read once at module load; summarized by `stepTraceReport()`. |
434
- | `MLX_BUN_GRAMMAR_DEBUG` | `=1` | Logs per-step grammar row state in the batch scheduler. |
435
- | `MLX_BUN_PREFILL_MEM_LOG` | `=1` | Logs active/peak memory after each serial prefill chunk. |
436
- | `MLX_BUN_EXPERT_TRACE` | `=<path>` | Records every MoE router decision as JSONL to that path (adds a per-call GPU→host sync — a measurement tool, not a serving path). |
437
- | `MLX_BUN_PI_DEBUG` | any non-empty | Extra `[pi-web]` logging (prompt fingerprint, tool/memory surface) for the web-chat pi session. |
438
- | `MLX_BUN_EVAL_DEBUG` | `=1` | HumanEval: pipe the sandbox's stderr and print failures. |
439
-
440
- ### Eval and training
441
-
442
- | Env var | Default | Effect |
443
- | --- | --- | --- |
444
- | `MLX_BUN_EVAL_THINK` | off (`=1`) | Evaluate with `enable_thinking` on (default off for parity with optiq's published non-thinking numbers). |
445
- | `MLX_BUN_EVAL_KV_QUANT` | off (`=1`) | Generate through the model's `kv_config.json` quantized KV during evals (default full-precision KV, matching optiq's eval). An explicit `--kv-quant` on `mlx-bun eval` wins. |
446
- | `MLX_BUN_MMLU_FROZEN` / `MLX_BUN_GSM8K_FROZEN` / `MLX_BUN_HUMANEVAL_FROZEN` / `MLX_BUN_IFEVAL_FROZEN` / `MLX_BUN_BFCL_FROZEN` / `MLX_BUN_HASHHOP_FROZEN` | on (`"0"` reverts) | Use the frozen oracle-exported problem sets (parity with the reference numbers); `=0` falls back to our own sampling of the full set. |
447
- | `MLX_BUN_TRAIN_ATTN` | `ops.sdpa` (unset) | `=flash` selects the hand-rolled O(L)-memory flash kernel for training attention (~30× slower). **Refused for Gemma models** (e4b SIGTRAPs at seq ≥ 2048); MiniCPM5 allowed. |
448
- | `MLX_BUN_FLASH_MIN_M` | `1024` | With a flash-CCE head requested, rows shorter than this take the exact fused head instead; `=0` always honors flash. |
449
- | `MLX_BUN_MEM_LOG` | off (`=1`) | Trainer per-step memory logging. |
450
-
451
- `MLX_BUN_CCE_*` (flash-CCE kernel variant selectors and epsilons in
452
- `src/train/flash-cce.ts`) and `MLX_BUN_SEG_*` (segmented-backward head and
453
- memory probes in `src/train/segmented.ts`) are intentionally undocumented
454
- developer knobs; `MLX_BUN_EVAL_KV_ARM_NOOP` is an inert placeholder the KL
455
- harness flips.
456
-
457
- ### Removed
458
-
459
- `MLX_BUN_PERF_KERNEL`, `MLX_BUN_FUSED_GELU`, `MLX_BUN_FUSED_DECODE`,
460
- `MLX_BUN_FUSED_SWIGLU*`, `MLX_BUN_CPM5_FAITHFUL`, and the `--l3` tier were
461
- deleted 2026-07-05 with their kernels
462
- ([unified-engine-frontier-plan.md](../design/unified-engine-frontier-plan.md));
463
- exporting the variables now does nothing, and `--l3` exits with a pointer.
464
-
465
- ## Execution modes: serial vs. `--batch N`
466
-
467
- Scheduling is **concurrency-driven** (default cap 8): a lone scheduler
468
- request uses the B=1 fast path — its caches are adopted serial-class
469
- objects, compiled decode replays, and the prompt cache and SSD tier serve
470
- it. Only a second concurrent request causes a batch layout to exist. The
471
- flag declares the concurrency cap; active rows select B=1 or B=N inside
472
- the scheduler.
473
-
474
- No flag is needed to enable this default. The cap is a maximum, not a minimum
475
- group size: a lone eligible request starts at B=1. The serial executor remains
476
- available through `--batch 1` and for unsupported request compositions.
477
-
478
- `--batch 1` pins the strict serialized single-queue path: one generation
479
- at a time, arrival-independent numerics (a request's bits never depend on
480
- what else was in flight). Pin it for golden regeneration and
481
- reproducibility work. Batched rows carry bf16 left-pad reduction-order
482
- noise vs their solo runs (calibrated per model in the gated suites) — a
483
- request that never shares a step is bit-identical either way.
484
-
485
- The batched engine is **bit-parity with `mlx_lm.server` at `B=N`** per
486
- row for bf16, and per-row oracle-gated for the quantized compositions:
487
-
488
- - **KV quant unset ⇒ bf16** — the batch path engages out of the box.
489
- - **`--kv-quant config`** (per-layer mixed precision) **batches** on
490
- every shipped model — full-attention and rotating layers — applied per
491
- row, gated bit-exact for unpadded rows vs the serial composition.
492
- - **`--kv-quant 4|8`** uses shared affine conversion and batches on supported
493
- full-attention, rotating and hybrid recurrent models.
494
- - **`turbo`** uses encoded shared rows for qualified start-zero full-attention caches; sliding layers stay bf16.
495
-
496
- ### Scheduling declaration (`GenerationGateway.place`)
497
-
498
- With a cap greater than one, `GenerationGateway.place()` freezes one
499
- scheduling mechanism for the exact resolved request shape: `continuous`
500
- admits it to the scheduler (which then picks B=1 or B=N from active rows);
501
- `serial` preserves the strict executor. The support check never removes,
502
- downgrades, or substitutes MTP, KV schemes, TurboQuant, grammar, adapters,
503
- or sampling — a composition the scheduler does not implement drains it and
504
- runs unchanged serially. The two mechanisms are mutually exclusive on the
505
- GPU (one `AsyncMutex`).
506
-
507
- | Request property | Continuous scheduler? |
508
- | --- | --- |
509
- | vision / audio / video parts | ❌ serial — offset-0 single-sequence prefill + media masks |
510
- | LoRA `adapter` (resolves to ≥1) | ✅ identical ordered adapter sets share a group; different sets wait for the next group |
511
- | `logprobs` / `top_logprobs` | ✅ ordinary and qualified MTP/lookup/standalone-draft groups capture per-request probabilities; other exclusions still apply |
512
- | explicit `seed` | ✅ request-local random stream; reproducibility also depends on model arithmetic and batch composition |
513
- | KV quant active | ✅ batches for per-layer `config` and uniform `4`/`8` schemes on supported cache layouts |
514
- | `--kv-quant turbo` | ✅ qualified TQ layouts; ordinary and supported grouped drafting library requests also support delayed row-local conversion |
515
- | `--draft-model` mounted | ✅ qualified MTP, lookup, standalone, assistant, DeepSpec and DSpark/DFlash groups; provider and request capabilities determine eligibility; supported ordinary requests batch |
516
- | `repetition_penalty` / `min_p` / `xtc_*` / `logit_bias` / presence+frequency penalties | ✅ batches — per-row logits processors over per-row device-side history (Qwen3.5 ships a *default* repetition penalty, so this is load-bearing) |
517
- | structured output (`response_format` / `guided_*`) | ✅ batches — per-row grammar matchers (`MLX_BUN_GRAMMAR_BATCH=0` forces serial) |
518
- | `temperature` / `top_p` / `top_k` | ✅ batches (each row samples with its own seed) |
519
- | `stop` sequences | ✅ batches (per-row `StopMatcher`) |
520
- | `tools` / `tool_choice` | ✅ batches (per-row tool router) |
521
- | `--thinking` / `enable_thinking` | ✅ batches (template-render concern) |
522
- | multi-turn / long prompt | ✅ batches with prompt-cache reuse: a joiner restores the longest usable cached prefix and prefills only the suffix (`cached_tokens` reported) |
523
-
524
- **Which models use continuous scheduling** (`#modelCachesBatchable`):
525
- full-attention (CPM), sliding-window (Gemma), hybrid gated-DeltaNet
526
- (Qwen3.5 — `MLX_BUN_BATCH_SSM=0` reverts to serial routing), and plain
527
- full-attention Tier-0 universal archs (Llama etc., gated token-exact vs
528
- mlx-lm B=2). Still serial by the capability gate: gemma2-family
529
- (`maskArray`) and sliding-window *universal* archs (unvalidated cells) and
530
- DiffusionGemma (non-autoregressive).
531
-
532
- A request requiring the serial mechanism **drains** the scheduler: while
533
- it waits, the scheduler stops admitting new rows, finishes the running
534
- ones, and releases the GPU (mlx-lm's `drain_batch`); admission then
535
- resumes, so batchable traffic cannot starve a serial-lane request.
536
- Placement is not load-dependent: a request admitted to the continuous
537
- scheduler stays there whether it is the only row or one of many.
538
-
539
- ## Compatibility matrix
540
-
541
- "serial" = `--batch 1`; `--batch N` permits continuous scheduling, though a
542
- declared composition may still require the serial mechanism as shown above.
543
-
544
- | Option | serial (`--batch 1`) | `--batch N` (N>1) |
545
- | --- | --- | --- |
546
- | `--kv-quant config` | ✅ applied to all requests | ✅ batches where the loaded cache capability supports the per-layer scheme; otherwise routes serial |
547
- | `--kv-quant 4`/`8` | ✅ applied to all requests | ✅ server start=0 converts during prefill and batches on supported cache layouts; delayed library thresholds still use serial |
548
- | `--kv-quant turbo[:k<bits>v<bits>]` | ✅ ordinary decode; strict serial speculation remains excluded | ✅ ordinary TQ, including delayed library conversion; supported grouped drafting also supports delayed library conversion |
549
- | `--kv-quant off` / unset | ✅ bf16 (the L1 default) | ✅ bf16 |
550
- | `--paged-kv` | ✅ | ✅ Gemma4 bf16; prompt-cache bypass |
551
- | `--memory-budget` | ✅ per-request admission | ✅ per-request admission — not aggregate (use `--kv-budget`) |
552
- | `--kv-budget` | n/a | ✅ aggregate queue/reject across rows |
553
- | `--prompt-cache` / `--ssd-cache` | ✅ prefix reuse + SSD restore | ✅ on both lanes: joiners `take()` at admission; never-merged rows `put()` back |
554
- | `--temperature`/`--top-p`/`--top-k` | ✅ | ✅ (per-row) |
555
- | `--thinking` | ✅ | ✅ |
556
- | vision / audio / video request | ✅ | ✅ via serial lane |
557
- | LoRA `adapter` | ✅ | ✅ compatible groups on adapter-capable backends |
558
- | `repetition_penalty` / `min_p` / `xtc_*` / `logit_bias` / presence+frequency | ✅ | ✅ (batches — per-row processors) |
559
- | `seed` | ✅ | ✅ request-local sampling |
560
- | `tools` / `stop` | ✅ | ✅ (batches) |
561
- | structured output (`response_format`/`guided_*`) | ✅ (mask in the decode loop) | ✅ (batches; per-row matchers) |
562
- | `--draft-model` / `--draft-kind` | ✅ eligible spec decode | ✅ qualified MTP/lookup/standalone-draft groups, including grammar/logprobs; other providers remain serial |
563
- | GLM `--mtp on` | ✅ native MTP spec decode | ⚠️ default-on MTP routes every request serial+spec; `--mtp off` exposes ordinary GLM batching |
564
- | `--compiled-decode` | ✅ | ✅ at **B=1 only**: a lone request's adopted serial-class caches replay the same compiled step; B>1 steps run the plain graph |
565
- | `--fused-sdpa` / `--force-wire` | ✅ (serial decode route) | n/a — compat mode, no perf flags by design |
566
-
567
- ### `--batch N` is compat mode — perf flags don't apply by design
568
-
569
- The bit-parity guarantee (mlx-lm B=N) is the *whole point* of `--batch N`,
570
- and it requires running the plain forward path. The scheduler
571
- ([batch-scheduler.ts](../../src/serve/batch-scheduler.ts)) drives the
572
- model through `forwardHidden`/`logitsFromHidden` directly (not
573
- `generate()`), so:
574
-
575
- - **`--compiled-decode`** engages at **B=1 only** (adopt-don't-copy: the
576
- lone request's caches stay serial-class, so the scheduler replays the
577
- serial engine's compiled step — same kill switch). A second row ⇒ the
578
- plain batched graph.
579
- - **`--fused-sdpa`** never engages in the batched lane (an L2 serial-lane
580
- composition).
581
- - **`--force-wire`** doesn't wire (the scheduler bypasses `generate()`'s
582
- wired scope).
583
- - **Always-on bit-exact kernels still run.** The compiled activations are
584
- bit-exact with the spelled-out MLP, so they stay on in both lanes —
585
- "compat mode" means *no parity-breaking optionality*, not -O0.
586
-
587
- ## Known limitations under `--batch N`
588
-
589
- Deliberate v1 scope, not bugs:
590
-
591
- 1. **Other draft providers lack shared state.** Qwen MTP, prompt lookup and
592
- standalone drafting reuse aligned prefill and completed-output state through
593
- the common RAM/SSD cache. Supported full-attention targets also retain
594
- lookup and standalone-draft state. Gemma assistant drafting retains its target hidden
595
- and donor KV through the same cache. Other providers start fresh. Long-conversation timing and pressure
596
- acceptance remain open.
597
- 2. **Aggregate admission is opt-in** via `--kv-budget`; without it N
598
- large-context rows can collectively exceed memory.
599
- 3. **Coverage depends on composition.** Same-B Gemma oracle tests cover
600
- sliding-window wrap and late joins. Broader media, resume, paged and method
601
- combinations remain open in Phase 18.
602
- 4. **bf16 by contract; mixed-KV batching beyond it.** mlx-lm's batched
603
- path *is* bf16. Per-layer `config` batching is a beyond-mlx-lm
604
- composition verified per row against the optiq oracle. Batched
605
- uniform/TurboQuant now has shared layouts; additional same-B external
606
- oracle and feature-composition checks remain.
607
- 5. **`extend` join** appends a joining request to the running batch's
608
- full-attention KV in one pad+concat (`MLX_BUN_BATCH_EXTEND=0` reverts
609
- to whole-batch re-merge); sliding-window layers still re-merge on join.
610
-
611
- ## Fidelity tiers and the decode route (`--l1` / `--l2`)
612
-
613
- The tiers are **correctness contracts**; each flag is an alias for a
614
- decode-route preset (`applyDecodeRoute()` in `src/cli.ts`), and any
615
- per-fork flag (`--kv-quant`, `--compiled-decode`, `--compiled-activations`,
616
- `--fused-sdpa`) overrides its tier's preset.
617
-
618
- | Tier | Contract | KV | Kernels | Verified against |
619
- | --- | --- | --- | --- | --- |
620
- | `--l1` | mlx-lm **bit-for-bit** | bf16 | compiled decode + compiled activations, fused-sdpa off | mlx-lm goldens (per machine) |
621
- | `--l2` | mlx-optiq **bit-for-bit** | mixed precision (`kv_config.json`) | + fused SDPA (matches optiq exactly) | optiq goldens |
622
- | *(none)* | **= `--l1`** | bf16 | as `--l1` | mlx-lm goldens |
623
- | **Lab** | no external oracle | — | env-flagged experiments with a bench + expiry; graduate only by beating L1 in a paired A/B | validity / KL / eval gates |
624
-
625
- Compiled decode is on in **every** tier (proven bit-exact with uncompiled —
626
- free speed, not a fidelity trade). **There is no `--l3` tier** (removed
627
- 2026-07-05; its role is the Lab).
628
-
629
- **KV precision is a separate axis from the tier's kernels.** `--l1
630
- --kv-quant 8` is a bit-exact L1 config: with fused-sdpa off our quantized
631
- decode runs `quantizedSdpaUnfused`, op-for-op mlx-lm's
632
- `quantized_scaled_dot_product_attention` (`mlx_lm/models/base.py`). Only
633
- the per-layer `config` scheme is optiq-only (→ L2).
634
-
635
- **Where each feature sits:** batching = L1-class (mlx-lm B=N parity);
636
- two-model speculative decoding = L1-class; structured output = L2-class
637
- (oMLX oracle; masking doesn't touch the numerics of valid tokens, so it
638
- composes with any tier); grammar × spec, HLG sampling, expert offload,
639
- TurboQuant's cache class, jump-forward decoding, and batched
640
- uniform/turbo KV are **no-oracle (Lab-gated)**.
641
-
642
- ## Feature matrix
643
-
644
- Everything mlx-bun serves, with its default, lane, fidelity tier, and knob.
645
-
646
- ### Serving & performance
647
-
648
- | Feature | Default | Lane | Tier | Knob |
649
- | --- | --- | --- | --- | --- |
650
- | OpenAI chat completions (`/v1/chat/completions`, SSE) | on | both | — | — |
651
- | Raw text completions (`/v1/completions`) | on | both | — | — |
652
- | Anthropic Messages (`/v1/messages`) | on | both | — | — |
653
- | OpenAI Responses shim (`/v1/responses`) | on | both | — | — |
654
- | Continuous batching (mlx-lm parity at the same B) | on, cap 8 | batch | L1 | `--batch <n>` (`1` pins serial) |
655
- | Prompt cache (prefix KV reuse) | on, 8 GiB | both | — | `--prompt-cache <GB>` (`0` = off) |
656
- | SSD KV cold tier (survives eviction + restarts; GLM compressed MLA/DSA state included) | off | both | — | `--ssd-cache <dir>` (+ `--ssd-cache-max`, `--ssd-cache-verify`, `--ssd-demote-idle`, `--generation-checkpoint`) |
657
- | Runtime isolation (crash-isolated engine child behind a proxy parent) | off | both | — | `--isolate` |
658
- | Model pool (LRU-capped resident engines under `--isolate`) | 1 | both | — | `--model-pool <n>` |
659
- | Mixed-precision KV (`kv_config.json`, optiq's scheme) | off | serial + batch (per-layer configs batch) | L2 | `--kv-quant config`, `--l2` |
660
- | Uniform quantized KV (mlx-lm's `--kv-bits` scheme) | off | serial + batch | L1 | `--kv-quant 4\|8` |
661
- | TurboQuant KV (rotation-based: affine keys + FWHT/Lloyd-Max values) | off | serial + qualified shared ordinary/drafting | Lab (codec oracle-backed; composition gates apply) | `--kv-quant turbo[:k<bits>v<bits>]` (default `k8v3`) |
662
- | Compiled decode (bit-exact graph replay) | on | serial, batch at B=1 | L1/L2 | `--compiled-decode on\|off` |
663
- | Compiled activations (mlx-lm's `@mx.compile` geglu/swiglu) | on | both | L1 | `--compiled-activations on\|off` |
664
- | Fused SDPA (optiq-exact quantized-KV attention) | follows `--kv-quant` | serial | L2 | `--fused-sdpa on\|off` |
665
- | Paged KV (vLLM-style block pool, gather before the stock SDPA) | off | shared B1/B>1 | gated bit-exact vs plain `KVCache` | `--paged-kv`, `--paged-kv-block-size <n>` |
666
- | Speculative decoding (two-model / Gemma `-assistant` / DSpark / DeepSpec / native MTP head) | off | shared Qwen methods; full-attention/rotating lookup/standalone and Gemma assistant/DeepSpec/DSpark; other combinations serial | per-drafter oracle (L1 two-model, L2 assistant, DeepSpec reference, Lab DSpark) | `--draft-model`, `--draft-kind`, `--num-draft-tokens` |
667
- | GLM-5.2 checkpoint-native MTP | on for GLM-5.2 | serial+spec | oracle trajectory + synthetic HTTP gate | `--mtp on\|off` |
668
- | Model-free prompt-lookup speculation (vLLM `ngram` port) | off | Qwen and full-attention targets shared / other models serial | lossless by verify (gated vs non-spec greedy) | `--draft-kind ngram`, `--ngram-max`, `--ngram-min`, `--num-draft-tokens` (default 10) |
669
- | Estimated memory admission | off (advisory) | both | — | `--memory-budget <GB>` opts in |
670
- | Aggregate KV admission for batch rows | off | batch | — | `--kv-budget <GB>` |
671
- | Expert offload (MoE experts on mmap) | off | serial | Lab | `--expert-offload` |
672
- | Extend-join (O(1) batch admission) | on | batch | L1 (mlx-lm `extend`) | `MLX_BUN_BATCH_EXTEND=0` |
673
- | Vectorized greedy batch sampling | on | batch | bit-equal A/B | `MLX_BUN_BATCH_VEC_SAMPLE=0` |
674
- | Pipelined batch token readback | on | batch | numerically equivalent | `MLX_BUN_BATCH_NO_PIPELINE=1` |
675
-
676
- ### Request features
677
-
678
- | Feature | Default | Lane | Tier | Knob |
679
- | --- | --- | --- | --- | --- |
680
- | Structured output (`response_format` json_object/json_schema) | on | both | L2 (oMLX) | request field; `MLX_BUN_GRAMMAR=0` kills |
681
- | Structured-output jump-forward (grammar-forced spans in one forward) | off | serial only | Lab | `MLX_BUN_GRAMMAR_JUMP=1` |
682
- | Token fast-forwarding for tool calls (template-determined spans in one forward) | off | serial only | opt-in; identity tested on covered fixtures, parser/held-out gates remain (`tests/parity/fill-strict.test.ts`) | `MLX_BUN_FILL=strict` |
683
- | Echo injection (session self-copy spans, verified against the same forward's logits) | off | serial only | Lab (paired A/B on task success + wall clock before any default) | `MLX_BUN_FILL=echo`, `MLX_BUN_FILL_K`, `MLX_BUN_FILL_CANDIDATES`, `MLX_BUN_FILL_INDEX_MAX` |
684
- | `guided_grammar` (EBNF) / `guided_regex`¹ / `guided_choice` / `structured_outputs` | on | both | L2 | request fields |
685
- | Structured output × speculative decoding | on when both active | Qwen grouped MTP, lookup and standalone drafting / eligible serial methods | Lab | — |
686
- | Quantized KV × speculative decoding | Shared Qwen supports uniform KV4/KV8 and TQ with zero or positive conversion thresholds; strict serial supports qualified KV4; per-layer mixed KV remains excluded | Qwen grouped MTP, lookup and standalone drafting / eligible serial methods | scheme and method gates | `MLX_BUN_QWEN_SPEC_KV4=0` disables the KV4 composition |
687
- | Tool calling (Gemma sentinel / CPM+Qwen XML / GLM `arg_key`+`arg_value`) + `role:"tool"` loops | on | both | — | request `tools` |
688
- | Vision (`image_url`; PNG/JPEG/HEIC/AVIF/WebP/TIFF/GIF/BMP) | on for models with a tower; SSRF guard on remote URLs | serial | L1/L2 | `--allow-private-media` |
689
- | Video input (`video_url`/`video`; AVFoundation sidecar, 2 fps, ≤768 frames, 256 MB body cap; never with audio) | on for Qwen3.5-family | serial | mlx-vlm oracle | `--allow-private-media`, `MLX_BUN_FRAME_EXTRACT` |
690
- | Audio input (`input_audio`/`audio`/`audio_url`; WAV native, mp3/m4a/flac/ogg/aiff via CoreAudio; ≤30 s per clip; mixes with images) | on for models with `audio_config` + sidecar tower (e4b) | serial³ | L2 (greedy stream exact vs optiq's internal model) | `--allow-private-media` |
691
- | LoRA adapters (mount at start / hot-swap) | off | compatible groups | — | `--adapter <dir>`, `POST /v1/adapters` |
692
- | 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 |
693
- | `logprobs` / `top_logprobs` | off | both | L1 | request fields |
694
- | Fixed `seed` reproducibility | off | both | — | request field; compare the same execution composition |
695
- | Thinking-mode control (hybrid-reasoning models) | model default | both | — | `--thinking`, `chat_template_kwargs`, `reasoning_effort` |
696
- | Stop sequences / streaming / usage accounting | on | both | — | request fields |
697
- | HLG tone-curve sampling | off | serial | Lab | `--hlg-sampling on` |
698
- | Spec-decode telemetry (`usage.speculation`) | on with a draft | Qwen shared MTP, lookup and standalone drafting / eligible serial methods | — | — |
699
- | Token-fast-forwarding telemetry (`usage.fill`) | on with `MLX_BUN_FILL=strict` | serial | — | — |
700
- | Per-turn lane telemetry (`usage.lane`: serial / serial+spec / batched) | on | both | — | — |
701
-
702
- ### Model coverage (per-model validated cells)
703
-
704
- | Family | Serial | Batch | Notes |
705
- | --- | --- | --- | --- |
706
- | MiniCPM5 (cpm5) | ✅ L1/L2 | ✅ | the starter model |
707
- | Gemma 4 (1B/e4b/12B/26B, + vision e4b/12B, + audio e4b) | ✅ L1/L2 | ✅ | sliding+full interleaved; MoE 26B |
708
- | Qwen3.5 (gated-DeltaNet hybrid) | ✅ L1/L2 | ✅ (SSM path) | `MLX_BUN_BATCH_SSM=0` reverts |
709
- | Qwen3.8-27B (same qwen3_5 graph) | ✅ L1 | ✅ (SSM path) | native MTP head via `--draft-model`/`--draft-kind mtp` (lossless-gated; slower on a quiet box — opt-in); images and video serve (mlx-vlm oracle) |
710
- | GLM-5.2 / Colibri | ✅ chat/text, Messages, Responses, SSE, tools, grammar, logprobs | ✅ compressed MLA/DSA scheduler | native MTP defaults to serial+spec; `--mtp off` enables batching; embeddings, vision/audio, adapters, training unsupported |
711
- | DiffusionGemma-26B (non-autoregressive) | ✅ (own engine) | — serial always | first bit-exact non-AR port |
712
- | Tier-0 universal (llama/qwen2/qwen3/olmo2/…, 11 archs) | ✅ L1 | ✅ plain full-attention archs² | gemma2-family / sliding-window universal → serial |
713
-
714
- ¹ `guided_regex` accepts the regex∩EBNF subset today (no `\d`/anchors — those degrade to prompt injection).
715
- ² Gated token-exact vs mlx-lm B=2 (static + dynamic join/leave) on Llama-3.2-3B.
716
- ³ Audio is a capability neither ancestor serves (mlx-lm strips the tower; optiq never wires it into its serve frontend). Serial by design; prompt cache skipped.
717
-
718
- Beyond serving, the same binary does training (`mlx-bun train`),
719
- quantization (`convert`, `fuse`), embeddings, local memory (`mlx-bun
720
- memory`), the pi agent (`mlx-bun pi`), the registry/`fit`/`gc`, HF
721
- `upload`, and the web Model Hub — see [cli.md](./cli.md).
722
-
723
- ## Performance characteristics & recipes
724
-
725
- Reference numbers are from this project's dev machines (loaded-machine
726
- numbers are directional only; [benchmarks.md](./benchmarks.md) holds the
727
- quotable set, and `scripts/bench-matrix.ts features` measures the
728
- composition cells in one run).
729
-
730
- - **A lone request is the serial engine** — prompt cache, compiled
731
- decode, and SSD restore all apply at B=1 under the default cap.
732
- - **`--batch N` wins under concurrency** — cpm5 `--batch 4`: ~349 tok/s
733
- aggregate vs ~173 serial-queued, TTFT 2–3× better; Llama-3B at B=2:
734
- 1.7× aggregate, TTFT 765→162 ms.
735
- - **Spec pays only on slow targets.** One accepted draft = one skipped
736
- target forward: 12B ≈ 1.09× at γ=1; fast small targets lose (e4b
737
- 0.78×). Draft for 12B+, skip below.
738
- - **Structured output is ~free** (<1% serial; bounded ~0.1 ms/step class
739
- in the batch lane).
740
- - **`--ssd-cache` has 0% decode overhead** — pure TTFT/restart win.
741
- - **Quantized-KV prefill pays a scheme-intrinsic tax at long context** —
742
- chunked prefill converts each chunk's KV at the boundary, so later
743
- chunks attend against the quantized prefix (the same streaming
744
- conversion optiq serve uses): ~30% prefill throughput vs bf16 at ~16k
745
- where the config quantizes every cache, single-digit % on the
746
- sliding-window gemmas. The lever is upstream (mlx `quantized_matmul`,
747
- [decode-speed-program.md](../design/decode-speed-program.md) lever 2).
748
-
749
- **Recipes:**
750
-
751
- - *Single-user agent/chat (the default use):*
752
- `mlx-bun serve <model> --ssd-cache <dir>` — L1, prompt cache + SSD tier.
753
- On 12B+ add `--draft-model <small-same-tokenizer>`.
754
- - *Several clients at once (throughput):*
755
- `mlx-bun serve <model> --batch 4 --ssd-cache <dir> --kv-budget <GB>` —
756
- supports qualified start-zero TurboQuant and a grouped Qwen MTP companion.
757
- Other draft providers still use serial speculation.
758
- - *UI must never lag / survive engine crashes:* add `--isolate`
759
- (`--model-pool 2` to keep two models resident).
760
- - *Reproducibility:* bare / `--l1` (≡ mlx-lm), `--l1 --batch 1` (strict
761
- serial), `--l2` (≡ optiq).
762
- - *Memory-tight big model:* `--kv-quant config|4|8|turbo` +
763
- `--memory-budget <GB>` + `--ssd-cache <dir>`; MoE adds
764
- `--expert-offload`. Start-zero TurboQuant supports shared execution.
765
-
766
- **Remaining exclusions:** media, paged KV, generation resume, fill and draft
767
- providers without grouped implementations still need shared execution work.
768
- Qwen ordinary, shared MTP and prompt lookup support positive library thresholds for uniform
769
- affine KV4/KV8 and TurboQuant. Ordinary Gemma supports positive affine KV4/KV8
770
- thresholds, including sliding-window layers. Other-model delayed affine remains
771
- open. Qwen MTP
772
- prefill and completed decode state use the common RAM/SSD cache. Generated
773
- checkpoints contain only processed tokens; persistence uses the existing
774
- queue. Strict serial deletion and complete feature parity
775
- remain acceptance work in Phase 6/18.
776
-
777
- ## Observability — `GET /stats`
778
-
779
- The live config and batch state. The canonical field-by-field snippet
780
- lives in [server-api.md](server-api.md#get-stats); highlights:
781
- `prompt_cache` (cap), `kv_quant.mode` (incl. `turbo kXvY`), the
782
- conditional `ssd_cache` block (pending/dropped/failed spill counters), the
783
- conditional `glm52` block, and `batch`
784
- (`mode`/`active_rows`/`pending_rows`/`submitted_rows`/`kv_bytes`/
785
- `kv_budget_bytes`).
786
-
787
- `batch.mode` is the truthful configured/capability state: `off` for
788
- `--batch 1`, `serial` when a larger configured cap cannot batch the loaded
789
- model's cache layout, and `batch` when the model is admitted.
790
- `batch.batched` is the compatibility boolean for `mode == "batch"`;
791
- `active_rows` is the instantaneous live-row count. Under `--isolate`,
792
- `GET /engine` on the parent reports the child pid, restart count, socket,
793
- and pool residency.
794
-
795
- Managed quantization and finetuning jobs wait for the serving gateway to drain,
796
- then hold its execution lease until their subprocess exits. Generation and native
797
- preparation wait during that job. Shutdown cancels queued jobs and terminates the
798
- host's active job before releasing its lease. Resident model weights remain
799
- loaded. Under isolation, the parent coordinates all of its model-pool workers.
800
- This controls execution, not memory capacity or independently launched servers.
801
-
802
- ### Delayed KV conversion in library requests
803
-
804
- The CLI keeps `quantizedKvStart=0`. A library `KvScheme("turbo", ...)` can
805
- set a positive threshold for ordinary or Qwen MTP shared execution. Every row converts
806
- at its own existing maintenance boundary. During the mixed phase, the
807
- cache retains plain and encoded rows independently while model attention
808
- still runs at the shared batch size. The fetched attention state restores
809
- only the rotated value rows; once all rows convert, the standard packed
810
- batch layout takes over. Shared MTP converts committed history before a
811
- verification round; crossing the threshold inside that round converts at
812
- resolution after rollback and before checkpoint publication. Rejected tokens
813
- cannot set the conversion offset.
814
-
815
- Qwen ordinary, shared MTP and prompt lookup also support positive `quantizedKvStart` with
816
- uniform affine KV4/KV8. Affine and TQ adapters share the same row-transition
817
- lifecycle. During mixed affine precision, each row uses its existing plain or
818
- quantized attention arithmetic; after conversion, the packed batch layout owns
819
- attention. The model binding declares this support; scheduling does not choose
820
- the codec or conversion boundary. Ordinary Gemma also supports delayed affine
821
- conversion in full and sliding-window layers. Rotating rows retain the same
822
- physical columns while converting independently, so shared attention masks stay
823
- aligned. Gemma speculative methods and other-model delayed affine remain open.
824
-
825
- A delayed conversion records the earliest reusable prefix offset. RAM and
826
- SSD reuse preserve earlier plain donors and never trim converted state
827
- below that boundary. Older TQ SSD files without this metadata remain
828
- usable at their stored offset, but cannot serve shorter prefixes. The
829
- start-zero default-group cache keys are unchanged; positive TQ and affine
830
- thresholds, and non-default affine group sizes, have distinct keys.
831
- No memory budget or admission default changes.
832
-
833
-
834
- Supported grouped draft providers also accept TurboQuant with positive library
835
- conversion thresholds. Full-attention layers use the selected codec; sliding
836
- layers stay bf16. Generated target and method-companion snapshots preserve
837
- precision through RAM and queued SSD persistence. Defaults are unchanged.
838
- Composition evidence and remaining gaps: [batching design](../design/batching.md).
839
-
840
- The programmatic `createServer` option `quantizedKvStart` sets the absolute
841
- per-row offset at which the selected KV scheme converts. Omission preserves
842
- the existing start-zero server policy. This option is resolved once with the
843
- KV scheme and shared by request preparation, execution, and checkpoint identity.
844
- Generation checkpoints preserve encoded state and each cache's earliest reusable
845
- offset; restoring a checkpoint does not re-quantize it. TurboQuant retains its
846
- existing full-attention scope, with sliding-window caches in bf16.