@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,131 @@
|
|
|
1
|
+
// Packed axis-1 trellis prefill without a full expanded weight allocation.
|
|
2
|
+
// SIMD-group fragment layout follows MLX steel/gemm/mma.h (MIT, Apple Inc.):
|
|
3
|
+
// https://github.com/ml-explore/mlx/blob/v0.31.2/mlx/backend/metal/kernels/steel/gemm/mma.h
|
|
4
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
5
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
6
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
7
|
+
import type { TrellisGeometry } from "./geometry";
|
|
8
|
+
import { HEADER } from "./codebook";
|
|
9
|
+
import { nativeTrellisWidePrefill } from "./wide-prefill";
|
|
10
|
+
|
|
11
|
+
/** Dispatch profile measured on Qwen's MLP geometry. No model-name check.
|
|
12
|
+
* `widePrefill` as for `wideTrellisPrefillEligible`: tiled steps aside where wide applies. */
|
|
13
|
+
export function tiledTrellisPrefillEligible(g: TrellisGeometry, m: number, dtype: Dtype, widePrefill: boolean): boolean {
|
|
14
|
+
return dtype === Dtype.bfloat16 && m >= 5 && m <= 32 && !nativeTrellisWidePrefill(m, widePrefill) &&
|
|
15
|
+
g.axis === 1 && g.T === 256 && g.L === 12 && [2, 3, 4].includes(g.k) &&
|
|
16
|
+
g.inFeatures === 5120 && g.outFeatures === 17408;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let kernel: MetalKernel | undefined;
|
|
20
|
+
function tiledKernel(): MetalKernel {
|
|
21
|
+
return kernel ??= new MetalKernel({ name: "mlx_bun_trellis_prefill_tile",
|
|
22
|
+
inputNames: ["x", "codes", "scales"], outputNames: ["out"],
|
|
23
|
+
header: "#include <metal_simdgroup_matrix>\n" + HEADER,
|
|
24
|
+
source: String.raw`
|
|
25
|
+
const uint tid=thread_position_in_threadgroup.x;
|
|
26
|
+
const uint lane=thread_index_in_simdgroup;
|
|
27
|
+
const uint sg=simdgroup_index_in_threadgroup;
|
|
28
|
+
const uint mbase=threadgroup_position_in_grid.y*BM;
|
|
29
|
+
const uint nbase=threadgroup_position_in_grid.x*BN;
|
|
30
|
+
const uint fm=((lane/4)&4)+((lane/2)%4);
|
|
31
|
+
const uint fn=((lane/4)&2)*2+(lane%2)*2;
|
|
32
|
+
// An eight-row tile assigns all four SIMD groups to output columns.
|
|
33
|
+
// Each output keeps the same 8x8 products and K accumulation order.
|
|
34
|
+
constexpr int WM=BM==8?1:2, WN=4/WM, SM=WM*8, SN=WN*8;
|
|
35
|
+
const uint sm=(sg/WN)*8+fm, sn=(sg%WN)*8+fn;
|
|
36
|
+
constexpr int TM=BM/SM, TN=BN/SN;
|
|
37
|
+
threadgroup T As[BM*BK];
|
|
38
|
+
threadgroup T Bs[BK*BN];
|
|
39
|
+
metal::simdgroup_float8x8 acc[TM][TN];
|
|
40
|
+
#pragma clang loop unroll(full)
|
|
41
|
+
for(uint i=0;i<TM;i++) {
|
|
42
|
+
#pragma clang loop unroll(full)
|
|
43
|
+
for(uint j=0;j<TN;j++) {
|
|
44
|
+
acc[i][j].thread_elements()[0]=0.0f;
|
|
45
|
+
acc[i][j].thread_elements()[1]=0.0f;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
constexpr uint wpb=BT*BITS/32;
|
|
49
|
+
for(uint kb=0;kb<KC;kb+=BK) {
|
|
50
|
+
for(uint a=tid;a<BM*BK;a+=128) {
|
|
51
|
+
const uint m=mbase+a/BK, k=kb+a%BK;
|
|
52
|
+
As[a]=(m<M && k<KC)?x[(ulong)m*KC+k]:T(0);
|
|
53
|
+
}
|
|
54
|
+
for(uint b=tid;b<BK*BN;b+=128) {
|
|
55
|
+
const uint k=kb+b/BN, n=nbase+b%BN;
|
|
56
|
+
T w=T(0);
|
|
57
|
+
if(k<KC && n<N) {
|
|
58
|
+
const uint row=AXIS==1?n:k;
|
|
59
|
+
const uint col=AXIS==1?k:n;
|
|
60
|
+
const uint block=col/BT, t=col%BT;
|
|
61
|
+
const device uint* bw=codes+(ulong)row*(C/BT)*wpb+block*wpb;
|
|
62
|
+
const uint pos=(BT-1-t)*BITS, wi=pos>>5, off=pos&31u;
|
|
63
|
+
uint win=bw[wi]>>off;
|
|
64
|
+
if(off+L>32)win|=bw[wi+1==wpb?0:wi+1]<<(32-off);
|
|
65
|
+
win&=(1u<<L)-1;
|
|
66
|
+
// Expansion consumes the precise host LUT even for variant 6.
|
|
67
|
+
const float value=trellis_val_rcp(win);
|
|
68
|
+
w=T(value*float(scales[row]));
|
|
69
|
+
}
|
|
70
|
+
Bs[b]=w;
|
|
71
|
+
}
|
|
72
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
73
|
+
#pragma clang loop unroll(full)
|
|
74
|
+
for(uint kk=0;kk<BK;kk+=8) {
|
|
75
|
+
metal::simdgroup_float8x8 a[TM],b[TN];
|
|
76
|
+
#pragma clang loop unroll(full)
|
|
77
|
+
for(uint i=0;i<TM;i++) {
|
|
78
|
+
a[i].thread_elements()[0]=float(As[(sm+i*SM)*BK+kk+fn]);
|
|
79
|
+
a[i].thread_elements()[1]=float(As[(sm+i*SM)*BK+kk+fn+1]);
|
|
80
|
+
}
|
|
81
|
+
#pragma clang loop unroll(full)
|
|
82
|
+
for(uint j=0;j<TN;j++) {
|
|
83
|
+
b[j].thread_elements()[0]=float(Bs[(kk+fm)*BN+sn+j*SN]);
|
|
84
|
+
b[j].thread_elements()[1]=float(Bs[(kk+fm)*BN+sn+j*SN+1]);
|
|
85
|
+
}
|
|
86
|
+
#pragma clang loop unroll(full)
|
|
87
|
+
for(uint i=0;i<TM;i++) {
|
|
88
|
+
#pragma clang loop unroll(full)
|
|
89
|
+
for(uint j=0;j<TN;j++) {
|
|
90
|
+
const uint nj=(i%2)?TN-1-j:j;
|
|
91
|
+
metal::simdgroup_multiply_accumulate(acc[i][nj],a[i],b[nj],acc[i][nj]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
96
|
+
}
|
|
97
|
+
#pragma clang loop unroll(full)
|
|
98
|
+
for(uint i=0;i<TM;i++) {
|
|
99
|
+
#pragma clang loop unroll(full)
|
|
100
|
+
for(uint j=0;j<TN;j++) {
|
|
101
|
+
const uint m=mbase+sm+i*SM,n=nbase+sn+j*SN;
|
|
102
|
+
if(m<M && n<N)out[(ulong)m*N+n]=T(acc[i][j].thread_elements()[0]);
|
|
103
|
+
if(m<M && n+1<N)out[(ulong)m*N+n+1]=T(acc[i][j].thread_elements()[1]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
` });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Shared operation for bf16 [M, K], axis-1 1MAD, T=256/L=12, k=2/3/4.
|
|
110
|
+
* M=5..32. Borrow inputs and return owned [M, N]; caller controls evaluation.
|
|
111
|
+
* Reconstruct the precise LUT value before bf16 weight rounding. The default
|
|
112
|
+
* packed matvec's unrefined f32 code value is a different numerical contract.
|
|
113
|
+
* Other geometries need a measured dispatch profile and model-level gates. */
|
|
114
|
+
export function tiledTrellisPrefill(
|
|
115
|
+
x: MlxArray, codes: MlxArray, scales: MlxArray, g: TrellisGeometry,
|
|
116
|
+
): MlxArray {
|
|
117
|
+
const [m, k] = x.shape;
|
|
118
|
+
if (x.ndim !== 2 || x.dtype !== Dtype.bfloat16 || !m || m < 5 || m > 32 ||
|
|
119
|
+
k !== g.inFeatures || g.axis !== 1 || g.T !== 256 || g.L !== 12 ||
|
|
120
|
+
![2, 3, 4].includes(g.k) || g.cols % 256 !== 0 || g.rows < 1)
|
|
121
|
+
throw new Error("unsupported tiled trellis prefill geometry or dtype");
|
|
122
|
+
const bm = m <= 8 ? 8 : m <= 16 ? 16 : 32, bn = 64, bk = 16;
|
|
123
|
+
const [out] = tiledKernel().apply([x, codes, scales], {
|
|
124
|
+
outputs: [{ shape: [m, g.outFeatures], dtype: x.dtype }],
|
|
125
|
+
grid: [Math.ceil(g.outFeatures / bn) * 128, Math.ceil(m / bm), 1],
|
|
126
|
+
threadGroup: [128, 1, 1], templateDtypes: { T: x.dtype },
|
|
127
|
+
templateInts: { M: m, N: g.outFeatures, KC: g.inFeatures, C: g.cols,
|
|
128
|
+
BITS: g.k, L: g.L, BT: g.T, AXIS: g.axis, BM: bm, BN: bn, BK: bk },
|
|
129
|
+
});
|
|
130
|
+
return out!;
|
|
131
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Four adjacent weights share one circular packed-word window. Keep the
|
|
2
|
+
// precise expansion values and MLX's matmul/evaluation boundary unchanged.
|
|
3
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
4
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
5
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
6
|
+
import type { TrellisGeometry } from "./geometry";
|
|
7
|
+
import { HEADER } from "./codebook";
|
|
8
|
+
|
|
9
|
+
const kernel = new MetalKernel({
|
|
10
|
+
name: "mlx_bun_trellis_vector_expand",
|
|
11
|
+
inputNames: ["codes", "scales"], outputNames: ["out"], header: HEADER,
|
|
12
|
+
source: String.raw`
|
|
13
|
+
uint c = thread_position_in_grid.x * 4;
|
|
14
|
+
uint r = thread_position_in_grid.y;
|
|
15
|
+
if constexpr (ROW_TILE > 0) {
|
|
16
|
+
constexpr uint groups = C / (BT * 2);
|
|
17
|
+
const uint tg = threadgroup_position_in_grid.x;
|
|
18
|
+
const uint tile = tg / (groups * ROW_TILE), within = tg % (groups * ROW_TILE);
|
|
19
|
+
r = tile * ROW_TILE + within % ROW_TILE;
|
|
20
|
+
c = (within / ROW_TILE) * BT * 2 + thread_position_in_threadgroup.x * 4;
|
|
21
|
+
}
|
|
22
|
+
if (c >= C || r >= R) return;
|
|
23
|
+
constexpr uint wpb = BT * BITS / 32;
|
|
24
|
+
const uint block = c / BT, t = c % BT;
|
|
25
|
+
const device uint* bw = codes + (INTERLEAVE
|
|
26
|
+
? (ulong)(block / 2) * R * 2 * wpb + (ulong)r * 2 * wpb + (block % 2) * wpb
|
|
27
|
+
: (ulong)r * (C / BT) * wpb + block * wpb);
|
|
28
|
+
const float scale = float(scales[r]);
|
|
29
|
+
// The last of four weights starts the window. Earlier weights occupy
|
|
30
|
+
// its higher bits; a second word also handles the circular block edge.
|
|
31
|
+
const uint pos = (BT - 1 - (t + 3)) * BITS, wi = pos >> 5, off = pos & 31u;
|
|
32
|
+
const ulong window = (ulong(bw[wi]) | (ulong(bw[wi + 1 == wpb ? 0 : wi + 1]) << 32)) >> off;
|
|
33
|
+
#pragma clang loop unroll(full)
|
|
34
|
+
for (uint i = 0; i < 4; i++) {
|
|
35
|
+
const uint s = uint(window >> ((3 - i) * BITS)) & ((1u << L) - 1);
|
|
36
|
+
// Residual refinement reproduces the host f32 LUT before scaling.
|
|
37
|
+
const float value = trellis_val_rcp(s);
|
|
38
|
+
out[(ulong)r * C + c + i] = T(value * scale);
|
|
39
|
+
}
|
|
40
|
+
`,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export function vectorTrellisExpandEligible(g: TrellisGeometry, dtype: Dtype): boolean {
|
|
44
|
+
return dtype === Dtype.bfloat16 && g.L === 12 && g.T === 256 &&
|
|
45
|
+
(g.k === 2 || g.k === 3 || g.k === 4) && g.rows > 0 && g.cols > 0 && g.cols % 256 === 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Decode the stored matrix; the caller owns the projection's evaluation boundary. */
|
|
49
|
+
export function vectorTrellisExpand(codes: MlxArray, scales: MlxArray, g: TrellisGeometry): MlxArray {
|
|
50
|
+
const rowTile = g.blockInterleave && g.rows % 128 === 0 ? 128 : 0;
|
|
51
|
+
return kernel.apply([codes, scales], {
|
|
52
|
+
outputs: [{ shape: [g.rows, g.cols], dtype: Dtype.bfloat16 }],
|
|
53
|
+
grid: rowTile ? [g.cols / 4 * g.rows, 1, 1] : [g.cols / 4, g.rows, 1], threadGroup: [128, 1, 1],
|
|
54
|
+
templateDtypes: { T: Dtype.bfloat16 },
|
|
55
|
+
templateInts: { R: g.rows, C: g.cols, BT: g.T, BITS: g.k, L: g.L,
|
|
56
|
+
INTERLEAVE: g.blockInterleave ?? 0, ROW_TILE: rowTile },
|
|
57
|
+
})[0]!;
|
|
58
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Packed Trellis prefill with MLX 0.32.2 GemvWide arithmetic.
|
|
2
|
+
// Ported from ml-explore/mlx v0.32.2, mlx/backend/metal/kernels/gemv.h
|
|
3
|
+
// (MIT). Decode weights to bf16 inside the native dot/unroll/shuffle order;
|
|
4
|
+
// share each decoded row across every input vector in this narrow regime.
|
|
5
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
6
|
+
import { type MlxArray } from "@mlx-bun/mlx/array";
|
|
7
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
8
|
+
import { type TrellisGeometry } from "./geometry";
|
|
9
|
+
import { HEADER } from "./codebook";
|
|
10
|
+
|
|
11
|
+
/** Matches the bundled runtime's native reduction where the GPU family has it
|
|
12
|
+
* (`widePrefill` from `qualifiedRepresentations`, resolved by the caller). */
|
|
13
|
+
export function nativeTrellisWidePrefill(m: number, widePrefill: boolean): boolean {
|
|
14
|
+
return m >= 5 && m <= 15 && widePrefill;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function wideTrellisPrefillEligible(g: TrellisGeometry, m: number, dtype: Dtype, widePrefill: boolean): boolean {
|
|
18
|
+
return dtype === Dtype.bfloat16 && nativeTrellisWidePrefill(m, widePrefill) &&
|
|
19
|
+
g.axis === 1 && g.T === 256 && g.L === 12 && [2, 3, 4].includes(g.k) &&
|
|
20
|
+
g.inFeatures === 5120 && g.outFeatures === 17408 && !g.blockInterleave;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let kernel: MetalKernel | undefined;
|
|
24
|
+
function wideKernel() {
|
|
25
|
+
return kernel ??= new MetalKernel({ name: 'mlx_bun_trellis_wide_prefill',
|
|
26
|
+
inputNames: ['x', 'codes', 'scales'], outputNames: ['out'], header: HEADER, source: String.raw`
|
|
27
|
+
constexpr uint unroll=8, rows_per_simd=32/KL, simdgroups=KL/8;
|
|
28
|
+
const uint lane=thread_index_in_simdgroup, sg=simdgroup_index_in_threadgroup;
|
|
29
|
+
const uint kl=lane%KL, row=threadgroup_position_in_grid.y*4+sg*rows_per_simd+lane/KL;
|
|
30
|
+
const uint vec0=threadgroup_position_in_grid.x*SM;
|
|
31
|
+
constexpr uint wpb=BT*BITS/32, row_words=KC*BITS/32;
|
|
32
|
+
const float scale=float(scales[row]);
|
|
33
|
+
constexpr uint n_v4=KC/4, n_main=n_v4-n_v4%(KL*unroll);
|
|
34
|
+
float result[SM]={0};
|
|
35
|
+
for(uint base=0;base<n_main;base+=KL*unroll) {
|
|
36
|
+
float4 wf[unroll];
|
|
37
|
+
#pragma clang loop unroll(full)
|
|
38
|
+
for(uint i=0;i<unroll;i++) {
|
|
39
|
+
#pragma clang loop unroll(full)
|
|
40
|
+
for(uint c=0;c<4;c++) {
|
|
41
|
+
const uint k=(base+i*KL+kl)*4+c, block=k/BT, t=k%BT;
|
|
42
|
+
const device uint* bw=codes+(ulong)row*row_words+block*wpb;
|
|
43
|
+
const uint pos=(BT-1-t)*BITS, wi=pos>>5, off=pos&31u;
|
|
44
|
+
uint win=bw[wi]>>off;
|
|
45
|
+
if(off+L>32)win|=bw[wi+1==wpb?0:wi+1]<<(32-off);
|
|
46
|
+
win&=(1u<<L)-1;
|
|
47
|
+
const float value=trellis_val_rcp(win);
|
|
48
|
+
wf[i][c]=float(T(value*scale));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
#pragma clang loop unroll(full)
|
|
52
|
+
for(uint v=0;v<SM;v++) {
|
|
53
|
+
const uint m=min(vec0+v,uint(M-1));
|
|
54
|
+
float acc=0;
|
|
55
|
+
#pragma clang loop unroll(full)
|
|
56
|
+
for(uint i=0;i<unroll;i++) {
|
|
57
|
+
const ulong offset=(ulong)m*KC+(base+i*KL+kl)*4;
|
|
58
|
+
const float4 xv=float4(float(x[offset]),float(x[offset+1]),float(x[offset+2]),float(x[offset+3]));
|
|
59
|
+
acc+=metal::dot(wf[i],xv);
|
|
60
|
+
}
|
|
61
|
+
result[v]+=acc;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
#pragma clang loop unroll(full)
|
|
65
|
+
for(uint v=0;v<SM;v++) {
|
|
66
|
+
#pragma clang loop unroll(full)
|
|
67
|
+
for(ushort off=KL/2;off>=1;off>>=1) result[v]+=simd_shuffle_down(result[v],off);
|
|
68
|
+
if(kl==0 && vec0+v<M) out[(ulong)(vec0+v)*N+row]=T(result[v]);
|
|
69
|
+
}
|
|
70
|
+
` });
|
|
71
|
+
}
|
|
72
|
+
/** Requires the caller to prove aligned, row-contiguous x, as Qwen does
|
|
73
|
+
* with its RMSNorm output. Preserve native fallback when that proof is absent. */
|
|
74
|
+
export function wideTrellisPrefill(x: MlxArray, codes: MlxArray, scales: MlxArray, g: TrellisGeometry): MlxArray {
|
|
75
|
+
const [m, k] = x.shape;
|
|
76
|
+
if (x.ndim !== 2 || x.dtype !== Dtype.bfloat16 || !m || m < 5 || m > 15 ||
|
|
77
|
+
k !== 5120 || g.inFeatures !== k || g.axis !== 1 || g.T !== 256 || g.L !== 12 ||
|
|
78
|
+
![2, 3, 4].includes(g.k) || g.blockInterleave || g.rows < 4 || g.rows % 4 ||
|
|
79
|
+
g.outFeatures !== g.rows || g.cols !== k || codes.dtype !== Dtype.uint32 ||
|
|
80
|
+
codes.ndim !== 2 || codes.shape[0] !== g.rows || codes.shape[1] !== k * g.k / 32 || scales.size !== g.rows)
|
|
81
|
+
throw new Error("unsupported wide trellis prefill geometry, dtype or layout");
|
|
82
|
+
const kl = m <= 5 ? 32 : 16;
|
|
83
|
+
return wideKernel().apply([x, codes, scales], {
|
|
84
|
+
outputs: [{ shape: [m, g.outFeatures], dtype: x.dtype }],
|
|
85
|
+
grid: [32, g.outFeatures / 4 * (kl / 8), 1], threadGroup: [32, kl / 8, 1],
|
|
86
|
+
templateDtypes: { T: x.dtype },
|
|
87
|
+
templateInts: { M: m, SM: m, KL: kl, KC: k, N: g.outFeatures, BT: g.T, L: g.L, BITS: g.k },
|
|
88
|
+
})[0]!;
|
|
89
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Exact byte-packed TurboQuant K/V decoding. The caller owns output arrays.
|
|
2
|
+
// Rotation and cache policy belong to the existing codec/cache layers.
|
|
3
|
+
import { type MlxArray, gpuStream } from '@mlx-bun/mlx/array';
|
|
4
|
+
import { Dtype, type MlxHandle } from '@mlx-bun/mlx/ffi';
|
|
5
|
+
import { isShapelessTracing } from '@mlx-bun/mlx/compile';
|
|
6
|
+
import { MetalKernel } from '@mlx-bun/mlx/metal-kernel';
|
|
7
|
+
|
|
8
|
+
export type PackedKvArrays = readonly [
|
|
9
|
+
keyIndices: MlxArray, keyScales: MlxArray, keyZeros: MlxArray,
|
|
10
|
+
valueIndices: MlxArray, valueScales: MlxArray,
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const source = `
|
|
14
|
+
uint col = thread_position_in_grid.x, pos = thread_position_in_grid.y;
|
|
15
|
+
uint bh = thread_position_in_grid.z;
|
|
16
|
+
if (col >= D || pos >= vp_shape[2] || bh >= vp_shape[0] * vp_shape[1]) return;
|
|
17
|
+
uint b = bh / vp_shape[1], h = bh % vp_shape[1];
|
|
18
|
+
uint ko = b * kp_strides[0] + h * kp_strides[1] + pos * kp_strides[2];
|
|
19
|
+
uint vpo = b * vp_strides[0] + h * vp_strides[1] + pos * vp_strides[2];
|
|
20
|
+
uint kso = b * ks_strides[0] + h * ks_strides[1] + pos * ks_strides[2] + (col / KG) * ks_strides[3];
|
|
21
|
+
uint kzo = b * kz_strides[0] + h * kz_strides[1] + pos * kz_strides[2] + (col / KG) * kz_strides[3];
|
|
22
|
+
uint vso = b * vs_strides[0] + h * vs_strides[1] + pos * vs_strides[2] + (col / VG) * vs_strides[3];
|
|
23
|
+
int key_code;
|
|
24
|
+
if (KBITS == 8) key_code = int(kp[ko + col * kp_strides[3]]);
|
|
25
|
+
else {
|
|
26
|
+
uint bit = col * KBITS, byte = bit / 8u, shift = bit % 8u;
|
|
27
|
+
uint word = uint(kp[ko + byte * kp_strides[3]]);
|
|
28
|
+
if (shift + KBITS > 8u) word |= uint(kp[ko + (byte + 1u) * kp_strides[3]]) << 8u;
|
|
29
|
+
key_code = int((word >> shift) & ((1u << KBITS) - 1u));
|
|
30
|
+
}
|
|
31
|
+
// Keep the incumbent f32 addition before multiplication.
|
|
32
|
+
float shifted = float(key_code) + float(kz[kzo]);
|
|
33
|
+
uint i = (bh * vp_shape[2] + pos) * D + col;
|
|
34
|
+
outK[i] = OutK(shifted * float(ks[kso]));
|
|
35
|
+
uint bit = col * VBITS, byte = bit / 8u, shift = bit % 8u;
|
|
36
|
+
uint word = uint(vp[vpo + byte * vp_strides[3]]);
|
|
37
|
+
if (shift + VBITS > 8u) word |= uint(vp[vpo + (byte + 1u) * vp_strides[3]]) << 8u;
|
|
38
|
+
uint code = (word >> shift) & ((1u << VBITS) - 1u);
|
|
39
|
+
outV[i] = OutV(centroids[code] * float(vs[vso]));
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
let kernel: MetalKernel | undefined;
|
|
43
|
+
function jointKernel(): MetalKernel {
|
|
44
|
+
return kernel ??= new MetalKernel({
|
|
45
|
+
name: 'turboquant_kv_decode',
|
|
46
|
+
inputNames: ['kp', 'ks', 'kz', 'vp', 'vs', 'centroids'],
|
|
47
|
+
outputNames: ['outK', 'outV'], source, ensureRowContiguous: false,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Return bf16 K and rotated V (f32 for eager inverse rotation, bf16 for
|
|
52
|
+
* deferred rotation). Null means the ordinary codec must handle this input.
|
|
53
|
+
* Input arrays and the shared centroid table remain borrowed. */
|
|
54
|
+
export function tryJointDecodePackedKv(
|
|
55
|
+
inputs: PackedKvArrays, centroids: MlxArray, kBits: number, vBits: number,
|
|
56
|
+
headDim: number, deferV: boolean, stream: MlxHandle = gpuStream,
|
|
57
|
+
): [MlxArray, MlxArray] | null {
|
|
58
|
+
if (stream !== gpuStream || isShapelessTracing() ||
|
|
59
|
+
![64, 128, 256, 512].includes(headDim) ||
|
|
60
|
+
![2, 4, 5, 8].includes(kBits) || ![2, 3, 4, 5, 8].includes(vBits)) return null;
|
|
61
|
+
const [kp, ks, kz, vp, vs] = inputs;
|
|
62
|
+
if (kp.dtype !== (kBits === 8 ? Dtype.int8 : Dtype.uint8) ||
|
|
63
|
+
vp.dtype !== Dtype.uint8 || centroids.dtype !== Dtype.float32 ||
|
|
64
|
+
centroids.ndim !== 1 || centroids.size !== (1 << vBits)) return null;
|
|
65
|
+
const shapes = inputs.map(a => a.shape);
|
|
66
|
+
if (shapes.some(shape => shape.length !== 4)) return null;
|
|
67
|
+
const [b, h, n] = shapes[3]!;
|
|
68
|
+
if (!b || !h || !n || b * h * n * headDim >= 2 ** 32 ||
|
|
69
|
+
shapes.some(shape => shape[0] !== b || shape[1] !== h || shape[2] !== n) ||
|
|
70
|
+
shapes[0]![3] !== headDim * kBits / 8 || shapes[3]![3] !== headDim * vBits / 8 ||
|
|
71
|
+
shapes[1]![3] !== shapes[2]![3]) return null;
|
|
72
|
+
const keyGroup = headDim / shapes[1]![3]!, valueGroup = headDim / shapes[4]![3]!;
|
|
73
|
+
if (![32, 64].includes(keyGroup) || ![32, 64].includes(valueGroup) ||
|
|
74
|
+
[ks, kz, vs].some(a => ![Dtype.float16, Dtype.bfloat16, Dtype.float32].includes(a.dtype))) return null;
|
|
75
|
+
const shape = [b, h, n, headDim], valueDtype = deferV ? Dtype.bfloat16 : Dtype.float32;
|
|
76
|
+
return jointKernel().apply([...inputs, centroids], {
|
|
77
|
+
templateDtypes: { OutK: Dtype.bfloat16, OutV: valueDtype },
|
|
78
|
+
templateInts: { D: headDim, KBITS: kBits, VBITS: vBits, KG: keyGroup, VG: valueGroup },
|
|
79
|
+
grid: [headDim, n, b * h], threadGroup: [Math.min(headDim, 256), Math.max(1, 256 / headDim), 1],
|
|
80
|
+
outputs: [{ shape, dtype: Dtype.bfloat16 }, { shape, dtype: valueDtype }], stream,
|
|
81
|
+
}) as [MlxArray, MlxArray];
|
|
82
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Joint packed K/V decode with eager inverse rotation in the measured D256 regime.
|
|
2
|
+
// Hadamard butterfly/layout follows MLX 0.31.2,
|
|
3
|
+
// mlx/backend/metal/kernels/hadamard.h, Copyright © 2024 Apple Inc., MIT.
|
|
4
|
+
import { type MlxArray, gpuStream } from "@mlx-bun/mlx/array";
|
|
5
|
+
import { Dtype, type MlxHandle } from "@mlx-bun/mlx/ffi";
|
|
6
|
+
import { isShapelessTracing } from "@mlx-bun/mlx/compile";
|
|
7
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
8
|
+
import { type PackedKvArrays } from "./decode";
|
|
9
|
+
|
|
10
|
+
const header = `
|
|
11
|
+
template <short R> inline void tq_inverse_radix(thread float* x) {
|
|
12
|
+
constexpr short logR = __builtin_ctz(R);
|
|
13
|
+
short h = 1;
|
|
14
|
+
#pragma unroll
|
|
15
|
+
for (short s = 0; s < logR; s++) {
|
|
16
|
+
#pragma unroll
|
|
17
|
+
for (short i = 0; i < R / 2; i++) {
|
|
18
|
+
short k = i & (h - 1), j = ((i - k) << 1) + k;
|
|
19
|
+
float a = x[j], b = x[j + h];
|
|
20
|
+
x[j] = a + b; x[j + h] = a - b;
|
|
21
|
+
}
|
|
22
|
+
h <<= 1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
const source = `
|
|
27
|
+
constexpr short D = 256, R = 16, NT = 16, LOG_R = 4;
|
|
28
|
+
uint pos = thread_position_in_grid.y, bh = thread_position_in_grid.z;
|
|
29
|
+
short i = thread_position_in_grid.x;
|
|
30
|
+
bool valid = pos < vp_shape[2];
|
|
31
|
+
uint b = bh / vp_shape[1], hidx = bh % vp_shape[1];
|
|
32
|
+
uint ko = b * kp_strides[0] + hidx * kp_strides[1] + pos * kp_strides[2];
|
|
33
|
+
uint vo = b * vp_strides[0] + hidx * vp_strides[1] + pos * vp_strides[2];
|
|
34
|
+
uint kso = b * ks_strides[0] + hidx * ks_strides[1] + pos * ks_strides[2];
|
|
35
|
+
uint kzo = b * kz_strides[0] + hidx * kz_strides[1] + pos * kz_strides[2];
|
|
36
|
+
uint vso = b * vs_strides[0] + hidx * vs_strides[1] + pos * vs_strides[2];
|
|
37
|
+
uint row = (bh * vp_shape[2] + pos) * D;
|
|
38
|
+
threadgroup float storage[D * 16];
|
|
39
|
+
threadgroup float* buf = storage + thread_position_in_threadgroup.y * D;
|
|
40
|
+
#pragma unroll
|
|
41
|
+
for (short j = 0; j < R / 4; j++) {
|
|
42
|
+
short index = j * 4 * NT + i * 4;
|
|
43
|
+
#pragma unroll
|
|
44
|
+
for (short r = 0; r < 4; r++) {
|
|
45
|
+
uint col = index + r;
|
|
46
|
+
if (!valid) { buf[col] = 0.0f; continue; }
|
|
47
|
+
int key_code = int(kp[ko + col * kp_strides[3]]);
|
|
48
|
+
float shifted = float(key_code) + float(kz[kzo + (col / 32) * kz_strides[3]]);
|
|
49
|
+
outK[row + col] = OutK(shifted * float(ks[kso + (col / 32) * ks_strides[3]]));
|
|
50
|
+
uint bit = col * 3u, byte = bit / 8u, shift = bit % 8u;
|
|
51
|
+
uint word = uint(vp[vo + byte * vp_strides[3]]);
|
|
52
|
+
if (shift + 3u > 8u) word |= uint(vp[vo + (byte + 1u) * vp_strides[3]]) << 8u;
|
|
53
|
+
uint code = (word >> shift) & 7u;
|
|
54
|
+
buf[col] = centroids[code * centroids_strides[0]] * float(vs[vso + (col / 32) * vs_strides[3]]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
threadgroup_barrier(mem_flags::mem_threadgroup);
|
|
58
|
+
float x[R]; short h = 1;
|
|
59
|
+
#pragma unroll
|
|
60
|
+
for (short s = 0; s < 2; s++) {
|
|
61
|
+
short k = i & (h - 1), j = ((i - k) << LOG_R) + k;
|
|
62
|
+
#pragma unroll
|
|
63
|
+
for (short r = 0; r < R; r++) x[r] = buf[j + h * r];
|
|
64
|
+
tq_inverse_radix<R>(x);
|
|
65
|
+
#pragma unroll
|
|
66
|
+
for (short r = 0; r < R; r++) buf[j + h * r] = x[r];
|
|
67
|
+
h <<= LOG_R;
|
|
68
|
+
threadgroup_barrier(mem_flags::mem_threadgroup);
|
|
69
|
+
}
|
|
70
|
+
#pragma unroll
|
|
71
|
+
for (short j = 0; j < R / 4; j++) {
|
|
72
|
+
short index = j * 4 * NT + i * 4;
|
|
73
|
+
#pragma unroll
|
|
74
|
+
for (short r = 0; r < 4; r++) {
|
|
75
|
+
uint col = index + r;
|
|
76
|
+
float normalized = buf[col] * 0.0625f;
|
|
77
|
+
if (valid) outV[row + col] = OutV(normalized * signs[col * signs_strides[0]]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
let kernel: MetalKernel | undefined;
|
|
83
|
+
function inverseKernel(): MetalKernel {
|
|
84
|
+
return kernel ??= new MetalKernel({
|
|
85
|
+
name: "turboquant_kv_inverse256",
|
|
86
|
+
inputNames: ["kp", "ks", "kz", "vp", "vs", "centroids", "signs"],
|
|
87
|
+
outputNames: ["outK", "outV"], header, source, ensureRowContiguous: false,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Borrow packed inputs and codec tables; return owned bf16 K/V or null.
|
|
92
|
+
* Only the measured eager D256/k8v3/B1/H4/fp16/group32 regime is eligible.
|
|
93
|
+
* Other regimes continue through the existing joint decoder or original codec.
|
|
94
|
+
* N affects dispatch size but is never a shader template parameter. */
|
|
95
|
+
export function tryDecodePackedKvInverse256(
|
|
96
|
+
inputs: PackedKvArrays, centroids: MlxArray, signs: MlxArray,
|
|
97
|
+
kBits: number, vBits: number, headDim: number, s: MlxHandle = gpuStream,
|
|
98
|
+
): [MlxArray, MlxArray] | null {
|
|
99
|
+
if (s !== gpuStream || isShapelessTracing() || headDim !== 256 || kBits !== 8 || vBits !== 3)
|
|
100
|
+
return null;
|
|
101
|
+
const [kp, ks, kz, vp, vs] = inputs;
|
|
102
|
+
const shape = kp.shape;
|
|
103
|
+
if (shape.length !== 4 || shape[0] !== 1 || shape[1] !== 4 || shape[3] !== 256)
|
|
104
|
+
return null;
|
|
105
|
+
const n = shape[2]!;
|
|
106
|
+
if (n < 8192 || n * 1024 >= 2 ** 32) return null;
|
|
107
|
+
const samePrefix = (a: MlxArray, width: number) => {
|
|
108
|
+
const x = a.shape;
|
|
109
|
+
return x.length === 4 && x[0] === 1 && x[1] === 4 && x[2] === n && x[3] === width;
|
|
110
|
+
};
|
|
111
|
+
if (kp.dtype !== Dtype.int8 || vp.dtype !== Dtype.uint8 || !samePrefix(vp, 96)) return null;
|
|
112
|
+
if (![ks, kz, vs].every(a => a.dtype === Dtype.float16 && samePrefix(a, 8))) return null;
|
|
113
|
+
if (centroids.dtype !== Dtype.float32 || centroids.shape.length !== 1 || centroids.shape[0] !== 8)
|
|
114
|
+
return null;
|
|
115
|
+
if (signs.dtype !== Dtype.float32 || signs.shape.length !== 1 || signs.shape[0] !== 256)
|
|
116
|
+
return null;
|
|
117
|
+
return inverseKernel().apply([...inputs, centroids, signs], {
|
|
118
|
+
templateDtypes: { OutK: Dtype.bfloat16, OutV: Dtype.bfloat16 },
|
|
119
|
+
grid: [16, Math.ceil(n / 16) * 16, 4], threadGroup: [16, 16, 1],
|
|
120
|
+
outputs: [{ shape, dtype: Dtype.bfloat16 }, { shape, dtype: Dtype.bfloat16 }], stream: s,
|
|
121
|
+
}) as [MlxArray, MlxArray];
|
|
122
|
+
}
|