@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,445 @@
1
+ // Pure, allocation-bounded reference arithmetic for the Colibri GLM-5.2 port.
2
+ //
3
+ // This module deliberately contains no model graph, storage policy, or MLX
4
+ // ownership. It is the executable numeric contract used by fixtures and by
5
+ // optimized implementations while those implementations are brought up.
6
+
7
+ export type NumericVector = ArrayLike<number>;
8
+ export type OutputMajorMatrix = ReadonlyArray<NumericVector>;
9
+
10
+ export interface Int8PerRowMatrix {
11
+ readonly outputRows: number;
12
+ readonly inputColumns: number;
13
+ readonly qbytes: NumericVector;
14
+ readonly scales: NumericVector;
15
+ }
16
+
17
+ export interface Int4Matrix {
18
+ readonly outputRows: number;
19
+ readonly inputColumns: number;
20
+ readonly qbytes: NumericVector;
21
+ readonly scales: NumericVector;
22
+ /** null means one scale per output row. */
23
+ readonly groupSize: number | null;
24
+ }
25
+
26
+ export interface Glm52Route {
27
+ readonly rawSigmoidScores: Float32Array;
28
+ readonly selectionScores: Float32Array;
29
+ readonly indices: number[];
30
+ readonly executionWeights: Float32Array;
31
+ }
32
+
33
+ export interface SwiGluWeights {
34
+ readonly gate: OutputMajorMatrix;
35
+ readonly up: OutputMajorMatrix;
36
+ readonly down: OutputMajorMatrix;
37
+ }
38
+
39
+ export interface RoutedSwiGluContribution {
40
+ readonly expert: SwiGluWeights;
41
+ readonly weight: number;
42
+ }
43
+
44
+ export interface DsaSelection {
45
+ readonly threshold: number;
46
+ readonly selected: number[];
47
+ }
48
+
49
+ function f32(value: number): number {
50
+ return Math.fround(value);
51
+ }
52
+
53
+ function integer(value: number, label: string, minimum = 1): number {
54
+ if (!Number.isSafeInteger(value) || value < minimum)
55
+ throw new Error(`${label} must be an integer >= ${minimum}`);
56
+ return value;
57
+ }
58
+
59
+ function vectorLength(vector: NumericVector, expected: number, label: string): void {
60
+ if (vector.length !== expected)
61
+ throw new Error(`${label} length ${vector.length} != ${expected}`);
62
+ }
63
+
64
+ function finite(value: number, label: string): number {
65
+ if (!Number.isFinite(value)) throw new Error(`${label} must be finite`);
66
+ return value;
67
+ }
68
+
69
+ function byteAt(bytes: NumericVector, index: number): number {
70
+ const value = bytes[index]!;
71
+ if (!Number.isInteger(value) || value < 0 || value > 255)
72
+ throw new Error(`quantized byte ${index} is outside uint8`);
73
+ return value;
74
+ }
75
+
76
+ function signedInt8(byte: number): number {
77
+ return byte < 128 ? byte : byte - 256;
78
+ }
79
+
80
+ function validateInt8(matrix: Int8PerRowMatrix): void {
81
+ const rows = integer(matrix.outputRows, "outputRows");
82
+ const columns = integer(matrix.inputColumns, "inputColumns");
83
+ vectorLength(matrix.qbytes, rows * columns, "int8 qbytes");
84
+ vectorLength(matrix.scales, rows, "int8 scales");
85
+ }
86
+
87
+ function int4Groups(matrix: Int4Matrix): number {
88
+ if (matrix.groupSize === null) return 1;
89
+ const groupSize = integer(matrix.groupSize, "groupSize");
90
+ return Math.ceil(matrix.inputColumns / groupSize);
91
+ }
92
+
93
+ function validateInt4(matrix: Int4Matrix): number {
94
+ const rows = integer(matrix.outputRows, "outputRows");
95
+ const columns = integer(matrix.inputColumns, "inputColumns");
96
+ const rowBytes = Math.ceil(columns / 2);
97
+ const groups = int4Groups(matrix);
98
+ vectorLength(matrix.qbytes, rows * rowBytes, "int4 qbytes");
99
+ vectorLength(matrix.scales, rows * groups, "int4 scales");
100
+ return groups;
101
+ }
102
+
103
+ function int4Value(matrix: Int4Matrix, output: number, input: number): number {
104
+ const rowBytes = Math.ceil(matrix.inputColumns / 2);
105
+ const byte = byteAt(matrix.qbytes, output * rowBytes + (input >> 1));
106
+ return ((input & 1) === 0 ? byte & 0x0f : byte >> 4) - 8;
107
+ }
108
+
109
+ function inputRows(inputs: ReadonlyArray<NumericVector>, columns: number): void {
110
+ for (let row = 0; row < inputs.length; row++)
111
+ vectorLength(inputs[row]!, columns, `input row ${row}`);
112
+ }
113
+
114
+ /** Expand signed int8 bytes using one float32 scale per output row. */
115
+ export function dequantizeInt8PerRowF32(matrix: Int8PerRowMatrix): Float32Array {
116
+ validateInt8(matrix);
117
+ const out = new Float32Array(matrix.outputRows * matrix.inputColumns);
118
+ for (let output = 0; output < matrix.outputRows; output++) {
119
+ const scale = finite(matrix.scales[output]!, `int8 scale ${output}`);
120
+ for (let input = 0; input < matrix.inputColumns; input++) {
121
+ const offset = output * matrix.inputColumns + input;
122
+ out[offset] = f32(signedInt8(byteAt(matrix.qbytes, offset)) * scale);
123
+ }
124
+ }
125
+ return out;
126
+ }
127
+
128
+ /**
129
+ * Colibri int8 matmul: accumulate x*q in float32 and apply the row scale once
130
+ * after the dot product. Weight storage is output-major [O,I].
131
+ */
132
+ export function matmulInt8PerRowF32(
133
+ inputs: ReadonlyArray<NumericVector>,
134
+ matrix: Int8PerRowMatrix,
135
+ ): Float32Array[] {
136
+ validateInt8(matrix);
137
+ inputRows(inputs, matrix.inputColumns);
138
+ return inputs.map((input) => {
139
+ const out = new Float32Array(matrix.outputRows);
140
+ for (let output = 0; output < matrix.outputRows; output++) {
141
+ let accumulator = f32(0);
142
+ const base = output * matrix.inputColumns;
143
+ for (let column = 0; column < matrix.inputColumns; column++) {
144
+ const quantized = signedInt8(byteAt(matrix.qbytes, base + column));
145
+ accumulator = f32(accumulator + f32(input[column]! * quantized));
146
+ }
147
+ out[output] = f32(accumulator * finite(matrix.scales[output]!, `int8 scale ${output}`));
148
+ }
149
+ return out;
150
+ });
151
+ }
152
+
153
+ /**
154
+ * Expand Colibri offset-binary int4. Low nibble is the even input column,
155
+ * high nibble the odd column. Scales are output-major, then input-group-major.
156
+ */
157
+ export function dequantizeInt4F32(matrix: Int4Matrix): Float32Array {
158
+ const groups = validateInt4(matrix);
159
+ const out = new Float32Array(matrix.outputRows * matrix.inputColumns);
160
+ for (let output = 0; output < matrix.outputRows; output++) {
161
+ for (let input = 0; input < matrix.inputColumns; input++) {
162
+ const group = matrix.groupSize === null ? 0 : Math.floor(input / matrix.groupSize);
163
+ const scale = finite(matrix.scales[output * groups + group]!, `int4 scale ${output}:${group}`);
164
+ out[output * matrix.inputColumns + input] = f32(int4Value(matrix, output, input) * scale);
165
+ }
166
+ }
167
+ return out;
168
+ }
169
+
170
+ /**
171
+ * Exact reference shape for both per-row and grouped int4. The grouped path
172
+ * applies each scale at its group boundary, matching Colibri rather than
173
+ * first expanding a second full-size float matrix.
174
+ */
175
+ export function matmulInt4F32(
176
+ inputs: ReadonlyArray<NumericVector>,
177
+ matrix: Int4Matrix,
178
+ ): Float32Array[] {
179
+ const groups = validateInt4(matrix);
180
+ inputRows(inputs, matrix.inputColumns);
181
+ const groupSize = matrix.groupSize ?? matrix.inputColumns;
182
+ return inputs.map((input) => {
183
+ const out = new Float32Array(matrix.outputRows);
184
+ for (let output = 0; output < matrix.outputRows; output++) {
185
+ let result = f32(0);
186
+ for (let group = 0; group < groups; group++) {
187
+ const start = group * groupSize;
188
+ const end = Math.min(start + groupSize, matrix.inputColumns);
189
+ let accumulator = f32(0);
190
+ for (let column = start; column < end; column++) {
191
+ accumulator = f32(
192
+ accumulator + f32(input[column]! * int4Value(matrix, output, column)),
193
+ );
194
+ }
195
+ const scale = finite(matrix.scales[output * groups + group]!, `int4 scale ${output}:${group}`);
196
+ result = f32(result + f32(accumulator * scale));
197
+ }
198
+ out[output] = result;
199
+ }
200
+ return out;
201
+ });
202
+ }
203
+
204
+ /** Output-major float32 matrix-vector multiply. */
205
+ export function matvecF32(input: NumericVector, weights: OutputMajorMatrix): Float32Array {
206
+ if (weights.length === 0) throw new Error("weights must contain an output row");
207
+ const columns = input.length;
208
+ integer(columns, "input length");
209
+ const out = new Float32Array(weights.length);
210
+ for (let output = 0; output < weights.length; output++) {
211
+ const row = weights[output]!;
212
+ vectorLength(row, columns, `weight row ${output}`);
213
+ let accumulator = f32(0);
214
+ for (let column = 0; column < columns; column++)
215
+ accumulator = f32(accumulator + f32(input[column]! * row[column]!));
216
+ out[output] = accumulator;
217
+ }
218
+ return out;
219
+ }
220
+
221
+ /** Colibri RMSNorm: weight is multiplicative, never `1 + weight`. */
222
+ export function rmsNormF32(
223
+ input: NumericVector,
224
+ weight: NumericVector,
225
+ epsilon: number,
226
+ ): Float32Array {
227
+ integer(input.length, "input length");
228
+ vectorLength(weight, input.length, "RMSNorm weight");
229
+ finite(epsilon, "RMSNorm epsilon");
230
+ if (epsilon < 0) throw new Error("RMSNorm epsilon must be non-negative");
231
+ let sumSquares = 0;
232
+ for (let index = 0; index < input.length; index++) {
233
+ const value = finite(input[index]!, `RMSNorm input ${index}`);
234
+ sumSquares += value * value; // Colibri accumulates this reduction in double.
235
+ }
236
+ const denominator = f32(f32(sumSquares / input.length) + f32(epsilon));
237
+ const inverseRoot = f32(1 / f32(Math.sqrt(denominator)));
238
+ return Float32Array.from({ length: input.length }, (_, index) =>
239
+ f32(f32(input[index]! * inverseRoot) * weight[index]!),
240
+ );
241
+ }
242
+
243
+ /**
244
+ * GLM partial RoPE. The first `rotaryDimensions` values are pair-interleaved
245
+ * on input and split into real/imaginary halves on output; any tail is kept.
246
+ */
247
+ export function partialInterleavedRopeF32(
248
+ input: NumericVector,
249
+ position: number,
250
+ rotaryDimensions: number,
251
+ theta: number,
252
+ ): Float32Array {
253
+ integer(input.length, "input length");
254
+ integer(rotaryDimensions, "rotaryDimensions", 2);
255
+ if ((rotaryDimensions & 1) !== 0 || rotaryDimensions > input.length)
256
+ throw new Error("rotaryDimensions must be even and no larger than input");
257
+ if (!Number.isSafeInteger(position) || position < 0)
258
+ throw new Error("position must be a non-negative integer");
259
+ finite(theta, "RoPE theta");
260
+ if (theta <= 0) throw new Error("RoPE theta must be positive");
261
+
262
+ const source = Float32Array.from(input);
263
+ const out = Float32Array.from(source);
264
+ const half = rotaryDimensions / 2;
265
+ for (let pair = 0; pair < half; pair++) {
266
+ const exponent = f32(f32(-2 * pair) / rotaryDimensions);
267
+ const inverseFrequency = f32(Math.pow(f32(theta), exponent));
268
+ const angle = f32(position * inverseFrequency);
269
+ const cosine = f32(Math.cos(angle));
270
+ const sine = f32(Math.sin(angle));
271
+ const a = source[2 * pair]!;
272
+ const b = source[2 * pair + 1]!;
273
+ out[pair] = f32(f32(a * cosine) - f32(b * sine));
274
+ out[half + pair] = f32(f32(b * cosine) + f32(a * sine));
275
+ }
276
+ return out;
277
+ }
278
+
279
+ export function sigmoidF32(value: number): number {
280
+ const exponential = f32(Math.exp(f32(-finite(value, "sigmoid input"))));
281
+ return f32(1 / f32(1 + exponential));
282
+ }
283
+
284
+ /**
285
+ * Exact noaux_tc router contract: rank sigmoid(logit)+bias, but execute using
286
+ * the unbiased sigmoid values. Strict-greater scanning makes lower expert IDs
287
+ * win exact ties.
288
+ */
289
+ export function routeTrueTopKF32(
290
+ logits: NumericVector,
291
+ correctionBias: NumericVector,
292
+ topK: number,
293
+ normalize: boolean,
294
+ routedScale: number,
295
+ ): Glm52Route {
296
+ integer(logits.length, "expert count");
297
+ vectorLength(correctionBias, logits.length, "correction bias");
298
+ integer(topK, "topK");
299
+ if (topK > logits.length) throw new Error("topK exceeds expert count");
300
+ finite(routedScale, "routed scale");
301
+
302
+ const rawSigmoidScores = new Float32Array(logits.length);
303
+ const selectionScores = new Float32Array(logits.length);
304
+ for (let expert = 0; expert < logits.length; expert++) {
305
+ const raw = sigmoidF32(logits[expert]!);
306
+ rawSigmoidScores[expert] = raw;
307
+ selectionScores[expert] = f32(raw + finite(correctionBias[expert]!, `bias ${expert}`));
308
+ }
309
+
310
+ const indices: number[] = [];
311
+ const selected = new Uint8Array(logits.length);
312
+ while (indices.length < topK) {
313
+ let best = -1;
314
+ let bestScore = -1e30;
315
+ for (let expert = 0; expert < logits.length; expert++) {
316
+ if (selected[expert] === 0 && selectionScores[expert]! > bestScore) {
317
+ best = expert;
318
+ bestScore = selectionScores[expert]!;
319
+ }
320
+ }
321
+ if (best < 0) throw new Error("router found no selectable expert");
322
+ selected[best] = 1;
323
+ indices.push(best);
324
+ }
325
+
326
+ const executionWeights = new Float32Array(topK);
327
+ let sum = f32(0);
328
+ if (normalize) {
329
+ for (const expert of indices) sum = f32(sum + rawSigmoidScores[expert]!);
330
+ sum = f32(sum + f32(1e-20));
331
+ }
332
+ for (let rank = 0; rank < topK; rank++) {
333
+ const raw = rawSigmoidScores[indices[rank]!]!;
334
+ const weight = normalize ? f32(raw / sum) : raw;
335
+ executionWeights[rank] = f32(weight * routedScale);
336
+ }
337
+ return { rawSigmoidScores, selectionScores, indices, executionWeights };
338
+ }
339
+
340
+ function siluF32(value: number): number {
341
+ return f32(value / f32(1 + f32(Math.exp(f32(-value)))));
342
+ }
343
+
344
+ /** Reference `down(silu(gate(x))*up(x))`. */
345
+ export function swiGluF32(input: NumericVector, weights: SwiGluWeights): Float32Array {
346
+ const gate = matvecF32(input, weights.gate);
347
+ const up = matvecF32(input, weights.up);
348
+ if (gate.length !== up.length)
349
+ throw new Error(`SwiGLU gate rows ${gate.length} != up rows ${up.length}`);
350
+ const hidden = new Float32Array(gate.length);
351
+ for (let index = 0; index < hidden.length; index++)
352
+ hidden[index] = f32(siluF32(gate[index]!) * up[index]!);
353
+ const out = matvecF32(hidden, weights.down);
354
+ for (let row = 0; row < weights.down.length; row++)
355
+ vectorLength(weights.down[row]!, hidden.length, `SwiGLU down row ${row}`);
356
+ return out;
357
+ }
358
+
359
+ /**
360
+ * Accumulate routed experts in route order, then add the unweighted shared
361
+ * expert, matching Colibri's reference composition.
362
+ */
363
+ export function composeSharedRoutedSwiGluF32(
364
+ input: NumericVector,
365
+ routed: ReadonlyArray<RoutedSwiGluContribution>,
366
+ shared: SwiGluWeights | null,
367
+ ): Float32Array {
368
+ if (routed.length === 0 && shared === null)
369
+ throw new Error("MoE composition needs a routed or shared expert");
370
+ let out: Float32Array | null = null;
371
+ for (let route = 0; route < routed.length; route++) {
372
+ const contribution = routed[route]!;
373
+ const value = swiGluF32(input, contribution.expert);
374
+ finite(contribution.weight, `route weight ${route}`);
375
+ out ??= new Float32Array(value.length);
376
+ if (out.length !== value.length) throw new Error("routed expert output dimensions differ");
377
+ for (let index = 0; index < out.length; index++)
378
+ out[index] = f32(out[index]! + f32(contribution.weight * value[index]!));
379
+ }
380
+ if (shared !== null) {
381
+ const value = swiGluF32(input, shared);
382
+ out ??= new Float32Array(value.length);
383
+ if (out.length !== value.length) throw new Error("shared expert output dimension differs");
384
+ for (let index = 0; index < out.length; index++)
385
+ out[index] = f32(out[index]! + value[index]!);
386
+ }
387
+ return out!;
388
+ }
389
+
390
+ /**
391
+ * Select the keep-th threshold, then preserve Colibri's two scans: positions
392
+ * strictly above threshold first, threshold ties second.
393
+ */
394
+ export function selectDsaThresholdTiesF32(
395
+ scores: NumericVector,
396
+ keep: number,
397
+ ): DsaSelection {
398
+ integer(scores.length, "DSA score count");
399
+ integer(keep, "DSA keep");
400
+ if (keep > scores.length) throw new Error("DSA keep exceeds score count");
401
+ const values = Array.from(scores, (score, index) => finite(score, `DSA score ${index}`));
402
+ const threshold = values.slice().sort((a, b) => b - a)[keep - 1]!;
403
+ const selected: number[] = [];
404
+ for (let position = 0; position < values.length && selected.length < keep; position++)
405
+ if (values[position]! > threshold) selected.push(position);
406
+ for (let position = 0; position < values.length && selected.length < keep; position++)
407
+ if (values[position] === threshold) selected.push(position);
408
+ return { threshold, selected };
409
+ }
410
+
411
+ /**
412
+ * DSA scores from already-projected query heads, shared index keys, and head
413
+ * weights:
414
+ * score_t = 1/sqrt(H) Σ_h w_h ReLU((q_h · k_t)/sqrt(D)).
415
+ */
416
+ export function dsaScoresFromProjectedF32(
417
+ queryHeads: OutputMajorMatrix,
418
+ keys: OutputMajorMatrix,
419
+ headWeights: NumericVector,
420
+ ): Float32Array {
421
+ const heads = integer(queryHeads.length, "DSA head count");
422
+ vectorLength(headWeights, heads, "DSA head weights");
423
+ const headDimensions = integer(queryHeads[0]!.length, "DSA head dimensions");
424
+ for (let head = 0; head < heads; head++)
425
+ vectorLength(queryHeads[head]!, headDimensions, `DSA query head ${head}`);
426
+ const headScale = f32(1 / f32(Math.sqrt(f32(heads))));
427
+ const dimensionScale = f32(1 / f32(Math.sqrt(f32(headDimensions))));
428
+ const out = new Float32Array(keys.length);
429
+ for (let position = 0; position < keys.length; position++) {
430
+ const key = keys[position]!;
431
+ vectorLength(key, headDimensions, `DSA key ${position}`);
432
+ let score = f32(0);
433
+ for (let head = 0; head < heads; head++) {
434
+ const query = queryHeads[head]!;
435
+ let dot = f32(0);
436
+ for (let dimension = 0; dimension < headDimensions; dimension++)
437
+ dot = f32(dot + f32(query[dimension]! * key[dimension]!));
438
+ dot = f32(dot * dimensionScale);
439
+ if (dot > 0)
440
+ score = f32(score + f32(finite(headWeights[head]!, `DSA head weight ${head}`) * dot));
441
+ }
442
+ out[position] = f32(score * headScale);
443
+ }
444
+ return out;
445
+ }