mlx-bun 0.2.0 → 0.4.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 -588
- package/docs/README.md +94 -0
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/archive/investigations/openjarvis-fit.md +198 -0
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
- package/docs/design/batching.md +1841 -0
- package/docs/design/decode-speed-program.md +2346 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +655 -334
- package/docs/design/kv-cache.md +824 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1990 -0
- package/docs/design/turboquant.md +2212 -0
- package/docs/design/unified-engine-frontier-plan.md +1833 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +50 -1
- package/docs/planning/release-notes-v0.4.0.md +45 -0
- package/docs/planning/video-series.md +2 -2
- package/docs/reference/benchmarks.md +3613 -0
- package/docs/reference/cli.md +434 -160
- package/docs/reference/distribution.md +328 -182
- package/docs/reference/environment.md +398 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +566 -168
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +113 -6
- package/docs/reference/server-api.md +944 -429
- package/docs/reference/server-config.md +740 -338
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +158 -0
- package/package.json +9 -4
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/assistant-target.ts +46 -0
- package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1790 -0
- package/src/backends/mlx/cache-attachment.ts +67 -0
- package/src/backends/mlx/cache-layout.ts +31 -0
- package/src/backends/mlx/checkpoint-state.ts +53 -0
- package/src/backends/mlx/continuation-persistence.ts +106 -0
- package/src/backends/mlx/continuation-request.ts +43 -0
- package/src/backends/mlx/continuation.ts +77 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +32 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/full-kv-row-append.ts +32 -0
- package/src/backends/mlx/full-kv-row-donor.ts +54 -0
- package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
- package/src/backends/mlx/gateway-binding.ts +130 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/kv-codec.ts +9 -0
- package/src/backends/mlx/kv-maintenance.ts +133 -0
- package/src/backends/mlx/kv-tensor-rows.ts +212 -0
- package/src/backends/mlx/memory-client.ts +189 -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-cohort.ts +89 -0
- package/src/backends/mlx/prefill-rows.ts +200 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/projected-context-rows.ts +72 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/request-state-policy.ts +41 -0
- package/src/backends/mlx/rollback.ts +89 -0
- package/src/backends/mlx/row-sampling.ts +49 -0
- package/src/backends/mlx/serial-executor.ts +242 -0
- package/src/backends/mlx/speculative-group.ts +359 -0
- package/src/backends/mlx/speculative-round.ts +161 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-rows.ts +104 -0
- package/src/backends/mlx/state-views.ts +46 -0
- package/src/backends/mlx/target-layout-capability.ts +35 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
- package/src/cli.ts +66 -58
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +60 -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/prefix-cache.ts +23 -0
- package/src/contracts/resources.ts +25 -0
- package/src/contracts/sampling.ts +23 -0
- package/src/contracts/scheduling.ts +45 -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 +53 -0
- package/src/engine/resources.ts +53 -0
- package/src/engine/scheduler.ts +72 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +236 -3
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +8 -96
- 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 +30 -16
- package/src/generate.ts +709 -417
- package/src/grammar.ts +12 -7
- package/src/harness-pi.ts +14 -33
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +7 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/draft-acceptance.ts +41 -0
- package/src/inference/draft-output.ts +49 -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 +12 -12
- 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 +70 -12
- package/src/kv-store.ts +177 -63
- 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} +5 -5
- package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
- package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +1 -1
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +30 -169
- 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 +1 -3
- package/src/mlx/array.ts +11 -11
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +58 -11
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +33 -13
- 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/artifact-identity.ts +73 -0
- package/src/model/batched-kv.ts +235 -0
- package/src/model/batched-mask.ts +20 -6
- package/src/model/batched-quant.ts +9 -3
- package/src/model/batched-quantized-kv.ts +144 -0
- package/src/model/batched-rotating-quant.ts +78 -17
- package/src/model/batched-rotating-state.ts +76 -0
- package/src/model/batched-rotating.ts +65 -23
- package/src/model/batched-row-storage.ts +52 -0
- package/src/model/batched-ssm.ts +52 -0
- package/src/model/batched-turboquant-kv.ts +93 -0
- package/src/model/compiled-decode.ts +8 -2
- package/src/model/decoded-kv-donor.ts +12 -0
- package/src/model/delayed-quantized-kv.ts +72 -0
- package/src/model/delayed-rotating-quantized-kv.ts +93 -0
- package/src/model/delayed-turboquant-kv.ts +55 -0
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +76 -33
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/full-prefill-padding.ts +56 -0
- package/src/model/full-prefill-row.ts +105 -0
- package/src/model/gemma4-base.ts +179 -80
- package/src/model/gemma4.ts +40 -32
- package/src/model/generated/gemma4-12b.ts +6 -3
- package/src/model/generated/gemma4-26b.ts +6 -3
- package/src/model/generated/gemma4-e4b.ts +6 -3
- package/src/model/glm52-cache.ts +80 -4
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +1 -1
- package/src/model/glm52-mla.ts +12 -6
- package/src/model/glm52.ts +19 -40
- package/src/model/implementation.ts +69 -0
- package/src/model/kv-attention-view.ts +67 -0
- package/src/model/minicpm5.ts +17 -15
- package/src/model/profile.ts +12 -2
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta-state.ts +74 -0
- package/src/model/qwen3-delta.ts +59 -36
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +202 -78
- package/src/model/rotating-kv-donor.ts +35 -0
- package/src/model/rotating-kv-layout.ts +262 -0
- package/src/model/rotating-row-transaction.ts +35 -0
- package/src/model/speculative-rotating-kv.ts +101 -0
- package/src/model/ssm-prefill-padding.ts +39 -0
- 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/turboquant-codec.ts +83 -0
- package/src/model/universal/dense.ts +15 -14
- package/src/model/universal/modules.ts +8 -1
- package/src/native-pack.ts +6 -5
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +8 -315
- package/src/preflight.ts +31 -15
- package/src/prompt-cache.ts +110 -69
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/config-writer.ts +10 -3
- package/src/quantize/rotate.ts +4 -4
- package/src/quantize/trellis.ts +586 -0
- package/src/responses.ts +28 -1
- package/src/runtime-config.ts +18 -4
- package/src/sampler.ts +40 -29
- package/src/serve/batch-scheduler.ts +8 -1671
- 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 +15 -7
- package/src/serve/discovery-routes.ts +12 -13
- package/src/serve/generation-gateway.ts +183 -213
- 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/lab-routes.ts +3 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +7 -5
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +511 -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/request-plan.ts +23 -18
- package/src/serve/request-prep.ts +344 -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 +5 -5
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +335 -2711
- package/src/spec/assistant-rows.ts +92 -0
- package/src/spec/assistant-source.ts +31 -55
- package/src/spec/cache-identity.ts +22 -0
- package/src/spec/deepspec-rows.ts +29 -0
- package/src/spec/deepspec-source.ts +16 -14
- package/src/spec/dflash-source.ts +36 -12
- package/src/spec/drafter.ts +153 -142
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +97 -122
- 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 +129 -172
- 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-graph.ts +29 -0
- package/src/spec/glm52-mtp-rows.ts +132 -0
- package/src/spec/glm52-mtp-source.ts +54 -137
- package/src/spec/glm52-mtp-state.ts +33 -0
- package/src/spec/ngram-source.ts +93 -21
- package/src/spec/projected-draft-rows.ts +73 -0
- package/src/spec/qwen-mtp-module.ts +171 -0
- package/src/spec/qwen-mtp-rows.ts +219 -0
- package/src/spec/qwen-mtp-source.ts +147 -195
- package/src/spec/qwen-mtp-state.ts +30 -0
- package/src/spec/serve-loop.ts +201 -201
- package/src/spec/source.ts +110 -13
- package/src/spec/two-model-rows.ts +61 -0
- package/src/spec/two-model.ts +44 -102
- package/src/ssd-cache.ts +99 -19
- package/src/ssd-durability.ts +36 -20
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +2 -2
- package/src/train/forward.ts +6 -0
- package/src/train/loss.ts +1 -1
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +5 -3
- package/src/train/trainer.ts +6 -6
- package/src/vision/prompt.ts +1 -1
- package/src/vision/qwen3vl-tower.ts +52 -10
- package/src/web/app.html +1 -1
- package/src/web/app.js +62 -60
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +4 -4
- 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 +55 -9
- package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/archive/investigations/hlg-ab.html +0 -34
- package/docs/archive/investigations/hlg-explorer.html +0 -238
- package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
- package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/archive/investigations/hlg-report.html +0 -262
- package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- 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 -318
- 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-serving-execution-seam.md +0 -81
- 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 -231
- 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 -415
- 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/turboquant-weights.md +0 -467
- 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/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -101
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -11
- /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
- /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
- /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
- /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
- /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
- /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
|
@@ -1,384 +1,705 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
status: active
|
|
3
|
+
axis: ON
|
|
4
|
+
canonical-for: model-support
|
|
5
|
+
plan-anchor: "Serving architecture consolidation `[~]` (opened 2026-08-21)"
|
|
6
|
+
last-verified: 2026-08-23
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Model support — run anything mlx-lm runs, and the ports we target
|
|
2
10
|
|
|
3
|
-
**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`MLX_BUN_TEST_UNIVERSAL=1`). Phases 2 (UniversalMoE), 3 (SSM/MLA one-offs),
|
|
9
|
-
4 (`mlx-bun port` scaffold) remain design.
|
|
11
|
+
**This is the one design doc for model support.** New model ports become
|
|
12
|
+
SECTIONS under §6 (Ports) of this file, not new files in `docs/design/`.
|
|
13
|
+
Per-port phase logs, gate results, and dates belong in PLAN.md (anchors are
|
|
14
|
+
named per section); this doc keeps the design and the oracle each port is
|
|
15
|
+
held to.
|
|
10
16
|
|
|
11
17
|
Direction (Josh): *"we should be able to run any model that mlx-lm can run.
|
|
12
18
|
Run any model generically; for the specific models we target, optimize them
|
|
13
19
|
further — push the quality/performance border outwards. Like the gemma
|
|
14
20
|
generator methodology."*
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
`src/model/gemma4-base.ts` (shared machinery) + `gemma4.ts` (config-driven
|
|
18
|
-
monolith) + `src/model/generated/*.ts` (codegen'd specializations via
|
|
19
|
-
`scripts/gen-model.ts`, gated bit-exact by `tests/generated-parity.test.ts`).
|
|
20
|
-
This doc generalizes that shape to the whole mlx-lm zoo:
|
|
22
|
+
Two tiers, one contract:
|
|
21
23
|
|
|
22
24
|
- **Tier-0 GENERIC** — one config-driven "universal" module per architecture
|
|
23
|
-
*family
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
*family*. Runs any covered checkpoint at **L1 parity** (bit-exact vs mlx-lm
|
|
26
|
+
on this machine's GPU). Monolith path only, without compiled decode.
|
|
27
|
+
Standard attention now uses the shared plain/affine KV port; the softcap
|
|
28
|
+
branch retains plain KV. Qualified full-attention targets compose delayed
|
|
29
|
+
affine conversion with standalone and lookup drafting through the same
|
|
30
|
+
cache transaction interface; rotating layouts use that interface for
|
|
31
|
+
per-layer conversion and assistant donors. Built: `src/model/universal/` (dense
|
|
32
|
+
llama-family). Design only: UniversalMoE.
|
|
33
|
+
- **Tier-1 TARGETED** — a model *graduates*: dedicated or generated forward,
|
|
34
|
+
L2 (mlx-optiq) composition where an optiq artifact exists, Lab experiments
|
|
35
|
+
where warranted, benchmark entries. The ports in §6.
|
|
36
|
+
|
|
37
|
+
**L1 = mlx-lm bit-exact is the gate for ANY new model**, generic or targeted.
|
|
38
|
+
Where no mlx-lm arm exists (audio, vision towers, DiffusionGemma, GLM-5.2's
|
|
39
|
+
Colibri container) the oracle is whoever ships the capability — optiq's
|
|
40
|
+
internal machinery, mlx-vlm, or the pinned Colibri engine — and the profile
|
|
41
|
+
declares that fidelity honestly (§3). A model the generic tier cannot hold to
|
|
42
|
+
L1 parity is not "supported with caveats"; it is unsupported until fixed.
|
|
34
43
|
|
|
35
44
|
---
|
|
36
45
|
|
|
37
|
-
## 1. The mlx-lm
|
|
46
|
+
## 1. The mlx-lm zoo, inventoried (mlx-lm 0.31.3, the oracle venv)
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
`site-packages/mlx_lm/models/*.py`. **108 model files** after excluding
|
|
48
|
+
108 model files in `site-packages/mlx_lm/models/` after excluding
|
|
41
49
|
infrastructure (`base`, `cache`, `rope_utils`, `activations`,
|
|
42
50
|
`switch_layers`, `ssm`, `gated_delta`, `mla`, `bitlinear_layers`,
|
|
43
|
-
`pipeline`). `utils.py MODEL_REMAPPING` adds free aliases
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(`smollm3` is literally a 75-line subclass of `llama` that swaps some
|
|
61
|
-
layers' rope for a no-op; `solar_open` is 38 lines. mlx-lm itself treats
|
|
62
|
-
this family as one module with per-file ModelArgs.)
|
|
63
|
-
|
|
64
|
-
**B. MoE llama-family (SwitchGLU experts) — ~17 files, a second module.**
|
|
65
|
-
Same block, MLP replaced by router + `SwitchGLU` (+ optional shared expert):
|
|
66
|
-
|
|
67
|
-
> mixtral, qwen2_moe, qwen3_moe, olmoe, phimoe, dots1, granitemoe,
|
|
68
|
-
> ernie4_5_moe, glm4_moe, hunyuan, Klear, bailing_moe, exaone_moe, deepseek
|
|
69
|
-
> (v1: MoE without MLA), step3p5, mimo_v2_flash, afmoe
|
|
70
|
-
> (llama4_text / gpt_oss are near-family but carry extra deltas —
|
|
71
|
-
> chunked-attention/NoPE, attention sinks.)
|
|
72
|
-
|
|
73
|
-
**C. MLA lineage (DeepSeek latent attention, usually + MoE + yarn) — ~11:**
|
|
74
|
-
> deepseek_v2, deepseek_v3 (+kimi_k2 remap), deepseek_v32, glm4_moe_lite,
|
|
75
|
-
> glm_moe_dsa, kimi_k25, kimi_vl, longcat_flash(+ngram), minicpm3, youtu_llm
|
|
76
|
-
|
|
77
|
-
**D. SSM / hybrid / linear-attention — ~17, individually shaped:**
|
|
78
|
-
> mamba, mamba2 (+falcon_mamba remap), falcon_h1, jamba, granitemoehybrid,
|
|
79
|
-
> nemotron_h, plamo2, lfm2, lfm2_moe, qwen3_next, kimi_linear, minimax,
|
|
80
|
-
> recurrent_gemma, rwkv7, baichuan_m1, **qwen3_5 (already ported)**,
|
|
81
|
-
> qwen3_5_moe
|
|
82
|
-
|
|
83
|
-
**E. Legacy / exotic one-offs — ~13, deprioritized:**
|
|
84
|
-
> gpt2, gpt_bigcode, gpt_neox, qwen (v1), openelm (per-layer varying dims),
|
|
85
|
-
> phi3small (blocksparse attn), phixtral, dbrx, nemotron-nas (variable
|
|
86
|
-
> blocks), bitnet (bitlinear), afm7, baichuan_m1 (also in D), lille-130m-ish
|
|
87
|
-
> oddities
|
|
88
|
-
|
|
89
|
-
**F. Vision/text wrappers — ~10, ~free once the text base exists:**
|
|
90
|
-
> gemma3, gemma4 (ours already), qwen2_vl (+qwen2_5_vl), qwen3_vl,
|
|
91
|
-
> qwen3_vl_moe, kimi_vl, lfm2-vl, mistral3 (+llava remap), pixtral, llama4
|
|
92
|
-
> — mlx-lm runs only their *text* stack; each wrapper is ~50–120 lines of
|
|
93
|
-
> config unwrapping + weight-prefix stripping.
|
|
94
|
-
|
|
95
|
-
### Coverage math
|
|
96
|
-
|
|
97
|
-
| Bucket | Files | Unlocked by |
|
|
98
|
-
|---|---|---|
|
|
99
|
-
| A. dense llama-family | ~36 (33%) | **one** UniversalDense module (Phase 1) |
|
|
100
|
-
| B. MoE llama-family | ~17 (16%) | **one** UniversalMoE module (Phase 2) |
|
|
101
|
-
| F. vision wrappers | ~10 (9%) | thin config/prefix shims over A/B (Phase 1–2) |
|
|
102
|
-
| C. MLA lineage | ~11 (10%) | one MLA attention module (Phase 3, demand-driven — most are >24 GB even at 4-bit) |
|
|
103
|
-
| D. SSM/hybrid | ~17 (16%) | individual ports, qwen3_5 pattern (Phase 3) |
|
|
104
|
-
| E. legacy/exotic | ~13 (12%) | individual ports, likely never |
|
|
105
|
-
| already in mlx-bun | 5 | gemma4(+text), qwen3, qwen3_5, minicpm5(llama-typed), diffusion_gemma |
|
|
106
|
-
|
|
107
|
-
**Two generic modules + the wrapper shims ≈ 60% of the zoo by file count,
|
|
108
|
-
and >90% of what actually gets downloaded** (Llama 3.x, Mistral/Ministral,
|
|
109
|
-
Qwen 2.5/3 dense+MoE, Gemma 1–3, Phi-3/4, SmolLM3, OLMo-2/3, GLM-4,
|
|
110
|
-
Granite, Mixtral, OLMoE are all in A/B/F).
|
|
51
|
+
`pipeline`). `utils.py MODEL_REMAPPING` adds free aliases (`mistral→llama`,
|
|
52
|
+
`kimi_k2→deepseek_v3`, `qwen2_5_vl→qwen2_vl`, `falcon_mamba→mamba`, …).
|
|
53
|
+
|
|
54
|
+
| Bucket | ~Files | Shape | Unlocked by |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| A. dense llama-family | ~36 | embed → N × (norm → GQA attn(+rope) → residual → norm → MLP → residual) → norm → head; every file a permutation of a dozen knobs | **UniversalDense** (built) |
|
|
57
|
+
| B. MoE llama-family | ~17 | same block, MLP → router + SwitchGLU (+ shared expert) | **UniversalMoE** (design) |
|
|
58
|
+
| F. vision/text wrappers | ~10 | mlx-lm runs only the text stack; ~50–120 lines of config unwrapping + prefix stripping | thin shims over A/B |
|
|
59
|
+
| C. MLA lineage | ~11 | DeepSeek latent attention, usually + MoE + yarn | one MLA module, demand-driven (most exceed local RAM at 4-bit) |
|
|
60
|
+
| D. SSM / hybrid / linear-attention | ~17 | individually shaped (mamba, jamba, lfm2, qwen3_next, rwkv7, qwen3_5 …) | individual ports, the qwen3_5 pattern |
|
|
61
|
+
| E. legacy / exotic | ~13 | gpt2, openelm, phi3small, dbrx, bitnet … | individual ports, likely never |
|
|
62
|
+
|
|
63
|
+
Two generic modules + the wrapper shims cover roughly 60% of the zoo by
|
|
64
|
+
file count and the large majority of what actually gets downloaded (Llama
|
|
65
|
+
3.x, Mistral/Ministral, Qwen 2.5/3 dense+MoE, Gemma 1–3, Phi-3/4, SmolLM3,
|
|
66
|
+
OLMo-2/3, GLM-4, Granite, Mixtral, OLMoE are all in A/B/F).
|
|
111
67
|
|
|
112
68
|
---
|
|
113
69
|
|
|
114
|
-
## 2.
|
|
115
|
-
|
|
116
|
-
Audited 2026-07-01; file references are load-bearing.
|
|
70
|
+
## 2. Building blocks (what every tier is made of)
|
|
117
71
|
|
|
118
|
-
- **Config parsing** — `src/config.ts loadModelConfig
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
map (`quantFor`), kv_config. **This is 70% of the normalization layer;**
|
|
124
|
-
it needs the delta fields from §3.1 and a table-driven (not if-chain)
|
|
125
|
-
quirk mechanism before it drowns.
|
|
72
|
+
- **Config parsing** — `src/config.ts loadModelConfig` produces a normalized
|
|
73
|
+
`TextConfig` (layerTypes/slidingWindow, headDim fallback, tie, softcap,
|
|
74
|
+
partialRotaryFactor, `ropeParameters`, per-layer quant map via `quantFor`,
|
|
75
|
+
kv_config, sidecar detection). Per-arch quirks for the generic tier live in
|
|
76
|
+
the descriptor table (§4.1), not in this if-chain.
|
|
126
77
|
- **Primitives** — `src/model/gemma4-base.ts`: `QuantizedLinear` (+LoRA
|
|
127
78
|
residual), `QuantizedEmbedding` (+tied `asLinear`), `RMSNorm`,
|
|
128
|
-
`QuantizedSwitchLinear` (MoE experts
|
|
129
|
-
|
|
130
|
-
`
|
|
131
|
-
|
|
132
|
-
`
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
139
|
-
`
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`
|
|
149
|
-
|
|
150
|
-
the
|
|
151
|
-
- **Tokenizer** — `src/tokenizer.ts`: `@huggingface/tokenizers` (pure JS)
|
|
152
|
-
reads stock `tokenizer.json` + `tokenizer_config.json`; already
|
|
153
|
-
generic across BPE/SentencePiece-as-tokenizer.json. Known landmine class:
|
|
154
|
-
BOS conventions (the double-BOS bug cost a debug session — see memory);
|
|
155
|
-
chat-template rendering rides Pi, with `/v1` as the boundary.
|
|
156
|
-
|
|
157
|
-
### Gaps the generic tier must close (found in this audit)
|
|
158
|
-
|
|
159
|
-
1. **No unquantized Linear.** `QuantizedLinear.load` throws without a
|
|
160
|
-
`.scales` tensor (`gemma4-base.ts:94`). Tier-0 v1 can inherit this
|
|
161
|
-
constraint (target mlx-community 4/8-bit checkpoints — what users pull
|
|
162
|
-
anyway), but a plain `DenseLinear` (bf16/fp16 `ops.matmul`) is a required
|
|
163
|
-
fast-follow: many small models ship only fp16.
|
|
164
|
-
2. **No additive linear bias.** `QuantizedLinear`'s `biases` are quant
|
|
165
|
-
zero-points, not a bias *term*. qwen2 (attention qkv bias), stablelm,
|
|
166
|
-
starcoder2, phi et al. need an optional post-matmul `+ bias` in the
|
|
167
|
-
linear primitive.
|
|
168
|
-
3. **Rope variants.** Only default/proportional exist in the runtime.
|
|
169
|
-
mlx-lm `rope_utils.py` also ships: `linear`, `llama3` (Llama3RoPE),
|
|
170
|
-
`yarn` (3 spellings), `longrope`/`su` (SuScaledRoPE), `mrope`. llama3 +
|
|
171
|
-
yarn + longrope are hard requirements for bucket A (Llama 3.x, Phi-3,
|
|
172
|
-
DeepSeek-lineage, various long-context finetunes).
|
|
173
|
-
4. **Attention-score softcap** (gemma2): needs the manual
|
|
174
|
-
(q·kᵀ → tanh-cap → softmax) path — `ops.sdpa` can't express it.
|
|
175
|
-
5. **factory.ts rejects unknown types** rather than attempting a generic
|
|
176
|
-
fallback (by design today; changes in §3.3).
|
|
79
|
+
`QuantizedSwitchLinear` (MoE experts), `KVCache`/`RotatingKVCache` (+
|
|
80
|
+
quantized and TurboQuant variants), mask machinery, `logitSoftcap`,
|
|
81
|
+
`disposing`. `src/model/universal/modules.ts` adds the dense
|
|
82
|
+
(unquantized) `nn.Linear`/`nn.Embedding` ports and the load-time
|
|
83
|
+
`WeightAudit`.
|
|
84
|
+
- **Generator** — `scripts/gen-model.ts` emits unrolled, branch-resolved
|
|
85
|
+
`forwardLayers` overrides of `Gemma4Model` into `src/model/generated/`
|
|
86
|
+
(e4b, 12B, 26B), dispatched by config fingerprint, gated bit-exact vs the
|
|
87
|
+
monolith by `tests/generated-parity.test.ts`.
|
|
88
|
+
- **Parity harness** — `scripts/regen.ts <job>` (jobs: `parity`,
|
|
89
|
+
`parity-26b`, `kvq`, `rotating-kvq`, `mixed-kv`, `lora`, `fused-sdpa`,
|
|
90
|
+
`universal`, `qwen-parity`, `minicpm5`, `minicpm5-kv`, `turboquant`,
|
|
91
|
+
`audio-fixtures`) drives the oracle venv
|
|
92
|
+
(`/Users/joshrossi/Code/mlx-lm/.venv/bin/python`) to emit
|
|
93
|
+
`<prefix>-parity.json` (explicit prompt ids + greedy ids) plus per-step raw
|
|
94
|
+
logit `.bin`s; `tests/*-parity.test.ts` replay the ids (no cross-stack
|
|
95
|
+
tokenizer dependency) and compare bit-exact on the same GPU. Manifests are
|
|
96
|
+
tracked; `.bin` blobs are machine-specific and untracked
|
|
97
|
+
(goldens/README.md).
|
|
98
|
+
- **Tokenizer** — `src/tokenizer.ts` (`@huggingface/tokenizers`, pure JS)
|
|
99
|
+
reads stock `tokenizer.json` + `tokenizer_config.json`. Known landmine:
|
|
100
|
+
BOS conventions (the double-BOS bug). Chat-template rendering rides Pi;
|
|
101
|
+
`/v1` is the boundary.
|
|
177
102
|
|
|
178
103
|
---
|
|
179
104
|
|
|
180
|
-
## 3.
|
|
181
|
-
|
|
182
|
-
### 3.1 Tier-0: `UniversalDense` (src/model/universal/)
|
|
105
|
+
## 3. Model profiles — capability declaration (`src/model/profile.ts`)
|
|
183
106
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
per-arch args) without one file per arch:
|
|
107
|
+
Model loading resolves ONE immutable profile before weights are opened.
|
|
108
|
+
A profile declares **construction only**: request-level methods (MTP, KV
|
|
109
|
+
schemes, adapters, grammar, sampling) are resolved elsewhere and cannot be
|
|
110
|
+
rewritten by profile selection.
|
|
189
111
|
|
|
190
112
|
```ts
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
embedScale?: "sqrt-hidden" | "mup" | null; // gemma family, minicpm
|
|
203
|
-
residualMultiplier?: ConfigPath; // granite
|
|
204
|
-
bias: { qkv?: boolean; o?: boolean; mlp?: boolean };
|
|
205
|
-
nope?: "interval" | "list"; // smollm3, llama4-style no-rope layers
|
|
206
|
-
// weights
|
|
207
|
-
weightMap?: Partial<Record<CanonicalName, string>>; // starcoder2 c_fc/c_proj, gpt2 h.N.*
|
|
208
|
-
sanitize?: (names: string[]) => Rename[]; // fused-proj splits, inv_freq drops
|
|
209
|
-
configAliases?: Record<string, string>; // norm_epsilon→rms_norm_eps etc.
|
|
113
|
+
interface ModelProfile {
|
|
114
|
+
id: string;
|
|
115
|
+
artifactFingerprint?: string; // exact external identity (hf:<repo>@<rev>); family profiles omit
|
|
116
|
+
configFingerprint?: string; // structural guard for an exact artifact declaration
|
|
117
|
+
fidelity: FidelityTarget; // {l1, mlx-lm, bit-exact} | {l2, mlx-optiq, bit-exact} | {l3, null, measured}
|
|
118
|
+
requiredCapabilities: EngineCapability[];
|
|
119
|
+
execution: { loader: "safetensors" | "colibri";
|
|
120
|
+
graph: "gemma4" | "minicpm5" | "qwen3.5" | "qwen3" | "qwen3-moe"
|
|
121
|
+
| "diffusion-gemma" | "glm5.2" | "universal-dense";
|
|
122
|
+
loop: "autoregressive" | "diffusion";
|
|
123
|
+
specialization: "artifact" | "dedicated" | "generated" | "generic" };
|
|
210
124
|
}
|
|
211
|
-
export const ARCHS: Record<string /* model_type */, ArchDescriptor> = { ... };
|
|
212
125
|
```
|
|
213
126
|
|
|
127
|
+
Engine capabilities (`ENGINE_CAPABILITIES`): `autoregressive`,
|
|
128
|
+
`colibri-container`, `diffusion`, `diffusion-gemma-graph`, `gemma4-graph`,
|
|
129
|
+
`generated-graph`, `glm5.2-graph`, `minicpm5-graph`, `mixed-precision-kv`,
|
|
130
|
+
`native-mtp`, `qwen3-graph`, `qwen3-moe-graph`, `qwen3.5-graph`,
|
|
131
|
+
`recurrent-state`, `safetensors`, `streamed-experts`,
|
|
132
|
+
`universal-dense-graph`, `vision-sidecar`.
|
|
133
|
+
|
|
134
|
+
Resolution (`resolveModelProfile`):
|
|
135
|
+
|
|
136
|
+
1. **Exact artifact profiles outrank family profiles.** The external
|
|
137
|
+
fingerprint is derived only from an immutable HF snapshot path
|
|
138
|
+
(`models--<org>--<repo>/snapshots/<40–64 hex>`); relocation keeps the
|
|
139
|
+
identity, mutable aliases and arbitrary local dirs return null. A matched
|
|
140
|
+
exact profile whose config fingerprint or graph acceptance mismatches
|
|
141
|
+
REFUSES — it never falls back. Built-in exact declarations today:
|
|
142
|
+
`qwen3.8-27b-optiq-4bit` (L1) and `glm5.2-colibri-int4-int8-mtp` (L3).
|
|
143
|
+
2. **Family profile** by config predicate (`src/model/support.ts`), in this
|
|
144
|
+
order: `glm_moe_dsa` → `diffusion_gemma` → MiniCPM5 (exact-shape `llama`
|
|
145
|
+
predicate) → `qwen3_5`/`qwen3_5_text` (dense hybrid only; the MoE variant
|
|
146
|
+
is excluded) → `qwen3_moe` → `qwen3` → `gemma4*` (generated class if
|
|
147
|
+
`GENERATED.has(fingerprint)`, else monolith) → universal-dense if
|
|
148
|
+
`genericArgsFor(config)` resolves → throw naming the targeted list and
|
|
149
|
+
the generic descriptor keys.
|
|
150
|
+
3. `validateProfile` enforces the fidelity/oracle pairing, loader↔graph
|
|
151
|
+
(`glm5.2` ⇒ colibri), loop↔graph (`diffusion-gemma` ⇒ diffusion), and that
|
|
152
|
+
every capability the execution composition implies is declared. Missing
|
|
153
|
+
engine capabilities refuse; nothing downgrades.
|
|
154
|
+
|
|
155
|
+
**Factory** (`src/model/factory.ts`): `openModel(dir)` resolves the profile,
|
|
156
|
+
routes `loader: "colibri"` through `openGlm52RuntimeModel` (header-only
|
|
157
|
+
memory plan first, then `Glm52Model.openStreamed`; the Colibri snapshot has no
|
|
158
|
+
`model.safetensors.index.json` so it bypasses `Weights.open`), and otherwise
|
|
159
|
+
`createModel(weights, config, profile)` switches on `execution.graph`.
|
|
160
|
+
`RuntimeModel` = `Gemma4Model | MiniCPM5Model | Qwen35Model | Qwen3Model |
|
|
161
|
+
Qwen3MoeModel | DiffusionGemmaModel | Glm52Model | UniversalDenseModel`.
|
|
162
|
+
|
|
163
|
+
**Support tiers in UX** (`supportTier(modelType, repoId)` →
|
|
164
|
+
`"targeted" | "generic" | null`): consumed by `mlx-bun ls`
|
|
165
|
+
(src/cli.ts), `src/hub-rest.ts`, and the serve discovery routes. Drafters
|
|
166
|
+
(`*_assistant`) are never selectable on their own. Note the MiniCPM5
|
|
167
|
+
*record*-level check keys on the repo id containing
|
|
168
|
+
`minicpm5-1b-optiq-4bit`; the config-level check is the exact-shape predicate.
|
|
169
|
+
|
|
170
|
+
Reference mirror of this section: docs/reference/models.md "Declared model
|
|
171
|
+
profiles" (keep in sync).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 4. Tier-0 design
|
|
176
|
+
|
|
177
|
+
### 4.1 `UniversalDense` (`src/model/universal/`)
|
|
178
|
+
|
|
179
|
+
One module (`dense.ts`), shaped like `qwen3.ts`, with every arch delta
|
|
180
|
+
selected by a `UniversalArgs` descriptor. `archs.ts` holds an explicit
|
|
181
|
+
table keyed by `model_type` (mlx-lm's `MODEL_REMAPPING` vendored in) — no
|
|
182
|
+
config sniffing to *identify* an arch; fingerprints remain a generated-
|
|
183
|
+
dispatch guard only. Descriptors in the table today (11):
|
|
184
|
+
**llama, smollm3, qwen2, qwen3, gemma, gemma2, phi3, olmo2, glm4, granite,
|
|
185
|
+
starcoder2**. `GENERIC_MODEL_TYPES` = the table's keys.
|
|
186
|
+
|
|
214
187
|
Key choices:
|
|
215
188
|
|
|
216
|
-
- **
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
- **
|
|
226
|
-
`
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
- **RuntimeModel surface
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
189
|
+
- **Transcribe mlx-lm op-for-op** inside each descriptor branch (q/k-norm
|
|
190
|
+
before vs after reshape, rope order, scale points, softcap, mask kinds).
|
|
191
|
+
The descriptor selects branches; it never approximates.
|
|
192
|
+
- **Rope factory** (`rope.ts`) — faithful port of `rope_utils.initialize_rope`:
|
|
193
|
+
default / linear / llama3 / yarn / longrope (SuScaledRoPE) / proportional.
|
|
194
|
+
Frequency tables are computed with the same mlx float32 ops the oracle uses
|
|
195
|
+
at module init so the bytes match; host double math only where the oracle
|
|
196
|
+
uses python floats. Gated by `tests/universal-rope.test.ts` against
|
|
197
|
+
machine-keyed oracle fixtures (`tests/fixtures/universal-rope/`).
|
|
198
|
+
- **Dense checkpoints** (`modules.ts`) — verbatim `mlx.nn.Linear`
|
|
199
|
+
(`addmm(bias, x, W.T)` / `x @ W.T`) and `nn.Embedding`; quantized paths
|
|
200
|
+
delegate to gemma4-base. Additive bias is a first-class field (qwen2 qkv,
|
|
201
|
+
starcoder2 all-bias).
|
|
202
|
+
- **Weight audit at load** — `WeightAudit.finish` diffs consumed tensors
|
|
203
|
+
against the shard index minus the arch's sanitize-drop rules; unconsumed
|
|
204
|
+
or missing tensors are a LOAD ERROR naming them, never a silently-wrong
|
|
205
|
+
model.
|
|
206
|
+
- **KV cache** — `KVCache`/`RotatingKVCache` unchanged; `layer_types` /
|
|
207
|
+
`sliding_window` already normalized. Standard attention consumes the shared
|
|
208
|
+
cache-attention interface; qualified Llama uniform KV4/KV8 serving and
|
|
209
|
+
generated-cache coverage are described in batching.md.
|
|
210
|
+
- **RuntimeModel surface** — the minimal contract `Qwen3Model` implements
|
|
211
|
+
(config, weightsBytes, loraState, makeCache, forwardHidden,
|
|
212
|
+
logitsFromHidden, forward, generate, loraTargets) so serving/eval/LoRA
|
|
213
|
+
hot-swap work day one. `forwardEmbeddings` is a stub (vision is per-arch).
|
|
214
|
+
|
|
215
|
+
### 4.2 The parity gate for a new generic arch
|
|
216
|
+
|
|
217
|
+
`tests/universal-manifest.ts` — one entry per launch arch pointing at the
|
|
218
|
+
SMALLEST mlx-community 4-bit checkpoint of that arch, skip-if-absent, with
|
|
219
|
+
`expectClass: "universal" | "dedicated"` (the `qwen3` entry expects
|
|
220
|
+
`Qwen3Model` — generic never shadows targeted, the gate still runs the
|
|
221
|
+
oracle bar). Flow: user downloads → `bun scripts/regen.ts universal [<prefix>|all]`
|
|
222
|
+
→ `MLX_BUN_TEST_UNIVERSAL=1 bun test tests/universal-parity.test.ts`.
|
|
223
|
+
Asserts: fingerprint-free construction, weight audit clean, greedy
|
|
224
|
+
trajectory match, per-step logits bit-exact.
|
|
225
|
+
|
|
226
|
+
**Definition of supported-generic = manifest entry green on the current
|
|
227
|
+
machine.** Adding a descriptor without its manifest goldens is the one
|
|
228
|
+
anti-pattern this design forbids.
|
|
229
|
+
|
|
230
|
+
### 4.3 `UniversalMoE` (design only)
|
|
244
231
|
|
|
245
232
|
Same block with the MLP swapped for router + `QuantizedSwitchLinear`
|
|
246
|
-
(already
|
|
233
|
+
(already serving 26B-A4B and Qwen3-MoE). Deltas to parameterize: top-k,
|
|
247
234
|
`norm_topk_probs`, routing score fn (softmax/sigmoid), routing scale,
|
|
248
235
|
shared-expert branch (+ optional shared-expert gate — qwen2_moe),
|
|
249
236
|
first-k-dense-replace (deepseek/glm4_moe layouts), grouped routing
|
|
250
237
|
(deepseek_v3-style, defer). gpt_oss (attention sinks) and llama4 (chunked
|
|
251
|
-
attention) are
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
238
|
+
attention) are not claimed by the generic MoE. RAM honesty belongs in the
|
|
239
|
+
`ls`/fit output (weightsBytes vs RAM), not in marketing.
|
|
240
|
+
|
|
241
|
+
### 4.4 Graduation to Tier-1
|
|
242
|
+
|
|
243
|
+
Criteria (all three): (a) L1 generic parity green and stable across real
|
|
244
|
+
use; (b) it is a daily driver / benchmark / product target; (c) a measured
|
|
245
|
+
perf or memory gap vs a dedicated path worth the maintenance (number in
|
|
246
|
+
docs/reference/benchmarks.md).
|
|
247
|
+
|
|
248
|
+
Process, in order, stop at any step: (1) L2 — optiq goldens
|
|
249
|
+
(`mixed-kv` pattern) if an optiq artifact/kv_config exists; (2) dedicated
|
|
250
|
+
or generated forward — extend `gen-model.ts` if gemma4-base-shaped,
|
|
251
|
+
otherwise a hand port (`qwen3_5.ts` pattern; hand ports are proven and
|
|
252
|
+
cheap); (3) perf levers behind their existing flags (compiled decode,
|
|
253
|
+
kv-quant, fused sdpa) — output-changing experiments are Lab items
|
|
254
|
+
(unified-engine-frontier-plan.md §6); (4) benchmark + docs entries, tier
|
|
255
|
+
label flips to `targeted`. Graduation never deletes the generic path — it
|
|
256
|
+
stays the permanent correctness fallback, as the monolith does for generated
|
|
257
|
+
gemma classes.
|
|
258
|
+
|
|
259
|
+
### 4.5 Remaining phases
|
|
260
|
+
|
|
261
|
+
| Phase | Scope | State |
|
|
262
|
+
|---|---|---|
|
|
263
|
+
| 1 | UniversalDense + descriptor table + rope factory + bias + manifest harness | built |
|
|
264
|
+
| 1.5 | dense (bf16/fp16) checkpoints, no `.scales` | built (`modules.ts`) |
|
|
265
|
+
| 2 | UniversalMoE: mixtral, qwen2_moe, olmoe, glm4_moe, dots1, granitemoe, ernie4_5_moe, phimoe (qwen3_moe is already a dedicated port) | design |
|
|
266
|
+
| 3 | demand-driven one-offs (SSM/hybrid: lfm2, qwen3_next, mamba2, nemotron_h; MLA if a runnable target appears) — each a real port with its own goldens and cache types | design |
|
|
267
|
+
| 4 | `mlx-bun port <hf-repo>`: download smallest snapshot → descriptor coverage check (config keys + weight-audit dry run) → auto-regen goldens vs the oracle venv → run the gate → print verdict + manifest entry. Optionally generalize `gen-model.ts` to emit from UniversalDense | design (no CLI command exists) |
|
|
263
268
|
|
|
264
|
-
|
|
265
|
-
createModel(weights, config):
|
|
266
|
-
1. dedicated classes (diffusion, minicpm5, qwen3_5, qwen3) — unchanged
|
|
267
|
-
2. gemma4*: GENERATED.get(fingerprint) ?? Gemma4Model — unchanged
|
|
268
|
-
3. ARCHS[remap(config.modelType)] → new UniversalDense/MoE(...) — NEW
|
|
269
|
-
4. throw "unsupported model_type X (nearest: …)" — unchanged shape
|
|
270
|
-
```
|
|
269
|
+
---
|
|
271
270
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
`input_layernorm`, `post_attention_layernorm`, `model.norm`,
|
|
287
|
-
`model.embed_tokens`, optional `lm_head`). The descriptor handles the
|
|
288
|
-
exceptions: rename maps (starcoder2 `c_fc/c_proj`), fused-proj split rules
|
|
289
|
-
(phi3 `qkv_proj`, `gate_up_proj` — split at load into views/copies),
|
|
290
|
-
prefix strips (vision wrappers `language_model.model.*` — gemma4 already
|
|
291
|
-
does this via `prefixBase`), and drop rules (`rotary_emb.inv_freq`,
|
|
292
|
-
mlx-lm `sanitize`).
|
|
293
|
-
|
|
294
|
-
**Every generic load runs a weight audit** (grow `scripts/inspect-model.ts`
|
|
295
|
-
into `src/model/universal/audit.ts`): after module construction, diff
|
|
296
|
-
{tensors in shard index} vs {tensors consumed}. Unconsumed or missing
|
|
297
|
-
tensors ⇒ load error naming them, not a silent wrong-answer model. This is
|
|
298
|
-
the cheap tripwire that catches descriptor mistakes before parity does
|
|
299
|
-
(the "verify the foundation" rule, mechanized).
|
|
300
|
-
|
|
301
|
-
### 3.5 The parity gate for a NEW arch (cost: ~2–4 h/arch, mostly waiting)
|
|
302
|
-
|
|
303
|
-
Pattern already proven three times (gemma/minicpm5/qwen). Parameterize it
|
|
304
|
-
once:
|
|
305
|
-
|
|
306
|
-
1. `scripts/regen-generic-goldens.ts <snapshot> <prefix>` — oracle venv
|
|
307
|
-
(`/Users/joshrossi/Code/mlx-lm/.venv/bin/python`, mlx-lm `load()` +
|
|
308
|
-
`make_prompt_cache`) emits `<prefix>-parity.json` (explicit prompt ids,
|
|
309
|
-
greedy ids) + 12 step-logit `.bin`s. Same-machine rule applies (logit
|
|
310
|
-
goldens are GPU-specific — label goldens with host).
|
|
311
|
-
2. `tests/generic-parity.test.ts` — iterates a manifest
|
|
312
|
-
(`tests/generic-manifest.ts`: prefix → snapshot path → model_type),
|
|
313
|
-
skipIf-gated on snapshot presence like every parity test. Asserts:
|
|
314
|
-
fingerprint-free construction, weight audit clean, greedy trajectory
|
|
315
|
-
match, per-step logits bit-exact.
|
|
316
|
-
3. Checkpoint choice: **smallest mlx-community 4-bit of the arch**
|
|
317
|
-
(0.5B–3B exists for nearly all of bucket A) — keeps the gate runnable
|
|
318
|
-
and the download small. Downloads stay a user action (ground rules).
|
|
319
|
-
|
|
320
|
-
Definition of supported-generic = manifest entry green on the current
|
|
321
|
-
machine. No entry, no support claim.
|
|
322
|
-
|
|
323
|
-
### 3.6 Graduation to Tier-1 (targeted)
|
|
324
|
-
|
|
325
|
-
**Criteria** (all three): (a) L1 generic parity green and stable across a
|
|
326
|
-
few sessions of real use; (b) it's a daily driver / benchmark / product
|
|
327
|
-
target (e.g. the Lucien pipeline models); (c) measured perf or memory gap
|
|
328
|
-
vs a dedicated path that's worth the maintenance (number in
|
|
329
|
-
`benchmarks/RESULTS.md`, per the every-perf-claim-gets-a-number rule).
|
|
330
|
-
|
|
331
|
-
**Process** (the gemma methodology, in order — stop at any step):
|
|
332
|
-
1. **L2**: optiq-quant goldens (`regen-*-kv-goldens` pattern, mixed-KV vs
|
|
333
|
-
the optiq oracle) if an optiq checkpoint/kv_config exists for it.
|
|
334
|
-
2. **Dedicated or generated forward**: if the arch is gemma4-base-shaped,
|
|
335
|
-
extend `gen-model.ts`; otherwise hand-port a dedicated module
|
|
336
|
-
(`qwen3_5.ts` pattern). Note: today's `gen-model.ts` subclasses
|
|
337
|
-
`Gemma4Model` specifically — generalizing it to emit from
|
|
338
|
-
`UniversalDense` is Phase 4 work, and *optional*: hand ports are proven
|
|
339
|
-
and cheap ("faithful port took ~1 hr, not the huge effort claimed").
|
|
340
|
-
3. **Perf levers**: compiled decode / kv-quant / fused-sdpa, each behind its
|
|
341
|
-
existing flag. (The former "L3 kernels" step — fused decode / flash paths
|
|
342
|
-
with frozen-oracle gates — was deleted 2026-07-05; output-changing
|
|
343
|
-
experiments are now Lab items, see
|
|
344
|
-
[unified-engine-frontier-plan.md §6](unified-engine-frontier-plan.md).)
|
|
345
|
-
4. RESULTS.md + docs entries; `mlx-bun models` label flips to `targeted`.
|
|
346
|
-
|
|
347
|
-
Nothing about graduation removes the generic path — it stays as the
|
|
348
|
-
always-correct fallback, exactly like the monolith does for generated
|
|
349
|
-
gemma classes today.
|
|
271
|
+
## 5. Multimodal seams shared by the ports
|
|
272
|
+
|
|
273
|
+
Every tower (vision or audio) returns language-space soft tokens
|
|
274
|
+
`[1, soft, textHidden]` pre-divided by `embed_scale` (the language model
|
|
275
|
+
re-multiplies), splices into the prompt through
|
|
276
|
+
`src/vision/prompt.ts buildMultimodalPrompt` (images + audio in document
|
|
277
|
+
order; `buildVisionPrompt` is a byte-identical wrapper), and enters the model
|
|
278
|
+
through `forwardEmbeddings` (merged embeddings; per-layer-input models take
|
|
279
|
+
a `multimodal` zeroing mask decoupled from the `bidir` attention overlay).
|
|
280
|
+
Media requests route to the **serial lane**, skip the prompt cache and spec
|
|
281
|
+
decode, and capability flags (`visionCapable`, `audioCapable` in
|
|
282
|
+
`src/registry.ts`) check TENSORS, not just config. Non-WAV audio transcodes
|
|
283
|
+
via macOS `afconvert`; video decodes via the AVFoundation sidecar
|
|
284
|
+
`mlx-bun-frame-extract` — zero vendored codecs.
|
|
350
285
|
|
|
351
286
|
---
|
|
352
287
|
|
|
353
|
-
##
|
|
288
|
+
## 6. Ports
|
|
289
|
+
|
|
290
|
+
One subsection per family. Each states the graph, its oracle, and the
|
|
291
|
+
design-relevant facts; phase logs live in PLAN.md at the named anchor.
|
|
292
|
+
|
|
293
|
+
### 6.1 Gemma-4 (e4b / 12B / 26B-A4B) — `src/model/gemma4.ts`, `gemma4-base.ts`, `generated/`
|
|
294
|
+
|
|
295
|
+
- **Graph**: line-for-line port of mlx-lm `gemma4_text.py` covering 12B
|
|
296
|
+
(dense), e4b (per-layer-input embeddings + KV-shared layers), 26B-A4B
|
|
297
|
+
(MoE: router + gather_qmm experts). SDPA scale 1.0 (q/k normalized);
|
|
298
|
+
full-attention layers use global_head_dim 512, one global KV head,
|
|
299
|
+
`attention_k_eq_v`; ProportionalRoPE rotates only
|
|
300
|
+
`partial_rotary_factor` dims; python-float scalars promote weakly; mlx
|
|
301
|
+
helper implementations replicated exactly (`x**3` is `mx.power`).
|
|
302
|
+
Sliding layers use a plain cache + window masks (numerically identical to
|
|
303
|
+
mlx-lm's RotatingKVCache).
|
|
304
|
+
- **Specialization**: `scripts/gen-model.ts` → `generated/gemma4-{e4b,12b,26b}.ts`,
|
|
305
|
+
fingerprint-dispatched, bit-exact vs the monolith
|
|
306
|
+
(`tests/generated-parity.test.ts`).
|
|
307
|
+
- **Oracle**: L1 mlx-lm (`goldens/parity.json` on the 12B snapshot,
|
|
308
|
+
`tests/parity.test.ts`; 26B `tests/parity-26b.test.ts`); L2 mlx-optiq for
|
|
309
|
+
the mixed-KV composition (26B `logits-26b-kvmix.bin`, `mixed-kv` job).
|
|
310
|
+
Profile: `gemma4-generated` / `gemma4-dedicated`, L1.
|
|
311
|
+
- **Vision**: two towers behind one merge contract — `src/vision/siglip.ts`
|
|
312
|
+
(full SigLIP encoder shipped by e2b/e4b/26B/31B; port of optiq's vendored
|
|
313
|
+
mlx-vlm gemma4 encoder from the bf16 `optiq_vision.safetensors` sidecar)
|
|
314
|
+
and `src/vision/embedder.ts` (12B `gemma4_unified` encoder-free patch
|
|
315
|
+
embedder). Oracle = optiq internals (`goldens/e4b-vision.json`,
|
|
316
|
+
`tests/e4b-vision.test.ts`, `tests/vision.test.ts`): spliced ids and
|
|
317
|
+
soft-token count EXACT, greedy PREFIX match; full bit-exact greedy is not
|
|
318
|
+
asserted because the 16-layer bf16 encoder composition drifts sub-bf16 and
|
|
319
|
+
the scale-1.0 softmax amplifies it (siglip.ts header).
|
|
320
|
+
- **Audio**: §6.6.
|
|
321
|
+
- PLAN anchors: Phase 12 (SigLIP), Phase 2 findings (parity notes).
|
|
322
|
+
|
|
323
|
+
### 6.2 MiniCPM5-1B — `src/model/minicpm5.ts`
|
|
324
|
+
|
|
325
|
+
- **Graph**: `model_type: llama` (plain Llama block — no MiniCPM residual
|
|
326
|
+
scaling), 24 layers, hidden 1536, 16/2 heads @128, vocab 130560, untied,
|
|
327
|
+
`rope_theta` from `ropeParameters.full_attention`. Port target mlx-lm
|
|
328
|
+
`models/llama.py`; the expert swiglu is mx.compile-compiled like the
|
|
329
|
+
oracle's `activations.py` (`compiledSwiglu`, kill-switch
|
|
330
|
+
`MLX_BUN_COMPILED_SWIGLU=0`) — the one fusion that matched the oracle's
|
|
331
|
+
kernel set and brought CPM5 decode to parity with mlx-lm
|
|
332
|
+
(decode-speed-program.md).
|
|
333
|
+
- **Dispatch**: the exact-shape `isMiniCPM5Config` predicate keeps it on
|
|
334
|
+
the dedicated class ahead of the generic `llama` descriptor.
|
|
335
|
+
- **Oracle**: L1 mlx-lm (`goldens/minicpm5-parity.json`,
|
|
336
|
+
`tests/minicpm5-parity.test.ts`); L2 mlx-optiq for per-layer quantized KV
|
|
337
|
+
(`goldens/minicpm5-kv-parity.json`, `tests/minicpm5-kv-parity.test.ts`,
|
|
338
|
+
bit-exact via `QuantizedKVCache` + `quantizedSdpaUnfused`). Also the
|
|
339
|
+
TurboQuant KV testbed (`TurboQuantKVCache`). Profile
|
|
340
|
+
`minicpm5-dedicated`, L1 (the L2 composition is a request-level KV scheme,
|
|
341
|
+
not a profile property).
|
|
342
|
+
- Training reference model for segmented backward and ORPO
|
|
343
|
+
(docs/design/orpo-training.md, orpo-training.md).
|
|
344
|
+
|
|
345
|
+
#### 6.2.1 MiniCPM5-2B investigation
|
|
346
|
+
|
|
347
|
+
Metadata and template inspection completed 2026-09-10. No weights were
|
|
348
|
+
downloaded and no GPU inference was run. This checkpoint is a candidate,
|
|
349
|
+
not an artifact with established parity or local performance results.
|
|
350
|
+
|
|
351
|
+
Start with the official [OpenBMB MLX artifact](https://huggingface.co/openbmb/MiniCPM5-2B-MLX),
|
|
352
|
+
revision `3d00c3da500debfe345e60e25a87ed2669f5b1ee`. Its config uses standard
|
|
353
|
+
Llama blocks, 42 layers, hidden size 2048, intermediate size 6144, 16 query
|
|
354
|
+
and 2 KV heads of dimension 128, untied embeddings, vocab 130560 and
|
|
355
|
+
RoPE theta 5000000. Quantization is affine 4-bit with group size 64.
|
|
356
|
+
Preserve both EOS IDs, `1` and `130073`, and the separate
|
|
357
|
+
`chat_template.jinja`. The release is text-only and Apache-2.0.
|
|
358
|
+
|
|
359
|
+
Current integration findings:
|
|
360
|
+
|
|
361
|
+
- `isMiniCPM5Config` in `src/model/support.ts` matches the older 24-layer,
|
|
362
|
+
hidden-1536 artifact. The 2B config fails that predicate and qualifies for
|
|
363
|
+
generic Llama through `genericArgsFor`; `familyProfile` therefore selects
|
|
364
|
+
the universal graph. Do not widen the predicate before auditing dedicated
|
|
365
|
+
execution, training and cache assumptions against this shape.
|
|
366
|
+
- A CPU-only smoke using the pinned config and template passed
|
|
367
|
+
`loadModelConfig`, `genericArgsFor`, `ChatTemplate.load` and rendering a
|
|
368
|
+
user → assistant tool call → tool result → user conversation. Explicit
|
|
369
|
+
thinking true/false both render correctly; the XML function call survives.
|
|
370
|
+
This checks rendering, not generated tool-call parsing or tokenizer parity.
|
|
371
|
+
- `resolveEnableThinking` applies the MiniCPM no-thinking default through
|
|
372
|
+
the same exact-shape predicate. It does not apply to 2B. With no explicit
|
|
373
|
+
option, this artifact's prompt ends at the assistant header; true appends
|
|
374
|
+
an open think tag, false appends a closed empty think block. Set this
|
|
375
|
+
explicitly in comparisons. Template support for disabling thinking does
|
|
376
|
+
not establish no-thinking quality.
|
|
377
|
+
|
|
378
|
+
Evaluation sequence:
|
|
379
|
+
|
|
380
|
+
1. Pin an 8-bit or BF16 control alongside the official 4-bit candidate.
|
|
381
|
+
Establish tokenizer/prompt identity and same-machine logits against the
|
|
382
|
+
pinned mlx-lm oracle, then test multi-turn tool calls, reasoning splits,
|
|
383
|
+
EOS, cache reuse and batched continuation. Keep quantization quality
|
|
384
|
+
comparisons separate from same-artifact runtime parity.
|
|
385
|
+
2. Compare with MiniCPM5-1B and Gemma e4b on held-out Dreaming segmentation,
|
|
386
|
+
extraction and source-grounded synthesis, plus bounded repository/tool
|
|
387
|
+
tasks. Score boundary/label accuracy and completed tasks, not just valid
|
|
388
|
+
JSON or XML. Use explicit thinking modes and equal token/time budgets.
|
|
389
|
+
3. Record first-answer latency, complete task time, output/reasoning tokens,
|
|
390
|
+
repetition and truncation rates, memory and context scaling. Local
|
|
391
|
+
measurements belong only in `docs/reference/benchmarks.md`, with a named
|
|
392
|
+
quiet machine and the required serving benchmark procedure.
|
|
393
|
+
4. Investigate the [released DSpark draft](https://huggingface.co/openbmb/MiniCPM5-2B-DSpark)
|
|
394
|
+
after ordinary inference passes. Its config declares `Qwen3DSparkModel`,
|
|
395
|
+
five draft layers, block size seven, and target taps `[1,10,20,30,39]`.
|
|
396
|
+
Existing Gemma DSpark support does not establish compatibility. Audit
|
|
397
|
+
the draft's architecture, target taps, weights and verifier before a
|
|
398
|
+
paired task-time comparison.
|
|
399
|
+
|
|
400
|
+
Evidence to use when designing the quality checks:
|
|
401
|
+
[OpenBMB's model card](https://huggingface.co/openbmb/MiniCPM5-2B) distinguishes
|
|
402
|
+
internally reproduced scores from Artificial Analysis results. The
|
|
403
|
+
[independent September 7 evaluation](https://artificialanalysis.ai/articles/openbmb-releases-minicpm5-2b)
|
|
404
|
+
supports strong capability for its size but reports substantial reasoning
|
|
405
|
+
token use and weak absolute terminal-task success. These evaluations do not
|
|
406
|
+
validate MLX 4-bit quality. [Upstream issue 374](https://github.com/OpenBMB/MiniCPM/issues/374)
|
|
407
|
+
reports repetition sensitivity in GGUF coding runs. That is an unreproduced
|
|
408
|
+
cross-runtime hypothesis for our sweep, not evidence of the same MLX failure
|
|
409
|
+
or a reason to change repetition defaults.
|
|
410
|
+
|
|
411
|
+
### 6.3 Qwen3 / Qwen3-MoE / Qwen3.5-family (3.6, 3.8) — `qwen3.ts`, `qwen3-moe.ts`, `qwen3_5.ts`
|
|
412
|
+
|
|
413
|
+
- **Qwen3** (`model_type: qwen3`): dense GQA with per-head q/k RMSNorm
|
|
414
|
+
before RoPE, theta 1e6, tied embeddings. Primary use is the
|
|
415
|
+
text-embedding backbone (`embedPooled`: last-token hidden, L2-normalized).
|
|
416
|
+
Oracle L1 mlx-lm (`tests/qwen3-embed-parity.test.ts`). Shadows the
|
|
417
|
+
generic `qwen3` descriptor.
|
|
418
|
+
- **Qwen3-MoE** (`qwen3_moe`): straight op-for-op transcription of
|
|
419
|
+
mlx-lm `qwen3_moe.py` + `switch_layers.py` — gate Linear → precise
|
|
420
|
+
softmax over all experts → argpartition top-k → renormalize → SwitchGLU
|
|
421
|
+
with compiled swiglu; `decoder_sparse_step` / `mlp_only_layers` dense
|
|
422
|
+
layers handled. Oracle L1 mlx-lm on the 30B-A3B
|
|
423
|
+
(`tests/qwen3-moe-parity.test.ts`; the cached checkpoint has no
|
|
424
|
+
kv_config, so no L2 bar).
|
|
425
|
+
- **Qwen3.5 hybrid** (`qwen3_5` / `qwen3_5_text`; the `qwen3_5_moe` variant
|
|
426
|
+
is excluded by `isQwen35Config`): 64 layers, every
|
|
427
|
+
`full_attention_interval`-th (4) a gated softmax-attention layer (q-gate
|
|
428
|
+
split, per-head q/k norm, partial RoPE 0.25 @ base 1e7, GQA 24/4 @256,
|
|
429
|
+
`o_proj(out·σ(gate))`), the rest **gated DeltaNet** linear attention
|
|
430
|
+
(`in_proj_qkv/z/b/a`, depthwise causal conv1d k=4, `A_log`/`dt_bias`
|
|
431
|
+
float, `RMSNormGated`). The recurrence is the reference's custom Metal
|
|
432
|
+
kernel `gated_delta_step` ported VERBATIM (`src/model/qwen3-delta.ts`) —
|
|
433
|
+
bit-exact parity requires it; the ops fallback reduces in a different
|
|
434
|
+
order. `SSMCache` (conv + recurrent state) implements `Cache` and the
|
|
435
|
+
spec-round contract (`specRoundBegin/Commit/Rollback`: free snapshot,
|
|
436
|
+
replay of the kept window on partial reject — bit-exact by construction
|
|
437
|
+
because the kernel's per-thread loop is serial). Weights under
|
|
438
|
+
`language_model.`; `output_gate_type` other than `"swish"`/absent throws.
|
|
439
|
+
**Qwen3.8-27B is byte-for-byte the 3.6-27B text geometry** — zero new
|
|
440
|
+
graph work; the exact profile `qwen3.8-27b-optiq-4bit` pins the validated
|
|
441
|
+
revision.
|
|
442
|
+
- **Oracles**: L1 mlx-lm `qwen3_5.py` with bf16 KV
|
|
443
|
+
(`goldens/qwen38-parity.json`, `tests/qwen-parity.test.ts`; earlier 4B/3.6
|
|
444
|
+
goldens via `regen.ts qwen-parity`); L2 mlx-optiq mixed-KV on the 3.5/3.6
|
|
445
|
+
OptiQ artifacts (`install_mixed_kv` per-layer bits keyed by cache index ≡
|
|
446
|
+
our `maybeQuantizeKv`). Qwen3.8's OptiQ repo ships no mixed-KV config →
|
|
447
|
+
no L2 bar; mixed-KV serving there is Lab-tier.
|
|
448
|
+
- **Vision + video** (`src/vision/qwen3vl-{preprocess,tower,prompt}.ts`,
|
|
449
|
+
`video-frames.ts`, `src/model/qwen3-mrope.ts`): mlx-vlm `qwen3_vl`
|
|
450
|
+
vision tower at the qwen3_5 configuration (depth 27, hidden 1152, heads
|
|
451
|
+
16 @72, patch 16, temporal 2, merge 2, deepstack empty) from the bf16
|
|
452
|
+
sidecar `optiq/optiq_vision.safetensors`; PIL-exact fixed-point bicubic
|
|
453
|
+
smart_resize; conv3d patch embed (new `mlx_conv3d` binding);
|
|
454
|
+
`ensure_fused_sdpa`'s 72→80 head-dim pad replicated; **interleaved
|
|
455
|
+
mRoPE** via the reference's verbatim Metal apply kernel with
|
|
456
|
+
`get_rope_index` positions + delta exact, installed per request on the
|
|
457
|
+
serial lane (text-only keeps the untouched fast-rope path — equal
|
|
458
|
+
position streams degenerate mRoPE to plain RoPE). Video: AVFoundation
|
|
459
|
+
sidecar samples at 2 fps (max 768 frames), temporal-pair patchify, gridT>1
|
|
460
|
+
tower, transformers' `<t seconds>` per-frame-group prompt format with a
|
|
461
|
+
python-`%.1f` port. Oracle = **mlx-vlm 0.6.14 pinned to mlx 0.31.2**
|
|
462
|
+
(independent of mlx-lm, so no composite bit-match target exists): tower
|
|
463
|
+
bit-exact at small grids, calibrated envelope at 2304 patches; e2e greedy
|
|
464
|
+
token-exact on 2/3 image fixtures, step-0 argmax exact on all
|
|
465
|
+
(`tests/qwen38-vision*.test.ts`).
|
|
466
|
+
- **Native MTP** (`src/spec/qwen-mtp-source.ts`, `--draft-kind mtp`): the
|
|
467
|
+
separately published `Qwen3.8-27B-MTP-*` head (`fc` over
|
|
468
|
+
concat(rms(embed(next)), rms(target_hidden)) → one full-attention layer
|
|
469
|
+
with its own KVCache → target lm_head, block_size 3, DeepSeek-V3 shape)
|
|
470
|
+
reads the target's PRE-final-norm hidden via `captureLayer`. Gate:
|
|
471
|
+
greedy speculation token-identical to non-spec greedy
|
|
472
|
+
(`tests/qwen38-mtp.test.ts`). Durable negative perf verdict on the quiet
|
|
473
|
+
M1 Max (MTP-on slower than off at γ=2 despite 61% acceptance) — stays
|
|
474
|
+
opt-in. Drafter logits verified against the mlx-vlm reference fed the
|
|
475
|
+
oracle's captured hidden grid.
|
|
476
|
+
- Training: `loraTargets()` wired; the DeltaNet kernel is inference-only —
|
|
477
|
+
training needs mlx-lm's pure-mlx `gated_delta_ops` scan under training
|
|
478
|
+
(open).
|
|
479
|
+
- PLAN anchors: Phase 14 (bring-up, 14g MTP, 14v vision, 14w video, 14y
|
|
480
|
+
YaRN open, 14z TurboQuant weights).
|
|
481
|
+
|
|
482
|
+
### 6.4 GLM-5.2 (`glm_moe_dsa`) — the Colibri hierarchy, `src/model/glm52*.ts`
|
|
483
|
+
|
|
484
|
+
Summary of docs/archive/investigations/colibri-glm52-port.md (frozen);
|
|
485
|
+
full phase record G0–G8 in git (`git show 3199c75:PLAN-archive.md`,
|
|
486
|
+
Phase 21, closed 2026-08-17). GLM-5.3+ would extend THIS section.
|
|
487
|
+
|
|
488
|
+
- **Decision**: a native `Glm52Model` over the PUBLIC Colibri container in
|
|
489
|
+
place (no second copy, no Colibri child process, no `--backend`); the
|
|
490
|
+
pinned Colibri build (`JustVugg/colibri` @ `44e489b`) is an external
|
|
491
|
+
executable oracle for formats, logits/tokens, routing traces, memory and
|
|
492
|
+
speed. Its policy code is studied and reproduced, not shipped.
|
|
493
|
+
- **Model**: 78 main layers (3 dense FFN + 75 sparse MoE, 256 routed
|
|
494
|
+
experts, top-8) + an MTP row with its own 256 experts (19,456 expert
|
|
495
|
+
instances). The dense spine (embeddings, lm-head, attention, norms, first
|
|
496
|
+
dense FFNs, routers, shared experts) stays resident at int4 (~9.9 GB); the
|
|
497
|
+
~370 GB routed-expert pool stays on disk.
|
|
498
|
+
- **Graph** (`glm52.ts`, `glm52-mla.ts`, `glm52-dsa.ts`, `glm52-moe.ts`):
|
|
499
|
+
MLA — q-a → norm → q-b; kv-a → latent norm; **compressed cache** of the
|
|
500
|
+
512-wide latent + 64 RoPE values per token (`MLACache`, ~57× smaller than
|
|
501
|
+
reconstructed K/V at this geometry), weight-absorption decode,
|
|
502
|
+
reconstructed-prefill fallback, partial interleaved RoPE. **DSA indexer**
|
|
503
|
+
— q/k/projection/norm, per-layer full/shared schedule, exact dense
|
|
504
|
+
fallback when the selected set covers the prefix (`DSAIndexCache` only on
|
|
505
|
+
layers that own it). MoE — sigmoid scores + correction bias for
|
|
506
|
+
selection, un-biased gate weights, true top-8, routed scale, shared expert
|
|
507
|
+
in parallel. Colibri arithmetic (offset-binary int4, per-row int8 scale
|
|
508
|
+
applied once, RMSNorm with multiplicative weight and double-accumulated
|
|
509
|
+
reduction) is mirrored in `glm52-reference.ts`. G2 favors an auditable
|
|
510
|
+
dequantize→f32 path; the Metal streamed kernel (`glm52-streamed-metal.ts`)
|
|
511
|
+
replaces the expert resolver without changing the graph.
|
|
512
|
+
- **Expert residency / streaming** (`glm52-residency.ts`,
|
|
513
|
+
`glm52-streamed-experts.ts`, `glm52-expert-layout.ts`, `glm52-pilot.ts`,
|
|
514
|
+
`glm52-coupling.ts`, `glm52-atlas.ts`): per-layer bounded LRU slots
|
|
515
|
+
derived from the whole-process memory equation, pinned hot-store seeded
|
|
516
|
+
from persistent usage, LFRU repinning with hysteresis, batch-union of
|
|
517
|
+
unique (layer, expert) across rows so each expert is read once per
|
|
518
|
+
layer/step, `pread` worker pool with slot generations and completion
|
|
519
|
+
fences (no reuse while a lazy MLX command can retain the buffer), PILOT
|
|
520
|
+
(next-layer router on the current state) and COUPLE (cross-layer route
|
|
521
|
+
pairs) prefetch, RSS feedback shrinking only the evictable tier. Unified
|
|
522
|
+
memory removes a copy, not the 370 GB: the meaningful states are disk /
|
|
523
|
+
resident / pinned / loading / in-flight / evictable.
|
|
524
|
+
- **Fixed-context admission** (`glm52-memory.ts`, `factory.ts
|
|
525
|
+
openGlm52RuntimeModel`): a header-only resource plan runs BEFORE any
|
|
526
|
+
resident tensor or expert slab is opened — process limit (default 25 GiB
|
|
527
|
+
preset or physical RAM, whichever is smaller), fixed context
|
|
528
|
+
(default 4096 tokens, 128 generation), allocator/Bun/safety reserves — and
|
|
529
|
+
refuses an impossible placement; the opened runtime's planned bytes must
|
|
530
|
+
equal the preflight equation or load fails. Serving clamps `max_tokens`
|
|
531
|
+
to the room under the fixed context (STATUS: "GLM fixed-context admission
|
|
532
|
+
correction", generalized to every model in v0.2.0).
|
|
533
|
+
- **Native MTP** (`src/spec/glm52-mtp-source.ts`): the checkpoint's int8 MTP
|
|
534
|
+
row as an in-process draft source sharing the target; serial only —
|
|
535
|
+
batched rows decode single tokens (Colibri keeps MTP out of its mux path
|
|
536
|
+
too). Batched caches land via `makeEmptyBatch/mergeRows/extractRow/
|
|
537
|
+
filterRows/projectedBytes` on right-justified latent/RoPE/DSA tensors —
|
|
538
|
+
no full K/V at merge, admission, extraction or cancellation.
|
|
539
|
+
- **Oracle / fidelity**: profile `glm5.2-colibri` / exact
|
|
540
|
+
`glm5.2-colibri-int4-int8-mtp`, **L3 (measured)** — Colibri is neither
|
|
541
|
+
mlx-lm nor mlx-optiq, so the tier system cannot call it bit-exact even
|
|
542
|
+
though the G2 gate is a teacher-forced trajectory from the pinned engine
|
|
543
|
+
on a tiny converted artifact (`tests/glm52-teacher-forcing.test.ts`,
|
|
544
|
+
`fixtures/colibri-glm52/`). Curated numbers live in code as operator
|
|
545
|
+
guidance (`GLM52_G5_MEASURED_WARM_DECODE_TPS`,
|
|
546
|
+
`GLM52_G5_DIRECT_ORACLE_WARM_DECODE_TPS`, M1 Max 32 GB, MTP on) and in
|
|
547
|
+
docs/reference/models.md "GLM-5.2 on a 32 GB Mac". The 24 GB M4 Pro is
|
|
548
|
+
below the one-slot-per-layer floor and out of scope.
|
|
549
|
+
- **Not claimed**: embeddings, image/audio input, LoRA, training, adapters
|
|
550
|
+
— advertised false, never faked (archive N8).
|
|
551
|
+
- PLAN anchor: Phase 21 (closed 2026-08-17); probes, gate tests, and
|
|
552
|
+
lab spikes for the port surface retired afterwards (commit fbafe44).
|
|
553
|
+
|
|
554
|
+
### 6.5 DiffusionGemma-26B-A4B — `src/model/diffusion-gemma.ts`, `src/diffusion/`, `src/vision/diffusion-vision.ts`
|
|
555
|
+
|
|
556
|
+
Summary of docs/design/generic-model-support.md (the D0 reference dossier
|
|
557
|
+
there stays the porting contract; do not extend it).
|
|
558
|
+
|
|
559
|
+
- **What it is**: the first non-autoregressive model — an encoder prefill
|
|
560
|
+
over the prompt builds a KV cache, then a decoder pass over a fixed
|
|
561
|
+
256-token canvas (initialized to uniform-random ids, NOT a mask token) is
|
|
562
|
+
denoised over up to 48 steps. 30 layers, hidden 2816, 16 heads; each
|
|
563
|
+
layer runs a parallel dense MLP + 128-expert top-8 MoE summed through 7
|
|
564
|
+
RMSNorms and a `layer_scalar`; attention scale 1.0, no attention softcap
|
|
565
|
+
(final-logit softcap 30 in fp32), QK/V-norm post-proj/pre-RoPE, full
|
|
566
|
+
layers (5,11,17,23,29) reuse k as v at hd 512 / kv 2 with partial rotary
|
|
567
|
+
0.25; tied 4-bit head via `QuantizedEmbedding.asLinear`; a
|
|
568
|
+
`SelfConditioning` MLP feeds soft embeddings from the previous step.
|
|
569
|
+
Bidirectional decoder masks (`_make_decoder_masks`) are the crux.
|
|
570
|
+
- **Engine** (`diffusion-generate.ts`): linear temperature schedule
|
|
571
|
+
(`t_min 0.4 → t_max 0.8`, DIVIDES logits), both samplers
|
|
572
|
+
(confidence-threshold = optiq public default, entropy-bound = engine
|
|
573
|
+
default), self-conditioning feedback, stability/EOS, block loop. RNG
|
|
574
|
+
parity via bound `mlx_random_randint`/`mlx_random_seed` threading the
|
|
575
|
+
global key in the reference's draw order. Parity traps recorded in the
|
|
576
|
+
source doc: division not reciprocal-multiply; independent history copies;
|
|
577
|
+
the as-loaded oracle has `generation_config = None` (stable-stop OFF,
|
|
578
|
+
eos {1, 106}).
|
|
579
|
+
- **Vision**: a DEDICATED tower (`diffusion-vision.ts`), not the e4b SigLIP
|
|
580
|
+
— inline-quantized `input_proj` truncates `2*(x-0.5)` patches to integers
|
|
581
|
+
(a trained-in quirk), head_dim 72 padded to 80 like the reference, plain
|
|
582
|
+
bf16 `down_proj`.
|
|
583
|
+
- **Oracle**: **mlx-optiq IS the oracle** (stock mlx-lm cannot load it);
|
|
584
|
+
the mixed-precision quant is the native weight format, so matching optiq
|
|
585
|
+
= L2 = the floor. Profile `diffusion-gemma-dedicated`, L2. Gates:
|
|
586
|
+
single forward bit-exact (`tests/diffusion-parity.test.ts`), generation
|
|
587
|
+
token-for-token for both samplers (`diffusion-gen-parity`), image
|
|
588
|
+
token-for-token (`diffusion-vision`), serving (`diffusion-serving`), LoRA
|
|
589
|
+
with the denoising objective (`diffusion-lora`,
|
|
590
|
+
`src/train/diffusion-lora.ts`; MoE backward by stop-gradient on router
|
|
591
|
+
indices). All `MLX_BUN_TEST_DIFFUSION=1`.
|
|
592
|
+
- **Entry points — honest state**: `src/generate.ts` routes by
|
|
593
|
+
`instanceof DiffusionGemmaModel` to `generateDiffusionInner`, and
|
|
594
|
+
`src/server.ts` has a diffusion vision lane; **`src/cli.ts` contains no
|
|
595
|
+
diffusion reference** (`grep -c diffusion src/cli.ts` = 0). There is no
|
|
596
|
+
diffusion-specific CLI surface; the model is reachable only through the
|
|
597
|
+
generic `serve` / `generate` path by profile + instanceof dispatch, and
|
|
598
|
+
streaming yields tokens after the engine completes. D4 (performance,
|
|
599
|
+
measured) is open.
|
|
600
|
+
|
|
601
|
+
### 6.6 Audio input (gemma-4 audio tower) — `src/audio/`
|
|
602
|
+
|
|
603
|
+
Summary of docs/design/generic-model-support.md. Scope: audio-in, text-out
|
|
604
|
+
through the chat API; TTS/STT endpoints, streaming audio, >30 s, batched
|
|
605
|
+
audio prefill, and 26B-A4B/DiffusionGemma audio (no `audio_config`) are
|
|
606
|
+
non-goals.
|
|
607
|
+
|
|
608
|
+
- **Oracle**: mlx-lm strips `audio_tower`/`embed_audio` at load and rejects
|
|
609
|
+
non-text content; optiq's internal gemma4 machinery is complete but its
|
|
610
|
+
serve frontend never exposes audio → the oracle is the optiq internal
|
|
611
|
+
model driven directly (`scripts/oracle/gen-e4b-audio-golden.py`,
|
|
612
|
+
`goldens/e4b-audio.json`). The e4b OptiQ-4bit sidecar already holds all
|
|
613
|
+
752 audio tensors (bf16, incl. clipped-linear min/max stats) plus
|
|
614
|
+
`audio_config` and token ids (`boa 256000`, `audio 258881`,
|
|
615
|
+
`eoa 258883`) — no download.
|
|
616
|
+
- **Pipeline**: `decode.ts` (RIFF/WAVE PCM16/24/32/f32, mean mixdown, linear
|
|
617
|
+
resample to 16 kHz, PCM16/32768 like the oracle; >30 s truncates at
|
|
618
|
+
480 000 samples BEFORE features, the oracle extractor's default) →
|
|
619
|
+
`transcode.ts` (`afconvert` for non-WAV, content-sniffed) →
|
|
620
|
+
`features.ts` (USM log-mel, frame 320 / hop 160 / rfft 512 in f64, 128 HTK
|
|
621
|
+
bins, `log(x+1e-3)`, the oracle's exact f32 Hann values baked in because
|
|
622
|
+
numpy's vectorized f32 cos differs by 1 ulp and log-amplifies) →
|
|
623
|
+
`conformer.ts` (SSCP two Conv2d stride-2 stages (128, 32) → Linear 1024 →
|
|
624
|
+
12 Conformer blocks with chunked local attention (chunk 12, left 13,
|
|
625
|
+
softcap 50), depthwise Conv1d k=5, clipped linears → output_proj 1536 →
|
|
626
|
+
`embed_audio` RMSNormNoScale → Linear → /embed_scale). **Dtype contract
|
|
627
|
+
differs from siglip**: the oracle feeds f32 mel into bf16 weights and mlx
|
|
628
|
+
promotes, so activations stay f32 end-to-end — do not cast to weight
|
|
629
|
+
dtype. Clipped-linear stats are load-bearing (off diverges 90%).
|
|
630
|
+
- **LM semantics (resolved against the oracle)**: audio tokens are strictly
|
|
631
|
+
CAUSAL; any audio in the prompt disables the vision bidir overlay
|
|
632
|
+
entirely; per-layer-input zeroing uses the union multimodal mask; USM
|
|
633
|
+
parameters are fixed constructor defaults (no per-bin normalization);
|
|
634
|
+
`<|audio|>` → `boa + audio×n + eoa` with `n = min(ceil(ms/40), 750)` is
|
|
635
|
+
splice-side. The merge divides by embed_scale AFTER the bf16 cast (weak
|
|
636
|
+
scalar) — `features(preDivide=false)` + astype + div mirrors it.
|
|
637
|
+
- **Serve**: OpenAI `input_audio` plus optiq `audio`/`audio_url` parts;
|
|
638
|
+
lazy `getAudioTower` from the same sidecar, zero new flags; a request
|
|
639
|
+
with audio on a towerless model is an explicit 400; Anthropic
|
|
640
|
+
`/v1/messages` rejects audio blocks with a pointer to the OpenAI
|
|
641
|
+
endpoint; `audio` capability flag on `/v1/models`, `/library`, and the pi
|
|
642
|
+
`ready` frame (requires `audio_config` AND tower tensors — the 12B stub
|
|
643
|
+
sidecar reads false).
|
|
644
|
+
- **Gates**: T0 mel model-free (`tests/audio-features.test.ts`, 1e-5),
|
|
645
|
+
T1 tower rel-RMSE (`e4b-audio-tower`, bit-exact result), T2 e2e greedy +
|
|
646
|
+
decoded text EXACT for both fixtures (`e4b-audio`), T3 HTTP
|
|
647
|
+
(`e4b-audio-serve`, `MLX_BUN_TEST_AUDIO_SERVE=1`).
|
|
648
|
+
- **Open (A5)**: bench cells (tower ms, TTFT delta, RSS delta) into
|
|
649
|
+
docs/reference/benchmarks.md; 12B audio cell needs a sidecar rebuild via
|
|
650
|
+
optiq `build_vision_sidecar` (local 12B sidecar holds 1 audio tensor);
|
|
651
|
+
features-matrix note audio×batching = serial.
|
|
652
|
+
- PLAN anchor: "Phase: audio input — gemma-4 audio tower, e4b first".
|
|
354
653
|
|
|
355
|
-
|
|
356
|
-
|---|---|---|---|---|
|
|
357
|
-
| **1** | `UniversalDense` + descriptor table + rope factory (llama3/yarn/longrope) + bias term + goldens harness. Launch archs: **llama (⇒ Llama 3.x + Mistral + Ministral), qwen2, qwen3(fold-in), gemma, gemma2, smollm3, olmo2, olmo3, phi3, glm4, granite, starcoder2** | ~20 files at launch; the rest of bucket A (~36 total) as S-sized descriptor+golden follow-ons; F-wrappers for covered bases | **L** (module M, rope M, harness S, 12×goldens S-each) | rope variants (llama3/yarn/longrope math), gemma2 softcap manual-attn path, phi3 fused-proj split, BOS/tokenizer conventions per family (the double-BOS class of bug), qwen2 qkv bias |
|
|
358
|
-
| **1.5** | `DenseLinear` (bf16/fp16 checkpoints, no `.scales`) | fp16-only small models; removes the "MLX-quantized only" constraint | **S–M** | dtype/cast points vs mlx-lm (bf16 matmul accumulation — see e4b length-sensitivity memory) |
|
|
359
|
-
| **2** | `UniversalMoE` (router + SwitchGLU + shared experts + first-k-dense) : **mixtral, qwen2_moe, qwen3_moe, olmoe, glm4_moe, dots1, granitemoe, ernie4_5_moe, phimoe** | ~12–15 of bucket B (gpt_oss/llama4 excluded) | **M** (SwitchGLU exists; routing variants are config) | routing-score parity (softmax vs sigmoid + norm_topk), RAM honesty on 24 GB |
|
|
360
|
-
| **3** | Demand-driven one-offs, qwen3_5 pattern: SSM/hybrid (**lfm2, qwen3_next, mamba2, nemotron_h**…), MLA module if a runnable target appears (**minicpm3**; deepseek-lineage mostly exceeds local RAM) | bucket C/D picks, ~1 model per effort unit | **M–L each** (cumulatively XL; never a blocker for A/B) | new cache types (conv/ssm state) touch the Cache interface + serving slots; each is a real port with its own goldens |
|
|
361
|
-
| **4** | Tooling: **`mlx-bun port <hf-repo>`** — download smallest snapshot → descriptor coverage check (config keys + weight-audit dry run) → auto-regen goldens vs oracle venv → run parity gate → print verdict + manifest entry. Optionally: generalize `gen-model.ts` to emit from UniversalDense for graduation | turns "new arch" into a ~1-command, ~1-hour operation; makes the coverage claim self-verifying | **M** (scaffold) + **L** (generator generalization, optional) | oracle-venv coupling (mlx-lm version drift changes goldens — pin + record versions in parity.json, already the pattern) |
|
|
362
|
-
|
|
363
|
-
Sequencing note: Phase 1's descriptor table should be *born* with only the
|
|
364
|
-
12 launch archs actually gated green — adding an arch without its manifest
|
|
365
|
-
goldens is the one anti-pattern this design forbids.
|
|
654
|
+
---
|
|
366
655
|
|
|
367
|
-
##
|
|
656
|
+
## 7. Top design decisions
|
|
368
657
|
|
|
369
658
|
1. **Explicit descriptor table keyed by model_type (+ vendored
|
|
370
659
|
MODEL_REMAPPING), not config sniffing** — support is a declared,
|
|
371
660
|
testable surface; fingerprints remain a generated-dispatch guard only.
|
|
372
|
-
2. **One
|
|
373
|
-
|
|
374
|
-
|
|
661
|
+
2. **One profile per load, resolved before weights open** — exact artifact
|
|
662
|
+
> family > generic; mismatches refuse, never downgrade; profiles declare
|
|
663
|
+
construction only.
|
|
375
664
|
3. **L1 bit-exact is the gate for generic too** — manifest-driven golden
|
|
376
|
-
harness (explicit ids, raw per-step logits, same
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
665
|
+
harness (explicit ids, raw per-step logits, same GPU).
|
|
666
|
+
4. **Weight audit at load** — unconsumed/missing tensors are a load error.
|
|
667
|
+
5. **Generic never shadows targeted; graduation never deletes generic.**
|
|
668
|
+
6. **The oracle for any capability is whoever ships it** — mlx-lm (L1),
|
|
669
|
+
mlx-optiq (L2), mlx-vlm / optiq internals / Colibri where those are the
|
|
670
|
+
only implementations — and the profile's fidelity label says which.
|
|
671
|
+
7. **Honest tiering in UX** — `mlx-bun ls`, hub REST, and discovery routes
|
|
672
|
+
show `targeted` vs `generic`; media capability flags check tensors.
|
|
673
|
+
8. **New ports are sections of this doc**, with their durable phase record
|
|
674
|
+
in PLAN.md.
|
|
675
|
+
|
|
676
|
+
## History
|
|
677
|
+
|
|
678
|
+
- 2026-06-24 — MiniCPM5 decode megakernel shelved (persistent single-dispatch
|
|
679
|
+
decode kernel, ~0.94× baseline at best; L2 ceiling 93/100 from quant
|
|
680
|
+
discontinuity amplifying 1-ULP GEMV drift). Premise removed by the
|
|
681
|
+
bandwidth-wall finding (decode-speed-program.md: the baseline decode path
|
|
682
|
+
sits at the memory-bandwidth wall; the real CPM5 waste was the unfused
|
|
683
|
+
swiglu, fixed by `compiledSwiglu`). Code shelved to scripts/experiments
|
|
684
|
+
2026-07-01 and deleted with that directory 2026-08-23 (git history); no
|
|
685
|
+
megakernel code remains in `src/`. The doc
|
|
686
|
+
`docs/design/generic-model-support.md` is superseded by this line.
|
|
687
|
+
- 2026-06-24 — DiffusionGemma D0–D3 + D5 landed (bit-exact forward,
|
|
688
|
+
token-for-token generation, image, LoRA); D4 open.
|
|
689
|
+
- 2026-06-15 → 2026-08-18 — Qwen3.5-family: 3.6 text parity both bars;
|
|
690
|
+
3.8 retarget (identical geometry), native MTP, vision, video landed.
|
|
691
|
+
- 2026-07-01 — Generic Phase 1 + 1.5 built (commit 9bd9f1b):
|
|
692
|
+
UniversalDense, 11 descriptors, rope factory, dense checkpoints, weight
|
|
693
|
+
audit, manifest harness.
|
|
694
|
+
- 2026-07-07 — Audio A0–A4 landed (e4b, oracle-exact); A5 open.
|
|
695
|
+
- 2026-08-17 — GLM-5.2 Colibri port closed (Phase 21); surface retired,
|
|
696
|
+
design archived.
|
|
697
|
+
- 2026-08-21 — Model profiles (`src/model/profile.ts`) introduced; exact
|
|
698
|
+
artifact declarations for Qwen3.8 OptiQ and GLM-5.2 Colibri.
|
|
699
|
+
- 2026-08-23 — This doc consolidated: audio-input-plan,
|
|
700
|
+
diffusion-gemma-port, minicpm5-decode-megakernel, and the Colibri archive
|
|
701
|
+
summarized here; ports become sections.
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
Non-Qwen grouped TurboQuant drafting, including assistant donor attention, uses
|
|
705
|
+
the shared cache interfaces. See [composition coverage](batching.md#turboquant-donor-attention-and-grouped-draft-composition).
|