mlx-bun 0.5.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 +1449 -109
- 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 +7 -5
- 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 +10 -10
- package/src/{serve → server}/chat-stage.ts +14 -14
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +33 -41
- 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 +25 -82
- 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 +6 -8
- package/src/{serve → server}/request-prep.ts +47 -50
- 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 -107
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +0 -3617
- 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/release-notes-v0.4.0.md +0 -45
- package/docs/archive/planning/release-notes-v0.5.0.md +0 -37
- 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 -2054
- package/docs/design/decode-speed-program.md +0 -2404
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -821
- package/docs/design/kv-cache.md +0 -993
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -2129
- package/docs/design/turboquant.md +0 -2225
- package/docs/design/unified-engine-frontier-plan.md +0 -1987
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -593
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/public-readiness-handoff.md +0 -244
- package/docs/planning/public-readiness.md +0 -149
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3587
- package/docs/reference/cli.md +0 -646
- package/docs/reference/distribution.md +0 -380
- package/docs/reference/environment.md +0 -494
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -688
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -346
- package/docs/reference/server-api.md +0 -1945
- package/docs/reference/server-config.md +0 -973
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/audiotoolbox.ts +0 -112
- package/src/audio/conformer.ts +0 -655
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/mic-capture.ts +0 -98
- package/src/audio/silero-vad.ts +0 -379
- package/src/audio/transcode.ts +0 -67
- package/src/audio/whisper-decode.ts +0 -774
- package/src/audio/whisper-fast.ts +0 -732
- package/src/audio/whisper-format.ts +0 -73
- package/src/audio/whisper-mel.ts +0 -185
- package/src/audio/whisper-timing.ts +0 -274
- package/src/audio/whisper-tokenizer.ts +0 -239
- package/src/audio/whisper-transcribe.ts +0 -410
- 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 -129
- package/src/backends/mlx/batch-group.ts +0 -1874
- 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 -107
- 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/encoder-cache.ts +0 -25
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -58
- package/src/backends/mlx/fill-group.ts +0 -497
- 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 -174
- 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 -161
- 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/mixed-iteration.ts +0 -62
- package/src/backends/mlx/model-prompt.ts +0 -178
- package/src/backends/mlx/model-serving.ts +0 -80
- package/src/backends/mlx/paged-cache-codec.ts +0 -27
- package/src/backends/mlx/prefill-cohort.ts +0 -100
- package/src/backends/mlx/prefill-policy.ts +0 -26
- package/src/backends/mlx/prefill-rows.ts +0 -244
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/prompt-input.ts +0 -29
- package/src/backends/mlx/qwen-prompt-input.ts +0 -40
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -54
- package/src/backends/mlx/rollback.ts +0 -92
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -251
- package/src/backends/mlx/speculative-group.ts +0 -438
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -131
- 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 -173
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3490
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -70
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/object-cache.ts +0 -8
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -261
- package/src/contracts/prefix-cache.ts +0 -33
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -54
- 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 -64
- package/src/engine/execution-tasks.ts +0 -44
- package/src/engine/namespaced-cache.ts +0 -13
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -92
- 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 -463
- 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 -1352
- package/src/grammar.ts +0 -604
- 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 -45
- 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 -279
- package/src/kv-store.ts +0 -1135
- package/src/lab/README.md +0 -22
- 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-attention.ts +0 -117
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -111
- package/src/lab/paged-kv/paged-kv.ts +0 -336
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -54
- 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 -425
- 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 -531
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/normalized-argmax.ts +0 -116
- package/src/mlx/ops.ts +0 -1108
- 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 -94
- 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 -57
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -215
- package/src/model/fingerprint.ts +0 -45
- 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 -2370
- package/src/model/gemma4.ts +0 -1395
- 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 -70
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -468
- package/src/model/quantized-append-attention.ts +0 -31
- 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 -250
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -881
- 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 -110
- package/src/model/token-groups.ts +0 -66
- 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 -89
- 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/model/whisper.ts +0 -435
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native/mic_capture.swift +0 -92
- package/src/native-pack.ts +0 -163
- 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 -1940
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -682
- 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 -77
- package/src/safetensors.ts +0 -165
- package/src/sampler.ts +0 -1012
- 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/audio-routes.ts +0 -323
- 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 -537
- 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 -49
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -161
- 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/serve/transcription-server.ts +0 -64
- package/src/serve/transcription-service.ts +0 -502
- package/src/server.ts +0 -1282
- package/src/spec/assistant-rows.ts +0 -93
- 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 -318
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -226
- 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 -230
- package/src/spec/qwen-mtp-source.ts +0 -386
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -587
- package/src/spec/source.ts +0 -228
- package/src/spec/two-model-rows.ts +0 -62
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -431
- package/src/ssd-durability.ts +0 -209
- package/src/storage/host-buffer.ts +0 -24
- package/src/storage/kv-writer.ts +0 -83
- package/src/storage/kv-writer.worker.js +0 -264
- package/src/storage/retention-policy.ts +0 -37
- package/src/tiered-prompt-cache.ts +0 -45
- 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 -176
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -409
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -233
- package/src/vision/qwen3vl-tower.ts +0 -566
- package/src/vision/siglip.ts +0 -607
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2155
- package/src/web/app.js +0 -5863
- 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 -1060
- package/src/web/src/composer.ts +0 -962
- 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/src/voice.ts +0 -141
- 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/{serve → server}/generated-token-history.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
package/src/model/qwen3_5.ts
DELETED
|
@@ -1,881 +0,0 @@
|
|
|
1
|
-
// Concrete model graph for Qwen3.5 hybrid models (e.g. Qwen3.6-27B-OptiQ-4bit).
|
|
2
|
-
// Port target: mlx_lm.models.qwen3_5 (+ qwen3_next Attention/MLP/RMSNormGated,
|
|
3
|
-
// gated_delta recurrence). The architecture is a 64-layer stack where every
|
|
4
|
-
// `fullAttentionInterval`-th layer is standard softmax attention and the rest
|
|
5
|
-
// are gated-DeltaNet linear-attention layers. Weights carry a
|
|
6
|
-
// `language_model.` prefix.
|
|
7
|
-
//
|
|
8
|
-
// Parity bars: bf16 KV → bit-exact vs mlx-lm; mixed-precision KV → bit-exact vs
|
|
9
|
-
// mlx-optiq (the 16 full-attention layers quantized per kv_config.json, via the
|
|
10
|
-
// shared maybeQuantizeKv path).
|
|
11
|
-
|
|
12
|
-
import type { ModelConfig } from "../config";
|
|
13
|
-
import { quantizedAppendAttention } from "./quantized-append-attention";
|
|
14
|
-
import { gatedDeltaState } from "./qwen3-delta-state";
|
|
15
|
-
import type { Weights } from "../weights";
|
|
16
|
-
import { runtimeFlag } from "../runtime-config";
|
|
17
|
-
import { mapTokenGroups, type TokenGroup } from "./token-groups";
|
|
18
|
-
import { MlxArray } from "../mlx/array";
|
|
19
|
-
import { Dtype, deviceArchitecture } from "../mlx/ffi";
|
|
20
|
-
import * as ops from "../mlx/ops";
|
|
21
|
-
import { CompiledFunction } from "../mlx/compile";
|
|
22
|
-
import { qwenAppendChunkSize } from "./qwen-append";
|
|
23
|
-
import { TrellisLinear, fusedGateUpEligible, fusedGateUpSwiglu, TRELLIS_MATVEC_MAX_M } from "./trellis-linear";
|
|
24
|
-
import {
|
|
25
|
-
argmaxLastPosition,
|
|
26
|
-
disposeTriple,
|
|
27
|
-
disposing,
|
|
28
|
-
KVCache,
|
|
29
|
-
LoraState,
|
|
30
|
-
QuantizedEmbedding,
|
|
31
|
-
QuantizedLinear,
|
|
32
|
-
quantizedSdpa,
|
|
33
|
-
RMSNorm,
|
|
34
|
-
type Cache,
|
|
35
|
-
type Mask,
|
|
36
|
-
} from "./gemma4-base";
|
|
37
|
-
import { qwen35WeightsView } from "./qwen3_5-checkpoint";
|
|
38
|
-
import { materializeCopy } from "../mlx/materialize";
|
|
39
|
-
import { gatedDeltaUpdate, SSMCache } from "./qwen3-delta";
|
|
40
|
-
import type { QwenConvolution } from "./qwen-conv";
|
|
41
|
-
import {
|
|
42
|
-
applyInterleavedRope, buildMropePositions, mropeInvFreq,
|
|
43
|
-
type MropeRequestState, type MropeForwardState,
|
|
44
|
-
} from "./qwen3-mrope";
|
|
45
|
-
|
|
46
|
-
const PREFIX = "language_model";
|
|
47
|
-
|
|
48
|
-
// ── Compiled activations ─────────────────────────────────────────────────────
|
|
49
|
-
// The oracle (mlx_lm/models/activations.py + qwen3_next.py) wraps BOTH swiglu
|
|
50
|
-
// activations in `@partial(mx.compile, shapeless=True)`. We match it: every
|
|
51
|
-
// activation site below (the MLP swiglu, the RMSNormGated `_precise_swiglu`, and
|
|
52
|
-
// the conv `nn.silu`) runs through a compiled closure unconditionally, so the
|
|
53
|
-
// dispatched kernel set matches the oracle op-for-op (= mlx-lm, bit-exact). Traced
|
|
54
|
-
// once (shapeless), replayed thereafter; autograd-safe (mx.compile threads VJP
|
|
55
|
-
// through the traced graph). `compiledSwiglu` is exported so the parity test can
|
|
56
|
-
// assert the closure exists and the MLP actually uses it.
|
|
57
|
-
|
|
58
|
-
/** activations.py: `@mx.compile def swiglu(gate, x): return nn.silu(gate) * x`.
|
|
59
|
-
* nn.silu(g) == g * sigmoid(g); mx.compile fuses sigmoid+mul+mul → one kernel. */
|
|
60
|
-
let _swigluClosure: CompiledFunction | null = null;
|
|
61
|
-
export function compiledSwiglu(gate: MlxArray, up: MlxArray): MlxArray {
|
|
62
|
-
if (!_swigluClosure) {
|
|
63
|
-
_swigluClosure = new CompiledFunction((inputs) => {
|
|
64
|
-
const g = inputs[0]!, u = inputs[1]!;
|
|
65
|
-
const sig = ops.sigmoid(g);
|
|
66
|
-
const silu = ops.mul(g, sig); sig.dispose();
|
|
67
|
-
const out = ops.mul(silu, u); silu.dispose();
|
|
68
|
-
return [out];
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
return _swigluClosure.apply([gate, up])[0]!;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** qwen3_next.py `_precise_swiglu(h, gate, x)`:
|
|
75
|
-
* gate = nn.silu(gate.astype(f32)); x = x.astype(f32); (gate*x).astype(h.dtype)
|
|
76
|
-
* Used by Qwen3NextRMSNormGated. Inputs: (h=hidden for the out dtype, gate=z,
|
|
77
|
-
* x=rms_norm(hidden)). mx.compile fuses the two casts + silu + mul + cast. */
|
|
78
|
-
let _preciseSwigluClosure: CompiledFunction | null = null;
|
|
79
|
-
export function compiledPreciseSwiglu(h: MlxArray, gate: MlxArray, x: MlxArray): MlxArray {
|
|
80
|
-
if (!_preciseSwigluClosure) {
|
|
81
|
-
_preciseSwigluClosure = new CompiledFunction((inputs) => {
|
|
82
|
-
const hh = inputs[0]!, g = inputs[1]!, xx = inputs[2]!;
|
|
83
|
-
const gf = g.astype(Dtype.float32);
|
|
84
|
-
const sig = ops.sigmoid(gf);
|
|
85
|
-
const silu = ops.mul(gf, sig); gf.dispose(); sig.dispose();
|
|
86
|
-
const xf = xx.astype(Dtype.float32);
|
|
87
|
-
const prod = ops.mul(silu, xf); silu.dispose(); xf.dispose();
|
|
88
|
-
const out = prod.astype(hh.dtype); prod.dispose();
|
|
89
|
-
return [out];
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return _preciseSwigluClosure.apply([h, gate, x])[0]!;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** mlx.nn.silu is `@partial(mx.compile, shapeless=True) def silu(x): x*sigmoid(x)`
|
|
96
|
-
* — a COMPILED kernel, not a standalone sigmoid+mul. Used for the conv
|
|
97
|
-
* activation `nn.silu(conv1d(...))`, matching mlx-lm's fused BV2ISigmoid…_V_. */
|
|
98
|
-
let _siluClosure: CompiledFunction | null = null;
|
|
99
|
-
export function compiledSilu(x: MlxArray): MlxArray {
|
|
100
|
-
if (!_siluClosure) {
|
|
101
|
-
_siluClosure = new CompiledFunction((inputs) => {
|
|
102
|
-
const xx = inputs[0]!;
|
|
103
|
-
const sig = ops.sigmoid(xx);
|
|
104
|
-
const out = ops.mul(xx, sig); sig.dispose(); // x * sigmoid(x)
|
|
105
|
-
return [out];
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
return _siluClosure.apply([x])[0]!;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// NOTE: the attention output gate is `self.o_proj(output * mx.sigmoid(gate))`
|
|
112
|
-
// INLINE in mlx-lm (qwen3_next.py) — NOT @mx.compile. It is intentionally kept
|
|
113
|
-
// as a standalone sigmoid + multiply in Qwen3Attention.forward so the dispatched
|
|
114
|
-
// kernel set matches the reference; there is no compiled-output-gate helper.
|
|
115
|
-
|
|
116
|
-
/** Gated-DeltaNet linear-attention layer (mlx-lm GatedDeltaNet). */
|
|
117
|
-
export class GatedDeltaNet {
|
|
118
|
-
/** Per-model experiment seam; null retains the oracle graph. The same
|
|
119
|
-
* implementation advances speculative rollback prefixes. Borrowed inputs,
|
|
120
|
-
* owned activation and independent state tail; no global runtime mutation. */
|
|
121
|
-
convolution: QwenConvolution | null = null;
|
|
122
|
-
readonly inProjQkv: QuantizedLinear;
|
|
123
|
-
readonly inProjZ: QuantizedLinear;
|
|
124
|
-
readonly inProjB: QuantizedLinear;
|
|
125
|
-
readonly inProjA: QuantizedLinear;
|
|
126
|
-
readonly outProj: QuantizedLinear;
|
|
127
|
-
readonly convWeight: MlxArray;
|
|
128
|
-
readonly aLog: MlxArray;
|
|
129
|
-
readonly dtBias: MlxArray;
|
|
130
|
-
readonly normWeight: MlxArray;
|
|
131
|
-
readonly eps: number;
|
|
132
|
-
readonly numKHeads: number;
|
|
133
|
-
readonly numVHeads: number;
|
|
134
|
-
readonly headKDim: number;
|
|
135
|
-
readonly headVDim: number;
|
|
136
|
-
readonly keyDim: number;
|
|
137
|
-
readonly valueDim: number;
|
|
138
|
-
readonly convKernel: number;
|
|
139
|
-
|
|
140
|
-
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
141
|
-
const t = config.text;
|
|
142
|
-
this.numKHeads = t.linearNumKeyHeads;
|
|
143
|
-
this.numVHeads = t.linearNumValueHeads;
|
|
144
|
-
this.headKDim = t.linearKeyHeadDim;
|
|
145
|
-
this.headVDim = t.linearValueHeadDim;
|
|
146
|
-
this.keyDim = this.headKDim * this.numKHeads;
|
|
147
|
-
this.valueDim = this.headVDim * this.numVHeads;
|
|
148
|
-
this.convKernel = t.linearConvKernelDim;
|
|
149
|
-
this.eps = t.rmsNormEps;
|
|
150
|
-
this.inProjQkv = QuantizedLinear.load(weights, `${prefix}.in_proj_qkv`, config);
|
|
151
|
-
this.inProjZ = QuantizedLinear.load(weights, `${prefix}.in_proj_z`, config);
|
|
152
|
-
this.inProjB = QuantizedLinear.load(weights, `${prefix}.in_proj_b`, config);
|
|
153
|
-
this.inProjA = QuantizedLinear.load(weights, `${prefix}.in_proj_a`, config);
|
|
154
|
-
this.outProj = QuantizedLinear.load(weights, `${prefix}.out_proj`, config);
|
|
155
|
-
this.convWeight = weights.tensor(`${prefix}.conv1d.weight`);
|
|
156
|
-
this.aLog = weights.tensor(`${prefix}.A_log`);
|
|
157
|
-
this.dtBias = weights.tensor(`${prefix}.dt_bias`);
|
|
158
|
-
this.normWeight = weights.tensor(`${prefix}.norm.weight`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
#convolve(qkv: MlxArray, state: MlxArray, rowLengths?: readonly number[]): [MlxArray, MlxArray] {
|
|
162
|
-
if (this.convolution) {
|
|
163
|
-
const result = this.convolution(qkv, state, this.convWeight);
|
|
164
|
-
if (!rowLengths) return result;
|
|
165
|
-
using input = ops.concatAxis([state, qkv], 1);
|
|
166
|
-
const tail = this.#convTail(input, qkv.shape[1]!, rowLengths);
|
|
167
|
-
result[1].dispose();
|
|
168
|
-
return [result[0], tail];
|
|
169
|
-
}
|
|
170
|
-
const [, S, D] = qkv.shape as [number, number, number];
|
|
171
|
-
const input = ops.concatAxis([state, qkv], 1);
|
|
172
|
-
// MLX copy and contiguous can both alias the whole prefill buffer.
|
|
173
|
-
// Materialize only the tail so cache residency follows its logical size.
|
|
174
|
-
const tail = this.#convTail(input, S, rowLengths);
|
|
175
|
-
const conv = ops.conv1d(input, this.convWeight, 1, 0, 1, D);
|
|
176
|
-
input.dispose();
|
|
177
|
-
const out = compiledSilu(conv);
|
|
178
|
-
conv.dispose();
|
|
179
|
-
return [out, tail];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
#convTail(input: MlxArray, processed: number, rowLengths?: readonly number[]): MlxArray {
|
|
183
|
-
const [B, , D] = input.shape as [number, number, number];
|
|
184
|
-
const nKeep = this.convKernel - 1;
|
|
185
|
-
if (rowLengths) {
|
|
186
|
-
using indices = ops.fromInt32(rowLengths.flatMap(length =>
|
|
187
|
-
Array.from({ length: nKeep }, (_, position) => length + position)), [B, nKeep, 1]);
|
|
188
|
-
return ops.takeAlongAxis(input, indices, 1);
|
|
189
|
-
}
|
|
190
|
-
using view = input.slice([0, processed, 0], [B, processed + nKeep, D]);
|
|
191
|
-
return materializeCopy(view);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
forward(x: MlxArray, cache: SSMCache, independentRows = false, mask?: MlxArray | null): MlxArray {
|
|
195
|
-
const [B, S] = x.shape as [number, number, number];
|
|
196
|
-
const convDim = this.keyDim * 2 + this.valueDim;
|
|
197
|
-
const nKeep = this.convKernel - 1;
|
|
198
|
-
const prof = (globalThis as Record<string, unknown>).__deltaProf as
|
|
199
|
-
Record<string, number>
|
|
200
|
-
| undefined;
|
|
201
|
-
|
|
202
|
-
// Armed speculative verify round (serve loop, serial lane): this forward
|
|
203
|
-
// must be rewindable. Snapshot = hand the REPLACED state slots to the
|
|
204
|
-
// round instead of disposing (free — arrays are immutable); record the
|
|
205
|
-
// position-local kernel inputs (qkv/a/b) and install the prefix replay.
|
|
206
|
-
const spec = cache.specRound;
|
|
207
|
-
if (spec) {
|
|
208
|
-
if (!spec.armed)
|
|
209
|
-
throw new Error("GatedDeltaNet: spec round already recorded this round");
|
|
210
|
-
spec.armed = false;
|
|
211
|
-
spec.S = S;
|
|
212
|
-
spec.replay = (c, keep) => this.#replaySpecPrefix(c, keep);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const t0 = prof ? performance.now() : 0;
|
|
216
|
-
let qkv = this.inProjQkv.forward(x, independentRows); // [B,S,convDim]
|
|
217
|
-
let z = this.inProjZ.forward(x, independentRows);
|
|
218
|
-
z = disposing(z, ops.reshape(z, [B, S, this.numVHeads, this.headVDim]));
|
|
219
|
-
const b = this.inProjB.forward(x, independentRows); // [B,S,numVHeads]
|
|
220
|
-
const a = this.inProjA.forward(x, independentRows);
|
|
221
|
-
if (prof) { ops.evalAll([qkv, z, b, a]); prof.proj = (prof.proj ?? 0) + performance.now() - t0; }
|
|
222
|
-
const tc = prof ? performance.now() : 0; // [B,S,numVHeads]
|
|
223
|
-
|
|
224
|
-
// The model shares one padding mask across recurrent layers. Direct layer
|
|
225
|
-
// callers can request the same cache-owned mask without a model wrapper.
|
|
226
|
-
using localMask = mask === undefined ? cache.prefillPadding?.makeMask(S) ?? null : null;
|
|
227
|
-
const ssmMask = mask ?? localMask;
|
|
228
|
-
if (ssmMask) {
|
|
229
|
-
using expanded = ops.reshape(ssmMask, [B, S, 1]);
|
|
230
|
-
using zero = MlxArray.fromBytesCopy(new Uint8Array(qkv.dtype === Dtype.float32 ? 4 : 2), [], qkv.dtype);
|
|
231
|
-
qkv = disposing(qkv, ops.where(expanded, qkv, zero));
|
|
232
|
-
}
|
|
233
|
-
// Convolution keeps each row's last real-token tail, including empty rows.
|
|
234
|
-
const convState =
|
|
235
|
-
cache.conv ?? ops.zeros([B, nKeep, convDim], x.dtype);
|
|
236
|
-
const [convOut, newConv] = this.#convolve(qkv, convState, cache.prefillPadding?.convolutionLengths(S));
|
|
237
|
-
if (!cache.conv) convState.dispose();
|
|
238
|
-
if (spec) spec.qkv = qkv;
|
|
239
|
-
else qkv.dispose();
|
|
240
|
-
if (spec) spec.prevConv = cache.conv;
|
|
241
|
-
else cache.conv?.dispose();
|
|
242
|
-
cache.conv = newConv;
|
|
243
|
-
|
|
244
|
-
if (prof) { ops.evalAll([convOut]); prof.conv = (prof.conv ?? 0) + performance.now() - tc; }
|
|
245
|
-
const tn = prof ? performance.now() : 0;
|
|
246
|
-
|
|
247
|
-
const [qFlat, kFlat, vFlat] = ops.split(
|
|
248
|
-
convOut, [this.keyDim, 2 * this.keyDim], -1,
|
|
249
|
-
) as [MlxArray, MlxArray, MlxArray];
|
|
250
|
-
convOut.dispose();
|
|
251
|
-
let q = ops.reshape(qFlat, [B, S, this.numKHeads, this.headKDim]);
|
|
252
|
-
qFlat.dispose();
|
|
253
|
-
let k = ops.reshape(kFlat, [B, S, this.numKHeads, this.headKDim]);
|
|
254
|
-
kFlat.dispose();
|
|
255
|
-
const v = disposing(vFlat, ops.reshape(vFlat, [B, S, this.numVHeads, this.headVDim]));
|
|
256
|
-
|
|
257
|
-
// inv_scale = head_k_dim ** -0.5; q *= inv_scale², k *= inv_scale.
|
|
258
|
-
const invScale = Math.pow(this.headKDim, -0.5);
|
|
259
|
-
q = disposing(q, ops.rmsNorm(q, null, 1e-6));
|
|
260
|
-
q = disposing(q, ops.mulScalar(q, invScale * invScale));
|
|
261
|
-
k = disposing(k, ops.rmsNorm(k, null, 1e-6));
|
|
262
|
-
k = disposing(k, ops.mulScalar(k, invScale));
|
|
263
|
-
if (prof) { ops.evalAll([q, k]); prof.norms = (prof.norms ?? 0) + performance.now() - tn; }
|
|
264
|
-
const tk = prof ? performance.now() : 0;
|
|
265
|
-
|
|
266
|
-
const [out, newState] = gatedDeltaUpdate(
|
|
267
|
-
q, k, v, a, b, this.aLog, this.dtBias, cache.recurrent, ssmMask,
|
|
268
|
-
);
|
|
269
|
-
if (prof) { ops.evalAll([out]); prof.kernel = (prof.kernel ?? 0) + performance.now() - tk; }
|
|
270
|
-
const to = prof ? performance.now() : 0;
|
|
271
|
-
q.dispose();
|
|
272
|
-
k.dispose();
|
|
273
|
-
v.dispose();
|
|
274
|
-
if (spec) {
|
|
275
|
-
spec.a = a;
|
|
276
|
-
spec.b = b;
|
|
277
|
-
spec.prevRecurrent = cache.recurrent;
|
|
278
|
-
} else {
|
|
279
|
-
a.dispose();
|
|
280
|
-
b.dispose();
|
|
281
|
-
cache.recurrent?.dispose();
|
|
282
|
-
}
|
|
283
|
-
cache.recurrent = newState;
|
|
284
|
-
cache.advance(S);
|
|
285
|
-
|
|
286
|
-
// RMSNormGated: silu(z_f32) * rms_norm(out)_f32, cast back to out dtype.
|
|
287
|
-
const gated = this.rmsNormGated(out, z);
|
|
288
|
-
out.dispose();
|
|
289
|
-
z.dispose();
|
|
290
|
-
const merged = ops.reshape(gated, [B, S, this.valueDim]);
|
|
291
|
-
gated.dispose();
|
|
292
|
-
const result = this.outProj.forward(merged, independentRows);
|
|
293
|
-
merged.dispose();
|
|
294
|
-
if (prof) { ops.evalAll([result]); prof.out = (prof.out ?? 0) + performance.now() - to; }
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/** Speculative rollback replay: with the pre-round snapshot RESTORED onto
|
|
299
|
-
* `cache`, re-advance the first `keep` window tokens from the recorded
|
|
300
|
-
* position-local inputs. Every op mirrors forward() on the same values —
|
|
301
|
-
* conv windows, silu, per-position norms, and the kernel's serial prefix
|
|
302
|
-
* are all independent of the rejected tail — so the resulting conv +
|
|
303
|
-
* recurrent state is BIT-EXACTLY what a forward over only the accepted
|
|
304
|
-
* prefix would have produced. Output projections (z / out_proj) are state-
|
|
305
|
-
* free and skipped: only the states matter here. */
|
|
306
|
-
#replaySpecPrefix(cache: SSMCache, keep: number | readonly number[]): void {
|
|
307
|
-
const r = cache.specRound;
|
|
308
|
-
if (!r || !r.qkv || !r.a || !r.b)
|
|
309
|
-
throw new Error("GatedDeltaNet replay without recorded round inputs");
|
|
310
|
-
const B = r.qkv.shape[0]!;
|
|
311
|
-
const count = typeof keep === "number" ? keep : Math.max(...keep);
|
|
312
|
-
const rowLengths = typeof keep === "number" ? undefined : keep;
|
|
313
|
-
const convDim = this.keyDim * 2 + this.valueDim;
|
|
314
|
-
const nKeep = this.convKernel - 1;
|
|
315
|
-
|
|
316
|
-
const qkvPfxView = r.qkv.slice([0, 0, 0], [B, count, convDim]);
|
|
317
|
-
const qkvPfx = ops.contiguous(qkvPfxView);
|
|
318
|
-
qkvPfxView.dispose();
|
|
319
|
-
const convState = cache.conv ?? ops.zeros([B, nKeep, convDim], qkvPfx.dtype);
|
|
320
|
-
const [convOut, newConv] = this.#convolve(qkvPfx, convState, rowLengths);
|
|
321
|
-
if (!cache.conv) convState.dispose();
|
|
322
|
-
qkvPfx.dispose();
|
|
323
|
-
cache.conv?.dispose();
|
|
324
|
-
cache.conv = newConv;
|
|
325
|
-
|
|
326
|
-
const [qFlat, kFlat, vFlat] = ops.split(
|
|
327
|
-
convOut, [this.keyDim, 2 * this.keyDim], -1,
|
|
328
|
-
) as [MlxArray, MlxArray, MlxArray];
|
|
329
|
-
convOut.dispose();
|
|
330
|
-
let q = rowLengths ? null : ops.reshape(qFlat, [B, count, this.numKHeads, this.headKDim]);
|
|
331
|
-
qFlat.dispose();
|
|
332
|
-
let k = ops.reshape(kFlat, [B, count, this.numKHeads, this.headKDim]);
|
|
333
|
-
kFlat.dispose();
|
|
334
|
-
const v = disposing(vFlat, ops.reshape(vFlat, [B, count, this.numVHeads, this.headVDim]));
|
|
335
|
-
const invScale = Math.pow(this.headKDim, -0.5);
|
|
336
|
-
if (q) {
|
|
337
|
-
q = disposing(q, ops.rmsNorm(q, null, 1e-6));
|
|
338
|
-
q = disposing(q, ops.mulScalar(q, invScale * invScale));
|
|
339
|
-
}
|
|
340
|
-
k = disposing(k, ops.rmsNorm(k, null, 1e-6));
|
|
341
|
-
k = disposing(k, ops.mulScalar(k, invScale));
|
|
342
|
-
|
|
343
|
-
const aPfxView = r.a.slice([0, 0, 0], [B, count, this.numVHeads]);
|
|
344
|
-
const aPfx = ops.contiguous(aPfxView);
|
|
345
|
-
aPfxView.dispose();
|
|
346
|
-
const bPfxView = r.b.slice([0, 0, 0], [B, count, this.numVHeads]);
|
|
347
|
-
const bPfx = ops.contiguous(bPfxView);
|
|
348
|
-
bPfxView.dispose();
|
|
349
|
-
|
|
350
|
-
let newState: MlxArray;
|
|
351
|
-
if (rowLengths) {
|
|
352
|
-
// Unequal prefixes need a row-length-aware recurrence. The state-only
|
|
353
|
-
// kernel omits query/output work. Uniform replay retains its measured
|
|
354
|
-
// kernel until the separate optimization demonstrates a serving win.
|
|
355
|
-
newState = gatedDeltaState(k, v, aPfx, bPfx, this.aLog, this.dtBias, cache.recurrent, rowLengths);
|
|
356
|
-
} else {
|
|
357
|
-
const [output, state] = gatedDeltaUpdate(q!, k, v, aPfx, bPfx, this.aLog, this.dtBias, cache.recurrent);
|
|
358
|
-
output.dispose(); newState = state;
|
|
359
|
-
}
|
|
360
|
-
q?.dispose();
|
|
361
|
-
k.dispose();
|
|
362
|
-
v.dispose();
|
|
363
|
-
aPfx.dispose();
|
|
364
|
-
bPfx.dispose();
|
|
365
|
-
cache.recurrent?.dispose();
|
|
366
|
-
cache.recurrent = newState;
|
|
367
|
-
if (typeof keep === "number") cache.advance(keep);
|
|
368
|
-
else cache.advanceRows(keep);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
private rmsNormGated(hidden: MlxArray, gate: MlxArray): MlxArray {
|
|
372
|
-
const xn = ops.rmsNorm(hidden, this.normWeight, this.eps); // bf16
|
|
373
|
-
// Oracle: _precise_swiglu(hidden, gate, xn) — ALWAYS one @mx.compile kernel
|
|
374
|
-
// (matches mlx-lm; no unfused silu+mul+cast).
|
|
375
|
-
const res = compiledPreciseSwiglu(hidden, gate, xn);
|
|
376
|
-
xn.dispose();
|
|
377
|
-
return res;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/** Full (softmax) attention with output gate + q/k norm + partial RoPE. */
|
|
382
|
-
export class Qwen3Attention {
|
|
383
|
-
readonly qProj: QuantizedLinear;
|
|
384
|
-
readonly kProj: QuantizedLinear;
|
|
385
|
-
readonly vProj: QuantizedLinear;
|
|
386
|
-
readonly oProj: QuantizedLinear;
|
|
387
|
-
readonly qNorm: RMSNorm;
|
|
388
|
-
readonly kNorm: RMSNorm;
|
|
389
|
-
readonly nHeads: number;
|
|
390
|
-
readonly nKvHeads: number;
|
|
391
|
-
readonly headDim: number;
|
|
392
|
-
readonly scale: number;
|
|
393
|
-
readonly ropeDims: number;
|
|
394
|
-
readonly ropeBase: number;
|
|
395
|
-
|
|
396
|
-
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
397
|
-
const t = config.text;
|
|
398
|
-
this.nHeads = t.numAttentionHeads;
|
|
399
|
-
this.nKvHeads = t.numKeyValueHeads;
|
|
400
|
-
this.headDim = t.headDim;
|
|
401
|
-
this.scale = Math.pow(this.headDim, -0.5);
|
|
402
|
-
this.ropeDims = Math.trunc(this.headDim * t.partialRotaryFactor);
|
|
403
|
-
this.ropeBase = t.ropeParameters.full_attention?.ropeTheta ?? 10000;
|
|
404
|
-
this.qProj = QuantizedLinear.load(weights, `${prefix}.q_proj`, config);
|
|
405
|
-
this.kProj = QuantizedLinear.load(weights, `${prefix}.k_proj`, config);
|
|
406
|
-
this.vProj = QuantizedLinear.load(weights, `${prefix}.v_proj`, config);
|
|
407
|
-
this.oProj = QuantizedLinear.load(weights, `${prefix}.o_proj`, config);
|
|
408
|
-
this.qNorm = new RMSNorm(weights.tensor(`${prefix}.q_norm.weight`), t.rmsNormEps);
|
|
409
|
-
this.kNorm = new RMSNorm(weights.tensor(`${prefix}.k_norm.weight`), t.rmsNormEps);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
forward(x: MlxArray, mask: Mask, cache: Cache, independentRows = false,
|
|
413
|
-
mrope: MropeForwardState | null = null): MlxArray {
|
|
414
|
-
const [B, L] = x.shape as [number, number, number];
|
|
415
|
-
|
|
416
|
-
// q_proj emits 2× head_dim per head → split into queries + gate.
|
|
417
|
-
const qp = this.qProj.forward(x, independentRows);
|
|
418
|
-
const qpr = disposing(qp, ops.reshape(qp, [B, L, this.nHeads, this.headDim * 2]));
|
|
419
|
-
const [qHeads, gateHeads] = ops.split(qpr, [this.headDim], -1) as [MlxArray, MlxArray];
|
|
420
|
-
qpr.dispose();
|
|
421
|
-
const gate = disposing(gateHeads, ops.reshape(gateHeads, [B, L, this.nHeads * this.headDim]));
|
|
422
|
-
|
|
423
|
-
let k = this.kProj.forward(x, independentRows);
|
|
424
|
-
let v = this.vProj.forward(x, independentRows);
|
|
425
|
-
|
|
426
|
-
// q/k norm over head_dim BEFORE transpose (reference order).
|
|
427
|
-
let q = this.qNorm.forward(qHeads);
|
|
428
|
-
qHeads.dispose();
|
|
429
|
-
q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
|
|
430
|
-
k = disposing(k, ops.reshape(k, [B, L, this.nKvHeads, this.headDim]));
|
|
431
|
-
k = disposing(k, this.kNorm.forward(k));
|
|
432
|
-
k = disposing(k, ops.transposeAxes(k, [0, 2, 1, 3]));
|
|
433
|
-
v = disposing(v, ops.reshape(v, [B, L, this.nKvHeads, this.headDim]));
|
|
434
|
-
v = disposing(v, ops.transposeAxes(v, [0, 2, 1, 3]));
|
|
435
|
-
|
|
436
|
-
// Batched decode: the scheduler's mask wrapper exposes each row's REAL
|
|
437
|
-
// position as ropeOffsetArr (rows have different prompt lengths); the
|
|
438
|
-
// dynamic-offset kernel is the same fast::rope, bit-exact vs the static
|
|
439
|
-
// form (tests/unit/compile.test.ts). Serial lane: scalar offset, unchanged.
|
|
440
|
-
// Media forwards supply their own 3D interleaved positions. The reference
|
|
441
|
-
// never uses the fused fast-rope kernel when position_ids are supplied,
|
|
442
|
-
// so this IS the oracle's own arithmetic. Text-only stays on ops.rope.
|
|
443
|
-
const mr = mrope;
|
|
444
|
-
const offArr = (cache as { ropeOffsetArr?: MlxArray }).ropeOffsetArr;
|
|
445
|
-
if (mr) {
|
|
446
|
-
q = disposing(q, applyInterleavedRope(q, mr));
|
|
447
|
-
k = disposing(k, applyInterleavedRope(k, mr));
|
|
448
|
-
} else {
|
|
449
|
-
q = disposing(q, offArr
|
|
450
|
-
? ops.ropeDynamic(q, this.ropeDims, this.ropeBase, offArr, null)
|
|
451
|
-
: ops.rope(q, this.ropeDims, this.ropeBase, cache.offset, null));
|
|
452
|
-
k = disposing(k, offArr
|
|
453
|
-
? ops.ropeDynamic(k, this.ropeDims, this.ropeBase, offArr, null)
|
|
454
|
-
: ops.rope(k, this.ropeDims, this.ropeBase, cache.offset, null));
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
let attn: MlxArray;
|
|
458
|
-
const quantized = cache.quantizedAttention;
|
|
459
|
-
if (cache.attentionState) {
|
|
460
|
-
const view = cache.attentionState.appendAndFetch(k, v);
|
|
461
|
-
k.dispose(); v.dispose();
|
|
462
|
-
try { attn = view.attend(q, this.scale, mask, independentRows); } finally { view.dispose(); }
|
|
463
|
-
} else if (quantized) {
|
|
464
|
-
const [keys, values] = quantized.updateAndFetchQuantized(k, v);
|
|
465
|
-
k.dispose();
|
|
466
|
-
v.dispose();
|
|
467
|
-
attn = independentRows && L > 1
|
|
468
|
-
? quantizedAppendAttention(q, keys, values, this.scale, quantized.groupSize, quantized.bits)
|
|
469
|
-
: quantizedSdpa(q, keys, values, this.scale, mask, quantized.groupSize, quantized.bits);
|
|
470
|
-
disposeTriple(keys);
|
|
471
|
-
disposeTriple(values);
|
|
472
|
-
} else {
|
|
473
|
-
const [keys, values] = cache.updateAndFetch(k, v);
|
|
474
|
-
k.dispose();
|
|
475
|
-
v.dispose();
|
|
476
|
-
attn = ops.sdpa(q, keys, values, this.scale, mask.mode, mask.arr);
|
|
477
|
-
keys.dispose();
|
|
478
|
-
values.dispose();
|
|
479
|
-
}
|
|
480
|
-
q.dispose();
|
|
481
|
-
|
|
482
|
-
const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
|
|
483
|
-
attn.dispose();
|
|
484
|
-
const merged = ops.reshape(attnT, [B, L, -1]);
|
|
485
|
-
attnT.dispose();
|
|
486
|
-
// qwen3_next.py:158 return self.o_proj(output * mx.sigmoid(gate))
|
|
487
|
-
// INLINE, not @mx.compile — copy the exact ops.
|
|
488
|
-
const sig = ops.sigmoid(gate);
|
|
489
|
-
gate.dispose();
|
|
490
|
-
const gated = ops.mul(merged, sig);
|
|
491
|
-
merged.dispose();
|
|
492
|
-
sig.dispose();
|
|
493
|
-
const out = this.oProj.forward(gated, independentRows);
|
|
494
|
-
gated.dispose();
|
|
495
|
-
return out;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/** MLP projections are affine-quantized (QuantizedLinear) or, in a Q2b
|
|
500
|
-
* packed-trellis artifact, TrellisLinear — chosen per module by the config's
|
|
501
|
-
* quantization entry (`mode: "trellis"`). */
|
|
502
|
-
export type MlpLinear = QuantizedLinear | TrellisLinear;
|
|
503
|
-
function loadMlpLinear(weights: Weights, path: string, config: ModelConfig): MlpLinear {
|
|
504
|
-
if (!TrellisLinear.isTrellis(config, path)) return QuantizedLinear.load(weights, path, config);
|
|
505
|
-
// M4 Pro measurements support the 27B down projection at M3/4. The
|
|
506
|
-
// operation also checks variant, dtype and packed-code layout eligibility.
|
|
507
|
-
const useSharedScatterCodebook = config.text.hiddenSize === 5120 &&
|
|
508
|
-
config.text.intermediateSize === 17408 && path.endsWith(".down_proj");
|
|
509
|
-
return TrellisLinear.load(weights, path, config, useSharedScatterCodebook);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
export class Qwen3MLP {
|
|
513
|
-
readonly gate: MlpLinear;
|
|
514
|
-
readonly up: MlpLinear;
|
|
515
|
-
readonly down: MlpLinear;
|
|
516
|
-
|
|
517
|
-
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
518
|
-
this.gate = loadMlpLinear(weights, `${prefix}.gate_proj`, config);
|
|
519
|
-
this.up = loadMlpLinear(weights, `${prefix}.up_proj`, config);
|
|
520
|
-
this.down = loadMlpLinear(weights, `${prefix}.down_proj`, config);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
forward(x: MlxArray, inputRowContiguous = false, independentRows = false): MlxArray {
|
|
524
|
-
// Packed-trellis decode (M ≤ 4): gate, up and the swiglu in ONE kernel —
|
|
525
|
-
// x read once, no gate/up vectors materialized. This Lab path retains
|
|
526
|
-
// the packed activation arithmetic documented in turboquant.md.
|
|
527
|
-
if (this.gate instanceof TrellisLinear && this.up instanceof TrellisLinear &&
|
|
528
|
-
fusedGateUpEligible(this.gate, this.up) &&
|
|
529
|
-
x.shape.slice(0, -1).reduce((a, b) => a * b, 1) <= TRELLIS_MATVEC_MAX_M) {
|
|
530
|
-
const hidden = fusedGateUpSwiglu(x, this.gate, this.up);
|
|
531
|
-
const out = this.down instanceof QuantizedLinear ? this.down.forward(hidden, independentRows) : this.down.forward(hidden);
|
|
532
|
-
hidden.dispose();
|
|
533
|
-
return out;
|
|
534
|
-
}
|
|
535
|
-
const g = this.gate instanceof TrellisLinear ? this.gate.forward(x, inputRowContiguous) : this.gate.forward(x, independentRows);
|
|
536
|
-
const u = this.up instanceof TrellisLinear ? this.up.forward(x, inputRowContiguous) : this.up.forward(x, independentRows);
|
|
537
|
-
// Oracle: down_proj(swiglu(gate_proj(x), up_proj(x))) — swiglu ALWAYS compiled
|
|
538
|
-
// (mlx-lm's @mx.compile swiglu; no unfused silu+mul, matches its kernel set).
|
|
539
|
-
const hidden = compiledSwiglu(g, u);
|
|
540
|
-
g.dispose();
|
|
541
|
-
u.dispose();
|
|
542
|
-
const out = this.down instanceof QuantizedLinear ? this.down.forward(hidden, independentRows) : this.down.forward(hidden);
|
|
543
|
-
hidden.dispose();
|
|
544
|
-
return out;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
export class Qwen3Layer {
|
|
549
|
-
readonly isLinear: boolean;
|
|
550
|
-
readonly linearAttn: GatedDeltaNet | null = null;
|
|
551
|
-
readonly selfAttn: Qwen3Attention | null = null;
|
|
552
|
-
readonly mlp: Qwen3MLP;
|
|
553
|
-
readonly inputNorm: RMSNorm;
|
|
554
|
-
readonly postAttnNorm: RMSNorm;
|
|
555
|
-
|
|
556
|
-
constructor(weights: Weights, config: ModelConfig, layerIdx: number) {
|
|
557
|
-
const prefix = `${PREFIX}.model.layers.${layerIdx}`;
|
|
558
|
-
this.isLinear = (layerIdx + 1) % config.text.fullAttentionInterval !== 0;
|
|
559
|
-
if (this.isLinear)
|
|
560
|
-
this.linearAttn = new GatedDeltaNet(weights, config, `${prefix}.linear_attn`);
|
|
561
|
-
else this.selfAttn = new Qwen3Attention(weights, config, `${prefix}.self_attn`);
|
|
562
|
-
this.mlp = new Qwen3MLP(weights, config, `${prefix}.mlp`);
|
|
563
|
-
this.inputNorm = new RMSNorm(weights.tensor(`${prefix}.input_layernorm.weight`), config.text.rmsNormEps);
|
|
564
|
-
this.postAttnNorm = new RMSNorm(weights.tensor(`${prefix}.post_attention_layernorm.weight`), config.text.rmsNormEps);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
forward(x: MlxArray, faMask: Mask, cache: Cache, independentRows = false, ssmMask?: MlxArray | null,
|
|
568
|
-
mrope: MropeForwardState | null = null): MlxArray {
|
|
569
|
-
using h = this.forwardAttn(x, faMask, cache, independentRows, ssmMask, mrope);
|
|
570
|
-
return this.forwardMlp(h, independentRows);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
forwardAttn(x: MlxArray, faMask: Mask, cache: Cache, independentRows = false, ssmMask?: MlxArray | null,
|
|
574
|
-
mrope: MropeForwardState | null = null): MlxArray {
|
|
575
|
-
using xn = this.inputNorm.forward(x);
|
|
576
|
-
using r = this.isLinear
|
|
577
|
-
? this.linearAttn!.forward(xn, cache as SSMCache, independentRows, ssmMask)
|
|
578
|
-
: this.selfAttn!.forward(xn, faMask, cache, independentRows, mrope);
|
|
579
|
-
return ops.add(x, r);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
forwardMlp(h: MlxArray, independentRows = false): MlxArray {
|
|
583
|
-
using hn = this.postAttnNorm.forward(h);
|
|
584
|
-
// RMSNorm allocates an aligned row-contiguous output. Pass that layout
|
|
585
|
-
// proof so Trellis can match native small-prefill matmul without an eval.
|
|
586
|
-
using m = this.mlp.forward(hn, true, independentRows);
|
|
587
|
-
return ops.add(h, m);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
export class Qwen35Model {
|
|
592
|
-
readonly config: ModelConfig;
|
|
593
|
-
readonly weightsBytes: number;
|
|
594
|
-
/** Base path for LoRA target keys (weights carry the language_model prefix). */
|
|
595
|
-
readonly prefixBase = "language_model.model";
|
|
596
|
-
readonly loraState = new LoraState();
|
|
597
|
-
readonly embed: QuantizedEmbedding;
|
|
598
|
-
readonly layers: Qwen3Layer[];
|
|
599
|
-
readonly finalNorm: RMSNorm;
|
|
600
|
-
/** null when tied: the output head reuses embed_tokens (embed.asLinear). */
|
|
601
|
-
readonly lmHead: QuantizedLinear | null;
|
|
602
|
-
readonly tied: boolean;
|
|
603
|
-
readonly faIdx: number;
|
|
604
|
-
|
|
605
|
-
constructor(weights: Weights, config: ModelConfig) {
|
|
606
|
-
// Checkpoint-generation normalization BEFORE the first tensor() call: the
|
|
607
|
-
// 5.8-family export names the trunk `model.language_model.*` with a
|
|
608
|
-
// top-level `lm_head`, ships `mtp.*` in-repo, and stores RMSNorm gains as
|
|
609
|
-
// γ−1 with HF-layout conv1d. The view maps all of that onto the names and
|
|
610
|
-
// values this graph reads (mlx-lm's post-sanitize space). No-op — nothing
|
|
611
|
-
// installed at all — for artifacts already in that space.
|
|
612
|
-
const view = qwen35WeightsView(weights);
|
|
613
|
-
if (view) weights.setView(view);
|
|
614
|
-
this.config = config;
|
|
615
|
-
this.tied = config.text.tieWordEmbeddings;
|
|
616
|
-
this.weightsBytes = [...weights.shards.files.values()]
|
|
617
|
-
.reduce((a, f) => a + f.mmap.size, 0);
|
|
618
|
-
this.embed = QuantizedEmbedding.load(weights, `${PREFIX}.model.embed_tokens`, config);
|
|
619
|
-
this.layers = Array.from(
|
|
620
|
-
{ length: config.text.numHiddenLayers },
|
|
621
|
-
(_, i) => new Qwen3Layer(weights, config, i),
|
|
622
|
-
);
|
|
623
|
-
this.finalNorm = new RMSNorm(weights.tensor(`${PREFIX}.model.norm.weight`), config.text.rmsNormEps);
|
|
624
|
-
// Tied models (e.g. Qwen3.5-4B) ship no lm_head; the reference uses
|
|
625
|
-
// embed_tokens.as_linear (mlx-lm qwen3_5 TextModel.__call__).
|
|
626
|
-
this.lmHead = this.tied ? null : QuantizedLinear.load(weights, `${PREFIX}.lm_head`, config);
|
|
627
|
-
this.faIdx = config.text.fullAttentionInterval - 1;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
loraTargets(): Map<string, QuantizedLinear> {
|
|
631
|
-
const out = new Map<string, QuantizedLinear>();
|
|
632
|
-
for (let i = 0; i < this.layers.length; i++) {
|
|
633
|
-
const l = this.layers[i]!;
|
|
634
|
-
const p = `${PREFIX}.model.layers.${i}`;
|
|
635
|
-
if (l.selfAttn) {
|
|
636
|
-
out.set(`${p}.self_attn.q_proj`, l.selfAttn.qProj);
|
|
637
|
-
out.set(`${p}.self_attn.k_proj`, l.selfAttn.kProj);
|
|
638
|
-
out.set(`${p}.self_attn.v_proj`, l.selfAttn.vProj);
|
|
639
|
-
out.set(`${p}.self_attn.o_proj`, l.selfAttn.oProj);
|
|
640
|
-
} else if (l.linearAttn) {
|
|
641
|
-
out.set(`${p}.linear_attn.in_proj_qkv`, l.linearAttn.inProjQkv);
|
|
642
|
-
out.set(`${p}.linear_attn.in_proj_z`, l.linearAttn.inProjZ);
|
|
643
|
-
out.set(`${p}.linear_attn.in_proj_b`, l.linearAttn.inProjB);
|
|
644
|
-
out.set(`${p}.linear_attn.in_proj_a`, l.linearAttn.inProjA);
|
|
645
|
-
out.set(`${p}.linear_attn.out_proj`, l.linearAttn.outProj);
|
|
646
|
-
}
|
|
647
|
-
// Trellis-coded MLP tensors are not LoRA targets (no adapter seam yet).
|
|
648
|
-
if (l.mlp.gate instanceof QuantizedLinear) out.set(`${p}.mlp.gate_proj`, l.mlp.gate);
|
|
649
|
-
if (l.mlp.up instanceof QuantizedLinear) out.set(`${p}.mlp.up_proj`, l.mlp.up);
|
|
650
|
-
if (l.mlp.down instanceof QuantizedLinear) out.set(`${p}.mlp.down_proj`, l.mlp.down);
|
|
651
|
-
}
|
|
652
|
-
return out;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
makeCache(): Cache[] {
|
|
656
|
-
return this.layers.map((l) => (l.isLinear ? new SSMCache() : new KVCache()));
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
/** The 27B append path keeps the native M1 affine arithmetic while Trellis
|
|
660
|
-
* shares up to four rows. Other shapes retain single-token execution. */
|
|
661
|
-
createAppend(policy: { hasAdapters: boolean; pagedKv: boolean }) {
|
|
662
|
-
const t = this.config.text;
|
|
663
|
-
if (policy.hasAdapters || policy.pagedKv || this.loraState.active.length || this.mrope ||
|
|
664
|
-
t.hiddenSize !== 5120 || t.intermediateSize !== 17408 || this.layers.length !== 64 ||
|
|
665
|
-
t.headDim !== 256 || t.numAttentionHeads !== 24 || t.numKeyValueHeads !== 4)
|
|
666
|
-
return null;
|
|
667
|
-
if (deviceArchitecture() !== "applegpu_g16s") return null;
|
|
668
|
-
const qualified = (linear: QuantizedLinear | TrellisLinear) => {
|
|
669
|
-
if (linear instanceof TrellisLinear) return true;
|
|
670
|
-
const { mode, bits, groupSize } = linear.spec;
|
|
671
|
-
return mode === "affine" && [2, 3, 4, 6, 8].includes(bits) && [32, 64, 128].includes(groupSize);
|
|
672
|
-
};
|
|
673
|
-
for (const layer of this.layers) {
|
|
674
|
-
const a = layer.linearAttn, s = layer.selfAttn;
|
|
675
|
-
const attention = a ? [a.inProjQkv, a.inProjZ, a.inProjB, a.inProjA, a.outProj]
|
|
676
|
-
: [s!.qProj, s!.kProj, s!.vProj, s!.oProj];
|
|
677
|
-
if (!attention.every(qualified) || ![layer.mlp.gate, layer.mlp.up, layer.mlp.down].every(qualified))
|
|
678
|
-
return null;
|
|
679
|
-
}
|
|
680
|
-
return {
|
|
681
|
-
affineKvBits: [4, 8],
|
|
682
|
-
turboQuantFormats: [{ kBits: 8, vBits: 3 }],
|
|
683
|
-
maxChunkSize: (state: readonly Cache[], rows = 1) => rows === 1 ? qwenAppendChunkSize(state[0]!.offset) : 1,
|
|
684
|
-
forwardHidden: (ids: MlxArray, cache: Cache[]): MlxArray => {
|
|
685
|
-
// Wider cohorts retain their ordinary one-position numerical graph.
|
|
686
|
-
// The specialized multi-position append remains qualified at B=1.
|
|
687
|
-
if (ids.shape.length === 2 && ids.shape[0]! > 1 && ids.shape[1] === 1)
|
|
688
|
-
return this.forwardHidden(ids, cache);
|
|
689
|
-
if (ids.shape.length !== 2 || ids.shape[0] !== 1 || ids.shape[1]! > 4)
|
|
690
|
-
throw new Error("Qwen committed-token append supports one position per shared row or up to four positions at B=1");
|
|
691
|
-
const hidden = this.embed.encode(ids);
|
|
692
|
-
return this.forwardLayers(hidden, cache, true);
|
|
693
|
-
},
|
|
694
|
-
};
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
forwardHidden(ids: MlxArray, cache: Cache[]): MlxArray {
|
|
698
|
-
const h = this.embed.encode(ids);
|
|
699
|
-
return this.forwardLayers(h, cache);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
/** Borrowed request positions, including different positions for each row. */
|
|
703
|
-
forwardHiddenAtPositions(ids: MlxArray, cache: Cache[], positions: MlxArray): MlxArray {
|
|
704
|
-
return this.forwardLayers(this.embed.encode(ids), cache, false, positions);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
forwardEmbeddingsAtPositions(embeds: MlxArray, cache: Cache[], positions: MlxArray): MlxArray {
|
|
708
|
-
return this.forwardLayers(ops.contiguous(embeds), cache, false, positions);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
/** Attention and DeltaNet retain disjoint row state. Only tokenwise MLP
|
|
712
|
-
* work is eligible for packing; verification can preserve its geometry. */
|
|
713
|
-
forwardHiddenMixed(work: readonly TokenGroup[]): MlxArray[] {
|
|
714
|
-
if (work.length === 1 && !work[0]!.captureLayer) return [this.forwardHidden(work[0]!.ids, work[0]!.cache)];
|
|
715
|
-
const groups: Array<{ h: MlxArray; mask?: Mask; ssmMask?: MlxArray | null }> = [];
|
|
716
|
-
const results: MlxArray[] = [];
|
|
717
|
-
const pack = runtimeFlag("MLX_BUN_MIXED_PACKED_MLP", true);
|
|
718
|
-
const bounded = work.some(group => group.ids.shape[1]! > TRELLIS_MATVEC_MAX_M);
|
|
719
|
-
try {
|
|
720
|
-
for (const { ids, cache } of work) {
|
|
721
|
-
const group: typeof groups[number] = { h: this.embed.encode(ids) }; groups.push(group);
|
|
722
|
-
group.mask = cache[this.faIdx]!.makeMask(ids.shape[1]!, null);
|
|
723
|
-
group.ssmMask = (cache[0] as SSMCache).prefillPadding?.makeMask(ids.shape[1]!);
|
|
724
|
-
}
|
|
725
|
-
for (const [i, layer] of this.layers.entries()) {
|
|
726
|
-
const mids: MlxArray[] = [];
|
|
727
|
-
try {
|
|
728
|
-
for (const [row, group] of groups.entries())
|
|
729
|
-
mids.push(layer.forwardAttn(group.h, group.mask!, work[row]!.cache[i]!, false, group.ssmMask));
|
|
730
|
-
const outputs = mapTokenGroups(work, mids, hidden => layer.forwardMlp(hidden), pack);
|
|
731
|
-
for (const [row, group] of groups.entries()) { group.h.dispose(); group.h = outputs[row]!; }
|
|
732
|
-
// Materialize every layer's recurrent tail as well as the residual.
|
|
733
|
-
// It is not a dependency of h and otherwise pins prefill buffers.
|
|
734
|
-
if (bounded) {
|
|
735
|
-
const caches = work.map(group => group.cache[i]!);
|
|
736
|
-
const state = caches.map(cache => cache.state());
|
|
737
|
-
try { ops.evalAll([...groups.map(group => group.h), ...state.flat()]); }
|
|
738
|
-
finally { for (const [row, cache] of caches.entries())
|
|
739
|
-
if (cache.stateNeedsDispose) for (const value of state[row]!) value.dispose(); }
|
|
740
|
-
}
|
|
741
|
-
for (const [row, group] of groups.entries()) work[row]!.captureLayer?.(i, group.h);
|
|
742
|
-
} finally { for (const mid of mids) mid.dispose(); }
|
|
743
|
-
}
|
|
744
|
-
for (const [row, group] of groups.entries()) {
|
|
745
|
-
const hidden = this.finalNorm.forward(group.h); results.push(hidden);
|
|
746
|
-
work[row]!.captureLayer?.(this.layers.length, hidden);
|
|
747
|
-
}
|
|
748
|
-
return results;
|
|
749
|
-
} catch (error) { for (const result of results) result.dispose(); throw error; }
|
|
750
|
-
finally { for (const group of groups) { group.h.dispose(); group.mask?.arr?.dispose(); group.ssmMask?.dispose(); } }
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
/** Active vision mRoPE request state (serial lane; set by the generation
|
|
754
|
-
* gateway around a vision request's run, null for text-only — which keeps
|
|
755
|
-
* the bit-exact fast-rope path). The explicit serial executor scopes this value.
|
|
756
|
-
* Shared media forwards pass request-owned positions directly. */
|
|
757
|
-
mrope: MropeRequestState | null = null;
|
|
758
|
-
#mropeInvFreq: MlxArray | null = null;
|
|
759
|
-
|
|
760
|
-
/** Vision prefill: spliced input embeddings [1, L, H] (image features
|
|
761
|
-
* overwriting image-token rows — the caller builds them). Caller keeps
|
|
762
|
-
* ownership of `embeds`. bidir/ids/multimodal are the Gemma-shaped extras
|
|
763
|
-
* and are unused: Qwen3.5 vision attends fully causally. */
|
|
764
|
-
forwardEmbeddings(
|
|
765
|
-
embeds: MlxArray, cache: Cache[], _bidir: MlxArray | null,
|
|
766
|
-
_ids: MlxArray | null = null, _multimodal: MlxArray | null = null,
|
|
767
|
-
): MlxArray {
|
|
768
|
-
const h = ops.contiguous(embeds); // fresh handle — the layer loop consumes it
|
|
769
|
-
return this.forwardLayers(h, cache);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/** Layer-output tap (same contract as Gemma4Model.hiddenTap): the serve
|
|
773
|
-
* loop's forwardMaybeTap sets it around prefill/verify forwards so
|
|
774
|
-
* KV-borrowing draft sources (native Qwen MTP) can read PRE-final-norm
|
|
775
|
-
* hiddens — layer 63's output stream, what mlx-vlm captures with
|
|
776
|
-
* skip_final_norm=True. No-op (and graph-identical) when null. */
|
|
777
|
-
hiddenTap: { layers: Set<number>; pos?: number; captured: Map<number, MlxArray> } | null = null;
|
|
778
|
-
|
|
779
|
-
/** Store layer `i`'s residual stream ([1,L,H]) if the tap requests it.
|
|
780
|
-
* Copies so the loop's h.dispose() can't free the capture. */
|
|
781
|
-
protected captureLayer(i: number, h: MlxArray): void {
|
|
782
|
-
const tap = this.hiddenTap;
|
|
783
|
-
if (!tap || !tap.layers.has(i)) return;
|
|
784
|
-
const H = h.shape[2]!;
|
|
785
|
-
const src = tap.pos !== undefined ? h.slice([0, tap.pos, 0], [1, tap.pos + 1, H]) : h;
|
|
786
|
-
const copy = ops.contiguous(src);
|
|
787
|
-
if (src !== h) src.dispose();
|
|
788
|
-
tap.captured.set(i, copy);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
protected forwardLayers(h0: MlxArray, cache: Cache[], independentRows = false,
|
|
792
|
-
positions?: MlxArray): MlxArray {
|
|
793
|
-
const L = h0.shape[1]!;
|
|
794
|
-
// One full-attention mask shared by all full layers (same offset); linear
|
|
795
|
-
// layers see no ssm mask at B=1.
|
|
796
|
-
const faMask = cache[this.faIdx]!.makeMask(L, null);
|
|
797
|
-
using ssmMask = (cache[0] as SSMCache).prefillPadding?.makeMask(L) ?? null;
|
|
798
|
-
// Vision requests: one interleaved-mRoPE cos/sin table per forward,
|
|
799
|
-
// shared by all 12 full-attention layers (positions are layer-invariant).
|
|
800
|
-
let mropeFwd: ReturnType<typeof buildMropePositions> | null = null;
|
|
801
|
-
if (positions || this.mrope) {
|
|
802
|
-
const t = this.config.text;
|
|
803
|
-
const ropeDims = Math.trunc(t.headDim * t.partialRotaryFactor);
|
|
804
|
-
const base = t.ropeParameters.full_attention?.ropeTheta ?? 10000;
|
|
805
|
-
this.#mropeInvFreq ??= mropeInvFreq(ropeDims, base);
|
|
806
|
-
mropeFwd = positions ? { posIds: positions, invFreq: this.#mropeInvFreq, rotaryDims: ropeDims }
|
|
807
|
-
: buildMropePositions(this.mrope!, cache[this.faIdx]!.offset, L, this.#mropeInvFreq, ropeDims);
|
|
808
|
-
}
|
|
809
|
-
let h: MlxArray | null = h0;
|
|
810
|
-
const prof = (globalThis as Record<string, unknown>).__deltaProf as
|
|
811
|
-
Record<string, number>
|
|
812
|
-
| undefined;
|
|
813
|
-
try {
|
|
814
|
-
for (let i = 0; i < this.layers.length; i++) {
|
|
815
|
-
const tl = prof ? performance.now() : 0;
|
|
816
|
-
const next = this.layers[i]!.forward(h, faMask, cache[i]!, independentRows, ssmMask, mropeFwd);
|
|
817
|
-
h.dispose();
|
|
818
|
-
h = next;
|
|
819
|
-
if (L > TRELLIS_MATVEC_MAX_M) {
|
|
820
|
-
// Affine prefills also need bounded evaluation: a retained prefix
|
|
821
|
-
// history can leave too little room for the entire deferred graph.
|
|
822
|
-
// Materialize the cache outputs too. In particular, the tiny
|
|
823
|
-
// copied conv tail is not a dependency of `h`; leaving it lazy
|
|
824
|
-
// pins the whole prefill conv buffer until the chunk ends.
|
|
825
|
-
const state = cache[i]!.state();
|
|
826
|
-
try { ops.evalAll([h, ...state]); }
|
|
827
|
-
finally { if (cache[i]!.stateNeedsDispose) for (const a of state) a.dispose(); }
|
|
828
|
-
}
|
|
829
|
-
if (prof) {
|
|
830
|
-
ops.evalAll([h]);
|
|
831
|
-
const key = this.layers[i]!.isLinear ? "layerLin" : "layerFull";
|
|
832
|
-
prof[key] = (prof[key] ?? 0) + performance.now() - tl;
|
|
833
|
-
}
|
|
834
|
-
this.captureLayer(i, h); // native-MTP pre-final-norm tap (no-op unless set)
|
|
835
|
-
}
|
|
836
|
-
const out = disposing(h, this.finalNorm.forward(h));
|
|
837
|
-
h = null; // consumed — the finally must not double-free
|
|
838
|
-
return out;
|
|
839
|
-
} finally {
|
|
840
|
-
if (mropeFwd && !positions) mropeFwd.posIds.dispose();
|
|
841
|
-
// A mid-loop layer throw must not strand the mask array or the
|
|
842
|
-
// in-flight [1,L,H] residual (2026-08-18 review).
|
|
843
|
-
faMask.arr?.dispose();
|
|
844
|
-
h?.dispose();
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
logitsFromHidden(h: MlxArray): MlxArray {
|
|
849
|
-
return this.tied ? this.embed.asLinear(h) : this.lmHead!.forward(h);
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
forward(tokens: number[] | MlxArray, cache: Cache[]): MlxArray {
|
|
853
|
-
const ids = Array.isArray(tokens)
|
|
854
|
-
? ops.fromInt32(tokens, [1, tokens.length])
|
|
855
|
-
: tokens;
|
|
856
|
-
const h = this.forwardHidden(ids, cache);
|
|
857
|
-
if (Array.isArray(tokens)) ids.dispose();
|
|
858
|
-
const logits = this.logitsFromHidden(h);
|
|
859
|
-
h.dispose();
|
|
860
|
-
return logits;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
generate(promptTokens: number[], maxTokens: number, eosIds: number[] = []): number[] {
|
|
864
|
-
const cache = this.makeCache();
|
|
865
|
-
const out: number[] = [];
|
|
866
|
-
try {
|
|
867
|
-
let tokens = promptTokens;
|
|
868
|
-
for (let step = 0; step < maxTokens; step++) {
|
|
869
|
-
const logits = this.forward(tokens, cache);
|
|
870
|
-
const next = argmaxLastPosition(logits);
|
|
871
|
-
logits.dispose();
|
|
872
|
-
if (eosIds.includes(next)) break;
|
|
873
|
-
out.push(next);
|
|
874
|
-
tokens = [next];
|
|
875
|
-
}
|
|
876
|
-
} finally {
|
|
877
|
-
for (const c of cache) c.dispose();
|
|
878
|
-
}
|
|
879
|
-
return out;
|
|
880
|
-
}
|
|
881
|
-
}
|