mlx-bun 0.4.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 (601) hide show
  1. package/README.md +1453 -88
  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 +10 -8
  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 +12 -10
  78. package/src/{serve → server}/chat-stage.ts +27 -22
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +42 -42
  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 +42 -83
  85. package/src/server/generated-token-history.ts +57 -0
  86. package/src/{serve → server}/http.ts +25 -13
  87. package/src/{serve → server}/inference-request.ts +5 -5
  88. package/src/server/job-routes.ts +20 -0
  89. package/src/server/media-prompt.ts +63 -0
  90. package/src/server/memory-completion-client.ts +46 -0
  91. package/src/server/model-routes.ts +192 -0
  92. package/src/{serve → server}/openai-wire.ts +3 -2
  93. package/src/{serve → server}/pipeline.ts +1 -1
  94. package/src/server/prompt-builder.ts +13 -0
  95. package/src/server/prompt-contracts.ts +17 -0
  96. package/src/server/proxy-routes.ts +187 -0
  97. package/src/server/publishing-routes.ts +41 -0
  98. package/src/{serve → server}/request-plan.ts +8 -8
  99. package/src/{serve → server}/request-prep.ts +82 -68
  100. package/src/{serve → server}/responses-client.ts +30 -13
  101. package/src/{responses.ts → server/responses.ts} +12 -93
  102. package/src/server/routes.ts +205 -0
  103. package/src/server/start.ts +72 -0
  104. package/src/server/status-routes.ts +108 -0
  105. package/src/{serve → server}/text-completion-stage.ts +25 -4
  106. package/src/server/text-prompt.ts +12 -0
  107. package/src/{serve → server}/token-streams.ts +36 -38
  108. package/src/server/worker-routes.ts +311 -0
  109. package/src/storage/paths.ts +61 -0
  110. package/src/web/assets.ts +37 -0
  111. package/src/web/{src → browser}/api.ts +5 -23
  112. package/src/web/browser/chat-host.ts +17 -0
  113. package/src/web/browser/installed-panels.ts +6 -0
  114. package/src/web/browser/main.ts +55 -0
  115. package/src/web/browser/markdown.ts +279 -0
  116. package/src/web/browser/memory-panel.ts +9 -0
  117. package/src/web/browser/palette.ts +64 -0
  118. package/src/web/browser/protocol.ts +13 -0
  119. package/src/web/browser/shell.ts +467 -0
  120. package/src/web/{src → browser}/status.ts +32 -36
  121. package/src/web/build.ts +51 -0
  122. package/src/web/public/app.html +1054 -0
  123. package/src/web/{sw.js → public/sw.js} +4 -3
  124. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  125. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  126. package/THIRD_PARTY_LICENSES.md +0 -51
  127. package/docs/README.md +0 -94
  128. package/docs/archive/hlg-sampling.md +0 -350
  129. package/docs/archive/investigations/audio-input-plan.md +0 -356
  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/web-ui-pass-plan.md +0 -213
  174. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  175. package/docs/design/batching.md +0 -1841
  176. package/docs/design/decode-speed-program.md +0 -2349
  177. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  178. package/docs/design/generic-model-support.md +0 -705
  179. package/docs/design/kv-cache.md +0 -824
  180. package/docs/design/orpo-training.md +0 -680
  181. package/docs/design/speculative-decoding.md +0 -1990
  182. package/docs/design/turboquant.md +0 -2212
  183. package/docs/design/unified-engine-frontier-plan.md +0 -1880
  184. package/docs/design/web-chat-redesign.md +0 -695
  185. package/docs/planning/PRODUCT_ROADMAP.md +0 -594
  186. package/docs/planning/ResearchTopics.md +0 -119
  187. package/docs/planning/release-notes-v0.4.0.md +0 -45
  188. package/docs/planning/video-series.md +0 -421
  189. package/docs/reference/benchmarks.md +0 -3613
  190. package/docs/reference/cli.md +0 -585
  191. package/docs/reference/distribution.md +0 -355
  192. package/docs/reference/environment.md +0 -398
  193. package/docs/reference/glossary.md +0 -39
  194. package/docs/reference/library-api.md +0 -674
  195. package/docs/reference/memory.md +0 -260
  196. package/docs/reference/models.md +0 -334
  197. package/docs/reference/server-api.md +0 -1775
  198. package/docs/reference/server-config.md +0 -846
  199. package/docs/reference/training.md +0 -462
  200. package/docs/reference/troubleshooting.md +0 -158
  201. package/src/admission-plan.ts +0 -18
  202. package/src/audio/conformer.ts +0 -647
  203. package/src/audio/decode.ts +0 -133
  204. package/src/audio/features.ts +0 -202
  205. package/src/audio/transcode.ts +0 -67
  206. package/src/backends/mlx/assistant-target.ts +0 -46
  207. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  208. package/src/backends/mlx/autoregressive.ts +0 -108
  209. package/src/backends/mlx/batch-group.ts +0 -1790
  210. package/src/backends/mlx/cache-attachment.ts +0 -67
  211. package/src/backends/mlx/cache-layout.ts +0 -31
  212. package/src/backends/mlx/checkpoint-state.ts +0 -53
  213. package/src/backends/mlx/continuation-persistence.ts +0 -106
  214. package/src/backends/mlx/continuation-request.ts +0 -43
  215. package/src/backends/mlx/continuation.ts +0 -77
  216. package/src/backends/mlx/diffusion.ts +0 -39
  217. package/src/backends/mlx/draft-target.ts +0 -32
  218. package/src/backends/mlx/evaluation.ts +0 -105
  219. package/src/backends/mlx/fill-append.ts +0 -45
  220. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  221. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  222. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  223. package/src/backends/mlx/gateway-binding.ts +0 -130
  224. package/src/backends/mlx/graph.ts +0 -38
  225. package/src/backends/mlx/kv-codec.ts +0 -9
  226. package/src/backends/mlx/kv-maintenance.ts +0 -133
  227. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  228. package/src/backends/mlx/memory-client.ts +0 -189
  229. package/src/backends/mlx/methods.ts +0 -90
  230. package/src/backends/mlx/model-prompt.ts +0 -164
  231. package/src/backends/mlx/model-serving.ts +0 -79
  232. package/src/backends/mlx/prefill-cohort.ts +0 -89
  233. package/src/backends/mlx/prefill-rows.ts +0 -200
  234. package/src/backends/mlx/prefill.ts +0 -33
  235. package/src/backends/mlx/projected-context-rows.ts +0 -72
  236. package/src/backends/mlx/request-policy.ts +0 -20
  237. package/src/backends/mlx/request-state-policy.ts +0 -41
  238. package/src/backends/mlx/rollback.ts +0 -89
  239. package/src/backends/mlx/row-sampling.ts +0 -49
  240. package/src/backends/mlx/serial-executor.ts +0 -242
  241. package/src/backends/mlx/speculative-group.ts +0 -359
  242. package/src/backends/mlx/speculative-round.ts +0 -161
  243. package/src/backends/mlx/speculative.ts +0 -114
  244. package/src/backends/mlx/state-rows.ts +0 -104
  245. package/src/backends/mlx/state-views.ts +0 -46
  246. package/src/backends/mlx/target-layout-capability.ts +0 -35
  247. package/src/backends/mlx/text-engine.ts +0 -73
  248. package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
  249. package/src/chat-template.ts +0 -382
  250. package/src/cli.ts +0 -3168
  251. package/src/config.ts +0 -399
  252. package/src/contracts/completion.ts +0 -16
  253. package/src/contracts/execution.ts +0 -60
  254. package/src/contracts/generation.ts +0 -103
  255. package/src/contracts/host.ts +0 -7
  256. package/src/contracts/pi-provider.ts +0 -30
  257. package/src/contracts/pi.ts +0 -259
  258. package/src/contracts/prefix-cache.ts +0 -23
  259. package/src/contracts/resources.ts +0 -25
  260. package/src/contracts/sampling.ts +0 -23
  261. package/src/contracts/scheduling.ts +0 -45
  262. package/src/contracts/tsconfig.json +0 -14
  263. package/src/dataset/generators.ts +0 -1087
  264. package/src/dataset/index.ts +0 -12
  265. package/src/dataset/job.ts +0 -81
  266. package/src/dataset/llm.ts +0 -71
  267. package/src/dataset/registry.ts +0 -528
  268. package/src/diffusion/diffusion-generate.ts +0 -507
  269. package/src/download.ts +0 -505
  270. package/src/embed.ts +0 -77
  271. package/src/engine/admission.ts +0 -59
  272. package/src/engine/cancellation.ts +0 -38
  273. package/src/engine/engine.ts +0 -56
  274. package/src/engine/execution-coordinator.ts +0 -70
  275. package/src/engine/execution-plan.ts +0 -53
  276. package/src/engine/resources.ts +0 -53
  277. package/src/engine/scheduler.ts +0 -72
  278. package/src/engine/session.ts +0 -247
  279. package/src/eval/README.md +0 -130
  280. package/src/eval/ifeval.ts +0 -81
  281. package/src/eval/kl-prompts.ts +0 -29
  282. package/src/eval/kl.ts +0 -590
  283. package/src/eval/perplexity.ts +0 -164
  284. package/src/eval/quality-db.ts +0 -92
  285. package/src/eval/reference-logits.ts +0 -207
  286. package/src/eval/runner.ts +0 -124
  287. package/src/eval/score.ts +0 -49
  288. package/src/eval/tasks/bfcl.ts +0 -535
  289. package/src/eval/tasks/gsm8k.ts +0 -98
  290. package/src/eval/tasks/hashhop.ts +0 -139
  291. package/src/eval/tasks/humaneval.ts +0 -275
  292. package/src/eval/tasks/ifeval.ts +0 -525
  293. package/src/eval/tasks/mmlu.ts +0 -157
  294. package/src/eval/ultrafeedback.ts +0 -60
  295. package/src/evaldb.ts +0 -199
  296. package/src/expert-io.ts +0 -393
  297. package/src/expert-offload-build.ts +0 -77
  298. package/src/expert-offload.ts +0 -76
  299. package/src/expert-residency.ts +0 -1134
  300. package/src/expert-usage.ts +0 -415
  301. package/src/fill/echo-index.ts +0 -188
  302. package/src/fill/fill-session.ts +0 -452
  303. package/src/fill/proposal.ts +0 -68
  304. package/src/fill/schema-rows.ts +0 -506
  305. package/src/fill/tool-boundary.ts +0 -103
  306. package/src/fit.ts +0 -249
  307. package/src/generate.ts +0 -1346
  308. package/src/grammar.ts +0 -591
  309. package/src/harness-pi.ts +0 -184
  310. package/src/hf-push.ts +0 -628
  311. package/src/hub-rest.ts +0 -242
  312. package/src/index.ts +0 -63
  313. package/src/inference/denoising.ts +0 -17
  314. package/src/inference/draft-acceptance.ts +0 -41
  315. package/src/inference/draft-output.ts +0 -49
  316. package/src/inference/graph.ts +0 -33
  317. package/src/inference/prefill.ts +0 -39
  318. package/src/inference/rollback.ts +0 -7
  319. package/src/jobs/index.ts +0 -31
  320. package/src/jobs/job-entry.ts +0 -107
  321. package/src/jobs/task-client.ts +0 -19
  322. package/src/jobs/types.ts +0 -2
  323. package/src/kv-scheme.ts +0 -257
  324. package/src/kv-store.ts +0 -1099
  325. package/src/lab/README.md +0 -18
  326. package/src/lab/curve/curve-designer.html +0 -303
  327. package/src/lab/curve/curve-sampler.ts +0 -122
  328. package/src/lab/expert-trace/expert-trace.ts +0 -69
  329. package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
  330. package/src/lab/paged-kv/paged-kv.ts +0 -270
  331. package/src/library.ts +0 -40
  332. package/src/lora.ts +0 -408
  333. package/src/md-modules.d.ts +0 -49
  334. package/src/media-fetch.ts +0 -442
  335. package/src/memory/article.ts +0 -558
  336. package/src/memory/chunk-validation.ts +0 -150
  337. package/src/memory/chunk.ts +0 -318
  338. package/src/memory/cluster.ts +0 -351
  339. package/src/memory/coverage.ts +0 -134
  340. package/src/memory/crosslink.ts +0 -0
  341. package/src/memory/db.ts +0 -253
  342. package/src/memory/entity.ts +0 -203
  343. package/src/memory/gate.ts +0 -187
  344. package/src/memory/history.ts +0 -152
  345. package/src/memory/ingest.ts +0 -335
  346. package/src/memory/model.ts +0 -183
  347. package/src/memory/normalize.ts +0 -671
  348. package/src/memory/parse.ts +0 -22
  349. package/src/memory/pipeline.ts +0 -275
  350. package/src/memory/prompts.ts +0 -65
  351. package/src/memory/query.ts +0 -334
  352. package/src/memory/reconcile.ts +0 -734
  353. package/src/memory/redirect.ts +0 -108
  354. package/src/memory/reindex.ts +0 -325
  355. package/src/memory/resolve.ts +0 -307
  356. package/src/memory/rest.ts +0 -245
  357. package/src/memory/route.ts +0 -272
  358. package/src/memory/schedule.ts +0 -165
  359. package/src/memory/stages.ts +0 -777
  360. package/src/memory/synthesize.ts +0 -1638
  361. package/src/memory/tools.ts +0 -749
  362. package/src/memory/vault.ts +0 -1194
  363. package/src/memory/wikify.ts +0 -1064
  364. package/src/mlx/array.ts +0 -388
  365. package/src/mlx/autograd.ts +0 -304
  366. package/src/mlx/checkpoint.ts +0 -149
  367. package/src/mlx/compile.ts +0 -168
  368. package/src/mlx/custom-vjp.ts +0 -188
  369. package/src/mlx/ffi.ts +0 -512
  370. package/src/mlx/materialize.ts +0 -23
  371. package/src/mlx/metal-kernel.ts +0 -159
  372. package/src/mlx/ops.ts +0 -1021
  373. package/src/mlx/quantized-rows.ts +0 -36
  374. package/src/mlx/token-bitmask.ts +0 -52
  375. package/src/mlx/turboquant-kv-decode.ts +0 -82
  376. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  377. package/src/mlx/turboquant-ops.ts +0 -861
  378. package/src/mlx/turboquant-tables.ts +0 -237
  379. package/src/mmap.ts +0 -90
  380. package/src/model/artifact-identity.ts +0 -73
  381. package/src/model/batched-kv.ts +0 -235
  382. package/src/model/batched-mask.ts +0 -279
  383. package/src/model/batched-quant.ts +0 -212
  384. package/src/model/batched-quantized-kv.ts +0 -144
  385. package/src/model/batched-rotating-quant.ts +0 -353
  386. package/src/model/batched-rotating-state.ts +0 -149
  387. package/src/model/batched-rotating.ts +0 -338
  388. package/src/model/batched-row-storage.ts +0 -179
  389. package/src/model/batched-ssm.ts +0 -52
  390. package/src/model/batched-turboquant-kv.ts +0 -93
  391. package/src/model/compiled-decode.ts +0 -712
  392. package/src/model/decoded-kv-donor.ts +0 -12
  393. package/src/model/delayed-quantized-kv.ts +0 -72
  394. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  395. package/src/model/delayed-turboquant-kv.ts +0 -55
  396. package/src/model/diffusion-gemma.ts +0 -1026
  397. package/src/model/factory.ts +0 -189
  398. package/src/model/fingerprint.ts +0 -33
  399. package/src/model/flash-attention.ts +0 -694
  400. package/src/model/full-prefill-padding.ts +0 -56
  401. package/src/model/full-prefill-row.ts +0 -105
  402. package/src/model/gemma4-base.ts +0 -2351
  403. package/src/model/gemma4.ts +0 -1315
  404. package/src/model/generated/gemma4-12b.ts +0 -429
  405. package/src/model/generated/gemma4-26b.ts +0 -448
  406. package/src/model/generated/gemma4-e4b.ts +0 -717
  407. package/src/model/generated/index.ts +0 -18
  408. package/src/model/glm52-atlas.ts +0 -511
  409. package/src/model/glm52-cache.ts +0 -792
  410. package/src/model/glm52-config.ts +0 -262
  411. package/src/model/glm52-container.ts +0 -305
  412. package/src/model/glm52-coupling.ts +0 -388
  413. package/src/model/glm52-dsa.ts +0 -606
  414. package/src/model/glm52-expert-layout.ts +0 -253
  415. package/src/model/glm52-layout.ts +0 -152
  416. package/src/model/glm52-memory.ts +0 -500
  417. package/src/model/glm52-mla.ts +0 -792
  418. package/src/model/glm52-moe.ts +0 -223
  419. package/src/model/glm52-pilot.ts +0 -537
  420. package/src/model/glm52-reference.ts +0 -445
  421. package/src/model/glm52-residency.ts +0 -557
  422. package/src/model/glm52-resident-weights.ts +0 -135
  423. package/src/model/glm52-streamed-experts.ts +0 -453
  424. package/src/model/glm52-streamed-metal.ts +0 -610
  425. package/src/model/glm52-weights.ts +0 -503
  426. package/src/model/glm52.ts +0 -1132
  427. package/src/model/implementation.ts +0 -69
  428. package/src/model/kv-attention-view.ts +0 -67
  429. package/src/model/minicpm5.ts +0 -376
  430. package/src/model/profile.ts +0 -443
  431. package/src/model/qwen-append.ts +0 -12
  432. package/src/model/qwen-conv.ts +0 -52
  433. package/src/model/qwen3-delta-state.ts +0 -74
  434. package/src/model/qwen3-delta.ts +0 -451
  435. package/src/model/qwen3-moe.ts +0 -404
  436. package/src/model/qwen3-mrope.ts +0 -252
  437. package/src/model/qwen3.ts +0 -277
  438. package/src/model/qwen3_5-checkpoint.ts +0 -164
  439. package/src/model/qwen3_5.ts +0 -819
  440. package/src/model/rotating-kv-donor.ts +0 -35
  441. package/src/model/rotating-kv-layout.ts +0 -262
  442. package/src/model/rotating-row-transaction.ts +0 -35
  443. package/src/model/speculative-rotating-kv.ts +0 -101
  444. package/src/model/ssm-prefill-padding.ts +0 -39
  445. package/src/model/support.ts +0 -102
  446. package/src/model/trellis-balanced-scatter.ts +0 -51
  447. package/src/model/trellis-linear.ts +0 -672
  448. package/src/model/trellis-shared-m.ts +0 -151
  449. package/src/model/trellis-shared-scatter.ts +0 -144
  450. package/src/model/trellis-splitk-prefill.ts +0 -158
  451. package/src/model/trellis-tiled-prefill.ts +0 -136
  452. package/src/model/trellis-vector-expand.ts +0 -62
  453. package/src/model/trellis-wide-prefill.ts +0 -94
  454. package/src/model/turboquant-codec.ts +0 -83
  455. package/src/model/universal/archs.ts +0 -332
  456. package/src/model/universal/dense.ts +0 -612
  457. package/src/model/universal/modules.ts +0 -170
  458. package/src/model/universal/rope.ts +0 -381
  459. package/src/native/expert_io.c +0 -523
  460. package/src/native/frame_extract.swift +0 -140
  461. package/src/native-pack.ts +0 -162
  462. package/src/pi-provider.ts +0 -53
  463. package/src/pi-session.ts +0 -81
  464. package/src/pi-terminal.ts +0 -274
  465. package/src/pi-web.ts +0 -1932
  466. package/src/preflight.ts +0 -158
  467. package/src/prompt-cache.ts +0 -460
  468. package/src/quantize/allocator.ts +0 -627
  469. package/src/quantize/atomic-output.ts +0 -38
  470. package/src/quantize/calibration.ts +0 -181
  471. package/src/quantize/config-writer.ts +0 -145
  472. package/src/quantize/index.ts +0 -84
  473. package/src/quantize/job.ts +0 -162
  474. package/src/quantize/quantizer.ts +0 -666
  475. package/src/quantize/rotate.ts +0 -603
  476. package/src/quantize/safetensors-writer.ts +0 -249
  477. package/src/quantize/sensitivity.ts +0 -216
  478. package/src/quantize/trellis.ts +0 -586
  479. package/src/quantize/weight-transform.ts +0 -292
  480. package/src/registry.ts +0 -602
  481. package/src/runtime-config.ts +0 -81
  482. package/src/safetensors.ts +0 -158
  483. package/src/sampler.ts +0 -1011
  484. package/src/serve/admin-routes.ts +0 -184
  485. package/src/serve/assets/curve-terrain.html +0 -105
  486. package/src/serve/assets/training-inference-map.html +0 -575
  487. package/src/serve/aux-routes.ts +0 -132
  488. package/src/serve/batch-scheduler.ts +0 -8
  489. package/src/serve/checkpoint-identity.ts +0 -64
  490. package/src/serve/generation-gateway.ts +0 -496
  491. package/src/serve/isolate.ts +0 -609
  492. package/src/serve/kv-budget.ts +0 -14
  493. package/src/serve/lab-routes.ts +0 -341
  494. package/src/serve/lane-registry.ts +0 -45
  495. package/src/serve/model-admin-routes.ts +0 -155
  496. package/src/serve/model-binding.ts +0 -43
  497. package/src/serve/model-host.ts +0 -511
  498. package/src/serve/parent-application.ts +0 -56
  499. package/src/serve/prompt-response-trace.ts +0 -147
  500. package/src/serve/response-lease.ts +0 -24
  501. package/src/serve/session-search.ts +0 -326
  502. package/src/serve/static-routes.ts +0 -101
  503. package/src/server.ts +0 -1314
  504. package/src/spec/assistant-rows.ts +0 -92
  505. package/src/spec/assistant-source.ts +0 -126
  506. package/src/spec/cache-identity.ts +0 -22
  507. package/src/spec/deepspec-rows.ts +0 -29
  508. package/src/spec/deepspec-source.ts +0 -145
  509. package/src/spec/dflash-source.ts +0 -149
  510. package/src/spec/drafter.ts +0 -304
  511. package/src/spec/dspark/ab-stats.ts +0 -136
  512. package/src/spec/dspark/calibration.ts +0 -112
  513. package/src/spec/dspark/data-dflash.ts +0 -156
  514. package/src/spec/dspark/data.ts +0 -201
  515. package/src/spec/dspark/deepspec-module.ts +0 -776
  516. package/src/spec/dspark/generate-dflash.ts +0 -245
  517. package/src/spec/dspark/generate.ts +0 -290
  518. package/src/spec/dspark/loader.ts +0 -23
  519. package/src/spec/dspark/loss.ts +0 -213
  520. package/src/spec/dspark/module-dflash.ts +0 -560
  521. package/src/spec/dspark/module.ts +0 -540
  522. package/src/spec/dspark/quantize-drafter.ts +0 -91
  523. package/src/spec/dspark/sample.ts +0 -112
  524. package/src/spec/generate.ts +0 -276
  525. package/src/spec/glm52-mtp-graph.ts +0 -29
  526. package/src/spec/glm52-mtp-rows.ts +0 -132
  527. package/src/spec/glm52-mtp-source.ts +0 -317
  528. package/src/spec/glm52-mtp-state.ts +0 -33
  529. package/src/spec/ngram-source.ts +0 -204
  530. package/src/spec/projected-draft-rows.ts +0 -73
  531. package/src/spec/qwen-mtp-module.ts +0 -171
  532. package/src/spec/qwen-mtp-rows.ts +0 -219
  533. package/src/spec/qwen-mtp-source.ts +0 -383
  534. package/src/spec/qwen-mtp-state.ts +0 -30
  535. package/src/spec/serve-loop.ts +0 -585
  536. package/src/spec/source.ts +0 -215
  537. package/src/spec/two-model-rows.ts +0 -61
  538. package/src/spec/two-model.ts +0 -113
  539. package/src/ssd-cache.ts +0 -372
  540. package/src/ssd-durability.ts +0 -211
  541. package/src/tokenizer.ts +0 -335
  542. package/src/tool-approvals.ts +0 -131
  543. package/src/tool-call.ts +0 -695
  544. package/src/train/dataset.ts +0 -484
  545. package/src/train/diffusion-lora.ts +0 -216
  546. package/src/train/export.ts +0 -32
  547. package/src/train/flash-cce.ts +0 -1234
  548. package/src/train/forward.ts +0 -266
  549. package/src/train/fuse.ts +0 -243
  550. package/src/train/index.ts +0 -46
  551. package/src/train/job.ts +0 -205
  552. package/src/train/lora-params.ts +0 -254
  553. package/src/train/loss.ts +0 -1591
  554. package/src/train/merge.ts +0 -195
  555. package/src/train/optimizer.ts +0 -183
  556. package/src/train/prefix-shared.ts +0 -490
  557. package/src/train/rank.ts +0 -137
  558. package/src/train/segmented.ts +0 -1828
  559. package/src/train/steel-qmm-header.ts +0 -1461
  560. package/src/train/trainer.ts +0 -1221
  561. package/src/train/watch.ts +0 -542
  562. package/src/vision/diffusion-vision.ts +0 -620
  563. package/src/vision/embedder.ts +0 -168
  564. package/src/vision/preprocess.ts +0 -247
  565. package/src/vision/prompt.ts +0 -373
  566. package/src/vision/qwen3vl-preprocess.ts +0 -409
  567. package/src/vision/qwen3vl-prompt.ts +0 -196
  568. package/src/vision/qwen3vl-tower.ts +0 -555
  569. package/src/vision/siglip.ts +0 -599
  570. package/src/vision/video-frames.ts +0 -148
  571. package/src/web/app.html +0 -2143
  572. package/src/web/app.js +0 -5703
  573. package/src/web/skills/memory/SKILL.md +0 -120
  574. package/src/web/skills/web-research/SKILL.md +0 -46
  575. package/src/web/skills.ts +0 -97
  576. package/src/web/src/adapters-panel.ts +0 -288
  577. package/src/web/src/assistant.ts +0 -451
  578. package/src/web/src/chat.ts +0 -1057
  579. package/src/web/src/composer.ts +0 -959
  580. package/src/web/src/dataset.ts +0 -132
  581. package/src/web/src/finetune.ts +0 -267
  582. package/src/web/src/hub.ts +0 -428
  583. package/src/web/src/main.ts +0 -98
  584. package/src/web/src/markdown.ts +0 -0
  585. package/src/web/src/memory-panel.ts +0 -572
  586. package/src/web/src/model-picker.ts +0 -159
  587. package/src/web/src/palette.ts +0 -346
  588. package/src/web/src/protocol.ts +0 -26
  589. package/src/web/src/quantize.ts +0 -167
  590. package/src/web/src/rag.ts +0 -274
  591. package/src/web/src/sessions.ts +0 -469
  592. package/src/web/src/shell.ts +0 -804
  593. package/src/web/src/ui-catalog.ts +0 -78
  594. package/src/web/vendor/README.md +0 -61
  595. package/src/web-assets.ts +0 -47
  596. package/src/web-tools.ts +0 -478
  597. package/src/weights.ts +0 -255
  598. /package/src/{serve → server}/completion-sink.ts +0 -0
  599. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  600. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  601. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
