@mlx-bun/inference 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +1475 -2
- package/THIRD_PARTY_NOTICES.md +3404 -0
- package/dist/native/libmlx_bun_ane.dylib +0 -0
- package/dist/native/libmlx_bun_expert_io.dylib +0 -0
- package/dist/native/mlx-bun-frame-extract +0 -0
- package/examples/fit-model.ts +25 -0
- package/examples/qwen3-forward.ts +42 -0
- package/examples/qwen3-generate.ts +28 -0
- package/examples/trellis-expand.ts +23 -0
- package/package.json +129 -4
- package/src/adapters/available.ts +110 -0
- package/src/adapters/index.ts +3 -0
- package/src/adapters/manager.ts +316 -0
- package/src/artifacts/auxiliary-files.ts +45 -0
- package/src/artifacts/config-dialects.ts +94 -0
- package/src/artifacts/config.ts +341 -0
- package/src/artifacts/draft-vocabulary.ts +30 -0
- package/src/artifacts/expert-offload-build.ts +75 -0
- package/src/artifacts/expert-offload.ts +89 -0
- package/src/artifacts/experts/index.ts +3 -0
- package/src/artifacts/experts/io.ts +386 -0
- package/src/artifacts/experts/residency.ts +1134 -0
- package/src/artifacts/experts/usage.ts +415 -0
- package/src/artifacts/fingerprint.ts +44 -0
- package/src/artifacts/glm52/container.ts +305 -0
- package/src/artifacts/glm52/expert-layout.ts +249 -0
- package/src/artifacts/glm52/index.ts +7 -0
- package/src/artifacts/glm52/kernel-layout.ts +124 -0
- package/src/artifacts/glm52/layout.ts +152 -0
- package/src/artifacts/glm52/memory.ts +500 -0
- package/src/artifacts/glm52/resident-weights.ts +135 -0
- package/src/artifacts/glm52/weights.ts +503 -0
- package/src/artifacts/glm52-config.ts +262 -0
- package/src/artifacts/identity.ts +94 -0
- package/src/artifacts/index.ts +15 -0
- package/src/artifacts/mmap.ts +90 -0
- package/src/artifacts/safetensors-writer.ts +249 -0
- package/src/artifacts/safetensors.ts +164 -0
- package/src/artifacts/turboquant-fold.ts +42 -0
- package/src/artifacts/weight-audit.ts +43 -0
- package/src/artifacts/weights.ts +255 -0
- package/src/contracts/index.ts +2 -0
- package/src/contracts/mlx/attention.ts +8 -0
- package/src/contracts/mlx/cache.ts +510 -0
- package/src/contracts/mlx/checkpoint.ts +10 -0
- package/src/contracts/mlx/draft-checkpoint.ts +14 -0
- package/src/contracts/mlx/draft-projection.ts +27 -0
- package/src/contracts/mlx/draft-target.ts +84 -0
- package/src/contracts/mlx/drafter.ts +176 -0
- package/src/contracts/mlx/forward-work.ts +23 -0
- package/src/contracts/mlx/glm52-weights.ts +25 -0
- package/src/contracts/mlx/graph.ts +309 -0
- package/src/contracts/mlx/head.ts +6 -0
- package/src/contracts/mlx/index.ts +15 -0
- package/src/contracts/mlx/kv-codec.ts +9 -0
- package/src/contracts/mlx/media.ts +113 -0
- package/src/contracts/mlx/positions.ts +16 -0
- package/src/contracts/mlx/row-table.ts +2 -0
- package/src/contracts/mlx/trainable.ts +103 -0
- package/src/contracts/mlx/whisper.ts +96 -0
- package/src/contracts/portable/composition.ts +106 -0
- package/src/contracts/portable/denoising.ts +17 -0
- package/src/contracts/portable/execution.ts +79 -0
- package/src/contracts/portable/generation.ts +103 -0
- package/src/contracts/portable/graph.ts +80 -0
- package/src/contracts/portable/index.ts +15 -0
- package/src/contracts/portable/memory-plan.ts +26 -0
- package/src/contracts/portable/object-cache.ts +8 -0
- package/src/contracts/portable/prefill.ts +63 -0
- package/src/contracts/portable/prefix-cache.ts +33 -0
- package/src/contracts/portable/prompt.ts +2 -0
- package/src/contracts/portable/resources.ts +25 -0
- package/src/contracts/portable/rollback.ts +7 -0
- package/src/contracts/portable/sampling.ts +44 -0
- package/src/contracts/portable/scheduling.ts +54 -0
- package/src/contracts/portable/token-delivery.ts +4 -0
- package/src/contracts/portable/tsconfig.json +14 -0
- package/src/embeddings/index.ts +1 -0
- package/src/embeddings/text.ts +85 -0
- package/src/execution/admission.ts +59 -0
- package/src/execution/batch-group.ts +1240 -0
- package/src/execution/batch-types.ts +225 -0
- package/src/execution/cancellation.ts +38 -0
- package/src/execution/continuation-request.ts +45 -0
- package/src/execution/continuation-types.ts +10 -0
- package/src/execution/coordinator.ts +70 -0
- package/src/execution/denoising-group.ts +180 -0
- package/src/execution/engine.ts +56 -0
- package/src/execution/fill-group.ts +505 -0
- package/src/execution/fit.ts +184 -0
- package/src/execution/gateway-binding.ts +178 -0
- package/src/execution/grammar-group.ts +224 -0
- package/src/execution/index.ts +18 -0
- package/src/execution/methods.ts +75 -0
- package/src/execution/mixed-iteration.ts +96 -0
- package/src/execution/plan.ts +65 -0
- package/src/execution/prefill-cohort.ts +100 -0
- package/src/execution/prefill-rows.ts +263 -0
- package/src/execution/request-policy.ts +19 -0
- package/src/execution/row-sampling.ts +49 -0
- package/src/execution/scheduler.ts +92 -0
- package/src/execution/session.ts +247 -0
- package/src/execution/speculative-group.ts +797 -0
- package/src/execution/tasks.ts +44 -0
- package/src/generation/autoregressive.ts +840 -0
- package/src/generation/bindings/autoregressive.ts +104 -0
- package/src/generation/bindings/denoising.ts +60 -0
- package/src/generation/bindings/prefill-policy.ts +36 -0
- package/src/generation/checkpoint-identity.ts +60 -0
- package/src/generation/denoising.ts +85 -0
- package/src/generation/diffusion.ts +583 -0
- package/src/generation/fill/echo-index.ts +188 -0
- package/src/generation/fill/index.ts +3 -0
- package/src/generation/fill/proposal.ts +69 -0
- package/src/generation/fill/schema-rows.ts +506 -0
- package/src/generation/fill/session.ts +464 -0
- package/src/generation/fill/tool-boundary.ts +103 -0
- package/src/generation/fill-append.ts +58 -0
- package/src/generation/generate.ts +44 -0
- package/src/generation/grammar-step.ts +39 -0
- package/src/generation/index.ts +14 -0
- package/src/generation/phase-dispatch.ts +115 -0
- package/src/generation/prefill.ts +33 -0
- package/src/generation/result.ts +49 -0
- package/src/generation/scopes.ts +157 -0
- package/src/generation/speculative/acceptance.ts +41 -0
- package/src/generation/speculative/adaptive-draft-gate.ts +166 -0
- package/src/generation/speculative/bindings/assistant-rows.ts +102 -0
- package/src/generation/speculative/bindings/autoregressive-rows.ts +124 -0
- package/src/generation/speculative/bindings/binding.ts +106 -0
- package/src/generation/speculative/bindings/deepspec-rows.ts +33 -0
- package/src/generation/speculative/bindings/draft-target.ts +10 -0
- package/src/generation/speculative/bindings/glm52-mtp-rows.ts +128 -0
- package/src/generation/speculative/bindings/projected-context-rows.ts +78 -0
- package/src/generation/speculative/bindings/projected-draft-rows.ts +95 -0
- package/src/generation/speculative/bindings/qwen-mtp-rows.ts +336 -0
- package/src/generation/speculative/bindings/two-model-rows.ts +63 -0
- package/src/generation/speculative/cache-identity.ts +16 -0
- package/src/generation/speculative/draft-kind.ts +149 -0
- package/src/generation/speculative/draft-policy.ts +41 -0
- package/src/generation/speculative/draft-registry.ts +118 -0
- package/src/generation/speculative/draft-vocab.ts +110 -0
- package/src/generation/speculative/index.ts +17 -0
- package/src/generation/speculative/output.ts +49 -0
- package/src/generation/speculative/round.ts +307 -0
- package/src/generation/speculative/source.ts +144 -0
- package/src/generation/speculative/sources/assistant-source.ts +64 -0
- package/src/generation/speculative/sources/deepspec-source.ts +70 -0
- package/src/generation/speculative/sources/dflash-source.ts +84 -0
- package/src/generation/speculative/sources/dflash2-source.ts +86 -0
- package/src/generation/speculative/sources/glm52-mtp-source.ts +66 -0
- package/src/generation/speculative/sources/ngram-source.ts +165 -0
- package/src/generation/speculative/sources/qwen-mtp-source.ts +154 -0
- package/src/generation/speculative/sources/two-model.ts +75 -0
- package/src/generation/types.ts +194 -0
- package/src/index.ts +20 -0
- package/src/input/audio/audiotoolbox.ts +112 -0
- package/src/input/audio/decode.ts +133 -0
- package/src/input/audio/features.ts +202 -0
- package/src/input/audio/index.ts +6 -0
- package/src/input/audio/transcode.ts +67 -0
- package/src/input/audio/whisper-mel.ts +185 -0
- package/src/input/audio/whisper-tokenizer.ts +238 -0
- package/src/input/chat-template.ts +389 -0
- package/src/input/index.ts +6 -0
- package/src/input/media-fetch.ts +439 -0
- package/src/input/packed-mixed.ts +43 -0
- package/src/input/special-tokens.ts +75 -0
- package/src/input/token-groups.ts +49 -0
- package/src/input/tokenizer.ts +336 -0
- package/src/input/tool-call.ts +689 -0
- package/src/input/vision/index.ts +3 -0
- package/src/input/vision/preprocess.ts +247 -0
- package/src/input/vision/prompt.ts +398 -0
- package/src/input/vision/qwen3vl-preprocess.ts +409 -0
- package/src/input/vision/qwen3vl-prompt.ts +237 -0
- package/src/input/vision/video-frames.ts +100 -0
- package/src/kernels/ane/fill.ts +101 -0
- package/src/kernels/ane/linear.ts +416 -0
- package/src/kernels/attention/flash.ts +694 -0
- package/src/kernels/attention/kvq4-decode.ts +155 -0
- package/src/kernels/attention/masks.ts +40 -0
- package/src/kernels/attention/multi-query.ts +193 -0
- package/src/kernels/attention/paged.ts +130 -0
- package/src/kernels/delta/gated.ts +306 -0
- package/src/kernels/delta/index.ts +3 -0
- package/src/kernels/delta/silu-rms-heads.ts +69 -0
- package/src/kernels/delta/state.ts +74 -0
- package/src/kernels/gated-rms-norm.ts +64 -0
- package/src/kernels/glm52/layout.ts +37 -0
- package/src/kernels/glm52/streamed-experts.ts +360 -0
- package/src/kernels/logits.ts +38 -0
- package/src/kernels/quantization/affine-row.ts +154 -0
- package/src/kernels/quantization/affine-rows.ts +36 -0
- package/src/kernels/quantization/affine-split-mma.ts +144 -0
- package/src/kernels/quantization/affine3-mma.ts +117 -0
- package/src/kernels/quantization/affine3-rows.ts +103 -0
- package/src/kernels/quantization/affine4-mma.ts +113 -0
- package/src/kernels/quantization/affine4-rows.ts +102 -0
- package/src/kernels/residual-rms-norm.ts +65 -0
- package/src/kernels/sampling/index.ts +2 -0
- package/src/kernels/sampling/normalized-argmax.ts +116 -0
- package/src/kernels/sampling/token-bitmask.ts +52 -0
- package/src/kernels/softcap.ts +35 -0
- package/src/kernels/trellis/codebook.ts +123 -0
- package/src/kernels/trellis/down-codebook.ts +184 -0
- package/src/kernels/trellis/down-factored.ts +180 -0
- package/src/kernels/trellis/down-k3-interleaved-factored.ts +146 -0
- package/src/kernels/trellis/down-mma-wide.ts +195 -0
- package/src/kernels/trellis/down-mma.ts +145 -0
- package/src/kernels/trellis/expand.ts +42 -0
- package/src/kernels/trellis/gate-up-codebook-mma.ts +141 -0
- package/src/kernels/trellis/gate-up-codebook.ts +137 -0
- package/src/kernels/trellis/gate-up-factored.ts +197 -0
- package/src/kernels/trellis/gate-up-mma-wide.ts +147 -0
- package/src/kernels/trellis/gate-up-mma.ts +148 -0
- package/src/kernels/trellis/gate-up.ts +248 -0
- package/src/kernels/trellis/geometry.ts +22 -0
- package/src/kernels/trellis/index.ts +103 -0
- package/src/kernels/trellis/launch.ts +12 -0
- package/src/kernels/trellis/mixed-gate-up-factored.ts +119 -0
- package/src/kernels/trellis/mixed-gate-up.ts +146 -0
- package/src/kernels/trellis/qualified.ts +34 -0
- package/src/kernels/trellis/reduce.ts +150 -0
- package/src/kernels/trellis/scatter.ts +407 -0
- package/src/kernels/trellis/splitk-prefill.ts +152 -0
- package/src/kernels/trellis/tiled-prefill.ts +131 -0
- package/src/kernels/trellis/vector-expand.ts +58 -0
- package/src/kernels/trellis/wide-prefill.ts +89 -0
- package/src/kernels/turboquant/decode.ts +82 -0
- package/src/kernels/turboquant/index.ts +5 -0
- package/src/kernels/turboquant/inverse.ts +122 -0
- package/src/kernels/turboquant/ops.ts +860 -0
- package/src/kernels/turboquant/signs.ts +130 -0
- package/src/kernels/turboquant/tables.ts +124 -0
- package/src/layers/affine-verify-linear.ts +75 -0
- package/src/layers/ane-prefill-split.ts +283 -0
- package/src/layers/compiled-normalization.ts +41 -0
- package/src/layers/delta-heads.ts +23 -0
- package/src/layers/dense-embedding.ts +29 -0
- package/src/layers/dense-linear.ts +32 -0
- package/src/layers/dequantized-linear.ts +72 -0
- package/src/layers/folded-attention.ts +42 -0
- package/src/layers/geglu.ts +130 -0
- package/src/layers/helpers.ts +7 -0
- package/src/layers/index.ts +36 -0
- package/src/layers/kv4-decode-attention.ts +15 -0
- package/src/layers/layer-norm.ts +24 -0
- package/src/layers/loading.ts +92 -0
- package/src/layers/lora.ts +150 -0
- package/src/layers/normalization.ts +9 -0
- package/src/layers/prefix-layout.ts +33 -0
- package/src/layers/quantized-append-attention.ts +32 -0
- package/src/layers/quantized-attention.ts +353 -0
- package/src/layers/quantized-embedding.ts +39 -0
- package/src/layers/quantized-linear.ts +137 -0
- package/src/layers/quantized-switch-linear.ts +37 -0
- package/src/layers/qwen-append.ts +12 -0
- package/src/layers/qwen-mrope.ts +238 -0
- package/src/layers/rope-2d.ts +110 -0
- package/src/layers/rope.ts +389 -0
- package/src/layers/swiglu.ts +23 -0
- package/src/layers/trellis-codebook-down.ts +52 -0
- package/src/layers/trellis-codebook-gate-up.ts +42 -0
- package/src/layers/trellis-down.ts +117 -0
- package/src/layers/trellis-gate-up.ts +71 -0
- package/src/layers/trellis-linear.ts +211 -0
- package/src/layers/trellis-prompt.ts +102 -0
- package/src/layers/trellis-reduce-gate-up.ts +73 -0
- package/src/layers/trellis-scatter-down.ts +98 -0
- package/src/models/ane-install.ts +74 -0
- package/src/models/audio/conformer.ts +656 -0
- package/src/models/cache-composition.ts +44 -0
- package/src/models/capabilities.ts +89 -0
- package/src/models/chat-template.ts +10 -0
- package/src/models/composition.ts +107 -0
- package/src/models/diffusion-gemma/experts.ts +59 -0
- package/src/models/diffusion-gemma/family.ts +21 -0
- package/src/models/diffusion-gemma/model.ts +900 -0
- package/src/models/diffusion-gemma/vision.ts +549 -0
- package/src/models/drafter-loaders.ts +49 -0
- package/src/models/drafters.ts +39 -0
- package/src/models/factory.ts +351 -0
- package/src/models/families.ts +70 -0
- package/src/models/family.ts +125 -0
- package/src/models/gemma4/assistant-target.ts +46 -0
- package/src/models/gemma4/assistant.ts +327 -0
- package/src/models/gemma4/blocks.ts +755 -0
- package/src/models/gemma4/compiled-decode.ts +452 -0
- package/src/models/gemma4/family.ts +39 -0
- package/src/models/gemma4/gemma4-12b.ts +677 -0
- package/src/models/gemma4/gemma4-26b.ts +544 -0
- package/src/models/gemma4/gemma4-e4b.ts +599 -0
- package/src/models/gemma4/graphs.ts +147 -0
- package/src/models/gemma4/media.ts +88 -0
- package/src/models/gemma4/model.ts +860 -0
- package/src/models/gemma4/serving-blocks.ts +72 -0
- package/src/models/gemma4/trainable.ts +186 -0
- package/src/models/gemma4/written-blocks.ts +232 -0
- package/src/models/gemma4/written-forward.ts +159 -0
- package/src/models/gemma4/written-input.ts +29 -0
- package/src/models/glm52/atlas.ts +507 -0
- package/src/models/glm52/coupling.ts +388 -0
- package/src/models/glm52/dsa.ts +601 -0
- package/src/models/glm52/family.ts +20 -0
- package/src/models/glm52/mla.ts +812 -0
- package/src/models/glm52/model.ts +1127 -0
- package/src/models/glm52/moe.ts +223 -0
- package/src/models/glm52/mtp.ts +60 -0
- package/src/models/glm52/pilot.ts +537 -0
- package/src/models/glm52/reference.ts +445 -0
- package/src/models/glm52/residency.ts +557 -0
- package/src/models/glm52/streamed-experts.ts +447 -0
- package/src/models/graph.ts +59 -0
- package/src/models/implementation.ts +230 -0
- package/src/models/index.ts +15 -0
- package/src/models/media-input.ts +15 -0
- package/src/models/memory-plan.ts +39 -0
- package/src/models/minicpm5/family.ts +29 -0
- package/src/models/minicpm5/model.ts +394 -0
- package/src/models/minicpm5/trainable.ts +90 -0
- package/src/models/profile.ts +337 -0
- package/src/models/qwen/blocks.ts +658 -0
- package/src/models/qwen/checkpoint.ts +190 -0
- package/src/models/qwen/families.ts +57 -0
- package/src/models/qwen/media-input.ts +161 -0
- package/src/models/qwen/mtp.ts +101 -0
- package/src/models/qwen/qwen3-moe.ts +355 -0
- package/src/models/qwen/qwen3.ts +323 -0
- package/src/models/qwen/qwen38-27b-trellis-m1max.ts +1532 -0
- package/src/models/qwen/qwen38-27b-trellis-m4pro.ts +1092 -0
- package/src/models/qwen/qwen3_5.ts +433 -0
- package/src/models/qwen/written-layers.ts +285 -0
- package/src/models/row-table.ts +1 -0
- package/src/models/runtime.ts +73 -0
- package/src/models/speculative/deepspec-artifact.ts +10 -0
- package/src/models/speculative/deepspec.ts +744 -0
- package/src/models/speculative/dflash.ts +553 -0
- package/src/models/speculative/dflash2-artifact.ts +9 -0
- package/src/models/speculative/dflash2-operations.ts +1 -0
- package/src/models/speculative/dflash2.ts +576 -0
- package/src/models/speculative/loader.ts +29 -0
- package/src/models/support.ts +79 -0
- package/src/models/universal/archs.ts +365 -0
- package/src/models/universal/blocks.ts +479 -0
- package/src/models/universal/dense.ts +255 -0
- package/src/models/universal/family.ts +17 -0
- package/src/models/vision/qwen3vl.ts +566 -0
- package/src/models/vision/siglip.ts +520 -0
- package/src/models/vision/unified.ts +176 -0
- package/src/models/whisper/family.ts +19 -0
- package/src/models/whisper/fast.ts +734 -0
- package/src/models/whisper/model.ts +430 -0
- package/src/runtime/compiled-trace.ts +16 -0
- package/src/runtime/config.ts +77 -0
- package/src/runtime/expert-trace.ts +71 -0
- package/src/runtime/graph-forward.ts +65 -0
- package/src/runtime/integers.ts +6 -0
- package/src/runtime/native.ts +16 -0
- package/src/runtime/resources.ts +53 -0
- package/src/runtime/row-operations.ts +42 -0
- package/src/runtime/trace.ts +161 -0
- package/src/sampling/curve.ts +122 -0
- package/src/sampling/draft.ts +55 -0
- package/src/sampling/extras.ts +45 -0
- package/src/sampling/filters.ts +134 -0
- package/src/sampling/grammar.ts +630 -0
- package/src/sampling/hlg.ts +290 -0
- package/src/sampling/index.ts +9 -0
- package/src/sampling/processors.ts +142 -0
- package/src/sampling/sampler.ts +120 -0
- package/src/sampling/step.ts +343 -0
- package/src/sampling/types.ts +161 -0
- package/src/sampling/window-filters.ts +46 -0
- package/src/scoring/decisions.ts +96 -0
- package/src/scoring/full-sequence.ts +103 -0
- package/src/scoring/index.ts +9 -0
- package/src/scoring/kl.ts +29 -0
- package/src/scoring/perplexity.ts +165 -0
- package/src/scoring/response-logps.ts +65 -0
- package/src/state/affine-attention.ts +180 -0
- package/src/state/attachment.ts +68 -0
- package/src/state/attention-read.ts +215 -0
- package/src/state/batched-kv.ts +294 -0
- package/src/state/batched-mask.ts +445 -0
- package/src/state/batched-quant.ts +389 -0
- package/src/state/batched-quantized-kv.ts +209 -0
- package/src/state/batched-rotating-quant.ts +457 -0
- package/src/state/batched-rotating-state.ts +149 -0
- package/src/state/batched-rotating.ts +430 -0
- package/src/state/batched-row-storage.ts +179 -0
- package/src/state/batched-ssm.ts +54 -0
- package/src/state/batched-turboquant-kv.ts +144 -0
- package/src/state/bf16-first-kv.ts +663 -0
- package/src/state/cache-service.ts +592 -0
- package/src/state/capabilities.ts +65 -0
- package/src/state/checkpoint.ts +46 -0
- package/src/state/continuation-persistence.ts +126 -0
- package/src/state/decode-step-inputs.ts +31 -0
- package/src/state/decoded-kv-donor.ts +12 -0
- package/src/state/delayed-quantized-kv.ts +141 -0
- package/src/state/delayed-rotating-quantized-kv.ts +178 -0
- package/src/state/delayed-turboquant-kv.ts +123 -0
- package/src/state/durability.ts +214 -0
- package/src/state/encoder-cache.ts +26 -0
- package/src/state/full-kv-row-append.ts +33 -0
- package/src/state/full-kv-row-donor.ts +54 -0
- package/src/state/full-prefill-padding.ts +56 -0
- package/src/state/full-prefill-row.ts +112 -0
- package/src/state/full-transitioning-kv-rows.ts +70 -0
- package/src/state/glm52-cache.ts +783 -0
- package/src/state/grouped-heads-kv4-cache.ts +26 -0
- package/src/state/index.ts +38 -0
- package/src/state/kv-attention-view.ts +77 -0
- package/src/state/kv-budget.ts +14 -0
- package/src/state/kv-scheme.ts +315 -0
- package/src/state/kv-storage.ts +57 -0
- package/src/state/kv-tensor-rows.ts +212 -0
- package/src/state/kv.ts +324 -0
- package/src/state/kv4-head256-cache.ts +46 -0
- package/src/state/latent-legos.ts +895 -0
- package/src/state/layout.ts +277 -0
- package/src/state/leases.ts +26 -0
- package/src/state/paged/cache.ts +689 -0
- package/src/state/paged/codec.ts +36 -0
- package/src/state/paged/rows.ts +223 -0
- package/src/state/persistence-types.ts +173 -0
- package/src/state/persistence-worker.ts +83 -0
- package/src/state/persistence.ts +1036 -0
- package/src/state/persistence.worker.d.ts +3 -0
- package/src/state/persistence.worker.js +264 -0
- package/src/state/prefix-cache.ts +685 -0
- package/src/state/quantized-kv.ts +369 -0
- package/src/state/quantized-tensor.ts +26 -0
- package/src/state/request-policy.ts +48 -0
- package/src/state/retention-policy.ts +37 -0
- package/src/state/rollback.ts +131 -0
- package/src/state/rotating-kv-donor.ts +35 -0
- package/src/state/rotating-kv-layout.ts +341 -0
- package/src/state/rotating-kv.ts +529 -0
- package/src/state/rotating-quantized-kv.ts +616 -0
- package/src/state/rotating-row-transaction.ts +35 -0
- package/src/state/rows.ts +104 -0
- package/src/state/softcap-attention.ts +118 -0
- package/src/state/speculative/glm52-mtp-state.ts +38 -0
- package/src/state/speculative/qwen-mtp-state.ts +34 -0
- package/src/state/speculative-rotating-kv.ts +113 -0
- package/src/state/ssd-cache.ts +434 -0
- package/src/state/ssm-prefill-padding.ts +39 -0
- package/src/state/ssm.ts +422 -0
- package/src/state/target-layout.ts +7 -0
- package/src/state/tiered-prefix-cache.ts +45 -0
- package/src/state/training-cache.ts +300 -0
- package/src/state/transitioning-kv-rows.ts +267 -0
- package/src/state/turboquant-attention.ts +97 -0
- package/src/state/turboquant-codec.ts +90 -0
- package/src/state/turboquant-kv.ts +442 -0
- package/src/state/views.ts +26 -0
- package/src/transcription/index.ts +3 -0
- package/src/transcription/silero-vad.ts +379 -0
- package/src/transcription/whisper/decode.ts +773 -0
- package/src/transcription/whisper/format.ts +74 -0
- package/src/transcription/whisper/index.ts +4 -0
- package/src/transcription/whisper/timing.ts +274 -0
- package/src/transcription/whisper/transcribe.ts +394 -0
- package/src/transcription/whisper/types.ts +22 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import type { MlxCacheLayer, MlxMixedRange, MlxSequenceRange } from "../../contracts/mlx/graph";
|
|
2
|
+
// Concrete model graph for MiniCPM5-1B-OptiQ-4bit.
|
|
3
|
+
// Port target: mlx_lm.models.llama from the oracle venv. Each block is built
|
|
4
|
+
// once and reads its cache through the cache contract for the phase its caller
|
|
5
|
+
// names (`ReadPhase`); the cache was composed with its read, so no block builds
|
|
6
|
+
// a mask or chooses an attention kernel. The training forward
|
|
7
|
+
// (`forwardTraining`) reads its training caches the same way and adds only the
|
|
8
|
+
// prefix-shared block RoPE.
|
|
9
|
+
|
|
10
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
11
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
12
|
+
import { LoraState } from "../../layers/lora";
|
|
13
|
+
import type { GraphDeclaration } from "../../contracts/portable/graph";
|
|
14
|
+
import type { MlxRowTable, MlxCapturingForward, MlxDeclaredGraph, MlxHeadForward, MlxPhaseForward, MlxPromptRange, MlxTokenPhases, MlxVerifyForward } from "../../contracts/mlx/graph";
|
|
15
|
+
import type { TrainableGraph } from "../../contracts/mlx/trainable";
|
|
16
|
+
import { miniCpmTrainable } from "./trainable";
|
|
17
|
+
import { declareGraph } from "../capabilities";
|
|
18
|
+
import { DEFAULT_PHASE_ROWS, rowTable, type ReadPhase } from "../graph";
|
|
19
|
+
import type { ModelConfig } from "../../artifacts/config";
|
|
20
|
+
import type { Weights } from "../../artifacts/weights";
|
|
21
|
+
import type { Cache, TrainingAttentionCache } from "../../contracts/mlx/cache";
|
|
22
|
+
import { disposing } from "../../layers/helpers";
|
|
23
|
+
import { RMSNorm } from "../../layers/normalization";
|
|
24
|
+
import { QuantizedEmbedding } from "../../layers/quantized-embedding";
|
|
25
|
+
import { QuantizedLinear, QuantizedLinearPlain } from "../../layers/quantized-linear";
|
|
26
|
+
import { composedFullAttentionCache } from "../../state/bf16-first-kv";
|
|
27
|
+
import { AttentionMasks } from "../../state/attention-read";
|
|
28
|
+
import { deferredTurboQuantKernels } from "../../state/turboquant-attention";
|
|
29
|
+
import { compiledSwiglu } from "../../layers/swiglu";
|
|
30
|
+
import { cacheRead, type AttentionReadStrategy } from "../qwen/blocks";
|
|
31
|
+
|
|
32
|
+
export class LlamaAttention {
|
|
33
|
+
readonly qProj: QuantizedLinear;
|
|
34
|
+
readonly kProj: QuantizedLinear;
|
|
35
|
+
readonly vProj: QuantizedLinear;
|
|
36
|
+
readonly oProj: QuantizedLinear;
|
|
37
|
+
readonly nHeads: number;
|
|
38
|
+
readonly nKvHeads: number;
|
|
39
|
+
readonly headDim: number;
|
|
40
|
+
readonly scale: number;
|
|
41
|
+
readonly ropeBase: number;
|
|
42
|
+
|
|
43
|
+
readonly #q: QuantizedLinearPlain;
|
|
44
|
+
readonly #k: QuantizedLinearPlain;
|
|
45
|
+
readonly #v: QuantizedLinearPlain;
|
|
46
|
+
readonly #out: QuantizedLinearPlain;
|
|
47
|
+
|
|
48
|
+
/** `reads` is how the block reads its cache: the cache's own read, fixed when
|
|
49
|
+
* the block is built. */
|
|
50
|
+
constructor(weights: Weights, config: ModelConfig, prefix: string, readonly reads: AttentionReadStrategy = cacheRead) {
|
|
51
|
+
const t = config.text;
|
|
52
|
+
this.nHeads = t.numAttentionHeads;
|
|
53
|
+
this.nKvHeads = t.numKeyValueHeads;
|
|
54
|
+
this.headDim = t.headDim;
|
|
55
|
+
this.scale = Math.pow(this.headDim, -0.5);
|
|
56
|
+
this.ropeBase = t.ropeParameters.full_attention?.ropeTheta ?? 10000;
|
|
57
|
+
this.qProj = QuantizedLinear.load(weights, `${prefix}.q_proj`, config);
|
|
58
|
+
this.kProj = QuantizedLinear.load(weights, `${prefix}.k_proj`, config);
|
|
59
|
+
this.vProj = QuantizedLinear.load(weights, `${prefix}.v_proj`, config);
|
|
60
|
+
this.oProj = QuantizedLinear.load(weights, `${prefix}.o_proj`, config);
|
|
61
|
+
this.#q = new QuantizedLinearPlain(this.qProj);
|
|
62
|
+
this.#k = new QuantizedLinearPlain(this.kProj);
|
|
63
|
+
this.#v = new QuantizedLinearPlain(this.vProj);
|
|
64
|
+
this.#out = new QuantizedLinearPlain(this.oProj);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** `x` [B, L, hidden] (borrowed) to an owned [B, L, hidden], appending to
|
|
68
|
+
* `cache` and attending through the read `phase` names. */
|
|
69
|
+
forward(x: MlxArray, cache: Cache, phase: ReadPhase): MlxArray {
|
|
70
|
+
const [B, L] = x.shape as [number, number, number];
|
|
71
|
+
let [q, k, v] = this.#heads(x, B, L);
|
|
72
|
+
// RoPE: a number offset takes the static fast::rope; an array offset
|
|
73
|
+
// (per-row positions for left-padded batched decode) takes the dynamic
|
|
74
|
+
// variant — same kernel, offset read from the array. Captured once: rope
|
|
75
|
+
// runs before the append, so K and Q share the pre-write offset.
|
|
76
|
+
const offsetArr = cache.ropeOffsetArr;
|
|
77
|
+
const ropeStep = (x: MlxArray): MlxArray => offsetArr
|
|
78
|
+
? ops.ropeDynamic(x, this.headDim, this.ropeBase, offsetArr, null)
|
|
79
|
+
: ops.rope(x, this.headDim, this.ropeBase, cache.offset, null);
|
|
80
|
+
q = disposing(q, ropeStep(q));
|
|
81
|
+
k = disposing(k, ropeStep(k));
|
|
82
|
+
const read = this.reads.read(cache, phase, k, v);
|
|
83
|
+
k.dispose();
|
|
84
|
+
v.dispose();
|
|
85
|
+
let attn: MlxArray;
|
|
86
|
+
try { attn = read.attend(q, this.scale); } finally { read.dispose(); }
|
|
87
|
+
q.dispose();
|
|
88
|
+
return this.#output(attn, B, L);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** The training forward over a training cache (`TrainingCache`,
|
|
92
|
+
* `PrefixSharedCache`), roped at the positions the cache owns (block-wise
|
|
93
|
+
* for a prefix-shared concat), read through its window read, which owns the mask (causal, padded or
|
|
94
|
+
* block-sparse) and the kernel the run composed (the SDPA, or the validated
|
|
95
|
+
* flash kernel). */
|
|
96
|
+
forwardTraining(x: MlxArray, cache: TrainingAttentionCache): MlxArray {
|
|
97
|
+
const [B, L] = x.shape as [number, number, number];
|
|
98
|
+
let [q, k, v] = this.#heads(x, B, L);
|
|
99
|
+
const ropeStep = (x: MlxArray): MlxArray =>
|
|
100
|
+
cache.ropePositions(x, (block, offset) => ops.rope(block, this.headDim, this.ropeBase, offset, null));
|
|
101
|
+
q = disposing(q, ropeStep(q));
|
|
102
|
+
k = disposing(k, ropeStep(k));
|
|
103
|
+
const read = cache.appendWindow(k, v);
|
|
104
|
+
k.dispose();
|
|
105
|
+
v.dispose();
|
|
106
|
+
let attn: MlxArray;
|
|
107
|
+
try { attn = read.attend(q, this.scale); } finally { read.dispose(); }
|
|
108
|
+
q.dispose();
|
|
109
|
+
return this.#output(attn, B, L);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** q, k and v heads [B, H, L, D] of `x` (borrowed), before RoPE. */
|
|
113
|
+
#heads(x: MlxArray, B: number, L: number): [MlxArray, MlxArray, MlxArray] {
|
|
114
|
+
let q = this.#q.forward(x);
|
|
115
|
+
let k = this.#k.forward(x);
|
|
116
|
+
let v = this.#v.forward(x);
|
|
117
|
+
|
|
118
|
+
q = disposing(q, ops.reshape(q, [B, L, this.nHeads, this.headDim]));
|
|
119
|
+
k = disposing(k, ops.reshape(k, [B, L, this.nKvHeads, this.headDim]));
|
|
120
|
+
v = disposing(v, ops.reshape(v, [B, L, this.nKvHeads, this.headDim]));
|
|
121
|
+
|
|
122
|
+
q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
|
|
123
|
+
k = disposing(k, ops.transposeAxes(k, [0, 2, 1, 3]));
|
|
124
|
+
v = disposing(v, ops.transposeAxes(v, [0, 2, 1, 3]));
|
|
125
|
+
return [q, k, v];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** The output projection of `attn` [B, H, L, D] (consumed). */
|
|
129
|
+
#output(attn: MlxArray, B: number, L: number): MlxArray {
|
|
130
|
+
const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
|
|
131
|
+
attn.dispose();
|
|
132
|
+
const merged = ops.reshape(attnT, [B, L, -1]);
|
|
133
|
+
attnT.dispose();
|
|
134
|
+
const out = this.#out.forward(merged);
|
|
135
|
+
merged.dispose();
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** The MLP with mlx_lm activations.py's compiled swiglu, at every sequence
|
|
141
|
+
* length: separate kernels differ numerically on MLX 0.32.2 at larger prefill
|
|
142
|
+
* shapes. */
|
|
143
|
+
export class LlamaMLP {
|
|
144
|
+
readonly kind = "compiled";
|
|
145
|
+
readonly gate: QuantizedLinear;
|
|
146
|
+
readonly up: QuantizedLinear;
|
|
147
|
+
readonly down: QuantizedLinear;
|
|
148
|
+
|
|
149
|
+
readonly #gate: QuantizedLinearPlain;
|
|
150
|
+
readonly #up: QuantizedLinearPlain;
|
|
151
|
+
readonly #down: QuantizedLinearPlain;
|
|
152
|
+
|
|
153
|
+
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
154
|
+
this.gate = QuantizedLinear.load(weights, `${prefix}.gate_proj`, config);
|
|
155
|
+
this.up = QuantizedLinear.load(weights, `${prefix}.up_proj`, config);
|
|
156
|
+
this.down = QuantizedLinear.load(weights, `${prefix}.down_proj`, config);
|
|
157
|
+
this.#gate = new QuantizedLinearPlain(this.gate);
|
|
158
|
+
this.#up = new QuantizedLinearPlain(this.up);
|
|
159
|
+
this.#down = new QuantizedLinearPlain(this.down);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** MLP: returns mlp(x); the caller adds the residual when given. */
|
|
163
|
+
forward(x: MlxArray, residual?: MlxArray): MlxArray {
|
|
164
|
+
const gate = this.#gate.forward(x);
|
|
165
|
+
const up = this.#up.forward(x);
|
|
166
|
+
const hidden = compiledSwiglu(gate, up);
|
|
167
|
+
gate.dispose();
|
|
168
|
+
up.dispose();
|
|
169
|
+
return downWithResidual(this.#down, hidden, residual);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The MLP with the swiglu as separate silu and multiply kernels: the explicit
|
|
174
|
+
* layer form, available for callers writing their own graph. */
|
|
175
|
+
export class LlamaUnfusedMLP {
|
|
176
|
+
readonly kind = "unfused";
|
|
177
|
+
readonly gate: QuantizedLinear;
|
|
178
|
+
readonly up: QuantizedLinear;
|
|
179
|
+
readonly down: QuantizedLinear;
|
|
180
|
+
|
|
181
|
+
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
182
|
+
this.gate = QuantizedLinear.load(weights, `${prefix}.gate_proj`, config);
|
|
183
|
+
this.up = QuantizedLinear.load(weights, `${prefix}.up_proj`, config);
|
|
184
|
+
this.down = QuantizedLinear.load(weights, `${prefix}.down_proj`, config);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** MLP: returns mlp(x); the caller adds the residual when given. */
|
|
188
|
+
forward(x: MlxArray, residual?: MlxArray): MlxArray {
|
|
189
|
+
const gate = this.gate.forward(x);
|
|
190
|
+
const up = this.up.forward(x);
|
|
191
|
+
const sig = ops.sigmoid(gate);
|
|
192
|
+
const silu = ops.mul(gate, sig);
|
|
193
|
+
gate.dispose();
|
|
194
|
+
sig.dispose();
|
|
195
|
+
const hidden = ops.mul(silu, up);
|
|
196
|
+
silu.dispose();
|
|
197
|
+
up.dispose();
|
|
198
|
+
return downWithResidual(this.down, hidden, residual);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** down(hidden) (hidden consumed), plus `residual` when given. */
|
|
203
|
+
function downWithResidual(down: { forward(x: MlxArray): MlxArray }, hidden: MlxArray, residual: MlxArray | undefined): MlxArray {
|
|
204
|
+
const m = down.forward(hidden);
|
|
205
|
+
hidden.dispose();
|
|
206
|
+
if (residual == null) return m;
|
|
207
|
+
return disposing(m, ops.add(residual, m));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type MiniCpmMlp = LlamaMLP | LlamaUnfusedMLP;
|
|
211
|
+
type MlpBlock = new (weights: Weights, config: ModelConfig, prefix: string) => MiniCpmMlp;
|
|
212
|
+
|
|
213
|
+
export class LlamaLayer {
|
|
214
|
+
readonly attn: LlamaAttention;
|
|
215
|
+
readonly mlp: MiniCpmMlp;
|
|
216
|
+
readonly inputNorm: RMSNorm;
|
|
217
|
+
readonly postAttnNorm: RMSNorm;
|
|
218
|
+
|
|
219
|
+
constructor(weights: Weights, config: ModelConfig, prefix: string, Mlp: MlpBlock = LlamaMLP) {
|
|
220
|
+
this.attn = new LlamaAttention(weights, config, `${prefix}.self_attn`);
|
|
221
|
+
this.mlp = new Mlp(weights, config, `${prefix}.mlp`);
|
|
222
|
+
this.inputNorm = new RMSNorm(weights.tensor(`${prefix}.input_layernorm.weight`), config.text.rmsNormEps);
|
|
223
|
+
this.postAttnNorm = new RMSNorm(weights.tensor(`${prefix}.post_attention_layernorm.weight`), config.text.rmsNormEps);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
forward(x: MlxArray, cache: Cache, phase: ReadPhase): MlxArray {
|
|
227
|
+
const xn = this.inputNorm.forward(x);
|
|
228
|
+
const a = this.attn.forward(xn, cache, phase);
|
|
229
|
+
xn.dispose();
|
|
230
|
+
return this.#mlp(x, a);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** The training forward (`LlamaAttention.forwardTraining`). */
|
|
234
|
+
forwardTraining(x: MlxArray, cache: TrainingAttentionCache): MlxArray {
|
|
235
|
+
const xn = this.inputNorm.forward(x);
|
|
236
|
+
const a = this.attn.forwardTraining(xn, cache);
|
|
237
|
+
xn.dispose();
|
|
238
|
+
return this.#mlp(x, a);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** The residual over the attention output `a` (consumed), then the MLP. */
|
|
242
|
+
#mlp(x: MlxArray, a: MlxArray): MlxArray {
|
|
243
|
+
const h = ops.add(x, a);
|
|
244
|
+
a.dispose();
|
|
245
|
+
const hn = this.postAttnNorm.forward(h);
|
|
246
|
+
// Pass the residual h INTO the MLP so the fused kernel absorbs it (out = h + mlp).
|
|
247
|
+
const out = this.mlp.forward(hn, h);
|
|
248
|
+
hn.dispose();
|
|
249
|
+
h.dispose();
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export class MiniCPM5Model implements MlxDeclaredGraph, MlxTokenPhases {
|
|
255
|
+
readonly config: ModelConfig;
|
|
256
|
+
readonly weightsBytes: number;
|
|
257
|
+
readonly prefixBase = "model";
|
|
258
|
+
readonly loraState = new LoraState();
|
|
259
|
+
/** An ordinary autoregressive graph: every method over every cache lego. */
|
|
260
|
+
get graphCapabilities(): GraphDeclaration { return declareGraph(); }
|
|
261
|
+
#trainable: TrainableGraph | undefined;
|
|
262
|
+
/** The separate quantized head, segmented backward, prefix-shared ORPO and flash training attention. */
|
|
263
|
+
get trainable(): TrainableGraph { return this.#trainable ??= miniCpmTrainable(this); }
|
|
264
|
+
readonly embed: QuantizedEmbedding;
|
|
265
|
+
readonly layers: LlamaLayer[];
|
|
266
|
+
readonly finalNorm: RMSNorm;
|
|
267
|
+
readonly lmHead: QuantizedLinear;
|
|
268
|
+
readonly #head: QuantizedLinearPlain;
|
|
269
|
+
|
|
270
|
+
constructor(weights: Weights, config: ModelConfig, maxPhaseRows = DEFAULT_PHASE_ROWS) {
|
|
271
|
+
if (config.text.tieWordEmbeddings)
|
|
272
|
+
throw new Error("llama tied embeddings are not supported yet");
|
|
273
|
+
this.config = config;
|
|
274
|
+
this.weightsBytes = [...weights.shards.files.values()]
|
|
275
|
+
.reduce((a, f) => a + f.mmap.size, 0);
|
|
276
|
+
this.embed = QuantizedEmbedding.load(weights, "model.embed_tokens", config);
|
|
277
|
+
const Mlp = LlamaMLP;
|
|
278
|
+
this.layers = Array.from(
|
|
279
|
+
{ length: config.text.numHiddenLayers },
|
|
280
|
+
(_, i) => new LlamaLayer(weights, config, `model.layers.${i}`, Mlp),
|
|
281
|
+
);
|
|
282
|
+
this.finalNorm = new RMSNorm(weights.tensor("model.norm.weight"), config.text.rmsNormEps);
|
|
283
|
+
this.lmHead = QuantizedLinear.load(weights, "lm_head", config);
|
|
284
|
+
this.#head = new QuantizedLinearPlain(this.lmHead);
|
|
285
|
+
|
|
286
|
+
const multiSequencePrompt: MlxCapturingForward = (ids, cache) =>
|
|
287
|
+
this.forwardLayers(this.embed.encode(ids), cache, "window");
|
|
288
|
+
this.prompt = [{ from: 1, to: Infinity, operation: multiSequencePrompt }];
|
|
289
|
+
this.promptChunk = this.prompt;
|
|
290
|
+
this.multiSequencePrompt = this.prompt;
|
|
291
|
+
this.multiSequencePromptChunk = this.multiSequencePrompt;
|
|
292
|
+
this.appendKnown = [{from:1,to:Infinity,operation:(ids, cache) =>
|
|
293
|
+
this.forwardLayers(this.embed.encode(ids), cache, "window")}];
|
|
294
|
+
this.logits = rowTable<MlxHeadForward>(hidden => this.logitsFromHidden(hidden), maxPhaseRows);
|
|
295
|
+
this.decode = rowTable<MlxPhaseForward>((ids, cache) =>
|
|
296
|
+
this.forwardLayers(this.embed.encode(ids), cache, "decode"), maxPhaseRows);
|
|
297
|
+
this.verify = rowTable<MlxVerifyForward>((ids, cache) =>
|
|
298
|
+
this.forwardLayers(this.embed.encode(ids), cache, "window"), maxPhaseRows);
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
this.sequence = [{from:1,to:Infinity,operation:(ids,cache)=>this.sequenceHidden(ids,cache,1)}];
|
|
302
|
+
|
|
303
|
+
this.cacheLayers = this.layers.map(() => ({kind:"full" as const,turboQuant:"deferred" as const}));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
loraTargets(): Map<string, QuantizedLinear> {
|
|
307
|
+
const out = new Map<string, QuantizedLinear>();
|
|
308
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
309
|
+
const l = this.layers[i]!;
|
|
310
|
+
const p = `model.layers.${i}`;
|
|
311
|
+
out.set(`${p}.self_attn.q_proj`, l.attn.qProj);
|
|
312
|
+
out.set(`${p}.self_attn.k_proj`, l.attn.kProj);
|
|
313
|
+
out.set(`${p}.self_attn.v_proj`, l.attn.vProj);
|
|
314
|
+
out.set(`${p}.self_attn.o_proj`, l.attn.oProj);
|
|
315
|
+
out.set(`${p}.mlp.gate_proj`, l.mlp.gate);
|
|
316
|
+
out.set(`${p}.mlp.up_proj`, l.mlp.up);
|
|
317
|
+
out.set(`${p}.mlp.down_proj`, l.mlp.down);
|
|
318
|
+
}
|
|
319
|
+
return out;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Builds no constants and opens no weights: nothing to release. */
|
|
323
|
+
dispose(): void {}
|
|
324
|
+
|
|
325
|
+
/** One cache per layer, sharing one mask memo. Their TurboQuant read is
|
|
326
|
+
* deferred (`deferredTurboQuantKernels`): attention runs on the rotated
|
|
327
|
+
* values and the read un-rotates its output. */
|
|
328
|
+
readonly cacheLayers: readonly MlxCacheLayer[];
|
|
329
|
+
readonly sequence: readonly MlxSequenceRange[];
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
/** The scoring and training forward (`MlxSequenceForward`, `trainForward`
|
|
333
|
+
* over the training caches): the window read at every width. The training
|
|
334
|
+
* caches were composed with the run's training attention, so a run that
|
|
335
|
+
* selects flash attention reads with it here. */
|
|
336
|
+
sequenceHidden(ids: MlxArray, cache: Cache[], _width: number): MlxArray {
|
|
337
|
+
return this.forwardLayers(this.embed.encode(ids), cache, "window");
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** One whole chunk of a prompt; rows are sequences times the chunk size. The GPU is this graph's one unit. */
|
|
341
|
+
readonly prompt: readonly MlxPromptRange[];
|
|
342
|
+
readonly promptChunk: typeof this.prompt;
|
|
343
|
+
readonly multiSequencePromptChunk: typeof this.multiSequencePrompt;
|
|
344
|
+
readonly multiSequencePrompt: readonly MlxPromptRange[];
|
|
345
|
+
|
|
346
|
+
/** A prompt's positions that are not a whole chunk: the window read at every width. */
|
|
347
|
+
|
|
348
|
+
/** Known tokens: this graph declares no committed spans, so they read as a window. */
|
|
349
|
+
readonly appendKnown: import("../../contracts/mlx/graph").MlxKnownOperations;
|
|
350
|
+
|
|
351
|
+
/** The one output head at every width. */
|
|
352
|
+
readonly logits: MlxRowTable<MlxHeadForward>;
|
|
353
|
+
|
|
354
|
+
/** One new token per sequence: `ids` [sequences, 1]. */
|
|
355
|
+
readonly decode: MlxRowTable<MlxCapturingForward>;
|
|
356
|
+
|
|
357
|
+
/** A speculative window of depth + 1 positions per sequence. This graph
|
|
358
|
+
* declares no hidden-layer taps, so `capture` is always null. */
|
|
359
|
+
readonly verify: MlxRowTable<MlxCapturingForward>;
|
|
360
|
+
|
|
361
|
+
/** The decoder over `h0` (consumed), every block reading its cache for `phase`. */
|
|
362
|
+
protected forwardLayers(h0: MlxArray, cache: Cache[], phase: ReadPhase): MlxArray {
|
|
363
|
+
let h = h0;
|
|
364
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
365
|
+
const next = this.layers[i]!.forward(h, cache[i]!, phase);
|
|
366
|
+
h.dispose();
|
|
367
|
+
h = next;
|
|
368
|
+
}
|
|
369
|
+
return disposing(h, this.finalNorm.forward(h));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Run decoder layers `[aIdx, bIdx)` on hidden `h`, returning the residual
|
|
373
|
+
* stream after the last layer in the range (NO finalNorm). The input `h` is
|
|
374
|
+
* NEVER disposed — the caller owns it (for segmented backward `h` is a leaf
|
|
375
|
+
* whose lifetime is managed by the autograd closure); intra-range
|
|
376
|
+
* intermediates ARE disposed. The segmented-backward and prefix-shared
|
|
377
|
+
* training paths' building block (`02d723a:docs/design/orpo-training.md`
|
|
378
|
+
* §5.3). MiniCPM5 is plain full-attention with no KV-sharing, so each layer
|
|
379
|
+
* reads its own stateless training cache `cache[i]`. */
|
|
380
|
+
runLayerRange(h: MlxArray, aIdx: number, bIdx: number, cache: Cache[]): MlxArray {
|
|
381
|
+
if (aIdx >= bIdx) return h;
|
|
382
|
+
let cur = h;
|
|
383
|
+
for (let i = aIdx; i < bIdx; i++) {
|
|
384
|
+
const next = this.layers[i]!.forwardTraining(cur, cache[i] as TrainingAttentionCache);
|
|
385
|
+
if (i > aIdx) cur.dispose(); // keep the input boundary leaf; drop interiors
|
|
386
|
+
cur = next;
|
|
387
|
+
}
|
|
388
|
+
return cur;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
logitsFromHidden(h: MlxArray): MlxArray {
|
|
392
|
+
return this.#head.forward(h);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import type { Cache, SharedKv } from "../../contracts/mlx/cache";
|
|
3
|
+
import type { HeadQuant, PrefixLayout, SegmentedPass, TrainableGraph } from "../../contracts/mlx/trainable";
|
|
4
|
+
import { AttentionMasks } from "../../state/attention-read";
|
|
5
|
+
import { prefixSharedCaches, selectedTrainingAttention, TrainingCache } from "../../state/training-cache";
|
|
6
|
+
import type { RMSNorm } from "../../layers/normalization";
|
|
7
|
+
import type { QuantizedEmbedding } from "../../layers/quantized-embedding";
|
|
8
|
+
import type { QuantizedLinear } from "../../layers/quantized-linear";
|
|
9
|
+
|
|
10
|
+
/** What the training declaration reads from a MiniCPM5 model (structural, so this
|
|
11
|
+
* module does not depend on the model file). */
|
|
12
|
+
export interface MiniCpmTraining {
|
|
13
|
+
readonly embed: QuantizedEmbedding;
|
|
14
|
+
readonly layers: readonly unknown[];
|
|
15
|
+
readonly finalNorm: RMSNorm;
|
|
16
|
+
readonly lmHead: QuantizedLinear;
|
|
17
|
+
/** The training forward over layers `[aIdx, bIdx)`; `h` stays the caller's. */
|
|
18
|
+
runLayerRange(h: MlxArray, aIdx: number, bIdx: number, cache: Cache[]): MlxArray;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** One stateless training cache per layer, full attention, sharing one mask
|
|
22
|
+
* memo and attending with the run's training attention: prefix-shared caches
|
|
23
|
+
* under a layout, plain ones otherwise. */
|
|
24
|
+
function trainingCaches(model: MiniCpmTraining, prefix?: PrefixLayout): Cache[] {
|
|
25
|
+
const attention = selectedTrainingAttention(), windows = model.layers.map(() => null);
|
|
26
|
+
if (prefix) return prefixSharedCaches(prefix, windows, attention);
|
|
27
|
+
const masks = new AttentionMasks();
|
|
28
|
+
return windows.map(window => new TrainingCache(window, masks, attention));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** One segmented pass over a MiniCPM5 sequence: plain full attention with no KV
|
|
32
|
+
* sharing, so each layer reads its own stateless cache (prefix-shared caches
|
|
33
|
+
* read under the block-sparse mask when a layout is given). */
|
|
34
|
+
class MiniCpmSegmentedPass implements SegmentedPass {
|
|
35
|
+
readonly input: MlxArray;
|
|
36
|
+
private readonly caches: Cache[];
|
|
37
|
+
|
|
38
|
+
constructor(private readonly model: MiniCpmTraining, ids: MlxArray, prefix?: PrefixLayout) {
|
|
39
|
+
this.caches = trainingCaches(model, prefix);
|
|
40
|
+
try {
|
|
41
|
+
this.input = model.embed.encode(ids); // [1, T, hidden]
|
|
42
|
+
} catch (error) {
|
|
43
|
+
this.releaseCaches();
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private releaseCaches(): void {
|
|
49
|
+
for (const c of this.caches) c.dispose();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
runRange(h: MlxArray, lo: number, hi: number, _donorKvIn: Map<number, SharedKv>) {
|
|
53
|
+
return { h: this.model.runLayerRange(h, lo, hi, this.caches), donorKvOut: new Map<number, SharedKv>() };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dispose(): void { this.releaseCaches(); }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** MiniCPM5's training declaration. */
|
|
60
|
+
export function miniCpmTrainable(model: MiniCpmTraining): TrainableGraph {
|
|
61
|
+
return {
|
|
62
|
+
lmHead(): HeadQuant {
|
|
63
|
+
const h = model.lmHead;
|
|
64
|
+
return { w: h.w, scales: h.scales, biases: h.biases, spec: h.spec, softcap: null };
|
|
65
|
+
},
|
|
66
|
+
flashAttention: { supported: true },
|
|
67
|
+
segmented: {
|
|
68
|
+
layerCount: model.layers.length,
|
|
69
|
+
sharedKv: { reusedDonors: new Set(), donorOf: model.layers.map(() => null) },
|
|
70
|
+
finalNorm: (h) => model.finalNorm.forward(h),
|
|
71
|
+
begin: (ids, prefix) => new MiniCpmSegmentedPass(model, ids, prefix),
|
|
72
|
+
},
|
|
73
|
+
prefixShared: {
|
|
74
|
+
/** The training forward (`runLayerRange`) over the whole concat, whose
|
|
75
|
+
* prefix-shared caches read under the block-sparse mask and whose
|
|
76
|
+
* queries and keys take the block-wise RoPE those caches own. */
|
|
77
|
+
prefixSharedHidden(ids: MlxArray, layout: PrefixLayout): MlxArray {
|
|
78
|
+
const caches = trainingCaches(model, layout);
|
|
79
|
+
try {
|
|
80
|
+
const h0 = model.embed.encode(ids);
|
|
81
|
+
let h: MlxArray;
|
|
82
|
+
try { h = model.runLayerRange(h0, 0, model.layers.length, caches); } finally { h0.dispose(); }
|
|
83
|
+
try { return model.finalNorm.forward(h); } finally { h.dispose(); } // [1, T, hidden], post-finalNorm
|
|
84
|
+
} finally {
|
|
85
|
+
for (const c of caches) c.dispose();
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|