@mlx-bun/inference 0.0.0-stage → 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 (467) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1475 -2
  3. package/THIRD_PARTY_NOTICES.md +3404 -0
  4. package/dist/native/libmlx_bun_ane.dylib +0 -0
  5. package/dist/native/libmlx_bun_expert_io.dylib +0 -0
  6. package/dist/native/mlx-bun-frame-extract +0 -0
  7. package/examples/fit-model.ts +25 -0
  8. package/examples/qwen3-forward.ts +42 -0
  9. package/examples/qwen3-generate.ts +28 -0
  10. package/examples/trellis-expand.ts +23 -0
  11. package/package.json +129 -4
  12. package/src/adapters/available.ts +110 -0
  13. package/src/adapters/index.ts +3 -0
  14. package/src/adapters/manager.ts +316 -0
  15. package/src/artifacts/auxiliary-files.ts +45 -0
  16. package/src/artifacts/config-dialects.ts +94 -0
  17. package/src/artifacts/config.ts +341 -0
  18. package/src/artifacts/draft-vocabulary.ts +30 -0
  19. package/src/artifacts/expert-offload-build.ts +75 -0
  20. package/src/artifacts/expert-offload.ts +89 -0
  21. package/src/artifacts/experts/index.ts +3 -0
  22. package/src/artifacts/experts/io.ts +386 -0
  23. package/src/artifacts/experts/residency.ts +1134 -0
  24. package/src/artifacts/experts/usage.ts +415 -0
  25. package/src/artifacts/fingerprint.ts +44 -0
  26. package/src/artifacts/glm52/container.ts +305 -0
  27. package/src/artifacts/glm52/expert-layout.ts +249 -0
  28. package/src/artifacts/glm52/index.ts +7 -0
  29. package/src/artifacts/glm52/kernel-layout.ts +124 -0
  30. package/src/artifacts/glm52/layout.ts +152 -0
  31. package/src/artifacts/glm52/memory.ts +500 -0
  32. package/src/artifacts/glm52/resident-weights.ts +135 -0
  33. package/src/artifacts/glm52/weights.ts +503 -0
  34. package/src/artifacts/glm52-config.ts +262 -0
  35. package/src/artifacts/identity.ts +94 -0
  36. package/src/artifacts/index.ts +15 -0
  37. package/src/artifacts/mmap.ts +90 -0
  38. package/src/artifacts/safetensors-writer.ts +249 -0
  39. package/src/artifacts/safetensors.ts +164 -0
  40. package/src/artifacts/turboquant-fold.ts +42 -0
  41. package/src/artifacts/weight-audit.ts +43 -0
  42. package/src/artifacts/weights.ts +255 -0
  43. package/src/contracts/index.ts +2 -0
  44. package/src/contracts/mlx/attention.ts +8 -0
  45. package/src/contracts/mlx/cache.ts +510 -0
  46. package/src/contracts/mlx/checkpoint.ts +10 -0
  47. package/src/contracts/mlx/draft-checkpoint.ts +14 -0
  48. package/src/contracts/mlx/draft-projection.ts +27 -0
  49. package/src/contracts/mlx/draft-target.ts +84 -0
  50. package/src/contracts/mlx/drafter.ts +176 -0
  51. package/src/contracts/mlx/forward-work.ts +23 -0
  52. package/src/contracts/mlx/glm52-weights.ts +25 -0
  53. package/src/contracts/mlx/graph.ts +309 -0
  54. package/src/contracts/mlx/head.ts +6 -0
  55. package/src/contracts/mlx/index.ts +15 -0
  56. package/src/contracts/mlx/kv-codec.ts +9 -0
  57. package/src/contracts/mlx/media.ts +113 -0
  58. package/src/contracts/mlx/positions.ts +16 -0
  59. package/src/contracts/mlx/row-table.ts +2 -0
  60. package/src/contracts/mlx/trainable.ts +103 -0
  61. package/src/contracts/mlx/whisper.ts +96 -0
  62. package/src/contracts/portable/composition.ts +106 -0
  63. package/src/contracts/portable/denoising.ts +17 -0
  64. package/src/contracts/portable/execution.ts +79 -0
  65. package/src/contracts/portable/generation.ts +103 -0
  66. package/src/contracts/portable/graph.ts +80 -0
  67. package/src/contracts/portable/index.ts +15 -0
  68. package/src/contracts/portable/memory-plan.ts +26 -0
  69. package/src/contracts/portable/object-cache.ts +8 -0
  70. package/src/contracts/portable/prefill.ts +63 -0
  71. package/src/contracts/portable/prefix-cache.ts +33 -0
  72. package/src/contracts/portable/prompt.ts +2 -0
  73. package/src/contracts/portable/resources.ts +25 -0
  74. package/src/contracts/portable/rollback.ts +7 -0
  75. package/src/contracts/portable/sampling.ts +44 -0
  76. package/src/contracts/portable/scheduling.ts +54 -0
  77. package/src/contracts/portable/token-delivery.ts +4 -0
  78. package/src/contracts/portable/tsconfig.json +14 -0
  79. package/src/embeddings/index.ts +1 -0
  80. package/src/embeddings/text.ts +85 -0
  81. package/src/execution/admission.ts +59 -0
  82. package/src/execution/batch-group.ts +1240 -0
  83. package/src/execution/batch-types.ts +225 -0
  84. package/src/execution/cancellation.ts +38 -0
  85. package/src/execution/continuation-request.ts +45 -0
  86. package/src/execution/continuation-types.ts +10 -0
  87. package/src/execution/coordinator.ts +70 -0
  88. package/src/execution/denoising-group.ts +180 -0
  89. package/src/execution/engine.ts +56 -0
  90. package/src/execution/fill-group.ts +505 -0
  91. package/src/execution/fit.ts +184 -0
  92. package/src/execution/gateway-binding.ts +178 -0
  93. package/src/execution/grammar-group.ts +224 -0
  94. package/src/execution/index.ts +18 -0
  95. package/src/execution/methods.ts +75 -0
  96. package/src/execution/mixed-iteration.ts +96 -0
  97. package/src/execution/plan.ts +65 -0
  98. package/src/execution/prefill-cohort.ts +100 -0
  99. package/src/execution/prefill-rows.ts +263 -0
  100. package/src/execution/request-policy.ts +19 -0
  101. package/src/execution/row-sampling.ts +49 -0
  102. package/src/execution/scheduler.ts +92 -0
  103. package/src/execution/session.ts +247 -0
  104. package/src/execution/speculative-group.ts +797 -0
  105. package/src/execution/tasks.ts +44 -0
  106. package/src/generation/autoregressive.ts +840 -0
  107. package/src/generation/bindings/autoregressive.ts +104 -0
  108. package/src/generation/bindings/denoising.ts +60 -0
  109. package/src/generation/bindings/prefill-policy.ts +36 -0
  110. package/src/generation/checkpoint-identity.ts +60 -0
  111. package/src/generation/denoising.ts +85 -0
  112. package/src/generation/diffusion.ts +583 -0
  113. package/src/generation/fill/echo-index.ts +188 -0
  114. package/src/generation/fill/index.ts +3 -0
  115. package/src/generation/fill/proposal.ts +69 -0
  116. package/src/generation/fill/schema-rows.ts +506 -0
  117. package/src/generation/fill/session.ts +464 -0
  118. package/src/generation/fill/tool-boundary.ts +103 -0
  119. package/src/generation/fill-append.ts +58 -0
  120. package/src/generation/generate.ts +44 -0
  121. package/src/generation/grammar-step.ts +39 -0
  122. package/src/generation/index.ts +14 -0
  123. package/src/generation/phase-dispatch.ts +115 -0
  124. package/src/generation/prefill.ts +33 -0
  125. package/src/generation/result.ts +49 -0
  126. package/src/generation/scopes.ts +157 -0
  127. package/src/generation/speculative/acceptance.ts +41 -0
  128. package/src/generation/speculative/adaptive-draft-gate.ts +166 -0
  129. package/src/generation/speculative/bindings/assistant-rows.ts +102 -0
  130. package/src/generation/speculative/bindings/autoregressive-rows.ts +124 -0
  131. package/src/generation/speculative/bindings/binding.ts +106 -0
  132. package/src/generation/speculative/bindings/deepspec-rows.ts +33 -0
  133. package/src/generation/speculative/bindings/draft-target.ts +10 -0
  134. package/src/generation/speculative/bindings/glm52-mtp-rows.ts +128 -0
  135. package/src/generation/speculative/bindings/projected-context-rows.ts +78 -0
  136. package/src/generation/speculative/bindings/projected-draft-rows.ts +95 -0
  137. package/src/generation/speculative/bindings/qwen-mtp-rows.ts +336 -0
  138. package/src/generation/speculative/bindings/two-model-rows.ts +63 -0
  139. package/src/generation/speculative/cache-identity.ts +16 -0
  140. package/src/generation/speculative/draft-kind.ts +149 -0
  141. package/src/generation/speculative/draft-policy.ts +41 -0
  142. package/src/generation/speculative/draft-registry.ts +118 -0
  143. package/src/generation/speculative/draft-vocab.ts +110 -0
  144. package/src/generation/speculative/index.ts +17 -0
  145. package/src/generation/speculative/output.ts +49 -0
  146. package/src/generation/speculative/round.ts +307 -0
  147. package/src/generation/speculative/source.ts +144 -0
  148. package/src/generation/speculative/sources/assistant-source.ts +64 -0
  149. package/src/generation/speculative/sources/deepspec-source.ts +70 -0
  150. package/src/generation/speculative/sources/dflash-source.ts +84 -0
  151. package/src/generation/speculative/sources/dflash2-source.ts +86 -0
  152. package/src/generation/speculative/sources/glm52-mtp-source.ts +66 -0
  153. package/src/generation/speculative/sources/ngram-source.ts +165 -0
  154. package/src/generation/speculative/sources/qwen-mtp-source.ts +154 -0
  155. package/src/generation/speculative/sources/two-model.ts +75 -0
  156. package/src/generation/types.ts +194 -0
  157. package/src/index.ts +20 -0
  158. package/src/input/audio/audiotoolbox.ts +112 -0
  159. package/src/input/audio/decode.ts +133 -0
  160. package/src/input/audio/features.ts +202 -0
  161. package/src/input/audio/index.ts +6 -0
  162. package/src/input/audio/transcode.ts +67 -0
  163. package/src/input/audio/whisper-mel.ts +185 -0
  164. package/src/input/audio/whisper-tokenizer.ts +238 -0
  165. package/src/input/chat-template.ts +389 -0
  166. package/src/input/index.ts +6 -0
  167. package/src/input/media-fetch.ts +439 -0
  168. package/src/input/packed-mixed.ts +43 -0
  169. package/src/input/special-tokens.ts +75 -0
  170. package/src/input/token-groups.ts +49 -0
  171. package/src/input/tokenizer.ts +336 -0
  172. package/src/input/tool-call.ts +689 -0
  173. package/src/input/vision/index.ts +3 -0
  174. package/src/input/vision/preprocess.ts +247 -0
  175. package/src/input/vision/prompt.ts +398 -0
  176. package/src/input/vision/qwen3vl-preprocess.ts +409 -0
  177. package/src/input/vision/qwen3vl-prompt.ts +237 -0
  178. package/src/input/vision/video-frames.ts +100 -0
  179. package/src/kernels/ane/fill.ts +101 -0
  180. package/src/kernels/ane/linear.ts +416 -0
  181. package/src/kernels/attention/flash.ts +694 -0
  182. package/src/kernels/attention/kvq4-decode.ts +155 -0
  183. package/src/kernels/attention/masks.ts +40 -0
  184. package/src/kernels/attention/multi-query.ts +193 -0
  185. package/src/kernels/attention/paged.ts +130 -0
  186. package/src/kernels/delta/gated.ts +306 -0
  187. package/src/kernels/delta/index.ts +3 -0
  188. package/src/kernels/delta/silu-rms-heads.ts +69 -0
  189. package/src/kernels/delta/state.ts +74 -0
  190. package/src/kernels/gated-rms-norm.ts +64 -0
  191. package/src/kernels/glm52/layout.ts +37 -0
  192. package/src/kernels/glm52/streamed-experts.ts +360 -0
  193. package/src/kernels/logits.ts +38 -0
  194. package/src/kernels/quantization/affine-row.ts +154 -0
  195. package/src/kernels/quantization/affine-rows.ts +36 -0
  196. package/src/kernels/quantization/affine-split-mma.ts +144 -0
  197. package/src/kernels/quantization/affine3-mma.ts +117 -0
  198. package/src/kernels/quantization/affine3-rows.ts +103 -0
  199. package/src/kernels/quantization/affine4-mma.ts +113 -0
  200. package/src/kernels/quantization/affine4-rows.ts +102 -0
  201. package/src/kernels/residual-rms-norm.ts +65 -0
  202. package/src/kernels/sampling/index.ts +2 -0
  203. package/src/kernels/sampling/normalized-argmax.ts +116 -0
  204. package/src/kernels/sampling/token-bitmask.ts +52 -0
  205. package/src/kernels/softcap.ts +35 -0
  206. package/src/kernels/trellis/codebook.ts +123 -0
  207. package/src/kernels/trellis/down-codebook.ts +184 -0
  208. package/src/kernels/trellis/down-factored.ts +180 -0
  209. package/src/kernels/trellis/down-k3-interleaved-factored.ts +146 -0
  210. package/src/kernels/trellis/down-mma-wide.ts +195 -0
  211. package/src/kernels/trellis/down-mma.ts +145 -0
  212. package/src/kernels/trellis/expand.ts +42 -0
  213. package/src/kernels/trellis/gate-up-codebook-mma.ts +141 -0
  214. package/src/kernels/trellis/gate-up-codebook.ts +137 -0
  215. package/src/kernels/trellis/gate-up-factored.ts +197 -0
  216. package/src/kernels/trellis/gate-up-mma-wide.ts +147 -0
  217. package/src/kernels/trellis/gate-up-mma.ts +148 -0
  218. package/src/kernels/trellis/gate-up.ts +248 -0
  219. package/src/kernels/trellis/geometry.ts +22 -0
  220. package/src/kernels/trellis/index.ts +103 -0
  221. package/src/kernels/trellis/launch.ts +12 -0
  222. package/src/kernels/trellis/mixed-gate-up-factored.ts +119 -0
  223. package/src/kernels/trellis/mixed-gate-up.ts +146 -0
  224. package/src/kernels/trellis/qualified.ts +34 -0
  225. package/src/kernels/trellis/reduce.ts +150 -0
  226. package/src/kernels/trellis/scatter.ts +407 -0
  227. package/src/kernels/trellis/splitk-prefill.ts +152 -0
  228. package/src/kernels/trellis/tiled-prefill.ts +131 -0
  229. package/src/kernels/trellis/vector-expand.ts +58 -0
  230. package/src/kernels/trellis/wide-prefill.ts +89 -0
  231. package/src/kernels/turboquant/decode.ts +82 -0
  232. package/src/kernels/turboquant/index.ts +5 -0
  233. package/src/kernels/turboquant/inverse.ts +122 -0
  234. package/src/kernels/turboquant/ops.ts +860 -0
  235. package/src/kernels/turboquant/signs.ts +130 -0
  236. package/src/kernels/turboquant/tables.ts +124 -0
  237. package/src/layers/affine-verify-linear.ts +75 -0
  238. package/src/layers/ane-prefill-split.ts +283 -0
  239. package/src/layers/compiled-normalization.ts +41 -0
  240. package/src/layers/delta-heads.ts +23 -0
  241. package/src/layers/dense-embedding.ts +29 -0
  242. package/src/layers/dense-linear.ts +32 -0
  243. package/src/layers/dequantized-linear.ts +72 -0
  244. package/src/layers/folded-attention.ts +42 -0
  245. package/src/layers/geglu.ts +130 -0
  246. package/src/layers/helpers.ts +7 -0
  247. package/src/layers/index.ts +36 -0
  248. package/src/layers/kv4-decode-attention.ts +15 -0
  249. package/src/layers/layer-norm.ts +24 -0
  250. package/src/layers/loading.ts +92 -0
  251. package/src/layers/lora.ts +150 -0
  252. package/src/layers/normalization.ts +9 -0
  253. package/src/layers/prefix-layout.ts +33 -0
  254. package/src/layers/quantized-append-attention.ts +32 -0
  255. package/src/layers/quantized-attention.ts +353 -0
  256. package/src/layers/quantized-embedding.ts +39 -0
  257. package/src/layers/quantized-linear.ts +137 -0
  258. package/src/layers/quantized-switch-linear.ts +37 -0
  259. package/src/layers/qwen-append.ts +12 -0
  260. package/src/layers/qwen-mrope.ts +238 -0
  261. package/src/layers/rope-2d.ts +110 -0
  262. package/src/layers/rope.ts +389 -0
  263. package/src/layers/swiglu.ts +23 -0
  264. package/src/layers/trellis-codebook-down.ts +52 -0
  265. package/src/layers/trellis-codebook-gate-up.ts +42 -0
  266. package/src/layers/trellis-down.ts +117 -0
  267. package/src/layers/trellis-gate-up.ts +71 -0
  268. package/src/layers/trellis-linear.ts +211 -0
  269. package/src/layers/trellis-prompt.ts +102 -0
  270. package/src/layers/trellis-reduce-gate-up.ts +73 -0
  271. package/src/layers/trellis-scatter-down.ts +98 -0
  272. package/src/models/ane-install.ts +74 -0
  273. package/src/models/audio/conformer.ts +656 -0
  274. package/src/models/cache-composition.ts +44 -0
  275. package/src/models/capabilities.ts +89 -0
  276. package/src/models/chat-template.ts +10 -0
  277. package/src/models/composition.ts +107 -0
  278. package/src/models/diffusion-gemma/experts.ts +59 -0
  279. package/src/models/diffusion-gemma/family.ts +21 -0
  280. package/src/models/diffusion-gemma/model.ts +900 -0
  281. package/src/models/diffusion-gemma/vision.ts +549 -0
  282. package/src/models/drafter-loaders.ts +49 -0
  283. package/src/models/drafters.ts +39 -0
  284. package/src/models/factory.ts +351 -0
  285. package/src/models/families.ts +70 -0
  286. package/src/models/family.ts +125 -0
  287. package/src/models/gemma4/assistant-target.ts +46 -0
  288. package/src/models/gemma4/assistant.ts +327 -0
  289. package/src/models/gemma4/blocks.ts +755 -0
  290. package/src/models/gemma4/compiled-decode.ts +452 -0
  291. package/src/models/gemma4/family.ts +39 -0
  292. package/src/models/gemma4/gemma4-12b.ts +677 -0
  293. package/src/models/gemma4/gemma4-26b.ts +544 -0
  294. package/src/models/gemma4/gemma4-e4b.ts +599 -0
  295. package/src/models/gemma4/graphs.ts +147 -0
  296. package/src/models/gemma4/media.ts +88 -0
  297. package/src/models/gemma4/model.ts +860 -0
  298. package/src/models/gemma4/serving-blocks.ts +72 -0
  299. package/src/models/gemma4/trainable.ts +186 -0
  300. package/src/models/gemma4/written-blocks.ts +232 -0
  301. package/src/models/gemma4/written-forward.ts +159 -0
  302. package/src/models/gemma4/written-input.ts +29 -0
  303. package/src/models/glm52/atlas.ts +507 -0
  304. package/src/models/glm52/coupling.ts +388 -0
  305. package/src/models/glm52/dsa.ts +601 -0
  306. package/src/models/glm52/family.ts +20 -0
  307. package/src/models/glm52/mla.ts +812 -0
  308. package/src/models/glm52/model.ts +1127 -0
  309. package/src/models/glm52/moe.ts +223 -0
  310. package/src/models/glm52/mtp.ts +60 -0
  311. package/src/models/glm52/pilot.ts +537 -0
  312. package/src/models/glm52/reference.ts +445 -0
  313. package/src/models/glm52/residency.ts +557 -0
  314. package/src/models/glm52/streamed-experts.ts +447 -0
  315. package/src/models/graph.ts +59 -0
  316. package/src/models/implementation.ts +230 -0
  317. package/src/models/index.ts +15 -0
  318. package/src/models/media-input.ts +15 -0
  319. package/src/models/memory-plan.ts +39 -0
  320. package/src/models/minicpm5/family.ts +29 -0
  321. package/src/models/minicpm5/model.ts +394 -0
  322. package/src/models/minicpm5/trainable.ts +90 -0
  323. package/src/models/profile.ts +337 -0
  324. package/src/models/qwen/blocks.ts +658 -0
  325. package/src/models/qwen/checkpoint.ts +190 -0
  326. package/src/models/qwen/families.ts +57 -0
  327. package/src/models/qwen/media-input.ts +161 -0
  328. package/src/models/qwen/mtp.ts +101 -0
  329. package/src/models/qwen/qwen3-moe.ts +355 -0
  330. package/src/models/qwen/qwen3.ts +323 -0
  331. package/src/models/qwen/qwen38-27b-trellis-m1max.ts +1532 -0
  332. package/src/models/qwen/qwen38-27b-trellis-m4pro.ts +1092 -0
  333. package/src/models/qwen/qwen3_5.ts +433 -0
  334. package/src/models/qwen/written-layers.ts +285 -0
  335. package/src/models/row-table.ts +1 -0
  336. package/src/models/runtime.ts +73 -0
  337. package/src/models/speculative/deepspec-artifact.ts +10 -0
  338. package/src/models/speculative/deepspec.ts +744 -0
  339. package/src/models/speculative/dflash.ts +553 -0
  340. package/src/models/speculative/dflash2-artifact.ts +9 -0
  341. package/src/models/speculative/dflash2-operations.ts +1 -0
  342. package/src/models/speculative/dflash2.ts +576 -0
  343. package/src/models/speculative/loader.ts +29 -0
  344. package/src/models/support.ts +79 -0
  345. package/src/models/universal/archs.ts +365 -0
  346. package/src/models/universal/blocks.ts +479 -0
  347. package/src/models/universal/dense.ts +255 -0
  348. package/src/models/universal/family.ts +17 -0
  349. package/src/models/vision/qwen3vl.ts +566 -0
  350. package/src/models/vision/siglip.ts +520 -0
  351. package/src/models/vision/unified.ts +176 -0
  352. package/src/models/whisper/family.ts +19 -0
  353. package/src/models/whisper/fast.ts +734 -0
  354. package/src/models/whisper/model.ts +430 -0
  355. package/src/runtime/compiled-trace.ts +16 -0
  356. package/src/runtime/config.ts +77 -0
  357. package/src/runtime/expert-trace.ts +71 -0
  358. package/src/runtime/graph-forward.ts +65 -0
  359. package/src/runtime/integers.ts +6 -0
  360. package/src/runtime/native.ts +16 -0
  361. package/src/runtime/resources.ts +53 -0
  362. package/src/runtime/row-operations.ts +42 -0
  363. package/src/runtime/trace.ts +161 -0
  364. package/src/sampling/curve.ts +122 -0
  365. package/src/sampling/draft.ts +55 -0
  366. package/src/sampling/extras.ts +45 -0
  367. package/src/sampling/filters.ts +134 -0
  368. package/src/sampling/grammar.ts +630 -0
  369. package/src/sampling/hlg.ts +290 -0
  370. package/src/sampling/index.ts +9 -0
  371. package/src/sampling/processors.ts +142 -0
  372. package/src/sampling/sampler.ts +120 -0
  373. package/src/sampling/step.ts +343 -0
  374. package/src/sampling/types.ts +161 -0
  375. package/src/sampling/window-filters.ts +46 -0
  376. package/src/scoring/decisions.ts +96 -0
  377. package/src/scoring/full-sequence.ts +103 -0
  378. package/src/scoring/index.ts +9 -0
  379. package/src/scoring/kl.ts +29 -0
  380. package/src/scoring/perplexity.ts +165 -0
  381. package/src/scoring/response-logps.ts +65 -0
  382. package/src/state/affine-attention.ts +180 -0
  383. package/src/state/attachment.ts +68 -0
  384. package/src/state/attention-read.ts +215 -0
  385. package/src/state/batched-kv.ts +294 -0
  386. package/src/state/batched-mask.ts +445 -0
  387. package/src/state/batched-quant.ts +389 -0
  388. package/src/state/batched-quantized-kv.ts +209 -0
  389. package/src/state/batched-rotating-quant.ts +457 -0
  390. package/src/state/batched-rotating-state.ts +149 -0
  391. package/src/state/batched-rotating.ts +430 -0
  392. package/src/state/batched-row-storage.ts +179 -0
  393. package/src/state/batched-ssm.ts +54 -0
  394. package/src/state/batched-turboquant-kv.ts +144 -0
  395. package/src/state/bf16-first-kv.ts +663 -0
  396. package/src/state/cache-service.ts +592 -0
  397. package/src/state/capabilities.ts +65 -0
  398. package/src/state/checkpoint.ts +46 -0
  399. package/src/state/continuation-persistence.ts +126 -0
  400. package/src/state/decode-step-inputs.ts +31 -0
  401. package/src/state/decoded-kv-donor.ts +12 -0
  402. package/src/state/delayed-quantized-kv.ts +141 -0
  403. package/src/state/delayed-rotating-quantized-kv.ts +178 -0
  404. package/src/state/delayed-turboquant-kv.ts +123 -0
  405. package/src/state/durability.ts +214 -0
  406. package/src/state/encoder-cache.ts +26 -0
  407. package/src/state/full-kv-row-append.ts +33 -0
  408. package/src/state/full-kv-row-donor.ts +54 -0
  409. package/src/state/full-prefill-padding.ts +56 -0
  410. package/src/state/full-prefill-row.ts +112 -0
  411. package/src/state/full-transitioning-kv-rows.ts +70 -0
  412. package/src/state/glm52-cache.ts +783 -0
  413. package/src/state/grouped-heads-kv4-cache.ts +26 -0
  414. package/src/state/index.ts +38 -0
  415. package/src/state/kv-attention-view.ts +77 -0
  416. package/src/state/kv-budget.ts +14 -0
  417. package/src/state/kv-scheme.ts +315 -0
  418. package/src/state/kv-storage.ts +57 -0
  419. package/src/state/kv-tensor-rows.ts +212 -0
  420. package/src/state/kv.ts +324 -0
  421. package/src/state/kv4-head256-cache.ts +46 -0
  422. package/src/state/latent-legos.ts +895 -0
  423. package/src/state/layout.ts +277 -0
  424. package/src/state/leases.ts +26 -0
  425. package/src/state/paged/cache.ts +689 -0
  426. package/src/state/paged/codec.ts +36 -0
  427. package/src/state/paged/rows.ts +223 -0
  428. package/src/state/persistence-types.ts +173 -0
  429. package/src/state/persistence-worker.ts +83 -0
  430. package/src/state/persistence.ts +1036 -0
  431. package/src/state/persistence.worker.d.ts +3 -0
  432. package/src/state/persistence.worker.js +264 -0
  433. package/src/state/prefix-cache.ts +685 -0
  434. package/src/state/quantized-kv.ts +369 -0
  435. package/src/state/quantized-tensor.ts +26 -0
  436. package/src/state/request-policy.ts +48 -0
  437. package/src/state/retention-policy.ts +37 -0
  438. package/src/state/rollback.ts +131 -0
  439. package/src/state/rotating-kv-donor.ts +35 -0
  440. package/src/state/rotating-kv-layout.ts +341 -0
  441. package/src/state/rotating-kv.ts +529 -0
  442. package/src/state/rotating-quantized-kv.ts +616 -0
  443. package/src/state/rotating-row-transaction.ts +35 -0
  444. package/src/state/rows.ts +104 -0
  445. package/src/state/softcap-attention.ts +118 -0
  446. package/src/state/speculative/glm52-mtp-state.ts +38 -0
  447. package/src/state/speculative/qwen-mtp-state.ts +34 -0
  448. package/src/state/speculative-rotating-kv.ts +113 -0
  449. package/src/state/ssd-cache.ts +434 -0
  450. package/src/state/ssm-prefill-padding.ts +39 -0
  451. package/src/state/ssm.ts +422 -0
  452. package/src/state/target-layout.ts +7 -0
  453. package/src/state/tiered-prefix-cache.ts +45 -0
  454. package/src/state/training-cache.ts +300 -0
  455. package/src/state/transitioning-kv-rows.ts +267 -0
  456. package/src/state/turboquant-attention.ts +97 -0
  457. package/src/state/turboquant-codec.ts +90 -0
  458. package/src/state/turboquant-kv.ts +442 -0
  459. package/src/state/views.ts +26 -0
  460. package/src/transcription/index.ts +3 -0
  461. package/src/transcription/silero-vad.ts +379 -0
  462. package/src/transcription/whisper/decode.ts +773 -0
  463. package/src/transcription/whisper/format.ts +74 -0
  464. package/src/transcription/whisper/index.ts +4 -0
  465. package/src/transcription/whisper/timing.ts +274 -0
  466. package/src/transcription/whisper/transcribe.ts +394 -0
  467. package/src/transcription/whisper/types.ts +22 -0
