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
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Qwen3.5/3.8 multimodal RoPE (mRoPE) — the language-side position machinery
|
|
2
|
+
// for vision requests (PLAN 14v), port of mlx-vlm's qwen3_5 language rope:
|
|
3
|
+
// MRoPERotaryEmbedding (style "interleaved", mrope_section [11,11,10]) +
|
|
4
|
+
// get_rope_index + the rope_deltas decode continuation.
|
|
5
|
+
//
|
|
6
|
+
// TEXT-ONLY EQUIVALENCE: with all three position streams equal, interleaved
|
|
7
|
+
// selection collapses to plain partial RoPE — which is why the text path's
|
|
8
|
+
// ops.rope stays bit-exact untouched. This module only activates for
|
|
9
|
+
// requests whose prompt contains vision spans; while active, EVERY
|
|
10
|
+
// full-attention rope in the request (prefill AND decode) goes through the
|
|
11
|
+
// manual interleaved path, mirroring the reference (which never uses the
|
|
12
|
+
// fused fast-rope kernel when position_ids are supplied).
|
|
13
|
+
//
|
|
14
|
+
// Position semantics (get_rope_index, B=1 serial): text tokens advance all
|
|
15
|
+
// three streams together; an image span of grid (t, h/merge, w/merge) gets
|
|
16
|
+
// t/h/w grid positions offset by the current base; text after an image
|
|
17
|
+
// resumes at max+1. delta = (max position + 1) - sequence length; decode
|
|
18
|
+
// positions are offset + delta on all three streams.
|
|
19
|
+
|
|
20
|
+
import { MlxArray } from "../mlx/array";
|
|
21
|
+
import { Dtype } from "../mlx/ffi";
|
|
22
|
+
import * as ops from "../mlx/ops";
|
|
23
|
+
import { MetalKernel } from "../mlx/metal-kernel";
|
|
24
|
+
|
|
25
|
+
export interface MropeRequestState {
|
|
26
|
+
/** Full-grid positions for the prompt, one Int32Array per t/h/w stream. */
|
|
27
|
+
positions: [Int32Array, Int32Array, Int32Array];
|
|
28
|
+
/** (max position + 1) - promptLength; decode positions = offset + delta. */
|
|
29
|
+
delta: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface MropeForwardState {
|
|
33
|
+
/** Effective positions [3, 1, L] int32 for the CURRENT forward window. */
|
|
34
|
+
posIds: MlxArray;
|
|
35
|
+
/** Borrowed model-owned f32 inv_freq (mropeInvFreq) — not disposed here. */
|
|
36
|
+
invFreq: MlxArray;
|
|
37
|
+
rotaryDims: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Active per-forward mRoPE cos/sin, read by Qwen3Attention.forward. Null on
|
|
41
|
+
* the text-only path (serial lane only — vision requests never batch). */
|
|
42
|
+
export let activeMrope: MropeForwardState | null = null;
|
|
43
|
+
export function setActiveMrope(s: MropeForwardState | null): void {
|
|
44
|
+
activeMrope = s;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const MROPE_SECTION = [11, 11, 10] as const;
|
|
48
|
+
|
|
49
|
+
/** Interleaved frequency→stream selector (rope_utils
|
|
50
|
+
* _interleaved_position_selector): default t(0); indices 1,4,7,… take
|
|
51
|
+
* h(1) while < section[1]*3; indices 2,5,8,… take w(2) while < section[2]*3. */
|
|
52
|
+
export function interleavedSelector(freqDim: number): Int32Array {
|
|
53
|
+
const sel = new Int32Array(freqDim);
|
|
54
|
+
for (let dim = 1; dim <= 2; dim++) {
|
|
55
|
+
const offset = dim; // h starts at 1, w at 2
|
|
56
|
+
for (let i = offset; i < Math.min(MROPE_SECTION[dim]! * 3, freqDim); i += 3)
|
|
57
|
+
sel[i] = dim;
|
|
58
|
+
}
|
|
59
|
+
return sel;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** inv_freq for the language rope — computed on-device exactly like
|
|
63
|
+
* compute_inv_freq (Metal powf is not correctly rounded; a JS emulation
|
|
64
|
+
* drifts by 1 ulp on some entries). Returned as a live f32 device array
|
|
65
|
+
* (the apply kernel reads it directly). */
|
|
66
|
+
export function mropeInvFreq(rotaryDims: number, base: number): MlxArray {
|
|
67
|
+
const ar = ops.arange(0, rotaryDims, 2, Dtype.float32);
|
|
68
|
+
const ex = ops.mulScalar(ar, 1 / rotaryDims);
|
|
69
|
+
ar.dispose();
|
|
70
|
+
const theta = MlxArray.fromFloat32(Float32Array.from([base]), [1]);
|
|
71
|
+
const p = ops.pow(theta, ex);
|
|
72
|
+
theta.dispose();
|
|
73
|
+
ex.dispose();
|
|
74
|
+
const one = MlxArray.fromFloat32(Float32Array.from([1]), [1]);
|
|
75
|
+
const invA = ops.div(one, p);
|
|
76
|
+
one.dispose();
|
|
77
|
+
p.dispose();
|
|
78
|
+
return invA;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Effective positions [3,1,L] int32 for window [offset, offset+L) —
|
|
82
|
+
* prompt-grid positions while inside the prompt, offset+delta beyond it
|
|
83
|
+
* (the reference's rope_deltas continuation). */
|
|
84
|
+
export function buildMropePositions(
|
|
85
|
+
state: MropeRequestState, offset: number, L: number,
|
|
86
|
+
invFreq: MlxArray, rotaryDims: number,
|
|
87
|
+
): MropeForwardState {
|
|
88
|
+
const P = state.positions;
|
|
89
|
+
const promptLen = P[0].length;
|
|
90
|
+
const joint = new Int32Array(3 * L);
|
|
91
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
92
|
+
for (let l = 0; l < L; l++) {
|
|
93
|
+
const idx = offset + l;
|
|
94
|
+
joint[axis * L + l] = idx < promptLen ? P[axis]![idx]! : idx + state.delta;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { posIds: MlxArray.fromInt32(joint, [3, 1, L]), invFreq, rotaryDims };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The reference language-side apply is a CUSTOM METAL KERNEL (rope_utils
|
|
101
|
+
// _mrope_apply_kernel, pairing "half_split", position_ndim 3): per rotated
|
|
102
|
+
// pair it computes angle = pos * inv_freq in f32, cos/sin in-kernel, and
|
|
103
|
+
// writes x*c − x_pair*s / x_pair*c + x*s with ONE rounding to the tensor
|
|
104
|
+
// dtype. A bf16 cos/sin manual path is ~0.4% off per rotation and moved
|
|
105
|
+
// step-0 logits by ~1.0 — this verbatim port is the oracle's arithmetic.
|
|
106
|
+
const kernelCache = new Map<number, MetalKernel>();
|
|
107
|
+
function mropeKernel(rotaryDims: number): MetalKernel {
|
|
108
|
+
let k = kernelCache.get(rotaryDims);
|
|
109
|
+
if (k) return k;
|
|
110
|
+
const half = rotaryDims / 2;
|
|
111
|
+
const source = `
|
|
112
|
+
uint elem = thread_position_in_grid.x;
|
|
113
|
+
|
|
114
|
+
const int half_dim = ${half};
|
|
115
|
+
const int q_bsz = x_shape[0];
|
|
116
|
+
const int q_heads = x_shape[1];
|
|
117
|
+
const int q_len = x_shape[2];
|
|
118
|
+
const int q_dim = x_shape[3];
|
|
119
|
+
const int slots = half_dim + q_dim - ${rotaryDims};
|
|
120
|
+
const int work_size = q_bsz * q_heads * q_len * slots;
|
|
121
|
+
|
|
122
|
+
if (elem >= uint(work_size)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
int local = int(elem);
|
|
127
|
+
int slot = local % slots;
|
|
128
|
+
int tmp = local / slots;
|
|
129
|
+
int t = tmp % q_len;
|
|
130
|
+
tmp = tmp / q_len;
|
|
131
|
+
int h = tmp % q_heads;
|
|
132
|
+
int b = tmp / q_heads;
|
|
133
|
+
int base = ((b * q_heads + h) * q_len + t) * q_dim;
|
|
134
|
+
|
|
135
|
+
if (slot >= half_dim) {
|
|
136
|
+
int pass_d = ${rotaryDims} + slot - half_dim;
|
|
137
|
+
int pass_idx = base + pass_d;
|
|
138
|
+
x_out[pass_idx] = x[pass_idx];
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
int freq_idx = slot;
|
|
143
|
+
int d = freq_idx;
|
|
144
|
+
int pair_d = d + half_dim;
|
|
145
|
+
int axis = int(position_selector[freq_idx]);
|
|
146
|
+
float pos = static_cast<float>(position_ids[(axis * q_bsz + b) * q_len + t]);
|
|
147
|
+
float angle = pos * static_cast<float>(inv_freq[freq_idx]);
|
|
148
|
+
float c = metal::cos(angle);
|
|
149
|
+
float s = metal::sin(angle);
|
|
150
|
+
|
|
151
|
+
int idx = base + d;
|
|
152
|
+
float xv = static_cast<float>(x[idx]);
|
|
153
|
+
float xp = static_cast<float>(x[base + pair_d]);
|
|
154
|
+
x_out[idx] = static_cast<T>(xv * c - xp * s);
|
|
155
|
+
x_out[base + pair_d] = static_cast<T>(xp * c + xv * s);
|
|
156
|
+
`;
|
|
157
|
+
k = new MetalKernel({
|
|
158
|
+
name: `mrope_apply_half_split_${rotaryDims}_3d`,
|
|
159
|
+
inputNames: ["x", "position_ids", "inv_freq", "position_selector"],
|
|
160
|
+
outputNames: ["x_out"],
|
|
161
|
+
source,
|
|
162
|
+
ensureRowContiguous: true,
|
|
163
|
+
});
|
|
164
|
+
kernelCache.set(rotaryDims, k);
|
|
165
|
+
return k;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const selectorCache = new Map<number, MlxArray>();
|
|
169
|
+
function selectorArr(half: number): MlxArray {
|
|
170
|
+
let s = selectorCache.get(half);
|
|
171
|
+
if (!s) {
|
|
172
|
+
s = MlxArray.fromInt32(interleavedSelector(half), [half]);
|
|
173
|
+
selectorCache.set(half, s);
|
|
174
|
+
}
|
|
175
|
+
return s;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Apply interleaved mRoPE to one [B, heads, L, headDim] tensor via the
|
|
179
|
+
* reference's exact Metal kernel. `invFreq` is the f32 device array from
|
|
180
|
+
* mropeInvFreq. */
|
|
181
|
+
export function applyInterleavedRope(
|
|
182
|
+
x: MlxArray, fwd: MropeForwardState,
|
|
183
|
+
): MlxArray {
|
|
184
|
+
const rotaryDims = fwd.rotaryDims;
|
|
185
|
+
const [B, H, L, D] = x.shape as [number, number, number, number];
|
|
186
|
+
const half = rotaryDims / 2;
|
|
187
|
+
const slots = half + D - rotaryDims;
|
|
188
|
+
const work = B * H * L * slots;
|
|
189
|
+
const [out] = mropeKernel(rotaryDims).apply(
|
|
190
|
+
[x, fwd.posIds, fwd.invFreq, selectorArr(half)],
|
|
191
|
+
{
|
|
192
|
+
outputs: [{ shape: [B, H, L, D], dtype: x.dtype }],
|
|
193
|
+
grid: [work, 1, 1],
|
|
194
|
+
threadGroup: [256, 1, 1],
|
|
195
|
+
templateDtypes: { T: x.dtype },
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
return out!;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** get_rope_index port (B=1, no attention mask): positions per stream + the
|
|
202
|
+
* decode delta for a prompt with vision spans. `grids` are the per-image
|
|
203
|
+
* (t, h, w) grids in PATCH units and must appear in prompt order. */
|
|
204
|
+
export function qwenRopeIndex(
|
|
205
|
+
ids: readonly number[],
|
|
206
|
+
grids: readonly [number, number, number][],
|
|
207
|
+
mergeSize: number,
|
|
208
|
+
imageTokenId: number,
|
|
209
|
+
videoTokenId: number,
|
|
210
|
+
): MropeRequestState {
|
|
211
|
+
const L = ids.length;
|
|
212
|
+
const P: [Int32Array, Int32Array, Int32Array] =
|
|
213
|
+
[new Int32Array(L), new Int32Array(L), new Int32Array(L)];
|
|
214
|
+
let write = 0; // next output index (== st in the reference walk)
|
|
215
|
+
let base = 0; // st_idx: next position after everything placed so far
|
|
216
|
+
let gi = 0;
|
|
217
|
+
let i = 0;
|
|
218
|
+
while (i < L) {
|
|
219
|
+
const tok = ids[i]!;
|
|
220
|
+
if ((tok === imageTokenId || tok === videoTokenId) && gi < grids.length) {
|
|
221
|
+
const [t, h, w] = grids[gi]!;
|
|
222
|
+
gi++;
|
|
223
|
+
const gh = Math.trunc(h / mergeSize);
|
|
224
|
+
const gw = Math.trunc(w / mergeSize);
|
|
225
|
+
const span = t * gh * gw;
|
|
226
|
+
for (let k = 0; k < span; k++) {
|
|
227
|
+
const tt = Math.trunc(k / (gh * gw));
|
|
228
|
+
const rem = k % (gh * gw);
|
|
229
|
+
const hh = Math.trunc(rem / gw);
|
|
230
|
+
const ww = rem % gw;
|
|
231
|
+
P[0][write + k] = base + tt;
|
|
232
|
+
P[1][write + k] = base + hh;
|
|
233
|
+
P[2][write + k] = base + ww;
|
|
234
|
+
}
|
|
235
|
+
// Reference: next base = max position in the span + 1 = base +
|
|
236
|
+
// max(t, gh, gw) … computed as llm_pos_ids.max()+1.
|
|
237
|
+
base = base + Math.max(t, gh, gw);
|
|
238
|
+
write += span;
|
|
239
|
+
i += span;
|
|
240
|
+
} else {
|
|
241
|
+
P[0][write] = base;
|
|
242
|
+
P[1][write] = base;
|
|
243
|
+
P[2][write] = base;
|
|
244
|
+
base++;
|
|
245
|
+
write++;
|
|
246
|
+
i++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (write !== L)
|
|
250
|
+
throw new Error(`qwenRopeIndex covered ${write} of ${L} tokens (grids misaligned?)`);
|
|
251
|
+
return { positions: P, delta: base - L };
|
|
252
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Qwen3.5 checkpoint-generation normalization — the load-seam port of
|
|
2
|
+
// mlx_lm.models.qwen3_5's `Model.sanitize` + `TextModel.sanitize`.
|
|
3
|
+
//
|
|
4
|
+
// Two checkpoint generations ship the same graph under different conventions:
|
|
5
|
+
//
|
|
6
|
+
// pre-5.8 (mlx-lm-converted) 5.8-family (transformers 5.8.0 export)
|
|
7
|
+
// ────────────────────────── ───────────────────────────────────────
|
|
8
|
+
// language_model.model.* model.language_model.*
|
|
9
|
+
// language_model.lm_head.* lm_head.* (top level)
|
|
10
|
+
// vision_tower.* model.visual.*
|
|
11
|
+
// (no mtp tensors in-repo) mtp.* (in-repo)
|
|
12
|
+
// conv1d.weight [C, K, 1] conv1d.weight [C, 1, K] (HF layout)
|
|
13
|
+
// RMSNorm gains stored as γ RMSNorm gains stored as γ−1
|
|
14
|
+
//
|
|
15
|
+
// Our graph speaks the FIRST column (`PREFIX = "language_model"` in
|
|
16
|
+
// qwen3_5.ts) — which is exactly mlx-lm's post-sanitize name space — so this
|
|
17
|
+
// module maps the artifact onto it instead of teaching every consumer two
|
|
18
|
+
// namings. The rules below are a line-for-line copy of the oracle; see
|
|
19
|
+
// mlx_lm/models/qwen3_5.py `Model.sanitize` (naming/drop) and
|
|
20
|
+
// `TextModel.sanitize` (γ shift, conv layout).
|
|
21
|
+
//
|
|
22
|
+
// The γ shift is the dangerous one: a spurious +1.0 silently corrupts an old
|
|
23
|
+
// artifact. The oracle's discriminator is NOT the naming — it is
|
|
24
|
+
// should_shift = any("mtp." in k) or any conv1d.weight with shape[-1] != 1
|
|
25
|
+
// evaluated over the whole (post-rename, pre-drop) weight map. Reproduced
|
|
26
|
+
// verbatim. Measured on the two artifacts in play (2026-09-01, M1 Max):
|
|
27
|
+
// • ~/.cache/…/models--mjriii--Qwen3.8-27B/snapshots/staged — no mtp.*,
|
|
28
|
+
// conv1d [10240,4,1] → no shift; layer-0 input_layernorm ≡ 1.0.
|
|
29
|
+
// • /Volumes/MLX-Models/models/mjriii/Qwen3.8-27B-{tqalloc-norot,rtn4-g64}
|
|
30
|
+
// — 31 mtp.* tensors, conv1d [10240,1,4] → shift; layer-0
|
|
31
|
+
// input_layernorm mean −0.0334 (= γ−1), byte-identical to the raw
|
|
32
|
+
// Qwen/Qwen3.8-27B 5.8 checkpoint (the quantizer copies norms verbatim).
|
|
33
|
+
|
|
34
|
+
import type { MlxArray } from "../mlx/array";
|
|
35
|
+
import * as ops from "../mlx/ops";
|
|
36
|
+
import type { Weights, WeightsView } from "../weights";
|
|
37
|
+
|
|
38
|
+
/** Header-level facts about one stored tensor (no bytes are read). */
|
|
39
|
+
export interface CheckpointTensor {
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly shape: readonly number[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Qwen35Sanitized {
|
|
45
|
+
/** canonical (graph) name → the name the artifact actually stores. */
|
|
46
|
+
readonly names: Map<string, string>;
|
|
47
|
+
/** Canonical names stored as γ−1: a +1.0 is due at load. */
|
|
48
|
+
readonly normShift: Set<string>;
|
|
49
|
+
/** Canonical names in HF conv layout: a moveaxis(2, 1) is due at load. */
|
|
50
|
+
readonly convMoveaxis: Set<string>;
|
|
51
|
+
/** True when the artifact already IS our canonical layout — no view needed
|
|
52
|
+
* and the pre-existing load path runs untouched. */
|
|
53
|
+
readonly identity: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** mlx-lm `TextModel.sanitize` norm_keys, verbatim and in order. */
|
|
57
|
+
const NORM_KEYS = [
|
|
58
|
+
".input_layernorm.weight",
|
|
59
|
+
".post_attention_layernorm.weight",
|
|
60
|
+
"model.norm.weight",
|
|
61
|
+
".q_norm.weight",
|
|
62
|
+
".k_norm.weight",
|
|
63
|
+
] as const;
|
|
64
|
+
|
|
65
|
+
/** mlx-lm `Model.sanitize`: drop vision, fold every naming onto
|
|
66
|
+
* `language_model.…`. Returns null for a dropped tensor. */
|
|
67
|
+
function canonicalName(key: string): string | null {
|
|
68
|
+
if (key.startsWith("vision_tower") || key.startsWith("model.visual")) return null;
|
|
69
|
+
if (key.startsWith("model.language_model"))
|
|
70
|
+
return "language_model.model" + key.slice("model.language_model".length);
|
|
71
|
+
if (key.startsWith("language_model.")) return key;
|
|
72
|
+
return "language_model." + key;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Port of mlx_lm.models.qwen3_5 `Model.sanitize` ∘ `TextModel.sanitize`,
|
|
77
|
+
* name/shape half. Pure: takes header facts, returns the load plan.
|
|
78
|
+
*/
|
|
79
|
+
export function sanitizeQwen35Checkpoint(
|
|
80
|
+
tensors: Iterable<CheckpointTensor>,
|
|
81
|
+
): Qwen35Sanitized {
|
|
82
|
+
// Pass 1 — rename (vision dropped), exactly as Model.sanitize.
|
|
83
|
+
const renamed: { canonical: string; source: string; shape: readonly number[] }[] = [];
|
|
84
|
+
let sawForeignName = false;
|
|
85
|
+
for (const t of tensors) {
|
|
86
|
+
const canonical = canonicalName(t.name);
|
|
87
|
+
if (canonical === null) {
|
|
88
|
+
sawForeignName ||= t.name.startsWith("model.visual");
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (canonical !== t.name) sawForeignName = true;
|
|
92
|
+
renamed.push({ canonical, source: t.name, shape: t.shape });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Pass 2 — TextModel.sanitize's two flags, over the renamed map BEFORE the
|
|
96
|
+
// mtp drop (the oracle computes them first, then filters).
|
|
97
|
+
const hasMtpWeights = renamed.some((t) => t.canonical.includes("mtp."));
|
|
98
|
+
const hasUnsanitizedConv1d = renamed.some(
|
|
99
|
+
(t) => t.canonical.includes("conv1d.weight") && t.shape[t.shape.length - 1] !== 1,
|
|
100
|
+
);
|
|
101
|
+
const shouldShiftNormWeights = hasMtpWeights || hasUnsanitizedConv1d;
|
|
102
|
+
|
|
103
|
+
const names = new Map<string, string>();
|
|
104
|
+
const normShift = new Set<string>();
|
|
105
|
+
const convMoveaxis = new Set<string>();
|
|
106
|
+
for (const t of renamed) {
|
|
107
|
+
if (t.canonical.includes("mtp.")) continue; // oracle drops these outright
|
|
108
|
+
names.set(t.canonical, t.source);
|
|
109
|
+
if (t.canonical.includes("conv1d.weight") && t.shape[t.shape.length - 1] !== 1)
|
|
110
|
+
convMoveaxis.add(t.canonical);
|
|
111
|
+
if (
|
|
112
|
+
shouldShiftNormWeights &&
|
|
113
|
+
NORM_KEYS.some((sfx) => t.canonical.endsWith(sfx)) &&
|
|
114
|
+
t.shape.length === 1
|
|
115
|
+
)
|
|
116
|
+
normShift.add(t.canonical);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
names,
|
|
121
|
+
normShift,
|
|
122
|
+
convMoveaxis,
|
|
123
|
+
identity: !sawForeignName && !hasMtpWeights && !shouldShiftNormWeights &&
|
|
124
|
+
convMoveaxis.size === 0,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The {@link WeightsView} for a qwen3.5 artifact, or null when the artifact is
|
|
130
|
+
* already canonical (then nothing is installed and the load path is bit-for-bit
|
|
131
|
+
* what it was before this seam existed).
|
|
132
|
+
*/
|
|
133
|
+
export function qwen35WeightsView(weights: Weights): WeightsView | null {
|
|
134
|
+
const plan = sanitizeQwen35Checkpoint(
|
|
135
|
+
weights.tensorNames.map((name) => ({ name, shape: weights.info(name).shape })),
|
|
136
|
+
);
|
|
137
|
+
if (plan.identity) return null;
|
|
138
|
+
return {
|
|
139
|
+
names: plan.names,
|
|
140
|
+
fixup(canonical: string, arr: MlxArray): MlxArray | null {
|
|
141
|
+
// Oracle order: moveaxis first, then the γ shift (disjoint sets — a
|
|
142
|
+
// conv1d weight is 3-D and never a norm gain).
|
|
143
|
+
if (plan.convMoveaxis.has(canonical)) {
|
|
144
|
+
// `v.moveaxis(2, 1)` on [C, 1, K] → [C, K, 1]. Materialized: the
|
|
145
|
+
// conv1d kernel consumes it every forward, and the transposed view
|
|
146
|
+
// would otherwise pin the source shard buffer.
|
|
147
|
+
const moved = ops.transposeAxes(arr, [0, 2, 1]);
|
|
148
|
+
const out = ops.contiguous(moved);
|
|
149
|
+
moved.dispose();
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
if (plan.normShift.has(canonical)) {
|
|
153
|
+
// `v + 1.0` — a weak python scalar, so the add happens at the gain's
|
|
154
|
+
// own dtype (bf16 here); scalarLike builds the constant host-side at
|
|
155
|
+
// that dtype for the same single-kernel add the reference dispatches.
|
|
156
|
+
const one = ops.scalarLike(1, arr);
|
|
157
|
+
const out = ops.add(arr, one);
|
|
158
|
+
one.dispose();
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|