mlx-bun 0.5.0 → 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 (640) hide show
  1. package/README.md +1449 -109
  2. package/THIRD_PARTY_NOTICES.md +882 -0
  3. package/bin/mlx-bun.convert.mjs +4 -0
  4. package/bin/mlx-bun.fuse.mjs +4 -0
  5. package/bin/mlx-bun.generate.mjs +4 -0
  6. package/bin/mlx-bun.lora.mjs +4 -0
  7. package/bin/mlx-bun.mjs +13 -21
  8. package/bin/mlx-bun.server.mjs +4 -0
  9. package/bin/mlx-bun.upload.mjs +4 -0
  10. package/dist/web/app.js +9584 -0
  11. package/package.json +50 -53
  12. package/src/cli/ane-install.ts +76 -0
  13. package/src/cli/args.ts +179 -0
  14. package/src/cli/engine-entry.ts +68 -0
  15. package/src/cli/inference.ts +214 -0
  16. package/src/cli/job-entry.ts +97 -0
  17. package/src/cli/library-host.ts +117 -0
  18. package/src/cli/main.ts +57 -0
  19. package/src/cli/memory-engine.ts +163 -0
  20. package/src/cli/memory.ts +36 -0
  21. package/src/cli/mlx-lm-aliases.ts +309 -0
  22. package/src/cli/model-choice.ts +33 -0
  23. package/src/cli/model-selection.ts +84 -0
  24. package/src/cli/module-host.ts +11 -0
  25. package/src/cli/module-verbs.ts +50 -0
  26. package/src/cli/numerical-policy.ts +12 -0
  27. package/src/cli/perplexity.ts +89 -0
  28. package/src/cli/serve-host.ts +423 -0
  29. package/src/cli/serve-isolated.ts +217 -0
  30. package/src/cli/serve-options.ts +106 -0
  31. package/src/cli/serve-state.ts +205 -0
  32. package/src/cli/serve.ts +500 -0
  33. package/src/cli/served-model-host.ts +102 -0
  34. package/src/cli/server-entry.ts +148 -0
  35. package/src/cli/serving-unit.ts +177 -0
  36. package/src/{tui.ts → cli/terminal.ts} +13 -8
  37. package/src/cli/worker-adapters.ts +34 -0
  38. package/src/cli/worker-entry.ts +272 -0
  39. package/src/cli/worker-unit.ts +179 -0
  40. package/src/engine/adapter-operation.ts +26 -0
  41. package/src/engine/cache-services.ts +114 -0
  42. package/src/engine/completion.ts +39 -0
  43. package/src/engine/generation-gateway.ts +358 -0
  44. package/src/engine/index.ts +59 -0
  45. package/src/engine/kv-budget.ts +120 -0
  46. package/src/engine/media-preparation.ts +232 -0
  47. package/src/engine/model-binding.ts +24 -0
  48. package/src/engine/model-host.ts +513 -0
  49. package/src/engine/model-serving.ts +89 -0
  50. package/src/{serve → engine}/preparation.ts +7 -5
  51. package/src/{serve → engine}/session-completion-engine.ts +6 -6
  52. package/src/engine/telemetry.ts +109 -0
  53. package/src/hub/downloads.ts +116 -0
  54. package/src/jobs/db.ts +16 -7
  55. package/src/jobs/events.ts +29 -0
  56. package/src/jobs/executable.ts +5 -0
  57. package/src/jobs/host.ts +51 -0
  58. package/src/jobs/in-process.ts +55 -0
  59. package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
  60. package/src/jobs/runner.ts +150 -231
  61. package/src/jobs/service.ts +75 -0
  62. package/src/jobs/sse.ts +59 -23
  63. package/src/jobs/worker-memory.ts +46 -0
  64. package/src/jobs/worker-process.ts +163 -0
  65. package/src/jobs/worker-supervisor.ts +258 -0
  66. package/src/modules.ts +58 -0
  67. package/src/publishing/catalog-hub.ts +18 -0
  68. package/src/publishing/credentials.ts +31 -0
  69. package/src/publishing/upload.ts +37 -0
  70. package/src/residency/leased-adapters.ts +21 -0
  71. package/src/residency/local-records.ts +16 -0
  72. package/src/residency/model-residency.ts +405 -0
  73. package/src/residency/record-index.ts +28 -0
  74. package/src/residency/resident-estimate.ts +50 -0
  75. package/src/{anthropic.ts → server/anthropic.ts} +3 -81
  76. package/src/server/cache-routes.ts +36 -0
  77. package/src/{serve → server}/chat-request.ts +10 -10
  78. package/src/{serve → server}/chat-stage.ts +14 -14
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +33 -41
  81. package/src/server/decision-body.ts +55 -0
  82. package/src/server/decision-routes.ts +134 -0
  83. package/src/server/decision-wire.ts +228 -0
  84. package/src/{serve → server}/discovery-routes.ts +25 -82
  85. package/src/{serve → server}/http.ts +25 -13
  86. package/src/{serve → server}/inference-request.ts +5 -5
  87. package/src/server/job-routes.ts +20 -0
  88. package/src/server/media-prompt.ts +63 -0
  89. package/src/server/memory-completion-client.ts +46 -0
  90. package/src/server/model-routes.ts +192 -0
  91. package/src/{serve → server}/openai-wire.ts +3 -2
  92. package/src/{serve → server}/pipeline.ts +1 -1
  93. package/src/server/prompt-builder.ts +13 -0
  94. package/src/server/prompt-contracts.ts +17 -0
  95. package/src/server/proxy-routes.ts +187 -0
  96. package/src/server/publishing-routes.ts +41 -0
  97. package/src/{serve → server}/request-plan.ts +6 -8
  98. package/src/{serve → server}/request-prep.ts +47 -50
  99. package/src/{serve → server}/responses-client.ts +30 -13
  100. package/src/{responses.ts → server/responses.ts} +12 -93
  101. package/src/server/routes.ts +205 -0
  102. package/src/server/start.ts +72 -0
  103. package/src/server/status-routes.ts +108 -0
  104. package/src/{serve → server}/text-completion-stage.ts +25 -4
  105. package/src/server/text-prompt.ts +12 -0
  106. package/src/{serve → server}/token-streams.ts +36 -38
  107. package/src/server/worker-routes.ts +311 -0
  108. package/src/storage/paths.ts +61 -0
  109. package/src/web/assets.ts +37 -0
  110. package/src/web/{src → browser}/api.ts +5 -23
  111. package/src/web/browser/chat-host.ts +17 -0
  112. package/src/web/browser/installed-panels.ts +6 -0
  113. package/src/web/browser/main.ts +55 -0
  114. package/src/web/browser/markdown.ts +279 -0
  115. package/src/web/browser/memory-panel.ts +9 -0
  116. package/src/web/browser/palette.ts +64 -0
  117. package/src/web/browser/protocol.ts +13 -0
  118. package/src/web/browser/shell.ts +467 -0
  119. package/src/web/{src → browser}/status.ts +32 -36
  120. package/src/web/build.ts +51 -0
  121. package/src/web/public/app.html +1054 -0
  122. package/src/web/{sw.js → public/sw.js} +4 -3
  123. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  124. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  125. package/THIRD_PARTY_LICENSES.md +0 -51
  126. package/docs/README.md +0 -107
  127. package/docs/archive/hlg-sampling.md +0 -350
  128. package/docs/archive/investigations/audio-input-plan.md +0 -356
  129. package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +0 -3617
  130. package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
  131. package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
  132. package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
  133. package/docs/archive/investigations/curve-bisector-routing.md +0 -123
  134. package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
  135. package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
  136. package/docs/archive/investigations/dspark-handoff.md +0 -224
  137. package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
  138. package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
  139. package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
  140. package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
  141. package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
  142. package/docs/archive/investigations/lab-build-journal.md +0 -157
  143. package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
  144. package/docs/archive/investigations/openjarvis-fit.md +0 -198
  145. package/docs/archive/investigations/openwiki-evaluation.md +0 -249
  146. package/docs/archive/investigations/optimization_plan.md +0 -346
  147. package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
  148. package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
  149. package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
  150. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
  151. package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
  152. package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
  153. package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
  154. package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
  155. package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
  156. package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
  157. package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
  158. package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
  159. package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
  160. package/docs/archive/planning/chat-ui-vision.md +0 -50
  161. package/docs/archive/planning/chunk-task-roadmap.md +0 -77
  162. package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
  163. package/docs/archive/planning/journal.md +0 -316
  164. package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
  165. package/docs/archive/planning/pi-integration-review.md +0 -178
  166. package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
  167. package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
  168. package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
  169. package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
  170. package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
  171. package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
  172. package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
  173. package/docs/archive/planning/release-notes-v0.4.0.md +0 -45
  174. package/docs/archive/planning/release-notes-v0.5.0.md +0 -37
  175. package/docs/archive/planning/web-ui-pass-plan.md +0 -213
  176. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  177. package/docs/design/batching.md +0 -2054
  178. package/docs/design/decode-speed-program.md +0 -2404
  179. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  180. package/docs/design/generic-model-support.md +0 -821
  181. package/docs/design/kv-cache.md +0 -993
  182. package/docs/design/orpo-training.md +0 -680
  183. package/docs/design/speculative-decoding.md +0 -2129
  184. package/docs/design/turboquant.md +0 -2225
  185. package/docs/design/unified-engine-frontier-plan.md +0 -1987
  186. package/docs/design/web-chat-redesign.md +0 -695
  187. package/docs/planning/PRODUCT_ROADMAP.md +0 -593
  188. package/docs/planning/ResearchTopics.md +0 -119
  189. package/docs/planning/public-readiness-handoff.md +0 -244
  190. package/docs/planning/public-readiness.md +0 -149
  191. package/docs/planning/video-series.md +0 -421
  192. package/docs/reference/benchmarks.md +0 -3587
  193. package/docs/reference/cli.md +0 -646
  194. package/docs/reference/distribution.md +0 -380
  195. package/docs/reference/environment.md +0 -494
  196. package/docs/reference/glossary.md +0 -39
  197. package/docs/reference/library-api.md +0 -688
  198. package/docs/reference/memory.md +0 -260
  199. package/docs/reference/models.md +0 -346
  200. package/docs/reference/server-api.md +0 -1945
  201. package/docs/reference/server-config.md +0 -973
  202. package/docs/reference/training.md +0 -462
  203. package/docs/reference/troubleshooting.md +0 -158
  204. package/src/admission-plan.ts +0 -18
  205. package/src/audio/audiotoolbox.ts +0 -112
  206. package/src/audio/conformer.ts +0 -655
  207. package/src/audio/decode.ts +0 -133
  208. package/src/audio/features.ts +0 -202
  209. package/src/audio/mic-capture.ts +0 -98
  210. package/src/audio/silero-vad.ts +0 -379
  211. package/src/audio/transcode.ts +0 -67
  212. package/src/audio/whisper-decode.ts +0 -774
  213. package/src/audio/whisper-fast.ts +0 -732
  214. package/src/audio/whisper-format.ts +0 -73
  215. package/src/audio/whisper-mel.ts +0 -185
  216. package/src/audio/whisper-timing.ts +0 -274
  217. package/src/audio/whisper-tokenizer.ts +0 -239
  218. package/src/audio/whisper-transcribe.ts +0 -410
  219. package/src/backends/mlx/assistant-target.ts +0 -46
  220. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  221. package/src/backends/mlx/autoregressive.ts +0 -129
  222. package/src/backends/mlx/batch-group.ts +0 -1874
  223. package/src/backends/mlx/cache-attachment.ts +0 -67
  224. package/src/backends/mlx/cache-layout.ts +0 -31
  225. package/src/backends/mlx/checkpoint-state.ts +0 -53
  226. package/src/backends/mlx/continuation-persistence.ts +0 -107
  227. package/src/backends/mlx/continuation-request.ts +0 -43
  228. package/src/backends/mlx/continuation.ts +0 -77
  229. package/src/backends/mlx/diffusion.ts +0 -39
  230. package/src/backends/mlx/draft-target.ts +0 -32
  231. package/src/backends/mlx/encoder-cache.ts +0 -25
  232. package/src/backends/mlx/evaluation.ts +0 -105
  233. package/src/backends/mlx/fill-append.ts +0 -58
  234. package/src/backends/mlx/fill-group.ts +0 -497
  235. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  236. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  237. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  238. package/src/backends/mlx/gateway-binding.ts +0 -174
  239. package/src/backends/mlx/graph.ts +0 -38
  240. package/src/backends/mlx/kv-codec.ts +0 -9
  241. package/src/backends/mlx/kv-maintenance.ts +0 -161
  242. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  243. package/src/backends/mlx/memory-client.ts +0 -189
  244. package/src/backends/mlx/methods.ts +0 -90
  245. package/src/backends/mlx/mixed-iteration.ts +0 -62
  246. package/src/backends/mlx/model-prompt.ts +0 -178
  247. package/src/backends/mlx/model-serving.ts +0 -80
  248. package/src/backends/mlx/paged-cache-codec.ts +0 -27
  249. package/src/backends/mlx/prefill-cohort.ts +0 -100
  250. package/src/backends/mlx/prefill-policy.ts +0 -26
  251. package/src/backends/mlx/prefill-rows.ts +0 -244
  252. package/src/backends/mlx/prefill.ts +0 -33
  253. package/src/backends/mlx/projected-context-rows.ts +0 -72
  254. package/src/backends/mlx/prompt-input.ts +0 -29
  255. package/src/backends/mlx/qwen-prompt-input.ts +0 -40
  256. package/src/backends/mlx/request-policy.ts +0 -20
  257. package/src/backends/mlx/request-state-policy.ts +0 -54
  258. package/src/backends/mlx/rollback.ts +0 -92
  259. package/src/backends/mlx/row-sampling.ts +0 -49
  260. package/src/backends/mlx/serial-executor.ts +0 -251
  261. package/src/backends/mlx/speculative-group.ts +0 -438
  262. package/src/backends/mlx/speculative-round.ts +0 -161
  263. package/src/backends/mlx/speculative.ts +0 -131
  264. package/src/backends/mlx/state-rows.ts +0 -104
  265. package/src/backends/mlx/state-views.ts +0 -46
  266. package/src/backends/mlx/target-layout-capability.ts +0 -35
  267. package/src/backends/mlx/text-engine.ts +0 -73
  268. package/src/backends/mlx/transitioning-kv-rows.ts +0 -173
  269. package/src/chat-template.ts +0 -382
  270. package/src/cli.ts +0 -3490
  271. package/src/config.ts +0 -399
  272. package/src/contracts/completion.ts +0 -16
  273. package/src/contracts/execution.ts +0 -70
  274. package/src/contracts/generation.ts +0 -103
  275. package/src/contracts/host.ts +0 -7
  276. package/src/contracts/object-cache.ts +0 -8
  277. package/src/contracts/pi-provider.ts +0 -30
  278. package/src/contracts/pi.ts +0 -261
  279. package/src/contracts/prefix-cache.ts +0 -33
  280. package/src/contracts/resources.ts +0 -25
  281. package/src/contracts/sampling.ts +0 -23
  282. package/src/contracts/scheduling.ts +0 -54
  283. package/src/contracts/tsconfig.json +0 -14
  284. package/src/dataset/generators.ts +0 -1087
  285. package/src/dataset/index.ts +0 -12
  286. package/src/dataset/job.ts +0 -81
  287. package/src/dataset/llm.ts +0 -71
  288. package/src/dataset/registry.ts +0 -528
  289. package/src/diffusion/diffusion-generate.ts +0 -507
  290. package/src/download.ts +0 -505
  291. package/src/embed.ts +0 -77
  292. package/src/engine/admission.ts +0 -59
  293. package/src/engine/cancellation.ts +0 -38
  294. package/src/engine/engine.ts +0 -56
  295. package/src/engine/execution-coordinator.ts +0 -70
  296. package/src/engine/execution-plan.ts +0 -64
  297. package/src/engine/execution-tasks.ts +0 -44
  298. package/src/engine/namespaced-cache.ts +0 -13
  299. package/src/engine/resources.ts +0 -53
  300. package/src/engine/scheduler.ts +0 -92
  301. package/src/engine/session.ts +0 -247
  302. package/src/eval/README.md +0 -130
  303. package/src/eval/ifeval.ts +0 -81
  304. package/src/eval/kl-prompts.ts +0 -29
  305. package/src/eval/kl.ts +0 -590
  306. package/src/eval/perplexity.ts +0 -164
  307. package/src/eval/quality-db.ts +0 -92
  308. package/src/eval/reference-logits.ts +0 -207
  309. package/src/eval/runner.ts +0 -124
  310. package/src/eval/score.ts +0 -49
  311. package/src/eval/tasks/bfcl.ts +0 -535
  312. package/src/eval/tasks/gsm8k.ts +0 -98
  313. package/src/eval/tasks/hashhop.ts +0 -139
  314. package/src/eval/tasks/humaneval.ts +0 -275
  315. package/src/eval/tasks/ifeval.ts +0 -525
  316. package/src/eval/tasks/mmlu.ts +0 -157
  317. package/src/eval/ultrafeedback.ts +0 -60
  318. package/src/evaldb.ts +0 -199
  319. package/src/expert-io.ts +0 -393
  320. package/src/expert-offload-build.ts +0 -77
  321. package/src/expert-offload.ts +0 -76
  322. package/src/expert-residency.ts +0 -1134
  323. package/src/expert-usage.ts +0 -415
  324. package/src/fill/echo-index.ts +0 -188
  325. package/src/fill/fill-session.ts +0 -463
  326. package/src/fill/proposal.ts +0 -68
  327. package/src/fill/schema-rows.ts +0 -506
  328. package/src/fill/tool-boundary.ts +0 -103
  329. package/src/fit.ts +0 -249
  330. package/src/generate.ts +0 -1352
  331. package/src/grammar.ts +0 -604
  332. package/src/harness-pi.ts +0 -184
  333. package/src/hf-push.ts +0 -628
  334. package/src/hub-rest.ts +0 -242
  335. package/src/index.ts +0 -63
  336. package/src/inference/denoising.ts +0 -17
  337. package/src/inference/draft-acceptance.ts +0 -41
  338. package/src/inference/draft-output.ts +0 -49
  339. package/src/inference/graph.ts +0 -33
  340. package/src/inference/prefill.ts +0 -45
  341. package/src/inference/rollback.ts +0 -7
  342. package/src/jobs/index.ts +0 -31
  343. package/src/jobs/job-entry.ts +0 -107
  344. package/src/jobs/task-client.ts +0 -19
  345. package/src/jobs/types.ts +0 -2
  346. package/src/kv-scheme.ts +0 -279
  347. package/src/kv-store.ts +0 -1135
  348. package/src/lab/README.md +0 -22
  349. package/src/lab/curve/curve-designer.html +0 -303
  350. package/src/lab/curve/curve-sampler.ts +0 -122
  351. package/src/lab/expert-trace/expert-trace.ts +0 -69
  352. package/src/lab/paged-kv/paged-attention.ts +0 -117
  353. package/src/lab/paged-kv/paged-kv-rows.ts +0 -111
  354. package/src/lab/paged-kv/paged-kv.ts +0 -336
  355. package/src/library.ts +0 -40
  356. package/src/lora.ts +0 -408
  357. package/src/md-modules.d.ts +0 -54
  358. package/src/media-fetch.ts +0 -442
  359. package/src/memory/article.ts +0 -558
  360. package/src/memory/chunk-validation.ts +0 -150
  361. package/src/memory/chunk.ts +0 -318
  362. package/src/memory/cluster.ts +0 -351
  363. package/src/memory/coverage.ts +0 -134
  364. package/src/memory/crosslink.ts +0 -0
  365. package/src/memory/db.ts +0 -253
  366. package/src/memory/entity.ts +0 -203
  367. package/src/memory/gate.ts +0 -187
  368. package/src/memory/history.ts +0 -152
  369. package/src/memory/ingest.ts +0 -335
  370. package/src/memory/model.ts +0 -183
  371. package/src/memory/normalize.ts +0 -671
  372. package/src/memory/parse.ts +0 -22
  373. package/src/memory/pipeline.ts +0 -275
  374. package/src/memory/prompts.ts +0 -65
  375. package/src/memory/query.ts +0 -334
  376. package/src/memory/reconcile.ts +0 -734
  377. package/src/memory/redirect.ts +0 -108
  378. package/src/memory/reindex.ts +0 -325
  379. package/src/memory/resolve.ts +0 -307
  380. package/src/memory/rest.ts +0 -245
  381. package/src/memory/route.ts +0 -272
  382. package/src/memory/schedule.ts +0 -165
  383. package/src/memory/stages.ts +0 -777
  384. package/src/memory/synthesize.ts +0 -1638
  385. package/src/memory/tools.ts +0 -749
  386. package/src/memory/vault.ts +0 -1194
  387. package/src/memory/wikify.ts +0 -1064
  388. package/src/mlx/array.ts +0 -425
  389. package/src/mlx/autograd.ts +0 -304
  390. package/src/mlx/checkpoint.ts +0 -149
  391. package/src/mlx/compile.ts +0 -168
  392. package/src/mlx/custom-vjp.ts +0 -188
  393. package/src/mlx/ffi.ts +0 -531
  394. package/src/mlx/materialize.ts +0 -23
  395. package/src/mlx/metal-kernel.ts +0 -159
  396. package/src/mlx/normalized-argmax.ts +0 -116
  397. package/src/mlx/ops.ts +0 -1108
  398. package/src/mlx/quantized-rows.ts +0 -36
  399. package/src/mlx/token-bitmask.ts +0 -52
  400. package/src/mlx/turboquant-kv-decode.ts +0 -82
  401. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  402. package/src/mlx/turboquant-ops.ts +0 -861
  403. package/src/mlx/turboquant-tables.ts +0 -237
  404. package/src/mmap.ts +0 -90
  405. package/src/model/artifact-identity.ts +0 -73
  406. package/src/model/batched-kv.ts +0 -235
  407. package/src/model/batched-mask.ts +0 -279
  408. package/src/model/batched-quant.ts +0 -212
  409. package/src/model/batched-quantized-kv.ts +0 -144
  410. package/src/model/batched-rotating-quant.ts +0 -353
  411. package/src/model/batched-rotating-state.ts +0 -149
  412. package/src/model/batched-rotating.ts +0 -338
  413. package/src/model/batched-row-storage.ts +0 -179
  414. package/src/model/batched-ssm.ts +0 -52
  415. package/src/model/batched-turboquant-kv.ts +0 -94
  416. package/src/model/compiled-decode.ts +0 -712
  417. package/src/model/decoded-kv-donor.ts +0 -12
  418. package/src/model/delayed-quantized-kv.ts +0 -72
  419. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  420. package/src/model/delayed-turboquant-kv.ts +0 -57
  421. package/src/model/diffusion-gemma.ts +0 -1026
  422. package/src/model/factory.ts +0 -215
  423. package/src/model/fingerprint.ts +0 -45
  424. package/src/model/flash-attention.ts +0 -694
  425. package/src/model/full-prefill-padding.ts +0 -56
  426. package/src/model/full-prefill-row.ts +0 -105
  427. package/src/model/gemma4-base.ts +0 -2370
  428. package/src/model/gemma4.ts +0 -1395
  429. package/src/model/generated/gemma4-12b.ts +0 -429
  430. package/src/model/generated/gemma4-26b.ts +0 -448
  431. package/src/model/generated/gemma4-e4b.ts +0 -717
  432. package/src/model/generated/index.ts +0 -18
  433. package/src/model/glm52-atlas.ts +0 -511
  434. package/src/model/glm52-cache.ts +0 -792
  435. package/src/model/glm52-config.ts +0 -262
  436. package/src/model/glm52-container.ts +0 -305
  437. package/src/model/glm52-coupling.ts +0 -388
  438. package/src/model/glm52-dsa.ts +0 -606
  439. package/src/model/glm52-expert-layout.ts +0 -253
  440. package/src/model/glm52-layout.ts +0 -152
  441. package/src/model/glm52-memory.ts +0 -500
  442. package/src/model/glm52-mla.ts +0 -792
  443. package/src/model/glm52-moe.ts +0 -223
  444. package/src/model/glm52-pilot.ts +0 -537
  445. package/src/model/glm52-reference.ts +0 -445
  446. package/src/model/glm52-residency.ts +0 -557
  447. package/src/model/glm52-resident-weights.ts +0 -135
  448. package/src/model/glm52-streamed-experts.ts +0 -453
  449. package/src/model/glm52-streamed-metal.ts +0 -610
  450. package/src/model/glm52-weights.ts +0 -503
  451. package/src/model/glm52.ts +0 -1132
  452. package/src/model/implementation.ts +0 -69
  453. package/src/model/kv-attention-view.ts +0 -70
  454. package/src/model/minicpm5.ts +0 -376
  455. package/src/model/profile.ts +0 -468
  456. package/src/model/quantized-append-attention.ts +0 -31
  457. package/src/model/qwen-append.ts +0 -12
  458. package/src/model/qwen-conv.ts +0 -52
  459. package/src/model/qwen3-delta-state.ts +0 -74
  460. package/src/model/qwen3-delta.ts +0 -451
  461. package/src/model/qwen3-moe.ts +0 -404
  462. package/src/model/qwen3-mrope.ts +0 -250
  463. package/src/model/qwen3.ts +0 -277
  464. package/src/model/qwen3_5-checkpoint.ts +0 -164
  465. package/src/model/qwen3_5.ts +0 -881
  466. package/src/model/rotating-kv-donor.ts +0 -35
  467. package/src/model/rotating-kv-layout.ts +0 -262
  468. package/src/model/rotating-row-transaction.ts +0 -35
  469. package/src/model/speculative-rotating-kv.ts +0 -101
  470. package/src/model/ssm-prefill-padding.ts +0 -39
  471. package/src/model/support.ts +0 -110
  472. package/src/model/token-groups.ts +0 -66
  473. package/src/model/trellis-balanced-scatter.ts +0 -51
  474. package/src/model/trellis-linear.ts +0 -672
  475. package/src/model/trellis-shared-m.ts +0 -151
  476. package/src/model/trellis-shared-scatter.ts +0 -144
  477. package/src/model/trellis-splitk-prefill.ts +0 -158
  478. package/src/model/trellis-tiled-prefill.ts +0 -136
  479. package/src/model/trellis-vector-expand.ts +0 -62
  480. package/src/model/trellis-wide-prefill.ts +0 -94
  481. package/src/model/turboquant-codec.ts +0 -89
  482. package/src/model/universal/archs.ts +0 -332
  483. package/src/model/universal/dense.ts +0 -612
  484. package/src/model/universal/modules.ts +0 -170
  485. package/src/model/universal/rope.ts +0 -381
  486. package/src/model/whisper.ts +0 -435
  487. package/src/native/expert_io.c +0 -523
  488. package/src/native/frame_extract.swift +0 -140
  489. package/src/native/mic_capture.swift +0 -92
  490. package/src/native-pack.ts +0 -163
  491. package/src/pi-provider.ts +0 -53
  492. package/src/pi-session.ts +0 -81
  493. package/src/pi-terminal.ts +0 -274
  494. package/src/pi-web.ts +0 -1940
  495. package/src/preflight.ts +0 -158
  496. package/src/prompt-cache.ts +0 -682
  497. package/src/quantize/allocator.ts +0 -627
  498. package/src/quantize/atomic-output.ts +0 -38
  499. package/src/quantize/calibration.ts +0 -181
  500. package/src/quantize/config-writer.ts +0 -145
  501. package/src/quantize/index.ts +0 -84
  502. package/src/quantize/job.ts +0 -162
  503. package/src/quantize/quantizer.ts +0 -666
  504. package/src/quantize/rotate.ts +0 -603
  505. package/src/quantize/safetensors-writer.ts +0 -249
  506. package/src/quantize/sensitivity.ts +0 -216
  507. package/src/quantize/trellis.ts +0 -586
  508. package/src/quantize/weight-transform.ts +0 -292
  509. package/src/registry.ts +0 -602
  510. package/src/runtime-config.ts +0 -77
  511. package/src/safetensors.ts +0 -165
  512. package/src/sampler.ts +0 -1012
  513. package/src/serve/admin-routes.ts +0 -184
  514. package/src/serve/assets/curve-terrain.html +0 -105
  515. package/src/serve/assets/training-inference-map.html +0 -575
  516. package/src/serve/audio-routes.ts +0 -323
  517. package/src/serve/aux-routes.ts +0 -132
  518. package/src/serve/batch-scheduler.ts +0 -8
  519. package/src/serve/checkpoint-identity.ts +0 -64
  520. package/src/serve/generation-gateway.ts +0 -537
  521. package/src/serve/isolate.ts +0 -609
  522. package/src/serve/kv-budget.ts +0 -14
  523. package/src/serve/lab-routes.ts +0 -341
  524. package/src/serve/lane-registry.ts +0 -45
  525. package/src/serve/model-admin-routes.ts +0 -155
  526. package/src/serve/model-binding.ts +0 -49
  527. package/src/serve/model-host.ts +0 -511
  528. package/src/serve/parent-application.ts +0 -56
  529. package/src/serve/prompt-response-trace.ts +0 -161
  530. package/src/serve/response-lease.ts +0 -24
  531. package/src/serve/session-search.ts +0 -326
  532. package/src/serve/static-routes.ts +0 -101
  533. package/src/serve/transcription-server.ts +0 -64
  534. package/src/serve/transcription-service.ts +0 -502
  535. package/src/server.ts +0 -1282
  536. package/src/spec/assistant-rows.ts +0 -93
  537. package/src/spec/assistant-source.ts +0 -126
  538. package/src/spec/cache-identity.ts +0 -22
  539. package/src/spec/deepspec-rows.ts +0 -29
  540. package/src/spec/deepspec-source.ts +0 -145
  541. package/src/spec/dflash-source.ts +0 -149
  542. package/src/spec/drafter.ts +0 -304
  543. package/src/spec/dspark/ab-stats.ts +0 -136
  544. package/src/spec/dspark/calibration.ts +0 -112
  545. package/src/spec/dspark/data-dflash.ts +0 -156
  546. package/src/spec/dspark/data.ts +0 -201
  547. package/src/spec/dspark/deepspec-module.ts +0 -776
  548. package/src/spec/dspark/generate-dflash.ts +0 -245
  549. package/src/spec/dspark/generate.ts +0 -290
  550. package/src/spec/dspark/loader.ts +0 -23
  551. package/src/spec/dspark/loss.ts +0 -213
  552. package/src/spec/dspark/module-dflash.ts +0 -560
  553. package/src/spec/dspark/module.ts +0 -540
  554. package/src/spec/dspark/quantize-drafter.ts +0 -91
  555. package/src/spec/dspark/sample.ts +0 -112
  556. package/src/spec/generate.ts +0 -276
  557. package/src/spec/glm52-mtp-graph.ts +0 -29
  558. package/src/spec/glm52-mtp-rows.ts +0 -132
  559. package/src/spec/glm52-mtp-source.ts +0 -318
  560. package/src/spec/glm52-mtp-state.ts +0 -33
  561. package/src/spec/ngram-source.ts +0 -226
  562. package/src/spec/projected-draft-rows.ts +0 -73
  563. package/src/spec/qwen-mtp-module.ts +0 -171
  564. package/src/spec/qwen-mtp-rows.ts +0 -230
  565. package/src/spec/qwen-mtp-source.ts +0 -386
  566. package/src/spec/qwen-mtp-state.ts +0 -30
  567. package/src/spec/serve-loop.ts +0 -587
  568. package/src/spec/source.ts +0 -228
  569. package/src/spec/two-model-rows.ts +0 -62
  570. package/src/spec/two-model.ts +0 -113
  571. package/src/ssd-cache.ts +0 -431
  572. package/src/ssd-durability.ts +0 -209
  573. package/src/storage/host-buffer.ts +0 -24
  574. package/src/storage/kv-writer.ts +0 -83
  575. package/src/storage/kv-writer.worker.js +0 -264
  576. package/src/storage/retention-policy.ts +0 -37
  577. package/src/tiered-prompt-cache.ts +0 -45
  578. package/src/tokenizer.ts +0 -335
  579. package/src/tool-approvals.ts +0 -131
  580. package/src/tool-call.ts +0 -695
  581. package/src/train/dataset.ts +0 -484
  582. package/src/train/diffusion-lora.ts +0 -216
  583. package/src/train/export.ts +0 -32
  584. package/src/train/flash-cce.ts +0 -1234
  585. package/src/train/forward.ts +0 -266
  586. package/src/train/fuse.ts +0 -243
  587. package/src/train/index.ts +0 -46
  588. package/src/train/job.ts +0 -205
  589. package/src/train/lora-params.ts +0 -254
  590. package/src/train/loss.ts +0 -1591
  591. package/src/train/merge.ts +0 -195
  592. package/src/train/optimizer.ts +0 -183
  593. package/src/train/prefix-shared.ts +0 -490
  594. package/src/train/rank.ts +0 -137
  595. package/src/train/segmented.ts +0 -1828
  596. package/src/train/steel-qmm-header.ts +0 -1461
  597. package/src/train/trainer.ts +0 -1221
  598. package/src/train/watch.ts +0 -542
  599. package/src/vision/diffusion-vision.ts +0 -620
  600. package/src/vision/embedder.ts +0 -176
  601. package/src/vision/preprocess.ts +0 -247
  602. package/src/vision/prompt.ts +0 -409
  603. package/src/vision/qwen3vl-preprocess.ts +0 -409
  604. package/src/vision/qwen3vl-prompt.ts +0 -233
  605. package/src/vision/qwen3vl-tower.ts +0 -566
  606. package/src/vision/siglip.ts +0 -607
  607. package/src/vision/video-frames.ts +0 -148
  608. package/src/web/app.html +0 -2155
  609. package/src/web/app.js +0 -5863
  610. package/src/web/skills/memory/SKILL.md +0 -120
  611. package/src/web/skills/web-research/SKILL.md +0 -46
  612. package/src/web/skills.ts +0 -97
  613. package/src/web/src/adapters-panel.ts +0 -288
  614. package/src/web/src/assistant.ts +0 -451
  615. package/src/web/src/chat.ts +0 -1060
  616. package/src/web/src/composer.ts +0 -962
  617. package/src/web/src/dataset.ts +0 -132
  618. package/src/web/src/finetune.ts +0 -267
  619. package/src/web/src/hub.ts +0 -428
  620. package/src/web/src/main.ts +0 -98
  621. package/src/web/src/markdown.ts +0 -0
  622. package/src/web/src/memory-panel.ts +0 -572
  623. package/src/web/src/model-picker.ts +0 -159
  624. package/src/web/src/palette.ts +0 -346
  625. package/src/web/src/protocol.ts +0 -26
  626. package/src/web/src/quantize.ts +0 -167
  627. package/src/web/src/rag.ts +0 -274
  628. package/src/web/src/sessions.ts +0 -469
  629. package/src/web/src/shell.ts +0 -804
  630. package/src/web/src/ui-catalog.ts +0 -78
  631. package/src/web/src/voice.ts +0 -141
  632. package/src/web/vendor/README.md +0 -61
  633. package/src/web-assets.ts +0 -47
  634. package/src/web-tools.ts +0 -478
  635. package/src/weights.ts +0 -255
  636. /package/src/{serve → server}/completion-sink.ts +0 -0
  637. /package/src/{serve → server}/generated-token-history.ts +0 -0
  638. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  639. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  640. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