package/src/lab/README.md DELETED
@@ -1,18 +0,0 @@
1
- # src/lab — quarantined, no-oracle code
2
-
3
- Everything here is a Lab-tier module (docs/design/unified-engine-frontier-plan.md):
4
- no external oracle, off by default, kept only while a measurement decides its
5
- fate (PLAN.md "Maintainability program", D6 darlings). Rules, gate-enforced by
6
- `scripts/check-hygiene.ts` (check 11):
7
-
8
- - nothing outside `src/lab/` may import from `src/lab/` except the edges listed
9
- in `LAB_IMPORT_ALLOWLIST` — those are recorded debt, not permission;
10
- - a new production dependency on a Lab module is a decision, not a default:
11
- either promote the module out of the lab with an oracle/measurement, or
12
- route it through an option seam.
13
-
14
- | module | flag / entry | oracle |
15
- |---|---|---|
16
- | `curve/` (curve sampler + designer page) | `--curve-*`, `/curves` | none (Lab) |
17
- | `paged-kv/` | `--paged-kv` (serial-only) | parity vs plain KVCache (bit-exact), no measured win |
18
- | `expert-trace/` | `MLX_BUN_EXPERT_TRACE` hook in gemma4 | closed study (expert-offload) |
@@ -1,303 +0,0 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8">
2
- <meta name="viewport" content="width=device-width,initial-scale=1">
3
- <title>HLG Curve Designer</title>
4
- <style>
5
- :root{--text:#1f2937;--text2:#475569;--text3:#94a3b8;--bg:#f7f9fc;--card:#fff;--bd:#e2e8f0;
6
- --accent:#2563eb;--accent2:#0891b2;--pos:#16a34a;--warn:#d97706;--danger:#dc2626;--grid:#eef2f7;}
7
- *{box-sizing:border-box}
8
- body{margin:0;background:var(--bg);color:var(--text);font:13.5px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
9
- .wrap{max-width:1240px;margin:0 auto;padding:18px 20px 70px}
10
- .head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:14px}
11
- h1{font-size:19px;margin:0;letter-spacing:-.01em}
12
- .head a.back{font-size:12px;color:var(--accent);text-decoration:none}
13
- .head .desc{color:var(--text2);font-size:13px}
14
- .engine{margin-left:auto;display:flex;align-items:center;gap:7px;font-size:12px}
15
- .engine input{font:12px ui-monospace,Menlo,monospace;border:1px solid var(--bd);border-radius:7px;padding:6px 8px;width:230px;background:var(--card)}
16
- .engine .dot{width:8px;height:8px;border-radius:50%;background:var(--text3)}
17
- .engine .dot.ok{background:var(--pos)} .engine .dot.bad{background:var(--danger)}
18
- .cols{display:grid;grid-template-columns:minmax(440px,1fr) 1fr;gap:18px;align-items:start}
19
- @media(max-width:920px){.cols{grid-template-columns:1fr}}
20
- .card{background:var(--card);border:1px solid var(--bd);border-radius:14px;padding:14px 16px;box-shadow:0 1px 2px rgba(15,23,42,.04),0 10px 30px -24px rgba(15,23,42,.2)}
21
- .card h2{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--text2);margin:0 0 10px;display:flex;align-items:center;gap:10px}
22
- svg.plot{width:100%;height:auto;display:block;touch-action:none;cursor:crosshair}
23
- .slopes{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin:10px 0 4px}
24
- .slopes .s{background:var(--grid);border-radius:9px;padding:6px 8px}
25
- .slopes .s .k{font-size:9px;text-transform:uppercase;letter-spacing:.03em;color:var(--text3)}
26
- .slopes .s .v{font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
27
- .slopes .s .t{font-size:9.5px}
28
- .copyrow{display:flex;gap:7px;align-items:center;margin-top:12px}
29
- .copyrow input{flex:1;font:11px ui-monospace,Menlo,monospace;border:1px solid var(--bd);border-radius:7px;padding:7px 8px;background:var(--grid)}
30
- button.primary{background:var(--accent);color:#fff;border:0;border-radius:9px;padding:9px 16px;font:700 13px inherit;cursor:pointer}
31
- button.primary:disabled{opacity:.55;cursor:default}
32
- button.ghost{background:var(--card);border:1px solid var(--bd);border-radius:8px;padding:7px 11px;font:600 12px inherit;color:var(--text2);cursor:pointer}
33
- .prompt{width:100%;font:13px inherit;border:1px solid var(--bd);border-radius:9px;padding:9px 10px;resize:vertical;min-height:54px;background:var(--card)}
34
- .pchips{display:flex;gap:6px;flex-wrap:wrap;margin:8px 0}
35
- .pchips button{font:600 11px/1 inherit;padding:6px 9px;border:1px solid var(--bd);background:var(--grid);border-radius:7px;cursor:pointer;color:var(--text2)}
36
- .genrow{display:flex;gap:10px;align-items:center;margin:10px 0;flex-wrap:wrap}
37
- .genrow .mini{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text2)}
38
- .genrow .mini input{width:56px;font:12px inherit;border:1px solid var(--bd);border-radius:6px;padding:5px 6px}
39
- .samples{display:flex;flex-direction:column;gap:8px;margin-top:6px}
40
- .samp{font-size:13.5px;background:var(--grid);border-radius:9px;padding:9px 11px;border-left:3px solid var(--accent);white-space:pre-wrap}
41
- .samp.junk{border-left-color:var(--danger);background:#fef6f6}
42
- .samp .tag{font-size:10px;font-weight:700;color:var(--danger);float:right}
43
- .status{font-size:12px;color:var(--text3);min-height:16px}
44
- .note{font-size:11.5px;color:var(--text3);margin-top:10px;line-height:1.5}
45
- .testcard{border:1px solid var(--bd);border-radius:12px;padding:13px 15px;margin:6px 0;background:linear-gradient(180deg,#f4f8ff,#fff)}
46
- .testcard .opt{font-size:14px;background:var(--card);border:1px solid var(--bd);border-radius:9px;padding:10px 12px;margin:7px 0;cursor:pointer;display:flex;gap:9px;transition:border-color .12s}
47
- .testcard .opt:hover{border-color:var(--accent2)}
48
- .testcard .opt .lab{font-weight:800;color:var(--accent2);flex:none}
49
- .testcard .opt.picked{border-color:var(--accent2);box-shadow:0 0 0 2px rgba(8,145,178,.15)}
50
- .testcard .opt .reveal{margin-left:auto;font-size:11px;font-weight:700;flex:none;align-self:center}
51
- .testcard .q{font-size:12.5px;font-weight:600;margin:4px 0 2px}
52
- .testcard .verdict{font-size:13px;font-weight:700;margin-top:8px;min-height:18px}
53
- </style></head>
54
- <body><div class="wrap">
55
- <div class="head">
56
- <h1>HLG Curve Designer</h1>
57
- <a class="back" href="/" id="backLink" style="display:none">← mlx-bun</a>
58
- <span class="desc">Drag the curve over the signal → generate → read prose → adjust.</span>
59
- <span class="engine"><span class="dot" id="engdot"></span>engine <input id="engine"></span>
60
- </div>
61
- <div class="cols">
62
- <div class="card">
63
- <h2>Transfer curve <span style="font-weight:400;text-transform:none;letter-spacing:0;color:var(--text3)">x = p_in, y = p_out (log) · diagonal = temperature 1 · the gray histogram is the real next-token signal</span></h2>
64
- <svg class="plot" id="plot" viewBox="0 0 460 360"></svg>
65
- <div class="slopes" id="slopeReadout"></div>
66
- <div id="baselineHint" style="font-size:11.5px;font-weight:600;margin:4px 0 0"></div>
67
- <div class="copyrow"><input id="cfgField" readonly><button class="ghost" id="copyBtn">Copy values</button><button class="ghost" id="resetBtn">Reset</button><span id="copyOk" style="color:var(--pos);font-weight:700;font-size:11px"></span></div>
68
- <div class="note">Five movable control points; drag any of them (including the corners). It always stays a smooth monotone curve. <b>Above the diagonal</b> raises those tokens, <b>below</b> lowers them; drag a point down over the histogram's tail to gate it.</div>
69
- </div>
70
- <div class="card">
71
- <h2>Generate</h2>
72
- <textarea class="prompt" id="prompt">Write the first sentence of a short story about a lighthouse keeper who discovers something strange in the fog.</textarea>
73
- <div class="pchips" id="pchips"></div>
74
- <div class="genrow">
75
- <button class="primary" id="genBtn">Generate</button>
76
- <button class="primary" id="testBtn" style="background:var(--accent2)" title="One sentence from the default recipe, one from your curve — unlabeled. Guess which is which.">Test (blind)</button>
77
- <button class="ghost" id="sigBtn">↻ load signal</button>
78
- <button class="ghost" id="copyTextBtn" style="display:none">Copy text</button>
79
- <span class="mini">N <input id="nSamp" type="number" min="1" max="8" value="4"></span>
80
- <span class="mini">seed <input id="seed" type="number" value="100"></span>
81
- <span class="status" id="status"></span>
82
- </div>
83
- <div id="testArea"></div>
84
- <div class="samples" id="samples"></div>
85
- <div class="note">Samples are a <b>feel-check</b>, not evidence — easy to overfit. The blind two-judge eval stays the verdict.</div>
86
- </div>
87
- </div>
88
-
89
- <script>
90
- const ln=Math.log;
91
- const UMIN=ln(1e-6); // bottom-left / plot floor (matches src/lab/curve/curve-sampler.ts CURVE_UMIN)
92
- const ENGINE_BASE = location.protocol.startsWith("http") ? location.origin : "http://localhost:8080";
93
- // ---- curve state: 5 movable control points, sorted ascending in p_in ----
94
- function identityPoints(){ return [{x_pct:1e-4,y_pct:1e-4},{x_pct:0.1,y_pct:0.1},{x_pct:1,y_pct:1},{x_pct:9,y_pct:9},{x_pct:100,y_pct:100}]; }
95
- let C = { space:"logprob", points:identityPoints(), monotonic:true };
96
- let SIGNAL=null; // {bins:[], vocab}
97
- let LAST=null; // {prompt, curve, samples} of the most recent generation
98
- const PROMPTS=[
99
- "Write the first sentence of a short story about a lighthouse keeper who discovers something strange in the fog.",
100
- "In one sentence, what causes the seasons on Earth?",
101
- "Give one unusual but genuinely plausible use for a paperclip, in a sentence.",
102
- "Describe the feeling of a city at 3am in one vivid sentence.",
103
- ];
104
-
105
- // ---- math: monotone cubic (PCHIP), IDENTICAL to src/lab/curve/curve-sampler.ts ----
106
- const Lp=pt=>[ln(Math.max(pt.x_pct,1e-9)/100),ln(Math.max(pt.y_pct,1e-9)/100)];
107
- function knotArrays(c){ const k=c.points.map(Lp).sort((a,b)=>a[0]-b[0]); return {X:k.map(q=>q[0]),Y:k.map(q=>q[1])}; }
108
- function secants(c){ const {X,Y}=knotArrays(c),s=[]; for(let i=X.length-1;i>0;i--)s.push((Y[i]-Y[i-1])/(X[i]-X[i-1])); return s; }
109
- function monotone(c){ return secants(c).every(s=>s>=-1e-12); }
110
- // identity = every control point on the diagonal ⇒ generate with the model's DEFAULT
111
- // chat recipe (the real "what you'd get chatting" baseline), not a literal temp-1 curve.
112
- function isIdentity(c){ return c.points.every(p=>Math.abs(ln(Math.max(p.x_pct,1e-9))-ln(Math.max(p.y_pct,1e-9)))<0.03); }
113
- function cubicInU(x0,h,y0,y1,m0,m1){ const c0=y0,c1=h*m0,c2=-3*y0-2*h*m0+3*y1-h*m1,c3=2*y0+h*m0-2*y1+h*m1; const s=1/h,s2=s*s,s3=s2*s; let A=c0,B=0,C=0,D=0; B+=c1*s;A+=-c1*s*x0; C+=c2*s2;B+=-2*x0*c2*s2;A+=x0*x0*c2*s2; D+=c3*s3;C+=-3*x0*c3*s3;B+=3*x0*x0*c3*s3;A+=-x0*x0*x0*c3*s3; return {A,B,C,D}; }
114
- function buildSpline(c){ const {X,Y}=knotArrays(c),n=X.length,D=[];
115
- for(let i=0;i<n-1;i++)D.push((Y[i+1]-Y[i])/(X[i+1]-X[i]));
116
- const M=new Array(n); M[0]=D[0]; M[n-1]=D[n-2];
117
- for(let i=1;i<n-1;i++){ if(D[i-1]*D[i]<=0){M[i]=0;continue;} const h1=X[i]-X[i-1],h2=X[i+1]-X[i],w1=2*h2+h1,w2=h2+2*h1; M[i]=(w1+w2)/(w1/D[i-1]+w2/D[i]); }
118
- const segs=[]; for(let i=0;i<n-1;i++)segs.push(cubicInU(X[i],X[i+1]-X[i],Y[i],Y[i+1],M[i],M[i+1])); return {X,Y,M,segs}; }
119
- function evalSpline(sp,u){ const n=sp.X.length;
120
- if(u<sp.X[0])return sp.Y[0]+Math.max(sp.M[0],1)*(u-sp.X[0]);
121
- if(u>sp.X[n-1])return sp.Y[n-1]+sp.M[n-1]*(u-sp.X[n-1]);
122
- let i=sp.segs.length-1; while(i>0&&u<sp.X[i])i--; const s=sp.segs[i]; return s.A+s.B*u+s.C*u*u+s.D*u*u*u; }
123
-
124
- // ---- plot mapping ----
125
- const VBW=460,VBH=360,PL=46,PR=14,PT=14,PB=34, FLOOR=1e-4;
126
- // The data domain [UMIN,0] maps EXACTLY onto the box, so its corners ARE the data
127
- // extremes: the first control point lives in the bottom-left corner, the last in
128
- // the top-right. Dragging an endpoint keeps it welded to the box edge — its X is
129
- // pinned (see clampPoint) and Y slides along that edge, like a tone-curve endpoint.
130
- const px=u=>PL+(1-u/UMIN)*(VBW-PL-PR), py=u=>PT+(u/UMIN)*(VBH-PT-PB);
131
- const uX=mx=>UMIN*(1-(mx-PL)/(VBW-PL-PR)), uY=my=>UMIN*((my-PT)/(VBH-PT-PB)), pct=u=>Math.exp(u)*100;
132
- const TICKS=[100,10,1,0.1,0.01,0.001,0.0001]; // 0.0001% = UMIN = the box floor/left edge, so the corner is labeled
133
- const PCOL=["#94a3b8","#0891b2","#7c3aed","#2563eb","#94a3b8"]; // endpoint, knee, center, shoulder, endpoint
134
-
135
- function draw(){
136
- let s=`<defs><clipPath id="plotclip"><rect x="${PL}" y="${PT}" width="${VBW-PL-PR}" height="${VBH-PT-PB}"/></clipPath></defs>`;
137
- // signal histogram (behind)
138
- if(SIGNAL&&SIGNAL.bins){ const b=SIGNAL.bins,NB=b.length,maxc=Math.max(...b,1),hz=(VBH-PT-PB)*0.55,base=VBH-PB;
139
- for(let i=0;i<NB;i++){ if(!b[i])continue; const x0=px(UMIN*(1-i/NB)),x1=px(UMIN*(1-(i+1)/NB)); const hgt=ln(1+b[i])/ln(1+maxc)*hz;
140
- s+=`<rect x="${Math.min(x0,x1)}" y="${base-hgt}" width="${Math.abs(x1-x0)+0.4}" height="${hgt}" fill="var(--text3)" opacity="0.26"/>`; } }
141
- for(const p of TICKS){ const u=ln(p/100);
142
- s+=`<line x1="${px(u)}" y1="${PT}" x2="${px(u)}" y2="${VBH-PB}" stroke="var(--grid)"/><line x1="${PL}" y1="${py(u)}" x2="${VBW-PR}" y2="${py(u)}" stroke="var(--grid)"/>`;
143
- s+=`<text x="${px(u)}" y="${VBH-PB+13}" text-anchor="middle" font-size="8.5" fill="var(--text3)">${p}%</text>`;
144
- s+=`<text x="${PL-9}" y="${py(u)+3}" text-anchor="end" font-size="8.5" fill="var(--text3)">${p}%</text>`; }
145
- s+=`<text x="${(PL+VBW-PR)/2}" y="${VBH-3}" text-anchor="middle" font-size="10" fill="var(--text2)">p_in (model's true probability)</text>`;
146
- s+=`<line x1="${px(UMIN)}" y1="${py(UMIN)}" x2="${px(0)}" y2="${py(0)}" stroke="var(--text3)" stroke-width="1.4" stroke-dasharray="5 4"/>`;
147
- // smooth clipped curve
148
- const sp=buildSpline(C); let d="";
149
- for(let i=0;i<=240;i++){ const u=UMIN*(1-i/240); const v=Math.max(Math.min(evalSpline(sp,u),0),UMIN*1.25); d+=(i?"L":"M")+px(u).toFixed(1)+" "+py(v).toFixed(1)+" "; }
150
- s+=`<g clip-path="url(#plotclip)"><path d="${d}" fill="none" stroke="var(--accent)" stroke-width="2.6"/></g>`;
151
- // 5 control points
152
- C.points.forEach((p,i)=>{ const u=Lp(p); const col=PCOL[Math.min(i,PCOL.length-1)];
153
- s+=`<circle class="kp" data-i="${i}" cx="${px(u[0])}" cy="${py(u[1])}" r="7" fill="${col}" stroke="#fff" stroke-width="2" style="cursor:grab"/>`; });
154
- document.getElementById("plot").innerHTML=s;
155
- bindDrag(); drawSlopes(); document.getElementById("cfgField").value=cfgJSON();
156
- document.getElementById("baselineHint").innerHTML = isIdentity(C)
157
- ? '<span style="color:var(--pos)">● identity</span> — Generate uses the model’s <b>default chat recipe</b> (temp + top-p + top-k): the real baseline.'
158
- : '<span style="color:var(--accent)">● custom curve</span> — Generate replaces temperature+softmax with your curve.';
159
- }
160
- function drawSlopes(){
161
- const sc=secants(C); const names=["head","upper-mid","lower-mid","shadows"];
162
- const cell=(k,sl)=>{ const t=sl<0.97?"flatten":sl>1.03?"sharpen":"≈ identity", col=sl<0.97?"var(--pos)":sl>1.03?"var(--danger)":"var(--text2)";
163
- return `<div class="s"><div class="k">${k}</div><div class="v">${sl.toFixed(2)}</div><div class="t" style="color:${col}">${t}</div></div>`; };
164
- document.getElementById("slopeReadout").innerHTML=sc.slice(0,4).map((sl,i)=>cell(names[i]||("seg"+i),sl)).join("");
165
- }
166
-
167
- function clampPoint(i){
168
- const P=C.points, n=P.length, lo=i>0?P[i-1]:null, hi=i<n-1?P[i+1]:null;
169
- if(i===0) P[i].x_pct=FLOOR; // first point welded to the LEFT edge of the box
170
- else if(i===n-1) P[i].x_pct=100; // last point welded to the RIGHT edge of the box
171
- else P[i].x_pct=Math.max(lo.x_pct*1.03, Math.min(hi.x_pct*0.97, P[i].x_pct));
172
- P[i].y_pct=Math.max(lo?lo.y_pct*1.03:FLOOR, Math.min(hi?hi.y_pct*0.97:100, P[i].y_pct));
173
- }
174
- function bindDrag(){
175
- const svg=document.getElementById("plot");
176
- svg.querySelectorAll(".kp").forEach(el=>{
177
- el.addEventListener("pointerdown",ev=>{ ev.preventDefault(); el.setPointerCapture(ev.pointerId);
178
- clearGeneratedState();
179
- const i=+el.dataset.i, rect=svg.getBoundingClientRect();
180
- const move=e=>{ const mx=(e.clientX-rect.left)*(VBW/rect.width), my=(e.clientY-rect.top)*(VBH/rect.height);
181
- C.points[i].x_pct=Math.min(100,Math.max(FLOOR,pct(uX(mx)))); C.points[i].y_pct=Math.min(100,Math.max(FLOOR,pct(uY(my)))); clampPoint(i); draw(); };
182
- const up=()=>{ try{el.releasePointerCapture(ev.pointerId)}catch(_){}; window.removeEventListener("pointermove",move); window.removeEventListener("pointerup",up); };
183
- window.addEventListener("pointermove",move); window.addEventListener("pointerup",up);
184
- });
185
- });
186
- }
187
- function cfgJSON(){ return JSON.stringify({space:"logprob",points:C.points.map(p=>({x_pct:+p.x_pct.toFixed(4),y_pct:+p.y_pct.toFixed(5)})),monotonic:true}); }
188
- function clearGeneratedState(status=""){
189
- document.getElementById("samples").innerHTML="";
190
- document.getElementById("testArea").innerHTML="";
191
- document.getElementById("copyTextBtn").style.display="none";
192
- document.getElementById("status").textContent=status;
193
- LAST=null; TESTST=null;
194
- }
195
-
196
- // ---- server calls ----
197
- const engBase=()=>document.getElementById("engine").value.replace(/\/(generate|signal)\/?$/,"");
198
- async function probe(){ const dot=document.getElementById("engdot");
199
- try{ const r=await fetch(engBase()+"/v1"); dot.className="dot "+(r.ok?"ok":"bad"); }catch(_){ dot.className="dot bad"; } }
200
- async function loadSignal(){
201
- const st=document.getElementById("status");
202
- try{ const r=await fetch(engBase()+"/signal",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({prompt:document.getElementById("prompt").value})});
203
- if(!r.ok)return; const j=await r.json(); SIGNAL=j; draw(); st.textContent="signal loaded ("+(j.vocab||"?")+" tokens)"; setTimeout(()=>{if(st.textContent.startsWith("signal"))st.textContent=""},1800);
204
- }catch(_){ /* engine not up — no histogram */ }
205
- }
206
- async function generate(){
207
- const btn=document.getElementById("genBtn"), st=document.getElementById("status"), out=document.getElementById("samples");
208
- clearGeneratedState();
209
- if(!monotone(C)){ st.textContent="curve not monotone."; return; }
210
- btn.disabled=true; const baseline=isIdentity(C); st.textContent=baseline?"generating (model default)…":"generating…"; out.innerHTML="";
211
- const payload={ prompt:document.getElementById("prompt").value,
212
- n:Math.max(1,Math.min(8,+document.getElementById("nSamp").value||4)), seed:+document.getElementById("seed").value||100, max_tokens:90,
213
- ...(baseline?{default:true}:{curve:JSON.parse(cfgJSON())}) };
214
- try{
215
- const r=await fetch(engBase()+"/generate",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(payload)});
216
- const j=await r.json();
217
- if(!r.ok){ st.textContent="engine error: "+(j.error||r.status); btn.disabled=false; return; }
218
- const tag = j.mode==="default"&&j.recipe ? `model default · T=${j.recipe.temperature} top-p=${j.recipe.topP} top-k=${j.recipe.topK}` : "your curve";
219
- st.textContent=`${tag} · ${j.samples.length} samples · seed ${j.seed}`;
220
- out.innerHTML=j.samples.map((x,i)=>`<div class="samp${x.junk?" junk":""}">${x.junk?'<span class="tag">JUNK</span>':""}<b>${i+1}.</b> ${esc(x.text)}</div>`).join("");
221
- LAST={ prompt:payload.prompt, mode:j.mode, recipe:j.recipe, curve:cfgJSON(), samples:j.samples };
222
- document.getElementById("copyTextBtn").style.display="inline";
223
- }catch(e){ st.textContent="cannot reach engine — is the server running? "+e.message; }
224
- btn.disabled=false;
225
- }
226
- function esc(s){ return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }
227
-
228
- // ---- blind test: 1 sentence from the default recipe + 1 from the curve, unlabeled, guess which ----
229
- async function postGen(payload){
230
- const r=await fetch(engBase()+"/generate",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(payload)});
231
- const j=await r.json(); if(!r.ok) throw new Error(j.error||r.status); return j;
232
- }
233
- let TESTST=null; // {prompt, opts:[A,B], curveSlot, guessed}
234
- async function runTest(){
235
- const tb=document.getElementById("testBtn"), st=document.getElementById("status"), area=document.getElementById("testArea");
236
- if(!monotone(C)){ st.textContent="curve not monotone."; return; }
237
- if(isIdentity(C)){ st.textContent="shape the curve first — identity IS the default, nothing to compare."; return; }
238
- tb.disabled=true; st.textContent="testing (default vs curve)…"; area.innerHTML="";
239
- const prompt=document.getElementById("prompt").value, fld=+document.getElementById("seed").value||0;
240
- // Fresh INDEPENDENT seeds each run, so repeated Tests give a new pair (not the same
241
- // two sentences with their A/B position flipped). Combined with the coin flip below
242
- // this makes the randomness self-evident — no fixed "curve sentence" to track.
243
- const seedD=fld+Math.floor(Math.random()*1e6), seedC=fld+Math.floor(Math.random()*1e6);
244
- try{
245
- const [d,c]=await Promise.all([
246
- postGen({prompt,default:true,n:1,seed:seedD,max_tokens:60}),
247
- postGen({prompt,curve:JSON.parse(cfgJSON()),n:1,seed:seedC,max_tokens:60}),
248
- ]);
249
- const dText=d.samples[0].text, cText=c.samples[0].text, curveFirst=Math.random()<0.5;
250
- TESTST={ prompt, opts:[ curveFirst?cText:dText, curveFirst?dText:cText ], curveSlot: curveFirst?0:1, guessed:false };
251
- renderTestCard(); st.textContent="blind pair ready — which is your curve?";
252
- }catch(e){ st.textContent="test failed: "+e.message; }
253
- tb.disabled=false;
254
- }
255
- function renderTestCard(){
256
- const area=document.getElementById("testArea"), T=TESTST;
257
- area.innerHTML=`<div class="testcard">
258
- <div class="opt" data-s="0"><span class="lab">A</span><span>${esc(T.opts[0])}</span><span class="reveal" id="rv0"></span></div>
259
- <div class="opt" data-s="1"><span class="lab">B</span><span>${esc(T.opts[1])}</span><span class="reveal" id="rv1"></span></div>
260
- <div class="q">Which came from <b>your curve</b>? (the other is the model's default recipe)</div>
261
- <div style="display:flex;gap:8px"><button class="ghost" data-g="0">It's A</button><button class="ghost" data-g="1">It's B</button><button class="ghost" id="copyPairBtn" style="margin-left:auto">Copy pair (blind)</button></div>
262
- <div class="verdict" id="verdict"></div></div>`;
263
- area.querySelectorAll("button[data-g]").forEach(b=>b.addEventListener("click",()=>guess(+b.dataset.g)));
264
- area.querySelector("#copyPairBtn").addEventListener("click",copyPair);
265
- }
266
- function guess(slot){
267
- const T=TESTST; if(!T||T.guessed)return; T.guessed=true;
268
- document.getElementById("rv"+T.curveSlot).innerHTML='<span style="color:var(--accent2)">← your curve</span>';
269
- document.getElementById("rv"+(1-T.curveSlot)).innerHTML='<span style="color:var(--text3)">← model default</span>';
270
- document.querySelectorAll(".testcard .opt")[slot].classList.add("picked");
271
- document.getElementById("verdict").innerHTML = slot===T.curveSlot
272
- ? '<span style="color:var(--pos)">✓ Correct — you picked your curve.</span>'
273
- : '<span style="color:var(--danger)">✗ Nope — that was the model default; your curve was '+(T.curveSlot===0?"A":"B")+'.</span>';
274
- }
275
- function copyPair(){
276
- const T=TESTST; if(!T)return;
277
- const txt="Prompt: "+T.prompt+"\n\nA: "+T.opts[0]+"\nB: "+T.opts[1]+"\n\n(one is a custom log-prob sampling curve, the other the model's default recipe — which is which?)";
278
- const v=document.getElementById("verdict"), prev=v.innerHTML, done=()=>{v.innerHTML='<span style="color:var(--pos)">pair copied ✓ (blind — paste to a judge)</span>';setTimeout(()=>{v.innerHTML=prev},1700);};
279
- if(navigator.clipboard)navigator.clipboard.writeText(txt).then(done,done); else { const ta=document.createElement("textarea"); ta.value=txt; document.body.appendChild(ta); ta.select(); try{document.execCommand("copy")}catch(_){}; ta.remove(); done(); }
280
- }
281
-
282
- // ---- wiring ----
283
- document.getElementById("engine").value=ENGINE_BASE+"/generate";
284
- if(location.protocol.startsWith("http")) document.getElementById("backLink").style.display="inline";
285
- document.getElementById("pchips").innerHTML=PROMPTS.map((p,i)=>`<button data-i="${i}">${p.slice(0,38)}…</button>`).join("");
286
- document.getElementById("pchips").querySelectorAll("button").forEach(b=>b.addEventListener("click",()=>{document.getElementById("prompt").value=PROMPTS[+b.dataset.i];clearGeneratedState();loadSignal();}));
287
- document.getElementById("genBtn").addEventListener("click",generate);
288
- document.getElementById("testBtn").addEventListener("click",runTest);
289
- document.getElementById("sigBtn").addEventListener("click",loadSignal);
290
- document.getElementById("copyTextBtn").addEventListener("click",()=>{ if(!LAST)return;
291
- const sampler = LAST.mode==="default"&&LAST.recipe ? "Sampler: model default recipe (T="+LAST.recipe.temperature+", top-p="+LAST.recipe.topP+", top-k="+LAST.recipe.topK+")" : "Curve: "+LAST.curve;
292
- const txt="Prompt: "+LAST.prompt+"\n"+sampler+"\n\n"+LAST.samples.map((s,i)=>(i+1)+". "+(s.junk?"[JUNK] ":"")+s.text).join("\n\n");
293
- const st=document.getElementById("status"), done=()=>{st.textContent="text copied ✓";setTimeout(()=>{if(st.textContent==="text copied ✓")st.textContent=""},1500);};
294
- if(navigator.clipboard)navigator.clipboard.writeText(txt).then(done,done); else { const ta=document.createElement("textarea"); ta.value=txt; document.body.appendChild(ta); ta.select(); try{document.execCommand("copy")}catch(_){}; ta.remove(); done(); } });
295
- document.getElementById("resetBtn").addEventListener("click",()=>{C.points=identityPoints();draw();clearGeneratedState();});
296
- document.getElementById("copyBtn").addEventListener("click",()=>{ const f=document.getElementById("cfgField"); f.select();
297
- const ok=document.getElementById("copyOk"), done=()=>{ok.textContent="Copied!";setTimeout(()=>ok.textContent="",1500);};
298
- if(navigator.clipboard)navigator.clipboard.writeText(f.value).then(done,()=>{document.execCommand("copy");done();}); else {document.execCommand("copy");done();} });
299
- document.getElementById("engine").addEventListener("change",()=>{clearGeneratedState();probe();loadSignal();});
300
- document.getElementById("prompt").addEventListener("change",()=>{clearGeneratedState();loadSignal();});
301
- draw(); probe(); loadSignal();
302
- </script>
303
- </body></html>
@@ -1,122 +0,0 @@
1
- // curve-sampler.ts — the v2 log-prob transfer-curve sampler. Replaces the whole
2
- // temperature+softmax stage with a drawn MONOTONE CUBIC curve in log-probability
3
- // space:
4
- //
5
- // p_out_i = exp(curve(log p_in_i)) / Σ_j exp(curve(log p_in_j))
6
- //
7
- // `lp` reaching the sampler is already log p_in (toLogprobs = logits − logsumexp),
8
- // so the curve maps it directly and an identity curve reproduces temperature 1.
9
- // The curve is a Fritsch–Carlson monotone cubic Hermite (PCHIP) through N movable
10
- // control points in nat log-prob space (DaVinci-curves style — the endpoints start
11
- // at the corners but are draggable too). Smooth, never overshoots, monotone. A
12
- // control point dragged below the diagonal suppresses those tokens; the gate is
13
- // emergent from the curve shape, not a separate threshold.
14
- //
15
- // Reading the curve: at a given p_in, ABOVE the diagonal raises those tokens,
16
- // BELOW lowers them (renorm makes the literal number an intent); the SLOPE across
17
- // a region sets how evenly the tokens inside it spread (flat<1 even, steep>1 separated).
18
-
19
- import { MlxArray } from "../../mlx/array";
20
- import * as ops from "../../mlx/ops";
21
-
22
- export interface CurvePoint { x_pct: number; y_pct: number; }
23
- export interface CurveParams {
24
- space?: "logprob";
25
- points: CurvePoint[]; // ≥2 control points, all movable; first/last are the endpoints
26
- monotonic?: boolean;
27
- }
28
-
29
- /** Bottom-left default anchor / plot floor (p = 1e-6). */
30
- export const CURVE_UMIN = Math.log(1e-6);
31
- const L = (pt: CurvePoint): [number, number] => [Math.log(Math.max(pt.x_pct, 1e-9) / 100), Math.log(Math.max(pt.y_pct, 1e-9) / 100)];
32
-
33
- /** Control points in nat log-prob space, sorted ascending in x. */
34
- function knotArrays(p: CurveParams): { X: number[]; Y: number[] } {
35
- const k = p.points.map(L).sort((a, b) => a[0] - b[0]);
36
- return { X: k.map((q) => q[0]), Y: k.map((q) => q[1]) };
37
- }
38
-
39
- /** Consecutive-point secants, top→bottom (region slopes; what the editor readout shows). */
40
- export function curveSecants(p: CurveParams): number[] {
41
- const { X, Y } = knotArrays(p);
42
- const s: number[] = [];
43
- for (let i = X.length - 1; i > 0; i--) s.push((Y[i]! - Y[i - 1]!) / (X[i]! - X[i - 1]!));
44
- return s;
45
- }
46
- /** True iff every consecutive-point secant is ≥ 0 (monotone non-decreasing). */
47
- export function isMonotone(p: CurveParams): boolean {
48
- return p.points.length >= 2 && curveSecants(p).every((s) => s >= -1e-12);
49
- }
50
-
51
- interface Seg { A: number; B: number; C: number; D: number } // cubic in u: A+Bu+Cu²+Du³
52
- export interface Spline { X: number[]; Y: number[]; M: number[]; segs: Seg[] }
53
-
54
- function cubicInU(x0: number, h: number, y0: number, y1: number, m0: number, m1: number): Seg {
55
- const c0 = y0, c1 = h * m0;
56
- const c2 = -3 * y0 - 2 * h * m0 + 3 * y1 - h * m1;
57
- const c3 = 2 * y0 + h * m0 - 2 * y1 + h * m1;
58
- const s = 1 / h, s2 = s * s, s3 = s2 * s;
59
- let A = c0, B = 0, C = 0, D = 0;
60
- B += c1 * s; A += -c1 * s * x0;
61
- C += c2 * s2; B += -2 * x0 * c2 * s2; A += x0 * x0 * c2 * s2;
62
- D += c3 * s3; C += -3 * x0 * c3 * s3; B += 3 * x0 * x0 * c3 * s3; A += -x0 * x0 * x0 * c3 * s3;
63
- return { A, B, C, D };
64
- }
65
-
66
- /** Monotone cubic (Fritsch–Carlson) over the N control points. */
67
- export function buildSpline(p: CurveParams): Spline {
68
- const { X, Y } = knotArrays(p);
69
- const n = X.length;
70
- const Dsec: number[] = [];
71
- for (let i = 0; i < n - 1; i++) Dsec.push((Y[i + 1]! - Y[i]!) / (X[i + 1]! - X[i]!));
72
- const M = new Array<number>(n);
73
- M[0] = Dsec[0]!; M[n - 1] = Dsec[n - 2]!;
74
- for (let i = 1; i < n - 1; i++) {
75
- if (Dsec[i - 1]! * Dsec[i]! <= 0) { M[i] = 0; continue; }
76
- const h1 = X[i]! - X[i - 1]!, h2 = X[i + 1]! - X[i]!;
77
- const w1 = 2 * h2 + h1, w2 = h2 + 2 * h1;
78
- M[i] = (w1 + w2) / (w1 / Dsec[i - 1]! + w2 / Dsec[i]!);
79
- }
80
- const segs: Seg[] = [];
81
- for (let i = 0; i < n - 1; i++) segs.push(cubicInU(X[i]!, X[i + 1]! - X[i]!, Y[i]!, Y[i + 1]!, M[i]!, M[i + 1]!));
82
- return { X, Y, M, segs };
83
- }
84
-
85
- /** Scalar eval (editor preview / tests). Extrapolates linearly past both endpoints. */
86
- export function evalSpline(sp: Spline, u: number): number {
87
- const n = sp.X.length;
88
- if (u < sp.X[0]!) return sp.Y[0]! + Math.max(sp.M[0]!, 1) * (u - sp.X[0]!); // deep tail: slope ≥1, stays gated
89
- if (u > sp.X[n - 1]!) return sp.Y[n - 1]! + sp.M[n - 1]! * (u - sp.X[n - 1]!);
90
- let i = sp.segs.length - 1;
91
- while (i > 0 && u < sp.X[i]!) i--;
92
- const s = sp.segs[i]!;
93
- return s.A + s.B * u + s.C * u * u + s.D * u * u * u;
94
- }
95
- export function curveAt(p: CurveParams, u: number): number { return evalSpline(buildSpline(p), u); }
96
-
97
- /** Apply the monotone-cubic transfer to normalized logprobs `lp` [.., V] (on-device). */
98
- export function applyCurve(lp: MlxArray, p: CurveParams): MlxArray {
99
- const sp = buildSpline(p);
100
- const n = sp.X.length;
101
- const tmp: MlxArray[] = [];
102
- const k = <T extends MlxArray>(a: T): T => { tmp.push(a); return a; };
103
- const C = (v: number): MlxArray => k(ops.scalarLike(v, lp));
104
- const lp2 = k(ops.mul(lp, lp));
105
- const lp3 = k(ops.mul(lp2, lp));
106
- const seg = (s: Seg): MlxArray => k(ops.add(
107
- k(ops.add(C(s.A), k(ops.mulScalar(lp, s.B)))),
108
- k(ops.add(k(ops.mulScalar(lp2, s.C)), k(ops.mulScalar(lp3, s.D)))),
109
- ));
110
- // below the bottom point: slope ≥ 1 (deep tail stays gated)
111
- const lowSlope = Math.max(sp.M[0]!, 1);
112
- let out: MlxArray = k(ops.add(C(sp.Y[0]! - lowSlope * sp.X[0]!), k(ops.mulScalar(lp, lowSlope))));
113
- for (let i = 0; i < sp.segs.length; i++) {
114
- const next = ops.where(k(ops.greaterEqual(lp, C(sp.X[i]!))), seg(sp.segs[i]!), out);
115
- tmp.push(next); out = next;
116
- }
117
- // above the top point: linear extrapolation with the top tangent (if it was dragged left of 100%)
118
- const aboveExt = k(ops.add(C(sp.Y[n - 1]! - sp.M[n - 1]! * sp.X[n - 1]!), k(ops.mulScalar(lp, sp.M[n - 1]!))));
119
- const result = ops.where(k(ops.greaterEqual(lp, C(sp.X[n - 1]!))), aboveExt, out);
120
- for (const a of tmp) a.dispose();
121
- return result;
122
- }
@@ -1,69 +0,0 @@
1
- // E0 expert-routing tracer (PLAN Phase 19 — expert offload).
2
- //
3
- // Records every MoE router decision as JSONL — one record per router call:
4
- // { c: callSeq, l: layerIdx, s: [B, L, k], i: [flattened uint32 expert ids] }
5
- // Analyse with analyze-expert-trace.ts (deleted 2026-08-23; git history) (coverage curve, working-set
6
- // size, within-task stability, cross-task specialisation).
7
- //
8
- // Two ways to drive it:
9
- // - env: `MLX_BUN_EXPERT_TRACE=<path> mlx-bun serve ...` (auto-starts here)
10
- // - programmatic: beginExpertTrace(path) / endExpertTrace() per domain
11
- // (run-expert-trace.ts (deleted 2026-08-23; git history) uses this to trace several domains from
12
- // one model load).
13
- //
14
- // Recording adds a per-call GPU->host sync (it reads the routed indices back),
15
- // so a traced run decodes slower — it's a MEASUREMENT tool, not a serving
16
- // path. When no trace is active, isExpertTracing() is false and the hook in
17
- // Router.forward is a single branch (zero overhead) — inert by default, same
18
- // discipline as the slots flag.
19
-
20
- import { Dtype } from "../../mlx/ffi";
21
- import type { MlxArray } from "../../mlx/array";
22
- import { runtimeValue } from "../../runtime-config";
23
-
24
- let sink: Bun.FileSink | null = null;
25
- let seq = 0;
26
- let written = 0;
27
-
28
- export function beginExpertTrace(path: string): void {
29
- if (sink) endExpertTrace();
30
- sink = Bun.file(path).writer();
31
- seq = 0;
32
- written = 0;
33
- sink.write(JSON.stringify({ meta: "mlx-bun-expert-trace-v1", note: "one record per router call" }) + "\n");
34
- process.stderr.write(`[expert-trace] recording -> ${path}\n`);
35
- }
36
-
37
- export function endExpertTrace(): void {
38
- if (!sink) return;
39
- sink.flush();
40
- sink.end();
41
- process.stderr.write(`[expert-trace] wrote ${written} records (${seq} calls)\n`);
42
- sink = null;
43
- }
44
-
45
- /** Alias kept for the process-exit handler / env callers. */
46
- export const finishExpertTrace = endExpertTrace;
47
-
48
- export function isExpertTracing(): boolean {
49
- return sink !== null;
50
- }
51
-
52
- /** Record one router decision. `indices` is [B, L, k] uint32 (expert ids). */
53
- export function recordRouting(layer: number, indices: MlxArray): void {
54
- if (!sink) return;
55
- const shape = indices.shape; // [B, L, k]
56
- const f = indices.astype(Dtype.float32); // ids <=127 are exact in f32
57
- const data = f.toFloat32();
58
- f.dispose();
59
- const ids = new Array<number>(data.length);
60
- for (let i = 0; i < data.length; i++) ids[i] = Math.round(data[i]!);
61
- sink.write(JSON.stringify({ c: seq++, l: layer, s: shape, i: ids }) + "\n");
62
- if (++written % 2000 === 0) sink.flush();
63
- }
64
-
65
- const expertTracePath = runtimeValue("MLX_BUN_EXPERT_TRACE");
66
- if (expertTracePath) beginExpertTrace(expertTracePath);
67
-
68
- process.on("exit", () => { try { endExpertTrace(); } catch { /* best-effort */ } });
69
- process.on("SIGINT", () => { endExpertTrace(); process.exit(0); });
@@ -1,83 +0,0 @@
1
- import type { BatchableCache, Cache, Mask } from "../../model/gemma4-base";
2
- import { buildBatchedDecodeMask, mergeKVRows } from "../../model/batched-mask";
3
- import { MlxArray } from "../../mlx/array";
4
- import { disposeResources } from "../../engine/resources";
5
- import { PagedKVCache, poolBlocksFor } from "./paged-kv";
6
-
7
- /** Block storage owns row membership; attention consumes the same gathered
8
- * K/V representation as the existing paged cache. No scheduler policy here. */
9
- export class PagedKvRows implements BatchableCache {
10
- #rows: PagedKVCache[] = [];
11
- #rope?: MlxArray;
12
- #ropeOffset = -1;
13
-
14
- constructor(readonly capacityTokens: number, readonly blockSize: number) {}
15
- signature(): string { return "kv:paged-rows"; }
16
- get batchSize(): number { return this.#rows.length; }
17
- get offset(): number { return Math.max(0, ...this.#rows.map(row => row.offset)); }
18
- get rowOffsets(): number[] { return this.#rows.map(row => row.offset); }
19
- get leftPad(): number[] { const width = this.offset; return this.#rows.map(row => width - row.offset); }
20
- get ropeOffsetArr(): MlxArray | undefined {
21
- if (this.#rows.length < 2) return undefined;
22
- if (!this.#rope || this.#ropeOffset !== this.offset) {
23
- this.releaseRopeArr();
24
- this.#rope = MlxArray.fromInt32(Int32Array.from(this.rowOffsets), [this.batchSize]);
25
- this.#ropeOffset = this.offset;
26
- }
27
- return this.#rope;
28
- }
29
- releaseRopeArr(): void { this.#rope?.dispose(); this.#rope = undefined; this.#ropeOffset = -1; }
30
- makeEmptyBatch(): PagedKvRows { return new PagedKvRows(this.capacityTokens, this.blockSize); }
31
-
32
- mergeRows(rows: readonly Cache[]): void {
33
- const next: PagedKVCache[] = [];
34
- try {
35
- for (const source of rows) {
36
- if (source instanceof PagedKvRows) {
37
- for (const row of source.#rows) next.push(row.clone());
38
- } else if (source instanceof PagedKVCache) next.push(source.clone());
39
- else throw new Error(`Paged rows cannot merge ${source.signature()}`);
40
- }
41
- } catch (error) { disposeResources(next); throw error; }
42
- const previous = this.#rows; this.#rows = next;
43
- this.releaseRopeArr(); disposeResources(previous);
44
- }
45
- extractRow(row: number): PagedKVCache { return this.#rows[row]!.clone(); }
46
- filterRows(keep: readonly number[]): void {
47
- const previous = this.#rows;
48
- this.#rows = keep.map(row => previous[row]!);
49
- const retained = new Set(keep);
50
- this.releaseRopeArr();
51
- disposeResources(previous.filter((_, row) => !retained.has(row)));
52
- }
53
-
54
- updateAndFetch(keys: MlxArray, values: MlxArray): [MlxArray, MlxArray] {
55
- if (this.#rows.length === 1) return this.#rows[0]!.updateAndFetch(keys, values);
56
- const fetched: Array<{ keys: MlxArray; values: MlxArray }> = [];
57
- try {
58
- for (const [row, storage] of this.#rows.entries()) {
59
- using k = keys.slice([row, 0, 0, 0], [row + 1, ...keys.shape.slice(1)]);
60
- using v = values.slice([row, 0, 0, 0], [row + 1, ...values.shape.slice(1)]);
61
- const [nextK, nextV] = storage.updateAndFetch(k, v);
62
- fetched.push({ keys: nextK, values: nextV });
63
- }
64
- const result = mergeKVRows(fetched);
65
- return [result.keys, result.values];
66
- } finally { disposeResources(fetched.flatMap(row => [row.keys, row.values])); }
67
- }
68
- makeMask(tokens: number, window: number | null): Mask {
69
- if (this.#rows.length === 1) return this.#rows[0]!.makeMask(tokens, window);
70
- return { mode: "array", arr: buildBatchedDecodeMask(this.batchSize, tokens,
71
- this.offset + tokens, this.leftPad, window) };
72
- }
73
- state(): MlxArray[] { return this.#rows.flatMap(row => row.state()); }
74
- isTrimmable(): boolean { return true; }
75
- trim(tokens: number): void { for (const row of this.#rows) row.trim(tokens); this.releaseRopeArr(); }
76
- projectedBytes(tokens: number): number {
77
- const pool = this.#rows.find(row => row.pool)?.pool;
78
- if (!pool) return 0;
79
- const bytesPerBlock = (pool.keys.nbytes + pool.values.nbytes) / pool.numBlocks;
80
- return poolBlocksFor(tokens, this.blockSize) * bytesPerBlock;
81
- }
82
- dispose(): void { const rows = this.#rows; this.#rows = []; this.releaseRopeArr(); disposeResources(rows); }
83
- }