@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,116 @@
1
+ // Greedy selection preserves dtype-rounded normalized scores, including ties.
2
+ // Native logsumexp retains the reference reduction. Tiled selection avoids
3
+ // writing the vocabulary-sized normalized array. Inputs remain borrowed.
4
+ import { MlxArray } from "@mlx-bun/mlx/array";
5
+ import { Dtype } from "@mlx-bun/mlx/ffi";
6
+ import * as ops from "@mlx-bun/mlx/ops";
7
+ import { CompiledFunction, isShapelessTracing } from "@mlx-bun/mlx/compile";
8
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
9
+
10
+ const header = `
11
+ inline bool better(float x, uint xi, float y, uint yi) {
12
+ return x > y || (x == y && xi < yi);
13
+ }`;
14
+
15
+ // Four simdgroups reduce score/index pairs. Lowest token ID wins every tie.
16
+ // The caller finishes the simd==0 block by writing its output from lane zero.
17
+ const reduction = `
18
+ for (uint distance = 16; distance > 0; distance >>= 1) {
19
+ float other = simd_shuffle_down(best, distance);
20
+ uint oi = simd_shuffle_down(bestId, distance);
21
+ if (lane + distance < 32 && better(other, oi, best, bestId)) {
22
+ best = other; bestId = oi;
23
+ }
24
+ }
25
+ threadgroup float scores[4];
26
+ threadgroup uint ids[4];
27
+ if (lane == 0) { scores[simd] = best; ids[simd] = bestId; }
28
+ threadgroup_barrier(mem_flags::mem_threadgroup);
29
+ if (simd == 0) {
30
+ best = lane < 4 ? scores[lane] : -INFINITY;
31
+ bestId = lane < 4 ? ids[lane] : 0xffffffffu;
32
+ for (uint distance = 2; distance > 0; distance >>= 1) {
33
+ float other = simd_shuffle_down(best, distance);
34
+ uint oi = simd_shuffle_down(bestId, distance);
35
+ if (lane + distance < 4 && better(other, oi, best, bestId)) {
36
+ best = other; bestId = oi;
37
+ }
38
+ }
39
+ `;
40
+
41
+ const partialSource = `
42
+ const uint tid = thread_position_in_threadgroup.x;
43
+ const uint lane = tid % 32, simd = tid / 32;
44
+ const uint row = threadgroup_position_in_grid.y;
45
+ const uint tile = threadgroup_position_in_grid.x;
46
+ float best = -INFINITY;
47
+ uint bestId = 0xffffffffu;
48
+ for (uint i = tile * 1024 + tid; i < min(uint(V), (tile + 1) * 1024); i += 128) {
49
+ float value = float(T(logits[row * V + i] - lse[row]));
50
+ // A nonfinite logsumexp produces only NaN/-inf normalized scores.
51
+ // Native argmax selects token zero for this degenerate row.
52
+ value = isnan(value) ? -INFINITY : value;
53
+ if (better(value, i, best, bestId)) { best = value; bestId = i; }
54
+ }
55
+ ${reduction}
56
+ if (lane == 0) { values[row * P + tile] = best; indices[row * P + tile] = bestId; }
57
+ }
58
+ `;
59
+
60
+ const finishSource = `
61
+ const uint tid = thread_position_in_threadgroup.x;
62
+ const uint lane = tid % 32, simd = tid / 32;
63
+ const uint row = threadgroup_position_in_grid.y;
64
+ float best = -INFINITY;
65
+ uint bestId = 0xffffffffu;
66
+ for (uint i = tid; i < P; i += 128) {
67
+ float value = values[row * P + i];
68
+ uint id = indices[row * P + i];
69
+ if (better(value, id, best, bestId)) { best = value; bestId = id; }
70
+ }
71
+ ${reduction}
72
+ if (lane == 0) out[row] = bestId;
73
+ }
74
+ `;
75
+
76
+ let partial: MetalKernel | undefined;
77
+ let finish: MetalKernel | undefined;
78
+ let compiled: CompiledFunction | undefined;
79
+
80
+ function kernelGraph(logits: MlxArray): MlxArray {
81
+ const shape = logits.shape;
82
+ const vocab = shape.at(-1)!, rows = logits.size / vocab, tiles = Math.ceil(vocab / 1024);
83
+ partial ??= new MetalKernel({ name: "normalized_argmax_partial", header,
84
+ inputNames: ["logits", "lse"], outputNames: ["values", "indices"], source: partialSource });
85
+ finish ??= new MetalKernel({ name: "normalized_argmax_finish", header,
86
+ inputNames: ["values", "indices"], outputNames: ["out"], source: finishSource });
87
+ using lse = ops.logsumexpAxis(logits, -1, true);
88
+ const [values, indices] = partial.apply([logits, lse], {
89
+ outputs: [{ shape: [rows, tiles], dtype: Dtype.float32 }, { shape: [rows, tiles], dtype: Dtype.uint32 }],
90
+ grid: [tiles * 128, rows, 1], threadGroup: [128, 1, 1],
91
+ templateInts: { V: vocab, P: tiles }, templateDtypes: { T: logits.dtype },
92
+ });
93
+ try {
94
+ using tokens = finish.apply([values!, indices!], {
95
+ outputs: [{ shape: [rows], dtype: Dtype.uint32 }],
96
+ grid: [128, rows, 1], threadGroup: [128, 1, 1], templateInts: { P: tiles },
97
+ })[0]!;
98
+ return ops.reshape(tokens, shape.slice(0, -1));
99
+ } finally { values!.dispose(); indices!.dispose(); }
100
+ }
101
+
102
+ /** Return owned greedy IDs with the same shape/rounding as argmax(logprobs).
103
+ * Fixed-shape compilation caches graph/FFI work for repeated row geometries.
104
+ * Shapeless enclosing graphs retain native operations, which support symbolic
105
+ * sizes; integer/empty inputs also retain the original operation semantics. */
106
+ export function normalizedArgmax(logits: MlxArray): MlxArray {
107
+ const dtype = logits.dtype;
108
+ if (isShapelessTracing() || logits.size === 0 ||
109
+ (dtype !== Dtype.float32 && dtype !== Dtype.float16 && dtype !== Dtype.bfloat16)) {
110
+ using lse = ops.logsumexpAxis(logits, -1, true);
111
+ using scores = ops.sub(logits, lse);
112
+ return ops.argmaxAxis(scores, -1);
113
+ }
114
+ compiled ??= new CompiledFunction(([input]) => [kernelGraph(input!)], false);
115
+ return compiled.apply([logits])[0]!;
116
+ }
@@ -0,0 +1,52 @@
1
+ // XGrammar's additive 0/-Infinity mask contract, decoded from packed bits.
2
+ // Reference: mlc-ai/xgrammar b5048784, apply_token_bitmask_mlx.py (Apache-2.0).
3
+ import { MlxArray } from "@mlx-bun/mlx/array";
4
+ import { CompiledFunction } from "@mlx-bun/mlx/compile";
5
+ import { Dtype } from "@mlx-bun/mlx/ffi";
6
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
7
+
8
+ let compiled: CompiledFunction | undefined;
9
+ let kernel: MetalKernel | undefined;
10
+
11
+ function maskGraph(logits: MlxArray, bits: MlxArray): MlxArray {
12
+ kernel ??= new MetalKernel({
13
+ name: "mlx_bun_token_bitmask",
14
+ inputNames: ["logits", "bits"],
15
+ outputNames: ["out"],
16
+ source: String.raw`
17
+ const uint i = thread_position_in_grid.x;
18
+ if (i >= SIZE) return;
19
+ const uint id = i % V;
20
+ const uint word = uint(bits[id >> 5]);
21
+ const bool valid = ((word >> (id & 31)) & 1u) != 0;
22
+ out[i] = logits[i] + T(valid ? 0.0f : -INFINITY);
23
+ `,
24
+ });
25
+ return kernel.apply([logits, bits], {
26
+ outputs: [{ shape: logits.shape, dtype: logits.dtype }],
27
+ grid: [logits.size, 1, 1],
28
+ threadGroup: [128, 1, 1],
29
+ templateDtypes: { T: logits.dtype },
30
+ templateInts: { V: logits.shape.at(-1)!, SIZE: logits.size },
31
+ })[0]!;
32
+ }
33
+
34
+ /** Apply one little-endian token bitmask to every row along the final axis.
35
+ * Borrow logits; return an owned lazy result. Copy the mutable host bits now,
36
+ * so a matcher can advance before GPU evaluation. Missing words reject tokens.
37
+ * Preserve the additive-mask expression, including NaNs and signed zero.
38
+ * Shape-specialized compilation handles bf16/f16/f32 and strided inputs. */
39
+ export function applyTokenBitmask(logits: MlxArray, bits: Int32Array): MlxArray {
40
+ const vocab = logits.shape.at(-1);
41
+ if (!vocab || logits.size === 0 || logits.size > 0x7fffffff)
42
+ throw new Error("token bitmask requires nonempty logits with at most 2^31-1 elements");
43
+ if (![Dtype.bfloat16, Dtype.float16, Dtype.float32].includes(logits.dtype))
44
+ throw new Error("token bitmask requires bf16, f16 or f32 logits");
45
+ const copy = new Int32Array(Math.ceil(vocab / 32));
46
+ copy.set(bits.subarray(0, copy.length));
47
+ const deviceBits = MlxArray.fromInt32(copy, [copy.length]);
48
+ try {
49
+ compiled ??= new CompiledFunction(([x, mask]) => [maskGraph(x!, mask!)], false);
50
+ return compiled.apply([logits, deviceBits])[0]!;
51
+ } finally { deviceBits.dispose(); }
52
+ }
@@ -0,0 +1,35 @@
1
+ // Compiled (fused) Gemma logit softcap, matching mlx-lm's gemma4_text.py
2
+ // `@partial(mx.compile) logit_softcap`. The unfused composition lives in
3
+ // logits.ts; the two are separate on purpose (see compiledLogitSoftcap).
4
+
5
+ import { MlxArray } from "@mlx-bun/mlx/array";
6
+ import * as ops from "@mlx-bun/mlx/ops";
7
+ import { CompiledFunction } from "@mlx-bun/mlx/compile";
8
+
9
+ /** gemma4_text.py `@partial(mx.compile) def logit_softcap(softcap, x):
10
+ * return mx.tanh(x / softcap) * softcap`
11
+ * The oracle fuses divide+tanh+multiply into ONE kernel; our default
12
+ * `logitSoftcap` (logits.ts) runs them UNFUSED (standalone div + tanh + mul →
13
+ * a separate `vn_Tanh` + `vsn_Divide`). Keyed by cap so the softcap is baked
14
+ * as a graph constant (matching the oracle's weak-scalar → the
15
+ * `…Divide…Tanh…Multiply…_VC_` kernel). The two implementations are
16
+ * intentionally separate: this one reproduces the oracle's compiled kernel
17
+ * (Gemma4's final softcap, outside a compiled trace); `logitSoftcap` is the
18
+ * plain composition used elsewhere (Universal attention/final softcap, and
19
+ * inside a compiled trace). Neither may replace the other. */
20
+ const _softcapClosures = new Map<number, CompiledFunction>();
21
+ export function compiledLogitSoftcap(x: MlxArray, cap: number): MlxArray {
22
+ let fn = _softcapClosures.get(cap);
23
+ if (!fn) {
24
+ fn = new CompiledFunction((inputs) => {
25
+ const xx = inputs[0]!; // tanh(x / softcap) * softcap
26
+ const capArr = ops.scalarLike(cap, xx);
27
+ const scaled = ops.div(xx, capArr);
28
+ const t = ops.tanh(scaled); scaled.dispose();
29
+ const out = ops.mul(t, capArr); t.dispose(); capArr.dispose();
30
+ return [out];
31
+ });
32
+ _softcapClosures.set(cap, fn);
33
+ }
34
+ return fn.apply([x])[0]!;
35
+ }
@@ -0,0 +1,123 @@
1
+ import { MlxArray } from "@mlx-bun/mlx/array";
2
+
3
+ /** The only definition of the 1MAD decode arithmetic; every kernel header includes it. */
4
+ export const HEADER = String.raw`
5
+ static inline float trellis_bf16(float v) {
6
+ uint u = as_type<uint>(v);
7
+ u = (u + 0x7FFFu + ((u >> 16) & 1u)) & 0xFFFF0000u;
8
+ return as_type<float>(u);
9
+ }
10
+ // QTIP 1MAD computed code for state s: x = s*34038481 + 76625530 (mod 2^32),
11
+ // y = sum of the four bytes of x - 510, value = y / 147.800537109375. Two
12
+ // byte-pair adds replace the four extracts; precise divide matches the host
13
+ // LUT (lut1mad below) bit for bit.
14
+ static inline int trellis_y(uint s) {
15
+ const uint x = s * 34038481u + 76625530u;
16
+ const uint p = (x & 0x00FF00FFu) + ((x >> 8) & 0x00FF00FFu);
17
+ return (int)((p & 0xFFFFu) + (p >> 16)) - 510;
18
+ }
19
+ static inline float trellis_val(uint s) {
20
+ return metal::precise::divide((float)trellis_y(s), 147.800537109375f);
21
+ }
22
+ // y × (1/d) refined by one residual step: q' = fma(fma(-q, d, y), 1/d, q).
23
+ // Correctly rounded for every y in [-510, 510] (checked host-side against
24
+ // the LUT), 3 FMA-class ops instead of a precise divide. Every expansion and
25
+ // prefill kernel that reproduces the host LUT decodes through this.
26
+ static inline float trellis_refined_y(int y) {
27
+ const float yf = (float)y;
28
+ const float r = 1.0f / 147.800537109375f;
29
+ const float q = yf * r;
30
+ const float e = metal::fma(-q, 147.800537109375f, yf);
31
+ return metal::fma(e, r, q);
32
+ }
33
+ static inline float trellis_val_rcp(uint s) { return trellis_refined_y(trellis_y(s)); }
34
+ // Unrefined y × (1/d) (≤1 ulp f32): the packed matvec/scatter weight is this
35
+ // f32 code value, a different numerical contract from the LUT-exact decode above.
36
+ static inline float trellis_unrefined_y(int y) {
37
+ return (float)y * (1.0f / 147.800537109375f);
38
+ }
39
+ // The code value y as f32 without an integer-to-float conversion: y + 510
40
+ // (0..1020) ORed into the mantissa of 2^23, whose ULP is one, minus 2^23 + 510.
41
+ // Equal to (float)trellis_y(s). Factored kernels accumulate y·x and apply
42
+ // scale·TRELLIS_RCP once per output (or fold it into each input row).
43
+ static inline float trellis_y_f32(uint s) {
44
+ return as_type<float>(0x4b000000u | uint(trellis_y(s) + 510)) - 8389118.0f;
45
+ }
46
+ #define TRELLIS_RCP (1.0f / 147.800537109375f)
47
+ // For y in [-510, 510], 2^23 has unit f32 spacing, so setting its low
48
+ // mantissa bits constructs 2^23+y+510 exactly. Subtracting 2^23+510
49
+ // recovers the same f32 y as the integer conversion; the reciprocal is unchanged.
50
+ static inline float trellis_unrefined_bits_y(int y) {
51
+ const float lifted = as_type<float>(0x4b000000u | uint(y + 510));
52
+ return (lifted - 8389118.0f) * (1.0f / 147.800537109375f);
53
+ }
54
+ // VARIANT: 0 = inline 1MAD + precise divide; 1 = inline 1MAD × reciprocal
55
+ // (1 ulp risk vs the host LUT); 2 = 4096-entry f32 LUT in threadgroup memory;
56
+ // 3 = the same LUT gathered from device memory.
57
+ // 4 = NO decode (timing floor only, wrong numerics); 5 = rcp decode, no bf16
58
+ // rounding; 6 = unrefined y×(1/d) (≤1 ulp f32), no bf16 rounding — the
59
+ // weight is f32 code×scale, more accurate than the artifact's stored bf16.
60
+ #define TRELLIS_DECODE(win, lutTG, lut) \
61
+ ((VARIANT) == 0 ? trellis_val(win) : \
62
+ (VARIANT) == 1 || (VARIANT) == 5 ? trellis_val_rcp(win) : \
63
+ (VARIANT) == 6 ? trellis_unrefined_y(trellis_y(win)) : \
64
+ (VARIANT) == 2 ? lutTG[win] : \
65
+ (VARIANT) == 4 ? (float)(win) : lut[win])
66
+ #define TRELLIS_ROUND(v) ((VARIANT) >= 4 ? (v) : trellis_bf16(v))
67
+ // state_t of one packed block: L bits at offset (BT-1-t)*K, wrapping (32-bit ops).
68
+ static inline uint trellis_state(const device uint32_t* blk, uint wpb, uint t, uint bt, uint k, uint l) {
69
+ const uint p = (bt - 1u - t) * k;
70
+ const uint wi = p >> 5;
71
+ const uint off = p & 31u;
72
+ uint win = blk[wi] >> off;
73
+ if (off + l > 32u) win |= blk[(wi + 1u == wpb) ? 0u : (wi + 1u)] << (32u - off);
74
+ return win & ((1u << l) - 1u);
75
+ }
76
+ `;
77
+
78
+ /** The one-row threadgroup-codebook kernels' table read (gate-up-codebook, down-codebook): the code value of the
79
+ * L-bit window at bit `off` of a lane's words w, read as the L + 2 bits [off - 2, off + L), the window's byte offset
80
+ * in a float table plus two low bits that the M1 Max (applegpu_g13s) threadgroup load ignores for a 4-byte element,
81
+ * so one bit-field extract serves each window; the kernels' bit-identity tests hold them to the reference bits. A
82
+ * field that crosses a word, or starts below bit 0, reads the virtual words v (v[i]: the high half of w[i - 1] and
83
+ * the low half of w[i], bits [32i - 16, 32i + 16)). `off` and `l` are compile-time constants at every call. */
84
+ export const CODEBOOK_WINDOW = String.raw`
85
+ static inline float trellis_codebook_window(const threadgroup uchar* table, thread const uint* w, thread const uint* v,
86
+ uint off, uint l) {
87
+ const int f = int(off) - 2;
88
+ const uint mask = (1u << (l + 2u)) - 1u;
89
+ uint bits;
90
+ if (f >= 0 && uint(f & 31) + l + 2u <= 32u) bits = (w[f >> 5] >> uint(f & 31)) & mask;
91
+ else { const uint vi = uint(f + 16) >> 5; bits = (v[vi] >> uint(f + 16 - 32 * int(vi))) & mask; }
92
+ return *(const threadgroup float*)(table + bits);
93
+ }
94
+ `;
95
+
96
+ export function lut1mad(L: number): Float32Array {
97
+ const n = 1 << L;
98
+ const out = new Float32Array(n);
99
+ const M = (1n << 32n) - 1n;
100
+ for (let i = 0; i < n; i++) {
101
+ let x = BigInt(i) & M;
102
+ x = (x * 34038481n + 76625530n) & M;
103
+ const y =
104
+ Number((x & 255n) + ((x >> 8n) & 255n) + ((x >> 16n) & 255n) + ((x >> 24n) & 255n)) - 510;
105
+ out[i] = y / 147.800537109375;
106
+ }
107
+ return out;
108
+ }
109
+
110
+ export function wordsPerBlock(T: number, k: number): number {
111
+ if ((T * k) % 32 !== 0) throw new Error(`T·k = ${T * k} not a multiple of 32`);
112
+ return (T * k) / 32;
113
+ }
114
+
115
+ const luts = new Map<number, MlxArray>();
116
+ export function lutFor(L: number): MlxArray {
117
+ let a = luts.get(L);
118
+ if (!a) { a = MlxArray.fromFloat32(lut1mad(L), [1 << L]); a.eval(); luts.set(L, a); }
119
+ return a;
120
+ }
121
+
122
+ // Variants 7..13 retain variant 6 decoded values.
123
+ export function decoderVariant(selected: number): number { return selected >= 7 && selected <= 13 ? 6 : selected; }
@@ -0,0 +1,184 @@
1
+ import { MlxArray } from "@mlx-bun/mlx/array";
2
+ import { Dtype } from "@mlx-bun/mlx/ffi";
3
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
4
+ import type { TrellisGeometry } from "./geometry";
5
+ import { CODEBOOK_WINDOW, HEADER } from "./codebook";
6
+ import { TRELLIS_CODEBOOK_DOWN_THREADS } from "./launch";
7
+
8
+ // Axis-0 (down) projection of one activation row over T 256 Trellis codes,
9
+ // decoding through a threadgroup codebook (every code value y·(1/147.8) of the
10
+ // 2^L states, generated once per threadgroup). Each lane owns P = 16
11
+ // consecutive positions of one block: it loads the words they span (plus the
12
+ // next lane's first word for the last windows) for U input rows ahead, aligns
13
+ // them to its first bit once per row where P·K is not a multiple of 32 (the
14
+ // 3-bit codes, whose odd lanes start at bit 16), then reads every window with
15
+ // one bit-field extract at a compile-time shift (CODEBOOK_WINDOW, codebook.ts).
16
+ // No lane exchanges data, so lanes past the last block return at once.
17
+ // Split-K over input rows into SPLITS f32 partials, summed as MLX sums them
18
+ // (a threadgroup adds the four splits of the first stage, FOLD the rest) and
19
+ // cast to the activation dtype. Every position accumulates the same f32 code·scale weights over the same
20
+ // rows in the same order as trellisScatter's single-row kernels at variant 13
21
+ // (the balanced one for the 3-bit block interleave), so the output is theirs
22
+ // bit for bit.
23
+ const SPLITS = 128, P = 16, U = 2;
24
+
25
+ const SOURCE = String.raw`
26
+ threadgroup float codebook[4096]; // 2^L codes, then the eight SIMD groups' partials
27
+ for (uint i = thread_position_in_threadgroup.x; i < (1u << (uint)L); i += (uint)THREADS)
28
+ codebook[i] = trellis_unrefined_bits_y(trellis_y(i));
29
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
30
+ constexpr uint BITS = (uint)(P * K); // a lane's bits
31
+ constexpr uint SHIFT = BITS % 32u; // 0, or 16: odd lanes start at bit 16 of a word
32
+ constexpr bool ALIGNED = SHIFT == 0u;
33
+ constexpr uint NA = (BITS + (uint)L - (uint)K + 31u) / 32u; // words its windows span from its first bit
34
+ constexpr uint NL = ALIGNED ? NA : NA + 1u; // words it loads
35
+ constexpr uint LB = 256u / (uint)P; // lanes per block
36
+ constexpr uint WPB = 8u * (uint)K; // words per block
37
+ constexpr uint NB = (uint)(C / 256); // blocks
38
+ constexpr uint SGS = (NB + 32u / LB - 1u) / (32u / LB); // SIMD groups per split
39
+ constexpr ulong ROWW = INTERLEAVE ? 2ul * WPB : (ulong)NB * WPB;
40
+ constexpr uint ROWS_PER = ((uint)R + (uint)SPLITS - 1u) / (uint)SPLITS;
41
+ constexpr uint SG_COLS = 32u * (uint)P; // a SIMD group's columns
42
+ // Threadgroup t: row group y = t % 32 and SIMD groups (k, c) = (s % 4, s / 4) take split y + 32k of column group
43
+ // 2·(t / 32) + c, so the threadgroup holds the four splits MLX's column sum adds first for 2·SG_COLS columns.
44
+ const uint lane = thread_index_in_simdgroup;
45
+ const uint sg = simdgroup_index_in_threadgroup;
46
+ const uint ty = threadgroup_position_in_grid.y;
47
+ const uint y = ty % 32u;
48
+ const uint split = y + 32u * (sg % 4u);
49
+ const uint colGroup = 2u * (ty / 32u) + sg / 4u;
50
+ const uint li = lane % LB;
51
+ const uint blk = colGroup * (32u / LB) + lane / LB;
52
+ const bool active = colGroup < SGS && blk < NB;
53
+ const device uint32_t* blockWords = codes + (!active ? 0ul : INTERLEAVE
54
+ ? (ulong)(blk / 2u) * (ulong)R * 2ul * WPB + (blk % 2u) * WPB : (ulong)blk * WPB);
55
+ const uint first = (li * BITS) >> 5;
56
+ const bool shifted = !ALIGNED && (li & 1u);
57
+ uint idx[NL];
58
+ #pragma clang loop unroll(full)
59
+ for (uint i = 0; i < NL; ++i) idx[i] = (first + i) % WPB;
60
+ const uint r0 = split * ROWS_PER;
61
+ const uint rows = !active ? 0u : (uint)R % (uint)SPLITS == 0u ? ROWS_PER : r0 >= (uint)R ? 0u : metal::min(ROWS_PER, (uint)R - r0);
62
+ const threadgroup uchar* table = (const threadgroup uchar*)codebook;
63
+ float acc[P];
64
+ #pragma clang loop unroll(full)
65
+ for (uint i = 0; i < (uint)P; ++i) acc[i] = 0.0f;
66
+ uint r = 0;
67
+ for (; r + (uint)U <= rows; r += (uint)U) {
68
+ uint ld[U][NL];
69
+ float xr[U], sr[U];
70
+ #pragma clang loop unroll(full)
71
+ for (uint u = 0; u < (uint)U; ++u) {
72
+ const device uint32_t* rowWords = blockWords + (ulong)(r0 + r + u) * ROWW;
73
+ #pragma clang loop unroll(full)
74
+ for (uint i = 0; i < NL; ++i) ld[u][i] = rowWords[idx[i]];
75
+ xr[u] = float(x[r0 + r + u]);
76
+ sr[u] = float(scales[r0 + r + u]);
77
+ }
78
+ #pragma clang loop unroll(full)
79
+ for (uint u = 0; u < (uint)U; ++u) {
80
+ uint w[NA], v[NA];
81
+ #pragma clang loop unroll(full)
82
+ for (uint i = 0; i < NA; ++i) w[i] = shifted ? (ld[u][i] >> SHIFT) | (ld[u][i + 1] << (32u - SHIFT)) : ld[u][i];
83
+ v[0] = w[0] << 16;
84
+ #pragma clang loop unroll(full)
85
+ for (uint i = 1; i < NA; ++i) v[i] = (w[i - 1] >> 16) | (w[i] << 16);
86
+ #pragma clang loop unroll(full)
87
+ for (uint i = 0; i < (uint)P; ++i) {
88
+ const float code = trellis_codebook_window(table, w, v, i * (uint)K, (uint)L);
89
+ acc[i] = metal::fma(code * sr[u], xr[u], acc[i]);
90
+ }
91
+ }
92
+ }
93
+ for (; r < rows; ++r) {
94
+ const device uint32_t* rowWords = blockWords + (ulong)(r0 + r) * ROWW;
95
+ uint ld[NL];
96
+ #pragma clang loop unroll(full)
97
+ for (uint i = 0; i < NL; ++i) ld[i] = rowWords[idx[i]];
98
+ const float xr = float(x[r0 + r]);
99
+ const float sr = float(scales[r0 + r]);
100
+ uint w[NA], v[NA];
101
+ #pragma clang loop unroll(full)
102
+ for (uint i = 0; i < NA; ++i) w[i] = shifted ? (ld[i] >> SHIFT) | (ld[i + 1] << (32u - SHIFT)) : ld[i];
103
+ v[0] = w[0] << 16;
104
+ #pragma clang loop unroll(full)
105
+ for (uint i = 1; i < NA; ++i) v[i] = (w[i - 1] >> 16) | (w[i] << 16);
106
+ #pragma clang loop unroll(full)
107
+ for (uint i = 0; i < (uint)P; ++i) {
108
+ const float code = trellis_codebook_window(table, w, v, i * (uint)K, (uint)L);
109
+ acc[i] = metal::fma(code * sr, xr, acc[i]);
110
+ }
111
+ }
112
+ // The four splits' partials meet in the codebook's memory; each column's first sum stage, ((0 + p[y]) + p[y + 32])
113
+ // + ..., in MLX's order, goes out as row y of the 32 the fold sums.
114
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
115
+ threadgroup float* sums = codebook;
116
+ const uint local = (lane / LB) * 256u + 255u - li * (uint)P;
117
+ #pragma clang loop unroll(full)
118
+ for (uint i = 0; i < (uint)P; ++i) sums[sg * SG_COLS + local - i] = acc[i];
119
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
120
+ for (uint c = thread_position_in_threadgroup.x; c < 2u * SG_COLS; c += (uint)THREADS) {
121
+ const uint group2 = c / SG_COLS, col = (2u * (ty / 32u) + group2) * SG_COLS + c % SG_COLS;
122
+ if (col >= (uint)C) continue;
123
+ float t = 0.0f;
124
+ #pragma clang loop unroll(full)
125
+ for (uint k = 0; k < 4u; ++k) t = sums[(group2 * 4u + k) * SG_COLS + c % SG_COLS] + t;
126
+ partial[(ulong)y * (ulong)C + col] = t;
127
+ }
128
+ `;
129
+
130
+ // The second stage of MLX's column sum over the SPLITS partials (col_reduce_looped, 32x32 tiles, the reduction it runs
131
+ // at this shape) and the cast to T, bit for bit: SIMD group s of a threadgroup's 32 columns sums each of its four
132
+ // columns over the 32 first-stage rows (lane y holds row y) with simd_sum.
133
+ const FOLD = String.raw`
134
+ const uint lane = thread_index_in_simdgroup;
135
+ const uint col = threadgroup_position_in_grid.x * 32u + simdgroup_index_in_threadgroup * 4u;
136
+ const float4 t = *(const device float4*)(partial + (ulong)lane * (ulong)C + col);
137
+ #pragma clang loop unroll(full)
138
+ for (uint i = 0; i < 4u; ++i) {
139
+ const float v = metal::simd_sum(t[i]);
140
+ if (lane == 0u) out[col + i] = T(v);
141
+ }
142
+ `;
143
+
144
+ let kernel: MetalKernel | undefined;
145
+ let fold: MetalKernel | undefined;
146
+
147
+ function launch(x2: MlxArray, codes: MlxArray, scales: MlxArray, g: TrellisGeometry, interleave: boolean): MlxArray {
148
+ const groupsPerSplit = Math.ceil((g.cols / 256) / (P / 8));
149
+ if (x2.shape[0] !== 1) throw new Error("downCodebookRow: expects one activation row");
150
+ if (g.axis !== 0 || g.T !== 256 || g.L > 12 || g.cols % 256) throw new Error("downCodebookRow: needs axis-0 codes at T 256, L <= 12");
151
+ kernel ??= new MetalKernel({ name: "mlx_bun_trellis_down_codebook_row", inputNames: ["x", "codes", "scales"],
152
+ outputNames: ["partial"], source: SOURCE, header: HEADER + CODEBOOK_WINDOW, ensureRowContiguous: true });
153
+ fold ??= new MetalKernel({ name: "mlx_bun_trellis_down_codebook_fold", inputNames: ["partial"], outputNames: ["out"],
154
+ source: FOLD, ensureRowContiguous: true });
155
+ // 32 row groups, each threadgroup two SIMD groups' columns of four splits.
156
+ const [partial] = kernel.apply([x2, codes, scales], {
157
+ outputs: [{ shape: [1, 32, g.cols], dtype: Dtype.float32 }],
158
+ grid: [TRELLIS_CODEBOOK_DOWN_THREADS, 32 * Math.ceil(groupsPerSplit / 2), 1],
159
+ threadGroup: [TRELLIS_CODEBOOK_DOWN_THREADS, 1, 1],
160
+ templateDtypes: { T: x2.dtype },
161
+ templateInts: { R: g.rows, C: g.cols, K: g.k, L: g.L, P, U, SPLITS, THREADS: TRELLIS_CODEBOOK_DOWN_THREADS,
162
+ INTERLEAVE: Number(interleave) },
163
+ });
164
+ const [out] = fold.apply([partial!], {
165
+ outputs: [{ shape: [1, g.cols], dtype: x2.dtype }],
166
+ grid: [8 * 32 * g.cols / 32, 1, 1], threadGroup: [8 * 32, 1, 1],
167
+ templateDtypes: { T: x2.dtype }, templateInts: { C: g.cols },
168
+ });
169
+ partial!.dispose();
170
+ return out!;
171
+ }
172
+
173
+ /** x2 [1, inFeatures] · W → [1, outFeatures] in x2's dtype over row-major 2- or
174
+ * 4-bit codes [rows, cols·K/32]. Borrows inputs. */
175
+ export function downCodebookRow(x2: MlxArray, codes: MlxArray, scales: MlxArray, g: TrellisGeometry): MlxArray {
176
+ if (g.blockInterleave || codes.ndim !== 2 || (g.k !== 2 && g.k !== 4)) throw new Error("downCodebookRow: needs row-major 2- or 4-bit codes");
177
+ return launch(x2, codes, scales, g, false);
178
+ }
179
+
180
+ /** The same over 3-bit block-interleaved codes [cols/512, rows, 48]. */
181
+ export function downK3InterleavedCodebookRow(x2: MlxArray, codes: MlxArray, scales: MlxArray, g: TrellisGeometry): MlxArray {
182
+ if (g.blockInterleave !== 2 || g.k !== 3) throw new Error("downK3InterleavedCodebookRow: needs 3-bit block-interleaved codes");
183
+ return launch(x2, codes, scales, g, true);
184
+ }