mlx-bun 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1453 -88
- package/THIRD_PARTY_NOTICES.md +882 -0
- package/bin/mlx-bun.convert.mjs +4 -0
- package/bin/mlx-bun.fuse.mjs +4 -0
- package/bin/mlx-bun.generate.mjs +4 -0
- package/bin/mlx-bun.lora.mjs +4 -0
- package/bin/mlx-bun.mjs +13 -21
- package/bin/mlx-bun.server.mjs +4 -0
- package/bin/mlx-bun.upload.mjs +4 -0
- package/dist/web/app.js +9584 -0
- package/package.json +50 -53
- package/src/cli/ane-install.ts +76 -0
- package/src/cli/args.ts +179 -0
- package/src/cli/engine-entry.ts +68 -0
- package/src/cli/inference.ts +214 -0
- package/src/cli/job-entry.ts +97 -0
- package/src/cli/library-host.ts +117 -0
- package/src/cli/main.ts +57 -0
- package/src/cli/memory-engine.ts +163 -0
- package/src/cli/memory.ts +36 -0
- package/src/cli/mlx-lm-aliases.ts +309 -0
- package/src/cli/model-choice.ts +33 -0
- package/src/cli/model-selection.ts +84 -0
- package/src/cli/module-host.ts +11 -0
- package/src/cli/module-verbs.ts +50 -0
- package/src/cli/numerical-policy.ts +12 -0
- package/src/cli/perplexity.ts +89 -0
- package/src/cli/serve-host.ts +423 -0
- package/src/cli/serve-isolated.ts +217 -0
- package/src/cli/serve-options.ts +106 -0
- package/src/cli/serve-state.ts +205 -0
- package/src/cli/serve.ts +500 -0
- package/src/cli/served-model-host.ts +102 -0
- package/src/cli/server-entry.ts +148 -0
- package/src/cli/serving-unit.ts +177 -0
- package/src/{tui.ts → cli/terminal.ts} +13 -8
- package/src/cli/worker-adapters.ts +34 -0
- package/src/cli/worker-entry.ts +272 -0
- package/src/cli/worker-unit.ts +179 -0
- package/src/engine/adapter-operation.ts +26 -0
- package/src/engine/cache-services.ts +114 -0
- package/src/engine/completion.ts +39 -0
- package/src/engine/generation-gateway.ts +358 -0
- package/src/engine/index.ts +59 -0
- package/src/engine/kv-budget.ts +120 -0
- package/src/engine/media-preparation.ts +232 -0
- package/src/engine/model-binding.ts +24 -0
- package/src/engine/model-host.ts +513 -0
- package/src/engine/model-serving.ts +89 -0
- package/src/{serve → engine}/preparation.ts +10 -8
- package/src/{serve → engine}/session-completion-engine.ts +6 -6
- package/src/engine/telemetry.ts +109 -0
- package/src/hub/downloads.ts +116 -0
- package/src/jobs/db.ts +16 -7
- package/src/jobs/events.ts +29 -0
- package/src/jobs/executable.ts +5 -0
- package/src/jobs/host.ts +51 -0
- package/src/jobs/in-process.ts +55 -0
- package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
- package/src/jobs/runner.ts +150 -231
- package/src/jobs/service.ts +75 -0
- package/src/jobs/sse.ts +59 -23
- package/src/jobs/worker-memory.ts +46 -0
- package/src/jobs/worker-process.ts +163 -0
- package/src/jobs/worker-supervisor.ts +258 -0
- package/src/modules.ts +58 -0
- package/src/publishing/catalog-hub.ts +18 -0
- package/src/publishing/credentials.ts +31 -0
- package/src/publishing/upload.ts +37 -0
- package/src/residency/leased-adapters.ts +21 -0
- package/src/residency/local-records.ts +16 -0
- package/src/residency/model-residency.ts +405 -0
- package/src/residency/record-index.ts +28 -0
- package/src/residency/resident-estimate.ts +50 -0
- package/src/{anthropic.ts → server/anthropic.ts} +3 -81
- package/src/server/cache-routes.ts +36 -0
- package/src/{serve → server}/chat-request.ts +12 -10
- package/src/{serve → server}/chat-stage.ts +27 -22
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +42 -42
- package/src/server/decision-body.ts +55 -0
- package/src/server/decision-routes.ts +134 -0
- package/src/server/decision-wire.ts +228 -0
- package/src/{serve → server}/discovery-routes.ts +42 -83
- package/src/server/generated-token-history.ts +57 -0
- package/src/{serve → server}/http.ts +25 -13
- package/src/{serve → server}/inference-request.ts +5 -5
- package/src/server/job-routes.ts +20 -0
- package/src/server/media-prompt.ts +63 -0
- package/src/server/memory-completion-client.ts +46 -0
- package/src/server/model-routes.ts +192 -0
- package/src/{serve → server}/openai-wire.ts +3 -2
- package/src/{serve → server}/pipeline.ts +1 -1
- package/src/server/prompt-builder.ts +13 -0
- package/src/server/prompt-contracts.ts +17 -0
- package/src/server/proxy-routes.ts +187 -0
- package/src/server/publishing-routes.ts +41 -0
- package/src/{serve → server}/request-plan.ts +8 -8
- package/src/{serve → server}/request-prep.ts +82 -68
- package/src/{serve → server}/responses-client.ts +30 -13
- package/src/{responses.ts → server/responses.ts} +12 -93
- package/src/server/routes.ts +205 -0
- package/src/server/start.ts +72 -0
- package/src/server/status-routes.ts +108 -0
- package/src/{serve → server}/text-completion-stage.ts +25 -4
- package/src/server/text-prompt.ts +12 -0
- package/src/{serve → server}/token-streams.ts +36 -38
- package/src/server/worker-routes.ts +311 -0
- package/src/storage/paths.ts +61 -0
- package/src/web/assets.ts +37 -0
- package/src/web/{src → browser}/api.ts +5 -23
- package/src/web/browser/chat-host.ts +17 -0
- package/src/web/browser/installed-panels.ts +6 -0
- package/src/web/browser/main.ts +55 -0
- package/src/web/browser/markdown.ts +279 -0
- package/src/web/browser/memory-panel.ts +9 -0
- package/src/web/browser/palette.ts +64 -0
- package/src/web/browser/protocol.ts +13 -0
- package/src/web/browser/shell.ts +467 -0
- package/src/web/{src → browser}/status.ts +32 -36
- package/src/web/build.ts +51 -0
- package/src/web/public/app.html +1054 -0
- package/src/web/{sw.js → public/sw.js} +4 -3
- package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
- package/src/web/{vendor → public/vendor}/hljs.js +2 -2
- package/THIRD_PARTY_LICENSES.md +0 -51
- package/docs/README.md +0 -94
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
- package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
- package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
- package/docs/archive/investigations/curve-bisector-routing.md +0 -123
- package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
- package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
- package/docs/archive/investigations/dspark-handoff.md +0 -224
- package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
- package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
- package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
- package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
- package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
- package/docs/archive/investigations/lab-build-journal.md +0 -157
- package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
- package/docs/archive/investigations/openjarvis-fit.md +0 -198
- package/docs/archive/investigations/openwiki-evaluation.md +0 -249
- package/docs/archive/investigations/optimization_plan.md +0 -346
- package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
- package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
- package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
- package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
- package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
- package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
- package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
- package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
- package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
- package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
- package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
- package/docs/archive/planning/chat-ui-vision.md +0 -50
- package/docs/archive/planning/chunk-task-roadmap.md +0 -77
- package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
- package/docs/archive/planning/journal.md +0 -316
- package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
- package/docs/archive/planning/pi-integration-review.md +0 -178
- package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
- package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
- package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
- package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
- package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
- package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
- package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
- package/docs/archive/planning/web-ui-pass-plan.md +0 -213
- package/docs/archive/planning/website-readme-pass-plan.md +0 -224
- package/docs/design/batching.md +0 -1841
- package/docs/design/decode-speed-program.md +0 -2349
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -705
- package/docs/design/kv-cache.md +0 -824
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -1990
- package/docs/design/turboquant.md +0 -2212
- package/docs/design/unified-engine-frontier-plan.md +0 -1880
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -594
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/release-notes-v0.4.0.md +0 -45
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3613
- package/docs/reference/cli.md +0 -585
- package/docs/reference/distribution.md +0 -355
- package/docs/reference/environment.md +0 -398
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -674
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -334
- package/docs/reference/server-api.md +0 -1775
- package/docs/reference/server-config.md +0 -846
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/conformer.ts +0 -647
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/transcode.ts +0 -67
- package/src/backends/mlx/assistant-target.ts +0 -46
- package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
- package/src/backends/mlx/autoregressive.ts +0 -108
- package/src/backends/mlx/batch-group.ts +0 -1790
- package/src/backends/mlx/cache-attachment.ts +0 -67
- package/src/backends/mlx/cache-layout.ts +0 -31
- package/src/backends/mlx/checkpoint-state.ts +0 -53
- package/src/backends/mlx/continuation-persistence.ts +0 -106
- package/src/backends/mlx/continuation-request.ts +0 -43
- package/src/backends/mlx/continuation.ts +0 -77
- package/src/backends/mlx/diffusion.ts +0 -39
- package/src/backends/mlx/draft-target.ts +0 -32
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -45
- package/src/backends/mlx/full-kv-row-append.ts +0 -32
- package/src/backends/mlx/full-kv-row-donor.ts +0 -54
- package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
- package/src/backends/mlx/gateway-binding.ts +0 -130
- package/src/backends/mlx/graph.ts +0 -38
- package/src/backends/mlx/kv-codec.ts +0 -9
- package/src/backends/mlx/kv-maintenance.ts +0 -133
- package/src/backends/mlx/kv-tensor-rows.ts +0 -212
- package/src/backends/mlx/memory-client.ts +0 -189
- package/src/backends/mlx/methods.ts +0 -90
- package/src/backends/mlx/model-prompt.ts +0 -164
- package/src/backends/mlx/model-serving.ts +0 -79
- package/src/backends/mlx/prefill-cohort.ts +0 -89
- package/src/backends/mlx/prefill-rows.ts +0 -200
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -41
- package/src/backends/mlx/rollback.ts +0 -89
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -242
- package/src/backends/mlx/speculative-group.ts +0 -359
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -114
- package/src/backends/mlx/state-rows.ts +0 -104
- package/src/backends/mlx/state-views.ts +0 -46
- package/src/backends/mlx/target-layout-capability.ts +0 -35
- package/src/backends/mlx/text-engine.ts +0 -73
- package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3168
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -60
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -259
- package/src/contracts/prefix-cache.ts +0 -23
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -45
- package/src/contracts/tsconfig.json +0 -14
- package/src/dataset/generators.ts +0 -1087
- package/src/dataset/index.ts +0 -12
- package/src/dataset/job.ts +0 -81
- package/src/dataset/llm.ts +0 -71
- package/src/dataset/registry.ts +0 -528
- package/src/diffusion/diffusion-generate.ts +0 -507
- package/src/download.ts +0 -505
- package/src/embed.ts +0 -77
- package/src/engine/admission.ts +0 -59
- package/src/engine/cancellation.ts +0 -38
- package/src/engine/engine.ts +0 -56
- package/src/engine/execution-coordinator.ts +0 -70
- package/src/engine/execution-plan.ts +0 -53
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -72
- package/src/engine/session.ts +0 -247
- package/src/eval/README.md +0 -130
- package/src/eval/ifeval.ts +0 -81
- package/src/eval/kl-prompts.ts +0 -29
- package/src/eval/kl.ts +0 -590
- package/src/eval/perplexity.ts +0 -164
- package/src/eval/quality-db.ts +0 -92
- package/src/eval/reference-logits.ts +0 -207
- package/src/eval/runner.ts +0 -124
- package/src/eval/score.ts +0 -49
- package/src/eval/tasks/bfcl.ts +0 -535
- package/src/eval/tasks/gsm8k.ts +0 -98
- package/src/eval/tasks/hashhop.ts +0 -139
- package/src/eval/tasks/humaneval.ts +0 -275
- package/src/eval/tasks/ifeval.ts +0 -525
- package/src/eval/tasks/mmlu.ts +0 -157
- package/src/eval/ultrafeedback.ts +0 -60
- package/src/evaldb.ts +0 -199
- package/src/expert-io.ts +0 -393
- package/src/expert-offload-build.ts +0 -77
- package/src/expert-offload.ts +0 -76
- package/src/expert-residency.ts +0 -1134
- package/src/expert-usage.ts +0 -415
- package/src/fill/echo-index.ts +0 -188
- package/src/fill/fill-session.ts +0 -452
- package/src/fill/proposal.ts +0 -68
- package/src/fill/schema-rows.ts +0 -506
- package/src/fill/tool-boundary.ts +0 -103
- package/src/fit.ts +0 -249
- package/src/generate.ts +0 -1346
- package/src/grammar.ts +0 -591
- package/src/harness-pi.ts +0 -184
- package/src/hf-push.ts +0 -628
- package/src/hub-rest.ts +0 -242
- package/src/index.ts +0 -63
- package/src/inference/denoising.ts +0 -17
- package/src/inference/draft-acceptance.ts +0 -41
- package/src/inference/draft-output.ts +0 -49
- package/src/inference/graph.ts +0 -33
- package/src/inference/prefill.ts +0 -39
- package/src/inference/rollback.ts +0 -7
- package/src/jobs/index.ts +0 -31
- package/src/jobs/job-entry.ts +0 -107
- package/src/jobs/task-client.ts +0 -19
- package/src/jobs/types.ts +0 -2
- package/src/kv-scheme.ts +0 -257
- package/src/kv-store.ts +0 -1099
- package/src/lab/README.md +0 -18
- package/src/lab/curve/curve-designer.html +0 -303
- package/src/lab/curve/curve-sampler.ts +0 -122
- package/src/lab/expert-trace/expert-trace.ts +0 -69
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
- package/src/lab/paged-kv/paged-kv.ts +0 -270
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -49
- package/src/media-fetch.ts +0 -442
- package/src/memory/article.ts +0 -558
- package/src/memory/chunk-validation.ts +0 -150
- package/src/memory/chunk.ts +0 -318
- package/src/memory/cluster.ts +0 -351
- package/src/memory/coverage.ts +0 -134
- package/src/memory/crosslink.ts +0 -0
- package/src/memory/db.ts +0 -253
- package/src/memory/entity.ts +0 -203
- package/src/memory/gate.ts +0 -187
- package/src/memory/history.ts +0 -152
- package/src/memory/ingest.ts +0 -335
- package/src/memory/model.ts +0 -183
- package/src/memory/normalize.ts +0 -671
- package/src/memory/parse.ts +0 -22
- package/src/memory/pipeline.ts +0 -275
- package/src/memory/prompts.ts +0 -65
- package/src/memory/query.ts +0 -334
- package/src/memory/reconcile.ts +0 -734
- package/src/memory/redirect.ts +0 -108
- package/src/memory/reindex.ts +0 -325
- package/src/memory/resolve.ts +0 -307
- package/src/memory/rest.ts +0 -245
- package/src/memory/route.ts +0 -272
- package/src/memory/schedule.ts +0 -165
- package/src/memory/stages.ts +0 -777
- package/src/memory/synthesize.ts +0 -1638
- package/src/memory/tools.ts +0 -749
- package/src/memory/vault.ts +0 -1194
- package/src/memory/wikify.ts +0 -1064
- package/src/mlx/array.ts +0 -388
- package/src/mlx/autograd.ts +0 -304
- package/src/mlx/checkpoint.ts +0 -149
- package/src/mlx/compile.ts +0 -168
- package/src/mlx/custom-vjp.ts +0 -188
- package/src/mlx/ffi.ts +0 -512
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/ops.ts +0 -1021
- package/src/mlx/quantized-rows.ts +0 -36
- package/src/mlx/token-bitmask.ts +0 -52
- package/src/mlx/turboquant-kv-decode.ts +0 -82
- package/src/mlx/turboquant-kv-inverse.ts +0 -122
- package/src/mlx/turboquant-ops.ts +0 -861
- package/src/mlx/turboquant-tables.ts +0 -237
- package/src/mmap.ts +0 -90
- package/src/model/artifact-identity.ts +0 -73
- package/src/model/batched-kv.ts +0 -235
- package/src/model/batched-mask.ts +0 -279
- package/src/model/batched-quant.ts +0 -212
- package/src/model/batched-quantized-kv.ts +0 -144
- package/src/model/batched-rotating-quant.ts +0 -353
- package/src/model/batched-rotating-state.ts +0 -149
- package/src/model/batched-rotating.ts +0 -338
- package/src/model/batched-row-storage.ts +0 -179
- package/src/model/batched-ssm.ts +0 -52
- package/src/model/batched-turboquant-kv.ts +0 -93
- package/src/model/compiled-decode.ts +0 -712
- package/src/model/decoded-kv-donor.ts +0 -12
- package/src/model/delayed-quantized-kv.ts +0 -72
- package/src/model/delayed-rotating-quantized-kv.ts +0 -93
- package/src/model/delayed-turboquant-kv.ts +0 -55
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -189
- package/src/model/fingerprint.ts +0 -33
- package/src/model/flash-attention.ts +0 -694
- package/src/model/full-prefill-padding.ts +0 -56
- package/src/model/full-prefill-row.ts +0 -105
- package/src/model/gemma4-base.ts +0 -2351
- package/src/model/gemma4.ts +0 -1315
- package/src/model/generated/gemma4-12b.ts +0 -429
- package/src/model/generated/gemma4-26b.ts +0 -448
- package/src/model/generated/gemma4-e4b.ts +0 -717
- package/src/model/generated/index.ts +0 -18
- package/src/model/glm52-atlas.ts +0 -511
- package/src/model/glm52-cache.ts +0 -792
- package/src/model/glm52-config.ts +0 -262
- package/src/model/glm52-container.ts +0 -305
- package/src/model/glm52-coupling.ts +0 -388
- package/src/model/glm52-dsa.ts +0 -606
- package/src/model/glm52-expert-layout.ts +0 -253
- package/src/model/glm52-layout.ts +0 -152
- package/src/model/glm52-memory.ts +0 -500
- package/src/model/glm52-mla.ts +0 -792
- package/src/model/glm52-moe.ts +0 -223
- package/src/model/glm52-pilot.ts +0 -537
- package/src/model/glm52-reference.ts +0 -445
- package/src/model/glm52-residency.ts +0 -557
- package/src/model/glm52-resident-weights.ts +0 -135
- package/src/model/glm52-streamed-experts.ts +0 -453
- package/src/model/glm52-streamed-metal.ts +0 -610
- package/src/model/glm52-weights.ts +0 -503
- package/src/model/glm52.ts +0 -1132
- package/src/model/implementation.ts +0 -69
- package/src/model/kv-attention-view.ts +0 -67
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -443
- package/src/model/qwen-append.ts +0 -12
- package/src/model/qwen-conv.ts +0 -52
- package/src/model/qwen3-delta-state.ts +0 -74
- package/src/model/qwen3-delta.ts +0 -451
- package/src/model/qwen3-moe.ts +0 -404
- package/src/model/qwen3-mrope.ts +0 -252
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -819
- package/src/model/rotating-kv-donor.ts +0 -35
- package/src/model/rotating-kv-layout.ts +0 -262
- package/src/model/rotating-row-transaction.ts +0 -35
- package/src/model/speculative-rotating-kv.ts +0 -101
- package/src/model/ssm-prefill-padding.ts +0 -39
- package/src/model/support.ts +0 -102
- package/src/model/trellis-balanced-scatter.ts +0 -51
- package/src/model/trellis-linear.ts +0 -672
- package/src/model/trellis-shared-m.ts +0 -151
- package/src/model/trellis-shared-scatter.ts +0 -144
- package/src/model/trellis-splitk-prefill.ts +0 -158
- package/src/model/trellis-tiled-prefill.ts +0 -136
- package/src/model/trellis-vector-expand.ts +0 -62
- package/src/model/trellis-wide-prefill.ts +0 -94
- package/src/model/turboquant-codec.ts +0 -83
- package/src/model/universal/archs.ts +0 -332
- package/src/model/universal/dense.ts +0 -612
- package/src/model/universal/modules.ts +0 -170
- package/src/model/universal/rope.ts +0 -381
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native-pack.ts +0 -162
- package/src/pi-provider.ts +0 -53
- package/src/pi-session.ts +0 -81
- package/src/pi-terminal.ts +0 -274
- package/src/pi-web.ts +0 -1932
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -460
- package/src/quantize/allocator.ts +0 -627
- package/src/quantize/atomic-output.ts +0 -38
- package/src/quantize/calibration.ts +0 -181
- package/src/quantize/config-writer.ts +0 -145
- package/src/quantize/index.ts +0 -84
- package/src/quantize/job.ts +0 -162
- package/src/quantize/quantizer.ts +0 -666
- package/src/quantize/rotate.ts +0 -603
- package/src/quantize/safetensors-writer.ts +0 -249
- package/src/quantize/sensitivity.ts +0 -216
- package/src/quantize/trellis.ts +0 -586
- package/src/quantize/weight-transform.ts +0 -292
- package/src/registry.ts +0 -602
- package/src/runtime-config.ts +0 -81
- package/src/safetensors.ts +0 -158
- package/src/sampler.ts +0 -1011
- package/src/serve/admin-routes.ts +0 -184
- package/src/serve/assets/curve-terrain.html +0 -105
- package/src/serve/assets/training-inference-map.html +0 -575
- package/src/serve/aux-routes.ts +0 -132
- package/src/serve/batch-scheduler.ts +0 -8
- package/src/serve/checkpoint-identity.ts +0 -64
- package/src/serve/generation-gateway.ts +0 -496
- package/src/serve/isolate.ts +0 -609
- package/src/serve/kv-budget.ts +0 -14
- package/src/serve/lab-routes.ts +0 -341
- package/src/serve/lane-registry.ts +0 -45
- package/src/serve/model-admin-routes.ts +0 -155
- package/src/serve/model-binding.ts +0 -43
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -147
- package/src/serve/response-lease.ts +0 -24
- package/src/serve/session-search.ts +0 -326
- package/src/serve/static-routes.ts +0 -101
- package/src/server.ts +0 -1314
- package/src/spec/assistant-rows.ts +0 -92
- package/src/spec/assistant-source.ts +0 -126
- package/src/spec/cache-identity.ts +0 -22
- package/src/spec/deepspec-rows.ts +0 -29
- package/src/spec/deepspec-source.ts +0 -145
- package/src/spec/dflash-source.ts +0 -149
- package/src/spec/drafter.ts +0 -304
- package/src/spec/dspark/ab-stats.ts +0 -136
- package/src/spec/dspark/calibration.ts +0 -112
- package/src/spec/dspark/data-dflash.ts +0 -156
- package/src/spec/dspark/data.ts +0 -201
- package/src/spec/dspark/deepspec-module.ts +0 -776
- package/src/spec/dspark/generate-dflash.ts +0 -245
- package/src/spec/dspark/generate.ts +0 -290
- package/src/spec/dspark/loader.ts +0 -23
- package/src/spec/dspark/loss.ts +0 -213
- package/src/spec/dspark/module-dflash.ts +0 -560
- package/src/spec/dspark/module.ts +0 -540
- package/src/spec/dspark/quantize-drafter.ts +0 -91
- package/src/spec/dspark/sample.ts +0 -112
- package/src/spec/generate.ts +0 -276
- package/src/spec/glm52-mtp-graph.ts +0 -29
- package/src/spec/glm52-mtp-rows.ts +0 -132
- package/src/spec/glm52-mtp-source.ts +0 -317
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -204
- package/src/spec/projected-draft-rows.ts +0 -73
- package/src/spec/qwen-mtp-module.ts +0 -171
- package/src/spec/qwen-mtp-rows.ts +0 -219
- package/src/spec/qwen-mtp-source.ts +0 -383
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -585
- package/src/spec/source.ts +0 -215
- package/src/spec/two-model-rows.ts +0 -61
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -372
- package/src/ssd-durability.ts +0 -211
- package/src/tokenizer.ts +0 -335
- package/src/tool-approvals.ts +0 -131
- package/src/tool-call.ts +0 -695
- package/src/train/dataset.ts +0 -484
- package/src/train/diffusion-lora.ts +0 -216
- package/src/train/export.ts +0 -32
- package/src/train/flash-cce.ts +0 -1234
- package/src/train/forward.ts +0 -266
- package/src/train/fuse.ts +0 -243
- package/src/train/index.ts +0 -46
- package/src/train/job.ts +0 -205
- package/src/train/lora-params.ts +0 -254
- package/src/train/loss.ts +0 -1591
- package/src/train/merge.ts +0 -195
- package/src/train/optimizer.ts +0 -183
- package/src/train/prefix-shared.ts +0 -490
- package/src/train/rank.ts +0 -137
- package/src/train/segmented.ts +0 -1828
- package/src/train/steel-qmm-header.ts +0 -1461
- package/src/train/trainer.ts +0 -1221
- package/src/train/watch.ts +0 -542
- package/src/vision/diffusion-vision.ts +0 -620
- package/src/vision/embedder.ts +0 -168
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -373
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -196
- package/src/vision/qwen3vl-tower.ts +0 -555
- package/src/vision/siglip.ts +0 -599
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2143
- package/src/web/app.js +0 -5703
- package/src/web/skills/memory/SKILL.md +0 -120
- package/src/web/skills/web-research/SKILL.md +0 -46
- package/src/web/skills.ts +0 -97
- package/src/web/src/adapters-panel.ts +0 -288
- package/src/web/src/assistant.ts +0 -451
- package/src/web/src/chat.ts +0 -1057
- package/src/web/src/composer.ts +0 -959
- package/src/web/src/dataset.ts +0 -132
- package/src/web/src/finetune.ts +0 -267
- package/src/web/src/hub.ts +0 -428
- package/src/web/src/main.ts +0 -98
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +0 -572
- package/src/web/src/model-picker.ts +0 -159
- package/src/web/src/palette.ts +0 -346
- package/src/web/src/protocol.ts +0 -26
- package/src/web/src/quantize.ts +0 -167
- package/src/web/src/rag.ts +0 -274
- package/src/web/src/sessions.ts +0 -469
- package/src/web/src/shell.ts +0 -804
- package/src/web/src/ui-catalog.ts +0 -78
- package/src/web/vendor/README.md +0 -61
- package/src/web-assets.ts +0 -47
- package/src/web-tools.ts +0 -478
- package/src/weights.ts +0 -255
- /package/src/{serve → server}/completion-sink.ts +0 -0
- /package/src/web/{icon.svg → public/icon.svg} +0 -0
- /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
- /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { KvDonorAttention } from "./gemma4-base";
|
|
2
|
-
import { BatchedRotatingState } from "./batched-rotating-state";
|
|
3
|
-
import { BatchedRotatingQuantCache } from "./batched-rotating-quant";
|
|
4
|
-
import { plainRowStorage, quantizedRowStorage, temporalStorageView } from "./batched-row-storage";
|
|
5
|
-
import { quantizedDonorAttention } from "./kv-attention-view";
|
|
6
|
-
import { decodedKvDonorAttention } from "./decoded-kv-donor";
|
|
7
|
-
import type { RotatingRing } from "./rotating-row-transaction";
|
|
8
|
-
|
|
9
|
-
/** Capture the same chronological donor rectangle for plain and encoded rings. */
|
|
10
|
-
export function captureRotatingDonorAttention(ring: RotatingRing): KvDonorAttention {
|
|
11
|
-
const position = new BatchedRotatingState(ring.maxSize, []);
|
|
12
|
-
position.restore(ring.positionSnapshot);
|
|
13
|
-
const offsets = position.offsets.map((_, row) => position.validOffset(row));
|
|
14
|
-
const ends = offsets.map((offset, row) => position.activeLength - (position.offsets[row]! - offset));
|
|
15
|
-
// Pending prefill keeps a shared physical rectangle, including when mixed
|
|
16
|
-
// rows are captured separately. Cropping from each row's valid end would
|
|
17
|
-
// give siblings different widths and can discard an earlier valid window.
|
|
18
|
-
const from = position.hasPendingPadding ? 0 : Math.max(0, position.activeLength - ring.maxSize);
|
|
19
|
-
const range = { from, to: position.activeLength };
|
|
20
|
-
const validity = { offsets,
|
|
21
|
-
starts: position.leftPad.map((pad, row) => Math.max(0, pad - from, ends[row]! - from - ring.maxSize)),
|
|
22
|
-
ends: ends.map(end => Math.max(0, end - from)) };
|
|
23
|
-
if (ring instanceof BatchedRotatingQuantCache) {
|
|
24
|
-
const keys = temporalStorageView(quantizedRowStorage, ring.keys!, position, range);
|
|
25
|
-
let values: import("../mlx/ops").QuantizedTensor;
|
|
26
|
-
try { values = temporalStorageView(quantizedRowStorage, ring.values!, position, range); }
|
|
27
|
-
catch (error) { quantizedRowStorage.dispose(keys); throw error; }
|
|
28
|
-
return quantizedDonorAttention(keys, values, validity, ring.groupSize, ring.bits);
|
|
29
|
-
}
|
|
30
|
-
const keys = temporalStorageView(plainRowStorage, ring.keys!, position, range);
|
|
31
|
-
let values: import("../mlx/array").MlxArray;
|
|
32
|
-
try { values = temporalStorageView(plainRowStorage, ring.values!, position, range); }
|
|
33
|
-
catch (error) { keys.dispose(); throw error; }
|
|
34
|
-
return decodedKvDonorAttention({ keys, values, ...validity });
|
|
35
|
-
}
|
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import { MlxArray } from "../mlx/array";
|
|
2
|
-
import * as ops from "../mlx/ops";
|
|
3
|
-
import { cloneKvCaches } from "../kv-store";
|
|
4
|
-
import { type BatchableCache, type Cache, type Mask, type PaddedPrefillCache, type PrefillPadding, RotatingKVCache, RotatingQuantizedKVCache } from "./gemma4-base";
|
|
5
|
-
import { BatchedRotatingCache, buildBatchedRotatingMask } from "./batched-rotating";
|
|
6
|
-
import { BatchedRotatingQuantCache } from "./batched-rotating-quant";
|
|
7
|
-
import { BatchedRotatingState, type RotatingPositionSnapshot } from "./batched-rotating-state";
|
|
8
|
-
import { plainRowStorage, quantizedRowStorage, temporalStorageView } from "./batched-row-storage";
|
|
9
|
-
import type { TransitioningKvPositions, TransitionedKvLayout } from "../backends/mlx/transitioning-kv-rows";
|
|
10
|
-
import { captureRotatingDonorAttention } from "./rotating-kv-donor";
|
|
11
|
-
|
|
12
|
-
import { rollbackRotatingRing } from "./rotating-row-transaction";
|
|
13
|
-
|
|
14
|
-
const fields = ["packed", "scales", "biases"] as const;
|
|
15
|
-
type Ring = BatchedRotatingCache | BatchedRotatingQuantCache;
|
|
16
|
-
|
|
17
|
-
function combinedPosition(rings: readonly Ring[]): RotatingPositionSnapshot {
|
|
18
|
-
const states = rings.map(ring => ring.positionSnapshot);
|
|
19
|
-
return { ...states[0]!, offsets: states.map(state => state.offsets[0]!),
|
|
20
|
-
leftPad: states.map(state => state.leftPad[0]!),
|
|
21
|
-
prefillEnds: states[0]!.prefillEnds
|
|
22
|
-
? states.map(state => state.prefillEnds![0]!) : undefined };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** One logical request with the group's physical ring geometry. This keeps
|
|
26
|
-
* masks stable while different requests cross their precision boundary. */
|
|
27
|
-
export class AlignedRotatingCache implements Cache {
|
|
28
|
-
minimumReusableOffset = 0;
|
|
29
|
-
constructor(public inner: Ring) {}
|
|
30
|
-
get offset(): number { return this.inner.validOffset(0); }
|
|
31
|
-
get affineConversion(): AlignedRotatingCache | undefined { return this.inner instanceof BatchedRotatingCache ? this : undefined; }
|
|
32
|
-
get quantizedAttention() { return this.inner instanceof BatchedRotatingQuantCache ? this.inner : undefined; }
|
|
33
|
-
signature(): string { return this.inner.signature(); }
|
|
34
|
-
captureDonorAttention() { return captureRotatingDonorAttention(this.inner); }
|
|
35
|
-
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] { return this.inner.updateAndFetch(k, v); }
|
|
36
|
-
makeMask(tokens: number, window: number | null): Mask { return this.inner.makeMask(tokens, window); }
|
|
37
|
-
isTrimmable(): boolean { return this.inner.positionSnapshot.totalOffset < this.inner.maxSize; }
|
|
38
|
-
trim(count: number): void { this.inner.trim(count); }
|
|
39
|
-
rollback(before: number, keep: number, preserveColumns: boolean): void {
|
|
40
|
-
this.inner = rollbackRotatingRing(this.inner, [before], keep, preserveColumns);
|
|
41
|
-
}
|
|
42
|
-
state(): MlxArray[] { return this.inner.state(); }
|
|
43
|
-
bytesPerToken(): number {
|
|
44
|
-
const state = this.state(), tokens = state[0]?.shape[2] ?? 0;
|
|
45
|
-
return tokens ? state.reduce((n, a) => n + a.nbytes, 0) / tokens : 0;
|
|
46
|
-
}
|
|
47
|
-
dispose(): void { this.inner.dispose(); }
|
|
48
|
-
extract(limit?: number): Cache {
|
|
49
|
-
const row = this.inner.extractRow(0, limit) ?? (this.inner instanceof BatchedRotatingQuantCache
|
|
50
|
-
? new RotatingQuantizedKVCache(this.inner.maxSize, this.inner.groupSize, this.inner.bits)
|
|
51
|
-
: new RotatingKVCache(this.inner.maxSize));
|
|
52
|
-
row.minimumReusableOffset = this.minimumReusableOffset;
|
|
53
|
-
return row;
|
|
54
|
-
}
|
|
55
|
-
toQuantized(groupSize: number, bits: number): AlignedRotatingCache {
|
|
56
|
-
const plain = this.inner as BatchedRotatingCache;
|
|
57
|
-
const keys = ops.quantize(plain.keys!, groupSize, bits);
|
|
58
|
-
let values: ops.QuantizedTensor;
|
|
59
|
-
try { values = ops.quantize(plain.values!, groupSize, bits); }
|
|
60
|
-
catch (error) { quantizedRowStorage.dispose(keys); throw error; }
|
|
61
|
-
const next = new AlignedRotatingCache(BatchedRotatingQuantCache.adoptPhysical(keys, values, groupSize, bits, plain.positionSnapshot));
|
|
62
|
-
next.minimumReusableOffset = this.minimumReusableOffset;
|
|
63
|
-
this.dispose();
|
|
64
|
-
return next;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Borrow the newest valid window from a solo cache, including a temporary
|
|
69
|
-
* oversized block. No dequantization or physical-ring normalization in place. */
|
|
70
|
-
export function rotatingSourcePosition(row: RotatingKVCache | RotatingQuantizedKVCache): BatchedRotatingState {
|
|
71
|
-
const state = new BatchedRotatingState(row.maxSize, [0], [row.offset]);
|
|
72
|
-
const length = row instanceof RotatingKVCache ? row.keys?.shape[2] ?? 0 : row.keys?.packed.shape[2] ?? 0;
|
|
73
|
-
state.restore({ maxSize: row.maxSize, offsets: [row.offset], leftPad: [0], totalOffset: row.offset,
|
|
74
|
-
ringIndex: row.ringIdx, rotated: row.ringIdx < row.offset && row.ringIdx < length });
|
|
75
|
-
return state;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Take ownership of solo rows and align them once at membership changes. */
|
|
79
|
-
export function alignRotatingRows(rows: Cache[]): AlignedRotatingCache[] {
|
|
80
|
-
const width = Math.max(0, ...rows.map(row => Math.min(row.offset, (row as RotatingKVCache).maxSize)));
|
|
81
|
-
const prototype = rows.find(row => row.state().length > 0) as RotatingKVCache | RotatingQuantizedKVCache | undefined;
|
|
82
|
-
const emptyPlane = (field: "keys" | "values"): MlxArray | null => {
|
|
83
|
-
if (!width || !prototype) return null;
|
|
84
|
-
const tensor = prototype[field]!;
|
|
85
|
-
if (tensor instanceof MlxArray) return ops.zeros([1, tensor.shape[1]!, width, tensor.shape[3]!], tensor.dtype);
|
|
86
|
-
return ops.zeros([1, tensor.packed.shape[1]!, width, tensor.packed.shape[3]! * 32 / (prototype as RotatingQuantizedKVCache).bits], tensor.scales.dtype);
|
|
87
|
-
};
|
|
88
|
-
const result: AlignedRotatingCache[] = [];
|
|
89
|
-
try {
|
|
90
|
-
for (const source of rows) {
|
|
91
|
-
if (!(source instanceof RotatingKVCache || source instanceof RotatingQuantizedKVCache))
|
|
92
|
-
throw new Error(`rotating layout cannot adopt ${source.signature()}`);
|
|
93
|
-
const length = Math.min(source.offset, source.maxSize), pad = width - length;
|
|
94
|
-
const position: RotatingPositionSnapshot = { maxSize: source.maxSize, offsets: [source.offset], leftPad: [pad],
|
|
95
|
-
totalOffset: width, ringIndex: width, rotated: false };
|
|
96
|
-
const state = rotatingSourcePosition(source);
|
|
97
|
-
const options = { from: Math.max(0, state.activeLength - length), to: state.activeLength };
|
|
98
|
-
let inner: Ring;
|
|
99
|
-
if (source instanceof RotatingKVCache) {
|
|
100
|
-
using k = source.keys ? temporalStorageView(plainRowStorage, source.keys, state, options) : null;
|
|
101
|
-
using v = source.values ? temporalStorageView(plainRowStorage, source.values, state, options) : null;
|
|
102
|
-
const keys = k ? plainRowStorage.padLeft(k, pad) : emptyPlane("keys");
|
|
103
|
-
let values: MlxArray | null;
|
|
104
|
-
try { values = v ? plainRowStorage.padLeft(v, pad) : emptyPlane("values"); }
|
|
105
|
-
catch (error) { keys?.dispose(); throw error; }
|
|
106
|
-
inner = BatchedRotatingCache.adoptPhysical(keys, values, position);
|
|
107
|
-
} else {
|
|
108
|
-
const k = source.keys ? temporalStorageView(quantizedRowStorage, source.keys, state, options) : null;
|
|
109
|
-
const v = source.values ? temporalStorageView(quantizedRowStorage, source.values, state, options) : null;
|
|
110
|
-
const empty = (field: "keys" | "values") => {
|
|
111
|
-
using tensor = emptyPlane(field);
|
|
112
|
-
return tensor ? ops.quantize(tensor, source.groupSize, source.bits) : null;
|
|
113
|
-
};
|
|
114
|
-
try {
|
|
115
|
-
const keys = k ? quantizedRowStorage.padLeft(k, pad) : empty("keys");
|
|
116
|
-
let values: ops.QuantizedTensor | null;
|
|
117
|
-
try { values = v ? quantizedRowStorage.padLeft(v, pad) : empty("values"); }
|
|
118
|
-
catch (error) { if (keys) quantizedRowStorage.dispose(keys); throw error; }
|
|
119
|
-
inner = BatchedRotatingQuantCache.adoptPhysical(keys, values, source.groupSize, source.bits, position);
|
|
120
|
-
} finally { if (k) quantizedRowStorage.dispose(k); if (v) quantizedRowStorage.dispose(v); }
|
|
121
|
-
}
|
|
122
|
-
const row = new AlignedRotatingCache(inner); row.minimumReusableOffset = source.minimumReusableOffset ?? 0;
|
|
123
|
-
result.push(row);
|
|
124
|
-
}
|
|
125
|
-
} catch (error) { for (const row of result) row.dispose(); throw error; }
|
|
126
|
-
for (const row of rows) row.dispose();
|
|
127
|
-
return result;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Position state has no codec or attention arithmetic. */
|
|
131
|
-
export class RotatingKvPositions implements TransitioningKvPositions {
|
|
132
|
-
#state: BatchedRotatingState;
|
|
133
|
-
#rope?: MlxArray;
|
|
134
|
-
constructor(maxSize: number) { this.#state = new BatchedRotatingState(maxSize, []); }
|
|
135
|
-
get rowOffsets(): readonly number[] { return this.#state.offsets; }
|
|
136
|
-
get leftPad(): readonly number[] { return this.#state.leftPad; }
|
|
137
|
-
get offset(): number { return this.#state.totalOffset; }
|
|
138
|
-
get batchSize(): number | null { return this.#state.batchSize || null; }
|
|
139
|
-
get ropeOffsetArr(): MlxArray | undefined {
|
|
140
|
-
if (!this.batchSize) return undefined;
|
|
141
|
-
return this.#rope ??= ops.fromInt32([...this.rowOffsets], [this.batchSize]);
|
|
142
|
-
}
|
|
143
|
-
sync(rows: readonly Cache[]): void {
|
|
144
|
-
this.#rope?.dispose(); this.#rope = undefined;
|
|
145
|
-
if (!rows.length) { this.#state = new BatchedRotatingState(this.#state.maxSize, []); return; }
|
|
146
|
-
this.#state.restore(combinedPosition(rows.map(row => (row as AlignedRotatingCache).inner)));
|
|
147
|
-
}
|
|
148
|
-
filterRows(keep: readonly number[]): void { this.#state.filter(keep); this.#rope?.dispose(); this.#rope = undefined; }
|
|
149
|
-
makeMask(tokens: number, window: number | null): Mask {
|
|
150
|
-
return { mode: "array", arr: buildBatchedRotatingMask(this.#state.batchSize, tokens, this.#state.leftPad,
|
|
151
|
-
this.#state.maxSize, window ?? this.#state.maxSize, this.#state.ringIndex, this.#state.totalOffset, this.#state.rotated,
|
|
152
|
-
tokens > 1 || this.#state.hasPendingPadding) };
|
|
153
|
-
}
|
|
154
|
-
dispose(): void { this.#rope?.dispose(); this.#rope = undefined; this.#state = new BatchedRotatingState(this.#state.maxSize, []); }
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** Once all rows use affine storage, concatenate their already-aligned planes
|
|
158
|
-
* without changing ring columns or rebuilding any attention mask. */
|
|
159
|
-
export class RotatingAffineLayout implements TransitionedKvLayout, PaddedPrefillCache {
|
|
160
|
-
#inner?: BatchedRotatingQuantCache;
|
|
161
|
-
#before?: number[];
|
|
162
|
-
#minimum: number[] = [];
|
|
163
|
-
constructor(readonly maxSize: number, readonly groupSize: number, readonly bits: number) {}
|
|
164
|
-
get minimumReusableOffset(): number { return Math.max(0, ...this.#minimum); }
|
|
165
|
-
get quantizedAttention() { return this.#inner; }
|
|
166
|
-
captureDonorAttention(): import("./gemma4-base").KvDonorAttention {
|
|
167
|
-
return captureRotatingDonorAttention(this.#inner!);
|
|
168
|
-
}
|
|
169
|
-
get rowOffsets(): readonly number[] { return this.#inner?.offsetArr ?? []; }
|
|
170
|
-
get leftPad(): readonly number[] { return this.#inner?.leftPad ?? []; }
|
|
171
|
-
get offset(): number { return this.#inner?.offset ?? 0; }
|
|
172
|
-
get batchSize(): number | null { return this.#inner?.batchSize || null; }
|
|
173
|
-
get ropeOffsetArr(): MlxArray | undefined { return this.#inner?.ropeOffsetArr; }
|
|
174
|
-
get maxTokens(): number { return this.maxSize; }
|
|
175
|
-
signature(): string { return `kv:rotating-affine:${this.maxSize}:${this.groupSize}:${this.bits}`; }
|
|
176
|
-
makeEmptyBatch(): RotatingAffineLayout { return new RotatingAffineLayout(this.maxSize, this.groupSize, this.bits); }
|
|
177
|
-
makeMask(tokens: number, window: number | null): Mask { return this.#inner!.makeMask(tokens, window); }
|
|
178
|
-
preparePrefill(padding: PrefillPadding): void { this.#inner!.preparePrefill(padding); }
|
|
179
|
-
finalizePrefill(): void { this.#inner!.finalizePrefill(); }
|
|
180
|
-
bytesPerToken(): number {
|
|
181
|
-
const tokens = this.#inner?.keys?.packed.shape[2] ?? 0;
|
|
182
|
-
return tokens ? this.state().reduce((n, a) => n + a.nbytes, 0) / (tokens * this.#inner!.batchSize) : 0;
|
|
183
|
-
}
|
|
184
|
-
projectedBytes(tokens: number): number { return this.bytesPerToken() * Math.min(tokens, this.maxSize); }
|
|
185
|
-
isTrimmable(): boolean { return this.#inner!.positionSnapshot.totalOffset < this.maxSize; }
|
|
186
|
-
trim(count: number): void { this.#inner!.trim(count); }
|
|
187
|
-
specRoundBegin(): void { this.#before = [...this.rowOffsets]; }
|
|
188
|
-
specRoundCommit(): void { this.#before = undefined; }
|
|
189
|
-
specRoundRollback(keep: number | readonly number[]): void {
|
|
190
|
-
this.#inner = rollbackRotatingRing(this.#inner!, this.#before!, keep);
|
|
191
|
-
this.#before = undefined;
|
|
192
|
-
}
|
|
193
|
-
updateAndFetch(): [MlxArray, MlxArray] { return this.#inner!.updateAndFetch(); }
|
|
194
|
-
releaseRopeArr(): void { this.#inner?.releaseRopeArr(); }
|
|
195
|
-
mergeRows(rows: readonly Cache[]): void {
|
|
196
|
-
const owned: Cache[] = [];
|
|
197
|
-
try {
|
|
198
|
-
for (const row of rows) {
|
|
199
|
-
if (row instanceof RotatingAffineLayout) {
|
|
200
|
-
for (let i = 0; i < (row.batchSize ?? 0); i++) owned.push(row.extractRow(i));
|
|
201
|
-
} else if (row instanceof AlignedRotatingCache) owned.push(row.extract());
|
|
202
|
-
else owned.push(...cloneKvCaches([row]));
|
|
203
|
-
}
|
|
204
|
-
if (!owned.length) { this.dispose(); return; }
|
|
205
|
-
const aligned = alignRotatingRows(owned); owned.length = 0;
|
|
206
|
-
try { this.adoptAlignedRows(aligned); } finally { for (const row of aligned) row.dispose(); }
|
|
207
|
-
} finally { for (const row of owned) row.dispose(); }
|
|
208
|
-
}
|
|
209
|
-
adoptAlignedRows(rows: readonly AlignedRotatingCache[]): void {
|
|
210
|
-
const rings = rows.map(row => (row as AlignedRotatingCache).inner as BatchedRotatingQuantCache);
|
|
211
|
-
const position = combinedPosition(rings);
|
|
212
|
-
if (rings.every(row => !row.keys)) {
|
|
213
|
-
const empty = BatchedRotatingQuantCache.adoptPhysical(null, null, this.groupSize, this.bits,
|
|
214
|
-
position);
|
|
215
|
-
this.#inner?.dispose(); this.#inner = empty; this.#minimum = rows.map(row => row.minimumReusableOffset ?? 0);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
const merge = (field: "keys" | "values") => {
|
|
219
|
-
const planes: MlxArray[] = [];
|
|
220
|
-
try {
|
|
221
|
-
for (const part of fields) planes.push(ops.concatAxis(rings.map(row => row[field]![part]), 0));
|
|
222
|
-
return { packed: planes[0]!, scales: planes[1]!, biases: planes[2]! };
|
|
223
|
-
} catch (error) { for (const plane of planes) plane.dispose(); throw error; }
|
|
224
|
-
};
|
|
225
|
-
const keys = merge("keys"); let values: ops.QuantizedTensor;
|
|
226
|
-
try { values = merge("values"); } catch (error) { quantizedRowStorage.dispose(keys); throw error; }
|
|
227
|
-
const inner = BatchedRotatingQuantCache.adoptPhysical(keys, values, this.groupSize, this.bits,
|
|
228
|
-
position);
|
|
229
|
-
this.#inner?.dispose(); this.#inner = inner; this.#minimum = rows.map(row => row.minimumReusableOffset ?? 0);
|
|
230
|
-
}
|
|
231
|
-
filterRows(keep: readonly number[]): void { this.#inner!.filterRows(keep); this.#minimum = keep.map(row => this.#minimum[row]!); }
|
|
232
|
-
extractRow(row: number): Cache {
|
|
233
|
-
return this.extract(row);
|
|
234
|
-
}
|
|
235
|
-
protected extract(row: number, limit?: number): Cache {
|
|
236
|
-
const result = this.#inner!.extractRow(row, limit) ?? new RotatingQuantizedKVCache(this.maxSize, this.groupSize, this.bits);
|
|
237
|
-
result.minimumReusableOffset = this.#minimum[row] ?? 0; return result;
|
|
238
|
-
}
|
|
239
|
-
state(): MlxArray[] { return this.#inner?.state() ?? []; }
|
|
240
|
-
dispose(): void { this.#inner?.dispose(); this.#inner = undefined; this.#minimum = []; this.#before = undefined; }
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/** A committed speculative checkpoint contains only the newest valid window. */
|
|
244
|
-
export class SpeculativeRotatingAffineLayout extends RotatingAffineLayout {
|
|
245
|
-
#ropeForOffset = -1;
|
|
246
|
-
override get ropeOffsetArr(): MlxArray | undefined {
|
|
247
|
-
if (this.#ropeForOffset !== this.offset) {
|
|
248
|
-
this.releaseRopeArr(); this.#ropeForOffset = this.offset;
|
|
249
|
-
}
|
|
250
|
-
return super.ropeOffsetArr;
|
|
251
|
-
}
|
|
252
|
-
override makeEmptyBatch(): SpeculativeRotatingAffineLayout {
|
|
253
|
-
return new SpeculativeRotatingAffineLayout(this.maxSize, this.groupSize, this.bits);
|
|
254
|
-
}
|
|
255
|
-
override makeMask(tokens: number, window: number | null): Mask {
|
|
256
|
-
if (this.leftPad.every(pad => pad === 0) &&
|
|
257
|
-
this.offset + tokens <= Math.min(this.maxSize, window ?? this.maxSize))
|
|
258
|
-
return { mode: tokens === 1 ? "" : "causal", arr: null };
|
|
259
|
-
return super.makeMask(tokens, window);
|
|
260
|
-
}
|
|
261
|
-
override extractRow(row: number): Cache { return this.extract(row, this.maxSize); }
|
|
262
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import * as ops from "../mlx/ops";
|
|
2
|
-
import { BatchedRotatingCache } from "./batched-rotating";
|
|
3
|
-
import { BatchedRotatingQuantCache } from "./batched-rotating-quant";
|
|
4
|
-
import { rotatingRollbackPlan } from "./batched-rotating-state";
|
|
5
|
-
import { plainRowStorage, quantizedRowStorage, rowRollIndices } from "./batched-row-storage";
|
|
6
|
-
|
|
7
|
-
export type RotatingRing = BatchedRotatingCache | BatchedRotatingQuantCache;
|
|
8
|
-
|
|
9
|
-
/** Retain accepted columns without decoding or recomputing the ring. Ownership
|
|
10
|
-
* moves to the returned ring; aligned members preserve their shared rectangle. */
|
|
11
|
-
export function rollbackRotatingRing(ring: BatchedRotatingCache, before: readonly number[], keep: number | readonly number[], preserveColumns?: boolean): BatchedRotatingCache;
|
|
12
|
-
export function rollbackRotatingRing(ring: BatchedRotatingQuantCache, before: readonly number[], keep: number | readonly number[], preserveColumns?: boolean): BatchedRotatingQuantCache;
|
|
13
|
-
export function rollbackRotatingRing(ring: RotatingRing, before: readonly number[], keep: number | readonly number[], preserveColumns?: boolean): RotatingRing;
|
|
14
|
-
export function rollbackRotatingRing(ring: RotatingRing, before: readonly number[],
|
|
15
|
-
keep: number | readonly number[], preserveColumns = false): RotatingRing {
|
|
16
|
-
const plan = rotatingRollbackPlan(ring.positionSnapshot, before, keep, preserveColumns);
|
|
17
|
-
if ("trim" in plan) { ring.trim(plan.trim); ring.releaseRopeArr(); return ring; }
|
|
18
|
-
let next: RotatingRing;
|
|
19
|
-
if (ring instanceof BatchedRotatingQuantCache) {
|
|
20
|
-
using indices = rowRollIndices(ring.keys!.packed.shape[2]!, plan.shifts);
|
|
21
|
-
const keys = quantizedRowStorage.rollRows(ring.keys!, indices);
|
|
22
|
-
let values: ops.QuantizedTensor;
|
|
23
|
-
try { values = quantizedRowStorage.rollRows(ring.values!, indices); }
|
|
24
|
-
catch (error) { quantizedRowStorage.dispose(keys); throw error; }
|
|
25
|
-
next = BatchedRotatingQuantCache.adoptPhysical(keys, values, ring.groupSize, ring.bits, plan.position);
|
|
26
|
-
} else {
|
|
27
|
-
using indices = rowRollIndices(ring.keys!.shape[2]!, plan.shifts);
|
|
28
|
-
const keys = plainRowStorage.rollRows(ring.keys!, indices);
|
|
29
|
-
let values: import("../mlx/array").MlxArray;
|
|
30
|
-
try { values = plainRowStorage.rollRows(ring.values!, indices); }
|
|
31
|
-
catch (error) { keys.dispose(); throw error; }
|
|
32
|
-
next = BatchedRotatingCache.adoptPhysical(keys, values, plan.position);
|
|
33
|
-
}
|
|
34
|
-
ring.dispose(); return next;
|
|
35
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { rotatingSourcePosition } from "./rotating-kv-layout";
|
|
2
|
-
import { MlxArray } from "../mlx/array";
|
|
3
|
-
import * as ops from "../mlx/ops";
|
|
4
|
-
import { type BatchableCache, type Cache, type Mask, type PrefillPadding, RotatingKVCache } from "./gemma4-base";
|
|
5
|
-
import { BatchedRotatingCache } from "./batched-rotating";
|
|
6
|
-
import { rollbackRotatingRing } from "./rotating-row-transaction";
|
|
7
|
-
import { BatchedRotatingState } from "./batched-rotating-state";
|
|
8
|
-
import { plainRowStorage, temporalStorageView } from "./batched-row-storage";
|
|
9
|
-
import { disposeResources } from "../engine/resources";
|
|
10
|
-
|
|
11
|
-
/** Ring transactions retain accepted KV columns, including rounds that cross
|
|
12
|
-
* the window boundary. The verify block already retains the complete history
|
|
13
|
-
* needed by its earliest query; no target recomputation or scheduler policy. */
|
|
14
|
-
export class SpeculativeRotatingKVCache implements BatchableCache {
|
|
15
|
-
#inner: BatchedRotatingCache;
|
|
16
|
-
#before?: number[];
|
|
17
|
-
constructor(readonly maxSize: number) { this.#inner = new BatchedRotatingCache(maxSize, []); }
|
|
18
|
-
signature(): string { return "kv:rotating-plain"; }
|
|
19
|
-
get offset(): number { return this.#inner.offset; }
|
|
20
|
-
get rowOffsets(): readonly number[] { return this.#inner.offsetArr; }
|
|
21
|
-
get leftPad(): readonly number[] { return this.#inner.leftPad; }
|
|
22
|
-
get batchSize(): number { return this.#inner.batchSize; }
|
|
23
|
-
get ropeOffsetArr(): MlxArray { return this.#inner.ropeOffsetArr; }
|
|
24
|
-
makeEmptyBatch(): SpeculativeRotatingKVCache { return new SpeculativeRotatingKVCache(this.maxSize); }
|
|
25
|
-
makeMask(tokens: number, window: number | null): Mask { return this.#inner.makeMask(tokens, window); }
|
|
26
|
-
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] { return this.#inner.updateAndFetch(k, v); }
|
|
27
|
-
preparePrefill(padding: PrefillPadding): void { this.#inner.preparePrefill(padding); }
|
|
28
|
-
finalizePrefill(): void { this.#inner.finalizePrefill(); }
|
|
29
|
-
state(): MlxArray[] { return this.#inner.state(); }
|
|
30
|
-
isTrimmable(): boolean { return this.#inner.isTrimmable(); }
|
|
31
|
-
trim(count: number): void { this.#inner.trim(count); }
|
|
32
|
-
bytesPerToken(): number {
|
|
33
|
-
const state = this.state();
|
|
34
|
-
return state.length ? state.reduce((n, a) => n + a.nbytes, 0) / (this.batchSize * state[0]!.shape[2]!) : 0;
|
|
35
|
-
}
|
|
36
|
-
projectedBytes(tokens: number): number { return this.bytesPerToken() * Math.min(tokens, this.maxSize); }
|
|
37
|
-
extractRow(row: number): Cache {
|
|
38
|
-
const result = new RotatingKVCache(this.maxSize);
|
|
39
|
-
if (!this.rowOffsets[row] || !this.#inner.keys || !this.#inner.values) return result;
|
|
40
|
-
const position = new BatchedRotatingState(this.maxSize, []); position.restore(this.#inner.positionSnapshot);
|
|
41
|
-
const range = { row, from: Math.max(0, position.leftPad[row]!, position.activeLength - this.maxSize),
|
|
42
|
-
to: position.activeLength, copy: true };
|
|
43
|
-
const keys = temporalStorageView(plainRowStorage, this.#inner.keys, position, range);
|
|
44
|
-
let values: MlxArray;
|
|
45
|
-
try { values = temporalStorageView(plainRowStorage, this.#inner.values, position, range); }
|
|
46
|
-
catch (error) { keys.dispose(); throw error; }
|
|
47
|
-
result.restoreState(keys, values, this.rowOffsets[row]!, keys.shape[2]!); return result;
|
|
48
|
-
}
|
|
49
|
-
captureDonorRows(): import("./gemma4-base").KvDonorRows {
|
|
50
|
-
const position = new BatchedRotatingState(this.maxSize, []); position.restore(this.#inner.positionSnapshot);
|
|
51
|
-
const from = Math.max(0, position.activeLength - this.maxSize);
|
|
52
|
-
const range = { from, to: position.activeLength };
|
|
53
|
-
const keys = temporalStorageView(plainRowStorage, this.#inner.keys!, position, range); let values: MlxArray;
|
|
54
|
-
try { values = temporalStorageView(plainRowStorage, this.#inner.values!, position, range); }
|
|
55
|
-
catch (error) { keys.dispose(); throw error; }
|
|
56
|
-
return { keys, values, offsets: [...this.rowOffsets], starts: this.leftPad.map(pad => Math.max(0, pad - from)),
|
|
57
|
-
ends: this.rowOffsets.map(() => position.activeLength - from) };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
filterRows(keep: readonly number[]): void { this.#inner.filterRows(keep); }
|
|
61
|
-
mergeRows(sources: readonly Cache[]): void {
|
|
62
|
-
const only = sources.length === 1 ? sources[0] : undefined;
|
|
63
|
-
if (only instanceof SpeculativeRotatingKVCache) {
|
|
64
|
-
const keys = only.#inner.keys ? ops.copyOf(only.#inner.keys) : null;
|
|
65
|
-
let values: MlxArray | null;
|
|
66
|
-
try { values = only.#inner.values ? ops.copyOf(only.#inner.values) : null; }
|
|
67
|
-
catch (error) { keys?.dispose(); throw error; }
|
|
68
|
-
const next = BatchedRotatingCache.adoptPhysical(keys, values, only.#inner.positionSnapshot);
|
|
69
|
-
this.#inner.dispose(); this.#inner = next; return;
|
|
70
|
-
}
|
|
71
|
-
const held: Cache[] = [], planes: { keys: MlxArray; values: MlxArray }[] = [], offsets: number[] = [];
|
|
72
|
-
try {
|
|
73
|
-
const rows = sources.flatMap(source => source instanceof SpeculativeRotatingKVCache
|
|
74
|
-
? Array.from({ length: source.batchSize }, (_, row) => { const cache = source.extractRow(row); held.push(cache); return cache; })
|
|
75
|
-
: [source]) as RotatingKVCache[];
|
|
76
|
-
const prototype = rows.find(row => row.keys !== null);
|
|
77
|
-
if (!prototype) {
|
|
78
|
-
this.#inner.dispose(); this.#inner = new BatchedRotatingCache(this.maxSize, rows.map(() => 0)); return;
|
|
79
|
-
}
|
|
80
|
-
for (const cache of rows) {
|
|
81
|
-
const state = rotatingSourcePosition(cache);
|
|
82
|
-
const range = { from: Math.max(0, state.activeLength - this.maxSize), to: state.activeLength };
|
|
83
|
-
const plane = (field: "keys" | "values") => cache[field]
|
|
84
|
-
? temporalStorageView(plainRowStorage, cache[field]!, state, range)
|
|
85
|
-
: ops.zeros([1, prototype[field]!.shape[1]!, 0, prototype[field]!.shape[3]!], prototype[field]!.dtype);
|
|
86
|
-
const keys = plane("keys"); let values: MlxArray;
|
|
87
|
-
try { values = plane("values"); } catch (error) { keys.dispose(); throw error; }
|
|
88
|
-
planes.push({ keys, values }); offsets.push(cache.offset);
|
|
89
|
-
}
|
|
90
|
-
const next = BatchedRotatingCache.merge(planes, offsets, this.maxSize);
|
|
91
|
-
this.#inner.dispose(); this.#inner = next;
|
|
92
|
-
} finally { disposeResources([...held, ...planes.flatMap(row => [row.keys, row.values])]); }
|
|
93
|
-
}
|
|
94
|
-
specRoundBegin(): void { this.#before = [...this.rowOffsets]; }
|
|
95
|
-
specRoundCommit(): void { this.#before = undefined; }
|
|
96
|
-
specRoundRollback(keep: number | readonly number[]): void {
|
|
97
|
-
this.#inner = rollbackRotatingRing(this.#inner, this.#before!, keep);
|
|
98
|
-
this.#before = undefined;
|
|
99
|
-
}
|
|
100
|
-
dispose(): void { this.#before = undefined; this.#inner.dispose(); }
|
|
101
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { PrefillPadding } from "./gemma4-base";
|
|
2
|
-
import type { MlxArray } from "../mlx/array";
|
|
3
|
-
import { Dtype } from "../mlx/ffi";
|
|
4
|
-
import * as ops from "../mlx/ops";
|
|
5
|
-
|
|
6
|
-
/** ArraysCache's remaining lengths and padding from mlx-lm (MIT).
|
|
7
|
-
* Recurrent state has no token axis to roll: masked tokens must not update it. */
|
|
8
|
-
export class SsmPrefillPadding {
|
|
9
|
-
#left: number[];
|
|
10
|
-
#lengths: number[];
|
|
11
|
-
constructor(padding: PrefillPadding) {
|
|
12
|
-
this.#left = padding.leftPadding ? [...padding.leftPadding] : padding.lengths.map(() => 0);
|
|
13
|
-
this.#lengths = [...padding.lengths];
|
|
14
|
-
}
|
|
15
|
-
convolutionLengths(tokens: number): number[] {
|
|
16
|
-
return this.#lengths.map(length => Math.max(0, Math.min(tokens, length)));
|
|
17
|
-
}
|
|
18
|
-
makeMask(tokens: number): MlxArray {
|
|
19
|
-
const B = this.#lengths.length;
|
|
20
|
-
using arange = ops.arange(0, tokens, 1, Dtype.int32);
|
|
21
|
-
using positions = ops.reshape(arange, [1, tokens]);
|
|
22
|
-
using left = ops.fromInt32(this.#left, [B, 1]);
|
|
23
|
-
using ends = ops.fromInt32(this.#lengths, [B, 1]);
|
|
24
|
-
using after = ops.greaterEqual(positions, left);
|
|
25
|
-
using before = ops.less(positions, ends);
|
|
26
|
-
return ops.logicalAnd(after, before);
|
|
27
|
-
}
|
|
28
|
-
advance(tokens: number): number[] {
|
|
29
|
-
const counts = this.#lengths.map((length, row) => Math.max(0,
|
|
30
|
-
Math.min(tokens, length) - Math.max(0, Math.min(tokens, this.#left[row]!))));
|
|
31
|
-
this.#lengths = this.#lengths.map(length => length - tokens);
|
|
32
|
-
this.#left = this.#left.map(left => left - tokens);
|
|
33
|
-
return counts;
|
|
34
|
-
}
|
|
35
|
-
filter(keep: readonly number[]): void {
|
|
36
|
-
this.#left = keep.map(row => this.#left[row]!);
|
|
37
|
-
this.#lengths = keep.map(row => this.#lengths[row]!);
|
|
38
|
-
}
|
|
39
|
-
}
|
package/src/model/support.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import type { ModelConfig } from "../config";
|
|
2
|
-
import { GENERIC_MODEL_TYPES, genericArgsFor, remapModelType } from "./universal/archs";
|
|
3
|
-
|
|
4
|
-
export function isMiniCPM5Config(config: ModelConfig): boolean {
|
|
5
|
-
const t = config.text;
|
|
6
|
-
return config.modelType === "llama" &&
|
|
7
|
-
t.hiddenSize === 1536 &&
|
|
8
|
-
t.numHiddenLayers === 24 &&
|
|
9
|
-
t.numAttentionHeads === 16 &&
|
|
10
|
-
t.numKeyValueHeads === 2 &&
|
|
11
|
-
t.headDim === 128 &&
|
|
12
|
-
t.vocabSize === 130560 &&
|
|
13
|
-
t.tieWordEmbeddings === false;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** Qwen3.5 hybrid gated-DeltaNet family (model_type qwen3_5 / qwen3_5_text).
|
|
17
|
-
* Dense MLP only for now — the MoE variant (qwen3_5_moe) is deferred. */
|
|
18
|
-
export function isQwen35Config(config: ModelConfig): boolean {
|
|
19
|
-
return (config.modelType === "qwen3_5" || config.modelType === "qwen3_5_text") &&
|
|
20
|
-
!config.text.enableMoeBlock &&
|
|
21
|
-
config.text.numExperts === 0 &&
|
|
22
|
-
config.text.linearNumValueHeads > 0 &&
|
|
23
|
-
config.text.fullAttentionInterval > 0;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Plain Qwen3 (model_type `qwen3`, Qwen3ForCausalLM) — a standard dense decoder
|
|
27
|
-
* with per-head q/k norm and tied embeddings. Used here as the text-embedding
|
|
28
|
-
* backbone (mlx-community Qwen3-Embedding-*). Distinct from the qwen3_5 hybrid. */
|
|
29
|
-
export function isQwen3Config(config: ModelConfig): boolean {
|
|
30
|
-
return config.modelType === "qwen3";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Qwen3-MoE (model_type `qwen3_moe`, Qwen3MoeForCausalLM) — plain-qwen3
|
|
34
|
-
* attention (per-head q/k norm, GQA, RoPE) with a sparse MoE FFN
|
|
35
|
-
* (gate Linear -> precise softmax -> top-k -> renormalize -> SwitchGLU experts
|
|
36
|
-
* with compiled swiglu). Distinct from the qwen3 embedding backbone and the
|
|
37
|
-
* qwen3_5 gated-DeltaNet hybrid. */
|
|
38
|
-
export function isQwen3MoeConfig(config: ModelConfig): boolean {
|
|
39
|
-
return config.modelType === "qwen3_moe";
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** GLM-5.2 Colibri architecture. Its dedicated MLA/DSA/shared-MoE graph is
|
|
43
|
-
* intentionally distinct from the universal dense `glm4` descriptor. */
|
|
44
|
-
export function isGlm52Config(config: ModelConfig): boolean {
|
|
45
|
-
return config.modelType === "glm_moe_dsa";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Speculative-decoding drafters (e.g. `gemma4_assistant`) are companion
|
|
49
|
-
* artifacts to a target model — Q-only, centroid-head, no standalone LM
|
|
50
|
-
* head. They are never servable/selectable on their own (the spec path
|
|
51
|
-
* loads them by explicit path), so they must be excluded from model
|
|
52
|
-
* resolution and the supported-model lists. See src/spec/drafter.ts. */
|
|
53
|
-
export function isDrafterModelType(modelType: string): boolean {
|
|
54
|
-
return modelType.endsWith("_assistant");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** DiffusionGemma (model_type `diffusion_gemma`): block/masked-diffusion canvas
|
|
58
|
-
* model. Non-autoregressive — routed through the diffusion engine, not the AR
|
|
59
|
-
* loop. See docs/design/generic-model-support.md. */
|
|
60
|
-
export function isDiffusionGemmaConfig(config: ModelConfig): boolean {
|
|
61
|
-
return config.modelType === "diffusion_gemma";
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Support tier for a registry record (docs/design/generic-model-support.md):
|
|
65
|
-
* "targeted" = dedicated/generated forward + L2/L3 paths;
|
|
66
|
-
* "generic" = the Tier-0 universal module (L1 monolith only);
|
|
67
|
-
* null = unsupported. Generic never shadows targeted. */
|
|
68
|
-
export function supportTier(modelType: string, repoId = ""): "targeted" | "generic" | null {
|
|
69
|
-
if (isDrafterModelType(modelType)) return null;
|
|
70
|
-
if (modelType.startsWith("gemma4")) return "targeted";
|
|
71
|
-
if (modelType === "diffusion_gemma") return "targeted";
|
|
72
|
-
// qwen3_5 / qwen3_5_text (dense hybrid). The MoE variant is a separate type.
|
|
73
|
-
if (modelType === "qwen3_5" || modelType === "qwen3_5_text") return "targeted";
|
|
74
|
-
if (modelType === "qwen3") return "targeted"; // plain Qwen3 (embedding backbone)
|
|
75
|
-
if (modelType === "qwen3_moe") return "targeted"; // Qwen3-MoE (sparse experts)
|
|
76
|
-
if (modelType === "glm_moe_dsa") return "targeted"; // dedicated GLM-5.2 MLA/DSA port
|
|
77
|
-
if (modelType === "llama" && repoId.toLowerCase().includes("minicpm5-1b-optiq-4bit"))
|
|
78
|
-
return "targeted";
|
|
79
|
-
// Tier-0 generic fallback: the universal-dense descriptor table.
|
|
80
|
-
if (GENERIC_MODEL_TYPES.has(remapModelType(modelType))) return "generic";
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function isSupportedModelRecord(modelType: string, repoId = ""): boolean {
|
|
85
|
-
return supportTier(modelType, repoId) !== null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function isSupportedModelConfig(config: ModelConfig): boolean {
|
|
89
|
-
if (isDrafterModelType(config.modelType)) return false;
|
|
90
|
-
if (
|
|
91
|
-
config.modelType.startsWith("gemma4") || isMiniCPM5Config(config) ||
|
|
92
|
-
isQwen35Config(config) || isQwen3Config(config) || isQwen3MoeConfig(config) ||
|
|
93
|
-
isDiffusionGemmaConfig(config) || isGlm52Config(config)
|
|
94
|
-
) return true;
|
|
95
|
-
// Generic tier: an arch descriptor exists for this model_type (and its
|
|
96
|
-
// config parses — a malformed config is unsupported, not a crash).
|
|
97
|
-
try {
|
|
98
|
-
return genericArgsFor(config) !== null;
|
|
99
|
-
} catch {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// Experimental variant 8, k=3 / T=256 / L<=12 only.
|
|
2
|
-
// The word-per-lane kernel uses 24 of 32 SIMD lanes for a 3-bit block.
|
|
3
|
-
// Assign eight outputs to every lane, load adjacent packed words, and align
|
|
4
|
-
// them once so each unrolled decoder has constant shifts. Row accumulation,
|
|
5
|
-
// split boundaries and the separate partial reduction stay identical to v6.
|
|
6
|
-
export const BALANCED_SCATTER_SOURCE = String.raw`
|
|
7
|
-
const uint lane = thread_index_in_simdgroup;
|
|
8
|
-
const uint sg = simdgroup_index_in_threadgroup;
|
|
9
|
-
const uint block = thread_position_in_grid.y * (uint)SG_TG + sg;
|
|
10
|
-
const uint nBlocks = (uint)C / (uint)BT;
|
|
11
|
-
const uint zi = thread_position_in_grid.z;
|
|
12
|
-
const uint sample = zi / (uint)SPLITS;
|
|
13
|
-
const uint split = zi - sample * (uint)SPLITS;
|
|
14
|
-
if (block >= nBlocks || sample >= (uint)M) return;
|
|
15
|
-
const uint wpb = (uint)(BT * K / 32);
|
|
16
|
-
const ulong rowWords = (ulong)(INTERLEAVE ? 2 : nBlocks) * wpb;
|
|
17
|
-
const uint pBase = lane * 8u * (uint)K;
|
|
18
|
-
const uint wi = pBase >> 5u;
|
|
19
|
-
const uint off = pBase & 31u;
|
|
20
|
-
const uint next = (wi + 1u == wpb) ? 0u : wi + 1u;
|
|
21
|
-
const device uint32_t* words = codes + (INTERLEAVE
|
|
22
|
-
? (ulong)(block / 2) * R * 2 * wpb + (block % 2) * wpb : (ulong)block * wpb);
|
|
23
|
-
const uint rowsPer = ((uint)R + (uint)SPLITS - 1u) / (uint)SPLITS;
|
|
24
|
-
const uint r0 = split * rowsPer;
|
|
25
|
-
const uint r1 = metal::min((uint)R, r0 + rowsPer);
|
|
26
|
-
const device T* xs = x + (ulong)sample * (ulong)R;
|
|
27
|
-
float acc[8];
|
|
28
|
-
#pragma clang loop unroll(full)
|
|
29
|
-
for (uint i = 0; i < 8u; ++i) acc[i] = 0.0f;
|
|
30
|
-
for (uint r = r0; r < r1; ++r) {
|
|
31
|
-
const uint word = words[(ulong)r * rowWords + wi];
|
|
32
|
-
const uint nxt = words[(ulong)r * rowWords + next];
|
|
33
|
-
const uint lo = off == 0u ? word : (word >> off) | (nxt << (32u - off));
|
|
34
|
-
const uint hi = off == 0u ? nxt : nxt >> off;
|
|
35
|
-
const float xr = float(xs[r]);
|
|
36
|
-
const float sr = float(scales[r]);
|
|
37
|
-
#pragma clang loop unroll(full)
|
|
38
|
-
for (uint i = 0; i < 8u; ++i) {
|
|
39
|
-
const uint shift = i * (uint)K;
|
|
40
|
-
uint win = lo >> shift;
|
|
41
|
-
if (shift + (uint)L > 32u) win |= hi << (32u - shift);
|
|
42
|
-
win &= (1u << (uint)L) - 1u;
|
|
43
|
-
const float value = (float)trellis_y(win) * (1.0f / 147.800537109375f);
|
|
44
|
-
acc[i] = metal::fma(value * sr, xr, acc[i]);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const ulong outBase = ((ulong)sample * (ulong)SPLITS + split) * (ulong)C;
|
|
48
|
-
#pragma clang loop unroll(full)
|
|
49
|
-
for (uint i = 0; i < 8u; ++i)
|
|
50
|
-
partial[outBase + block * (uint)BT + (uint)BT - 1u - lane * 8u - i] = acc[i];
|
|
51
|
-
`;
|