mlx-bun 0.0.13 → 0.3.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 (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -1,371 +0,0 @@
1
- # DSpark serving program — flip spec wall-clock positive + design the product surface
2
-
3
- Status: **PLANNED** (2026-07-07). Trigger for Josh's pickup: TurboQuant merge —
4
- but only Phase 5 actually depends on it; Phases 0–4 are start-anytime.
5
- Owner: decode / spec. Predecessors: PR #19 (DSpark paper code-complete +
6
- serve-integrated + DeepSpec oracle), the first-live-run findings in
7
- [dspark-handoff.md](../investigations/dspark-handoff.md) "FIRST LIVE RUN".
8
-
9
- ## The problem, in numbers (2026-07-07 first live run, loaded machine)
10
-
11
- `gemma-4-12B-it-OptiQ-4bit` + `deepseek-ai/dspark_gemma4_12b_block7` (γ=7):
12
-
13
- - **τ ≈ 2.8** committed tokens per target forward (2.7× fewer target calls) —
14
- the algorithm WORKS, at 26–33% per-token acceptance (the predicted
15
- OptiQ-4bit-target degradation vs their bf16 training).
16
- - **Wall-clock LOST ~3.4×** (spec 14.6 vs serial 49.8 agg tok/s). The tax is
17
- the drafter itself: 6.9 GB bf16 → ~3 GB of weight reads per draft round
18
- (2 GB untied lm_head + 7 × 134 MB markov_w2 + layers), ~14 host syncs per
19
- round in the transcription-faithful `draftBlock`, tapped verifies falling
20
- back to the unoptimized monolith, and ~14 GB of two-model weights
21
- squeezing the 24 GB box.
22
- - The 20 s bench TTFT was conc-4 queueing on the serial-forced spec lane
23
- (documented routing), not prefill — but per-request slowdown is real.
24
-
25
- **Goal:** spec ≥ 1.3× serial decode on 12B at the best config, clean-machine
26
- paired A/B — then (and only then) design when it's on by default. Every phase
27
- has its own gate; the drafter-quantization thesis
28
- ([[drafter-quantization-thesis]]) makes the risky-looking phase (aggressive
29
- quant) the SAFEST: drafter numerics only move acceptance, never correctness,
30
- so the entire quality gate is one acceptance A/B.
31
-
32
- **THE OBJECTIVE, stated right (Josh, 2026-07-07): 26–33% acceptance with the
33
- bf16 drafter is the WORKABLE BASELINE — τ≈2.8 already pays. The question
34
- quantization must answer is PRESERVATION: do we still get that number at
35
- 4-bit?** The point of quantizing (and of mixed precision specifically) is
36
- never compression for its own sake — it's cutting the drafter's cost 4×
37
- WITHOUT making it terrible at predicting tokens.
38
-
39
- **Sensitivity is MEASURED, never guessed — and THE TOOL ALREADY EXISTS
40
- (Josh): optiq's sensitivity method** (mlx-optiq.com/docs/sensitivity —
41
- per-group simulate-quant → KL vs reference on a curated calibration mix →
42
- greedy knapsack allocation to target BPW, emitted as a quant predicate).
43
- Phase 1e adopts it for the drafter rather than inventing anything; the
44
- drafter's target-hiddens-in forward even makes it cheaper (cached hiddens →
45
- no 12B in the sweep loop). Allocation comes from the measured table;
46
- hypotheses (lm_head argmax-proximal, chain compounding, buffered layers)
47
- are recorded for falsification only. Phase 1.5 (fine-tune) is an OPTIONAL
48
- UPSIDE lever on top of the workable baseline, not a premise that acceptance
49
- is broken.
50
-
51
- **And TurboQuant's role, stated right (Josh): TQ is the better-quant-at-
52
- EQUAL-bits instrument — the preservation tool, not a compression ladder.**
53
- Mechanism: distribute the weight vectors Gaussian, then place the
54
- quantization levels non-uniformly with FINER step sizes around the peak
55
- where the mass lives — affine 4-bit spends half its levels on tails TQ
56
- barely pays for. Expected: TQ-4bit preserves acceptance better than
57
- affine-4bit at the same size; the Phase-5 headline comparison is TQ-4 vs
58
- affine-4 AT EQUAL BPW, with lower-bpw rungs only after that's won.
59
-
60
- ## Phase 0 — baseline + attribution (no code; Josh's shell for GPU runs)
61
-
62
- The scoreboard everything else is measured against. All directional runs
63
- fine on a loaded box; the FINAL pre/post pair must be clean-machine.
64
-
65
- - [ ] **0a. Oracle gate the bf16 port ONCE** (before any optimization, so
66
- later acceptance deltas are attributable to quant/tuning, not port bugs):
67
- torch venv + DeepSpec install (header of
68
- `scripts/oracle-dspark-deepspec.py` documents setup), dump the temp-0
69
- trace (threshold 0 and 0.5 arms), run
70
- `scripts/dspark-deepspec-compare.ts` — target vs their reference on the
71
- **bf16 HF 12B** (`--target` the bf16 snapshot; the OptiQ-4bit arm is
72
- `--acceptance-only`, a measurement not a bit gate). Fixture per
73
- goldens/README.md conventions. Exit: round-for-round PASS, or a filed
74
- divergence with the first-divergent round attached.
75
- - [ ] **0b. γ sweep, conc 1** (no code): serve with `--num-draft-tokens`
76
- ∈ {2, 3, 5, 7} × `bench-feature-matrix.ts --concurrency 1 --cells
77
- serial,spec`. Record per-request tok/s + acceptance + TTFT per γ. Exit: a
78
- table; the best-γ config is the Phase 1 comparison base.
79
- - [ ] **0c. Time attribution**: xctrace (or coarse: MLX_BUN_LANE_DEBUG +
80
- timers around `source.draft` / verify forward / commit in a scratch
81
- branch) on ~20 rounds. Split: draft-block GPU, draft host syncs, verify
82
- forward, tap/commit overhead. Plus the paging check: RSS + `vm_stat`
83
- pageouts during a run (is the 14 GB pairing thrashing?). Exit: a
84
- percentage breakdown — it ORDERS phases 1–3 by measured value, replacing
85
- the estimates below.
86
-
87
- ## Phase 1 — quantize the drafter (uniform 4-bit baseline; NOT TurboQuant yet)
88
-
89
- The expected big lever: 6.9 GB → ~1.8 GB kills bandwidth AND memory pressure.
90
- mlx-native group quantization, no research dependency.
91
-
92
- - [x] **1a. `scripts/dspark-quantize-drafter.ts`** *(DONE 2026-07-07 — thin
93
- driver over the house quantizer: `src/spec/dspark/quantize-drafter.ts`
94
- adds a `quantizePredicate` overlay (confidence_head kept bf16, recorded
95
- as the mlx `false` convention); load smoke = DeepspecDrafter reload +
96
- one quantized fc forward)* — reads a DeepSpec-format
97
- checkpoint dir, writes a quantized sibling (same config.json + arch stamp,
98
- plus the house `quantization: {bits, group_size}` block). Per-tensor
99
- policy:
100
- - QUANTIZE (group-64, 4-bit default, flag-tunable): every 2-D matmul
101
- weight — `layers.*.self_attn.{q,k,o}_proj`, `layers.*.mlp.{gate,up,
102
- down}_proj`, `fc`, `lm_head`, `markov_head.markov_w2`, and
103
- `embed_tokens` + `markov_head.markov_w1` as quantized-gather lookups
104
- (mlx QuantizedEmbedding semantics — mlx-lm quantizes embeddings; ours
105
- must match its gather-dequant numerics).
106
- - KEEP bf16: all norms, `layers.*.layer_scalar`, `confidence_head.proj.*`
107
- (tiny), biases.
108
- - Output verified loadable before exit (load smoke).
109
- - [x] **1b. Quantized forward in `src/spec/dspark/deepspec-module.ts`**
110
- *(DONE 2026-07-07 — MatW/TableW weight representation: `.scales` sibling
111
- detection, quantized_matmul transpose=true for every Linear, mlx
112
- QuantizedEmbedding gather-dequant for embed_tokens/markov_w1; bf16 path
113
- keeps the lazy transpose views untouched; synthetic quantized-checkpoint
114
- describe block added — 8-bit tracks bf16 token-for-token)*:
115
- detect quantization at load (scales/biases sibling keys — the house
116
- detection pattern), route matmuls through `quantized_matmul` and lookups
117
- through the quantized-gather path; bf16 path untouched (both formats load
118
- through the same class — kind detection unchanged). Synthetic-format test
119
- extended with a tiny quantized checkpoint (same file, new describe block).
120
- - [x] **1c. The acceptance A/B harness** *(DONE 2026-07-07 — runner drives
121
- `specServeRun` per arm (target loaded once, drafters sequential); spec
122
- telemetry extended with per-position draftedByPos/acceptedByPos; the
123
- stats/verdict math is model-free in `src/spec/dspark/ab-stats.ts`,
124
- unit-tested in tests/dspark-ab-stats.test.ts; chat-template rendering
125
- pins enable_thinking OFF)* — `scripts/dspark-drafter-ab.ts`:
126
- same target, same prompt set (≥32 prompts, temp 0), drafter A vs drafter
127
- B; reports per-position acceptance, τ, tok/s, and a paired verdict. This
128
- is THE gate for every quantization experiment from here on (Phase 5
129
- reuses it unchanged). Model-free logic unit-tested; the run itself is
130
- GPU/Josh.
131
- - [ ] **1d. Run it**: 4-bit vs bf16 drafter at best-γ from 0b. Exit criteria:
132
- acceptance drop ≤ 3 points absolute AND wall-clock strictly improves;
133
- record both. If 4-bit alone flips spec past serial — say so loudly in the
134
- handoff, that's the headline.
135
- - [ ] **1e. The MEASURED sensitivity map — ADOPT OPTIQ'S METHOD, don't
136
- invent** (mlx-optiq.com/docs/sensitivity; source readable in the oracle
137
- venv's `site-packages/optiq`). Their loop, verbatim: reference logits on
138
- calibration data → simulate-quantize ONE group (quantize→dequantize
139
- round-trip) → KL divergence on the full output distribution → restore →
140
- next (group, bits); then their greedy knapsack (max KL-reduction per
141
- extra bit) allocates to a target BPW. **Applied to the drafter it gets
142
- CHEAPER than optiq's own runs**: the drafter isn't mlx_lm-loadable
143
- (its forward needs target hiddens), so `optiq convert` can't run on it
144
- directly — but that same fact removes the 12B from the loop entirely.
145
- Cache tapped hiddens ONCE over an optiq-style 6-domain calibration mix
146
- (our PATH-B shard format stores exactly this), then the whole sweep is
147
- drafter-forward-only KL: 3B × ~10 groups × candidate bits = minutes.
148
- The knapsack's output config gets ONE end-to-end acceptance A/B (1c
149
- harness) as confirmation — KL is the search signal, acceptance is the
150
- ship gate. Their protected-tensor defaults (lm_head/embed highest bits,
151
- first/last blocks) are noted as the static prior their own exact method
152
- exists to replace — we run the exact method; the drafter is small.
153
-
154
- ## Phase 1.5 — acceptance upside (OPTIONAL; the baseline is already workable)
155
-
156
- 26–33% (τ≈2.8) with the bf16 drafter pays as-is — this phase is the
157
- opportunistic numerator work on top, NOT a precondition: the gap vs their
158
- bf16-target numbers is distribution shift with a known mechanism, and every
159
- point recovered multiplies the cost work. Run it if Phase 1's preserved
160
- acceptance + cost win lands short of the ≥1.3× goal, or whenever the upside
161
- is worth the run.
162
-
163
- - [ ] **1.5a. Adaptation fine-tune on OUR target's hiddens** — their
164
- checkpoint as init (the expensive pretraining is done; this is short
165
- distribution adaptation, not their 10-epoch/38 TB run). The data comes
166
- from OUR stack by construction: tap `[5,17,29,41,46]` hidden dumps from
167
- the OptiQ-4bit 12B over on-distribution generations (the PATH-B regen
168
- tooling extracts exactly this). OPEN DESIGN (resolve first): where the
169
- gradient runs — (a) export our tapped-hidden shards into DeepSpec's
170
- torch trainer format and fine-tune with THEIR code (MIT; least new code,
171
- needs a torch box/venv and a shard-format bridge), vs (b) a training
172
- path for the deepspec module in our stack (autograd through the port —
173
- more work, fully local). Gate: acceptance A/B (1c harness) pre/post
174
- fine-tune on held-out prompts; expected: a large chunk of the
175
- bf16-vs-OptiQ gap closes.
176
- - [ ] **1.5b. Confidence-threshold activation** — at 26% acceptance the
177
- scheduler is finally in its design regime: sweep the raw threshold
178
- (their knob) and/or our calibrated thresholds; objective =
179
- tokens-per-second, not τ (pruning doomed positions trades a little τ
180
- for less wasted draft+verify work). Free: no code, the machinery
181
- shipped in PR #19.
182
- - [ ] **1.5c. Quantify the target-fidelity axis** (measurement, not a
183
- build): acceptance vs target quant — e.g. the same drafter against a
184
- higher-fidelity 12B variant if one fits (mixed/8-bit tap-layer
185
- experiments), to split "drafter needs adapting" from "target hiddens
186
- are too degraded". Informs whether 1.5a alone suffices.
187
-
188
- ## Phase 2 — tighten `draftBlock` (replay the proven tightening)
189
-
190
- `Gemma4DSparkModel.draftBlock` kept the reference's per-position structure
191
- (transcription fidelity): 7 argmax `itemUint32` syncs + 7 confidence
192
- `toFloat32` syncs per round. We already solved this exact shape once
193
- (module-dflash.ts, 2026-07-06 — bit-identity-pinned).
194
-
195
- - [ ] **2a. On-device token chaining**: the sequential Markov loop keeps the
196
- argmax result as a device `[1]` index feeding the next position's
197
- `takeAxis(markov_w1, ·)`; ONE concat + ONE host read after the loop.
198
- (Post-1b the bias matmul is quantized too.)
199
- - [ ] **2b. Confidence: compute NOTHING at threshold ≤ 0** (their default —
200
- today we compute + sync 7 confidences that are then unused); when a
201
- threshold IS set, per-position reads are inherent to the truncation
202
- decision (same reasoning as the dflash loop — document it).
203
- - [ ] **2c. `collectLogits`-style skip** for `baseLogits` if the serve path
204
- still materializes anything it discards (audit `DeepspecSource.draft` —
205
- it disposes `block.baseLogits` unread; make the module skip building it,
206
- mirroring `DflashDraftOpts.collectLogits`).
207
- - [ ] **Gate**: bit-identity — pinned tokens on the deterministic synthetic
208
- checkpoint pre/post rewrite (the tests/dspark-infer-loop.test.ts
209
- pattern), plus real-checkpoint determinism (same prompt twice → same
210
- drafts). Tightening is a pure optimization; any token change is a bug.
211
-
212
- ## Phase 3 — `captureLayer` in the generated gemma forwards
213
-
214
- Tapped spec forwards (prefill + EVERY verify round) currently fall back to
215
- the monolith (the 2026-07-07 guard fix — correct-but-unspecialized). The
216
- verify forward is the spec path's biggest single GPU cost; give it back the
217
- generated fast path. Independent of Phases 1–2; parallelizable.
218
-
219
- - [ ] **3a. `scripts/gen-model.ts`**: emit the tap exactly as the monolith
220
- does — `captureLayer(i, h)` after each layer's residual
221
- (gemma4.ts:970 semantics) + the post-finalNorm sentinel
222
- (index = nLayers, gemma4.ts:989) — and REMOVE `this.hiddenTap !== null`
223
- from the emitted fallback guard.
224
- - [ ] **3b. Regenerate all three** (12b / 26b / e4b; regen commands in each
225
- file's header) — the hand-patched guards are superseded by generator
226
- output.
227
- - [ ] **Gate**: (i) generated-parity suite green (untapped behavior
228
- untouched); (ii) NEW tap-parity check — tapped rows bit-equal
229
- monolith-vs-generated on the same input (model-gated test, e4b);
230
- (iii) spec bench pre/post for the verify-round win.
231
-
232
- ## Phase 4 — serving UX: flags, defaults, composition (the product pass)
233
-
234
- Decisions, made on Phase 0–3 DATA, then implemented. The doctrine rails:
235
- drop-in-replacement (a lone request must never get slower because a flag
236
- exists), dont-delete-optionality (losing configs stay documented
237
- default-off), spec = opt-in until it WINS a clean-machine paired A/B.
238
-
239
- - [ ] **4a. γ default per drafter kind**: the checkpoint's trained γ is the
240
- cap, not necessarily the default — if 0b says γ=3 beats γ=7 at our
241
- acceptance, `numDraftTokens` defaults to the measured-best (per-kind
242
- table in code, overridable), and the handoff documents why.
243
- - [ ] **4b. Quantized-drafter UX**: `mlx-bun get` the bf16 →
244
- `scripts/dspark-quantize-drafter.ts` is a manual step today; decide
245
- whether `serve --draft-model <bf16-dir>` should offer/auto-run the
246
- 4-bit conversion (like the starter-model flow) or just print the
247
- command. Also: registry listing shows drafters distinctly (they are not
248
- servable models — `/v1/models` must NOT list them; verify).
249
- - [ ] **4c. Spec × prompt-cache composition** (parity-plan §7.6 — currently
250
- BYPASSED on the spec path, v1 note in serve-loop.ts): multi-turn agents
251
- re-prefill every turn when a draft is mounted. Scope it here or
252
- explicitly re-defer with the measured cost (12B multi-turn TTFT with
253
- spec on). At minimum: the boundary-snapshot machinery must not regress
254
- when spec is mounted.
255
- - [ ] **4d. Surface audit**: `--draft-kind` (keep), `--num-draft-tokens`
256
- semantics doc, `/stats` shows mounted drafter + kind + γ, `usage.
257
- speculation` already ships. server-config.md gets a "speculative
258
- serving" section consolidating the four kinds + the when-does-it-pay
259
- table (from Phase 0/1 data). features-matrix + cli.md + README rows.
260
- - [ ] **4e. The default decision, written down**: for each (model, drafter)
261
- pair measured, spec default on/off per the clean-machine A/B — recorded
262
- in RESULTS.md "composition" + the features matrix. (Prediction to test:
263
- ON for 12B+quantized drafter, OFF for e4b anything.)
264
-
265
- ## Phase 5 — TurboQuant application (the trigger event)
266
-
267
- Trigger, precisely: **TQ WEIGHT quantization** in the convert tooling — PR
268
- #20 (2026-07-07) landed TurboQuant for KV; the rotation-based weight-side
269
- is the noted follow-up (turboquant-kv.md), and it's what the drafter
270
- needs. The drafter is its lowest-risk first customer — one-number gate,
271
- no KL/eval battery. **TQ's HYPOTHESIS here is PRESERVATION AT EQUAL BITS**
272
- (Gaussian-distributed vectors + finer step sizes around the peak, where
273
- affine spends half its levels on tails) — a hypothesis 5b MEASURES, never
274
- a default: TurboQuant earns its place the same way everything in this
275
- repo does.
276
-
277
- - [ ] **5a.** Extend `dspark-quantize-drafter.ts` with the TurboQuant
278
- scheme.
279
- - [ ] **5b. THE HEADLINE: TQ-4bit vs affine-4bit AT EQUAL BPW** through the
280
- Phase-1c harness — same size, whose acceptance is closer to bf16? If
281
- affine-4 bled in 1d, this is the expected fix; if affine-4 held, TQ's
282
- margin becomes headroom for lower rungs. Only AFTER TQ-4 ≥ affine-4:
283
- the lower-bpw ladder (3.5 / 3.0 / 2.5) → acceptance-per-byte curve,
284
- knee adopted (dont-delete-optionality for the rest).
285
- - [ ] **5b″. TQ IS HOW, SENSITIVITY-AWARE IS WHAT (Josh)** — two orthogonal
286
- axes, never mixed: TQ vs affine is a METHOD question (decided by 5b's
287
- equal-bpw measurement — a method that wins at equal bits wins for every
288
- tensor, so there is no reason to mix METHODS within an artifact);
289
- sensitivity is the bit ALLOCATION question (the 1e knapsack, whatever
290
- the method — candidate set {method-2, method-3, method-4, method-8} per
291
- group, measured KL cost each, greedy to target BPW). IF 5b confirms TQ,
292
- the artifact is TQ-uniform at knapsack-allocated bits; if it doesn't,
293
- affine-uniform at knapsack-allocated bits — either way the OUTCOME of
294
- the measurement, not a premise. Nothing here is "on by default";
295
- defaults are Phase 4e/6 decisions made on clean-machine numbers.
296
- - [ ] **5b′. PER-TENSOR MIXED PRECISION rungs** (Josh, 2026-07-07). The
297
- intuition "only 5 layers = few knobs" undercounts: the drafter's mass is
298
- ~10 TENSOR GROUPS, and two of them are 58% of the bytes — `lm_head`
299
- (~2 GB, read FULLY every round: the bandwidth whale) and `embed_tokens`
300
- (~2 GB, gather-only: ~free to read, pure resident-memory win), plus
301
- `markov_w2` (134 MB read ×7/round ≈ 940 MB). Both whales only shape the
302
- DRAFT distribution → acceptance-only risk. Mixed rungs to sweep: 3-bit
303
- lm_head + 3-bit markov_w2 + 4-bit layers; 2-bit embed variants; k_proj
304
- (2 M params) 8-bit for free. The ~10-group space is small enough for a
305
- near-exhaustive sweep through the SAME one-number harness — unlike
306
- sensitivity search on a full model. **Allocation objective (the point):
307
- PRESERVE the bf16 acceptance at the smallest cost, not minimize bytes —
308
- and allocation follows the MEASURED sensitivity table from 1e, never a
309
- prior.** The mixed rungs are built FROM the table: give the measured-
310
- sensitive groups more bits (or TQ them, post-Phase-5), squeeze the
311
- measured-insensitive ones. The "only 5 layers" worry dissolves either
312
- way — the tensor-group space (~10 knobs, two of them 58% of the bytes)
313
- is the real granularity, and 1e prices every knob empirically.
314
- - [ ] **5c.** If TurboQuant wins: fold the recipe into 4b's UX (the
315
- conversion the server offers is the TurboQuant one).
316
-
317
- ## Phase 6 — quotable results + promotion
318
-
319
- - [ ] Clean-machine protocol (reboot + `sudo purge`), then: bench-feature-
320
- matrix conc-1 AND agg×4, serial vs best-spec-config, on 12B (and e4b as
321
- the expected-negative control). Promote to `benchmarks/RESULTS.md`
322
- "composition"; update decode-speed-program.md (lever 1c: measured),
323
- STATUS, and the handoff's FIRST LIVE RUN section with the closing
324
- numbers.
325
- - [ ] Loose ends carried from PR #19, closed or re-deferred with reasons:
326
- the paper-faithful gated RNN head (seqHead:"gru", currently variant-
327
- documented), paper-Alg-1/STS survival-product scheduler (Lab item),
328
- per-slot spec under batching (unified-engine frontier row — NOT this
329
- program).
330
-
331
- ## Dependency graph + who does what
332
-
333
- ```
334
- 0a (oracle gate, Josh: venv+GPU) ──┐
335
- 0b (γ sweep, Josh: GPU) ──────────┼─→ 1a→1b→1c→1d (quant baseline; 1d Josh GPU)
336
- 0c (attribution, Josh: GPU) ───────┘ │
337
- ├─→ 1.5 (OPTIONAL acceptance
338
- │ upside: fine-tune on our
339
- │ target's hiddens + threshold
340
- │ sweep; run if 1's preserved
341
- │ acceptance falls short)
342
- ├─→ 2a-2c (tightening; CPU-gated)
343
- 3a-3b (generator tap; parallel anytime) ────┤
344
- └─→ 4 (UX, needs 0–3 data)
345
- TurboQuant merge ─→ 5a-5c (reuses 1c harness) ─→ 6 (clean machine, Josh)
346
- ```
347
- Priority note: Phase 1's PRESERVATION question ("do we keep 26–33% at
348
- 4-bit?") is the program's hinge — one A/B answers it; if affine-4 bleeds,
349
- the answers are MEASURED (1e sensitivity table → mixed allocation) and
350
- ENGINEERED (Phase 5: TQ-4 at equal bpw — the better quant is the designed
351
- fix, not a fallback).
352
-
353
- Code phases (1a/1b/2/3/4-impl) are agent-runnable sessions; every GPU
354
- measurement is Josh's shell. Nothing except Phase 5 waits on TurboQuant —
355
- Phases 0–4 can land first so TurboQuant drops into a finished harness.
356
-
357
- ## Exit criteria for the whole program
358
-
359
- 1. Spec wall-clock ≥ 1.3× serial on 12B at the recommended config,
360
- clean-machine paired — or a written verdict that it can't be reached and
361
- why (with the config left as a characterized default-off lever).
362
- 2. **Acceptance PRESERVED and understood**: the quantized drafter holds the
363
- bf16 baseline's 26–33% (or the mixed rung that does is adopted, or the
364
- loss is measured and accepted with numbers); the optional 1.5 upside
365
- levers are run-or-explicitly-deferred — the drafter predicts tokens;
366
- small was never the goal.
367
- 3. The acceptance-per-byte curve exists (TurboQuant vs 4-bit vs mixed vs
368
- bf16), with acceptance-at-fixed-budget allocation swept (5b′).
369
- 4. The serving surface is documented, defaults decided per-pair and
370
- recorded, and a fresh `mlx-bun get` → serve → speedup flow works without
371
- reading any design doc.
@@ -1,268 +0,0 @@
1
- # DSpark speculative decoding for mlx-bun
2
-
3
- Implementation of DeepSeek's **DSpark** ("Confidence-Scheduled Speculative
4
- Decoding with Semi-Autoregressive Generation", `DSpark_paper.pdf`) against this
5
- repo's models. DSpark = a **DFlash** parallel backbone (KV-injected, all γ draft
6
- tokens in one pass) **+ a lightweight sequential head** (Markov, Eq 5, or RNN,
7
- Eq 6) that adds intra-block dependency (the *semi-autoregressive* part) **+ a
8
- confidence head → STS calibration → hardware-aware prefix scheduler**. Decode
9
- becomes draft → verify → accept; output is lossless (bit-identical to the target
10
- at any temperature); only decode speed (τ) changes.
11
-
12
- > **DFlash vs DSpark:** DFlash is *only* the parallel backbone (prior work) and
13
- > suffers suffix decay. DSpark adds the sequential head + confidence-scheduled
14
- > verification. The sequential Markov head is what makes this DSpark.
15
-
16
- ## Two implementations (flag-selected, both in `src/spec/dspark/`)
17
-
18
- | | `module.ts` (v1) | `module-dflash.ts` (v2, **the real one**) |
19
- |---|---|---|
20
- | context | **single vector** (final hidden at the anchor) fused as one token | faithful **multi-layer KV injection** (Eq 2–3): H_ctx = RMSNorm(W_c·[H^{l1};…;H^{lm}]) over the FULL context, re-projected into every draft layer's K/V |
21
- | layers | 2 | 5 |
22
- | status | **superseded** — dropped the paper's core idea (kept as baseline) | the actual DSpark model (Markov variant) |
23
-
24
- v1 was a shortcut that removed the load-bearing mechanism; it never tested the
25
- paper. v2 is faithful. Checkpoints stamp `variant` in `dspark.json`; the runtime
26
- loads the matching module. (`variant:"dflash"` should be renamed to `"dspark"` —
27
- see Open items.)
28
-
29
- ## The mechanism (v2, paper Eq 2–3)
30
-
31
- - **Eq 2 (context):** tap the target's hidden states at layers `{l1…lm}` (e4b
32
- default {20,31,41,42}, the last = post-finalNorm), concat on the feature axis,
33
- project to the draft width: `H_ctx ∈ [L_ctx, d]`. Extraction via a parity-safe
34
- `model.hiddenTap` (no-op when off) added to `gemma4.ts` `forwardLayers`.
35
- - **Eq 3 (injection):** every draft layer forms `K_i=[W_i^K H_ctx; W_i^K H_d]`,
36
- `V_i` likewise, `Q_i=W_i^Q H_d`; the γ-block queries attend bidirectionally
37
- over `[context ++ block]`. Context is read-only memory re-projected fresh each
38
- layer. The draft projects the target's HIDDEN STATES with its OWN Wk/Wv (not
39
- the target's K/V — that's the separate `GemmaAssistantDrafter` baseline).
40
- - **Markov head (Eq 5):** `B_k = W1[x_{k-1}]·W2`, r=256, W2=0 init → starts as
41
- pure DFlash, τ climbs as intra-block dependency is learned.
42
- - **Confidence head (Eq 7):** `c_k = σ(wᵀ[h_k; W1[x_{k-1}]])`.
43
- - **Loss (Eq 9–12):** `0.1·CE + 0.9·TV + 1.0·BCE`, position-weighted.
44
- - **Lossless verify** (`generate-dflash.ts`): greedy = longest-prefix match;
45
- temp>0 = `min(1,p/q)` accept + residual `norm(relu(p−q))` resample. Growing
46
- multi-layer H_ctx buffer; rollback via `trim(n, bypass=true)` (physically
47
- slices the rejected tips past the sliding window — see `gemma4-base.ts`).
48
-
49
- ## Results & findings (measured, M1 Max 32GB, e4b OptiQ-4bit)
50
-
51
- **The architecture is CORRECT — proven by an overfit test.** Trained on 3
52
- articles, eval on the same 3: per-position acceptance **~0.75**, τ **3.24** —
53
- squarely paper-range (0.6–0.9 / τ 3–4). So the faithful DFlash, correctly
54
- implemented, reaches the paper's numbers.
55
-
56
- **Getting there required finding a real bug — an off-by-one in the p^t target
57
- alignment** (the TV loss, weight 0.9). Block position k predicts `x_{t+1+k}`,
58
- whose target distribution is `softmax(LM_head(h_{t+k}))`; the data gathered the
59
- hidden at `t+k+1` (shifted forward one). Present in **both v1 and v2** — so every
60
- τ number before the fix was trained against a shifted target. Fixed in
61
- `data-dflash.ts` (`blockIdx = g+k`, k=0..γ-1). Before fix: per-pos ~0.08. After:
62
- ~0.17 generalizing, ~0.75 overfit.
63
-
64
- **Two things stand between "correct architecture" and "net speedup," now
65
- separated:**
66
- 1. **Data.** 160 articles → generalizes only to per-pos ~0.17 (plateaus, doesn't
67
- climb); overfit on 3 proves capacity. The paper uses 1.3M samples × 10 epochs.
68
- → needs real data scale.
69
- 2. **Target speed (the decisive one).** Spec decode amortizes the fixed draft
70
- overhead only when the *target forward* is expensive. Measured decode:
71
- **e4b 45.9 tok/s, 12b 27.5 tok/s, 27B ~15 tok/s.** On fast e4b the draft
72
- overhead dominates → even τ≈3 nets ~0.4–0.5× (SLOWER). On a slow target (27B,
73
- ~67 ms/forward) that overhead is a small fraction → the same τ≈3 could land
74
- ~2–3× (15 → ~35–45 tok/s). **e4b is close to the worst case for spec decode;
75
- the 27B agentic workload is the ideal target and the real motivation.**
76
-
77
- Also confirmed: width is NOT the ceiling (`dDraft=1024` and `2560` both plateau
78
- ~0.17 pre-scale); the parity-safe `hiddenTap` doesn't change target numerics;
79
- long-context spec rollback works via the `trim(n, bypass)` physical-slice.
80
-
81
- ## Serve integration (Phase 1, 2026-07-06)
82
-
83
- DSpark is now serve-loadable behind the same `--draft-model` seam as every
84
- other drafter — one verify/accept executor, no lane routing. The seam
85
- (`src/spec/source.ts`) was extended from its two-model-only shape to carry the
86
- target state KV-borrowing drafters need (it previously could NOT host these,
87
- despite the header claiming so):
88
-
89
- - `DraftProvider.open({sampler, target:{model,caches}})` — the source gets the
90
- target model + its live caches.
91
- - `DraftSource.tapLayers?` — when set (DSpark), the serve loop taps the
92
- target's prefill + every verify forward and hands the captured `[1,L,m*H]`
93
- context to `prefill(ids, ctxML)` / `commit(n, kAccept, vCtxML)` (ownership
94
- transfers). `draft(feed, n, stepBase, anchorHidden?)` — the assistant borrows
95
- the target anchor hidden; DSpark drafts from its growing `H_ctx`.
96
-
97
- Provider selection is by artifact kind (`src/server.ts` `detectDraftKind`):
98
- `dspark.json` → **DflashProvider** (`src/spec/dflash-source.ts`), a `*_assistant`
99
- config → **AssistantProvider** (`src/spec/assistant-source.ts`, the optiq
100
- KV-borrowing Gemma drafter — ships a real ~1.09× γ=1 decode win with no
101
- training), else **TwoModelProvider**. `--draft-kind` overrides. The server pins
102
- `--num-draft-tokens` to the DSpark checkpoint's trained block width
103
- (`cfg.gamma`) so the serve loop never asks for more positions than were trained.
104
-
105
- **Unified-engine alignment (per-slot readiness).** This is the
106
- `DraftSource` seam the unified-engine plan names as the substrate for its
107
- frontier "per-slot drafting behind the `DraftSource` seam" row
108
- ([docs/design/unified-engine-frontier-plan.md](unified-engine-frontier-plan.md)).
109
- Spec still forces the serial lane today (upstream `is_batchable = draft is
110
- None`); Phase 1 did NOT change that — it made the seam *carry per-source target
111
- state* (each source binds its own `TargetView{model,caches}`, anchor hidden,
112
- and tapped H_ctx), which is exactly what a batched executor would need to open
113
- one `DraftSource` per row. So the seam is forward-compatible with per-slot
114
- drafting; the hard part that remains is the executor, not the seam — variable
115
- accept-length per slot breaks a uniform-B step (see
116
- [spec-decode-larger-targets.md](spec-decode-larger-targets.md) caveats), so
117
- per-slot spec is a real batched-scheduler project, not free composition.
118
-
119
- **v1 acceptance caveat:** the serve loop verifies with TOKEN-MATCH acceptance
120
- (mlx-lm/optiq style, lossless at any temperature), NOT the paper's
121
- distribution-level rejection-sampling verify. Greedy is identical; temp>0 is
122
- still lossless but lower-acceptance. The richer rejection-sampling verify stays
123
- in the standalone `generate-dflash.ts` (the measure script). See
124
- [[dspark-seam-kv-borrowing]].
125
-
126
- ## Files
127
- - `src/spec/source.ts` — the extended DraftSource/DraftProvider/TargetView seam.
128
- - `src/spec/assistant-source.ts` / `dflash-source.ts` — the two KV-borrowing providers.
129
- - `src/spec/serve-loop.ts` — the shared verify/accept executor (now tap-aware).
130
- - `src/model/gemma4.ts` — `hiddenTap`/`captureLayer` (parity-safe multi-layer tap).
131
- - `src/model/gemma4-base.ts` — `trim(n, bypass)` on rotating caches (spec rollback past the window).
132
- - `src/spec/dspark/module-dflash.ts` — faithful DFlash+Markov+confidence module.
133
- - `src/spec/dspark/data-dflash.ts` — multi-layer shards, variable-length prefix context, left-pad masking.
134
- - `src/spec/dspark/generate-dflash.ts` — growing-H_ctx lossless decode loop.
135
- - `src/spec/dspark/{loss,sample}.ts` — loss (Eq 9–12) + temp>0 sampling (shared with v1).
136
- - `src/spec/dspark/{module,data,generate}.ts` — v1 single-vector (superseded baseline).
137
- - `scripts/dspark-regen-dflash.ts` / `dspark-train-dflash.ts` (`--resume`) / `dspark-measure-dflash.ts`.
138
- - `scripts/dspark-dflash-smoke.ts` — CPU smoke (16/16). `scripts/dspark-smoke.ts` — v1 smoke (33/33).
139
-
140
- ## Run sequence (faithful DFlash; GPU = Josh runs)
141
- ```
142
- bun scripts/dspark-regen-dflash.ts --topics <topics.txt> --out <data> --max-resp 320
143
- bun scripts/dspark-train-dflash.ts --data <data> --out <ckpt> --iters 8000 --batch 8 [--resume] [--ddraft 2560]
144
- bun scripts/dspark-measure-dflash.ts --drafter <ckpt> --data <prompts.jsonl> # τ + tok/s vs vanilla
145
- ```
146
-
147
- ## Paper components — Phase 2 (2026-07-06): the paper is CODE-COMPLETE
148
-
149
- All remaining components landed the same day (multi-agent build, adversarially
150
- reviewed; smoke 21/21, dspark test files 17/17, real-weights serve gate 3/3):
151
-
152
- - **Alg 1, single-user form — confidence-scheduled draft-length pruning.**
153
- `forwardInfer` drops position k (and truncates the block) when
154
- `c_k < thresholds[k] ?? minConf`; position 0 always survives. Activation is
155
- checkpoint-driven: STS thresholds in `dspark.json` (`cfg.sts`) or the
156
- `MLX_BUN_DSPARK_MINCONF` env override — **uncalibrated checkpoints draft
157
- fixed-γ exactly as before** (zero behavior change). Losslessness invariant:
158
- pruning changes how many positions the target verifies, never what's emitted
159
- (gated: truncation-never-redraw, prefix-identical to the unpruned block).
160
- - **Variable-length draft contract.** `DraftSource.draft()` returns 1..n —
161
- the RETURN LENGTH is authoritative; the serve loop and `dflashGenerate`
162
- verify/trim/re-feed over `d = drafts.length`. Two-model/assistant return
163
- exactly n (unchanged).
164
- - **STS calibration (§3.2.1).** `src/spec/dspark/calibration.ts`
165
- (`fitStsThresholds`: per position, smallest τ whose Laplace-smoothed
166
- `P(accepted | conf ≥ τ)` ≥ target; pos 0 → 0, under-sampled → 0 (don't
167
- prune on thin evidence), unreachable target → 1.0) +
168
- `scripts/dspark-calibrate.ts` (GPU: greedy unpruned rounds via
169
- `dflashGenerate`'s `onRound` hook → fit → patch `config.sts` into
170
- dspark.json in place). ⚠ estimator shape is our reading — paper PDF absent.
171
- - **RNN sequential head (Eq 6 — ⚠ design-doc-faithful shape, paper PDF
172
- absent, flagged in code).** `cfg.seqHead: "markov"|"rnn"`; Elman recurrence
173
- `s_k = tanh(s_{k-1}·wH + E[x_{k-1}] + bH)`, `B_k = s_k·wO`, `wO` zero-init
174
- (starts as pure DFlash, like markov.w2); shares `markov.w1` as the token
175
- embedding (also feeds the confidence head). Same loss, autograd-gated;
176
- init-equivalence gate: rnn ≡ markov token-for-token at init.
177
- Train with `scripts/dspark-train-dflash.ts --seq-head rnn`.
178
- - **Draft loop TIGHTENED** (handoff item 3): greedy tokens chain ON-DEVICE
179
- (one concat + one host read after the loop, was γ syncs); confidence reads
180
- deferred+batched when pruning is inactive (per-position only when Alg 1
181
- needs the answer mid-loop — inherent); `collectLogits: false` on the serve
182
- path skips the per-position draft-logits materialization entirely
183
- (`draftLogits` now optional). Gate: bit-identical to the pre-tightening
184
- loop (pinned reference tokens, tests/dspark-infer-loop.test.ts).
185
- - **Rename + central loader.** Canonical variant is now `"dspark"`
186
- (`save()` stamps it; `load()` accepts legacy `"dflash"`);
187
- `src/spec/dspark/loader.ts` `loadDsparkDrafter()` dispatches by variant and
188
- refuses v1 single-vector checkpoints with a pointer at the v2 trainer. The
189
- serve path and the bench (`bench-feature-matrix.ts` via the server's
190
- exported `detectDraftKind`) both go through it.
191
-
192
- ## DeepSpec ground truth (2026-07-06 audit — paper arXiv:2607.05147 + source)
193
-
194
- DeepSeek open-sourced the reference implementation (**DeepSpec**, MIT,
195
- github.com/deepseek-ai/DeepSpec) + trained drafters incl.
196
- **`deepseek-ai/dspark_gemma4_12b_block7`** (for google/gemma-4-12B-it — our
197
- primary target; 6.86 GB bf16 single safetensors, γ=7). Two audit agents
198
- verified our build against the paper AND the source. Verdicts:
199
-
200
- - **MATCH the paper exactly:** Eq 2-3 (context + KV injection), the
201
- anchor++masks block, Eq 5 Markov (r=256), Eq 7 confidence (we add a
202
- zero-init bias — superset), **Eq 8-12 loss to the letter** (0.1/0.9/1.0,
203
- w_k=exp(−(k−1)/γ), analytic c*). Our defaults = their production config
204
- (γ=5, 5 layers, Markov head).
205
- - **Eq 6 RNN differs:** paper is a gated cell over
206
- `z_k=[s_{k−1}; W₁[x_{k−1}]; h_k]`, fused (2r+d)→3r projection,
207
- `B_k=W₂ᵀtanh(W_o z_k)` (conditioned on the backbone hidden). Ours is
208
- ungated Elman without h_k — kept as variant `"rnn"` (paper calls the gains
209
- "marginal"; production uses Markov); DeepSpec also ships an RNNHead of the
210
- gated form if we ever want the faithful one.
211
- - **§3.2.1 STS + Alg 1: the paper's machinery is NOT in the released code.**
212
- STS = Sequential Temperature Scaling (per-position temperatures by ECE grid
213
- search on cumulative survival products); Alg 1 = expected-throughput
214
- maximization over survival products with a profiled SPS(B) cost table —
215
- both live in their UNRELEASED production serving layer. The released
216
- reference ships **per-position threshold truncation on sigmoid confidence
217
- (default 0 = off), ℓ=0 allowed** — i.e. the released reference is shaped
218
- like OUR scheduler. Our threshold fit (`calibration.ts`) is therefore a
219
- reasonable calibrator for the reference-shaped scheduler, NOT the paper's
220
- STS; renamed framing in code comments. Paper-faithful STS/Alg-1 = a future
221
- Lab item if the survival-product scheduler ever earns a default.
222
- - **The reference drafter is a DIFFERENT module than ours:** a full
223
- Gemma4-shaped 5-layer transformer — hidden 3840, 16 Q heads × head_dim 512,
224
- **1 KV head with K≡V (`attention_k_eq_v`, no v_proj tensor; scale-less
225
- v_norm)**, attention scale 1.0 (QK-norm), RoPE partial_rotary 0.25 θ=1e6,
226
- per-layer learned `layer_scalar`, scaled embed (×√3840, not stored), UNTIED
227
- lm_head, final softcap 30, and an **incremental context-KV cache** (stores
228
- projected target-context K/V; crops the block's noise K/V each round).
229
- Sequential Markov sampling + confidence head (input [h; w1[prev]] = 4096)
230
- as in the paper. Checkpoint: 74 tensors, bf16, **no key prefix**;
231
- config.json `architectures: ["Gemma4DSparkModel"]` (loader detection key).
232
- **12B tap layers: `target_layer_ids [5,17,29,41,46]`** (their layer_id+1
233
- output convention == our tapLayers index; no final-norm sentinel).
234
- - **THE ORACLE:** their verify is leaky rejection sampling that at
235
- temperature 0 **degenerates to exact argmax token-match — RNG-free,
236
- token-for-token deterministic**. Their eval emits per-round
237
- proposal/accepted/next-token traces. Protocol: run their eval at temp 0
238
- (+ a threshold arm) on fixed prompts → JSONL round fixtures → our port
239
- must match round-for-round. Same discipline as the D2 diffusion oracle,
240
- minus RNG parity entirely.
241
-
242
- **Consequence:** DSpark is no longer oracle-less L3. The port of their module
243
- (the `deepspec` variant) + their checkpoint gives a bit-exact-gateable path to
244
- a REAL 12B speedup with zero training. Our own trainable module remains the
245
- research path for custom targets. Training recipe reference: open-perfectblend
246
- regenerated by the target, 10 epochs, batch 512, lr 6e-4, position decay
247
- exp(−pos/4), ~38 TB cached hiddens — i.e. our "thousands of generations" data
248
- estimate was directionally right and their scale is far beyond a laptop run.
249
-
250
- ## Open items / next
251
-
252
- - [x] Serve integration (Phase 1) · [x] Alg-1-shaped scheduler (matches the
253
- RELEASED reference; paper Alg-1 unreleased) · [x] threshold calibration ·
254
- [x] RNN head (Elman variant; paper's gated cell differs — documented above)
255
- · [x] loop tightening · [x] `dspark` rename + loader —
256
- **everything buildable without a GPU is DONE.**
257
- - [ ] **DeepSpec-variant port** (`Gemma4DSparkModel`) + loader detection +
258
- oracle scripts — the no-training path to the 12B speedup (in progress).
259
- - [ ] **Josh-gated GPU (the payoff):** real data scale (thousands of
260
- on-distribution generations) + **retarget to 12B** (`--model` +
261
- `--tap-layers 5,17,29,41,46` (DeepSeek's trained taps); 27B memory-infeasible to train on 24 GB, kept
262
- dim-generic) + train (`--seq-head` A/B optional) + **calibrate**
263
- (`scripts/dspark-calibrate.ts`) + live-τ measure. Recipe:
264
- [docs/investigations/dspark-handoff.md](../investigations/dspark-handoff.md).
265
- - [ ] Verify the Eq 6 / §3.2.1 shapes against the actual paper when the PDF
266
- is available (both flagged in code).
267
-
268
- Full session handoff: `docs/investigations/dspark-handoff.md`.