package/src/mlx/ops.ts DELETED
@@ -1,1108 +0,0 @@
1
- // Functional op layer over MlxArray. Parity-critical conventions:
2
- // - Python-float scalars in mlx promote weakly (bf16 array × float →
3
- // bf16, scalar cast to bf16 first). `scalarLike` replicates that.
4
- // - Op composition order mirrors mlx-lm exactly; see model/gemma4.ts.
5
-
6
- import { ptr, read } from "bun:ffi";
7
- import { C, Dtype, type MlxHandle, optFloat, optInt, outArray, takeMlxError } from "./ffi";
8
- import { MlxArray, gpuStream } from "./array";
9
-
10
- const cstrCache = new Map<string, Buffer>();
11
- function cstr(s: string): Buffer {
12
- let b = cstrCache.get(s);
13
- if (!b) {
14
- b = Buffer.from(s + "\0", "utf8");
15
- cstrCache.set(s, b);
16
- }
17
- return b;
18
- }
19
-
20
- type S = MlxHandle;
21
-
22
- export function add(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
23
- return new MlxArray(outArray("add", (o) => C.mlx_add(o, a.handle, b.handle, s)));
24
- }
25
-
26
- export function sub(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
27
- return new MlxArray(outArray("subtract", (o) => C.mlx_subtract(o, a.handle, b.handle, s)));
28
- }
29
-
30
- export function mul(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
31
- return new MlxArray(outArray("multiply", (o) => C.mlx_multiply(o, a.handle, b.handle, s)));
32
- }
33
-
34
- export function div(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
35
- return new MlxArray(outArray("divide", (o) => C.mlx_divide(o, a.handle, b.handle, s)));
36
- }
37
-
38
- export function tanh(a: MlxArray, s: S = gpuStream): MlxArray {
39
- return new MlxArray(outArray("tanh", (o) => C.mlx_tanh(o, a.handle, s)));
40
- }
41
-
42
- export function sigmoid(a: MlxArray, s: S = gpuStream): MlxArray {
43
- return new MlxArray(outArray("sigmoid", (o) => C.mlx_sigmoid(o, a.handle, s)));
44
- }
45
-
46
- /** f32 → bf16 truncation with round-to-nearest-even, returning the 2
47
- * little-endian bytes of the bf16 value. Matches mlx's
48
- * `static_cast<bfloat16_t>(float)` bit-for-bit so a host-built bf16 scalar is
49
- * numerically identical to `f32_scalar.astype(bf16)` — just without the GPU
50
- * Copy (astype) kernel. */
51
- function bf16Bytes(value: number): Uint8Array {
52
- const fb = new Float32Array([value]);
53
- const bits = new Uint32Array(fb.buffer)[0]!;
54
- let hi16: number;
55
- if (((bits >>> 23) & 0xff) === 0xff) {
56
- // inf / nan: keep the high 16 bits, and keep a NaN a (quiet) NaN.
57
- hi16 = (bits >>> 16) & 0xffff;
58
- if ((bits & 0x7fffff) !== 0) hi16 |= 0x40;
59
- } else {
60
- const roundingBias = 0x7fff + ((bits >>> 16) & 1); // round to nearest even
61
- hi16 = ((bits + roundingBias) >>> 16) & 0xffff;
62
- }
63
- return new Uint8Array([hi16 & 0xff, (hi16 >>> 8) & 0xff]);
64
- }
65
-
66
- /** Scalar constant with the same dtype as `like` (python weak-scalar semantics).
67
- * Built HOST-SIDE at the target dtype — mlx's own scalar→array path constructs
68
- * a bf16/f32 constant directly, so `scalar * bf16_array` is a single multiply.
69
- * Going through an f32 leaf + GPU `.astype(bf16)` (the old path) emits a
70
- * separate Copy kernel (`v_copy…`) that the reference never dispatches. */
71
- export function scalarLike(value: number, like: MlxArray): MlxArray {
72
- if (like.dtype === Dtype.float32)
73
- return MlxArray.fromFloat32(new Float32Array([value]), []);
74
- if (like.dtype === Dtype.bfloat16)
75
- return MlxArray.fromBytesCopy(bf16Bytes(value), [], Dtype.bfloat16);
76
- // f16 / other float dtypes: keep the astype path (rare here; no bit-exact JS
77
- // converter written for them yet).
78
- const f = MlxArray.fromFloat32(new Float32Array([value]), []);
79
- const cast = f.astype(like.dtype);
80
- f.dispose();
81
- return cast;
82
- }
83
-
84
- export function mulScalar(a: MlxArray, value: number, s: S = gpuStream): MlxArray {
85
- const k = scalarLike(value, a);
86
- const r = mul(a, k, s);
87
- k.dispose();
88
- return r;
89
- }
90
-
91
- export function rmsNorm(
92
- x: MlxArray, weight: MlxArray | null, eps: number, s: S = gpuStream,
93
- ): MlxArray {
94
- return new MlxArray(
95
- outArray("fast_rms_norm", (o) =>
96
- C.mlx_fast_rms_norm(o, x.handle, weight?.handle ?? 0n, eps, s),
97
- ),
98
- );
99
- }
100
-
101
- export function layerNorm(
102
- x: MlxArray, weight: MlxArray | null, bias: MlxArray | null, eps: number,
103
- s: S = gpuStream,
104
- ): MlxArray {
105
- return new MlxArray(
106
- outArray("fast_layer_norm", (o) =>
107
- C.mlx_fast_layer_norm(o, x.handle, weight?.handle ?? 0n, bias?.handle ?? 0n, eps, s),
108
- ),
109
- );
110
- }
111
-
112
- export function matmul(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
113
- return new MlxArray(outArray("matmul", (o) => C.mlx_matmul(o, a.handle, b.handle, s)));
114
- }
115
-
116
- /** Bit-identical copy through a FRESH primitive node (mx.copy). Unlike
117
- * `contiguous`, this always creates a new graph node even for an already-
118
- * contiguous input — the tool for DETACHING an array from a multi-output
119
- * primitive's sibling set (a retained sibling output pins every co-output's
120
- * buffer natively; see gatedDeltaUpdate's state detach, 2026-08-20). */
121
- export function copyOf(a: MlxArray, s: S = gpuStream): MlxArray {
122
- return new MlxArray(outArray("copy", (o) => C.mlx_copy(o, a.handle, s)));
123
- }
124
-
125
- /** Materialize a row-major contiguous copy (needed before rawBytes on views). */
126
- export function contiguous(a: MlxArray, s: S = gpuStream): MlxArray {
127
- return new MlxArray(
128
- outArray("contiguous", (o) => C.mlx_contiguous(o, a.handle, false, s)),
129
- );
130
- }
131
-
132
- export function logicalOr(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
133
- return new MlxArray(
134
- outArray("logical_or", (o) => C.mlx_logical_or(o, a.handle, b.handle, s)),
135
- );
136
- }
137
-
138
- export function rope(
139
- x: MlxArray, dims: number, base: number | null, offset: number,
140
- freqs: MlxArray | null, s: S = gpuStream,
141
- ): MlxArray {
142
- return new MlxArray(
143
- outArray("fast_rope", (o) =>
144
- C.mlx_fast_rope(
145
- o, x.handle, dims, false, optFloat(base), 1.0, offset,
146
- freqs?.handle ?? 0n, s,
147
- ),
148
- ),
149
- );
150
- }
151
-
152
- /** fast::rope with every knob exposed (traditional + scale), for the
153
- * universal rope factory (rope_utils.initialize_rope port). The plain
154
- * `rope` above stays byte-identical for existing call sites. */
155
- export function ropeScaled(
156
- x: MlxArray, dims: number, traditional: boolean, base: number | null,
157
- scale: number, offset: number, freqs: MlxArray | null, s: S = gpuStream,
158
- ): MlxArray {
159
- return new MlxArray(
160
- outArray("fast_rope", (o) =>
161
- C.mlx_fast_rope(
162
- o, x.handle, dims, traditional, optFloat(base), scale, offset,
163
- freqs?.handle ?? 0n, s,
164
- ),
165
- ),
166
- );
167
- }
168
-
169
- /** fast::rope with the position offset as an ARRAY (int32 scalar) instead
170
- * of a baked int — required inside compiled decode graphs, where the
171
- * offset changes every step but the graph must not. Same kernel as
172
- * `rope`; bit-exactness vs the static form is asserted in
173
- * tests/unit/compile.test.ts. */
174
- export function ropeDynamic(
175
- x: MlxArray, dims: number, base: number | null, offset: MlxArray,
176
- freqs: MlxArray | null, s: S = gpuStream,
177
- ): MlxArray {
178
- return new MlxArray(
179
- outArray("fast_rope_dynamic", (o) =>
180
- C.mlx_fast_rope_dynamic(
181
- o, x.handle, dims, false, optFloat(base), 1.0, offset.handle,
182
- freqs?.handle ?? 0n, s,
183
- ),
184
- ),
185
- );
186
- }
187
-
188
- /** Array-offset fast::rope with every knob exposed (traditional + scale) —
189
- * the dynamic twin of `ropeScaled`, for the universal rope factory's
190
- * batched-decode path (per-row [B] offsets under left-padding). Same
191
- * kernel as `ropeDynamic`; static/dynamic bit-exactness is asserted in
192
- * tests/unit/compile.test.ts. */
193
- export function ropeScaledDynamic(
194
- x: MlxArray, dims: number, traditional: boolean, base: number | null,
195
- scale: number, offset: MlxArray, freqs: MlxArray | null, s: S = gpuStream,
196
- ): MlxArray {
197
- return new MlxArray(
198
- outArray("fast_rope_dynamic", (o) =>
199
- C.mlx_fast_rope_dynamic(
200
- o, x.handle, dims, traditional, optFloat(base), scale, offset.handle,
201
- freqs?.handle ?? 0n, s,
202
- ),
203
- ),
204
- );
205
- }
206
-
207
- export function sdpa(
208
- q: MlxArray, k: MlxArray, v: MlxArray, scale: number,
209
- maskMode: "" | "causal" | "array", maskArr: MlxArray | null = null,
210
- s: S = gpuStream,
211
- ): MlxArray {
212
- return new MlxArray(
213
- outArray("fast_sdpa", (o) =>
214
- C.mlx_fast_scaled_dot_product_attention(
215
- o, q.handle, k.handle, v.handle, scale, ptr(cstr(maskMode)),
216
- maskArr?.handle ?? 0n, 0n, false, s,
217
- ),
218
- ),
219
- );
220
- }
221
-
222
- export interface QuantSpec {
223
- bits: number;
224
- groupSize: number;
225
- mode: string;
226
- }
227
-
228
- export function quantizedMatmul(
229
- x: MlxArray, w: MlxArray, scales: MlxArray, biases: MlxArray | null,
230
- spec: QuantSpec, transpose = true, s: S = gpuStream,
231
- ): MlxArray {
232
- // UPSTREAM MLX BUG WORKAROUND (found 2026-07-02, reproduced on stock mlx
233
- // 0.31.2): quantized_matmul with transpose=false returns WRONG VALUES when
234
- // the row count is 2 or 3 (relnorm ~0.3-1.1 vs the dequantized matmul);
235
- // M=1 and M>=4 are correct, transpose=true is correct at every M. Pad the
236
- // row axis to 4 with zeros and slice the result back. NOTE this wrapper
237
- // cannot protect mlx's INTERNAL vjp of a transpose=true qmm (C++ calls the
238
- // primitive directly) — training heads pad the span through the head
239
- // instead (loss.ts logitsFromHiddenPadM).
240
- const rowAxis = x.shape.length - 2;
241
- const rows = x.shape[rowAxis]!;
242
- if (!transpose && (rows === 2 || rows === 3)) {
243
- const padShape = [...x.shape];
244
- padShape[rowAxis] = 4 - rows;
245
- const pad = zeros(padShape, x.dtype, s);
246
- const xPad = concatAxis([x, pad], rowAxis, s);
247
- pad.dispose();
248
- const yPad = quantizedMatmul(xPad, w, scales, biases, spec, transpose, s);
249
- xPad.dispose();
250
- const start = MlxArray.fromInt32(new Int32Array([0]), [1]);
251
- const outShape = [...yPad.shape];
252
- outShape[rowAxis] = rows;
253
- const y = sliceDynamic(yPad, start, [rowAxis], outShape, s);
254
- start.dispose();
255
- yPad.dispose();
256
- return y;
257
- }
258
- return new MlxArray(
259
- outArray("quantized_matmul", (o) =>
260
- C.mlx_quantized_matmul(
261
- o, x.handle, w.handle, scales.handle, biases?.handle ?? 0n,
262
- transpose, optInt(spec.groupSize), optInt(spec.bits),
263
- ptr(cstr(spec.mode)), s,
264
- ),
265
- ),
266
- );
267
- }
268
-
269
- /** Gathered quantized matmul over stacked expert weights (MoE).
270
- * x [..., 1, K] with rhs_indices [...] selecting the expert per row;
271
- * port of mx.gather_qmm as QuantizedSwitchLinear uses it. */
272
- export function gatherQmm(
273
- x: MlxArray, w: MlxArray, scales: MlxArray, biases: MlxArray | null,
274
- rhsIndices: MlxArray, spec: QuantSpec, sortedIndices: boolean,
275
- transpose = true, s: S = gpuStream,
276
- ): MlxArray {
277
- return new MlxArray(
278
- outArray("gather_qmm", (o) =>
279
- C.mlx_gather_qmm(
280
- o, x.handle, w.handle, scales.handle, biases?.handle ?? 0n,
281
- 0n /* lhs_indices */, rhsIndices.handle, transpose,
282
- optInt(spec.groupSize), optInt(spec.bits), ptr(cstr(spec.mode)),
283
- sortedIndices, s,
284
- ),
285
- ),
286
- );
287
- }
288
-
289
- export function floorDivide(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
290
- return new MlxArray(
291
- outArray("floor_divide", (o) => C.mlx_floor_divide(o, a.handle, b.handle, s)),
292
- );
293
- }
294
-
295
- export function dequantize(
296
- w: MlxArray, scales: MlxArray, biases: MlxArray | null, spec: QuantSpec,
297
- s: S = gpuStream,
298
- ): MlxArray {
299
- return new MlxArray(
300
- outArray("dequantize", (o) =>
301
- C.mlx_dequantize(
302
- o, w.handle, scales.handle, biases?.handle ?? 0n,
303
- optInt(spec.groupSize), optInt(spec.bits), ptr(cstr(spec.mode)),
304
- 0n, optInt(null), s,
305
- ),
306
- ),
307
- );
308
- }
309
-
310
- export function takeAxis(a: MlxArray, indices: MlxArray, axis: number, s: S = gpuStream): MlxArray {
311
- return new MlxArray(
312
- outArray("take_axis", (o) => C.mlx_take_axis(o, a.handle, indices.handle, axis, s)),
313
- );
314
- }
315
-
316
- export function reshape(a: MlxArray, shape: number[], s: S = gpuStream): MlxArray {
317
- // bun:ffi cannot take a pointer to an empty view; ndim=0 ignores the dummy.
318
- const buf = new Int32Array(shape.length ? shape : [0]);
319
- return new MlxArray(
320
- outArray("reshape", (o) => C.mlx_reshape(o, a.handle, ptr(buf), BigInt(shape.length), s)),
321
- );
322
- }
323
-
324
- export function transposeAxes(a: MlxArray, axes: number[], s: S = gpuStream): MlxArray {
325
- const buf = new Int32Array(axes);
326
- return new MlxArray(
327
- outArray("transpose", (o) => C.mlx_transpose_axes(o, a.handle, ptr(buf), BigInt(axes.length), s)),
328
- );
329
- }
330
-
331
- export function argmaxAxis(a: MlxArray, axis: number, s: S = gpuStream): MlxArray {
332
- return new MlxArray(
333
- outArray("argmax_axis", (o) => C.mlx_argmax_axis(o, a.handle, axis, false, s)),
334
- );
335
- }
336
-
337
- export function concatAxis(arrays: MlxArray[], axis: number, s: S = gpuStream): MlxArray {
338
- const handles = new BigUint64Array(arrays.map((a) => a.handle));
339
- const vec = C.mlx_vector_array_new_data(ptr(handles), BigInt(arrays.length));
340
- try {
341
- return new MlxArray(
342
- outArray("concatenate", (o) => C.mlx_concatenate_axis(o, vec, axis, s)),
343
- );
344
- } finally {
345
- C.mlx_vector_array_free(vec);
346
- }
347
- }
348
-
349
- export function pow(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
350
- return new MlxArray(outArray("power", (o) => C.mlx_power(o, a.handle, b.handle, s)));
351
- }
352
-
353
- /** nn.gelu_approx: 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³))) — composed
354
- * exactly as mlx's python source, INCLUDING operand order: x**3 is mx.power
355
- * (NOT x·x·x — they round differently in bf16), and every scalar·array product
356
- * puts the SCALAR FIRST (`0.5 * x`, not `x * 0.5`). Multiply is commutative so
357
- * this is bit-identical, but it makes the compiled geglu graph's operand string
358
- * (`Multiply(C, V)`) match the oracle's fused kernel exactly. Scalars promote
359
- * weakly to x's dtype. */
360
- export function geluApprox(x: MlxArray, s: S = gpuStream): MlxArray {
361
- // EXACT copy of mlx's graph for
362
- // 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x**3)))
363
- // as dumped via mx.export_to_dot. mlx's `__rmul__`/`__radd__` canonicalize
364
- // every `scalar OP array` to `array OP scalar`, so every commutative product/
365
- // sum below is ARRAY-FIRST, constant-second (NOT scalar-first). Build order
366
- // follows Python left-to-right (`0.5 * x` first). Same libmlx compiles this to
367
- // the identical fused kernel.
368
- const cHalf = scalarLike(0.5, x);
369
- const halfx = mul(x, cHalf, s); // Multiply(x, 0.5)
370
- const cThree = scalarLike(3, x);
371
- const x3 = pow(x, cThree, s); // Power(x, 3)
372
- const cCoef = scalarLike(0.044715, x);
373
- const cx3 = mul(x3, cCoef, s); // Multiply(x**3, 0.044715)
374
- const inner = add(x, cx3, s); // Add(x, cx3)
375
- const cSqrt = scalarLike(Math.sqrt(2 / Math.PI), x);
376
- const scaled = mul(inner, cSqrt, s); // Multiply(inner, √(2/π))
377
- const t = tanh(scaled, s);
378
- const cOne = scalarLike(1, x);
379
- const t1 = add(t, cOne, s); // Add(tanh, 1)
380
- const out = mul(halfx, t1, s); // Multiply(halfx, 1+tanh)
381
- for (const a of [cHalf, halfx, cThree, x3, cCoef, cx3, inner, cSqrt, scaled, t, cOne, t1]) a.dispose();
382
- return out;
383
- }
384
-
385
- export function erf(a: MlxArray, s: S = gpuStream): MlxArray {
386
- return new MlxArray(outArray("erf", (o) => C.mlx_erf(o, a.handle, s)));
387
- }
388
-
389
- /** nn.gelu (PRECISE, erf-based): x · (1 + erf(x/√2)) / 2 — composed exactly
390
- * as mlx's python source (weak scalars promote to x's dtype). Used by the
391
- * gemma-1 gated MLP and starcoder2's plain MLP; distinct from geluApprox
392
- * (gelu_pytorch_tanh). */
393
- export function geluPrecise(x: MlxArray, s: S = gpuStream): MlxArray {
394
- const sqrt2 = scalarLike(Math.sqrt(2), x);
395
- const xs = div(x, sqrt2, s); // x / math.sqrt(2) — division, not mul-by-reciprocal
396
- const e = erf(xs, s);
397
- const one = scalarLike(1, x);
398
- const e1 = add(one, e, s);
399
- const xe = mul(x, e1, s);
400
- const two = scalarLike(2, x);
401
- const out = div(xe, two, s); // (...) / 2
402
- for (const a of [sqrt2, xs, e, one, e1, xe, two]) a.dispose();
403
- return out;
404
- }
405
-
406
- /** mx.addmm(c, a, b): a@b + c fused (α=β=1) — nn.Linear's bias path
407
- * (`mx.addmm(bias, x, weight.T)`). */
408
- export function addmm(c: MlxArray, a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
409
- return new MlxArray(
410
- outArray("addmm", (o) => C.mlx_addmm(o, c.handle, a.handle, b.handle, 1.0, 1.0, s)),
411
- );
412
- }
413
-
414
- export function exp(a: MlxArray, s: S = gpuStream): MlxArray {
415
- return new MlxArray(outArray("exp", (o) => C.mlx_exp(o, a.handle, s)));
416
- }
417
-
418
- export function cos(a: MlxArray, s: S = gpuStream): MlxArray {
419
- return new MlxArray(outArray("cos", (o) => C.mlx_cos(o, a.handle, s)));
420
- }
421
-
422
- export function sin(a: MlxArray, s: S = gpuStream): MlxArray {
423
- return new MlxArray(outArray("sin", (o) => C.mlx_sin(o, a.handle, s)));
424
- }
425
-
426
- export function neg(a: MlxArray, s: S = gpuStream): MlxArray {
427
- return new MlxArray(outArray("negative", (o) => C.mlx_negative(o, a.handle, s)));
428
- }
429
-
430
- export function argsortAxis(a: MlxArray, axis: number, s: S = gpuStream): MlxArray {
431
- return new MlxArray(outArray("argsort", (o) => C.mlx_argsort_axis(o, a.handle, axis, s)));
432
- }
433
-
434
- export function argpartitionAxis(a: MlxArray, kth: number, axis: number, s: S = gpuStream): MlxArray {
435
- return new MlxArray(
436
- outArray("argpartition", (o) => C.mlx_argpartition_axis(o, a.handle, kth, axis, s)),
437
- );
438
- }
439
-
440
- export function takeAlongAxis(a: MlxArray, idx: MlxArray, axis: number, s: S = gpuStream): MlxArray {
441
- return new MlxArray(
442
- outArray("take_along_axis", (o) => C.mlx_take_along_axis(o, a.handle, idx.handle, axis, s)),
443
- );
444
- }
445
-
446
- export function putAlongAxis(
447
- a: MlxArray, idx: MlxArray, values: MlxArray, axis: number, s: S = gpuStream,
448
- ): MlxArray {
449
- return new MlxArray(
450
- outArray("put_along_axis", (o) =>
451
- C.mlx_put_along_axis(o, a.handle, idx.handle, values.handle, axis, s),
452
- ),
453
- );
454
- }
455
-
456
- export function cumsum(a: MlxArray, axis: number, s: S = gpuStream): MlxArray {
457
- return new MlxArray(
458
- outArray("cumsum", (o) => C.mlx_cumsum_axis(o, a.handle, axis, false, true, 0n, s)),
459
- );
460
- }
461
-
462
- /** Cumulative maximum along `axis` (inclusive, forward) — mlx.core.cummax. */
463
- export function cummax(a: MlxArray, axis: number, s: S = gpuStream): MlxArray {
464
- return new MlxArray(
465
- outArray("cummax", (o) => C.mlx_cummax_axis(o, a.handle, axis, false, true, s)),
466
- );
467
- }
468
-
469
- export function where(cond: MlxArray, x: MlxArray, y: MlxArray, s: S = gpuStream): MlxArray {
470
- return new MlxArray(
471
- outArray("where", (o) => C.mlx_where(o, cond.handle, x.handle, y.handle, s)),
472
- );
473
- }
474
-
475
- // The old native arange workaround concerned stale typed-array out-pointer
476
- // reads after Bun JIT tier-up, not f64 argument marshaling. outArray uses
477
- // native pointer reads now. Large nonnegative unit-step int32 ranges avoid
478
- // host construction; small/general integer ranges retain JS conversion,
479
- // including its wrapping behavior outside int32. Cache storage stays bounded
480
- // as causal masks request new lengths on successive long-context rounds.
481
- const arangeCache = new Map<string, { array: MlxArray; bytes: number }>();
482
- const ARANGE_CACHE_MIN = 65536;
483
- const ARANGE_CACHE_BYTES = 8 * 1024 * 1024;
484
- let arangeCacheBytes = 0;
485
-
486
- export function arange(start: number, stop: number, step: number, dtype: Dtype, s: S = gpuStream): MlxArray {
487
- if (!Number.isInteger(start) || !Number.isInteger(step) || step === 0)
488
- throw new Error(`arange: integer start/step required (${start}, ${stop}, ${step})`);
489
- const n = Math.max(0, Math.ceil((stop - start) / step));
490
- const key = `${start}|${step}|${n}|${dtype}`;
491
- const cached = arangeCache.get(key);
492
- if (cached) {
493
- arangeCache.delete(key);
494
- arangeCache.set(key, cached);
495
- return cached.array.slice([0], [n], s);
496
- }
497
-
498
- let arr: MlxArray;
499
- const nativePositions = n === 0 ||
500
- (n >= ARANGE_CACHE_MIN && step === 1 && start >= 0 && stop <= 2147483647);
501
- if (dtype === Dtype.int32 && !nativePositions) {
502
- // Preserve JS conversion for small/general integer ranges.
503
- const data = new Int32Array(n);
504
- for (let i = 0; i < n; i++) data[i] = start + i * step;
505
- arr = MlxArray.fromInt32(data, [n]);
506
- } else {
507
- // Native mlx Arange in the target dtype — matches mlx's `Arange` op exactly.
508
- // The old `fromInt32 → .astype(dtype)` emitted a phantom int32→float Copy
509
- // (an AsType the oracle never dispatches — e.g. the proportional-RoPE freq
510
- // exponents). Integer start/step passed as doubles are exact.
511
- arr = new MlxArray(outArray("arange", (o) => C.mlx_arange(o, start, stop, step, dtype, s)));
512
- }
513
- if (n >= ARANGE_CACHE_MIN) {
514
- const bytes = arr.nbytes;
515
- if (bytes <= ARANGE_CACHE_BYTES) {
516
- while (arangeCacheBytes + bytes > ARANGE_CACHE_BYTES) {
517
- const [oldKey, old] = arangeCache.entries().next().value!;
518
- arangeCache.delete(oldKey);
519
- arangeCacheBytes -= old.bytes;
520
- // Returned slices retain their own native reference, including lazy
521
- // views that have not been evaluated when this owner is evicted.
522
- old.array.dispose();
523
- }
524
- arangeCache.set(key, { array: arr, bytes });
525
- arangeCacheBytes += bytes;
526
- return arr.slice([0], [n], s);
527
- }
528
- }
529
- return arr;
530
- }
531
-
532
- export function logsumexpAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
533
- return new MlxArray(
534
- outArray("logsumexp", (o) => C.mlx_logsumexp_axis(o, a.handle, axis, keepdims, s)),
535
- );
536
- }
537
-
538
- export function greaterEqual(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
539
- return new MlxArray(
540
- outArray("greater_equal", (o) => C.mlx_greater_equal(o, a.handle, b.handle, s)),
541
- );
542
- }
543
-
544
- export function less(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
545
- return new MlxArray(outArray("less", (o) => C.mlx_less(o, a.handle, b.handle, s)));
546
- }
547
-
548
- export function lessEqual(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
549
- return new MlxArray(outArray("less_equal", (o) => C.mlx_less_equal(o, a.handle, b.handle, s)));
550
- }
551
-
552
- export function logicalNot(a: MlxArray, s: S = gpuStream): MlxArray {
553
- return new MlxArray(outArray("logical_not", (o) => C.mlx_logical_not(o, a.handle, s)));
554
- }
555
-
556
- export function equal(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
557
- return new MlxArray(outArray("equal", (o) => C.mlx_equal(o, a.handle, b.handle, s)));
558
- }
559
-
560
- /** Reduce-all to a scalar (mlx.core.all). */
561
- export function allReduce(a: MlxArray, s: S = gpuStream): MlxArray {
562
- return new MlxArray(outArray("all", (o) => C.mlx_all(o, a.handle, false, s)));
563
- }
564
-
565
- /** any along one axis (mlx.core.any). */
566
- export function anyAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
567
- return new MlxArray(outArray("any_axis", (o) => C.mlx_any_axis(o, a.handle, axis, keepdims, s)));
568
- }
569
-
570
- /** Read a 0-d/1-elem boolean array to host (forces eval). */
571
- export function itemBool(a: MlxArray): boolean {
572
- const u = a.astype(Dtype.uint32);
573
- try {
574
- return itemUint32(u) !== 0;
575
- } finally {
576
- u.dispose();
577
- }
578
- }
579
-
580
- export function logicalAnd(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
581
- return new MlxArray(
582
- outArray("logical_and", (o) => C.mlx_logical_and(o, a.handle, b.handle, s)),
583
- );
584
- }
585
-
586
- export function zeros(shape: number[], dtype: Dtype, s: S = gpuStream): MlxArray {
587
- const buf = new Int32Array(shape);
588
- return new MlxArray(
589
- outArray("zeros", (o) => C.mlx_zeros(o, ptr(buf), BigInt(shape.length), dtype, s)),
590
- );
591
- }
592
-
593
- export function sliceUpdate(
594
- src: MlxArray, update: MlxArray, start: number[], stop: number[], s: S = gpuStream,
595
- ): MlxArray {
596
- const st = new Int32Array(start);
597
- const sp = new Int32Array(stop);
598
- const strides = new Int32Array(start.map(() => 1));
599
- return new MlxArray(
600
- outArray("slice_update", (o) =>
601
- C.mlx_slice_update(
602
- o, src.handle, update.handle,
603
- ptr(st), BigInt(st.length), ptr(sp), BigInt(sp.length),
604
- ptr(strides), BigInt(strides.length), s,
605
- ),
606
- ),
607
- );
608
- }
609
-
610
- /** mx.slice with start as an ARRAY and the output shape as constants —
611
- * the shapeless-compile-safe slice (mlx's Slice primitive cannot infer
612
- * output shapes; DynamicSlice's output shape IS sliceSize). Used only
613
- * inside compiled-decode traces for subrange slices whose bounds are
614
- * per-layer constants (full-range slices get simplified away and need
615
- * no substitute). Values identical to `slice`. */
616
- export function sliceDynamic(
617
- a: MlxArray, start: MlxArray, axes: number[], sliceSize: number[], s: S = gpuStream,
618
- ): MlxArray {
619
- const ax = new Int32Array(axes);
620
- const sz = new Int32Array(sliceSize);
621
- return new MlxArray(
622
- outArray("slice_dynamic", (o) =>
623
- C.mlx_slice_dynamic(
624
- o, a.handle, start.handle,
625
- ptr(ax), BigInt(ax.length), ptr(sz), BigInt(sz.length), s,
626
- ),
627
- ),
628
- );
629
- }
630
-
631
- /** slice_update with the start index as an ARRAY (one int32 per entry in
632
- * `axes`) — the compiled-decode form of the per-step cache write. Same
633
- * write as `sliceUpdate`; bit-exactness vs the static form is asserted
634
- * in tests/unit/compile.test.ts. */
635
- export function sliceUpdateDynamic(
636
- src: MlxArray, update: MlxArray, start: MlxArray, axes: number[], s: S = gpuStream,
637
- ): MlxArray {
638
- const ax = new Int32Array(axes);
639
- return new MlxArray(
640
- outArray("slice_update_dynamic", (o) =>
641
- C.mlx_slice_update_dynamic(
642
- o, src.handle, update.handle, start.handle,
643
- ptr(ax), BigInt(ax.length), s,
644
- ),
645
- ),
646
- );
647
- }
648
-
649
- export function randomKey(seed: bigint): MlxArray {
650
- return new MlxArray(outArray("random_key", (o) => C.mlx_random_key(o, seed)));
651
- }
652
-
653
- /** Set the GLOBAL mlx PRNG seed (mlx.core.random.seed). Calls to randint/etc
654
- * with a null key thread the global key, so seeding then calling in the same
655
- * order as the reference reproduces its draws bit-for-bit. */
656
- export function randomSeed(seed: bigint): void {
657
- if (C.mlx_random_seed(seed) !== 0) throw new Error(`mlx_random_seed failed: ${takeMlxError() ?? ""}`);
658
- }
659
-
660
- /** Uniform integers in [low, high) — mlx.core.random.randint. With key=null it
661
- * uses (and advances) the global key, matching mx.random.randint exactly. */
662
- export function randint(
663
- low: number, high: number, shape: number[], dtype: Dtype,
664
- key: MlxArray | null = null, s: S = gpuStream,
665
- ): MlxArray {
666
- const buf = new Int32Array(shape);
667
- const lo = MlxArray.fromInt32(new Int32Array([low]), []);
668
- const hi = MlxArray.fromInt32(new Int32Array([high]), []);
669
- try {
670
- return new MlxArray(
671
- outArray("random_randint", (o) =>
672
- C.mlx_random_randint(o, lo.handle, hi.handle, ptr(buf), BigInt(shape.length), dtype, key?.handle ?? 0n, s),
673
- ),
674
- );
675
- } finally {
676
- lo.dispose();
677
- hi.dispose();
678
- }
679
- }
680
-
681
- export function randomCategorical(logits: MlxArray, key: MlxArray | null, s: S = gpuStream): MlxArray {
682
- return new MlxArray(
683
- outArray("categorical", (o) =>
684
- C.mlx_random_categorical(o, logits.handle, -1, key?.handle ?? 0n, s),
685
- ),
686
- );
687
- }
688
-
689
- /** Eval several arrays in one call (e.g. cache state after a prefill chunk). */
690
- export function evalAll(arrays: MlxArray[]): void {
691
- const handles = new BigUint64Array(arrays.map((a) => a.handle));
692
- const vec = C.mlx_vector_array_new_data(ptr(handles), BigInt(arrays.length));
693
- try {
694
- if (C.mlx_eval(vec) !== 0) throw new Error(`mlx_eval failed: ${takeMlxError() ?? ""}`);
695
- } finally {
696
- C.mlx_vector_array_free(vec);
697
- }
698
- }
699
-
700
- /** Kick off async evaluation (decode pipelining). */
701
- export function asyncEvalAll(arrays: MlxArray[]): void {
702
- const handles = new BigUint64Array(arrays.map((a) => a.handle));
703
- const vec = C.mlx_vector_array_new_data(ptr(handles), BigInt(arrays.length));
704
- try {
705
- if (C.mlx_async_eval(vec) !== 0) throw new Error(`mlx_async_eval failed: ${takeMlxError() ?? ""}`);
706
- } finally {
707
- C.mlx_vector_array_free(vec);
708
- }
709
- }
710
-
711
- /** Read a scalar uint32 (forces eval). Hot per-token path: the out-param
712
- * is read back via read.u32, never out[0] (DFG stale-read bug — see
713
- * outArray in ffi.ts). */
714
- export function itemUint32(a: MlxArray): number {
715
- a.eval();
716
- const out = new Uint32Array(1);
717
- const p = ptr(out);
718
- if (C.mlx_array_item_uint32(p, a.handle) !== 0)
719
- throw new Error("mlx_array_item_uint32 failed");
720
- return read.u32(p, 0);
721
- }
722
-
723
- export function fromInt32(data: number[], shape: number[]): MlxArray {
724
- return MlxArray.fromInt32(new Int32Array(data), shape);
725
- }
726
-
727
- // --- quantized KV support (Phase 6) ---------------------------------------
728
-
729
- export interface QuantizedTensor {
730
- packed: MlxArray;
731
- scales: MlxArray;
732
- biases: MlxArray;
733
- }
734
-
735
- /** mx.quantize: w → (packed u32, scales, biases). `mode` defaults to the
736
- * mlx-standard "affine" scheme; the quantizer seam may pass others. */
737
- export function quantize(
738
- w: MlxArray, groupSize: number, bits: number, mode = "affine", s: S = gpuStream,
739
- ): QuantizedTensor {
740
- const slot = new BigUint64Array([C.mlx_vector_array_new()]);
741
- const slotPtr = ptr(slot);
742
- const status = C.mlx_quantize(
743
- slotPtr, w.handle, optInt(groupSize), optInt(bits), ptr(cstr(mode)), 0n, s,
744
- );
745
- if (status !== 0) throw new Error(`quantize failed: ${takeMlxError() ?? ""}`);
746
- const vec = read.u64(slotPtr, 0);
747
- const get = (i: number): MlxArray => {
748
- const aSlot = new BigUint64Array([C.mlx_array_new()]);
749
- const aPtr = ptr(aSlot);
750
- if (C.mlx_vector_array_get(aPtr, vec, BigInt(i)) !== 0)
751
- throw new Error("vector_array_get failed");
752
- return new MlxArray(read.u64(aPtr, 0));
753
- };
754
- try {
755
- return { packed: get(0), scales: get(1), biases: get(2) };
756
- } finally {
757
- C.mlx_vector_array_free(vec);
758
- }
759
- }
760
-
761
- // --- training: elementwise / reductions / random ------------------------
762
-
763
- /** Stops gradient flow through `a` (identity forward; ∂=0). DPO reference
764
- * logprobs are stop_gradient'd before the policy forward. */
765
- export function stopGradient(a: MlxArray, s: S = gpuStream): MlxArray {
766
- return new MlxArray(outArray("stop_gradient", (o) => C.mlx_stop_gradient(o, a.handle, s)));
767
- }
768
-
769
- export function log(a: MlxArray, s: S = gpuStream): MlxArray {
770
- return new MlxArray(outArray("log", (o) => C.mlx_log(o, a.handle, s)));
771
- }
772
-
773
- export function logaddexp(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
774
- return new MlxArray(outArray("logaddexp", (o) => C.mlx_logaddexp(o, a.handle, b.handle, s)));
775
- }
776
-
777
- export function sqrt(a: MlxArray, s: S = gpuStream): MlxArray {
778
- return new MlxArray(outArray("sqrt", (o) => C.mlx_sqrt(o, a.handle, s)));
779
- }
780
-
781
- export function rsqrt(a: MlxArray, s: S = gpuStream): MlxArray {
782
- return new MlxArray(outArray("rsqrt", (o) => C.mlx_rsqrt(o, a.handle, s)));
783
- }
784
-
785
- export function square(a: MlxArray, s: S = gpuStream): MlxArray {
786
- return new MlxArray(outArray("square", (o) => C.mlx_square(o, a.handle, s)));
787
- }
788
-
789
- export function abs(a: MlxArray, s: S = gpuStream): MlxArray {
790
- return new MlxArray(outArray("abs", (o) => C.mlx_abs(o, a.handle, s)));
791
- }
792
-
793
- /** Reduce-mean over all elements → scalar (keepdims=false) or [1,…]. */
794
- export function meanAll(a: MlxArray, keepdims = false, s: S = gpuStream): MlxArray {
795
- return new MlxArray(outArray("mean", (o) => C.mlx_mean(o, a.handle, keepdims, s)));
796
- }
797
-
798
- export function meanAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
799
- return new MlxArray(outArray("mean_axis", (o) => C.mlx_mean_axis(o, a.handle, axis, keepdims, s)));
800
- }
801
-
802
- export function clip(a: MlxArray, lo: MlxArray | null, hi: MlxArray | null, s: S = gpuStream): MlxArray {
803
- return new MlxArray(
804
- outArray("clip", (o) => C.mlx_clip(o, a.handle, lo?.handle ?? 0n, hi?.handle ?? 0n, s)),
805
- );
806
- }
807
-
808
- /** mx.random.normal(shape, dtype, loc, scale, key). key may be null. */
809
- export function randomNormal(
810
- shape: number[], dtype: Dtype, loc: number, scale: number,
811
- key: MlxArray | null, s: S = gpuStream,
812
- ): MlxArray {
813
- const buf = new Int32Array(shape);
814
- return new MlxArray(
815
- outArray("random_normal", (o) =>
816
- C.mlx_random_normal(o, ptr(buf), BigInt(shape.length), dtype, loc, scale, key?.handle ?? 0n, s),
817
- ),
818
- );
819
- }
820
-
821
- /** mx.random.uniform(low, high, shape, dtype, key). low/high are scalars.
822
- * Matches mlx-lm LoRALinear A init: uniform(-1/√in, +1/√in). */
823
- export function randomUniform(
824
- shape: number[], dtype: Dtype, low: number, high: number,
825
- key: MlxArray | null, s: S = gpuStream,
826
- ): MlxArray {
827
- const buf = new Int32Array(shape);
828
- const lo = MlxArray.fromFloat32(new Float32Array([low]), []);
829
- const hi = MlxArray.fromFloat32(new Float32Array([high]), []);
830
- try {
831
- return new MlxArray(
832
- outArray("random_uniform", (o) =>
833
- C.mlx_random_uniform(o, lo.handle, hi.handle, ptr(buf), BigInt(shape.length), dtype, key?.handle ?? 0n, s),
834
- ),
835
- );
836
- } finally {
837
- lo.dispose();
838
- hi.dispose();
839
- }
840
- }
841
-
842
- /** mx.random.split(key, num) → [num, 2] uint32 subkeys. */
843
- export function randomSplitNum(key: MlxArray, num: number, s: S = gpuStream): MlxArray {
844
- return new MlxArray(
845
- outArray("random_split", (o) => C.mlx_random_split_num(o, key.handle, num, s)),
846
- );
847
- }
848
-
849
- export function softmaxAxis(a: MlxArray, axis: number, precise: boolean, s: S = gpuStream): MlxArray {
850
- return new MlxArray(
851
- outArray("softmax", (o) => C.mlx_softmax_axis(o, a.handle, axis, precise, s)),
852
- );
853
- }
854
-
855
- export function maxAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
856
- return new MlxArray(
857
- outArray("max_axis", (o) => C.mlx_max_axis(o, a.handle, axis, keepdims, s)),
858
- );
859
- }
860
-
861
- export function sumAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
862
- return new MlxArray(
863
- outArray("sum_axis", (o) => C.mlx_sum_axis(o, a.handle, axis, keepdims, s)),
864
- );
865
- }
866
-
867
- /** View-preserving expand_dims (reshape on a non-contiguous view copies —
868
- * different kernel path, different reduction rounding; see Phase 6). */
869
- export function expandDims(a: MlxArray, axis: number, s: S = gpuStream): MlxArray {
870
- return new MlxArray(
871
- outArray("expand_dims", (o) => C.mlx_expand_dims(o, a.handle, axis, s)),
872
- );
873
- }
874
-
875
- export function maximum(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
876
- return new MlxArray(
877
- outArray("maximum", (o) => C.mlx_maximum(o, a.handle, b.handle, s)),
878
- );
879
- }
880
-
881
- /** quantized_matmul against a quantized tensor (x @ qt^T or x @ qt). */
882
- export function quantizedMatmulQT(
883
- x: MlxArray, qt: QuantizedTensor, transpose: boolean,
884
- groupSize: number, bits: number, s: S = gpuStream,
885
- ): MlxArray {
886
- return new MlxArray(
887
- outArray("quantized_matmul", (o) =>
888
- C.mlx_quantized_matmul(
889
- o, x.handle, qt.packed.handle, qt.scales.handle, qt.biases.handle,
890
- transpose, optInt(groupSize), optInt(bits), ptr(cstr("affine")), s,
891
- ),
892
- ),
893
- );
894
- }
895
-
896
- /** nn.Conv1d: input [B, L, C_in], weight [C_out, K, C_in/groups] → [B, L', C_out].
897
- * Depthwise (groups == channels) for the gated-DeltaNet causal conv; the model
898
- * left-pads with the conv-state cache, so padding is 0 here. */
899
- export function conv1d(
900
- input: MlxArray, weight: MlxArray, stride = 1, padding = 0, dilation = 1,
901
- groups = 1, s: S = gpuStream,
902
- ): MlxArray {
903
- return new MlxArray(
904
- outArray("conv1d", (o) =>
905
- C.mlx_conv1d(o, input.handle, weight.handle, stride, padding, dilation, groups, s),
906
- ),
907
- );
908
- }
909
-
910
- /** nn.Conv2d: input [B, H, W, C_in] (NHWC), weight [C_out, kH, kW, C_in/groups]
911
- * → [B, H', W', C_out]. mlx weight layout — the oracle transposes PyTorch's
912
- * [C_out, C_in, kH, kW] at load. For the gemma-4 audio SSCP subsampler. */
913
- export function conv2d(
914
- input: MlxArray, weight: MlxArray, stride: [number, number] = [1, 1],
915
- padding: [number, number] = [0, 0], dilation: [number, number] = [1, 1],
916
- groups = 1, s: S = gpuStream,
917
- ): MlxArray {
918
- return new MlxArray(
919
- outArray("conv2d", (o) =>
920
- C.mlx_conv2d(o, input.handle, weight.handle, stride[0], stride[1],
921
- padding[0], padding[1], dilation[0], dilation[1], groups, s),
922
- ),
923
- );
924
- }
925
-
926
- /** nn.Conv3d: input [B, D, H, W, C_in] (NDHWC), weight [C_out, kD, kH, kW,
927
- * C_in/groups] → [B, D', H', W', C_out]. The Qwen3-VL vision patch embed
928
- * (kernel == stride) — the conv KERNEL's accumulation order is the parity-
929
- * relevant arithmetic; a value-equivalent GEMM differs by bf16 ulp. */
930
- export function conv3d(
931
- input: MlxArray, weight: MlxArray,
932
- stride: [number, number, number] = [1, 1, 1],
933
- padding: [number, number, number] = [0, 0, 0],
934
- dilation: [number, number, number] = [1, 1, 1],
935
- groups = 1, s: S = gpuStream,
936
- ): MlxArray {
937
- return new MlxArray(
938
- outArray("conv3d", (o) =>
939
- C.mlx_conv3d(o, input.handle, weight.handle, stride[0], stride[1],
940
- stride[2], padding[0], padding[1], padding[2], dilation[0],
941
- dilation[1], dilation[2], groups, s),
942
- ),
943
- );
944
- }
945
-
946
- /** mx.split(a, indices, axis): split at the given boundary offsets along `axis`
947
- * into N+1 contiguous slices (mirrors numpy/mlx split-by-indices). */
948
- export function split(a: MlxArray, indices: number[], axis: number): MlxArray[] {
949
- const shape = a.shape;
950
- const ax = axis < 0 ? shape.length + axis : axis;
951
- const dim = shape[ax]!;
952
- const bounds = [0, ...indices, dim];
953
- const out: MlxArray[] = [];
954
- for (let i = 0; i < bounds.length - 1; i++) {
955
- const start = shape.map(() => 0);
956
- const stop = [...shape];
957
- start[ax] = bounds[i]!;
958
- stop[ax] = bounds[i + 1]!;
959
- out.push(a.slice(start, stop));
960
- }
961
- return out;
962
- }
963
-
964
- /** nn.softplus: log(1 + exp(x)) == logaddexp(x, 0). */
965
- export function softplus(a: MlxArray, s: S = gpuStream): MlxArray {
966
- const zero = scalarLike(0, a);
967
- const r = logaddexp(a, zero, s);
968
- zero.dispose();
969
- return r;
970
- }
971
-
972
- /** nn.silu: x * sigmoid(x). */
973
- export function silu(a: MlxArray, s: S = gpuStream): MlxArray {
974
- const sig = sigmoid(a, s);
975
- const r = mul(a, sig, s);
976
- sig.dispose();
977
- return r;
978
- }
979
-
980
- /** fast::hadamard_transform over the last axis. `scale` defaults to
981
- * 1/sqrt(dim) (mlx's own default when unset) — pass it explicitly to
982
- * match a reference that always states its normalization, per
983
- * turboquant-ops.ts's fwht(). */
984
- export function hadamardTransform(x: MlxArray, scale: number | null = null, s: S = gpuStream): MlxArray {
985
- return new MlxArray(
986
- outArray("hadamard_transform", (o) =>
987
- C.mlx_hadamard_transform(o, x.handle, optFloat(scale), s),
988
- ),
989
- );
990
- }
991
-
992
- export function minAxis(a: MlxArray, axis: number, keepdims: boolean, s: S = gpuStream): MlxArray {
993
- return new MlxArray(
994
- outArray("min_axis", (o) => C.mlx_min_axis(o, a.handle, axis, keepdims, s)),
995
- );
996
- }
997
-
998
- /** mx.round(x, decimals=0) — round-half-to-even at the ULP grid mlx uses. */
999
- export function round(a: MlxArray, s: S = gpuStream): MlxArray {
1000
- return new MlxArray(outArray("round", (o) => C.mlx_round(o, a.handle, 0, s)));
1001
- }
1002
-
1003
- export function greater(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1004
- return new MlxArray(outArray("greater", (o) => C.mlx_greater(o, a.handle, b.handle, s)));
1005
- }
1006
-
1007
- export function bitwiseAnd(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1008
- return new MlxArray(outArray("bitwise_and", (o) => C.mlx_bitwise_and(o, a.handle, b.handle, s)));
1009
- }
1010
-
1011
- export function bitwiseOr(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1012
- return new MlxArray(outArray("bitwise_or", (o) => C.mlx_bitwise_or(o, a.handle, b.handle, s)));
1013
- }
1014
-
1015
- export function leftShift(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1016
- return new MlxArray(outArray("left_shift", (o) => C.mlx_left_shift(o, a.handle, b.handle, s)));
1017
- }
1018
-
1019
- export function rightShift(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1020
- return new MlxArray(outArray("right_shift", (o) => C.mlx_right_shift(o, a.handle, b.handle, s)));
1021
- }
1022
-
1023
- // --- Whisper additions (fft / strided framing / pad / reductions) ----------
1024
-
1025
- /** mx.fft.rfft(a, n, axis) with numpy "backward" normalization. Real input
1026
- * → complex64 output of length n/2+1 along `axis`. */
1027
- export function rfft(a: MlxArray, n: number, axis = -1, s: S = gpuStream): MlxArray {
1028
- return new MlxArray(outArray("fft_rfft", (o) => C.mlx_fft_rfft(o, a.handle, n, axis, 0, s)));
1029
- }
1030
-
1031
- /** mx.as_strided(a, shape, strides, offset) — element strides. */
1032
- export function asStrided(
1033
- a: MlxArray, shape: number[], strides: number[], offset = 0, s: S = gpuStream,
1034
- ): MlxArray {
1035
- const shp = new Int32Array(shape);
1036
- const str = new BigInt64Array(strides.map((v) => BigInt(v)));
1037
- return new MlxArray(
1038
- outArray("as_strided", (o) =>
1039
- C.mlx_as_strided(o, a.handle, ptr(shp), BigInt(shape.length), ptr(str), BigInt(strides.length), BigInt(offset), s),
1040
- ),
1041
- );
1042
- }
1043
-
1044
- /** mx.pad(a, [(lo, hi), …]) with constant zero fill (all axes given). */
1045
- export function pad(a: MlxArray, widths: [number, number][], s: S = gpuStream): MlxArray {
1046
- const axes = new Int32Array(widths.map((_, i) => i));
1047
- const lo = new Int32Array(widths.map((w) => w[0]));
1048
- const hi = new Int32Array(widths.map((w) => w[1]));
1049
- const zero = scalarLike(0, a);
1050
- try {
1051
- return new MlxArray(
1052
- outArray("pad", (o) =>
1053
- C.mlx_pad(
1054
- o, a.handle, ptr(axes), BigInt(widths.length), ptr(lo), BigInt(widths.length),
1055
- ptr(hi), BigInt(widths.length), zero.handle, ptr(cstr("constant")), s,
1056
- ),
1057
- ),
1058
- );
1059
- } finally {
1060
- zero.dispose();
1061
- }
1062
- }
1063
-
1064
- export function log10(a: MlxArray, s: S = gpuStream): MlxArray {
1065
- return new MlxArray(outArray("log10", (o) => C.mlx_log10(o, a.handle, s)));
1066
- }
1067
-
1068
- /** Reduce-max over all elements → 0-d array (keepdims=false). */
1069
- export function maxAll(a: MlxArray, s: S = gpuStream): MlxArray {
1070
- return new MlxArray(outArray("max", (o) => C.mlx_max(o, a.handle, false, s)));
1071
- }
1072
-
1073
- export function broadcastTo(a: MlxArray, shape: number[], s: S = gpuStream): MlxArray {
1074
- const buf = new Int32Array(shape);
1075
- return new MlxArray(
1076
- outArray("broadcast_to", (o) => C.mlx_broadcast_to(o, a.handle, ptr(buf), BigInt(shape.length), s)),
1077
- );
1078
- }
1079
-
1080
- /** mx.topk(a, k, axis) — the k largest values along axis (unsorted). */
1081
- export function topkAxis(a: MlxArray, k: number, axis: number, s: S = gpuStream): MlxArray {
1082
- return new MlxArray(outArray("topk_axis", (o) => C.mlx_topk_axis(o, a.handle, k, axis, s)));
1083
- }
1084
-
1085
- export function varAxis(a: MlxArray, axis: number, keepdims: boolean, ddof = 0, s: S = gpuStream): MlxArray {
1086
- return new MlxArray(
1087
- outArray("var_axis", (o) => C.mlx_var_axis(o, a.handle, axis, keepdims, ddof, s)),
1088
- );
1089
- }
1090
-
1091
- export function stackAxis(arrays: MlxArray[], axis: number, s: S = gpuStream): MlxArray {
1092
- const handles = new BigUint64Array(arrays.map((a) => a.handle));
1093
- const vec = C.mlx_vector_array_new_data(ptr(handles), BigInt(arrays.length));
1094
- try {
1095
- return new MlxArray(outArray("stack_axis", (o) => C.mlx_stack_axis(o, vec, axis, s)));
1096
- } finally {
1097
- C.mlx_vector_array_free(vec);
1098
- }
1099
- }
1100
-
1101
- export function minimum(a: MlxArray, b: MlxArray, s: S = gpuStream): MlxArray {
1102
- return new MlxArray(outArray("minimum", (o) => C.mlx_minimum(o, a.handle, b.handle, s)));
1103
- }
1104
-
1105
- /** Flat mx.take(a, indices) — gathers from the flattened array. */
1106
- export function takeFlat(a: MlxArray, indices: MlxArray, s: S = gpuStream): MlxArray {
1107
- return new MlxArray(outArray("take", (o) => C.mlx_take(o, a.handle, indices.handle, s)));
1108
- }