@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,389 @@
|
|
|
1
|
+
// Chat template rendering via @huggingface/jinja (pure JS, purpose-built
|
|
2
|
+
// for HF chat templates). Rendering the model's own chat_template.jinja beats a hand-port because
|
|
3
|
+
// it can't rot when the model updates its template.
|
|
4
|
+
|
|
5
|
+
import { Template } from "@huggingface/jinja";
|
|
6
|
+
|
|
7
|
+
export interface ToolCall {
|
|
8
|
+
id?: string;
|
|
9
|
+
type?: "function";
|
|
10
|
+
function: {
|
|
11
|
+
name: string;
|
|
12
|
+
/** Object form preferred; OpenAI's JSON-string form is normalized by
|
|
13
|
+
* the server before rendering. */
|
|
14
|
+
arguments: Record<string, unknown> | string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ChatMessage {
|
|
19
|
+
role: string;
|
|
20
|
+
content?: string | Array<Record<string, unknown>> | null;
|
|
21
|
+
tool_calls?: ToolCall[];
|
|
22
|
+
tool_call_id?: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
reasoning?: string;
|
|
25
|
+
reasoning_content?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** OpenAI-style tool definition (function type). */
|
|
29
|
+
export interface ToolDefinition {
|
|
30
|
+
type: "function";
|
|
31
|
+
function: {
|
|
32
|
+
name: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
parameters?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RenderOptions {
|
|
39
|
+
addGenerationPrompt?: boolean;
|
|
40
|
+
tools?: ToolDefinition[] | null;
|
|
41
|
+
enableThinking?: boolean;
|
|
42
|
+
/** Template-level reasoning depth (Qwen3.8: xhigh|medium|low — the template
|
|
43
|
+
* RAISES on other values, so callers must map OpenAI levels first and only
|
|
44
|
+
* set this for templates that read it; see ChatTemplate.readsReasoningEffort). */
|
|
45
|
+
reasoningEffort?: "xhigh" | "medium" | "low";
|
|
46
|
+
/** Keep think blocks from historical assistant turns in the rendered prompt
|
|
47
|
+
* (Qwen3.8 `preserve_thinking`, template default true — better prompt-cache
|
|
48
|
+
* reuse and agent-trace continuity). Only passed when the template reads it. */
|
|
49
|
+
preserveThinking?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type ChatRenderer = (
|
|
53
|
+
messages: ChatMessage[],
|
|
54
|
+
options: RenderOptions,
|
|
55
|
+
) => string;
|
|
56
|
+
|
|
57
|
+
/** Reasoning markup a template's `enable_thinking` channel uses. */
|
|
58
|
+
export type ThinkingFormat = "think-tag" | "channel-tokens";
|
|
59
|
+
|
|
60
|
+
/** How to render chats for an artifact that ships no template source. */
|
|
61
|
+
export interface TemplateFallback {
|
|
62
|
+
readonly render: ChatRenderer;
|
|
63
|
+
readonly thinkingFormat: ThinkingFormat | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function glm52ContentText(content: ChatMessage["content"], label: string): string {
|
|
67
|
+
if (typeof content === "string") return content;
|
|
68
|
+
if (!Array.isArray(content))
|
|
69
|
+
throw new Error(`${label} must be a string or an array of text parts`);
|
|
70
|
+
return content.map((part, index) => {
|
|
71
|
+
if (
|
|
72
|
+
!part ||
|
|
73
|
+
(part.type !== "text" && part.type !== "input_text") ||
|
|
74
|
+
typeof part.text !== "string"
|
|
75
|
+
) {
|
|
76
|
+
throw new Error(`${label}.${index}: GLM-5.2 supports text content only`);
|
|
77
|
+
}
|
|
78
|
+
return part.text;
|
|
79
|
+
}).join("");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Text/tool subset of the pinned GLM-5.2 template used by Colibri. */
|
|
83
|
+
export function renderGlm52Chat(
|
|
84
|
+
messages: ChatMessage[],
|
|
85
|
+
options: RenderOptions = {},
|
|
86
|
+
): string {
|
|
87
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
88
|
+
throw new Error("GLM-5.2 messages must be a non-empty array");
|
|
89
|
+
const {
|
|
90
|
+
addGenerationPrompt = true,
|
|
91
|
+
tools = null,
|
|
92
|
+
enableThinking = false,
|
|
93
|
+
} = options;
|
|
94
|
+
const prompt = ["[gMASK]<sop>"];
|
|
95
|
+
if (enableThinking)
|
|
96
|
+
prompt.push("<|system|>Reasoning Effort: Max");
|
|
97
|
+
|
|
98
|
+
const normalizedTools = normalizeToolSchemas(tools);
|
|
99
|
+
if (normalizedTools && normalizedTools.length > 0) {
|
|
100
|
+
prompt.push(
|
|
101
|
+
"<|system|>\n# Tools\n\nYou may call one or more functions to assist with the " +
|
|
102
|
+
"user query.\n\nYou are provided with function signatures within <tools></tools> " +
|
|
103
|
+
"XML tags:\n<tools>\n",
|
|
104
|
+
);
|
|
105
|
+
for (const tool of normalizedTools) {
|
|
106
|
+
const fn = { ...tool.function } as Record<string, unknown>;
|
|
107
|
+
delete fn.defer_loading;
|
|
108
|
+
delete fn.strict;
|
|
109
|
+
prompt.push(`${JSON.stringify(fn)}\n`);
|
|
110
|
+
}
|
|
111
|
+
prompt.push(
|
|
112
|
+
"</tools>\n\nFor each function call, output the function name and arguments " +
|
|
113
|
+
"within the following XML format:\n<tool_call>{function-name}" +
|
|
114
|
+
"<arg_key>{arg-key-1}</arg_key><arg_value>{arg-value-1}</arg_value>" +
|
|
115
|
+
"<arg_key>{arg-key-2}</arg_key><arg_value>{arg-value-2}</arg_value>...</tool_call>",
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let previousWasTool = false;
|
|
120
|
+
for (let index = 0; index < messages.length; index++) {
|
|
121
|
+
const message = messages[index]!;
|
|
122
|
+
const role = message.role;
|
|
123
|
+
if (role === "system" || role === "developer") {
|
|
124
|
+
prompt.push(
|
|
125
|
+
`<|system|>${glm52ContentText(message.content, `messages.${index}.content`)}`,
|
|
126
|
+
);
|
|
127
|
+
} else if (role === "user") {
|
|
128
|
+
prompt.push(
|
|
129
|
+
`<|user|>${glm52ContentText(message.content, `messages.${index}.content`)}`,
|
|
130
|
+
);
|
|
131
|
+
} else if (role === "assistant") {
|
|
132
|
+
const content = message.content === null || message.content === undefined
|
|
133
|
+
? ""
|
|
134
|
+
: glm52ContentText(message.content, `messages.${index}.content`);
|
|
135
|
+
prompt.push(`<|assistant|><think></think>${content.trim()}`);
|
|
136
|
+
for (const call of message.tool_calls ?? []) {
|
|
137
|
+
const raw = call.function.arguments;
|
|
138
|
+
let args: Record<string, unknown> = {};
|
|
139
|
+
if (typeof raw === "string") {
|
|
140
|
+
try {
|
|
141
|
+
const parsed = JSON.parse(raw);
|
|
142
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
143
|
+
args = parsed as Record<string, unknown>;
|
|
144
|
+
} catch {
|
|
145
|
+
// Match the pinned template path: malformed historical arguments
|
|
146
|
+
// contribute an empty call body rather than changing the prompt.
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
args = raw;
|
|
150
|
+
}
|
|
151
|
+
prompt.push(`<tool_call>${call.function.name}`);
|
|
152
|
+
for (const [key, value] of Object.entries(args)) {
|
|
153
|
+
prompt.push(
|
|
154
|
+
`<arg_key>${key}</arg_key><arg_value>` +
|
|
155
|
+
`${typeof value === "string" ? value : JSON.stringify(value)}</arg_value>`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
prompt.push("</tool_call>");
|
|
159
|
+
}
|
|
160
|
+
} else if (role === "tool") {
|
|
161
|
+
if (!previousWasTool) prompt.push("<|observation|>");
|
|
162
|
+
prompt.push(
|
|
163
|
+
`<tool_response>${glm52ContentText(message.content, `messages.${index}.content`)}` +
|
|
164
|
+
"</tool_response>",
|
|
165
|
+
);
|
|
166
|
+
} else {
|
|
167
|
+
throw new Error(`GLM-5.2 unsupported message role ${JSON.stringify(role)}`);
|
|
168
|
+
}
|
|
169
|
+
previousWasTool = role === "tool";
|
|
170
|
+
}
|
|
171
|
+
if (addGenerationPrompt) {
|
|
172
|
+
prompt.push(
|
|
173
|
+
enableThinking
|
|
174
|
+
? "<|assistant|><think>"
|
|
175
|
+
: "<|assistant|><think></think>",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
return prompt.join("");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** JSON-schema type implied by a literal value. */
|
|
182
|
+
function jsonTypeOf(v: unknown): string {
|
|
183
|
+
if (typeof v === "number") return Number.isInteger(v) ? "integer" : "number";
|
|
184
|
+
if (typeof v === "boolean") return "boolean";
|
|
185
|
+
if (Array.isArray(v)) return "array";
|
|
186
|
+
if (v !== null && typeof v === "object") return "object";
|
|
187
|
+
return "string";
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Infer a JSON-schema `type` for a node that lacks one (enum/const/anyOf/…). */
|
|
191
|
+
function inferSchemaType(node: Record<string, unknown>): string {
|
|
192
|
+
if (Array.isArray(node.enum) && node.enum.length > 0) return jsonTypeOf(node.enum[0]);
|
|
193
|
+
if ("const" in node) return jsonTypeOf(node.const);
|
|
194
|
+
if (node.properties || node.additionalProperties) return "object";
|
|
195
|
+
if (node.items !== undefined || node.prefixItems !== undefined) return "array";
|
|
196
|
+
for (const key of ["anyOf", "oneOf", "allOf"] as const) {
|
|
197
|
+
const subs = node[key];
|
|
198
|
+
if (Array.isArray(subs) && subs.length > 0) {
|
|
199
|
+
const types = subs
|
|
200
|
+
.map((s) => (s && typeof s === "object" ? (s as Record<string, unknown>).type : undefined))
|
|
201
|
+
.filter((t): t is string => typeof t === "string");
|
|
202
|
+
const first = types[0];
|
|
203
|
+
if (first !== undefined) return first;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return "string";
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Recursively ensure every JSON-schema node carries a `type`.
|
|
211
|
+
*
|
|
212
|
+
* Why: HF chat templates (e.g. Gemma's tool-declaration block) do
|
|
213
|
+
* `value['type'] | upper`, which throws "Cannot apply filter upper to
|
|
214
|
+
* UndefinedValue" for schemas that describe a parameter via `anyOf`/`enum`/
|
|
215
|
+
* `const` without a top-level `type` (TypeBox unions/literals emit exactly
|
|
216
|
+
* this). We synthesize a sensible `type` so any tool renders, regardless of
|
|
217
|
+
* how its schema was authored. Returns a new object; never mutates input.
|
|
218
|
+
*/
|
|
219
|
+
export function normalizeSchemaTypes(node: unknown): unknown {
|
|
220
|
+
if (Array.isArray(node)) return node.map(normalizeSchemaTypes);
|
|
221
|
+
if (!node || typeof node !== "object") return node;
|
|
222
|
+
const out: Record<string, unknown> = { ...(node as Record<string, unknown>) };
|
|
223
|
+
if (out.properties && typeof out.properties === "object") {
|
|
224
|
+
const props: Record<string, unknown> = {};
|
|
225
|
+
for (const [k, v] of Object.entries(out.properties as Record<string, unknown>)) props[k] = normalizeSchemaTypes(v);
|
|
226
|
+
out.properties = props;
|
|
227
|
+
}
|
|
228
|
+
if (out.items !== undefined) out.items = normalizeSchemaTypes(out.items);
|
|
229
|
+
if (out.prefixItems !== undefined) out.prefixItems = normalizeSchemaTypes(out.prefixItems);
|
|
230
|
+
if (out.additionalProperties && typeof out.additionalProperties === "object") {
|
|
231
|
+
out.additionalProperties = normalizeSchemaTypes(out.additionalProperties);
|
|
232
|
+
}
|
|
233
|
+
for (const key of ["anyOf", "oneOf", "allOf"] as const) {
|
|
234
|
+
if (Array.isArray(out[key])) out[key] = (out[key] as unknown[]).map(normalizeSchemaTypes);
|
|
235
|
+
}
|
|
236
|
+
if (typeof out.type !== "string") out.type = inferSchemaType(out);
|
|
237
|
+
return out;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Apply normalizeSchemaTypes to every tool's parameter schema. */
|
|
241
|
+
export function normalizeToolSchemas(tools: ToolDefinition[] | null): ToolDefinition[] | null {
|
|
242
|
+
if (!tools) return tools;
|
|
243
|
+
return tools.map((t) => ({
|
|
244
|
+
...t,
|
|
245
|
+
function: {
|
|
246
|
+
...t.function,
|
|
247
|
+
parameters: t.function.parameters
|
|
248
|
+
? (normalizeSchemaTypes(t.function.parameters) as Record<string, unknown>)
|
|
249
|
+
: t.function.parameters,
|
|
250
|
+
},
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export class ChatTemplate {
|
|
255
|
+
readonly #template: Template | null;
|
|
256
|
+
readonly #renderer: ChatRenderer | null;
|
|
257
|
+
readonly #bosToken: string | null;
|
|
258
|
+
readonly #eosToken: string | null;
|
|
259
|
+
/** True when the template reads `reasoning_effort` (Qwen3.8's xhigh/medium/
|
|
260
|
+
* low depth control). Callers must not pass the variable otherwise — and
|
|
261
|
+
* must never pass unmapped OpenAI level names; this template family raises
|
|
262
|
+
* on values outside its supported set. */
|
|
263
|
+
readonly readsReasoningEffort: boolean;
|
|
264
|
+
/** True when the template reads `preserve_thinking` (Qwen3.8: keep think
|
|
265
|
+
* blocks from historical turns; template default true). */
|
|
266
|
+
readonly readsPreserveThinking: boolean;
|
|
267
|
+
/** Which reasoning format the template's `enable_thinking` channel uses, or
|
|
268
|
+
* null if the model has no switchable reasoning:
|
|
269
|
+
* - "think-tag": `<think>…</think>` text markers (Qwen3.5, MiniCPM5) — split
|
|
270
|
+
* from decoded text by ThinkingTagSplitter.
|
|
271
|
+
* - "channel-tokens": `<|channel>thought\n…<channel|>` (Gemma 4) — the markers
|
|
272
|
+
* are SPECIAL TOKENS stripped at decode, so reasoning is split at the token
|
|
273
|
+
* level in ToolAwareStream (sentinel-tokens mode), not from decoded text.
|
|
274
|
+
* Drives both the parser path and the reasoning capability advertised to Pi. */
|
|
275
|
+
readonly thinkingFormat: ThinkingFormat | null;
|
|
276
|
+
/** True when the model has a switchable reasoning channel we can parse. */
|
|
277
|
+
readonly supportsThinking: boolean;
|
|
278
|
+
|
|
279
|
+
private constructor(
|
|
280
|
+
source: string | null,
|
|
281
|
+
bosToken: string | null,
|
|
282
|
+
eosToken: string | null,
|
|
283
|
+
forceNoThinking = false,
|
|
284
|
+
renderer: ChatRenderer | null = null,
|
|
285
|
+
explicitThinkingFormat: ThinkingFormat | null = null,
|
|
286
|
+
) {
|
|
287
|
+
if (source === null && renderer === null)
|
|
288
|
+
throw new Error("ChatTemplate needs a Jinja source or renderer");
|
|
289
|
+
this.#template = source === null ? null : new Template(source);
|
|
290
|
+
this.#renderer = renderer;
|
|
291
|
+
this.#bosToken = bosToken;
|
|
292
|
+
this.#eosToken = eosToken;
|
|
293
|
+
const gatesThinking = source?.includes("enable_thinking") ?? false;
|
|
294
|
+
this.readsReasoningEffort = source?.includes("reasoning_effort") ?? false;
|
|
295
|
+
this.readsPreserveThinking = source?.includes("preserve_thinking") ?? false;
|
|
296
|
+
// `forceNoThinking` suppresses the switchable channel even when the template
|
|
297
|
+
// carries the gemma markers. DiffusionGemma ships the shared gemma-family
|
|
298
|
+
// template (with the `<|channel>thought…<channel|>` reasoning channel), but
|
|
299
|
+
// its non-autoregressive canvas decode cannot reliably emit the `<channel|>`
|
|
300
|
+
// close, so an enabled channel never ends (everything is captured as
|
|
301
|
+
// reasoning, no answer). The OptiQ reference never enables thinking for this
|
|
302
|
+
// model — it always renders the template's `default(false)` pre-closed empty
|
|
303
|
+
// channel and decodes the whole canvas as plain text. We match that.
|
|
304
|
+
this.thinkingFormat = explicitThinkingFormat ?? (forceNoThinking
|
|
305
|
+
? null
|
|
306
|
+
: gatesThinking && source!.includes("<think>")
|
|
307
|
+
? "think-tag"
|
|
308
|
+
: gatesThinking && source!.includes("<|channel>")
|
|
309
|
+
? "channel-tokens"
|
|
310
|
+
: null);
|
|
311
|
+
this.supportsThinking = this.thinkingFormat !== null;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Loads the artifact's template. `fallback` renders artifacts that ship none
|
|
315
|
+
* (the model layer supplies it from the profile); without one, a missing
|
|
316
|
+
* template is an error. */
|
|
317
|
+
static async load(
|
|
318
|
+
modelDir: string,
|
|
319
|
+
opts: { disableThinking?: boolean; fallback?: TemplateFallback } = {},
|
|
320
|
+
): Promise<ChatTemplate> {
|
|
321
|
+
const config = (await Bun.file(`${modelDir}/tokenizer_config.json`).json()) as Record<string, any>;
|
|
322
|
+
let source: string | undefined = config.chat_template;
|
|
323
|
+
if (!source) {
|
|
324
|
+
const jinjaFile = Bun.file(`${modelDir}/chat_template.jinja`);
|
|
325
|
+
if (await jinjaFile.exists()) source = await jinjaFile.text();
|
|
326
|
+
}
|
|
327
|
+
if (!source) {
|
|
328
|
+
if (opts.fallback) {
|
|
329
|
+
const tokenText = (t: unknown): string | null =>
|
|
330
|
+
t == null ? null : typeof t === "string" ? t : (t as any).content;
|
|
331
|
+
return new ChatTemplate(
|
|
332
|
+
null,
|
|
333
|
+
tokenText(config.bos_token),
|
|
334
|
+
tokenText(config.eos_token),
|
|
335
|
+
false,
|
|
336
|
+
opts.fallback.render,
|
|
337
|
+
opts.fallback.thinkingFormat,
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
throw new Error(`${modelDir}: no chat template found`);
|
|
341
|
+
}
|
|
342
|
+
// @huggingface/jinja lacks the `min`/`max` array filters that real
|
|
343
|
+
// Jinja2 has. MiniCPM5's template uses `[a, b]|min` in its assistant
|
|
344
|
+
// tool-call history branch, so without this rewrite every multi-turn
|
|
345
|
+
// tool conversation fails at render time ("Unknown ArrayValue filter").
|
|
346
|
+
source = source
|
|
347
|
+
.replace(
|
|
348
|
+
/\[\s*([\w.]+)\s*,\s*([\w.]+)\s*\]\s*\|\s*min\b/g,
|
|
349
|
+
"($1 if $1 < $2 else $2)",
|
|
350
|
+
)
|
|
351
|
+
.replace(
|
|
352
|
+
/\[\s*([\w.]+)\s*,\s*([\w.]+)\s*\]\s*\|\s*max\b/g,
|
|
353
|
+
"($1 if $1 > $2 else $2)",
|
|
354
|
+
);
|
|
355
|
+
const tokenText = (t: unknown): string | null =>
|
|
356
|
+
t == null ? null : typeof t === "string" ? t : (t as any).content;
|
|
357
|
+
return new ChatTemplate(source, tokenText(config.bos_token), tokenText(config.eos_token));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
render(messages: ChatMessage[], options: RenderOptions = {}): string {
|
|
361
|
+
if (this.#renderer) return this.#renderer(messages, options);
|
|
362
|
+
const {
|
|
363
|
+
addGenerationPrompt = true,
|
|
364
|
+
tools = null,
|
|
365
|
+
enableThinking,
|
|
366
|
+
reasoningEffort,
|
|
367
|
+
preserveThinking,
|
|
368
|
+
} = options;
|
|
369
|
+
return this.#template!.render({
|
|
370
|
+
messages,
|
|
371
|
+
add_generation_prompt: addGenerationPrompt,
|
|
372
|
+
// Guarantee every tool param schema has a `type` so templates that do
|
|
373
|
+
// `value['type'] | upper` (Gemma) never see UndefinedValue.
|
|
374
|
+
tools: normalizeToolSchemas(tools),
|
|
375
|
+
...(enableThinking !== undefined ? { enable_thinking: enableThinking } : {}),
|
|
376
|
+
// Only set for templates that read them: reasoning_effort values are
|
|
377
|
+
// template-validated (Qwen3.8 raises on unknown levels), and an unread
|
|
378
|
+
// variable in other templates is dead context at best.
|
|
379
|
+
...(reasoningEffort !== undefined && this.readsReasoningEffort
|
|
380
|
+
? { reasoning_effort: reasoningEffort }
|
|
381
|
+
: {}),
|
|
382
|
+
...(preserveThinking !== undefined && this.readsPreserveThinking
|
|
383
|
+
? { preserve_thinking: preserveThinking }
|
|
384
|
+
: {}),
|
|
385
|
+
bos_token: this.#bosToken,
|
|
386
|
+
eos_token: this.#eosToken,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|