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.
- package/README.md +1453 -88
- package/THIRD_PARTY_NOTICES.md +882 -0
- package/bin/mlx-bun.convert.mjs +4 -0
- package/bin/mlx-bun.fuse.mjs +4 -0
- package/bin/mlx-bun.generate.mjs +4 -0
- package/bin/mlx-bun.lora.mjs +4 -0
- package/bin/mlx-bun.mjs +13 -21
- package/bin/mlx-bun.server.mjs +4 -0
- package/bin/mlx-bun.upload.mjs +4 -0
- package/dist/web/app.js +9584 -0
- package/package.json +50 -53
- package/src/cli/ane-install.ts +76 -0
- package/src/cli/args.ts +179 -0
- package/src/cli/engine-entry.ts +68 -0
- package/src/cli/inference.ts +214 -0
- package/src/cli/job-entry.ts +97 -0
- package/src/cli/library-host.ts +117 -0
- package/src/cli/main.ts +57 -0
- package/src/cli/memory-engine.ts +163 -0
- package/src/cli/memory.ts +36 -0
- package/src/cli/mlx-lm-aliases.ts +309 -0
- package/src/cli/model-choice.ts +33 -0
- package/src/cli/model-selection.ts +84 -0
- package/src/cli/module-host.ts +11 -0
- package/src/cli/module-verbs.ts +50 -0
- package/src/cli/numerical-policy.ts +12 -0
- package/src/cli/perplexity.ts +89 -0
- package/src/cli/serve-host.ts +423 -0
- package/src/cli/serve-isolated.ts +217 -0
- package/src/cli/serve-options.ts +106 -0
- package/src/cli/serve-state.ts +205 -0
- package/src/cli/serve.ts +500 -0
- package/src/cli/served-model-host.ts +102 -0
- package/src/cli/server-entry.ts +148 -0
- package/src/cli/serving-unit.ts +177 -0
- package/src/{tui.ts → cli/terminal.ts} +13 -8
- package/src/cli/worker-adapters.ts +34 -0
- package/src/cli/worker-entry.ts +272 -0
- package/src/cli/worker-unit.ts +179 -0
- package/src/engine/adapter-operation.ts +26 -0
- package/src/engine/cache-services.ts +114 -0
- package/src/engine/completion.ts +39 -0
- package/src/engine/generation-gateway.ts +358 -0
- package/src/engine/index.ts +59 -0
- package/src/engine/kv-budget.ts +120 -0
- package/src/engine/media-preparation.ts +232 -0
- package/src/engine/model-binding.ts +24 -0
- package/src/engine/model-host.ts +513 -0
- package/src/engine/model-serving.ts +89 -0
- package/src/{serve → engine}/preparation.ts +10 -8
- package/src/{serve → engine}/session-completion-engine.ts +6 -6
- package/src/engine/telemetry.ts +109 -0
- package/src/hub/downloads.ts +116 -0
- package/src/jobs/db.ts +16 -7
- package/src/jobs/events.ts +29 -0
- package/src/jobs/executable.ts +5 -0
- package/src/jobs/host.ts +51 -0
- package/src/jobs/in-process.ts +55 -0
- package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
- package/src/jobs/runner.ts +150 -231
- package/src/jobs/service.ts +75 -0
- package/src/jobs/sse.ts +59 -23
- package/src/jobs/worker-memory.ts +46 -0
- package/src/jobs/worker-process.ts +163 -0
- package/src/jobs/worker-supervisor.ts +258 -0
- package/src/modules.ts +58 -0
- package/src/publishing/catalog-hub.ts +18 -0
- package/src/publishing/credentials.ts +31 -0
- package/src/publishing/upload.ts +37 -0
- package/src/residency/leased-adapters.ts +21 -0
- package/src/residency/local-records.ts +16 -0
- package/src/residency/model-residency.ts +405 -0
- package/src/residency/record-index.ts +28 -0
- package/src/residency/resident-estimate.ts +50 -0
- package/src/{anthropic.ts → server/anthropic.ts} +3 -81
- package/src/server/cache-routes.ts +36 -0
- package/src/{serve → server}/chat-request.ts +12 -10
- package/src/{serve → server}/chat-stage.ts +27 -22
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +42 -42
- package/src/server/decision-body.ts +55 -0
- package/src/server/decision-routes.ts +134 -0
- package/src/server/decision-wire.ts +228 -0
- package/src/{serve → server}/discovery-routes.ts +42 -83
- package/src/server/generated-token-history.ts +57 -0
- package/src/{serve → server}/http.ts +25 -13
- package/src/{serve → server}/inference-request.ts +5 -5
- package/src/server/job-routes.ts +20 -0
- package/src/server/media-prompt.ts +63 -0
- package/src/server/memory-completion-client.ts +46 -0
- package/src/server/model-routes.ts +192 -0
- package/src/{serve → server}/openai-wire.ts +3 -2
- package/src/{serve → server}/pipeline.ts +1 -1
- package/src/server/prompt-builder.ts +13 -0
- package/src/server/prompt-contracts.ts +17 -0
- package/src/server/proxy-routes.ts +187 -0
- package/src/server/publishing-routes.ts +41 -0
- package/src/{serve → server}/request-plan.ts +8 -8
- package/src/{serve → server}/request-prep.ts +82 -68
- package/src/{serve → server}/responses-client.ts +30 -13
- package/src/{responses.ts → server/responses.ts} +12 -93
- package/src/server/routes.ts +205 -0
- package/src/server/start.ts +72 -0
- package/src/server/status-routes.ts +108 -0
- package/src/{serve → server}/text-completion-stage.ts +25 -4
- package/src/server/text-prompt.ts +12 -0
- package/src/{serve → server}/token-streams.ts +36 -38
- package/src/server/worker-routes.ts +311 -0
- package/src/storage/paths.ts +61 -0
- package/src/web/assets.ts +37 -0
- package/src/web/{src → browser}/api.ts +5 -23
- package/src/web/browser/chat-host.ts +17 -0
- package/src/web/browser/installed-panels.ts +6 -0
- package/src/web/browser/main.ts +55 -0
- package/src/web/browser/markdown.ts +279 -0
- package/src/web/browser/memory-panel.ts +9 -0
- package/src/web/browser/palette.ts +64 -0
- package/src/web/browser/protocol.ts +13 -0
- package/src/web/browser/shell.ts +467 -0
- package/src/web/{src → browser}/status.ts +32 -36
- package/src/web/build.ts +51 -0
- package/src/web/public/app.html +1054 -0
- package/src/web/{sw.js → public/sw.js} +4 -3
- package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
- package/src/web/{vendor → public/vendor}/hljs.js +2 -2
- package/THIRD_PARTY_LICENSES.md +0 -51
- package/docs/README.md +0 -94
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
- package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
- package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
- package/docs/archive/investigations/curve-bisector-routing.md +0 -123
- package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
- package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
- package/docs/archive/investigations/dspark-handoff.md +0 -224
- package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
- package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
- package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
- package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
- package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
- package/docs/archive/investigations/lab-build-journal.md +0 -157
- package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
- package/docs/archive/investigations/openjarvis-fit.md +0 -198
- package/docs/archive/investigations/openwiki-evaluation.md +0 -249
- package/docs/archive/investigations/optimization_plan.md +0 -346
- package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
- package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
- package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
- package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
- package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
- package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
- package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
- package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
- package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
- package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
- package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
- package/docs/archive/planning/chat-ui-vision.md +0 -50
- package/docs/archive/planning/chunk-task-roadmap.md +0 -77
- package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
- package/docs/archive/planning/journal.md +0 -316
- package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
- package/docs/archive/planning/pi-integration-review.md +0 -178
- package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
- package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
- package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
- package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
- package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
- package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
- package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
- package/docs/archive/planning/web-ui-pass-plan.md +0 -213
- package/docs/archive/planning/website-readme-pass-plan.md +0 -224
- package/docs/design/batching.md +0 -1841
- package/docs/design/decode-speed-program.md +0 -2349
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -705
- package/docs/design/kv-cache.md +0 -824
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -1990
- package/docs/design/turboquant.md +0 -2212
- package/docs/design/unified-engine-frontier-plan.md +0 -1880
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -594
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/release-notes-v0.4.0.md +0 -45
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3613
- package/docs/reference/cli.md +0 -585
- package/docs/reference/distribution.md +0 -355
- package/docs/reference/environment.md +0 -398
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -674
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -334
- package/docs/reference/server-api.md +0 -1775
- package/docs/reference/server-config.md +0 -846
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/conformer.ts +0 -647
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/transcode.ts +0 -67
- package/src/backends/mlx/assistant-target.ts +0 -46
- package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
- package/src/backends/mlx/autoregressive.ts +0 -108
- package/src/backends/mlx/batch-group.ts +0 -1790
- package/src/backends/mlx/cache-attachment.ts +0 -67
- package/src/backends/mlx/cache-layout.ts +0 -31
- package/src/backends/mlx/checkpoint-state.ts +0 -53
- package/src/backends/mlx/continuation-persistence.ts +0 -106
- package/src/backends/mlx/continuation-request.ts +0 -43
- package/src/backends/mlx/continuation.ts +0 -77
- package/src/backends/mlx/diffusion.ts +0 -39
- package/src/backends/mlx/draft-target.ts +0 -32
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -45
- package/src/backends/mlx/full-kv-row-append.ts +0 -32
- package/src/backends/mlx/full-kv-row-donor.ts +0 -54
- package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
- package/src/backends/mlx/gateway-binding.ts +0 -130
- package/src/backends/mlx/graph.ts +0 -38
- package/src/backends/mlx/kv-codec.ts +0 -9
- package/src/backends/mlx/kv-maintenance.ts +0 -133
- package/src/backends/mlx/kv-tensor-rows.ts +0 -212
- package/src/backends/mlx/memory-client.ts +0 -189
- package/src/backends/mlx/methods.ts +0 -90
- package/src/backends/mlx/model-prompt.ts +0 -164
- package/src/backends/mlx/model-serving.ts +0 -79
- package/src/backends/mlx/prefill-cohort.ts +0 -89
- package/src/backends/mlx/prefill-rows.ts +0 -200
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -41
- package/src/backends/mlx/rollback.ts +0 -89
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -242
- package/src/backends/mlx/speculative-group.ts +0 -359
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -114
- package/src/backends/mlx/state-rows.ts +0 -104
- package/src/backends/mlx/state-views.ts +0 -46
- package/src/backends/mlx/target-layout-capability.ts +0 -35
- package/src/backends/mlx/text-engine.ts +0 -73
- package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3168
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -60
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -259
- package/src/contracts/prefix-cache.ts +0 -23
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -45
- package/src/contracts/tsconfig.json +0 -14
- package/src/dataset/generators.ts +0 -1087
- package/src/dataset/index.ts +0 -12
- package/src/dataset/job.ts +0 -81
- package/src/dataset/llm.ts +0 -71
- package/src/dataset/registry.ts +0 -528
- package/src/diffusion/diffusion-generate.ts +0 -507
- package/src/download.ts +0 -505
- package/src/embed.ts +0 -77
- package/src/engine/admission.ts +0 -59
- package/src/engine/cancellation.ts +0 -38
- package/src/engine/engine.ts +0 -56
- package/src/engine/execution-coordinator.ts +0 -70
- package/src/engine/execution-plan.ts +0 -53
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -72
- package/src/engine/session.ts +0 -247
- package/src/eval/README.md +0 -130
- package/src/eval/ifeval.ts +0 -81
- package/src/eval/kl-prompts.ts +0 -29
- package/src/eval/kl.ts +0 -590
- package/src/eval/perplexity.ts +0 -164
- package/src/eval/quality-db.ts +0 -92
- package/src/eval/reference-logits.ts +0 -207
- package/src/eval/runner.ts +0 -124
- package/src/eval/score.ts +0 -49
- package/src/eval/tasks/bfcl.ts +0 -535
- package/src/eval/tasks/gsm8k.ts +0 -98
- package/src/eval/tasks/hashhop.ts +0 -139
- package/src/eval/tasks/humaneval.ts +0 -275
- package/src/eval/tasks/ifeval.ts +0 -525
- package/src/eval/tasks/mmlu.ts +0 -157
- package/src/eval/ultrafeedback.ts +0 -60
- package/src/evaldb.ts +0 -199
- package/src/expert-io.ts +0 -393
- package/src/expert-offload-build.ts +0 -77
- package/src/expert-offload.ts +0 -76
- package/src/expert-residency.ts +0 -1134
- package/src/expert-usage.ts +0 -415
- package/src/fill/echo-index.ts +0 -188
- package/src/fill/fill-session.ts +0 -452
- package/src/fill/proposal.ts +0 -68
- package/src/fill/schema-rows.ts +0 -506
- package/src/fill/tool-boundary.ts +0 -103
- package/src/fit.ts +0 -249
- package/src/generate.ts +0 -1346
- package/src/grammar.ts +0 -591
- package/src/harness-pi.ts +0 -184
- package/src/hf-push.ts +0 -628
- package/src/hub-rest.ts +0 -242
- package/src/index.ts +0 -63
- package/src/inference/denoising.ts +0 -17
- package/src/inference/draft-acceptance.ts +0 -41
- package/src/inference/draft-output.ts +0 -49
- package/src/inference/graph.ts +0 -33
- package/src/inference/prefill.ts +0 -39
- package/src/inference/rollback.ts +0 -7
- package/src/jobs/index.ts +0 -31
- package/src/jobs/job-entry.ts +0 -107
- package/src/jobs/task-client.ts +0 -19
- package/src/jobs/types.ts +0 -2
- package/src/kv-scheme.ts +0 -257
- package/src/kv-store.ts +0 -1099
- package/src/lab/README.md +0 -18
- package/src/lab/curve/curve-designer.html +0 -303
- package/src/lab/curve/curve-sampler.ts +0 -122
- package/src/lab/expert-trace/expert-trace.ts +0 -69
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
- package/src/lab/paged-kv/paged-kv.ts +0 -270
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -49
- package/src/media-fetch.ts +0 -442
- package/src/memory/article.ts +0 -558
- package/src/memory/chunk-validation.ts +0 -150
- package/src/memory/chunk.ts +0 -318
- package/src/memory/cluster.ts +0 -351
- package/src/memory/coverage.ts +0 -134
- package/src/memory/crosslink.ts +0 -0
- package/src/memory/db.ts +0 -253
- package/src/memory/entity.ts +0 -203
- package/src/memory/gate.ts +0 -187
- package/src/memory/history.ts +0 -152
- package/src/memory/ingest.ts +0 -335
- package/src/memory/model.ts +0 -183
- package/src/memory/normalize.ts +0 -671
- package/src/memory/parse.ts +0 -22
- package/src/memory/pipeline.ts +0 -275
- package/src/memory/prompts.ts +0 -65
- package/src/memory/query.ts +0 -334
- package/src/memory/reconcile.ts +0 -734
- package/src/memory/redirect.ts +0 -108
- package/src/memory/reindex.ts +0 -325
- package/src/memory/resolve.ts +0 -307
- package/src/memory/rest.ts +0 -245
- package/src/memory/route.ts +0 -272
- package/src/memory/schedule.ts +0 -165
- package/src/memory/stages.ts +0 -777
- package/src/memory/synthesize.ts +0 -1638
- package/src/memory/tools.ts +0 -749
- package/src/memory/vault.ts +0 -1194
- package/src/memory/wikify.ts +0 -1064
- package/src/mlx/array.ts +0 -388
- package/src/mlx/autograd.ts +0 -304
- package/src/mlx/checkpoint.ts +0 -149
- package/src/mlx/compile.ts +0 -168
- package/src/mlx/custom-vjp.ts +0 -188
- package/src/mlx/ffi.ts +0 -512
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/ops.ts +0 -1021
- package/src/mlx/quantized-rows.ts +0 -36
- package/src/mlx/token-bitmask.ts +0 -52
- package/src/mlx/turboquant-kv-decode.ts +0 -82
- package/src/mlx/turboquant-kv-inverse.ts +0 -122
- package/src/mlx/turboquant-ops.ts +0 -861
- package/src/mlx/turboquant-tables.ts +0 -237
- package/src/mmap.ts +0 -90
- package/src/model/artifact-identity.ts +0 -73
- package/src/model/batched-kv.ts +0 -235
- package/src/model/batched-mask.ts +0 -279
- package/src/model/batched-quant.ts +0 -212
- package/src/model/batched-quantized-kv.ts +0 -144
- package/src/model/batched-rotating-quant.ts +0 -353
- package/src/model/batched-rotating-state.ts +0 -149
- package/src/model/batched-rotating.ts +0 -338
- package/src/model/batched-row-storage.ts +0 -179
- package/src/model/batched-ssm.ts +0 -52
- package/src/model/batched-turboquant-kv.ts +0 -93
- package/src/model/compiled-decode.ts +0 -712
- package/src/model/decoded-kv-donor.ts +0 -12
- package/src/model/delayed-quantized-kv.ts +0 -72
- package/src/model/delayed-rotating-quantized-kv.ts +0 -93
- package/src/model/delayed-turboquant-kv.ts +0 -55
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -189
- package/src/model/fingerprint.ts +0 -33
- package/src/model/flash-attention.ts +0 -694
- package/src/model/full-prefill-padding.ts +0 -56
- package/src/model/full-prefill-row.ts +0 -105
- package/src/model/gemma4-base.ts +0 -2351
- package/src/model/gemma4.ts +0 -1315
- package/src/model/generated/gemma4-12b.ts +0 -429
- package/src/model/generated/gemma4-26b.ts +0 -448
- package/src/model/generated/gemma4-e4b.ts +0 -717
- package/src/model/generated/index.ts +0 -18
- package/src/model/glm52-atlas.ts +0 -511
- package/src/model/glm52-cache.ts +0 -792
- package/src/model/glm52-config.ts +0 -262
- package/src/model/glm52-container.ts +0 -305
- package/src/model/glm52-coupling.ts +0 -388
- package/src/model/glm52-dsa.ts +0 -606
- package/src/model/glm52-expert-layout.ts +0 -253
- package/src/model/glm52-layout.ts +0 -152
- package/src/model/glm52-memory.ts +0 -500
- package/src/model/glm52-mla.ts +0 -792
- package/src/model/glm52-moe.ts +0 -223
- package/src/model/glm52-pilot.ts +0 -537
- package/src/model/glm52-reference.ts +0 -445
- package/src/model/glm52-residency.ts +0 -557
- package/src/model/glm52-resident-weights.ts +0 -135
- package/src/model/glm52-streamed-experts.ts +0 -453
- package/src/model/glm52-streamed-metal.ts +0 -610
- package/src/model/glm52-weights.ts +0 -503
- package/src/model/glm52.ts +0 -1132
- package/src/model/implementation.ts +0 -69
- package/src/model/kv-attention-view.ts +0 -67
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -443
- package/src/model/qwen-append.ts +0 -12
- package/src/model/qwen-conv.ts +0 -52
- package/src/model/qwen3-delta-state.ts +0 -74
- package/src/model/qwen3-delta.ts +0 -451
- package/src/model/qwen3-moe.ts +0 -404
- package/src/model/qwen3-mrope.ts +0 -252
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -819
- package/src/model/rotating-kv-donor.ts +0 -35
- package/src/model/rotating-kv-layout.ts +0 -262
- package/src/model/rotating-row-transaction.ts +0 -35
- package/src/model/speculative-rotating-kv.ts +0 -101
- package/src/model/ssm-prefill-padding.ts +0 -39
- package/src/model/support.ts +0 -102
- package/src/model/trellis-balanced-scatter.ts +0 -51
- package/src/model/trellis-linear.ts +0 -672
- package/src/model/trellis-shared-m.ts +0 -151
- package/src/model/trellis-shared-scatter.ts +0 -144
- package/src/model/trellis-splitk-prefill.ts +0 -158
- package/src/model/trellis-tiled-prefill.ts +0 -136
- package/src/model/trellis-vector-expand.ts +0 -62
- package/src/model/trellis-wide-prefill.ts +0 -94
- package/src/model/turboquant-codec.ts +0 -83
- package/src/model/universal/archs.ts +0 -332
- package/src/model/universal/dense.ts +0 -612
- package/src/model/universal/modules.ts +0 -170
- package/src/model/universal/rope.ts +0 -381
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native-pack.ts +0 -162
- package/src/pi-provider.ts +0 -53
- package/src/pi-session.ts +0 -81
- package/src/pi-terminal.ts +0 -274
- package/src/pi-web.ts +0 -1932
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -460
- package/src/quantize/allocator.ts +0 -627
- package/src/quantize/atomic-output.ts +0 -38
- package/src/quantize/calibration.ts +0 -181
- package/src/quantize/config-writer.ts +0 -145
- package/src/quantize/index.ts +0 -84
- package/src/quantize/job.ts +0 -162
- package/src/quantize/quantizer.ts +0 -666
- package/src/quantize/rotate.ts +0 -603
- package/src/quantize/safetensors-writer.ts +0 -249
- package/src/quantize/sensitivity.ts +0 -216
- package/src/quantize/trellis.ts +0 -586
- package/src/quantize/weight-transform.ts +0 -292
- package/src/registry.ts +0 -602
- package/src/runtime-config.ts +0 -81
- package/src/safetensors.ts +0 -158
- package/src/sampler.ts +0 -1011
- package/src/serve/admin-routes.ts +0 -184
- package/src/serve/assets/curve-terrain.html +0 -105
- package/src/serve/assets/training-inference-map.html +0 -575
- package/src/serve/aux-routes.ts +0 -132
- package/src/serve/batch-scheduler.ts +0 -8
- package/src/serve/checkpoint-identity.ts +0 -64
- package/src/serve/generation-gateway.ts +0 -496
- package/src/serve/isolate.ts +0 -609
- package/src/serve/kv-budget.ts +0 -14
- package/src/serve/lab-routes.ts +0 -341
- package/src/serve/lane-registry.ts +0 -45
- package/src/serve/model-admin-routes.ts +0 -155
- package/src/serve/model-binding.ts +0 -43
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -147
- package/src/serve/response-lease.ts +0 -24
- package/src/serve/session-search.ts +0 -326
- package/src/serve/static-routes.ts +0 -101
- package/src/server.ts +0 -1314
- package/src/spec/assistant-rows.ts +0 -92
- package/src/spec/assistant-source.ts +0 -126
- package/src/spec/cache-identity.ts +0 -22
- package/src/spec/deepspec-rows.ts +0 -29
- package/src/spec/deepspec-source.ts +0 -145
- package/src/spec/dflash-source.ts +0 -149
- package/src/spec/drafter.ts +0 -304
- package/src/spec/dspark/ab-stats.ts +0 -136
- package/src/spec/dspark/calibration.ts +0 -112
- package/src/spec/dspark/data-dflash.ts +0 -156
- package/src/spec/dspark/data.ts +0 -201
- package/src/spec/dspark/deepspec-module.ts +0 -776
- package/src/spec/dspark/generate-dflash.ts +0 -245
- package/src/spec/dspark/generate.ts +0 -290
- package/src/spec/dspark/loader.ts +0 -23
- package/src/spec/dspark/loss.ts +0 -213
- package/src/spec/dspark/module-dflash.ts +0 -560
- package/src/spec/dspark/module.ts +0 -540
- package/src/spec/dspark/quantize-drafter.ts +0 -91
- package/src/spec/dspark/sample.ts +0 -112
- package/src/spec/generate.ts +0 -276
- package/src/spec/glm52-mtp-graph.ts +0 -29
- package/src/spec/glm52-mtp-rows.ts +0 -132
- package/src/spec/glm52-mtp-source.ts +0 -317
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -204
- package/src/spec/projected-draft-rows.ts +0 -73
- package/src/spec/qwen-mtp-module.ts +0 -171
- package/src/spec/qwen-mtp-rows.ts +0 -219
- package/src/spec/qwen-mtp-source.ts +0 -383
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -585
- package/src/spec/source.ts +0 -215
- package/src/spec/two-model-rows.ts +0 -61
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -372
- package/src/ssd-durability.ts +0 -211
- package/src/tokenizer.ts +0 -335
- package/src/tool-approvals.ts +0 -131
- package/src/tool-call.ts +0 -695
- package/src/train/dataset.ts +0 -484
- package/src/train/diffusion-lora.ts +0 -216
- package/src/train/export.ts +0 -32
- package/src/train/flash-cce.ts +0 -1234
- package/src/train/forward.ts +0 -266
- package/src/train/fuse.ts +0 -243
- package/src/train/index.ts +0 -46
- package/src/train/job.ts +0 -205
- package/src/train/lora-params.ts +0 -254
- package/src/train/loss.ts +0 -1591
- package/src/train/merge.ts +0 -195
- package/src/train/optimizer.ts +0 -183
- package/src/train/prefix-shared.ts +0 -490
- package/src/train/rank.ts +0 -137
- package/src/train/segmented.ts +0 -1828
- package/src/train/steel-qmm-header.ts +0 -1461
- package/src/train/trainer.ts +0 -1221
- package/src/train/watch.ts +0 -542
- package/src/vision/diffusion-vision.ts +0 -620
- package/src/vision/embedder.ts +0 -168
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -373
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -196
- package/src/vision/qwen3vl-tower.ts +0 -555
- package/src/vision/siglip.ts +0 -599
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2143
- package/src/web/app.js +0 -5703
- package/src/web/skills/memory/SKILL.md +0 -120
- package/src/web/skills/web-research/SKILL.md +0 -46
- package/src/web/skills.ts +0 -97
- package/src/web/src/adapters-panel.ts +0 -288
- package/src/web/src/assistant.ts +0 -451
- package/src/web/src/chat.ts +0 -1057
- package/src/web/src/composer.ts +0 -959
- package/src/web/src/dataset.ts +0 -132
- package/src/web/src/finetune.ts +0 -267
- package/src/web/src/hub.ts +0 -428
- package/src/web/src/main.ts +0 -98
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +0 -572
- package/src/web/src/model-picker.ts +0 -159
- package/src/web/src/palette.ts +0 -346
- package/src/web/src/protocol.ts +0 -26
- package/src/web/src/quantize.ts +0 -167
- package/src/web/src/rag.ts +0 -274
- package/src/web/src/sessions.ts +0 -469
- package/src/web/src/shell.ts +0 -804
- package/src/web/src/ui-catalog.ts +0 -78
- package/src/web/vendor/README.md +0 -61
- package/src/web-assets.ts +0 -47
- package/src/web-tools.ts +0 -478
- package/src/weights.ts +0 -255
- /package/src/{serve → server}/completion-sink.ts +0 -0
- /package/src/web/{icon.svg → public/icon.svg} +0 -0
- /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
- /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
|
@@ -1,712 +0,0 @@
|
|
|
1
|
-
// Compiled decode step (Phase A of docs/archive/investigations/optimization_plan.md).
|
|
2
|
-
//
|
|
3
|
-
// The single-token decode graph is identical token-to-token except for
|
|
4
|
-
// integer state (RoPE offset, cache write position, active length). This
|
|
5
|
-
// module wraps one whole step — embed → all layers → finalNorm → logits —
|
|
6
|
-
// in an mx.compile'd closure (src/mlx/compile.ts) so the per-step graph
|
|
7
|
-
// is REPLAYED in C++ instead of rebuilt through ~2000 bun:ffi crossings.
|
|
8
|
-
//
|
|
9
|
-
// How the per-step state crosses into a fixed graph:
|
|
10
|
-
// - RoPE offset and ring write positions enter as int32 ARRAY inputs
|
|
11
|
-
// (fast_rope_dynamic / slice_update_dynamic) — values change, graph
|
|
12
|
-
// doesn't.
|
|
13
|
-
// - Shapes that grow (the active KV prefix) enter as inputs and the
|
|
14
|
-
// closure is compiled shapeless=true: dim sizes may vary per step,
|
|
15
|
-
// ndim/dtype may not.
|
|
16
|
-
//
|
|
17
|
-
// The trace runs the UNMODIFIED Gemma4Model.forwardHidden against trace
|
|
18
|
-
// adapters that subclass the real cache classes — so the compiled graph
|
|
19
|
-
// is the production op sequence by construction, not a reimplementation.
|
|
20
|
-
// Per-cache fetch strategy (see DecodeStepPlan in gemma4.ts):
|
|
21
|
-
// - "concat": graph returns this step's (quantized) KV row; the buffer
|
|
22
|
-
// write stays OUTSIDE, right after the step — the buffer keeps a single
|
|
23
|
-
// reference at its slice_update, so mlx donates it (no per-step copy).
|
|
24
|
-
// - "ring": write in-graph at a dynamic position, read the full updated
|
|
25
|
-
// ring — bit-exact with the rotating steady state, where a concat
|
|
26
|
-
// would permute KV positions and change reduction order.
|
|
27
|
-
//
|
|
28
|
-
// Anything this module can't express falls back to the uncompiled path
|
|
29
|
-
// (generate.ts catches and disables for the generation): active LoRA
|
|
30
|
-
// adapters (their weights would bake into the trace as constants),
|
|
31
|
-
// unknown cache classes, diverged cache offsets.
|
|
32
|
-
|
|
33
|
-
import { MlxArray } from "../mlx/array";
|
|
34
|
-
import { CompiledFunction } from "../mlx/compile";
|
|
35
|
-
import * as ops from "../mlx/ops";
|
|
36
|
-
import { runtimeValue } from "../runtime-config";
|
|
37
|
-
import {
|
|
38
|
-
Gemma4Model,
|
|
39
|
-
KVCache,
|
|
40
|
-
QuantizedKVCache,
|
|
41
|
-
RotatingKVCache,
|
|
42
|
-
RotatingQuantizedKVCache,
|
|
43
|
-
setCompiledTrace,
|
|
44
|
-
type Cache,
|
|
45
|
-
type DecodeStepPlan,
|
|
46
|
-
type SharedKv,
|
|
47
|
-
} from "./gemma4";
|
|
48
|
-
|
|
49
|
-
type AnyCache = KVCache | QuantizedKVCache | RotatingKVCache | RotatingQuantizedKVCache;
|
|
50
|
-
|
|
51
|
-
const fullSlice = (a: MlxArray): MlxArray => {
|
|
52
|
-
const stop = a.shape;
|
|
53
|
-
return a.slice(stop.map(() => 0), stop);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const catAxis2 = (a: ops.QuantizedTensor, b: ops.QuantizedTensor): ops.QuantizedTensor => ({
|
|
57
|
-
packed: ops.concatAxis([a.packed, b.packed], 2),
|
|
58
|
-
scales: ops.concatAxis([a.scales, b.scales], 2),
|
|
59
|
-
biases: ops.concatAxis([a.biases, b.biases], 2),
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// --- trace adapters ---------------------------------------------------------
|
|
63
|
-
// Subclasses so Attention.forward's instanceof dispatch (quantized vs
|
|
64
|
-
// plain) routes exactly as it does for the real cache. `offset` is set
|
|
65
|
-
// for completeness only: at L=1 every makeMask returns mode "" and the
|
|
66
|
-
// RoPE offset rides the ropeOffsetArr input, so the baked value cannot
|
|
67
|
-
// leak into the graph. Adapters live only for the duration of one trace.
|
|
68
|
-
|
|
69
|
-
/** Growing plain cache (KVCache, or RotatingKVCache before the window
|
|
70
|
-
* fills): fetch = concat(active prefix, new row); new row is a closure
|
|
71
|
-
* output for the outside write. */
|
|
72
|
-
class TraceConcatPlain extends KVCache {
|
|
73
|
-
override readonly ropeOffsetArr: MlxArray;
|
|
74
|
-
outs: MlxArray[] = [];
|
|
75
|
-
constructor(
|
|
76
|
-
offset: number,
|
|
77
|
-
readonly activeK: MlxArray,
|
|
78
|
-
readonly activeV: MlxArray,
|
|
79
|
-
ropeOffsetArr: MlxArray,
|
|
80
|
-
) {
|
|
81
|
-
super();
|
|
82
|
-
this.offset = offset;
|
|
83
|
-
this.ropeOffsetArr = ropeOffsetArr;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
override updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
|
87
|
-
// same-shape reshape: an owned alias that survives the caller's
|
|
88
|
-
// dispose of k/v, so the row can be a closure output
|
|
89
|
-
this.outs = [ops.reshape(k, k.shape), ops.reshape(v, v.shape)];
|
|
90
|
-
return [
|
|
91
|
-
ops.concatAxis([this.activeK, k], 2),
|
|
92
|
-
ops.concatAxis([this.activeV, v], 2),
|
|
93
|
-
];
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** Growing quantized cache: quantize in-graph, fetch = per-component
|
|
98
|
-
* concat, the six quantized row components are closure outputs. */
|
|
99
|
-
class TraceConcatQuant extends QuantizedKVCache {
|
|
100
|
-
override readonly ropeOffsetArr: MlxArray;
|
|
101
|
-
outs: MlxArray[] = [];
|
|
102
|
-
constructor(
|
|
103
|
-
offset: number, groupSize: number, bits: number,
|
|
104
|
-
readonly activeKq: ops.QuantizedTensor,
|
|
105
|
-
readonly activeVq: ops.QuantizedTensor,
|
|
106
|
-
ropeOffsetArr: MlxArray,
|
|
107
|
-
) {
|
|
108
|
-
super(groupSize, bits);
|
|
109
|
-
this.offset = offset;
|
|
110
|
-
this.ropeOffsetArr = ropeOffsetArr;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
override updateAndFetchQuantized(k: MlxArray, v: MlxArray): [ops.QuantizedTensor, ops.QuantizedTensor] {
|
|
114
|
-
const kq = ops.quantize(k, this.groupSize, this.bits);
|
|
115
|
-
const vq = ops.quantize(v, this.groupSize, this.bits);
|
|
116
|
-
this.outs = [kq.packed, kq.scales, kq.biases, vq.packed, vq.scales, vq.biases];
|
|
117
|
-
return [catAxis2(this.activeKq, kq), catAxis2(this.activeVq, vq)];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Rotating plain cache at steady state: write in-graph at the dynamic
|
|
122
|
-
* ring position, fetch the full updated buffer (mirrors #updateInPlace →
|
|
123
|
-
* #fetchAll); updated buffers are closure outputs. */
|
|
124
|
-
class TraceRingPlain extends RotatingKVCache {
|
|
125
|
-
override readonly ropeOffsetArr: MlxArray;
|
|
126
|
-
outs: MlxArray[] = [];
|
|
127
|
-
constructor(
|
|
128
|
-
offset: number, maxSize: number,
|
|
129
|
-
readonly bufK: MlxArray,
|
|
130
|
-
readonly bufV: MlxArray,
|
|
131
|
-
readonly writePosArr: MlxArray,
|
|
132
|
-
ropeOffsetArr: MlxArray,
|
|
133
|
-
) {
|
|
134
|
-
super(maxSize);
|
|
135
|
-
this.offset = offset;
|
|
136
|
-
this.ropeOffsetArr = ropeOffsetArr;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
override updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
|
140
|
-
const updK = ops.sliceUpdateDynamic(this.bufK, k, this.writePosArr, [2]);
|
|
141
|
-
const updV = ops.sliceUpdateDynamic(this.bufV, v, this.writePosArr, [2]);
|
|
142
|
-
this.outs = [updK, updV];
|
|
143
|
-
return [fullSlice(updK), fullSlice(updV)];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/** Rotating quantized cache at steady state: quantize + six dynamic
|
|
148
|
-
* writes in-graph, fetch full updated buffers (mirrors the oracle's
|
|
149
|
-
* _update_in_place → _active_slices). */
|
|
150
|
-
class TraceRingQuant extends RotatingQuantizedKVCache {
|
|
151
|
-
override readonly ropeOffsetArr: MlxArray;
|
|
152
|
-
outs: MlxArray[] = [];
|
|
153
|
-
constructor(
|
|
154
|
-
offset: number, maxSize: number, groupSize: number, bits: number,
|
|
155
|
-
readonly bufKq: ops.QuantizedTensor,
|
|
156
|
-
readonly bufVq: ops.QuantizedTensor,
|
|
157
|
-
readonly writePosArr: MlxArray,
|
|
158
|
-
ropeOffsetArr: MlxArray,
|
|
159
|
-
) {
|
|
160
|
-
super(maxSize, groupSize, bits);
|
|
161
|
-
this.offset = offset;
|
|
162
|
-
this.ropeOffsetArr = ropeOffsetArr;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
override updateAndFetchQuantized(k: MlxArray, v: MlxArray): [ops.QuantizedTensor, ops.QuantizedTensor] {
|
|
166
|
-
const kq = ops.quantize(k, this.groupSize, this.bits);
|
|
167
|
-
const vq = ops.quantize(v, this.groupSize, this.bits);
|
|
168
|
-
const upd = (buf: ops.QuantizedTensor, row: ops.QuantizedTensor): ops.QuantizedTensor => ({
|
|
169
|
-
packed: ops.sliceUpdateDynamic(buf.packed, row.packed, this.writePosArr, [2]),
|
|
170
|
-
scales: ops.sliceUpdateDynamic(buf.scales, row.scales, this.writePosArr, [2]),
|
|
171
|
-
biases: ops.sliceUpdateDynamic(buf.biases, row.biases, this.writePosArr, [2]),
|
|
172
|
-
});
|
|
173
|
-
const updK = upd(this.bufKq, kq);
|
|
174
|
-
const updV = upd(this.bufVq, vq);
|
|
175
|
-
for (const t of [kq, vq])
|
|
176
|
-
for (const a of [t.packed, t.scales, t.biases]) a.dispose();
|
|
177
|
-
this.outs = [updK.packed, updK.scales, updK.biases, updV.packed, updV.scales, updV.biases];
|
|
178
|
-
return [
|
|
179
|
-
{ packed: fullSlice(updK.packed), scales: fullSlice(updK.scales), biases: fullSlice(updK.biases) },
|
|
180
|
-
{ packed: fullSlice(updV.packed), scales: fullSlice(updV.scales), biases: fullSlice(updV.biases) },
|
|
181
|
-
];
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// --- slot layout ------------------------------------------------------------
|
|
186
|
-
|
|
187
|
-
interface SlotDesc {
|
|
188
|
-
kind: "p-cat" | "q-cat" | "p-ring" | "q-ring";
|
|
189
|
-
offset: number;
|
|
190
|
-
maxSize: number;
|
|
191
|
-
groupSize: number;
|
|
192
|
-
bits: number;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function slotDesc(c: AnyCache, plan: DecodeStepPlan): SlotDesc {
|
|
196
|
-
const cat = plan.fetch === "concat";
|
|
197
|
-
if (c instanceof QuantizedKVCache)
|
|
198
|
-
return { kind: "q-cat", offset: c.offset, maxSize: 0, groupSize: c.groupSize, bits: c.bits };
|
|
199
|
-
if (c instanceof RotatingQuantizedKVCache)
|
|
200
|
-
return { kind: cat ? "q-cat" : "q-ring", offset: c.offset, maxSize: c.maxSize, groupSize: c.groupSize, bits: c.bits };
|
|
201
|
-
if (c instanceof RotatingKVCache)
|
|
202
|
-
return { kind: cat ? "p-cat" : "p-ring", offset: c.offset, maxSize: c.maxSize, groupSize: 0, bits: 0 };
|
|
203
|
-
return { kind: "p-cat", offset: c.offset, maxSize: 0, groupSize: 0, bits: 0 };
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** Graph-shape signature: anything that changes the traced op sequence
|
|
207
|
-
* must appear here (cache kinds/quant params and the env flags read
|
|
208
|
-
* inside quantizedSdpa's dispatch). Offsets/capacities don't — they're
|
|
209
|
-
* array values or shapeless dims. */
|
|
210
|
-
function closureKey(descs: SlotDesc[]): string {
|
|
211
|
-
const flags = `nf=${runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1" ? 1 : 0}`;
|
|
212
|
-
return descs.map((d) => `${d.kind}:${d.groupSize}:${d.bits}`).join(",") + "|" + flags;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function makeTraceFn(model: Gemma4Model, descs: SlotDesc[]) {
|
|
216
|
-
return (inputs: MlxArray[]): MlxArray[] => {
|
|
217
|
-
const ropeOff = inputs[1]!;
|
|
218
|
-
let pos = 2;
|
|
219
|
-
const triple = (at: number): ops.QuantizedTensor => ({
|
|
220
|
-
packed: inputs[at]!, scales: inputs[at + 1]!, biases: inputs[at + 2]!,
|
|
221
|
-
});
|
|
222
|
-
const adapters: (TraceConcatPlain | TraceConcatQuant | TraceRingPlain | TraceRingQuant)[] = [];
|
|
223
|
-
for (const d of descs) {
|
|
224
|
-
switch (d.kind) {
|
|
225
|
-
case "p-cat":
|
|
226
|
-
adapters.push(new TraceConcatPlain(d.offset, inputs[pos]!, inputs[pos + 1]!, ropeOff));
|
|
227
|
-
pos += 2;
|
|
228
|
-
break;
|
|
229
|
-
case "q-cat":
|
|
230
|
-
adapters.push(new TraceConcatQuant(d.offset, d.groupSize, d.bits, triple(pos), triple(pos + 3), ropeOff));
|
|
231
|
-
pos += 6;
|
|
232
|
-
break;
|
|
233
|
-
case "p-ring":
|
|
234
|
-
adapters.push(new TraceRingPlain(d.offset, d.maxSize, inputs[pos]!, inputs[pos + 1]!, inputs[pos + 2]!, ropeOff));
|
|
235
|
-
pos += 3;
|
|
236
|
-
break;
|
|
237
|
-
case "q-ring":
|
|
238
|
-
adapters.push(new TraceRingQuant(d.offset, d.maxSize, d.groupSize, d.bits, triple(pos), triple(pos + 3), inputs[pos + 6]!, ropeOff));
|
|
239
|
-
pos += 7;
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
setCompiledTrace(true);
|
|
244
|
-
try {
|
|
245
|
-
const ids = ops.reshape(inputs[0]!, [1, 1]);
|
|
246
|
-
const h = model.forwardHidden(ids, adapters as unknown as Cache[]);
|
|
247
|
-
ids.dispose();
|
|
248
|
-
const logits = model.logitsFromHidden(h);
|
|
249
|
-
h.dispose();
|
|
250
|
-
return [logits, ...adapters.flatMap((a) => a.outs)];
|
|
251
|
-
} finally {
|
|
252
|
-
setCompiledTrace(false);
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// --- segmented mode (dense models) ------------------------------------------
|
|
258
|
-
// Measured (PLAN Phase A findings): the concat fetch materializes a copy
|
|
259
|
-
// of each growing cache's active window every step — per-op encode
|
|
260
|
-
// overhead + 2× byte traffic + allocator churn from monotonically
|
|
261
|
-
// growing transient sizes. Ring-phase caches (write-in-graph, read the
|
|
262
|
-
// updated buffer) cost nothing extra. So for models without KV sharing /
|
|
263
|
-
// per-layer inputs / MoE, the compiled graph is SEGMENTED at growing-
|
|
264
|
-
// cache layers: those layers run uncompiled (today's exact view-based
|
|
265
|
-
// ops — no copies, bit-exact trivially) and everything between them
|
|
266
|
-
// replays compiled. At steady state on the 12B that is 6 JS layers and
|
|
267
|
-
// 7 compiled segments per step.
|
|
268
|
-
|
|
269
|
-
/** Non-mutating phase check (segmented mode decides layer placement
|
|
270
|
-
* BEFORE any cache bookkeeping runs). Mirrors prepareDecodeStep's
|
|
271
|
-
* outcome: rotating caches go ring once the next write lands at or past
|
|
272
|
-
* the window; everything else grows. */
|
|
273
|
-
function decodePhase(c: AnyCache): "concat" | "ring" {
|
|
274
|
-
if (c instanceof RotatingKVCache || c instanceof RotatingQuantizedKVCache)
|
|
275
|
-
return c.offset + 1 < c.maxSize ? "concat" : "ring";
|
|
276
|
-
return "concat";
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function disposeShared(s: SharedKv): void {
|
|
280
|
-
if (s.kind === "view") {
|
|
281
|
-
s.attention.dispose();
|
|
282
|
-
s.offsetArr?.dispose();
|
|
283
|
-
} else if (s.kind === "plain") {
|
|
284
|
-
s.keys.dispose();
|
|
285
|
-
s.values.dispose();
|
|
286
|
-
} else {
|
|
287
|
-
for (const t of [s.keys, s.values])
|
|
288
|
-
for (const a of [t.packed, t.scales, t.biases]) a.dispose();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/** Trace one compiled segment: layers [from, to) — all ring caches —
|
|
293
|
-
* with embed before (first) and finalNorm+logits after (last).
|
|
294
|
-
* Input layout: [idsOrH, ropeOffset, ...ring slots in layer order].
|
|
295
|
-
* Output layout: [hOrLogits, ...ring buffer updates]. */
|
|
296
|
-
function makeSegmentTraceFn(
|
|
297
|
-
model: Gemma4Model, descs: SlotDesc[], from: number, to: number,
|
|
298
|
-
first: boolean, last: boolean,
|
|
299
|
-
) {
|
|
300
|
-
return (inputs: MlxArray[]): MlxArray[] => {
|
|
301
|
-
setCompiledTrace(true);
|
|
302
|
-
try {
|
|
303
|
-
const ropeOff = inputs[1]!;
|
|
304
|
-
let pos = 2;
|
|
305
|
-
const triple = (at: number): ops.QuantizedTensor => ({
|
|
306
|
-
packed: inputs[at]!, scales: inputs[at + 1]!, biases: inputs[at + 2]!,
|
|
307
|
-
});
|
|
308
|
-
const adapters: (TraceRingPlain | TraceRingQuant)[] = [];
|
|
309
|
-
for (const d of descs) {
|
|
310
|
-
if (d.kind === "p-ring") {
|
|
311
|
-
adapters.push(new TraceRingPlain(d.offset, d.maxSize, inputs[pos]!, inputs[pos + 1]!, inputs[pos + 2]!, ropeOff));
|
|
312
|
-
pos += 3;
|
|
313
|
-
} else {
|
|
314
|
-
adapters.push(new TraceRingQuant(d.offset, d.maxSize, d.groupSize, d.bits, triple(pos), triple(pos + 3), inputs[pos + 6]!, ropeOff));
|
|
315
|
-
pos += 7;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
let h: MlxArray;
|
|
320
|
-
if (first) {
|
|
321
|
-
const ids = ops.reshape(inputs[0]!, [1, 1]);
|
|
322
|
-
const embedded = model.embed.encode(ids);
|
|
323
|
-
ids.dispose();
|
|
324
|
-
h = ops.mulScalar(embedded, model.embedScale);
|
|
325
|
-
embedded.dispose();
|
|
326
|
-
} else {
|
|
327
|
-
// owned alias of the carried hidden state (constant [1,1,H])
|
|
328
|
-
h = ops.reshape(inputs[0]!, inputs[0]!.shape);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
for (let i = from; i < to; i++) {
|
|
332
|
-
const layer = model.layers[i]!;
|
|
333
|
-
const adapter = adapters[i - from]!;
|
|
334
|
-
const window = layer.layerType === "sliding_attention" ? model.windowSize : null;
|
|
335
|
-
const mask = adapter.makeMask(1, window); // N=1 → mode ""
|
|
336
|
-
const { h: next, shared } = layer.forward(h, mask, adapter as unknown as Cache, null, null);
|
|
337
|
-
h.dispose();
|
|
338
|
-
h = next;
|
|
339
|
-
disposeShared(shared);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
let out = h;
|
|
343
|
-
if (last) {
|
|
344
|
-
const normed = model.finalNorm.forward(h);
|
|
345
|
-
h.dispose();
|
|
346
|
-
out = model.logitsFromHidden(normed);
|
|
347
|
-
normed.dispose();
|
|
348
|
-
}
|
|
349
|
-
return [out, ...adapters.flatMap((a) => a.outs)];
|
|
350
|
-
} finally {
|
|
351
|
-
setCompiledTrace(false);
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// --- runner -----------------------------------------------------------------
|
|
357
|
-
|
|
358
|
-
const runners = new WeakMap<Gemma4Model, CompiledDecode>();
|
|
359
|
-
|
|
360
|
-
export class CompiledDecode {
|
|
361
|
-
/** Total compiled steps executed (tests assert the compiled path ran
|
|
362
|
-
* rather than silently falling back). */
|
|
363
|
-
static stepsExecuted = 0;
|
|
364
|
-
/** Total UNEXPECTED retraces observed (a shapeless closure tracing more
|
|
365
|
-
* than once). Must stay 0: a retrace means per-step JS graph builds
|
|
366
|
-
* sneaked back in, which both wrecks the perf win and signals shape
|
|
367
|
-
* drift. Surfaced loudly; tests assert on it. */
|
|
368
|
-
static unexpectedRetraces = 0;
|
|
369
|
-
|
|
370
|
-
#closures = new Map<string, CompiledFunction>();
|
|
371
|
-
/** Segmented mode: per layout key, one closure per segment (null for
|
|
372
|
-
* empty middle segments, which are identity). */
|
|
373
|
-
#segClosures = new Map<string, (CompiledFunction | null)[]>();
|
|
374
|
-
/** Closure keys whose apply failed (e.g. a primitive without
|
|
375
|
-
* output_shapes under shapeless replay): never re-trace these — the
|
|
376
|
-
* caller falls back to uncompiled without paying a trace per
|
|
377
|
-
* generation. */
|
|
378
|
-
#broken = new Set<string>();
|
|
379
|
-
/** Dense models (no KV sharing, per-layer inputs, or MoE) use the
|
|
380
|
-
* segmented form — growing-cache layers uncompiled, ring runs
|
|
381
|
-
* compiled. Models with cross-layer plumbing keep the whole-graph
|
|
382
|
-
* form (measured net-win on e4b; the concat copies it pays are the
|
|
383
|
-
* price of the sharing). */
|
|
384
|
-
readonly #segmented: boolean;
|
|
385
|
-
|
|
386
|
-
private constructor(readonly model: Gemma4Model) {
|
|
387
|
-
// A fresh resume has no prefill to evaluate lazy FP32 constants. Capture
|
|
388
|
-
// their values, not their construction graph, in every compiled closure.
|
|
389
|
-
model.materializeGraphConstants();
|
|
390
|
-
const t = model.config.text;
|
|
391
|
-
this.#segmented =
|
|
392
|
-
t.numKvSharedLayers === 0 && !t.enableMoeBlock && model.perLayerWidth === 0;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
static for(model: Gemma4Model): CompiledDecode {
|
|
396
|
-
let r = runners.get(model);
|
|
397
|
-
if (!r) {
|
|
398
|
-
r = new CompiledDecode(model);
|
|
399
|
-
runners.set(model, r);
|
|
400
|
-
}
|
|
401
|
-
return r;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/** Compilable this step? (Cheap; checked per generation setup.) */
|
|
405
|
-
static supports(caches: Cache[]): boolean {
|
|
406
|
-
return caches.every(
|
|
407
|
-
(c) =>
|
|
408
|
-
c instanceof KVCache ||
|
|
409
|
-
c instanceof QuantizedKVCache ||
|
|
410
|
-
c instanceof RotatingKVCache ||
|
|
411
|
-
c instanceof RotatingQuantizedKVCache,
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/** One decode step: consumes the pending token array (uint32 [1],
|
|
416
|
-
* unevaluated is fine), advances every cache by one position, returns
|
|
417
|
-
* the logits node plus the cache-update nodes that must ride the same
|
|
418
|
-
* async_eval. Throws on unsupported state — caller falls back to the
|
|
419
|
-
* uncompiled path (any growth already done is benign). */
|
|
420
|
-
step(cur: MlxArray, caches: Cache[]): { logits: MlxArray; evalWith: MlxArray[] } {
|
|
421
|
-
const offset0 = caches[0]!.offset;
|
|
422
|
-
for (const c of caches)
|
|
423
|
-
if (c.offset !== offset0)
|
|
424
|
-
throw new Error("compiled decode: cache offsets diverged");
|
|
425
|
-
return this.#segmented
|
|
426
|
-
? this.#stepSegmented(cur, caches as AnyCache[], offset0)
|
|
427
|
-
: this.#stepWhole(cur, caches as AnyCache[], offset0);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
#stepWhole(cur: MlxArray, anyCaches: AnyCache[], offset0: number): { logits: MlxArray; evalWith: MlxArray[] } {
|
|
431
|
-
const plans = anyCaches.map((c) => c.prepareDecodeStep());
|
|
432
|
-
const descs = anyCaches.map((c, i) => slotDesc(c, plans[i]!));
|
|
433
|
-
const key = closureKey(descs);
|
|
434
|
-
if (this.#broken.has(key)) throw new Error(`compiled decode: known-broken closure ${key}`);
|
|
435
|
-
|
|
436
|
-
// gather inputs — [cur, ropeOffset, ...per-cache slots]
|
|
437
|
-
const inputs: MlxArray[] = [cur];
|
|
438
|
-
const temps: MlxArray[] = [];
|
|
439
|
-
const ropeOff = ops.fromInt32([offset0], []);
|
|
440
|
-
temps.push(ropeOff);
|
|
441
|
-
inputs.push(ropeOff);
|
|
442
|
-
const writePosCache = new Map<number, MlxArray>();
|
|
443
|
-
const writePos = (v: number): MlxArray => {
|
|
444
|
-
let a = writePosCache.get(v);
|
|
445
|
-
if (!a) {
|
|
446
|
-
a = ops.fromInt32([v], [1]);
|
|
447
|
-
writePosCache.set(v, a);
|
|
448
|
-
temps.push(a);
|
|
449
|
-
}
|
|
450
|
-
return a;
|
|
451
|
-
};
|
|
452
|
-
const activeView = (a: MlxArray, len: number): MlxArray => {
|
|
453
|
-
const stop = [...a.shape];
|
|
454
|
-
stop[2] = len;
|
|
455
|
-
const view = a.slice(stop.map(() => 0), stop);
|
|
456
|
-
temps.push(view);
|
|
457
|
-
return view;
|
|
458
|
-
};
|
|
459
|
-
for (let i = 0; i < anyCaches.length; i++) {
|
|
460
|
-
const c = anyCaches[i]!;
|
|
461
|
-
const p = plans[i]!;
|
|
462
|
-
const d = descs[i]!;
|
|
463
|
-
if (d.kind === "p-cat") {
|
|
464
|
-
const pc = c as KVCache | RotatingKVCache;
|
|
465
|
-
inputs.push(activeView(pc.keys!, p.activeLen), activeView(pc.values!, p.activeLen));
|
|
466
|
-
} else if (d.kind === "q-cat") {
|
|
467
|
-
const qc = c as QuantizedKVCache | RotatingQuantizedKVCache;
|
|
468
|
-
for (const t of [qc.keys!, qc.values!])
|
|
469
|
-
inputs.push(
|
|
470
|
-
activeView(t.packed, p.activeLen),
|
|
471
|
-
activeView(t.scales, p.activeLen),
|
|
472
|
-
activeView(t.biases, p.activeLen),
|
|
473
|
-
);
|
|
474
|
-
} else if (d.kind === "p-ring") {
|
|
475
|
-
const rc = c as RotatingKVCache;
|
|
476
|
-
inputs.push(rc.keys!, rc.values!, writePos(p.writePos));
|
|
477
|
-
} else {
|
|
478
|
-
const rq = c as RotatingQuantizedKVCache;
|
|
479
|
-
inputs.push(
|
|
480
|
-
rq.keys!.packed, rq.keys!.scales, rq.keys!.biases,
|
|
481
|
-
rq.values!.packed, rq.values!.scales, rq.values!.biases,
|
|
482
|
-
writePos(p.writePos),
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
let closure = this.#closures.get(key);
|
|
488
|
-
if (!closure) {
|
|
489
|
-
closure = new CompiledFunction(makeTraceFn(this.model, descs), true);
|
|
490
|
-
this.#closures.set(key, closure);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
let outs: MlxArray[];
|
|
494
|
-
try {
|
|
495
|
-
outs = closure.apply(inputs);
|
|
496
|
-
} catch (e) {
|
|
497
|
-
this.#broken.add(key);
|
|
498
|
-
throw e;
|
|
499
|
-
} finally {
|
|
500
|
-
for (const t of temps) t.dispose();
|
|
501
|
-
}
|
|
502
|
-
if (closure.traceCount > 1) {
|
|
503
|
-
CompiledDecode.unexpectedRetraces++;
|
|
504
|
-
console.warn(
|
|
505
|
-
`compiled decode: closure retraced (count=${closure.traceCount}) — ` +
|
|
506
|
-
`input ndim/dtype drifted for key ${key}`,
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const logits = outs[0]!;
|
|
511
|
-
const evalWith: MlxArray[] = [];
|
|
512
|
-
let oi = 1;
|
|
513
|
-
for (let i = 0; i < anyCaches.length; i++) {
|
|
514
|
-
const c = anyCaches[i]!;
|
|
515
|
-
const d = descs[i]!;
|
|
516
|
-
if (d.kind === "p-cat") {
|
|
517
|
-
evalWith.push(...(c as KVCache | RotatingKVCache).writeDecodeStep(outs[oi]!, outs[oi + 1]!));
|
|
518
|
-
oi += 2;
|
|
519
|
-
} else if (d.kind === "q-cat") {
|
|
520
|
-
evalWith.push(...(c as QuantizedKVCache | RotatingQuantizedKVCache).writeDecodeStep(outs.slice(oi, oi + 6)));
|
|
521
|
-
oi += 6;
|
|
522
|
-
} else if (d.kind === "p-ring") {
|
|
523
|
-
// ring updates are ancestors of the logits (the in-graph fetch
|
|
524
|
-
// reads the updated buffer) — no explicit eval root needed
|
|
525
|
-
(c as RotatingKVCache).adoptDecodeStep(outs[oi]!, outs[oi + 1]!);
|
|
526
|
-
oi += 2;
|
|
527
|
-
} else {
|
|
528
|
-
(c as RotatingQuantizedKVCache).adoptDecodeStep(outs.slice(oi, oi + 6));
|
|
529
|
-
oi += 6;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
CompiledDecode.stepsExecuted++;
|
|
533
|
-
return { logits, evalWith };
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
#stepSegmented(cur: MlxArray, anyCaches: AnyCache[], offset0: number): { logits: MlxArray; evalWith: MlxArray[] } {
|
|
537
|
-
const phases = anyCaches.map(decodePhase);
|
|
538
|
-
// ring caches need their host bookkeeping (growth/trim/rotation) now;
|
|
539
|
-
// growing caches keep it inside their layer's real updateAndFetch
|
|
540
|
-
const plans = anyCaches.map((c, i) =>
|
|
541
|
-
phases[i] === "ring" ? c.prepareDecodeStep() : null,
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
// layout: consecutive ring layers form compiled segments, each
|
|
545
|
-
// growing-cache layer runs uncompiled between them
|
|
546
|
-
const segs: { from: number; to: number }[] = [];
|
|
547
|
-
const jsLayers: number[] = [];
|
|
548
|
-
let runStart = 0;
|
|
549
|
-
for (let i = 0; i < anyCaches.length; i++) {
|
|
550
|
-
if (phases[i] === "concat") {
|
|
551
|
-
segs.push({ from: runStart, to: i });
|
|
552
|
-
jsLayers.push(i);
|
|
553
|
-
runStart = i + 1;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
segs.push({ from: runStart, to: anyCaches.length });
|
|
557
|
-
|
|
558
|
-
// layout key: ring slot tags at their positions; js layers only by
|
|
559
|
-
// position (their quant params live outside the closures)
|
|
560
|
-
const key =
|
|
561
|
-
"seg|" +
|
|
562
|
-
anyCaches
|
|
563
|
-
.map((c, i) => (phases[i] === "ring" ? `${slotDesc(c, plans[i]!).kind}:${slotDesc(c, plans[i]!).groupSize}:${slotDesc(c, plans[i]!).bits}` : "js"))
|
|
564
|
-
.join(",") +
|
|
565
|
-
`|nf=${runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1" ? 1 : 0}`;
|
|
566
|
-
if (this.#broken.has(key)) throw new Error(`compiled decode: known-broken closure ${key}`);
|
|
567
|
-
|
|
568
|
-
let closures = this.#segClosures.get(key);
|
|
569
|
-
if (!closures) {
|
|
570
|
-
closures = segs.map(() => null);
|
|
571
|
-
this.#segClosures.set(key, closures);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
const ropeOff = ops.fromInt32([offset0], []);
|
|
575
|
-
const writePosCache = new Map<number, MlxArray>();
|
|
576
|
-
const stepTemps: MlxArray[] = [ropeOff];
|
|
577
|
-
const writePos = (v: number): MlxArray => {
|
|
578
|
-
let a = writePosCache.get(v);
|
|
579
|
-
if (!a) {
|
|
580
|
-
a = ops.fromInt32([v], [1]);
|
|
581
|
-
writePosCache.set(v, a);
|
|
582
|
-
stepTemps.push(a);
|
|
583
|
-
}
|
|
584
|
-
return a;
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
const evalWith: MlxArray[] = [];
|
|
588
|
-
let carried = cur; // seg 0 consumes the token array; later, hidden state
|
|
589
|
-
let carriedOwned = false; // cur belongs to the caller
|
|
590
|
-
// Mid-step failure safety (a later segment's closure.apply can throw at
|
|
591
|
-
// first trace AFTER earlier layers already advanced): the step must be
|
|
592
|
-
// TRANSACTIONAL, or the caller's uncompiled re-forward of the same token
|
|
593
|
-
// double-writes the committed layers (+1 offset skew forever, silently
|
|
594
|
-
// corrupted attention). Two mechanisms, chosen by what each phase allows:
|
|
595
|
-
// - ring segments: adoptDecodeStep is a pure host-side handle swap with
|
|
596
|
-
// no reader between here and step end (each cache is read only by its
|
|
597
|
-
// own layer, inside the closure that produced the update), so the
|
|
598
|
-
// adopts are STAGED and committed only once every segment and js layer
|
|
599
|
-
// has succeeded. On failure the staged buffers are disposed and the
|
|
600
|
-
// ring caches are exactly at their pre-step state (prepareDecodeStep's
|
|
601
|
-
// growth/trim/rotate bookkeeping is benign for the uncompiled path —
|
|
602
|
-
// the same invariant #stepWhole and generate.ts's fallback rely on).
|
|
603
|
-
// - js (concat) layers: layer.forward commits via the cache's real
|
|
604
|
-
// updateAndFetch mid-loop, so on failure the commit is ROLLED BACK by
|
|
605
|
-
// reverting offset (and ring index) — trim(1) semantics. The written
|
|
606
|
-
// KV row beyond the reverted offset is dead data the re-forward
|
|
607
|
-
// overwrites at the same position (updateAndFetch writes at offset/
|
|
608
|
-
// ringIdx), so post-recovery state equals a single clean write; the
|
|
609
|
-
// in-place S=1 write slot is re-derived from the reverted ringIdx.
|
|
610
|
-
const stagedAdopts: { c: AnyCache; bufs: MlxArray[] }[] = [];
|
|
611
|
-
const committedJs: { c: AnyCache; offsetBefore: number }[] = [];
|
|
612
|
-
try {
|
|
613
|
-
for (let s = 0; s < segs.length; s++) {
|
|
614
|
-
const { from, to } = segs[s]!;
|
|
615
|
-
const firstSeg = s === 0;
|
|
616
|
-
const lastSeg = s === segs.length - 1;
|
|
617
|
-
if (firstSeg || lastSeg || from < to) {
|
|
618
|
-
const descs = [];
|
|
619
|
-
const inputs: MlxArray[] = [carried, ropeOff];
|
|
620
|
-
for (let i = from; i < to; i++) {
|
|
621
|
-
const c = anyCaches[i]!;
|
|
622
|
-
const p = plans[i]!;
|
|
623
|
-
descs.push(slotDesc(c, p));
|
|
624
|
-
if (c instanceof RotatingQuantizedKVCache) {
|
|
625
|
-
inputs.push(
|
|
626
|
-
c.keys!.packed, c.keys!.scales, c.keys!.biases,
|
|
627
|
-
c.values!.packed, c.values!.scales, c.values!.biases,
|
|
628
|
-
writePos(p.writePos),
|
|
629
|
-
);
|
|
630
|
-
} else {
|
|
631
|
-
const rc = c as RotatingKVCache;
|
|
632
|
-
inputs.push(rc.keys!, rc.values!, writePos(p.writePos));
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
let closure = closures[s];
|
|
636
|
-
if (!closure) {
|
|
637
|
-
closure = new CompiledFunction(
|
|
638
|
-
makeSegmentTraceFn(this.model, descs, from, to, firstSeg, lastSeg),
|
|
639
|
-
true,
|
|
640
|
-
);
|
|
641
|
-
closures[s] = closure;
|
|
642
|
-
}
|
|
643
|
-
let outs: MlxArray[];
|
|
644
|
-
try {
|
|
645
|
-
outs = closure.apply(inputs);
|
|
646
|
-
} catch (e) {
|
|
647
|
-
this.#broken.add(key);
|
|
648
|
-
throw e;
|
|
649
|
-
}
|
|
650
|
-
if (closure.traceCount > 1) {
|
|
651
|
-
CompiledDecode.unexpectedRetraces++;
|
|
652
|
-
console.warn(`compiled decode: segment ${s} retraced for key ${key}`);
|
|
653
|
-
}
|
|
654
|
-
if (carriedOwned) carried.dispose();
|
|
655
|
-
carried = outs[0]!;
|
|
656
|
-
carriedOwned = true;
|
|
657
|
-
// ring updates are ancestors of the carried hidden state (the
|
|
658
|
-
// in-graph fetch reads the updated buffer): no eval roots. The
|
|
659
|
-
// host-side adoption is deferred to the end of the step (see above).
|
|
660
|
-
let oi = 1;
|
|
661
|
-
for (let i = from; i < to; i++) {
|
|
662
|
-
const c = anyCaches[i]!;
|
|
663
|
-
const width = c instanceof RotatingQuantizedKVCache ? 6 : 2;
|
|
664
|
-
stagedAdopts.push({ c, bufs: outs.slice(oi, oi + width) });
|
|
665
|
-
oi += width;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
if (s < jsLayers.length) {
|
|
669
|
-
const li = jsLayers[s]!;
|
|
670
|
-
const layer = this.model.layers[li]!;
|
|
671
|
-
const c = anyCaches[li]!;
|
|
672
|
-
const window = layer.layerType === "sliding_attention" ? this.model.windowSize : null;
|
|
673
|
-
const mask = c.makeMask(1, window); // N=1 → mode ""
|
|
674
|
-
committedJs.push({ c, offsetBefore: c.offset });
|
|
675
|
-
const { h: next, shared } = layer.forward(carried, mask, c, null, null);
|
|
676
|
-
if (carriedOwned) carried.dispose();
|
|
677
|
-
carried = next;
|
|
678
|
-
carriedOwned = true;
|
|
679
|
-
disposeShared(shared);
|
|
680
|
-
mask.arr?.dispose();
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
// every segment and js layer succeeded — commit the staged ring adopts
|
|
684
|
-
for (const { c, bufs } of stagedAdopts) {
|
|
685
|
-
if (c instanceof RotatingQuantizedKVCache) c.adoptDecodeStep(bufs);
|
|
686
|
-
else (c as RotatingKVCache).adoptDecodeStep(bufs[0]!, bufs[1]!);
|
|
687
|
-
}
|
|
688
|
-
} catch (e) {
|
|
689
|
-
// unwind: free staged (never-adopted) ring buffers and the owned hidden
|
|
690
|
-
// state, and revert the js layers' committed writes, so the caller's
|
|
691
|
-
// uncompiled re-forward of this token starts from the pre-step state.
|
|
692
|
-
for (const { bufs } of stagedAdopts) for (const b of bufs) b.dispose();
|
|
693
|
-
for (const { c, offsetBefore } of committedJs)
|
|
694
|
-
if (c.offset > offsetBefore) c.trim(c.offset - offsetBefore);
|
|
695
|
-
if (carriedOwned) carried.dispose();
|
|
696
|
-
throw e;
|
|
697
|
-
} finally {
|
|
698
|
-
for (const t of stepTemps) t.dispose();
|
|
699
|
-
}
|
|
700
|
-
CompiledDecode.stepsExecuted++;
|
|
701
|
-
return { logits: carried, evalWith };
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
/** Free compiled closures (model unload). */
|
|
705
|
-
dispose(): void {
|
|
706
|
-
for (const c of this.#closures.values()) c.dispose();
|
|
707
|
-
this.#closures.clear();
|
|
708
|
-
for (const arr of this.#segClosures.values())
|
|
709
|
-
for (const c of arr) c?.dispose();
|
|
710
|
-
this.#segClosures.clear();
|
|
711
|
-
}
|
|
712
|
-
}
|