@@ -0,0 +1,144 @@
1
+ // The draft contract: a provider owns the draft machinery for the server's
2
+ // lifetime and opens row groups that the speculative group (the one served
3
+ // lane, `execution/speculative-group.ts`) drafts, verifies and commits through.
4
+ // A single request is a group of one row. Every drafter shares that one
5
+ // verify/accept executor (designed in `02d723a:docs/design/speculative-decoding.md`
6
+ // §1); the providers differ only in what fills the draft:
7
+ // - TwoModelProvider — mlx-lm parity (L1 oracle: mlx_lm.server --draft-model),
8
+ // a full second model; reads no target port.
9
+ // - AssistantProvider — the optiq KV-borrowing Gemma drafter
10
+ // (models/gemma4/assistant.ts; L2 oracle: optiq spec_generate): reads the
11
+ // target's donor K/V and the true hidden at each row's anchor.
12
+ // - DflashProvider, Dflash2Provider, DeepspecProvider — block drafters over
13
+ // the target's tapped hidden layers, projected once into context rows.
14
+ // - QwenMtpProvider, Glm52NativeMtpProvider — multi-token-prediction heads.
15
+ // - NgramProvider — model-free prompt lookup.
16
+ // KV-borrowing providers read target state through the `target` view their
17
+ // rows open with (see [[dspark-seam-kv-borrowing]]).
18
+
19
+ import type { MlxArray } from "@mlx-bun/mlx/array";
20
+ import type { PreparedStateChange } from "../../contracts/portable/resources";
21
+ import type { MlxDraftRows } from "./round";
22
+
23
+ export { targetLacks, type AssistantRowsTarget, type HiddenLayerTapsTarget, type RecurrentMtpTarget, type TargetPort, type TargetView } from "../../contracts/mlx/draft-target";
24
+ import type { TargetView } from "../../contracts/mlx/draft-target";
25
+
26
+ /** How a draft group's rows choose their tokens: each row's draw, and the
27
+ * selection the group resolved when it bound its requests. A drafter that
28
+ * selects over its target's head binds one selection operation from
29
+ * `selection` when its rows open; its draft loop calls that operation. */
30
+ export interface DraftRowSampling {
31
+ /** Borrow [B,V] log-probabilities; return owned [B] IDs on device: each row's
32
+ * own draw (argmax under the greedy draft policy). */
33
+ sample(logprobs: MlxArray, steps: readonly number[]): MlxArray;
34
+ readonly selection: DraftSelection;
35
+ }
36
+
37
+ /** The selection every row of one draft group shares, resolved once per request
38
+ * from its sampling and the vocabulary its drafter declares.
39
+ * - `sampled`: each row's `sample` over the full head's log-probabilities.
40
+ * - `greedy`: every row drafts by argmax (the composition's `greedyDraft`), so a
41
+ * drafter may select with the fused normalized argmax over the full head's
42
+ * logits instead of calling `sample`; the selected IDs are identical.
43
+ * - `listed`: the frequency-ranked draft vocabulary its drafter declared
44
+ * (ascending token ids) and each row's coupled draw over logits [B, N]
45
+ * restricted to them, returning full-vocabulary ids [B]. Bound only for
46
+ * requests whose draft sampler reproduces on the subset. */
47
+ export type DraftSelection =
48
+ | { readonly kind: "sampled" }
49
+ | { readonly kind: "greedy" }
50
+ | { readonly kind: "listed"; readonly ids: readonly number[];
51
+ sample(logits: MlxArray, head: import("./draft-vocab").DraftVocabularyHead, steps: readonly number[]): MlxArray };
52
+
53
+ /** Request-owned constraints can propose known continuations without changing
54
+ * their committed state. The target verifier still decides every output. */
55
+ export interface DraftRowConstraints {
56
+ propose(row: number, maxTokens: number): Promise<number[]>;
57
+ }
58
+
59
+ /** Method-owned state membership, independent of scheduling and cache tiers.
60
+ * Open/append borrow checkpoints; capture returns owned immutable state.
61
+ * Membership changes and capture occur only between committed rounds.
62
+ * The caller retains the provider's residency lease for the group's lifetime. */
63
+ export interface DraftRowGroup extends MlxDraftRows {
64
+ /** Consume externally chosen target inputs at a committed round boundary.
65
+ * Context and tokens are borrowed rectangular windows; lengths retain each
66
+ * row's consumed prefix, excluding right padding and the pending output. */
67
+ consume?(tokens: MlxArray, context: MlxArray, lengths: readonly number[]): void | Promise<void>;
68
+ /** Optional: the proposals `draftDevice` would make from `pending` [B, depth], owned and left on the device,
69
+ * without changing the rows' state (a recurrent head drafts under a round of its own state that it rolls back), so
70
+ * a method can compare them with the target's own next samples instead of verifying them. A drafter may propose
71
+ * fewer positions than `depth` (the first ones): a recurrent head proposes one. */
72
+ preview?(pending: readonly number[], depth: number, steps: readonly number[]): MlxArray | null;
73
+ readonly namespace: string;
74
+ readonly tapLayers: readonly number[];
75
+ readonly rowCount: number;
76
+ append(checkpoints: readonly DraftRowCheckpoint[]): void;
77
+ prepareAppend(checkpoints: readonly DraftRowCheckpoint[]): PreparedStateChange;
78
+ filterRows(keep: readonly number[]): void;
79
+ capture(row: number): DraftRowCheckpoint;
80
+ dispose(): void;
81
+ }
82
+
83
+ /** Draft preparation consumes each target chunk at the same batch geometry.
84
+ * Inputs are borrowed and contain only new tokens/context, with equal chunk
85
+ * lengths across rows. A null checkpoint appends a cold request. The provider
86
+ * owns alignment and retained hidden state; scheduling and persistence do not.
87
+ * Membership and capture occur between prefill calls. Capture returns owned
88
+ * state after at least one target token has been consumed for that row. */
89
+ export interface DraftPrefillGroup {
90
+ readonly namespace: string;
91
+ /** Target prefill shape required by this provider's oracle. Most mlx-lm
92
+ * providers leave the final prompt token pending (`tail-split`); the MTP
93
+ * heads start from a full-prompt target forward. */
94
+ readonly prefillMode: "tail-split" | "full";
95
+ readonly tapLayers: readonly number[];
96
+ readonly rowCount: number;
97
+ append(checkpoints: readonly (DraftRowCheckpoint | null)[]): void;
98
+ prepareAppend(checkpoints: readonly (DraftRowCheckpoint | null)[]): PreparedStateChange;
99
+ prefill(tokens: MlxArray, context?: MlxArray): void | Promise<void>;
100
+ /** Resolve borrowed backing before its external restore lease is released. */
101
+ materialize(): void;
102
+ filterRows(keep: readonly number[]): void;
103
+ capture(row: number): DraftRowCheckpoint;
104
+ dispose(): void;
105
+ }
106
+
107
+ export interface GroupedDraftProvider {
108
+ readonly supportsExternalTokens?: boolean;
109
+ /** The frequency-ranked draft vocabulary (ascending token ids) this provider's
110
+ * rows can select over for this target, or null. The binding resolves it once
111
+ * for the bound target; a request whose draft sampler reproduces on it drafts
112
+ * over it (`DraftSelection` `listed`). Absent: none. */
113
+ draftVocabulary?(target: TargetView): readonly number[] | null;
114
+ /** Resolve persistence identity without allocating a draft row. */
115
+ checkpointNamespace?(): string;
116
+ /** Draft state remains valid when target forwards run under a mounted
117
+ * adapter context. Unqualified learned draft graphs leave this absent. */
118
+ readonly supportsTargetAdapters?: boolean;
119
+ /** Target hidden layers every row of this provider taps for this target, in
120
+ * capture order. A provider whose rows tap must implement it; rows opened for
121
+ * the target tap exactly this list. The binding resolves it once and admits the
122
+ * provider only when the target forward can capture these layers. Absent: no taps. */
123
+ targetTapLayers?(target: TargetView): readonly number[];
124
+ openPrefill(options: { target: TargetView;
125
+ checkpoints: readonly (DraftRowCheckpoint | null)[] }): DraftPrefillGroup;
126
+ open(options: { target: TargetView; sampling: DraftRowSampling; constraints?: DraftRowConstraints;
127
+ checkpoints: readonly DraftRowCheckpoint[] }): DraftRowGroup;
128
+ }
129
+
130
+ /** Server-lifetime owner of the draft machinery (the loaded draft model). Its
131
+ * grouped rows are how every request drafts, one request or several. */
132
+ export interface DraftProvider {
133
+ /** Human-readable id (registry id / path tail) for logs + cache namespacing. */
134
+ readonly id: string;
135
+ readonly weightsBytes: number;
136
+ readonly grouped: GroupedDraftProvider;
137
+ dispose(): void;
138
+ }
139
+
140
+ import { DraftRowCheckpoint } from "../../contracts/mlx/draft-checkpoint";
141
+ export { type DraftRowCheckpoint } from "../../contracts/mlx/draft-checkpoint";
142
+ export { type DraftProjection } from "../../contracts/mlx/draft-projection";
143
+
144
+ import { DraftProjection } from "../../contracts/mlx/draft-projection";
@@ -0,0 +1,64 @@
1
+ import { artifactIdentity } from "../../../artifacts/identity";
2
+ import { assistantGroups } from "../bindings/assistant-rows";
3
+ // AssistantProvider — the optiq KV-borrowing Gemma "-assistant" drafter
4
+ // (packages/inference/src/models/gemma4/assistant.ts) behind the grouped draft
5
+ // rows. L2 oracle: optiq spec_generate. Its rows plug into the shared
6
+ // speculative group, so they compose with grammar, logits processors,
7
+ // admission accounting, and stats like any other provider's.
8
+ //
9
+ // KV-borrowing (why the rows read a TargetView): the drafter has NO cache of
10
+ // its own — each draft step reads the target's donor K/V (last sliding + last
11
+ // full layer, in chronological order) and, for the block's first step, the
12
+ // target's hidden at each row's anchor position, which the rows keep from the
13
+ // target's prefill and verify windows. See [[dspark-seam-kv-borrowing]].
14
+ //
15
+ // Drafting is GREEDY (the drafter's own argmax head), independent of the
16
+ // request sampler — drafts are only proposals; the target's verify (which does
17
+ // honor the sampler) decides every emitted token, so correctness holds at any
18
+ // temperature and only the acceptance RATE moves.
19
+
20
+ import { readdirSync, statSync } from "node:fs";
21
+ import { join } from "node:path";
22
+ import type { AssistantDrafterModel } from "../../../contracts/mlx/drafter";
23
+ import { DRAFT_CHECKPOINT_SCHEMA } from "../../../contracts/mlx/draft-checkpoint";
24
+ import { loadAssistantDrafter } from "../../../models/drafter-loaders";
25
+ import type { DraftProvider } from "../source";
26
+
27
+ /** Sum of the drafter's on-disk safetensors — admission accounting only. */
28
+ function safetensorsBytes(dir: string): number {
29
+ let total = 0;
30
+ for (const f of readdirSync(dir))
31
+ if (f.endsWith(".safetensors")) total += statSync(join(dir, f)).size;
32
+ return total;
33
+ }
34
+
35
+ export class AssistantProvider implements DraftProvider {
36
+ readonly id: string;
37
+ readonly weightsBytes: number;
38
+ readonly grouped: import("../source").GroupedDraftProvider;
39
+
40
+ private constructor(
41
+ private readonly drafter: AssistantDrafterModel,
42
+ id: string,
43
+ weightsBytes: number, namespace: string,
44
+ ) {
45
+ this.id = id;
46
+ this.weightsBytes = weightsBytes;
47
+ this.grouped = assistantGroups(drafter,namespace);
48
+ }
49
+
50
+ static async load(modelDir: string): Promise<AssistantProvider> {
51
+ const drafter = await loadAssistantDrafter(modelDir);
52
+ const id = modelDir.split("/").filter(Boolean).at(-1)!;
53
+ try {
54
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
55
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
56
+ .map(name => ({ name, path: join(modelDir, name) })));
57
+ return new AssistantProvider(drafter, id, safetensorsBytes(modelDir), `${DRAFT_CHECKPOINT_SCHEMA.assistant}:${identity}`);
58
+ } catch (error) { drafter.dispose(); throw error; }
59
+ }
60
+
61
+ dispose(): void {
62
+ this.drafter.dispose();
63
+ }
64
+ }
@@ -0,0 +1,70 @@
1
+ // DeepspecProvider — DeepSeek's released DSpark drafter checkpoints
2
+ // (Gemma4DSparkModel, e.g. deepseek-ai/dspark_gemma4_12b_block7) behind the
3
+ // grouped draft rows. The reference implementation is DeepSpec
4
+ // (github.com/deepseek-ai/DeepSpec, MIT); the module port with transcription
5
+ // notes lives in packages/inference/src/models/speculative/deepspec.ts. Oracle: DeepSpec's eval
6
+ // at temperature 0 (RNG-free — verify degenerates to argmax token-match),
7
+ // `02d723a:scripts/oracle/oracle-dspark-deepspec.py` → dspark-deepspec-compare.ts (deleted 2026-08-23; git history).
8
+ //
9
+ // Row mapping (why this fits the shared speculative group): the reference
10
+ // recycles target hidden states from each verify pass into the drafter's
11
+ // growing context — exactly the tapped context the rows consume:
12
+ // prefill → project the prompt's tapped hiddens into the
13
+ // per-layer context K/V rows (their DynamicCache
14
+ // of PROJECTED context rows, positions 0..Lp-1);
15
+ // draft → one block forward per row against its rows
16
+ // (anchor = the row's pending token at its
17
+ // context length); confidence truncation may
18
+ // return 0..depth tokens (ℓ=0 = plain step);
19
+ // commit → project + append ONLY the accepted rows
20
+ // [anchor + accepted drafts] (their crop()
21
+ // semantics: rejected rows never enter the
22
+ // context).
23
+ // Context rows are cached post-norm-post-rope — bit-equivalent to their
24
+ // in-round concat (per-row RMSNorm/RoPE; argued in projectContextKVRows's doc).
25
+
26
+ import { artifactIdentity } from "../../../artifacts/identity";
27
+ import { deepspecGroups } from "../bindings/deepspec-rows";
28
+ import { readdirSync, statSync } from "node:fs";
29
+ import { join } from "node:path";
30
+ import type { DeepspecDrafterModel } from "../../../contracts/mlx/drafter";
31
+ import { loadDeepspecDrafter } from "../../../models/drafter-loaders";
32
+ import type { DraftProvider } from "../source";
33
+
34
+ function safetensorsBytes(dir: string): number {
35
+ let total = 0;
36
+ for (const f of readdirSync(dir))
37
+ if (f.endsWith(".safetensors")) total += statSync(join(dir, f)).size;
38
+ return total;
39
+ }
40
+
41
+ export class DeepspecProvider implements DraftProvider {
42
+ readonly id: string;
43
+ readonly weightsBytes: number;
44
+ readonly grouped: import("../source").GroupedDraftProvider;
45
+ /** Trained block width (config block_size, e.g. 7) — the server pins
46
+ * numDraftTokens to this. */
47
+ readonly gamma: number;
48
+
49
+ private constructor(private readonly drafter: DeepspecDrafterModel, id: string, weightsBytes: number, namespace: string) {
50
+ this.id = id;
51
+ this.weightsBytes = weightsBytes;
52
+ this.gamma = drafter.gamma;
53
+ this.grouped = deepspecGroups(drafter, namespace);
54
+ }
55
+
56
+ static async load(modelDir: string): Promise<DeepspecProvider> {
57
+ const drafter = await loadDeepspecDrafter(modelDir);
58
+ const id = modelDir.split("/").filter(Boolean).at(-1)!;
59
+ try {
60
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
61
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
62
+ .map(name => ({ name, path: join(modelDir, name) })));
63
+ return new DeepspecProvider(drafter, id, safetensorsBytes(modelDir), `deepspec-context-v1:${identity}`);
64
+ } catch (error) { drafter.dispose(); throw error; }
65
+ }
66
+
67
+ dispose(): void {
68
+ this.drafter.dispose(); // owned MlxArrays (transpose views + mmap'd weights)
69
+ }
70
+ }
@@ -0,0 +1,84 @@
1
+ // DflashProvider — DSpark (faithful DFlash + Markov + confidence,
2
+ // packages/inference/src/models/speculative/dflash.ts) behind the grouped draft
3
+ // rows. L3 (KL/quality-gated). Its rows plug into the shared speculative group.
4
+ //
5
+ // H_ctx (why the rows tap): DSpark drafts by attending to a GROWING
6
+ // multi-layer context — the target's tapped hiddens over the accepted stream
7
+ // (paper Eq 2-3). The provider declares its tap layers, so the group taps the
8
+ // target's prefill (→ seeds each row's context) and every verify forward (→
9
+ // grown at commit by the accepted window; rejected tips are never appended,
10
+ // mirroring the target-cache trim). See [[dspark-seam-kv-borrowing]].
11
+ //
12
+ // v1 acceptance: the group verifies with TOKEN-MATCH acceptance
13
+ // (mlx-lm/optiq style — lossless at any temperature), NOT the paper's
14
+ // distribution-level rejection-sampling verify. Greedy is identical; temp>0 is
15
+ // still lossless but lower-acceptance. Drafting here is greedy (proposals; the
16
+ // target verify decides). Confidence-scheduled pruning (Alg 1) may return fewer
17
+ // than the requested tokens: active when the checkpoint carries STS thresholds
18
+ // (cfg.sts, §3.2.1) or via the MLX_BUN_DSPARK_MINCONF override; uncalibrated
19
+ // checkpoints draft fixed-length.
20
+
21
+ import { artifactIdentity } from "../../../artifacts/identity";
22
+ import { projectedDraftGroups } from "../bindings/projected-draft-rows";
23
+ import { readdirSync, statSync } from "node:fs";
24
+ import { join } from "node:path";
25
+ import type { DsparkDrafterModel } from "../../../contracts/mlx/drafter";
26
+ import { loadDsparkDrafter } from "../../../models/drafter-loaders";
27
+ import type { DraftProvider } from "../source";
28
+ import { targetLacks } from "../source";
29
+ import { runtimeValue } from "../../../runtime/config";
30
+
31
+ function safetensorsBytes(dir: string): number {
32
+ let total = 0;
33
+ for (const f of readdirSync(dir))
34
+ if (f.endsWith(".safetensors")) total += statSync(join(dir, f)).size;
35
+ return total;
36
+ }
37
+
38
+ export class DflashProvider implements DraftProvider {
39
+ readonly id: string;
40
+ readonly weightsBytes: number;
41
+ readonly grouped: import("../source").GroupedDraftProvider;
42
+ /** The trained block width — the server pins numDraftTokens to this so the
43
+ * group never asks for more positions than the block was trained for. */
44
+ readonly gamma: number;
45
+
46
+ private constructor(private readonly drafter: DsparkDrafterModel, id: string, weightsBytes: number, namespace: string) {
47
+ this.id = id;
48
+ this.weightsBytes = weightsBytes;
49
+ this.gamma = drafter.cfg.gamma;
50
+ this.grouped = projectedDraftGroups(namespace, drafter.cfg.tapLayers, target => {
51
+ if (!target.hiddenLayerTaps) throw targetLacks("hiddenLayerTaps");
52
+ const projection = target.hiddenLayerTaps.projection;
53
+ const minConf = runtimeValue("MLX_BUN_DSPARK_MINCONF");
54
+ return {
55
+ namespace, schema: "dflash-context-v1",
56
+ layers: drafter.cfg.nLayers,
57
+ project: hidden => drafter.projectContextRows(hidden),
58
+ draft(context, pending, _positions, depth) {
59
+ return drafter.forwardRows(projection, null, pending, depth, {
60
+ collectLogits: false, collectConfidence: false,
61
+ thresholds: drafter.cfg.sts?.thresholds,
62
+ ...(minConf ? { minConf: Number(minConf) } : {}),
63
+ }, context).tokens;
64
+ },
65
+ };
66
+ });
67
+ }
68
+
69
+ static async load(modelDir: string): Promise<DflashProvider> {
70
+ const drafter = await loadDsparkDrafter(modelDir); // variant dispatch (dspark|legacy dflash)
71
+ const id = modelDir.split("/").filter(Boolean).at(-1)!;
72
+ try {
73
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/dspark.json`).text(),
74
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
75
+ .map(name => ({ name, path: join(modelDir, name) })));
76
+ return new DflashProvider(drafter, id, safetensorsBytes(modelDir), `dflash-context-v1:${identity}`);
77
+ } catch (error) { drafter.dispose(); throw error; }
78
+ }
79
+
80
+ dispose(): void {
81
+ // Provider-owned weights are released when the mounted draft is closed.
82
+ this.drafter.dispose();
83
+ }
84
+ }
@@ -0,0 +1,86 @@
1
+ import { rowOperationFor } from "../../../models/graph";
2
+ // Dflash2Provider — the DFlash 2 block drafter (models/speculative/dflash2.ts)
3
+ // behind the grouped draft seam. Context rows are the target's tapped layer
4
+ // outputs over the accepted stream (prefill seeds them; each commit appends
5
+ // the anchor plus accepted rows), projected once into per-layer K/V.
6
+ // Drafting is greedy; the shared verify decides acceptance.
7
+ //
8
+ // The drafter loads in the basis it was trained on, its projections quantized
9
+ // to the width its composer passes (the draft registry passes 4: 1.0 GB
10
+ // resident instead of the 3.85 GB BF16 checkpoint). A target whose residual
11
+ // stream carries a TurboQuant R1 fold declares it on its draft target
12
+ // (`residualBasis`), and one whose composition measured them the kernels of
13
+ // those projections (`draftProjections`); binding a draft group applies both
14
+ // before the first draft.
15
+
16
+ import { artifactIdentity } from "../../../artifacts/identity";
17
+ import { projectedDraftGroups, type ProjectedDraftMethod } from "../bindings/projected-draft-rows";
18
+
19
+ import { readdirSync, statSync } from "node:fs";
20
+ import { join } from "node:path";
21
+ import type { DraftProvider, GroupedDraftProvider } from "../source";
22
+ import { targetLacks } from "../source";
23
+ import type { Dflash2DrafterModel } from "../../../contracts/mlx/drafter";
24
+ import { loadDflash2Drafter } from "../../../models/drafter-loaders";
25
+
26
+ export class Dflash2Provider implements DraftProvider {
27
+ readonly id: string;
28
+ readonly weightsBytes: number;
29
+ readonly grouped: GroupedDraftProvider;
30
+ readonly gamma: number;
31
+
32
+ private constructor(private readonly drafter: Dflash2DrafterModel, id: string, weightsBytes: number, namespace: string) {
33
+ this.id = id;
34
+ this.weightsBytes = weightsBytes;
35
+ this.gamma = drafter.gamma;
36
+ this.grouped = projectedDraftGroups(namespace, drafter.tapLayers, target => {
37
+ if (!target.hiddenLayerTaps) throw targetLacks("hiddenLayerTaps");
38
+ const layers = drafter.cfg.numTargetLayers;
39
+ if (target.hiddenLayerTaps.layerCount !== layers) throw new Error(
40
+ `DFlash 2 drafter was trained for a ${layers}-layer target; this model has ` +
41
+ `${target.hiddenLayerTaps.layerCount} layers — wrong (target, drafter) pairing`);
42
+ drafter.bindTarget(target.residualBasis ?? null, target.draftProjections ?? null);
43
+ const projection = target.hiddenLayerTaps.projection;
44
+ // The block for the rows drafted this round: anchors × columns rows index the drafter's draft table.
45
+ const draftDevice: NonNullable<ProjectedDraftMethod["draftDevice"]> = (context, pending, positions, depth) => {
46
+ const columns = drafter.blockColumns(depth);
47
+ return rowOperationFor(drafter.draft,(pending.length * columns))(context, projection, pending, positions, columns);
48
+ };
49
+ return {
50
+ namespace, schema: "dflash2-context-v1", layers: drafter.cfg.layers,
51
+ // The B × L context rows a prefill or a commit appends index the drafter's context tables.
52
+ project(hidden, positions) {
53
+ const width = (hidden.shape[0]! * hidden.shape[1]!);
54
+ using context = rowOperationFor(drafter.projectContext,width)(hidden);
55
+ return rowOperationFor(drafter.projectContextKVRows,width)(context, positions);
56
+ },
57
+ draft(context, pending, positions, depth) {
58
+ const steps = drafter.blockColumns(depth) - 1;
59
+ if (!steps) return pending.map(() => []);
60
+ using tokens = draftDevice(context, pending, positions, depth);
61
+ const flat = tokens.toIntTokens();
62
+ return pending.map((_, row) => flat.slice(row * steps, (row + 1) * steps));
63
+ },
64
+ draftDevice,
65
+ };
66
+ });
67
+ }
68
+
69
+ /** `bits`: the drafter's projection width (0 keeps BF16). Persisted context is
70
+ * keyed by the drafter and that width; the target's own identity scopes it
71
+ * to one residual basis. */
72
+ static async load(modelDir: string, options: { bits: number }): Promise<Dflash2Provider> {
73
+ const { bits } = options;
74
+ const drafter = await loadDflash2Drafter(modelDir, { bits });
75
+ const id = modelDir.split("/").filter(Boolean).at(-1)!;
76
+ try {
77
+ const files = readdirSync(modelDir).filter(file => file.endsWith(".safetensors"));
78
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
79
+ files.map(name => ({ name, path: join(modelDir, name) })));
80
+ const bytes = files.reduce((total, file) => total + statSync(join(modelDir, file)).size, 0);
81
+ return new Dflash2Provider(drafter, id, bytes, `dflash2-context-v1:${identity}:b${bits}`);
82
+ } catch (error) { drafter.dispose(); throw error; }
83
+ }
84
+
85
+ dispose(): void { this.drafter.dispose(); }
86
+ }
@@ -0,0 +1,66 @@
1
+ // Native GLM-5.2 MTP draft provider.
2
+ //
3
+ // The target and MTP row share embeddings, the output head, and the resident
4
+ // dense target weights. Only the MTP layer's own dense tensors and int8 routed
5
+ // experts add model weight residency. The shared speculative group owns
6
+ // verification, grammar composition, target-cache rollback, sampling, and
7
+ // telemetry. Prompt lookup remains the model-free alternative DraftProvider;
8
+ // selecting one provider per request prevents two independent draft histories
9
+ // from advancing the target or grammar state twice.
10
+
11
+ import type { NativeMtpHead } from "../../../contracts/mlx/drafter";
12
+ import { nativeMtpHeadOf } from "../../../models/drafter-loaders";
13
+ import type { DraftProvider, GroupedDraftProvider, TargetView, DraftRowSampling, DraftRowGroup, DraftPrefillGroup } from "../source";
14
+ import { DRAFT_CHECKPOINT_SCHEMA, type DraftRowCheckpoint } from "../../../contracts/mlx/draft-checkpoint";
15
+ import { Glm52MtpRows } from "../bindings/glm52-mtp-rows";
16
+ import { type Glm52MtpRowState } from "../../../state/speculative/glm52-mtp-state";
17
+ import { captureGlm52MtpState, restoreGlm52MtpState } from "../../../state/speculative/glm52-mtp-state";
18
+ import { applyStateChanges, disposeResources } from "../../../runtime/resources";
19
+
20
+ export class Glm52NativeMtpProvider implements DraftProvider {
21
+ readonly grouped: GroupedDraftProvider = {
22
+ checkpointNamespace: () => DRAFT_CHECKPOINT_SCHEMA.glm52Mtp,
23
+ open: options => this.#openRows(options.target, options.sampling, options.checkpoints),
24
+ openPrefill: options => this.#openRows(options.target, null, options.checkpoints),
25
+ };
26
+ readonly id = "glm52-native-mtp";
27
+ readonly weightsBytes = 0;
28
+ readonly #head: NativeMtpHead;
29
+
30
+ /** Binds the native MTP head `model` declares (`GraphCapabilities.nativeDraft`); it owns every shared and MTP weight. */
31
+ constructor(readonly model: object) {
32
+ this.#head = nativeMtpHeadOf(model);
33
+ }
34
+
35
+ #openRows(target: TargetView, sampling: DraftRowSampling | null,
36
+ checkpoints: readonly (DraftRowCheckpoint | null)[]): DraftRowGroup & DraftPrefillGroup {
37
+ if (target.identity !== this.model) throw new Error("native MTP provider was opened for a different target");
38
+ const rows = new Glm52MtpRows(this.#head, sampling);
39
+ const prepareAppend = (checkpoints: readonly (DraftRowCheckpoint | null)[]) => {
40
+ const states: (Glm52MtpRowState | null)[] = [];
41
+ try {
42
+ for (const checkpoint of checkpoints) states.push(checkpoint ? restoreGlm52MtpState(checkpoint, () => rows.makeCache()) : null);
43
+ return rows.prepareAppend(states);
44
+ } finally { disposeResources(states.flatMap(state => state ? [state.cache, state.hidden] : [])); }
45
+ };
46
+ const append = (states: readonly (DraftRowCheckpoint | null)[]) => applyStateChanges([() => prepareAppend(states)]);
47
+ try { append(checkpoints); } catch (error) { rows.dispose(); throw error; }
48
+ return {
49
+ namespace: DRAFT_CHECKPOINT_SCHEMA.glm52Mtp, prefillMode: "full", tapLayers: [],
50
+ get rowCount() { return rows.rowCount; },
51
+ append, prepareAppend, prefill: (tokens, context) => rows.prefill(tokens, context!),
52
+ materialize: rows.materialize.bind(rows), filterRows: rows.filterRows.bind(rows),
53
+ draft: rows.draft.bind(rows), commit: rows.commit.bind(rows),
54
+ capture(row) {
55
+ const state = rows.extractRow(row);
56
+ try { return captureGlm52MtpState(state); }
57
+ finally { state.cache.dispose(); state.hidden.dispose(); }
58
+ },
59
+ dispose: rows.dispose.bind(rows),
60
+ };
61
+ }
62
+
63
+ dispose(): void {
64
+ // The target model owns every shared/MTP weight and the expert tier.
65
+ }
66
+ }