@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,306 @@
1
+ // Gated DeltaNet recurrence for Qwen3.5 linear-attention layers.
2
+ //
3
+ // Port target: mlx_lm.models.gated_delta (compute_g + the `gated_delta_step`
4
+ // Metal kernel) and the recurrent-state cache. mlx-lm runs the GPU kernel by
5
+ // default (use_kernel = not training), and its float accumulation / simd_sum
6
+ // reduction order differ from the pure-ops fallback — so BIT-EXACT parity with
7
+ // mlx-lm requires the SAME kernel, dispatched with the SAME grid/threadgroup.
8
+ // We port the non-vectorized variant (g.ndim == 3). Padded prefill selects
9
+ // the oracle masked specialization; unpadded execution retains its kernel.
10
+ //
11
+ // Numerics (must match the reference dtypes exactly — mlx infers the kernel's
12
+ // pointer element types from the input arrays):
13
+ // q, k bf16 [B, T, Hk, Dk] (after inv_scale * rms_norm(., None))
14
+ // v bf16 [B, T, Hv, Dv]
15
+ // g f32 [B, T, Hv] (= exp(-exp(A_log_f32) * softplus(a+dt_bias)))
16
+ // beta bf16 [B, T, Hv] (= sigmoid(b))
17
+ // state_in f32 [B, Hv, Dv, Dk]
18
+ // y (out) bf16 [B, T, Hv, Dv] (InT)
19
+ // state_out f32 [B, Hv, Dv, Dk] (StT)
20
+ // GQA is handled inside the kernel (hk_idx = hv_idx / (Hv/Hk)); q/k stay at Hk.
21
+
22
+ import { MlxArray } from "@mlx-bun/mlx/array";
23
+ import { Vjp } from "@mlx-bun/mlx/autograd";
24
+ import { CompiledFunction } from "@mlx-bun/mlx/compile";
25
+ import { CustomVjp } from "@mlx-bun/mlx/custom-vjp";
26
+ import { Dtype } from "@mlx-bun/mlx/ffi";
27
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
28
+ import * as ops from "@mlx-bun/mlx/ops";
29
+
30
+ // Verbatim body of mlx-lm's gated_delta_step (has_mask=False, vectorized=False),
31
+ // with the only change being that the time count `T` arrives as a 1-element
32
+ // int32 input (`Tin`) and is read once — numerically identical to the
33
+ // reference (T only drives loop bounds and integer offsets), but avoids a
34
+ // kernel recompile per distinct sequence length.
35
+ const SOURCE = String.raw`
36
+ const int T = Tin[0];
37
+ auto n = thread_position_in_grid.z;
38
+ auto b_idx = n / Hv;
39
+ auto hv_idx = n % Hv;
40
+ auto hk_idx = hv_idx / (Hv / Hk);
41
+ constexpr int n_per_t = Dk / 32;
42
+
43
+ // q, k: [B, T, Hk, Dk]
44
+ auto q_ = q + b_idx * T * Hk * Dk + hk_idx * Dk;
45
+ auto k_ = k + b_idx * T * Hk * Dk + hk_idx * Dk;
46
+
47
+ // v, y: [B, T, Hv, Dv]
48
+ auto v_ = v + b_idx * T * Hv * Dv + hv_idx * Dv;
49
+ y += b_idx * T * Hv * Dv + hv_idx * Dv;
50
+
51
+ auto dk_idx = thread_position_in_threadgroup.x;
52
+ auto dv_idx = thread_position_in_grid.y;
53
+
54
+ // state_in, state_out: [B, Hv, Dv, Dk]
55
+ auto i_state = state_in + (n * Dv + dv_idx) * Dk;
56
+ auto o_state = state_out + (n * Dv + dv_idx) * Dk;
57
+
58
+ float state[n_per_t];
59
+ for (int i = 0; i < n_per_t; ++i) {
60
+ auto s_idx = n_per_t * dk_idx + i;
61
+ state[i] = static_cast<float>(i_state[s_idx]);
62
+ }
63
+
64
+ // g: [B, T, Hv]
65
+ auto g_ = g + b_idx * T * Hv;
66
+ auto beta_ = beta + b_idx * T * Hv;
67
+
68
+ for (int t = 0; t < T; ++t) {
69
+ if (true) {
70
+ float kv_mem = 0.0f;
71
+ for (int i = 0; i < n_per_t; ++i) {
72
+ auto s_idx = n_per_t * dk_idx + i;
73
+ state[i] = state[i] * g_[hv_idx];
74
+ kv_mem += state[i] * k_[s_idx];
75
+ }
76
+ kv_mem = simd_sum(kv_mem);
77
+
78
+ auto delta = (v_[dv_idx] - kv_mem) * beta_[hv_idx];
79
+
80
+ float out = 0.0f;
81
+ for (int i = 0; i < n_per_t; ++i) {
82
+ auto s_idx = n_per_t * dk_idx + i;
83
+ state[i] = state[i] + k_[s_idx] * delta;
84
+ out += state[i] * q_[s_idx];
85
+ }
86
+ out = simd_sum(out);
87
+ if (thread_index_in_simdgroup == 0) {
88
+ y[dv_idx] = static_cast<InT>(out);
89
+ }
90
+ } else {
91
+ y[dv_idx] = static_cast<InT>(0);
92
+ }
93
+ // Increment data pointers to next time step
94
+ q_ += Hk * Dk;
95
+ k_ += Hk * Dk;
96
+ v_ += Hv * Dv;
97
+ y += Hv * Dv;
98
+ g_ += Hv;
99
+ beta_ += Hv;
100
+ }
101
+ for (int i = 0; i < n_per_t; ++i) {
102
+ auto s_idx = n_per_t * dk_idx + i;
103
+ o_state[s_idx] = static_cast<StT>(state[i]);
104
+ }
105
+ `;
106
+
107
+ let kernel: MetalKernel | null = null;
108
+ let maskedKernel: MetalKernel | null = null;
109
+ function getKernel(masked = false): MetalKernel {
110
+ if (masked) return maskedKernel ??= new MetalKernel({
111
+ name: "gated_delta_step_mask",
112
+ inputNames: ["q", "k", "v", "g", "beta", "state_in", "Tin", "mask"],
113
+ outputNames: ["y", "state_out"],
114
+ source: SOURCE.replace("if (true)", "if (mask[b_idx * T + t])"),
115
+ ensureRowContiguous: true,
116
+ });
117
+ if (!kernel)
118
+ kernel = new MetalKernel({
119
+ name: "gated_delta_step",
120
+ inputNames: ["q", "k", "v", "g", "beta", "state_in", "Tin"],
121
+ outputNames: ["y", "state_out"],
122
+ source: SOURCE,
123
+ ensureRowContiguous: true,
124
+ });
125
+ return kernel;
126
+ }
127
+
128
+ /** compute_g: exp(-exp(A_log_f32) * softplus(a + dt_bias)). Output is f32
129
+ * (the f32 exp(A_log) promotes the bf16 softplus term) — the kernel reads g
130
+ * as float, so this dtype is load-bearing. */
131
+ let _computeGFn: CompiledFunction | null = null;
132
+ export function computeG(aLog: MlxArray, a: MlxArray, dtBias: MlxArray): MlxArray {
133
+ // mlx-lm gated_delta.py: `@partial(mx.compile, shapeless=True) compute_g` — the
134
+ // WHOLE chain (exp/neg/softplus/mul/exp) is ONE fused kernel there, not five
135
+ // separate dispatches. Traced once, replayed.
136
+ if (!_computeGFn) {
137
+ _computeGFn = new CompiledFunction((inp) => {
138
+ const aL = inp[0]!, aa = inp[1]!, dt = inp[2]!;
139
+ const aLogF = aL.astype(Dtype.float32);
140
+ const expA = ops.exp(aLogF); aLogF.dispose();
141
+ const negExpA = ops.neg(expA); expA.dispose();
142
+ const adt = ops.add(aa, dt);
143
+ // mlx nn.softplus(x) = mx.logaddexp(x, 0), where 0 is a weak Python int
144
+ // (no cast node). ops.softplus builds the 0 via scalarLike (fromFloat32 →
145
+ // f32→bf16 AsType). Build the 0 at adt's dtype from raw bytes so there is
146
+ // no cast — matching mlx's graph exactly.
147
+ const zbytes = adt.dtype === Dtype.float32
148
+ ? new Uint8Array([0, 0, 0, 0])
149
+ : new Uint8Array([0, 0]);
150
+ const zero = MlxArray.fromBytesCopy(zbytes, [], adt.dtype);
151
+ const sp = ops.logaddexp(adt, zero); adt.dispose(); zero.dispose();
152
+ const prod = ops.mul(negExpA, sp); negExpA.dispose(); sp.dispose();
153
+ const g = ops.exp(prod); prod.dispose();
154
+ return [g];
155
+ });
156
+ }
157
+ return _computeGFn.apply([aLog, a, dtBias])[0]!;
158
+ }
159
+
160
+ /** The kernel launch shared by the inference and training entries.
161
+ * q, k: [B, T, Hk, Dk] v: [B, T, Hv, Dv] g, beta: [B, T, Hv]
162
+ * state: [B, Hv, Dv, Dk] f32 (never null here) mask: [B, T] or null */
163
+ function launchRecurrence(
164
+ q: MlxArray, k: MlxArray, v: MlxArray, g: MlxArray, beta: MlxArray, stateIn: MlxArray, mask: MlxArray | null,
165
+ ): [MlxArray, MlxArray] {
166
+ const [B, T, Hk, Dk] = q.shape as [number, number, number, number];
167
+ const [, , Hv, Dv] = v.shape as [number, number, number, number];
168
+ const tArr = MlxArray.fromInt32(new Int32Array([T]), [1]);
169
+ const inputs = [q, k, v, g, beta, stateIn, tArr];
170
+ if (mask) inputs.push(mask);
171
+ const [y, stateOut] = getKernel(mask !== null).apply(inputs, {
172
+ outputs: [
173
+ { shape: [B, T, Hv, Dv], dtype: q.dtype },
174
+ { shape: [B, Hv, Dv, Dk], dtype: Dtype.float32 },
175
+ ],
176
+ grid: [32, Dv, B * Hv],
177
+ threadGroup: [32, 4, 1],
178
+ templateInts: { Dk, Dv, Hk, Hv },
179
+ templateDtypes: { InT: q.dtype, StT: Dtype.float32 },
180
+ });
181
+ tArr.dispose();
182
+ return [y!, stateOut!];
183
+ }
184
+
185
+ /** [B, T, Hk, D] in any float dtype -> float32 [B, T, Hv, D], head hv reading
186
+ * key head hv / (Hv / Hk): the kernel's GQA mapping. */
187
+ function float32PerValueHead(x: MlxArray, Hv: number): MlxArray {
188
+ const [B, T, Hk, D] = x.shape as [number, number, number, number];
189
+ using wide = x.astype(Dtype.float32);
190
+ using expanded = ops.expandDims(wide, 3);
191
+ using tiled = ops.broadcastTo(expanded, [B, T, Hk, Hv / Hk, D]);
192
+ return ops.reshape(tiled, [B, T, Hv, D]);
193
+ }
194
+
195
+ /** Position `t` of `x` [B, T, ...] with the T axis dropped. */
196
+ function atPosition(x: MlxArray, t: number): MlxArray {
197
+ const start = x.shape.map((_, axis) => (axis === 1 ? t : 0));
198
+ const stop = x.shape.map((size, axis) => (axis === 1 ? t + 1 : size));
199
+ using view = x.slice(start, stop);
200
+ return ops.reshape(view, x.shape.filter((_, axis) => axis !== 1));
201
+ }
202
+
203
+ /** The kernel's recurrence written in differentiable ops, float32 throughout
204
+ * like the kernel (mlx-lm's `gated_delta_ops`, with the state kept in float32).
205
+ * primals = [q, k, v, g, beta, state]; returns [y (q dtype), state (f32)].
206
+ * Only the training backward runs it (forward values come from the kernel). */
207
+ function recurrenceOps(primals: MlxArray[]): MlxArray[] {
208
+ const [q, k, v, g, beta, state0] = primals as [MlxArray, MlxArray, MlxArray, MlxArray, MlxArray, MlxArray];
209
+ const Hv = v.shape[2]!;
210
+ const T = q.shape[1]!;
211
+ using q32 = float32PerValueHead(q, Hv);
212
+ using k32 = float32PerValueHead(k, Hv);
213
+ using v32 = v.astype(Dtype.float32);
214
+ using beta32 = beta.astype(Dtype.float32);
215
+ let state = state0.astype(Dtype.float32);
216
+ const ys: MlxArray[] = [];
217
+ try {
218
+ for (let t = 0; t < T; t++) {
219
+ using qt = atPosition(q32, t); // [B, Hv, Dk]
220
+ using kt = atPosition(k32, t);
221
+ using vt = atPosition(v32, t); // [B, Hv, Dv]
222
+ using bt = atPosition(beta32, t); // [B, Hv]
223
+ using gt = atPosition(g, t);
224
+ using kRow = ops.expandDims(kt, 2); // [B, Hv, 1, Dk]
225
+ using qRow = ops.expandDims(qt, 2);
226
+ using decay = ops.reshape(gt, [...gt.shape, 1, 1]);
227
+ using decayed = ops.mul(state, decay);
228
+ using kvProduct = ops.mul(decayed, kRow);
229
+ using kvMem = ops.sumAxis(kvProduct, -1, false); // [B, Hv, Dv]
230
+ using residual = ops.sub(vt, kvMem);
231
+ using betaCol = ops.expandDims(bt, 2);
232
+ using delta = ops.mul(residual, betaCol);
233
+ using deltaCol = ops.expandDims(delta, 3); // [B, Hv, Dv, 1]
234
+ using update = ops.mul(kRow, deltaCol);
235
+ const next = ops.add(decayed, update);
236
+ state.dispose();
237
+ state = next;
238
+ using readout = ops.mul(state, qRow);
239
+ ys.push(ops.sumAxis(readout, -1, false));
240
+ }
241
+ using stacked = ops.stackAxis(ys, 1); // [B, T, Hv, Dv]
242
+ return [stacked.astype(q.dtype), state];
243
+ } catch (error) {
244
+ state.dispose();
245
+ throw error;
246
+ } finally {
247
+ for (const y of ys) y.dispose();
248
+ }
249
+ }
250
+
251
+ // Forward = the kernel above, so a training forward is bit-identical to an
252
+ // inference forward. The kernel is a CustomKernel with no vjp, so the backward
253
+ // recomputes the recurrence in `recurrenceOps` and differentiates that.
254
+ // Module-cached (never disposed): the closures read every shape from their
255
+ // arguments and must outlive each value_and_grad apply.
256
+ let differentiableRecurrence: CustomVjp | null = null;
257
+ function getDifferentiableRecurrence(): CustomVjp {
258
+ return differentiableRecurrence ??= new CustomVjp(
259
+ ([q, k, v, g, beta, state]) => launchRecurrence(q!, k!, v!, g!, beta!, state!, null),
260
+ (primals, cotangents) => {
261
+ const backward = new Vjp(recurrenceOps, 2);
262
+ try {
263
+ const { outputs, vjps } = backward.apply(primals, cotangents);
264
+ for (const output of outputs) output.dispose();
265
+ return vjps;
266
+ } finally {
267
+ backward.dispose();
268
+ }
269
+ },
270
+ );
271
+ }
272
+
273
+ /** gated_delta_update (use_kernel path): returns [y, newState].
274
+ * q, k: [B, S, Hk, Dk] bf16 v: [B, S, Hv, Dv] bf16
275
+ * a, b: [B, S, Hv] bf16 aLog, dtBias: [Hv]
276
+ * state: [B, Hv, Dv, Dk] f32 (or null → zeros)
277
+ * `differentiable` (unpadded training forwards) returns the same values and
278
+ * attaches a backward, so an enclosing value_and_grad can differentiate
279
+ * through the recurrence with respect to q, k, v, a, b and the state. */
280
+ export function gatedDeltaUpdate(
281
+ q: MlxArray, k: MlxArray, v: MlxArray, a: MlxArray, b: MlxArray,
282
+ aLog: MlxArray, dtBias: MlxArray, state: MlxArray | null, mask: MlxArray | null = null,
283
+ differentiable = false,
284
+ ): [MlxArray, MlxArray] {
285
+ if (differentiable && mask) throw new Error("gatedDeltaUpdate: the differentiable recurrence takes no padding mask");
286
+ const [B, , Hk, Dk] = q.shape as [number, number, number, number];
287
+ const [, , Hv, Dv] = v.shape as [number, number, number, number];
288
+
289
+ const beta = ops.sigmoid(b); // bf16
290
+ const g = computeG(aLog, a, dtBias); // f32
291
+
292
+ let stateIn = state;
293
+ let ownState = false;
294
+ if (!stateIn) {
295
+ stateIn = ops.zeros([B, Hv, Dv, Dk], Dtype.float32);
296
+ ownState = true;
297
+ }
298
+
299
+ const [y, stateOut] = differentiable
300
+ ? getDifferentiableRecurrence().apply([q, k, v, g, beta, stateIn]) as [MlxArray, MlxArray]
301
+ : launchRecurrence(q, k, v, g, beta, stateIn, mask);
302
+ beta.dispose();
303
+ g.dispose();
304
+ if (ownState) stateIn.dispose();
305
+ return [y, stateOut];
306
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./gated";
2
+ export * from "./state";
3
+ export * from "./silu-rms-heads";
@@ -0,0 +1,69 @@
1
+ // Copyright © 2024 Apple Inc. RMS reduction adapted under the MIT license;
2
+ // see THIRD_PARTY_NOTICES.md.
3
+ import type { MlxArray } from "@mlx-bun/mlx/array";
4
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
5
+
6
+ // The convolution's compiled SiLU, then MLX's four-reads RMS reduction for
7
+ // Q/K heads of up to 128 values. Keep the activation in registers and write V directly:
8
+ // no full activated convolution tensor or strided split views are needed.
9
+ // Sigmoid, SiLU, normalization, and scaling each retain their dtype rounding.
10
+ const SOURCE = String.raw`
11
+ const uint lane = thread_index_in_simdgroup;
12
+ const uint head = threadgroup_position_in_grid.x;
13
+ const uint row = threadgroup_position_in_grid.y;
14
+ const bool normalize = head < uint(2 * HK);
15
+ const uint width = normalize ? uint(DK) : uint(DV);
16
+ const uint channel = normalize ? head * uint(DK)
17
+ : uint(2 * HK * DK) + (head - uint(2 * HK)) * uint(DV);
18
+ T values[4];
19
+ float sum = 0.0f;
20
+ for (uint i = 0; i < 4u; ++i) {
21
+ const uint col = lane * 4u + i;
22
+ const T value = col < width ? x[row * uint(C) + channel + col] : T(0);
23
+ const auto y = 1 / (1 + metal::exp(metal::abs(value)));
24
+ const T sigmoid = T(value < T(0) ? y : 1 - y);
25
+ values[i] = T(value * sigmoid);
26
+ const float activated = float(values[i]);
27
+ sum += activated * activated;
28
+ }
29
+ if (normalize) {
30
+ sum = metal::simd_sum(sum);
31
+ const float inv = metal::precise::rsqrt(sum / float(DK) + 1e-6f);
32
+ const uint index = (row * uint(HK) + head % uint(HK)) * uint(DK) + lane * 4u;
33
+ for (uint i = 0; i < 4u; ++i) {
34
+ if (lane * 4u + i >= uint(DK)) continue;
35
+ const T normalized = T(float(values[i]) * inv);
36
+ if (head < uint(HK)) q[index + i] = qscale[lane * 4u + i] * normalized;
37
+ else k[index + i] = kscale[lane * 4u + i] * normalized;
38
+ }
39
+ } else {
40
+ const uint index = (row * uint(HV) + head - uint(2 * HK)) * uint(DV) + lane * 4u;
41
+ for (uint i = 0; i < 4u; ++i) if (lane * 4u + i < uint(DV)) v[index + i] = values[i];
42
+ }
43
+ `;
44
+
45
+ let kernel: MetalKernel | undefined;
46
+
47
+ /** Convolved [B,S,2*Hk*Dk+Hv*Dv] to owned Q, K, V heads, Dk/Dv <=128.
48
+ * Scale vectors have Dk entries in the input dtype, as MLX's RMS weights do. */
49
+ export function siluRmsHeads(x: MlxArray, qScale: MlxArray, kScale: MlxArray,
50
+ keyHeads: number, valueHeads: number, valueWidth: number): [MlxArray, MlxArray, MlxArray] {
51
+ const [batch, sequence, channels] = x.shape;
52
+ const keyWidth = qScale.size;
53
+ if (x.ndim !== 3 || channels !== 2 * keyHeads * keyWidth + valueHeads * valueWidth ||
54
+ keyWidth < 1 || keyWidth > 128 || valueWidth < 1 || valueWidth > 128 ||
55
+ qScale.ndim !== 1 || kScale.ndim !== 1 || kScale.size !== keyWidth ||
56
+ qScale.dtype !== x.dtype || kScale.dtype !== x.dtype)
57
+ throw new Error("siluRmsHeads: expects heads of up to 128 values and matching scale vectors");
58
+ kernel ??= new MetalKernel({ name: "mlx_bun_silu_rms_heads", inputNames: ["x", "qscale", "kscale"],
59
+ outputNames: ["q", "k", "v"], source: SOURCE });
60
+ return kernel.apply([x, qScale, kScale], {
61
+ outputs: [
62
+ { shape: [batch!, sequence!, keyHeads, keyWidth], dtype: x.dtype },
63
+ { shape: [batch!, sequence!, keyHeads, keyWidth], dtype: x.dtype },
64
+ { shape: [batch!, sequence!, valueHeads, valueWidth], dtype: x.dtype },
65
+ ],
66
+ grid: [32 * (2 * keyHeads + valueHeads), batch! * sequence!, 1], threadGroup: [32, 1, 1],
67
+ templateDtypes: { T: x.dtype }, templateInts: { C: channels!, HK: keyHeads, HV: valueHeads, DK: keyWidth, DV: valueWidth },
68
+ }) as [MlxArray, MlxArray, MlxArray];
69
+ }
@@ -0,0 +1,74 @@
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 * as ops from "@mlx-bun/mlx/ops";
5
+ import { computeG } from "./gated";
6
+
7
+ // The same recurrent arithmetic as gated_delta_step, with no query/output
8
+ // calculation. Each row replays only its retained prefix of the verify window.
9
+ const SOURCE = String.raw`
10
+ const int T = Tin[0];
11
+ auto n = thread_position_in_grid.z;
12
+ auto b_idx = n / Hv;
13
+ auto hv_idx = n % Hv;
14
+ auto hk_idx = hv_idx / (Hv / Hk);
15
+ constexpr int n_per_t = Dk / 32;
16
+ auto dk_idx = thread_position_in_threadgroup.x;
17
+ auto dv_idx = thread_position_in_grid.y;
18
+ auto k_ = k + b_idx * T * Hk * Dk + hk_idx * Dk;
19
+ auto v_ = v + b_idx * T * Hv * Dv + hv_idx * Dv;
20
+ auto g_ = g + b_idx * T * Hv;
21
+ auto beta_ = beta + b_idx * T * Hv;
22
+ auto i_state = state_in + (n * Dv + dv_idx) * Dk;
23
+ auto o_state = state_out + (n * Dv + dv_idx) * Dk;
24
+ float state[n_per_t];
25
+ for (int i = 0; i < n_per_t; ++i)
26
+ state[i] = static_cast<float>(i_state[n_per_t * dk_idx + i]);
27
+ const int keep = lengths[b_idx];
28
+ for (int t = 0; t < keep; ++t) {
29
+ float kv_mem = 0.0f;
30
+ for (int i = 0; i < n_per_t; ++i) {
31
+ auto s_idx = n_per_t * dk_idx + i;
32
+ state[i] = state[i] * g_[hv_idx];
33
+ kv_mem += state[i] * k_[s_idx];
34
+ }
35
+ kv_mem = simd_sum(kv_mem);
36
+ auto delta = (v_[dv_idx] - kv_mem) * beta_[hv_idx];
37
+ for (int i = 0; i < n_per_t; ++i) {
38
+ auto s_idx = n_per_t * dk_idx + i;
39
+ state[i] = state[i] + k_[s_idx] * delta;
40
+ }
41
+ k_ += Hk * Dk;
42
+ v_ += Hv * Dv;
43
+ g_ += Hv;
44
+ beta_ += Hv;
45
+ }
46
+ for (int i = 0; i < n_per_t; ++i)
47
+ o_state[n_per_t * dk_idx + i] = state[i];
48
+ `;
49
+
50
+ let kernel: MetalKernel | undefined;
51
+
52
+ /** State-only prefix replay. Inputs keep their original [B,T,...] strides;
53
+ * lengths are request-owned accepted counts, never scheduling decisions. */
54
+ export function gatedDeltaState(
55
+ k: MlxArray, v: MlxArray, a: MlxArray, b: MlxArray,
56
+ aLog: MlxArray, dtBias: MlxArray, state: MlxArray | null,
57
+ lengths: readonly number[],
58
+ ): MlxArray {
59
+ const [B, T, Hk, Dk] = k.shape as [number, number, number, number];
60
+ const [, , Hv, Dv] = v.shape as [number, number, number, number];
61
+ using beta = ops.sigmoid(b);
62
+ using g = computeG(aLog, a, dtBias);
63
+ using zero = state ? null : ops.zeros([B, Hv, Dv, Dk], Dtype.float32);
64
+ using t = ops.fromInt32([T], [1]);
65
+ using kept = ops.fromInt32([...lengths], [B]);
66
+ kernel ??= new MetalKernel({ name: "gated_delta_prefix_state",
67
+ inputNames: ["k", "v", "g", "beta", "state_in", "Tin", "lengths"],
68
+ outputNames: ["state_out"], source: SOURCE, ensureRowContiguous: true });
69
+ return kernel.apply([k, v, g, beta, state ?? zero!, t, kept], {
70
+ outputs: [{ shape: [B, Hv, Dv, Dk], dtype: Dtype.float32 }],
71
+ grid: [32, Dv, B * Hv], threadGroup: [32, 4, 1],
72
+ templateInts: { Dk, Dv, Hk, Hv },
73
+ })[0]!;
74
+ }
@@ -0,0 +1,64 @@
1
+ // Copyright © 2024 Apple Inc. RMS reduction adapted under the MIT license;
2
+ // see THIRD_PARTY_NOTICES.md.
3
+ import type { MlxArray } from "@mlx-bun/mlx/array";
4
+ import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
5
+
6
+ // MLX 0.32.2's four-value RMS reduction, followed by the float32 SiLU
7
+ // gate used by Qwen's RMSNormGated. The bf16 normalization rounding stays.
8
+ const SOURCE = String.raw`
9
+ const uint row = threadgroup_position_in_grid.x;
10
+ const uint lane = thread_index_in_simdgroup;
11
+ float acc = 0.0f;
12
+ const uint tid = thread_position_in_threadgroup.x;
13
+ threadgroup float sums[32];
14
+ threadgroup float inverse[1];
15
+ for (uint r = 0; r < uint(D); r += uint(THREADS) * 4u) {
16
+ for (uint i = 0; i < 4u; ++i) {
17
+ const uint col = r + tid * 4u + i;
18
+ const float value = col < uint(D) ? float(x[row * uint(D) + col]) : 0.0f;
19
+ acc += value * value;
20
+ }
21
+ }
22
+ acc = metal::simd_sum(acc);
23
+ if (THREADS > 32) {
24
+ const uint sg = simdgroup_index_in_threadgroup;
25
+ if (sg == 0) sums[lane] = 0.0f;
26
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
27
+ if (lane == 0) sums[sg] = acc;
28
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
29
+ if (sg == 0) {
30
+ acc = metal::simd_sum(sums[lane]);
31
+ if (lane == 0) inverse[0] = metal::precise::rsqrt(acc / float(D) + as_type<float>(uint(EPS)));
32
+ }
33
+ threadgroup_barrier(metal::mem_flags::mem_threadgroup);
34
+ }
35
+ const float inv = THREADS > 32 ? inverse[0]
36
+ : metal::precise::rsqrt(acc / float(D) + as_type<float>(uint(EPS)));
37
+ for (uint r = 0; r < uint(D); r += uint(THREADS) * 4u) {
38
+ for (uint i = 0; i < 4u; ++i) {
39
+ const uint col = r + tid * 4u + i, index = row * uint(D) + col;
40
+ if (col >= uint(D)) continue;
41
+ const T normalized = weight[col] * T(float(x[index]) * inv);
42
+ const float g = float(gate[index]);
43
+ const float y = 1.0f / (1.0f + metal::exp(metal::abs(g)));
44
+ const float sigmoid = g < 0.0f ? y : 1.0f - y;
45
+ out[index] = T((g * sigmoid) * float(normalized));
46
+ }
47
+ }
48
+ `;
49
+
50
+ let kernel: MetalKernel | undefined;
51
+
52
+ /** Equal-shaped row-contiguous inputs and a vector
53
+ * weight in the input dtype. Returns an owned gated normalization. */
54
+ export function gatedRmsNorm(x: MlxArray, gate: MlxArray, weight: MlxArray, eps: number): MlxArray {
55
+ const shape = x.shape, width = shape.at(-1)!;
56
+ const threads = Math.min(1024, Math.ceil(width / 128) * 32);
57
+ const epsBits = new Uint32Array(new Float32Array([eps]).buffer)[0]!;
58
+ kernel ??= new MetalKernel({ name: "mlx_bun_gated_rms_norm", inputNames: ["x", "gate", "weight"],
59
+ outputNames: ["out"], source: SOURCE });
60
+ return kernel.apply([x, gate, weight], {
61
+ outputs: [{ shape, dtype: x.dtype }], grid: [x.size / width * threads, 1, 1], threadGroup: [threads, 1, 1],
62
+ templateDtypes: { T: x.dtype }, templateInts: { D: width, THREADS: threads, EPS: epsBits },
63
+ })[0]!;
64
+ }
@@ -0,0 +1,37 @@
1
+
2
+
3
+ /**
4
+ * The subset of the canonical expert-slot layout consumed by the decode
5
+ * kernels. Offsets are bytes from the beginning of one aligned residency slot.
6
+ * Q4 (packed nibbles) and Q8 (int8) slots share this shape.
7
+ */
8
+ export interface Glm52CanonicalMetalLayout {
9
+ readonly hiddenSize: number;
10
+ readonly intermediateSize: number;
11
+ readonly slotBytes: number;
12
+ readonly downWeightOffset: number;
13
+ readonly gateWeightOffset: number;
14
+ readonly upWeightOffset: number;
15
+ readonly downScaleOffset: number;
16
+ readonly gateScaleOffset: number;
17
+ readonly upScaleOffset: number;
18
+ }
19
+
20
+ export type Glm52CanonicalQ4MetalLayout = Glm52CanonicalMetalLayout;
21
+ export type Glm52CanonicalQ8MetalLayout = Glm52CanonicalMetalLayout;
22
+
23
+ export function validateRange(
24
+ offset: number,
25
+ byteLength: number,
26
+ slotBytes: number,
27
+ label: string,
28
+ ): void {
29
+ if (!Number.isSafeInteger(offset) || offset < 0)
30
+ throw new Error(`${label} offset must be a non-negative safe integer`);
31
+ if (!Number.isSafeInteger(byteLength) || byteLength < 0)
32
+ throw new Error(`${label} length must be a non-negative safe integer`);
33
+ if (offset + byteLength > slotBytes)
34
+ throw new Error(`${label} exceeds the canonical expert slot`);
35
+ }
36
+
37
+ export const GLM52_EXPERT_SLOT_ALIGNMENT = 16 * 1024;