mlx-bun 0.0.13 → 0.3.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 +71 -578
- package/bin/mlx-bun.mjs +1 -1
- package/docs/README.md +91 -0
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
- package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
- package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +395 -149
- package/docs/reference/distribution.md +321 -181
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +580 -142
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +137 -6
- package/docs/reference/server-api.md +938 -422
- package/docs/reference/server-config.md +652 -320
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +10 -5
- package/src/admission-plan.ts +18 -0
- package/src/anthropic.ts +92 -3
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +189 -61
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +263 -23
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +10 -79
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +24 -43
- package/src/generate.ts +740 -337
- package/src/grammar.ts +14 -8
- package/src/harness-pi.ts +15 -34
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +27 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +15 -14
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +459 -234
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +20 -4
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +32 -170
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +3 -4
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +66 -22
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +64 -19
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +9 -3
- package/src/model/batched-quant.ts +2 -2
- package/src/model/batched-rotating-quant.ts +45 -99
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +57 -106
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +4 -3
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +87 -49
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +187 -17
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +52 -148
- package/src/model/generated/gemma4-26b.ts +34 -94
- package/src/model/generated/gemma4-e4b.ts +28 -76
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +7 -8
- package/src/model/profile.ts +443 -0
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +336 -60
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +15 -7
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +14 -320
- package/src/prompt-cache.ts +97 -54
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +16 -3
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/trellis.ts +586 -0
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +130 -3
- package/src/runtime-config.ts +81 -0
- package/src/sampler.ts +276 -4
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +8 -1558
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +354 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +204 -0
- package/src/serve/generation-gateway.ts +211 -243
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +341 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +155 -0
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +162 -0
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +101 -0
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +523 -3551
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +9 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +5 -4
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +9 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +528 -0
- package/src/spec/serve-loop.ts +179 -213
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +95 -24
- package/src/ssd-durability.ts +207 -0
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +14 -13
- package/src/train/forward.ts +38 -1
- package/src/train/loss.ts +3 -2
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +9 -6
- package/src/train/trainer.ts +9 -8
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +48 -2
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +555 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.html +1 -1
- package/src/web/app.js +15 -6
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +16 -9
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +134 -33
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -268
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -189
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -288
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/investigations/hlg-ab.html +0 -34
- package/docs/investigations/hlg-explorer.html +0 -238
- package/docs/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/investigations/hlg-figs/cross.svg +0 -1
- package/docs/investigations/hlg-figs/edges.svg +0 -1
- package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/investigations/hlg-report.html +0 -262
- package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -100
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -13
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
- /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
|
@@ -545,7 +545,7 @@ export function flashBackward(
|
|
|
545
545
|
// (dK_j[d] → [kv_row][d]); no post-transpose. (An earlier "fix" transposed
|
|
546
546
|
// it on the false belief the buffer was swapped — that transpose is only the
|
|
547
547
|
// identity at Tkv==D and corrupted dK for Tkv≠D; removed after
|
|
548
|
-
//
|
|
548
|
+
// flash-dkv-debug.ts (deleted 2026-08-23; git history) showed the raw output is correct.)
|
|
549
549
|
return [dq[0]!, dkv[0]!, dkv[1]!];
|
|
550
550
|
} finally {
|
|
551
551
|
Dvec.dispose();
|
|
@@ -621,8 +621,8 @@ export function flashAttention(
|
|
|
621
621
|
// - This flash kernel is the L2 path: a port of mlx-optiq's
|
|
622
622
|
// flash_attention_metal (O(L) backward memory). Its parity oracle is OPTIQ,
|
|
623
623
|
// not finite differences. Confirmed: optiq's flash dK == ops.sdpa to f16
|
|
624
|
-
// (scripts/flash-optiq-check.py, rel 0.0%), and mlx-bun's flash == ops.sdpa
|
|
625
|
-
// (tests/flash-attention.test.ts) ⟹ mlx-bun flash == optiq flash (L2 parity).
|
|
624
|
+
// (scripts/oracle/flash-optiq-check.py, rel 0.0%), and mlx-bun's flash == ops.sdpa
|
|
625
|
+
// (tests/unit/flash-attention.test.ts) ⟹ mlx-bun flash == optiq flash (L2 parity).
|
|
626
626
|
//
|
|
627
627
|
// Two real port bugs were fixed to reach that parity (the original diverged
|
|
628
628
|
// ~100% from optiq on dK): a spurious dK transpose in flashBackward (corrupted
|
package/src/model/gemma4-base.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// gemma4-base — the config-INDEPENDENT machinery shared by every
|
|
2
|
-
// architecture variant (docs/
|
|
2
|
+
// architecture variant (docs/archive/investigations/optimization_plan.md Phase B: pure code
|
|
3
3
|
// movement out of the gemma4.ts monolith; every definition here is
|
|
4
4
|
// verbatim from it). Cache classes, quantized-KV SDPA, masks, the
|
|
5
5
|
// quantized primitives + LoRA machinery, and small graph helpers live
|
|
@@ -13,8 +13,10 @@ import type { Weights } from "../weights";
|
|
|
13
13
|
import { MlxArray } from "../mlx/array";
|
|
14
14
|
import { Dtype } from "../mlx/ffi";
|
|
15
15
|
import * as ops from "../mlx/ops";
|
|
16
|
+
import { quantizedMatmulRows } from "../mlx/quantized-rows";
|
|
16
17
|
import { expertOffloadArray } from "../expert-offload";
|
|
17
18
|
import * as tq from "../mlx/turboquant-ops";
|
|
19
|
+
import { runtimeValue } from "../runtime-config";
|
|
18
20
|
|
|
19
21
|
export type MaskMode = "" | "causal";
|
|
20
22
|
export interface Mask {
|
|
@@ -53,6 +55,15 @@ export class LoraState {
|
|
|
53
55
|
dropoutSeed: number | null = null;
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
/** Replaceable quantized payload. Inference sees this as read-only through
|
|
59
|
+
* QuantizedLinear getters; sensitivity analysis exchanges it atomically. */
|
|
60
|
+
export interface QuantizedLinearState {
|
|
61
|
+
w: MlxArray;
|
|
62
|
+
scales: MlxArray;
|
|
63
|
+
biases: MlxArray | null;
|
|
64
|
+
spec: ops.QuantSpec;
|
|
65
|
+
}
|
|
66
|
+
|
|
56
67
|
/** Inverted LoRA-input dropout, keyed by (seed, id) so it is deterministic —
|
|
57
68
|
* the same (seed, id, shape) reproduces the mask, which is what makes the
|
|
58
69
|
* segmented / gradient-checkpoint recompute correct. kept ⇒ x/(1-p),
|
|
@@ -79,18 +90,48 @@ export class QuantizedLinear {
|
|
|
79
90
|
/** Stable per-target index for keying training-only LoRA dropout (set by
|
|
80
91
|
* attachForTraining). Gives each adapted linear an independent dropout mask. */
|
|
81
92
|
dropoutId = 0;
|
|
93
|
+
private _w: MlxArray;
|
|
94
|
+
private _scales: MlxArray;
|
|
95
|
+
private _biases: MlxArray | null;
|
|
96
|
+
private _spec: ops.QuantSpec;
|
|
82
97
|
|
|
83
98
|
constructor(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
w: MlxArray,
|
|
100
|
+
scales: MlxArray,
|
|
101
|
+
biases: MlxArray | null,
|
|
102
|
+
spec: ops.QuantSpec,
|
|
88
103
|
/** ADDITIVE bias term (`.bias`, mlx nn.QuantizedLinear's optional bias —
|
|
89
104
|
* qwen2 qkv, starcoder2, …). Distinct from `biases`, the quantization
|
|
90
105
|
* zero-points. Applied after the matmul, before any LoRA residual,
|
|
91
106
|
* exactly like mlx's QuantizedLinear.__call__. */
|
|
92
107
|
readonly bias: MlxArray | null = null,
|
|
93
|
-
) {
|
|
108
|
+
) {
|
|
109
|
+
this._w = w;
|
|
110
|
+
this._scales = scales;
|
|
111
|
+
this._biases = biases;
|
|
112
|
+
this._spec = spec;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get w(): MlxArray { return this._w; }
|
|
116
|
+
get scales(): MlxArray { return this._scales; }
|
|
117
|
+
get biases(): MlxArray | null { return this._biases; }
|
|
118
|
+
get spec(): ops.QuantSpec { return this._spec; }
|
|
119
|
+
|
|
120
|
+
/** Atomically install a quantized payload and return the previous one.
|
|
121
|
+
* This is the sole mutation capability used by sensitivity sweeps. */
|
|
122
|
+
exchangeQuantizedState(next: QuantizedLinearState): QuantizedLinearState {
|
|
123
|
+
const previous = {
|
|
124
|
+
w: this._w,
|
|
125
|
+
scales: this._scales,
|
|
126
|
+
biases: this._biases,
|
|
127
|
+
spec: this._spec,
|
|
128
|
+
};
|
|
129
|
+
this._w = next.w;
|
|
130
|
+
this._scales = next.scales;
|
|
131
|
+
this._biases = next.biases;
|
|
132
|
+
this._spec = next.spec;
|
|
133
|
+
return previous;
|
|
134
|
+
}
|
|
94
135
|
|
|
95
136
|
static load(weights: Weights, path: string, config: ModelConfig): QuantizedLinear {
|
|
96
137
|
if (!weights.has(`${path}.scales`))
|
|
@@ -109,14 +150,23 @@ export class QuantizedLinear {
|
|
|
109
150
|
/** (in_features, out_features) from the quantized tensors (reference
|
|
110
151
|
* _infer_linear_shape: scales are [out, in/group_size]). */
|
|
111
152
|
get inFeatures(): number {
|
|
112
|
-
return this.
|
|
153
|
+
return this._scales.shape[1]! * this._spec.groupSize;
|
|
113
154
|
}
|
|
114
155
|
get outFeatures(): number {
|
|
115
|
-
return this.
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
forward(x: MlxArray): MlxArray {
|
|
119
|
-
let out =
|
|
156
|
+
return this._scales.shape[0]!;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
forward(x: MlxArray, independentRows = false): MlxArray {
|
|
160
|
+
let out = independentRows ? quantizedMatmulRows(
|
|
161
|
+
x, this._w, this._scales, this._biases, this._spec,
|
|
162
|
+
) : ops.quantizedMatmul(
|
|
163
|
+
x,
|
|
164
|
+
this._w,
|
|
165
|
+
this._scales,
|
|
166
|
+
this._biases,
|
|
167
|
+
this._spec,
|
|
168
|
+
true,
|
|
169
|
+
);
|
|
120
170
|
// Additive bias (mlx QuantizedLinear: `x = x + self["bias"]`), before
|
|
121
171
|
// the LoRA residual (LoRALinear calls the base linear bias-inclusive).
|
|
122
172
|
if (this.bias) out = disposing(out, ops.add(out, this.bias));
|
|
@@ -216,6 +266,20 @@ export type SharedKv =
|
|
|
216
266
|
|
|
217
267
|
export interface Cache {
|
|
218
268
|
offset: number;
|
|
269
|
+
/** Stable storage identity for compatibility guards and persistence.
|
|
270
|
+
* REQUIRED: every capability predicate (isPlainKvCache, isRotating*,
|
|
271
|
+
* kv-store codecs) is a string compare on this value, so a missing
|
|
272
|
+
* override used to fail OPEN into wrong routing (PRs #42/#43:
|
|
273
|
+
* BatchedRotatingCache shipped without one and batched joins dropped
|
|
274
|
+
* running rows). Wrappers report their own kind plus the inner kind. */
|
|
275
|
+
signature(): string;
|
|
276
|
+
/** Physical cache storage consumed by one additional token for one row.
|
|
277
|
+
* Recurrent caches return 0 because their state does not grow with the
|
|
278
|
+
* sequence. Optional for stateless/training adapters that are never
|
|
279
|
+
* admitted or persisted. */
|
|
280
|
+
bytesPerToken?(): number;
|
|
281
|
+
/** state() returned temporary views that the caller must release. */
|
|
282
|
+
readonly stateNeedsDispose?: boolean;
|
|
219
283
|
/** Compiled-decode trace adapters expose the RoPE offset as an int32
|
|
220
284
|
* array input here; real caches leave it unset (static int path). */
|
|
221
285
|
readonly ropeOffsetArr?: MlxArray;
|
|
@@ -231,9 +295,56 @@ export interface Cache {
|
|
|
231
295
|
* speculative-decode rollback case (trim the last n ≤ γ tips right after a
|
|
232
296
|
* >1 concat write); rotating caches then physically shrink the buffer tail. */
|
|
233
297
|
trim(n: number, bypass?: boolean): void;
|
|
298
|
+
/** Speculative verify-round support for NON-trimmable recurrent caches
|
|
299
|
+
* (SSMCache — gated-DeltaNet conv + recurrent state). A cache exposing
|
|
300
|
+
* these is spec-eligible without isTrimmable(): the serve loop arms a
|
|
301
|
+
* round before the verify forward (the layer snapshots pre-round state —
|
|
302
|
+
* free, MLX arrays are immutable — and records its position-local kernel
|
|
303
|
+
* inputs), then resolves it: commit on full accept, or rollback(keep)
|
|
304
|
+
* which restores the snapshot and bit-exactly REPLAYS the first `keep`
|
|
305
|
+
* window tokens through the recurrence (identical arithmetic prefix ⇒
|
|
306
|
+
* identical state). Trimmable caches leave these unset and keep trim(). */
|
|
307
|
+
specRoundBegin?(): void;
|
|
308
|
+
specRoundCommit?(): void;
|
|
309
|
+
specRoundRollback?(keep: number): void;
|
|
234
310
|
dispose(): void;
|
|
235
311
|
}
|
|
236
312
|
|
|
313
|
+
export function cacheSignature(cache: Cache | undefined): string {
|
|
314
|
+
return cache ? cache.signature() : "unknown";
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export interface RowBatchCache extends Cache {
|
|
318
|
+
readonly batchSize: number;
|
|
319
|
+
filterRows(keep: readonly number[]): void;
|
|
320
|
+
extractRow(row: number): Cache | null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export function isRowBatchCache(cache: Cache): cache is RowBatchCache {
|
|
324
|
+
const candidate = cache as Partial<RowBatchCache>;
|
|
325
|
+
return typeof candidate.batchSize === "number" &&
|
|
326
|
+
typeof candidate.filterRows === "function" &&
|
|
327
|
+
typeof candidate.extractRow === "function";
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export function isPlainKvCache(cache: Cache | undefined): cache is KVCache {
|
|
331
|
+
return cacheSignature(cache) === "kv:plain";
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function isQuantizedKvCache(cache: Cache | undefined): cache is QuantizedKVCache {
|
|
335
|
+
return cacheSignature(cache).startsWith("kv:quant:");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function isRotatingPlainCache(cache: Cache | undefined): cache is RotatingKVCache {
|
|
339
|
+
return cacheSignature(cache) === "kv:rotating-plain";
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function isRotatingQuantizedCache(
|
|
343
|
+
cache: Cache | undefined,
|
|
344
|
+
): cache is RotatingQuantizedKVCache {
|
|
345
|
+
return cacheSignature(cache).startsWith("kv:rotating-quant:");
|
|
346
|
+
}
|
|
347
|
+
|
|
237
348
|
/**
|
|
238
349
|
* Capability contract for cache layouts that own their dynamic-row batching.
|
|
239
350
|
* The scheduler uses this for non-K/V state families (for example GLM's
|
|
@@ -296,6 +407,13 @@ export class KVCache implements Cache {
|
|
|
296
407
|
values: MlxArray | null = null;
|
|
297
408
|
offset = 0;
|
|
298
409
|
|
|
410
|
+
signature(): string { return "kv:plain"; }
|
|
411
|
+
|
|
412
|
+
bytesPerToken(): number {
|
|
413
|
+
const steps = this.keys?.shape[2] ?? 0;
|
|
414
|
+
return steps > 0 ? (this.keys!.nbytes + this.values!.nbytes) / steps : 0;
|
|
415
|
+
}
|
|
416
|
+
|
|
299
417
|
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
|
300
418
|
const prev = this.offset;
|
|
301
419
|
const L = k.shape[2]!;
|
|
@@ -469,6 +587,18 @@ export class QuantizedKVCache implements Cache {
|
|
|
469
587
|
|
|
470
588
|
constructor(readonly groupSize: number, readonly bits: number) {}
|
|
471
589
|
|
|
590
|
+
signature(): string { return `kv:quant:${this.bits}:${this.groupSize}`; }
|
|
591
|
+
|
|
592
|
+
bytesPerToken(): number {
|
|
593
|
+
const steps = this.keys?.packed.shape[2] ?? 0;
|
|
594
|
+
if (steps === 0 || !this.keys || !this.values) return 0;
|
|
595
|
+
const tensors = [
|
|
596
|
+
this.keys.packed, this.keys.scales, this.keys.biases,
|
|
597
|
+
this.values.packed, this.values.scales, this.values.biases,
|
|
598
|
+
];
|
|
599
|
+
return tensors.reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
|
|
600
|
+
}
|
|
601
|
+
|
|
472
602
|
updateAndFetch(): [MlxArray, MlxArray] {
|
|
473
603
|
throw new Error("QuantizedKVCache: use updateAndFetchQuantized");
|
|
474
604
|
}
|
|
@@ -681,6 +811,13 @@ export class RotatingKVCache implements Cache {
|
|
|
681
811
|
this.maxSize = maxSize;
|
|
682
812
|
}
|
|
683
813
|
|
|
814
|
+
signature(): string { return "kv:rotating-plain"; }
|
|
815
|
+
|
|
816
|
+
bytesPerToken(): number {
|
|
817
|
+
const steps = this.keys?.shape[2] ?? 0;
|
|
818
|
+
return steps > 0 ? (this.keys!.nbytes + this.values!.nbytes) / steps : 0;
|
|
819
|
+
}
|
|
820
|
+
|
|
684
821
|
/** v with ring contents rearranged into temporal order (keep=0). */
|
|
685
822
|
#temporalOrder(v: MlxArray): MlxArray {
|
|
686
823
|
const S = v.shape[2]!;
|
|
@@ -1011,6 +1148,18 @@ export class RotatingQuantizedKVCache implements Cache {
|
|
|
1011
1148
|
this.maxSize = maxSize;
|
|
1012
1149
|
}
|
|
1013
1150
|
|
|
1151
|
+
signature(): string { return `kv:rotating-quant:${this.bits}:${this.groupSize}`; }
|
|
1152
|
+
|
|
1153
|
+
bytesPerToken(): number {
|
|
1154
|
+
const steps = this.keys?.packed.shape[2] ?? 0;
|
|
1155
|
+
if (steps === 0 || !this.keys || !this.values) return 0;
|
|
1156
|
+
const tensors = [
|
|
1157
|
+
this.keys.packed, this.keys.scales, this.keys.biases,
|
|
1158
|
+
this.values.packed, this.values.scales, this.values.biases,
|
|
1159
|
+
];
|
|
1160
|
+
return tensors.reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1014
1163
|
updateAndFetch(): [MlxArray, MlxArray] {
|
|
1015
1164
|
throw new Error("RotatingQuantizedKVCache: use updateAndFetchQuantized");
|
|
1016
1165
|
}
|
|
@@ -1358,7 +1507,7 @@ export class RotatingQuantizedKVCache implements Cache {
|
|
|
1358
1507
|
/** One TurboQuant-encoded (K, V) storage tuple — the 5 arrays kv-store.ts
|
|
1359
1508
|
* and toQuantized/fromKVCache pass around. Not `ops.QuantizedTensor`
|
|
1360
1509
|
* (mlx's affine int4/int8 scheme): this is the rotation + Lloyd-Max
|
|
1361
|
-
* layout (docs/design/turboquant
|
|
1510
|
+
* layout (docs/design/turboquant.md), asymmetric-affine for keys,
|
|
1362
1511
|
* FWHT+Lloyd-Max for values. Field order is the kv-store.ts tensor-slot
|
|
1363
1512
|
* contract — do not reorder without updating snapshotCache/loadKvCache. */
|
|
1364
1513
|
export interface TurboQuantTensor {
|
|
@@ -1377,7 +1526,7 @@ export const disposeTurboQuant = (t: TurboQuantTensor): void => {
|
|
|
1377
1526
|
t.vScales.dispose();
|
|
1378
1527
|
};
|
|
1379
1528
|
|
|
1380
|
-
/** TurboQuant KV cache — v1 (docs/design/turboquant
|
|
1529
|
+
/** TurboQuant KV cache — v1 (docs/design/turboquant.md): dequantize-
|
|
1381
1530
|
* on-fetch. Deliberately does NOT subclass KVCache/RotatingKVCache (or
|
|
1382
1531
|
* QuantizedKVCache) — a novel class fails every generated-file
|
|
1383
1532
|
* `#matches()` guard and every batching `instanceof` allow-list, so it
|
|
@@ -1396,6 +1545,7 @@ export const disposeTurboQuant = (t: TurboQuantTensor): void => {
|
|
|
1396
1545
|
* a full-window dequant every step; the deferred-InvFWHT trick is a
|
|
1397
1546
|
* documented non-goal until the quality gate passes. */
|
|
1398
1547
|
export class TurboQuantKVCache implements Cache {
|
|
1548
|
+
readonly stateNeedsDispose = true;
|
|
1399
1549
|
static readonly STEP = 256;
|
|
1400
1550
|
/** Set only by compiled-decode trace adapters (see Cache) — TurboQuant
|
|
1401
1551
|
* is not a compiled-decode participant in v1 (novel class, monolith
|
|
@@ -1406,9 +1556,22 @@ export class TurboQuantKVCache implements Cache {
|
|
|
1406
1556
|
offset = 0;
|
|
1407
1557
|
/** Validated lazily on first update, once head_dim is known. */
|
|
1408
1558
|
#headDim: number | null = null;
|
|
1559
|
+
/** Experimental operation selection, captured once for this cache. */
|
|
1560
|
+
readonly #fusedDecode = process.env.MLX_BUN_TURBOQUANT_FUSED_DECODE === "1";
|
|
1409
1561
|
|
|
1410
1562
|
constructor(readonly kBits: number, readonly vBits: number) {}
|
|
1411
1563
|
|
|
1564
|
+
signature(): string { return `kv:turboquant:${this.kBits}:${this.vBits}`; }
|
|
1565
|
+
|
|
1566
|
+
bytesPerToken(): number {
|
|
1567
|
+
const steps = this.#seqLen();
|
|
1568
|
+
if (steps === 0 || !this.#kv) return 0;
|
|
1569
|
+
return [
|
|
1570
|
+
this.#kv.kIdx, this.#kv.kScales, this.#kv.kZeros,
|
|
1571
|
+
this.#kv.vPacked, this.#kv.vScales,
|
|
1572
|
+
].reduce((bytes, array) => bytes + array.nbytes, 0) / steps;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1412
1575
|
get headDim(): number | null {
|
|
1413
1576
|
return this.#headDim;
|
|
1414
1577
|
}
|
|
@@ -1473,6 +1636,13 @@ export class TurboQuantKVCache implements Cache {
|
|
|
1473
1636
|
const [B, H, , D] = a.shape as [number, number, number, number];
|
|
1474
1637
|
return a.slice([0, 0, 0, 0], [B, H, upTo, D]);
|
|
1475
1638
|
};
|
|
1639
|
+
if (this.#fusedDecode) {
|
|
1640
|
+
const inputs = [cut(t.kIdx), cut(t.kScales), cut(t.kZeros), cut(t.vPacked), cut(t.vScales)] as const;
|
|
1641
|
+
try {
|
|
1642
|
+
const decoded = tq.tryDecodePackedKv(inputs, this.kBits, this.vBits, headDim, deferV);
|
|
1643
|
+
if (decoded) return decoded;
|
|
1644
|
+
} finally { for (const input of inputs) input.dispose(); }
|
|
1645
|
+
}
|
|
1476
1646
|
const kIdxCut = cut(t.kIdx);
|
|
1477
1647
|
const kIdxUnpacked = this.kBits < 8 ? tq.unpackBits(kIdxCut, this.kBits, headDim) : kIdxCut;
|
|
1478
1648
|
if (kIdxUnpacked !== kIdxCut) kIdxCut.dispose();
|
|
@@ -1927,9 +2097,9 @@ export function quantizedSdpaTiled(
|
|
|
1927
2097
|
function fusedSdpaSupported(q: MlxArray, mask: Mask, groupSize: number, bits: number): boolean {
|
|
1928
2098
|
// Escape hatch mirroring optiq serve's --no-fused-kv: forces the
|
|
1929
2099
|
// stock unfused path everywhere. Also the A/B lever for
|
|
1930
|
-
// scripts/bench-fused-prefill.
|
|
2100
|
+
// scripts/bench-levers.ts fused-prefill. Read per call (cheap next to the
|
|
1931
2101
|
// FFI work) so tests and paired A/B harnesses can flip it in-process.
|
|
1932
|
-
if (
|
|
2102
|
+
if (runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1") return false;
|
|
1933
2103
|
if (bits !== 4 && bits !== 8) return false;
|
|
1934
2104
|
if (groupSize !== 32 && groupSize !== 64 && groupSize !== 128) return false;
|
|
1935
2105
|
if (q.dtype !== Dtype.bfloat16 && q.dtype !== Dtype.float16) return false;
|
|
@@ -1971,7 +2141,7 @@ export function quantizedSdpa(
|
|
|
1971
2141
|
* as a compile-time constant and call this for the rest. The combined
|
|
1972
2142
|
* predicate is exactly fusedSdpaSupported. */
|
|
1973
2143
|
export function fusedSdpaRuntimeOk(q: MlxArray, mask: Mask): boolean {
|
|
1974
|
-
if (
|
|
2144
|
+
if (runtimeValue("MLX_BUN_NO_FUSED_SDPA") === "1") return false;
|
|
1975
2145
|
if (q.dtype !== Dtype.bfloat16 && q.dtype !== Dtype.float16) return false;
|
|
1976
2146
|
if (mask.mode === "causal" || mask.mode === "") return true;
|
|
1977
2147
|
if (mask.mode === "array")
|
package/src/model/gemma4.ts
CHANGED
|
@@ -23,7 +23,7 @@ import type { Weights } from "../weights";
|
|
|
23
23
|
import { MlxArray } from "../mlx/array";
|
|
24
24
|
import { Dtype } from "../mlx/ffi";
|
|
25
25
|
import * as ops from "../mlx/ops";
|
|
26
|
-
import { isExpertTracing, recordRouting } from "../expert-trace";
|
|
26
|
+
import { isExpertTracing, recordRouting } from "../lab/expert-trace/expert-trace";
|
|
27
27
|
|
|
28
28
|
// The shared, config-independent machinery lives in gemma4-base.ts
|
|
29
29
|
// (Phase B extraction); this file keeps the architecture-specific
|
|
@@ -56,7 +56,7 @@ import { Checkpoint } from "../mlx/checkpoint";
|
|
|
56
56
|
import { flashAttention, getTrainingAttn, flashSupported } from "./flash-attention";
|
|
57
57
|
import { unrotateValues as tqUnrotateValues } from "../mlx/turboquant-ops";
|
|
58
58
|
import { CompiledFunction } from "../mlx/compile";
|
|
59
|
-
import { flagOn } from "../
|
|
59
|
+
import { flagOn } from "../runtime-config";
|
|
60
60
|
|
|
61
61
|
/** Verbatim port of mlx_lm/models/gemma4_text.py:
|
|
62
62
|
* `@partial(mx.compile, shapeless=True) def geglu(gate, x): return nn.gelu_approx(gate) * x`
|
|
@@ -242,7 +242,7 @@ class Attention {
|
|
|
242
242
|
/** A number offset takes the static fast::rope; an array offset (set by
|
|
243
243
|
* compiled-decode trace adapters) takes the dynamic variant — same
|
|
244
244
|
* kernel, offset read from the array (bit-exactness asserted in
|
|
245
|
-
* tests/compile.test.ts). */
|
|
245
|
+
* tests/unit/compile.test.ts). */
|
|
246
246
|
rope(x: MlxArray, offset: number | MlxArray): MlxArray {
|
|
247
247
|
return typeof offset === "number"
|
|
248
248
|
? ops.rope(x, this.headDim, this.ropeBase, offset, this.ropeFreqs)
|
|
@@ -370,7 +370,7 @@ class Attention {
|
|
|
370
370
|
// verified route: its dQ/dK/dV vjps are exact (finite-difference checked;
|
|
371
371
|
// it's what mlx-lm's tuner differentiates). The two historical bugs were
|
|
372
372
|
// in THIS flash kernel (spurious dK transpose, divergent dQ barrier),
|
|
373
|
-
// both fixed and gated by tests/flash-attention.test.ts vs the ops.sdpa
|
|
373
|
+
// both fixed and gated by tests/unit/flash-attention.test.ts vs the ops.sdpa
|
|
374
374
|
// oracle — see flash-attention.ts's routing comment. Flash also remains
|
|
375
375
|
// Gemma-guarded in the trainer (e4b >=2K SIGTRAP not yet re-validated).
|
|
376
376
|
// Full layers → window 0 (pure causal); sliding layers → their window.
|
|
@@ -885,7 +885,7 @@ export class Gemma4Model {
|
|
|
885
885
|
* which attend bidirectionally among themselves (use_bidirectional_attention:
|
|
886
886
|
* "vision" — text stays causal; audio prompts pass NO bidir mask, and a
|
|
887
887
|
* mixed image+audio prompt drops the image overlay too, §3.3 Q1 of
|
|
888
|
-
* docs/design/
|
|
888
|
+
* docs/design/generic-model-support.md). `ids` ([1, L], the spliced token ids)
|
|
889
889
|
* is required for per-layer-input models (e2b/e4b): multimodal soft-token
|
|
890
890
|
* positions get token 0's per-layer embedding, and their tower content
|
|
891
891
|
* enters only through the projection term (the merged hidden). Matches
|
|
@@ -1015,7 +1015,7 @@ export class Gemma4Model {
|
|
|
1015
1015
|
return h;
|
|
1016
1016
|
}
|
|
1017
1017
|
|
|
1018
|
-
// --- Segmented-backward support (docs/design/
|
|
1018
|
+
// --- Segmented-backward support (docs/design/orpo-training.md
|
|
1019
1019
|
// §4 Phase B). These are ADDITIVE — forwardLayers is untouched. The segmented
|
|
1020
1020
|
// driver builds masks + per-layer inputs ONCE, then drives runLayerRange per
|
|
1021
1021
|
// segment, threading the KV-shared donor K/V across segment boundaries.
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
// fingerprint: 9f812d2eb461fcbe
|
|
5
5
|
//
|
|
6
6
|
// Branch-resolved, unrolled forward pass for this architecture
|
|
7
|
-
// (docs/
|
|
8
|
-
// generator's gate: tests/generated-parity.test.ts. The cache-signature
|
|
7
|
+
// (docs/archive/investigations/optimization_plan.md Phase C). Bit-exactness vs the monolith is the
|
|
8
|
+
// generator's gate: tests/parity/generated-parity.test.ts. The cache-signature
|
|
9
9
|
// guard falls back to the monolith for anything this file wasn't
|
|
10
10
|
// generated for (bf16 compat runs, vision bidir prefill).
|
|
11
11
|
|
|
12
12
|
import { MlxArray } from "../../mlx/array";
|
|
13
13
|
import * as ops from "../../mlx/ops";
|
|
14
14
|
import {
|
|
15
|
+
cacheSignature,
|
|
15
16
|
disposing,
|
|
16
17
|
fusedSdpaRuntimeOk,
|
|
17
18
|
KVCache,
|
|
@@ -202,155 +203,58 @@ function donorFullQuantG64B4KeqVScal(layer: DecoderLayer, x: MlxArray, mask: Mas
|
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
export class GeneratedGemma4 extends Gemma4Model {
|
|
205
|
-
/** Per-layer cache
|
|
206
|
-
* for; anything else runs the monolith path. */
|
|
206
|
+
/** Per-layer cache signatures must match what this file was generated for. */
|
|
207
207
|
#matches(cache: Cache[]): boolean {
|
|
208
208
|
return (
|
|
209
209
|
cache.length === 48 &&
|
|
210
|
-
cache[0]
|
|
211
|
-
cache[
|
|
212
|
-
cache[
|
|
213
|
-
cache[
|
|
214
|
-
cache[
|
|
215
|
-
cache[
|
|
216
|
-
cache[
|
|
217
|
-
cache[
|
|
218
|
-
cache[
|
|
219
|
-
cache[
|
|
220
|
-
cache[
|
|
221
|
-
cache[
|
|
222
|
-
cache[
|
|
223
|
-
cache[
|
|
224
|
-
cache[
|
|
225
|
-
cache[
|
|
226
|
-
cache[
|
|
227
|
-
cache[
|
|
228
|
-
cache[
|
|
229
|
-
cache[
|
|
230
|
-
cache[
|
|
231
|
-
cache[
|
|
232
|
-
cache[
|
|
233
|
-
cache[
|
|
234
|
-
cache[
|
|
235
|
-
cache[
|
|
236
|
-
cache[
|
|
237
|
-
cache[
|
|
238
|
-
cache[
|
|
239
|
-
cache[
|
|
240
|
-
cache[
|
|
241
|
-
cache[
|
|
242
|
-
cache[
|
|
243
|
-
cache[
|
|
244
|
-
cache[
|
|
245
|
-
cache[
|
|
246
|
-
cache[
|
|
247
|
-
cache[
|
|
248
|
-
cache[
|
|
249
|
-
cache[
|
|
250
|
-
cache[
|
|
251
|
-
cache[
|
|
252
|
-
cache[
|
|
253
|
-
cache[
|
|
254
|
-
cache[
|
|
255
|
-
cache[
|
|
256
|
-
cache[
|
|
257
|
-
cache[
|
|
258
|
-
cache[16] instanceof RotatingQuantizedKVCache &&
|
|
259
|
-
cache[16].bits === 4 &&
|
|
260
|
-
cache[16].groupSize === 64 &&
|
|
261
|
-
cache[17] instanceof QuantizedKVCache &&
|
|
262
|
-
cache[17].bits === 4 &&
|
|
263
|
-
cache[17].groupSize === 64 &&
|
|
264
|
-
cache[18] instanceof RotatingQuantizedKVCache &&
|
|
265
|
-
cache[18].bits === 4 &&
|
|
266
|
-
cache[18].groupSize === 64 &&
|
|
267
|
-
cache[19] instanceof RotatingQuantizedKVCache &&
|
|
268
|
-
cache[19].bits === 4 &&
|
|
269
|
-
cache[19].groupSize === 64 &&
|
|
270
|
-
cache[20] instanceof RotatingQuantizedKVCache &&
|
|
271
|
-
cache[20].bits === 4 &&
|
|
272
|
-
cache[20].groupSize === 64 &&
|
|
273
|
-
cache[21] instanceof RotatingQuantizedKVCache &&
|
|
274
|
-
cache[21].bits === 4 &&
|
|
275
|
-
cache[21].groupSize === 64 &&
|
|
276
|
-
cache[22] instanceof RotatingQuantizedKVCache &&
|
|
277
|
-
cache[22].bits === 4 &&
|
|
278
|
-
cache[22].groupSize === 64 &&
|
|
279
|
-
cache[23] instanceof QuantizedKVCache &&
|
|
280
|
-
cache[23].bits === 4 &&
|
|
281
|
-
cache[23].groupSize === 64 &&
|
|
282
|
-
cache[24] instanceof RotatingQuantizedKVCache &&
|
|
283
|
-
cache[24].bits === 4 &&
|
|
284
|
-
cache[24].groupSize === 64 &&
|
|
285
|
-
cache[25] instanceof RotatingQuantizedKVCache &&
|
|
286
|
-
cache[25].bits === 4 &&
|
|
287
|
-
cache[25].groupSize === 64 &&
|
|
288
|
-
cache[26] instanceof RotatingQuantizedKVCache &&
|
|
289
|
-
cache[26].bits === 4 &&
|
|
290
|
-
cache[26].groupSize === 64 &&
|
|
291
|
-
cache[27] instanceof RotatingQuantizedKVCache &&
|
|
292
|
-
cache[27].bits === 4 &&
|
|
293
|
-
cache[27].groupSize === 64 &&
|
|
294
|
-
cache[28] instanceof RotatingQuantizedKVCache &&
|
|
295
|
-
cache[28].bits === 4 &&
|
|
296
|
-
cache[28].groupSize === 64 &&
|
|
297
|
-
cache[29] instanceof QuantizedKVCache &&
|
|
298
|
-
cache[29].bits === 4 &&
|
|
299
|
-
cache[29].groupSize === 64 &&
|
|
300
|
-
cache[30] instanceof RotatingQuantizedKVCache &&
|
|
301
|
-
cache[30].bits === 4 &&
|
|
302
|
-
cache[30].groupSize === 64 &&
|
|
303
|
-
cache[31] instanceof RotatingQuantizedKVCache &&
|
|
304
|
-
cache[31].bits === 4 &&
|
|
305
|
-
cache[31].groupSize === 64 &&
|
|
306
|
-
cache[32] instanceof RotatingQuantizedKVCache &&
|
|
307
|
-
cache[32].bits === 4 &&
|
|
308
|
-
cache[32].groupSize === 64 &&
|
|
309
|
-
cache[33] instanceof RotatingQuantizedKVCache &&
|
|
310
|
-
cache[33].bits === 4 &&
|
|
311
|
-
cache[33].groupSize === 64 &&
|
|
312
|
-
cache[34] instanceof RotatingQuantizedKVCache &&
|
|
313
|
-
cache[34].bits === 4 &&
|
|
314
|
-
cache[34].groupSize === 64 &&
|
|
315
|
-
cache[35] instanceof QuantizedKVCache &&
|
|
316
|
-
cache[35].bits === 4 &&
|
|
317
|
-
cache[35].groupSize === 64 &&
|
|
318
|
-
cache[36] instanceof RotatingQuantizedKVCache &&
|
|
319
|
-
cache[36].bits === 4 &&
|
|
320
|
-
cache[36].groupSize === 64 &&
|
|
321
|
-
cache[37] instanceof RotatingQuantizedKVCache &&
|
|
322
|
-
cache[37].bits === 4 &&
|
|
323
|
-
cache[37].groupSize === 64 &&
|
|
324
|
-
cache[38] instanceof RotatingQuantizedKVCache &&
|
|
325
|
-
cache[38].bits === 4 &&
|
|
326
|
-
cache[38].groupSize === 64 &&
|
|
327
|
-
cache[39] instanceof RotatingQuantizedKVCache &&
|
|
328
|
-
cache[39].bits === 4 &&
|
|
329
|
-
cache[39].groupSize === 64 &&
|
|
330
|
-
cache[40] instanceof RotatingQuantizedKVCache &&
|
|
331
|
-
cache[40].bits === 4 &&
|
|
332
|
-
cache[40].groupSize === 64 &&
|
|
333
|
-
cache[41] instanceof QuantizedKVCache &&
|
|
334
|
-
cache[41].bits === 4 &&
|
|
335
|
-
cache[41].groupSize === 64 &&
|
|
336
|
-
cache[42] instanceof RotatingQuantizedKVCache &&
|
|
337
|
-
cache[42].bits === 4 &&
|
|
338
|
-
cache[42].groupSize === 64 &&
|
|
339
|
-
cache[43] instanceof RotatingQuantizedKVCache &&
|
|
340
|
-
cache[43].bits === 4 &&
|
|
341
|
-
cache[43].groupSize === 64 &&
|
|
342
|
-
cache[44] instanceof RotatingQuantizedKVCache &&
|
|
343
|
-
cache[44].bits === 4 &&
|
|
344
|
-
cache[44].groupSize === 64 &&
|
|
345
|
-
cache[45] instanceof RotatingQuantizedKVCache &&
|
|
346
|
-
cache[45].bits === 4 &&
|
|
347
|
-
cache[45].groupSize === 64 &&
|
|
348
|
-
cache[46] instanceof RotatingQuantizedKVCache &&
|
|
349
|
-
cache[46].bits === 4 &&
|
|
350
|
-
cache[46].groupSize === 64 &&
|
|
351
|
-
cache[47] instanceof QuantizedKVCache &&
|
|
352
|
-
cache[47].bits === 4 &&
|
|
353
|
-
cache[47].groupSize === 64
|
|
210
|
+
cacheSignature(cache[0]) === "kv:rotating-quant:4:64" &&
|
|
211
|
+
cacheSignature(cache[1]) === "kv:rotating-quant:4:64" &&
|
|
212
|
+
cacheSignature(cache[2]) === "kv:rotating-quant:4:64" &&
|
|
213
|
+
cacheSignature(cache[3]) === "kv:rotating-quant:8:64" &&
|
|
214
|
+
cacheSignature(cache[4]) === "kv:rotating-quant:4:64" &&
|
|
215
|
+
cacheSignature(cache[5]) === "kv:quant:4:64" &&
|
|
216
|
+
cacheSignature(cache[6]) === "kv:rotating-quant:8:64" &&
|
|
217
|
+
cacheSignature(cache[7]) === "kv:rotating-quant:8:64" &&
|
|
218
|
+
cacheSignature(cache[8]) === "kv:rotating-quant:8:64" &&
|
|
219
|
+
cacheSignature(cache[9]) === "kv:rotating-quant:4:64" &&
|
|
220
|
+
cacheSignature(cache[10]) === "kv:rotating-quant:8:64" &&
|
|
221
|
+
cacheSignature(cache[11]) === "kv:quant:4:64" &&
|
|
222
|
+
cacheSignature(cache[12]) === "kv:rotating-quant:8:64" &&
|
|
223
|
+
cacheSignature(cache[13]) === "kv:rotating-quant:4:64" &&
|
|
224
|
+
cacheSignature(cache[14]) === "kv:rotating-quant:4:64" &&
|
|
225
|
+
cacheSignature(cache[15]) === "kv:rotating-quant:4:64" &&
|
|
226
|
+
cacheSignature(cache[16]) === "kv:rotating-quant:4:64" &&
|
|
227
|
+
cacheSignature(cache[17]) === "kv:quant:4:64" &&
|
|
228
|
+
cacheSignature(cache[18]) === "kv:rotating-quant:4:64" &&
|
|
229
|
+
cacheSignature(cache[19]) === "kv:rotating-quant:4:64" &&
|
|
230
|
+
cacheSignature(cache[20]) === "kv:rotating-quant:4:64" &&
|
|
231
|
+
cacheSignature(cache[21]) === "kv:rotating-quant:4:64" &&
|
|
232
|
+
cacheSignature(cache[22]) === "kv:rotating-quant:4:64" &&
|
|
233
|
+
cacheSignature(cache[23]) === "kv:quant:4:64" &&
|
|
234
|
+
cacheSignature(cache[24]) === "kv:rotating-quant:4:64" &&
|
|
235
|
+
cacheSignature(cache[25]) === "kv:rotating-quant:4:64" &&
|
|
236
|
+
cacheSignature(cache[26]) === "kv:rotating-quant:4:64" &&
|
|
237
|
+
cacheSignature(cache[27]) === "kv:rotating-quant:4:64" &&
|
|
238
|
+
cacheSignature(cache[28]) === "kv:rotating-quant:4:64" &&
|
|
239
|
+
cacheSignature(cache[29]) === "kv:quant:4:64" &&
|
|
240
|
+
cacheSignature(cache[30]) === "kv:rotating-quant:4:64" &&
|
|
241
|
+
cacheSignature(cache[31]) === "kv:rotating-quant:4:64" &&
|
|
242
|
+
cacheSignature(cache[32]) === "kv:rotating-quant:4:64" &&
|
|
243
|
+
cacheSignature(cache[33]) === "kv:rotating-quant:4:64" &&
|
|
244
|
+
cacheSignature(cache[34]) === "kv:rotating-quant:4:64" &&
|
|
245
|
+
cacheSignature(cache[35]) === "kv:quant:4:64" &&
|
|
246
|
+
cacheSignature(cache[36]) === "kv:rotating-quant:4:64" &&
|
|
247
|
+
cacheSignature(cache[37]) === "kv:rotating-quant:4:64" &&
|
|
248
|
+
cacheSignature(cache[38]) === "kv:rotating-quant:4:64" &&
|
|
249
|
+
cacheSignature(cache[39]) === "kv:rotating-quant:4:64" &&
|
|
250
|
+
cacheSignature(cache[40]) === "kv:rotating-quant:4:64" &&
|
|
251
|
+
cacheSignature(cache[41]) === "kv:quant:4:64" &&
|
|
252
|
+
cacheSignature(cache[42]) === "kv:rotating-quant:4:64" &&
|
|
253
|
+
cacheSignature(cache[43]) === "kv:rotating-quant:4:64" &&
|
|
254
|
+
cacheSignature(cache[44]) === "kv:rotating-quant:4:64" &&
|
|
255
|
+
cacheSignature(cache[45]) === "kv:rotating-quant:4:64" &&
|
|
256
|
+
cacheSignature(cache[46]) === "kv:rotating-quant:4:64" &&
|
|
257
|
+
cacheSignature(cache[47]) === "kv:quant:4:64"
|
|
354
258
|
);
|
|
355
259
|
}
|
|
356
260
|
|