@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,583 @@
|
|
|
1
|
+
// DiffusionGemma denoising generation engine (port D2). Block-diffusion, NOT
|
|
2
|
+
// autoregressive: prefill the prompt once, then for each canvas block fill a
|
|
3
|
+
// fixed-length canvas with uniform-random token ids and un-mask it over <=48
|
|
4
|
+
// denoising steps, feeding the previous step's soft embeddings back in
|
|
5
|
+
// (self-conditioning). Ported verbatim from
|
|
6
|
+
// optiq/vlm/_mlxvlm/generate/diffusion.py (stream_diffusion_generate).
|
|
7
|
+
//
|
|
8
|
+
// RNG parity: canvas init + per-step re-noise draw from a request-local copy of
|
|
9
|
+
// MLX's global key sequence (DenoisingKeys). Drawing in the reference's order
|
|
10
|
+
// reproduces its draws bit-for-bit → token-for-token parity on a fixed seed,
|
|
11
|
+
// and interleaved requests never consume each other's draws.
|
|
12
|
+
//
|
|
13
|
+
// Implements the public-API default sampler (confidence-threshold) AND the
|
|
14
|
+
// model-default (entropy-bound). temperature 0 (greedy) is the default and the
|
|
15
|
+
// only RNG consumers then are the canvas draws.
|
|
16
|
+
|
|
17
|
+
import type { DenoisingGraph } from "../contracts/portable/denoising";
|
|
18
|
+
import { assertMlxDenoisingGraph, bindLegacyDenoisingModel, type MlxDenoisingModel } from "./bindings/denoising";
|
|
19
|
+
import { cleanupFailure, disposeResources, ownResource } from "../runtime/resources";
|
|
20
|
+
import type { DisposableResource, ResourceOwner } from "../contracts/portable/resources";
|
|
21
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
22
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
23
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
24
|
+
import { disposing } from "../layers/helpers";
|
|
25
|
+
|
|
26
|
+
export interface DiffusionGenOptions {
|
|
27
|
+
maxTokens: number;
|
|
28
|
+
maxDenoisingSteps?: number; // default 48
|
|
29
|
+
minCanvasLength?: number; // default 64
|
|
30
|
+
maxCanvasLength?: number; // default model canvas (256)
|
|
31
|
+
fullCanvas?: boolean; // force full model canvas each block
|
|
32
|
+
sampler?: "confidence-threshold" | "entropy-bound"; // default confidence-threshold
|
|
33
|
+
threshold?: number; // confidence accept threshold (default 0.9)
|
|
34
|
+
entropyBound?: number; // entropy sampler bound (default 0.1)
|
|
35
|
+
temperature?: number; // default 0 (greedy)
|
|
36
|
+
tMin?: number; // schedule (default 0.4)
|
|
37
|
+
tMax?: number; // schedule (default 0.8)
|
|
38
|
+
// stable+confident early stop. The shipped checkpoint loads
|
|
39
|
+
// generation_config=None in optiq, so this is OFF in the oracle (entropy runs
|
|
40
|
+
// all steps). Only enabled when BOTH are provided (mirrors stopping_config).
|
|
41
|
+
stabilityThreshold?: number;
|
|
42
|
+
confidenceThreshold?: number;
|
|
43
|
+
eosTokenIds?: number[]; // default [1, 106] (the tokenizer stopping set; NOT 50)
|
|
44
|
+
seed?: bigint; // request-local key sequence seed (default 0)
|
|
45
|
+
/** Dequantized embedding table for self-conditioning. Borrowed: the caller
|
|
46
|
+
* keeps ownership. Absent → the run dequantizes and owns its own copy. */
|
|
47
|
+
embedWeight?: MlxArray;
|
|
48
|
+
/** Image-text-to-text: when set, `promptIds` are the SPLICED ids (with the
|
|
49
|
+
* <|image|> run) and the encoder prefills with the merged vision features +
|
|
50
|
+
* bidirectional overlay instead of the plain text path. Channel-first
|
|
51
|
+
* [1,3,H,W]. Caller keeps ownership. */
|
|
52
|
+
visionPixels?: MlxArray;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface DiffusionGenResult {
|
|
56
|
+
tokens: number[]; // emitted tokens (EOS-trimmed, EOS excluded)
|
|
57
|
+
blocks: number[][]; // per-block final argmax canvases (full, pre-trim)
|
|
58
|
+
steps: number; // total denoising steps run
|
|
59
|
+
finishReason: "stop" | "length";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const I32 = Dtype.int32;
|
|
63
|
+
|
|
64
|
+
/** logits / schedule_temperature (the diffusion linear temperature schedule). */
|
|
65
|
+
function linearTemp(curStep: number, maxSteps: number, tMin: number, tMax: number): number {
|
|
66
|
+
return tMin + (tMax - tMin) * (curStep / maxSteps);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** confidence = exp(token_logit - logsumexp(logits)) in fp32 (per position). */
|
|
70
|
+
function tokenProbability(processed: MlxArray, tokenIds: MlxArray): MlxArray {
|
|
71
|
+
const lf = processed.astype(Dtype.float32);
|
|
72
|
+
const tokExp = ops.expandDims(tokenIds, -1); // [1, L, 1]
|
|
73
|
+
const gathered = ops.takeAlongAxis(lf, tokExp, -1); // [1, L, 1]
|
|
74
|
+
tokExp.dispose();
|
|
75
|
+
const [b, l] = gathered.shape as [number, number, number];
|
|
76
|
+
const tokLogits = ops.reshape(gathered, [b, l]); // squeeze(-1)
|
|
77
|
+
gathered.dispose();
|
|
78
|
+
const lse = ops.logsumexpAxis(lf, -1, false); // [1, L]
|
|
79
|
+
lf.dispose();
|
|
80
|
+
const diff = ops.sub(tokLogits, lse);
|
|
81
|
+
tokLogits.dispose();
|
|
82
|
+
lse.dispose();
|
|
83
|
+
const conf = ops.exp(diff);
|
|
84
|
+
diff.dispose();
|
|
85
|
+
return conf;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** entropy chain (reference _diffusion_entropy_probs_chain): returns
|
|
89
|
+
* { probs, entropy } in fp32. probs = exp(logits - logsumexp). */
|
|
90
|
+
function entropyProbsChain(processed: MlxArray): { probs: MlxArray; entropy: MlxArray } {
|
|
91
|
+
const lf = processed.astype(Dtype.float32);
|
|
92
|
+
const lse = ops.logsumexpAxis(lf, -1, true); // [1, L, 1]
|
|
93
|
+
const logProbs = ops.sub(lf, lse);
|
|
94
|
+
lf.dispose();
|
|
95
|
+
lse.dispose();
|
|
96
|
+
const probs = ops.exp(logProbs);
|
|
97
|
+
const prod = ops.mul(probs, logProbs);
|
|
98
|
+
logProbs.dispose();
|
|
99
|
+
const summed = ops.sumAxis(prod, -1, false); // [1, L]
|
|
100
|
+
prod.dispose();
|
|
101
|
+
const entropy = ops.mulScalar(summed, -1);
|
|
102
|
+
summed.dispose();
|
|
103
|
+
return { probs, entropy };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** per-position entropy -sum(p*logp) over vocab, fp32. */
|
|
107
|
+
function tokenEntropy(processed: MlxArray): MlxArray {
|
|
108
|
+
const { probs, entropy } = entropyProbsChain(processed);
|
|
109
|
+
probs.dispose();
|
|
110
|
+
return entropy;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** soft embeddings from precomputed probs (entropy sampler path):
|
|
114
|
+
* (probs.astype(w) @ w).astype(w) * embed_scale. */
|
|
115
|
+
function softEmbeddingsFromProbs(probs: MlxArray, weight: MlxArray, embedScale: number): MlxArray {
|
|
116
|
+
const pc = probs.astype(weight.dtype);
|
|
117
|
+
const m = ops.matmul(pc, weight);
|
|
118
|
+
pc.dispose();
|
|
119
|
+
const mc = m.astype(weight.dtype);
|
|
120
|
+
m.dispose();
|
|
121
|
+
const out = ops.mulScalar(mc, embedScale);
|
|
122
|
+
mc.dispose();
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** confidence-threshold acceptance mask (reference _diffusion_confidence_transfer_mask). */
|
|
127
|
+
function confidenceTransferMask(
|
|
128
|
+
confidence: MlxArray,
|
|
129
|
+
unrevealed: MlxArray,
|
|
130
|
+
threshold: number,
|
|
131
|
+
forceAll: boolean,
|
|
132
|
+
): MlxArray {
|
|
133
|
+
if (forceAll) return ops.logicalNot(ops.logicalNot(unrevealed)); // copy of unrevealed
|
|
134
|
+
const thr = ops.scalarLike(threshold, confidence);
|
|
135
|
+
const ge = ops.greaterEqual(confidence, thr);
|
|
136
|
+
thr.dispose();
|
|
137
|
+
const transfer = ops.logicalAnd(unrevealed, ge);
|
|
138
|
+
ge.dispose();
|
|
139
|
+
const hasUnrevealed = ops.anyAxis(unrevealed, -1, true); // [1, 1]
|
|
140
|
+
const hasTransfer = ops.anyAxis(transfer, -1, true); // [1, 1]
|
|
141
|
+
const notTransfer = ops.logicalNot(hasTransfer);
|
|
142
|
+
hasTransfer.dispose();
|
|
143
|
+
const needsForce = ops.logicalAnd(hasUnrevealed, notTransfer); // [1, 1]
|
|
144
|
+
hasUnrevealed.dispose();
|
|
145
|
+
notTransfer.dispose();
|
|
146
|
+
const negInf = ops.scalarLike(-Infinity, confidence);
|
|
147
|
+
const maskedConf = ops.where(unrevealed, confidence, negInf); // [1, L]
|
|
148
|
+
negInf.dispose();
|
|
149
|
+
const best = ops.argmaxAxis(maskedConf, -1); // [1]
|
|
150
|
+
maskedConf.dispose();
|
|
151
|
+
const L = confidence.shape[confidence.shape.length - 1]!;
|
|
152
|
+
const positions = ops.arange(0, L, 1, I32); // [L]
|
|
153
|
+
const posRow = ops.reshape(positions, [1, L]);
|
|
154
|
+
positions.dispose();
|
|
155
|
+
const bestCol = ops.reshape(best, [1, 1]);
|
|
156
|
+
best.dispose();
|
|
157
|
+
const eq = ops.equal(posRow, bestCol); // [1, L]
|
|
158
|
+
posRow.dispose();
|
|
159
|
+
bestCol.dispose();
|
|
160
|
+
const forced = ops.logicalAnd(eq, needsForce); // broadcast [1, L]
|
|
161
|
+
eq.dispose();
|
|
162
|
+
needsForce.dispose();
|
|
163
|
+
const out = ops.logicalOr(transfer, forced);
|
|
164
|
+
transfer.dispose();
|
|
165
|
+
forced.dispose();
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** entropy-bound acceptance mask (reference _diffusion_entropy_transfer_mask):
|
|
170
|
+
* sort positions by ascending entropy; accept the lowest-entropy prefix while
|
|
171
|
+
* cumsum - cummax <= bound; unsort. */
|
|
172
|
+
function entropyTransferMask(entropy: MlxArray, bound: number): MlxArray {
|
|
173
|
+
const sortedIdx = ops.argsortAxis(entropy, -1); // [1, L]
|
|
174
|
+
const sortedEnt = ops.takeAlongAxis(entropy, sortedIdx, -1);
|
|
175
|
+
const cum = ops.cumsum(sortedEnt, -1);
|
|
176
|
+
const cmax = ops.cummax(sortedEnt, -1);
|
|
177
|
+
sortedEnt.dispose();
|
|
178
|
+
const delta = ops.sub(cum, cmax);
|
|
179
|
+
cum.dispose();
|
|
180
|
+
cmax.dispose();
|
|
181
|
+
const boundArr = ops.scalarLike(bound, delta);
|
|
182
|
+
const sortedSel = ops.lessEqual(delta, boundArr); // [1, L] bool
|
|
183
|
+
delta.dispose();
|
|
184
|
+
boundArr.dispose();
|
|
185
|
+
// put_along_axis: scatter sortedSel back via sortedIdx into a zero mask.
|
|
186
|
+
const zeros = ops.zeros(sortedSel.shape, sortedSel.dtype);
|
|
187
|
+
const out = ops.putAlongAxis(zeros, sortedIdx, sortedSel, -1);
|
|
188
|
+
zeros.dispose();
|
|
189
|
+
sortedIdx.dispose();
|
|
190
|
+
sortedSel.dispose();
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Request-local copy of MLX 0.32.2's global key sequence (random.cpp
|
|
195
|
+
* KeySequence): seed(s) installs key(s); each unkeyed draw splits the current
|
|
196
|
+
* key, keeps the first half and draws with the second. Equal seeds therefore
|
|
197
|
+
* give byte-identical draws to random.seed + unkeyed randint, without reading
|
|
198
|
+
* or reseeding the process-wide key. */
|
|
199
|
+
export class DenoisingKeys {
|
|
200
|
+
#key: MlxArray;
|
|
201
|
+
|
|
202
|
+
constructor(seed: bigint) {
|
|
203
|
+
this.#key = ops.randomKey(seed);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Uniform int32 ids in [0, high), advancing this sequence by one draw. */
|
|
207
|
+
randint(high: number, shape: number[]): MlxArray {
|
|
208
|
+
const split = ops.randomSplitNum(this.#key, 2);
|
|
209
|
+
let retained: MlxArray | null = null;
|
|
210
|
+
let draw: MlxArray | null = null;
|
|
211
|
+
try {
|
|
212
|
+
using first = split.slice([0, 0], [1, 2]);
|
|
213
|
+
using second = split.slice([1, 0], [2, 2]);
|
|
214
|
+
retained = ops.reshape(first, [2]);
|
|
215
|
+
draw = ops.reshape(second, [2]);
|
|
216
|
+
const out = ops.randint(0, high, shape, I32, draw);
|
|
217
|
+
this.#key.dispose();
|
|
218
|
+
this.#key = retained;
|
|
219
|
+
retained = null;
|
|
220
|
+
return out;
|
|
221
|
+
} finally {
|
|
222
|
+
split.dispose();
|
|
223
|
+
retained?.dispose();
|
|
224
|
+
draw?.dispose();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
dispose(): void {
|
|
229
|
+
this.#key.dispose();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** One request's bounded denoising units. The first advance prefills the
|
|
234
|
+
* prompt and draws the first canvas; each later advance runs one denoising
|
|
235
|
+
* step (a finished block also emits it and prepares the next). Only the
|
|
236
|
+
* final result leaves the run; close() releases a run that has not finished. */
|
|
237
|
+
export interface DenoisingRun {
|
|
238
|
+
advance(): DiffusionGenResult | undefined;
|
|
239
|
+
close(): void;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function openDenoisingRun<State>(
|
|
243
|
+
graph: DenoisingGraph<MlxArray, State>, promptIds: number[], opts: DiffusionGenOptions,
|
|
244
|
+
): DenoisingRun {
|
|
245
|
+
const steps = denoisingSteps(graph, promptIds, opts);
|
|
246
|
+
let finished = false;
|
|
247
|
+
return {
|
|
248
|
+
advance() {
|
|
249
|
+
if (finished) throw new Error("denoising run already finished");
|
|
250
|
+
let step: IteratorResult<void, DiffusionGenResult | undefined>;
|
|
251
|
+
try { step = steps.next(); }
|
|
252
|
+
catch (error) { finished = true; throw error; }
|
|
253
|
+
if (!step.done) return undefined;
|
|
254
|
+
finished = true;
|
|
255
|
+
if (!step.value) throw new Error("denoising ended without a result");
|
|
256
|
+
return step.value;
|
|
257
|
+
},
|
|
258
|
+
close() {
|
|
259
|
+
if (finished) return;
|
|
260
|
+
finished = true;
|
|
261
|
+
steps.return(undefined);
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Compatibility entry. Both sync and asynchronous callers drain one algorithm. */
|
|
267
|
+
export function diffusionGenerate(model: MlxDenoisingModel, promptIds: number[], opts: DiffusionGenOptions): DiffusionGenResult {
|
|
268
|
+
return denoiseSync(bindLegacyDenoisingModel(model).graph, promptIds, opts);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function denoiseSync<State>(graph: DenoisingGraph<MlxArray, State>, promptIds: number[], opts: DiffusionGenOptions): DiffusionGenResult {
|
|
272
|
+
const steps = denoisingSteps(graph, promptIds, opts);
|
|
273
|
+
while (true) {
|
|
274
|
+
const step = steps.next();
|
|
275
|
+
if (step.done) {
|
|
276
|
+
if (!step.value) throw new Error("denoising ended without a result");
|
|
277
|
+
return step.value;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** One macrotask between bounded denoising units allows cancellation and I/O.
|
|
283
|
+
* No tentative canvas tokens are published, and no extra device eval is added. */
|
|
284
|
+
export async function denoiseAsync<State>(
|
|
285
|
+
graph: DenoisingGraph<MlxArray, State>, promptIds: number[], opts: DiffusionGenOptions, signal?: AbortSignal,
|
|
286
|
+
): Promise<DiffusionGenResult> {
|
|
287
|
+
signal?.throwIfAborted();
|
|
288
|
+
const steps = denoisingSteps(graph, promptIds, opts);
|
|
289
|
+
try {
|
|
290
|
+
while (true) {
|
|
291
|
+
signal?.throwIfAborted();
|
|
292
|
+
const step = steps.next();
|
|
293
|
+
if (step.done) {
|
|
294
|
+
if (!step.value) throw new Error("denoising ended without a result");
|
|
295
|
+
return step.value;
|
|
296
|
+
}
|
|
297
|
+
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
298
|
+
}
|
|
299
|
+
} finally { steps.return(undefined); }
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function* denoisingSteps<State>(
|
|
303
|
+
graph: DenoisingGraph<MlxArray, State>, promptIds: number[], opts: DiffusionGenOptions,
|
|
304
|
+
): Generator<void, DiffusionGenResult | undefined> {
|
|
305
|
+
assertMlxDenoisingGraph(graph);
|
|
306
|
+
const vocab = graph.vocabSize;
|
|
307
|
+
const modelCanvas = graph.canvasLength;
|
|
308
|
+
const maxSteps = opts.maxDenoisingSteps ?? 48;
|
|
309
|
+
const fullCanvas = opts.fullCanvas ?? false;
|
|
310
|
+
const maxCanvas = fullCanvas ? modelCanvas : Math.min(modelCanvas, opts.maxCanvasLength ?? modelCanvas);
|
|
311
|
+
const minCanvas = Math.min(maxCanvas, opts.minCanvasLength ?? 64);
|
|
312
|
+
const sampler = opts.sampler ?? "confidence-threshold";
|
|
313
|
+
const threshold = opts.threshold ?? 0.9;
|
|
314
|
+
const entropyBound = opts.entropyBound ?? 0.1;
|
|
315
|
+
const temperature = opts.temperature ?? 0;
|
|
316
|
+
const tMin = opts.tMin ?? 0.4;
|
|
317
|
+
const tMax = opts.tMax ?? 0.8;
|
|
318
|
+
// Stable-stop is OFF unless both thresholds are explicitly provided (the
|
|
319
|
+
// oracle ships generation_config=None → stopping_config None → never stops).
|
|
320
|
+
const stableStop = opts.stabilityThreshold !== undefined && opts.confidenceThreshold !== undefined;
|
|
321
|
+
const stabilityThreshold = opts.stabilityThreshold ?? 1;
|
|
322
|
+
const stopConfidence = opts.confidenceThreshold ?? 0.005;
|
|
323
|
+
const eosIds = new Set(opts.eosTokenIds ?? [1, 106]);
|
|
324
|
+
const maxNewTokens = opts.maxTokens;
|
|
325
|
+
|
|
326
|
+
if (temperature > 0) throw new Error("diffusion temperature>0 (categorical sampling) not wired yet");
|
|
327
|
+
|
|
328
|
+
let keys: DenoisingKeys | null = null;
|
|
329
|
+
let stateOwner: ResourceOwner<State> | undefined;
|
|
330
|
+
let dequantWeight: MlxArray | null = null;
|
|
331
|
+
let ownedWeight: MlxArray | null = null;
|
|
332
|
+
let failure: { error: unknown } | undefined;
|
|
333
|
+
|
|
334
|
+
const emitted: number[] = [];
|
|
335
|
+
const blocks: number[][] = [];
|
|
336
|
+
let totalSteps = 0;
|
|
337
|
+
let generated = 0;
|
|
338
|
+
let finishReason: "stop" | "length" = "length";
|
|
339
|
+
let stopped = false;
|
|
340
|
+
let isFirstBlock = true;
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
keys = new DenoisingKeys(opts.seed ?? 0n);
|
|
344
|
+
const cache = graph.prefill(promptIds, opts.visionPixels);
|
|
345
|
+
stateOwner = ownResource(cache, (state) => graph.closeState(state));
|
|
346
|
+
dequantWeight = opts.embedWeight ?? (ownedWeight = graph.dequantEmbedWeight());
|
|
347
|
+
while (generated < maxNewTokens) {
|
|
348
|
+
const remaining = maxNewTokens - generated;
|
|
349
|
+
const canvasLength = fullCanvas
|
|
350
|
+
? modelCanvas
|
|
351
|
+
: Math.min(maxCanvas, Math.max(remaining, minCanvas));
|
|
352
|
+
|
|
353
|
+
if (!isFirstBlock) {
|
|
354
|
+
// Continuation: prefill the encoder over the previous accepted block.
|
|
355
|
+
const prev = blocks[blocks.length - 1]!;
|
|
356
|
+
const prevArr = MlxArray.fromInt32(Int32Array.from(prev), [1, prev.length]);
|
|
357
|
+
try { graph.extendPrefill(prevArr, cache); }
|
|
358
|
+
finally { prevArr.dispose(); }
|
|
359
|
+
}
|
|
360
|
+
isFirstBlock = false;
|
|
361
|
+
|
|
362
|
+
let currentCanvas: MlxArray | null = null;
|
|
363
|
+
let draftReveal: MlxArray | null = null;
|
|
364
|
+
let draftCanvas: MlxArray | null = null;
|
|
365
|
+
let argmaxCanvas: MlxArray | null = null;
|
|
366
|
+
let scEmbeddings: MlxArray | null = null;
|
|
367
|
+
const history: MlxArray[] = [];
|
|
368
|
+
let stepsThisCanvas = 0;
|
|
369
|
+
try {
|
|
370
|
+
currentCanvas = keys.randint(vocab, [1, canvasLength]); // RNG: init
|
|
371
|
+
draftReveal = ops.zeros([1, canvasLength], Dtype.bool);
|
|
372
|
+
draftCanvas = ops.reshape(currentCanvas, [1, canvasLength]); // alias copy
|
|
373
|
+
argmaxCanvas = ops.reshape(currentCanvas, [1, canvasLength]);
|
|
374
|
+
|
|
375
|
+
for (let curStep = maxSteps; curStep >= 1; curStep--) {
|
|
376
|
+
yield; // safe point before the next denoising step
|
|
377
|
+
stepsThisCanvas++;
|
|
378
|
+
let logits: MlxArray | null = null;
|
|
379
|
+
let processed: MlxArray | null = null;
|
|
380
|
+
let acceptance: MlxArray | null = null;
|
|
381
|
+
let nextSc: MlxArray | null = null;
|
|
382
|
+
try {
|
|
383
|
+
logits = graph.decoderLogits(currentCanvas, cache, scEmbeddings);
|
|
384
|
+
const schedT = linearTemp(curStep, maxSteps, tMin, tMax);
|
|
385
|
+
// Match the reference EXACTLY: divide (not reciprocal-multiply) — the
|
|
386
|
+
// f32 rounding differs and the confidence threshold is a hard cutoff
|
|
387
|
+
// that flips acceptance on a 1-ULP difference, diverging the trajectory.
|
|
388
|
+
const schedArr = ops.scalarLike(schedT, logits);
|
|
389
|
+
processed = ops.div(logits, schedArr);
|
|
390
|
+
schedArr.dispose();
|
|
391
|
+
logits.dispose();
|
|
392
|
+
|
|
393
|
+
argmaxCanvas.dispose();
|
|
394
|
+
const argmax = ops.argmaxAxis(processed, -1);
|
|
395
|
+
argmaxCanvas = argmax.astype(I32); // [1, L]
|
|
396
|
+
argmax.dispose();
|
|
397
|
+
|
|
398
|
+
if (curStep === 1) {
|
|
399
|
+
processed.dispose();
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// temperature 0 → denoiser canvas is the argmax.
|
|
404
|
+
const denoiser = argmaxCanvas;
|
|
405
|
+
|
|
406
|
+
if (sampler === "entropy-bound") {
|
|
407
|
+
// cur_step > 1 always here (cur_step==1 breaks before the sampler):
|
|
408
|
+
// entropy AND the next soft embeddings come from the SAME entropy
|
|
409
|
+
// chain (reference _diffusion_entropy_and_soft_embeddings) — NOT the
|
|
410
|
+
// softmax-precise path the confidence sampler uses.
|
|
411
|
+
const { probs, entropy } = entropyProbsChain(processed);
|
|
412
|
+
acceptance = entropyTransferMask(entropy, entropyBound);
|
|
413
|
+
entropy.dispose();
|
|
414
|
+
nextSc = softEmbeddingsFromProbs(probs, dequantWeight, graph.embedScale);
|
|
415
|
+
probs.dispose();
|
|
416
|
+
// accepted/current update (entropy variant)
|
|
417
|
+
const accepted = ops.where(acceptance, denoiser, currentCanvas);
|
|
418
|
+
const noise = keys.randint(vocab, [1, canvasLength]); // RNG: re-noise
|
|
419
|
+
const newCurrent = ops.where(acceptance, accepted, noise);
|
|
420
|
+
noise.dispose();
|
|
421
|
+
currentCanvas.dispose();
|
|
422
|
+
currentCanvas = newCurrent;
|
|
423
|
+
draftReveal.dispose();
|
|
424
|
+
const notAcceptance = ops.logicalNot(acceptance);
|
|
425
|
+
draftReveal = ops.logicalNot(notAcceptance); // = acceptance
|
|
426
|
+
notAcceptance.dispose();
|
|
427
|
+
draftCanvas.dispose();
|
|
428
|
+
draftCanvas = ops.reshape(argmaxCanvas, [1, canvasLength]);
|
|
429
|
+
accepted.dispose();
|
|
430
|
+
} else {
|
|
431
|
+
const unrevealed = ops.logicalNot(draftReveal);
|
|
432
|
+
const confidence = tokenProbability(processed, denoiser);
|
|
433
|
+
acceptance = confidenceTransferMask(confidence, unrevealed, threshold, false);
|
|
434
|
+
confidence.dispose();
|
|
435
|
+
const accepted = ops.where(acceptance, denoiser, draftCanvas);
|
|
436
|
+
const revealOrAccept = ops.logicalOr(draftReveal, acceptance);
|
|
437
|
+
const noise = keys.randint(vocab, [1, canvasLength]); // RNG: re-noise
|
|
438
|
+
const newCurrent = ops.where(revealOrAccept, accepted, noise);
|
|
439
|
+
noise.dispose();
|
|
440
|
+
currentCanvas.dispose();
|
|
441
|
+
currentCanvas = newCurrent;
|
|
442
|
+
const newReveal = ops.logicalOr(draftReveal, acceptance);
|
|
443
|
+
draftReveal.dispose();
|
|
444
|
+
draftReveal = newReveal;
|
|
445
|
+
const newDraft = ops.where(acceptance, accepted, draftCanvas);
|
|
446
|
+
draftCanvas.dispose();
|
|
447
|
+
draftCanvas = newDraft;
|
|
448
|
+
unrevealed.dispose();
|
|
449
|
+
revealOrAccept.dispose();
|
|
450
|
+
accepted.dispose();
|
|
451
|
+
}
|
|
452
|
+
acceptance.dispose();
|
|
453
|
+
|
|
454
|
+
// Early stop 1 (confidence sampler): all positions revealed.
|
|
455
|
+
if (sampler === "confidence-threshold") {
|
|
456
|
+
const allRevealed = ops.allReduce(draftReveal);
|
|
457
|
+
const done = ops.itemBool(allRevealed);
|
|
458
|
+
allRevealed.dispose();
|
|
459
|
+
if (done) {
|
|
460
|
+
processed.dispose();
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Early stop 2: stable + confident (only when explicitly configured;
|
|
466
|
+
// the as-loaded oracle has stopping_config None and never stops here).
|
|
467
|
+
if (
|
|
468
|
+
stableStop &&
|
|
469
|
+
stableAndConfident(argmaxCanvas, processed, history, stabilityThreshold, stopConfidence)
|
|
470
|
+
) {
|
|
471
|
+
// Entropy sampling precomputes the next step's self-conditioning
|
|
472
|
+
// tensor before evaluating this stop. The break means ownership is
|
|
473
|
+
// never transferred to scEmbeddings, so release the pending value.
|
|
474
|
+
nextSc?.dispose();
|
|
475
|
+
processed.dispose();
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Self-conditioning feedback for the next step.
|
|
480
|
+
if (curStep > 1) {
|
|
481
|
+
if (nextSc === null) nextSc = graph.softEmbeddings(processed, dequantWeight);
|
|
482
|
+
if (scEmbeddings) scEmbeddings.dispose();
|
|
483
|
+
scEmbeddings = nextSc;
|
|
484
|
+
nextSc = null; // ownership transferred to persistent feedback
|
|
485
|
+
}
|
|
486
|
+
processed.dispose();
|
|
487
|
+
} finally {
|
|
488
|
+
disposeResources([logits, processed, acceptance, nextSc]
|
|
489
|
+
.filter((array): array is MlxArray => array !== null));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (scEmbeddings) scEmbeddings.dispose();
|
|
494
|
+
for (const hh of history) hh.dispose();
|
|
495
|
+
currentCanvas.dispose();
|
|
496
|
+
draftReveal.dispose();
|
|
497
|
+
draftCanvas.dispose();
|
|
498
|
+
|
|
499
|
+
// Emit from the final argmax canvas.
|
|
500
|
+
const argmaxFloat = argmaxCanvas.astype(Dtype.float32);
|
|
501
|
+
let blockTokens: number[];
|
|
502
|
+
try { blockTokens = [...argmaxFloat.toFloat32()].map((x) => Math.round(x)); }
|
|
503
|
+
finally { argmaxFloat.dispose(); }
|
|
504
|
+
argmaxCanvas.dispose();
|
|
505
|
+
blocks.push(blockTokens);
|
|
506
|
+
totalSteps += stepsThisCanvas;
|
|
507
|
+
|
|
508
|
+
for (const tok of blockTokens) {
|
|
509
|
+
generated++;
|
|
510
|
+
if (eosIds.has(tok)) {
|
|
511
|
+
stopped = true;
|
|
512
|
+
finishReason = "stop";
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
emitted.push(tok);
|
|
516
|
+
if (generated >= maxNewTokens) {
|
|
517
|
+
stopped = true;
|
|
518
|
+
finishReason = "length";
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
if (stopped) break;
|
|
523
|
+
} finally {
|
|
524
|
+
disposeResources([currentCanvas, draftReveal, draftCanvas, argmaxCanvas, scEmbeddings, ...history]
|
|
525
|
+
.filter((array): array is MlxArray => array !== null));
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
} catch (error) {
|
|
529
|
+
failure = { error };
|
|
530
|
+
throw error;
|
|
531
|
+
} finally {
|
|
532
|
+
const cleanup = () => disposeResources([ownedWeight, keys,
|
|
533
|
+
...(stateOwner ? [{ dispose: () => stateOwner!.close() }] : [])]
|
|
534
|
+
.filter((resource): resource is DisposableResource => resource !== null));
|
|
535
|
+
if (failure) cleanupFailure(failure.error, cleanup);
|
|
536
|
+
else cleanup();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return { tokens: emitted, blocks, steps: totalSteps, finishReason };
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** stable (last `stabilityThreshold` argmax canvases identical) AND confident
|
|
543
|
+
* (mean token entropy < bound). Mutates `history` like the reference. */
|
|
544
|
+
function stableAndConfident(
|
|
545
|
+
argmaxCanvas: MlxArray,
|
|
546
|
+
processed: MlxArray,
|
|
547
|
+
history: MlxArray[],
|
|
548
|
+
stabilityThreshold: number,
|
|
549
|
+
confidenceThreshold: number,
|
|
550
|
+
): boolean {
|
|
551
|
+
let stable: boolean;
|
|
552
|
+
if (history.length === stabilityThreshold) {
|
|
553
|
+
stable = history.every((canvas) => {
|
|
554
|
+
const eq = ops.equal(argmaxCanvas, canvas);
|
|
555
|
+
const all = ops.allReduce(eq);
|
|
556
|
+
eq.dispose();
|
|
557
|
+
const v = ops.itemBool(all);
|
|
558
|
+
all.dispose();
|
|
559
|
+
return v;
|
|
560
|
+
});
|
|
561
|
+
} else {
|
|
562
|
+
stable = false;
|
|
563
|
+
}
|
|
564
|
+
// Push an INDEPENDENT copy (add-zero forces a fresh buffer): a reshape/view
|
|
565
|
+
// would alias argmaxCanvas and read freed/overwritten data once the caller
|
|
566
|
+
// disposes argmaxCanvas next step → false "stable" → premature stop.
|
|
567
|
+
const zero = ops.scalarLike(0, argmaxCanvas);
|
|
568
|
+
history.push(ops.add(argmaxCanvas, zero));
|
|
569
|
+
zero.dispose();
|
|
570
|
+
if (history.length > stabilityThreshold) history.shift()!.dispose();
|
|
571
|
+
if (!stable) return false;
|
|
572
|
+
|
|
573
|
+
const entropy = tokenEntropy(processed);
|
|
574
|
+
const meanEnt = ops.meanAll(entropy, false);
|
|
575
|
+
entropy.dispose();
|
|
576
|
+
const thr = ops.scalarLike(confidenceThreshold, meanEnt);
|
|
577
|
+
const lt = ops.less(meanEnt, thr);
|
|
578
|
+
meanEnt.dispose();
|
|
579
|
+
thr.dispose();
|
|
580
|
+
const confident = ops.itemBool(lt);
|
|
581
|
+
lt.dispose();
|
|
582
|
+
return confident;
|
|
583
|
+
}
|