mlx-bun 0.0.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -578
- package/bin/mlx-bun.mjs +1 -1
- package/docs/README.md +91 -0
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
- package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
- package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +395 -149
- package/docs/reference/distribution.md +321 -181
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +580 -142
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +137 -6
- package/docs/reference/server-api.md +938 -422
- package/docs/reference/server-config.md +652 -320
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +10 -5
- package/src/admission-plan.ts +18 -0
- package/src/anthropic.ts +92 -3
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +189 -61
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +263 -23
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +10 -79
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +24 -43
- package/src/generate.ts +740 -337
- package/src/grammar.ts +14 -8
- package/src/harness-pi.ts +15 -34
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +27 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +15 -14
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +459 -234
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +20 -4
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +32 -170
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +3 -4
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +66 -22
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +64 -19
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +9 -3
- package/src/model/batched-quant.ts +2 -2
- package/src/model/batched-rotating-quant.ts +45 -99
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +57 -106
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +4 -3
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +87 -49
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +187 -17
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +52 -148
- package/src/model/generated/gemma4-26b.ts +34 -94
- package/src/model/generated/gemma4-e4b.ts +28 -76
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +7 -8
- package/src/model/profile.ts +443 -0
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +336 -60
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +15 -7
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +14 -320
- package/src/prompt-cache.ts +97 -54
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +16 -3
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/trellis.ts +586 -0
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +130 -3
- package/src/runtime-config.ts +81 -0
- package/src/sampler.ts +276 -4
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +8 -1558
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +354 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +204 -0
- package/src/serve/generation-gateway.ts +211 -243
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +341 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +155 -0
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +162 -0
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +101 -0
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +523 -3551
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +9 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +5 -4
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +9 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +528 -0
- package/src/spec/serve-loop.ts +179 -213
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +95 -24
- package/src/ssd-durability.ts +207 -0
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +14 -13
- package/src/train/forward.ts +38 -1
- package/src/train/loss.ts +3 -2
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +9 -6
- package/src/train/trainer.ts +9 -8
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +48 -2
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +555 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.html +1 -1
- package/src/web/app.js +15 -6
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +16 -9
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +134 -33
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -268
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -189
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -288
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/investigations/hlg-ab.html +0 -34
- package/docs/investigations/hlg-explorer.html +0 -238
- package/docs/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/investigations/hlg-figs/cross.svg +0 -1
- package/docs/investigations/hlg-figs/edges.svg +0 -1
- package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/investigations/hlg-report.html +0 -262
- package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -100
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -13
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
- /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
package/src/train/forward.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { MlxArray } from "../mlx/array";
|
|
|
20
20
|
import { Dtype } from "../mlx/ffi";
|
|
21
21
|
import * as ops from "../mlx/ops";
|
|
22
22
|
import { createCausalMask, type Cache, type Mask } from "../model/gemma4-base";
|
|
23
|
+
import { SSMCache } from "../model/qwen3-delta";
|
|
23
24
|
import type { RuntimeModel } from "../model/factory";
|
|
24
25
|
|
|
25
26
|
/** Stateless cache for the training forward. Training is always a single
|
|
@@ -30,6 +31,8 @@ import type { RuntimeModel } from "../model/factory";
|
|
|
30
31
|
* backward recompute, and a stateful (appending) cache would corrupt on the
|
|
31
32
|
* second run. */
|
|
32
33
|
export class TrainingCache implements Cache {
|
|
34
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
35
|
+
signature(): string { return "train:training"; }
|
|
33
36
|
offset = 0;
|
|
34
37
|
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
|
35
38
|
// Return fresh views: the caller disposes its input k/v right after (its
|
|
@@ -57,6 +60,37 @@ export class TrainingCache implements Cache {
|
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
/** Stateless DeltaNet stand-in (same re-runnability contract as
|
|
64
|
+
* TrainingCache): state WRITES are discarded immediately, so a gradient-
|
|
65
|
+
* checkpoint recompute re-enters with the identical null-state conditions;
|
|
66
|
+
* reads always yield null (zeros inside the kernel) — a full-sequence
|
|
67
|
+
* forward from t=0, exactly the training/perplexity semantics. Before this
|
|
68
|
+
* existed, qwen3_5 routed its DeltaNet layers into plain TrainingCache and
|
|
69
|
+
* threw on the missing conv/recurrent/advance surface (the recorded
|
|
70
|
+
* "mlx-bun perplexity cannot score qwen3_5" gap). */
|
|
71
|
+
export class TrainingSSMCache implements Cache {
|
|
72
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
73
|
+
signature(): string { return "train:training-ssm"; }
|
|
74
|
+
offset = 0;
|
|
75
|
+
specRound: null = null;
|
|
76
|
+
get conv(): MlxArray | null { return null; }
|
|
77
|
+
set conv(v: MlxArray | null) { v?.dispose(); }
|
|
78
|
+
get recurrent(): MlxArray | null { return null; }
|
|
79
|
+
set recurrent(v: MlxArray | null) { v?.dispose(); }
|
|
80
|
+
advance(_n: number): void { /* offset pinned at 0 */ }
|
|
81
|
+
rowOffset(_i: number): number { return 0; }
|
|
82
|
+
updateAndFetch(): [MlxArray, MlxArray] {
|
|
83
|
+
throw new Error("TrainingSSMCache: DeltaNet layers do not use the KV path");
|
|
84
|
+
}
|
|
85
|
+
makeMask(_N: number, _w: number | null): Mask {
|
|
86
|
+
return { mode: "", arr: null }; // ssm_mask is None at B=1 (SSMCache parity)
|
|
87
|
+
}
|
|
88
|
+
state(): MlxArray[] { return []; }
|
|
89
|
+
isTrimmable(): boolean { return true; }
|
|
90
|
+
trim(_n: number): void { /* stateless */ }
|
|
91
|
+
dispose(): void { /* owns no arrays */ }
|
|
92
|
+
}
|
|
93
|
+
|
|
60
94
|
/** Run a full-sequence forward for training.
|
|
61
95
|
* @param ids int32 array [B, L].
|
|
62
96
|
* @returns logits [B, L, V] (caller owns; dispose when done).
|
|
@@ -90,7 +124,8 @@ export function trainForwardHidden(
|
|
|
90
124
|
// B=1 / no padding: stateless offset-0 caches (one per donor layer), so the
|
|
91
125
|
// forward is pure and safe to recompute under gradient checkpointing.
|
|
92
126
|
const probe = model.makeCache();
|
|
93
|
-
const cache: Cache[] = probe.map(() =>
|
|
127
|
+
const cache: Cache[] = probe.map((c) =>
|
|
128
|
+
c instanceof SSMCache ? new TrainingSSMCache() : new TrainingCache());
|
|
94
129
|
for (const c of probe) c.dispose();
|
|
95
130
|
try {
|
|
96
131
|
return model.forwardHidden(ids, cache); // [B, L, hidden]
|
|
@@ -161,6 +196,8 @@ export function buildBatchedPadMask(
|
|
|
161
196
|
* forwardLayers only disposes the mask it pulled from makeMask, so makeMask
|
|
162
197
|
* hands back a fresh view each call and keeps the canonical copy itself. */
|
|
163
198
|
class BatchedMaskCache implements Cache {
|
|
199
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
200
|
+
signature(): string { return "train:batched-mask"; }
|
|
164
201
|
constructor(
|
|
165
202
|
private readonly inner: Cache,
|
|
166
203
|
private readonly window: number | null,
|
package/src/train/loss.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { logitSoftcap } from "../model/gemma4-base";
|
|
|
27
27
|
import { trainForward, trainForwardHidden } from "./forward";
|
|
28
28
|
import { setLoraScale, type TrainableLora } from "./lora-params";
|
|
29
29
|
import { flashCceForward, flashCceBackward, type FlashCceHead } from "./flash-cce";
|
|
30
|
+
import { runtimeValue } from "../runtime-config";
|
|
30
31
|
|
|
31
32
|
/** The quantized LM-head weights + final-logit softcap, accessed uniformly across
|
|
32
33
|
* models for the fused linear-CE head: Gemma is tied (`embed.asLinear`, softcap
|
|
@@ -1189,7 +1190,7 @@ export function fusedRespLogpMean(
|
|
|
1189
1190
|
// [chunk,vocabBlock]. Otherwise the whole-vocab analytic head below.
|
|
1190
1191
|
const vb = vocabBlock > 0 && vocabBlock < V ? vocabBlock : 0;
|
|
1191
1192
|
// Auto-dispatch by M (kernel backlog #3; measured 2026-07-02 on the M1 Max,
|
|
1192
|
-
//
|
|
1193
|
+
// head-dispatch-sweep.ts (deleted 2026-08-23; git history)): the fused QM head is FASTER
|
|
1193
1194
|
// at short M (e4b M=64 1.6×, M=512 1.13×; CPM5 faster at EVERY M) — the
|
|
1194
1195
|
// flash head's win is residency, plus time at long M on e4b (M≥2048 after
|
|
1195
1196
|
// the 2026-07-02 filter/blockMax flip; 8K: 10.7 vs 13.2 s). So a
|
|
@@ -1197,7 +1198,7 @@ export function fusedRespLogpMean(
|
|
|
1197
1198
|
// e4b time-tie point where flash's memory win takes over) takes the EXACT
|
|
1198
1199
|
// fused head instead — short rows get the faster exact head for free.
|
|
1199
1200
|
// MLX_BUN_FLASH_MIN_M=0 always honors flash (the pre-dispatch behavior).
|
|
1200
|
-
const flashMinM = Number(
|
|
1201
|
+
const flashMinM = Number(runtimeValue("MLX_BUN_FLASH_MIN_M") ?? "1024");
|
|
1201
1202
|
const useFlash = flash && (flashMinM <= 0 || M >= flashMinM);
|
|
1202
1203
|
let op: CustomVjp;
|
|
1203
1204
|
if (useFlash) {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// prompt dominates (our chunk/document fine-tunes), ~0 when the response does.
|
|
12
12
|
//
|
|
13
13
|
// Bit-exact with the two-forward path (validated in
|
|
14
|
-
//
|
|
14
|
+
// prefix-shared-parity.ts (deleted 2026-08-23; git history)): each predicted token uses a hidden
|
|
15
15
|
// conditioned on exactly the same context + RoPE positions —
|
|
16
16
|
// chosen[k] from H[P-1+k] (k=0..Rc-1; H[P-1] = prompt's last)
|
|
17
17
|
// rejected[k] from H[P-1] (k=0) / H[P+Rc+k-1] (k≥1)
|
|
@@ -62,6 +62,8 @@ export function blockSparseMask(P: number, Rc: number, Rr: number): MlxArray {
|
|
|
62
62
|
* TrainingCache) but `makeMask` returns the block-sparse mask. One per layer;
|
|
63
63
|
* MiniCPM5's runLayerRange calls makeMask once and disposes the returned arr. */
|
|
64
64
|
export class PrefixSharedCache implements Cache {
|
|
65
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
66
|
+
signature(): string { return "train:prefix-shared"; }
|
|
65
67
|
offset = 0;
|
|
66
68
|
constructor(
|
|
67
69
|
private readonly P: number, private readonly Rc: number, private readonly Rr: number,
|
|
@@ -371,6 +373,8 @@ export function blockSparsePrefixMaskGemma(P: number, Rc: number, Rr: number, wi
|
|
|
371
373
|
* type serves both (the window arg selects the sliding term). One per DONOR
|
|
372
374
|
* layer (sharers reuse donors' fetched KV). */
|
|
373
375
|
class Gemma4PrefixSharedCache implements Cache {
|
|
376
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
377
|
+
signature(): string { return "train:gemma4prefix-shared"; }
|
|
374
378
|
offset = 0;
|
|
375
379
|
constructor(private readonly P: number, private readonly Rc: number, private readonly Rr: number) {}
|
|
376
380
|
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
package/src/train/segmented.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// segment-by-segment so only ONE segment's activations are ever live, instead
|
|
3
3
|
// of holding every layer's recompute activations at once (the spike that makes
|
|
4
4
|
// naive gradient checkpointing crash at long context). Design + proof:
|
|
5
|
-
// docs/design/
|
|
5
|
+
// docs/design/orpo-training.md (mechanism validated on a toy in
|
|
6
6
|
// scripts/ckpt-mem-test.ts, SEG mode: 0.000% grad error, peak below per-layer
|
|
7
7
|
// checkpointing; bit-exact on MiniCPM5 under flash attention).
|
|
8
8
|
//
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
// `value_and_grad(sum(stop_grad(dh) (.) segment_forward(...)))` is numerically
|
|
25
25
|
// identical but LEAKS ~one activation buffer per segment per step at the mlx
|
|
26
26
|
// level (measured; not GC/cache/synchronize/reuse reclaimable — see
|
|
27
|
-
// docs/design/
|
|
27
|
+
// docs/design/orpo-training.md §9.4). mlx_vjp takes the cotangent
|
|
28
28
|
// directly, needs no surrogate, and does not leak.
|
|
29
29
|
//
|
|
30
30
|
// IMPORTANT lifetime fact: mlx `eval` does NOT detach — an eval'd array retains
|
|
@@ -38,6 +38,7 @@ import { MlxArray } from "../mlx/array";
|
|
|
38
38
|
import * as ops from "../mlx/ops";
|
|
39
39
|
import { peakMemory } from "../mlx/ffi";
|
|
40
40
|
import { Vjp } from "../mlx/autograd";
|
|
41
|
+
import { runtimeValue } from "../runtime-config";
|
|
41
42
|
|
|
42
43
|
// MLX_BUN_SEG_MEM_LOG=1: log the within-step peak after each phase of the
|
|
43
44
|
// segmented step (forward+boundaries / head vjp / each segment backward).
|
|
@@ -46,7 +47,7 @@ import { Vjp } from "../mlx/autograd";
|
|
|
46
47
|
// (This is how the backlog-#2 refutation below was measured. An inter-segment
|
|
47
48
|
// clearCache was also tried and had NO effect — the watermark is live memory,
|
|
48
49
|
// not allocator cache retention.)
|
|
49
|
-
const SEG_MEM =
|
|
50
|
+
const SEG_MEM = runtimeValue("MLX_BUN_SEG_MEM_LOG") === "1";
|
|
50
51
|
const segMem = (label: string): void => {
|
|
51
52
|
if (SEG_MEM) console.log(` [seg-mem] ${label}: peak=${(peakMemory() / 1e9).toFixed(2)} GB`);
|
|
52
53
|
};
|
|
@@ -68,7 +69,7 @@ import { prefixSharedCaches, prefixGatherIdx, branchLogpMeanGathered, blockSpars
|
|
|
68
69
|
// memory at the TOP level but not when nested in the segmented mlx_vjp (its
|
|
69
70
|
// per-chunk graph isn't freed incrementally there); Checkpoint does. See
|
|
70
71
|
// docs/design/orpo-training.md.
|
|
71
|
-
const SEG_HEAD =
|
|
72
|
+
const SEG_HEAD = runtimeValue("MLX_BUN_SEG_HEAD") ?? "checkpoint";
|
|
72
73
|
function boundedHeadFromHidden(
|
|
73
74
|
model: MiniCPM5Model | Gemma4Model, h: MlxArray, ids: number[], mask: number[],
|
|
74
75
|
chunkSize: number, sink: Array<{ dispose(): void }>, span?: HeadSpan,
|
|
@@ -82,7 +83,7 @@ import { rowLength, type SftBatch, type DpoBatch } from "./dataset";
|
|
|
82
83
|
|
|
83
84
|
// Token-chunk size for the bounded SFT head (the ORPO paths take theirs from
|
|
84
85
|
// cfg.orpoChunkSize; SFT has no per-run knob, 512 matches the ORPO default).
|
|
85
|
-
const SFT_HEAD_CHUNK = Number(
|
|
86
|
+
const SFT_HEAD_CHUNK = Number(runtimeValue("MLX_BUN_SEG_HEAD_CHUNK") ?? "512");
|
|
86
87
|
|
|
87
88
|
/** [M,V]-bounded response-only CE from post-finalNorm hidden — the SFT
|
|
88
89
|
* segmented head (kernel-review backlog #8). Same span arithmetic and
|
|
@@ -129,7 +130,7 @@ export function planSegmentsBySize(nLayers: number, segSize: number): [number, n
|
|
|
129
130
|
// segment_size 1 measures 14.59 GB @8K (+3% step time) vs 17.5 @seg2. Below
|
|
130
131
|
// that needs the [M,V]-bounded SFT head (backlog #8, ~3 GB head-vjp spike)
|
|
131
132
|
// and/or an O(L)-memory attention backward. Evidence:
|
|
132
|
-
//
|
|
133
|
+
// seg-isolation-smoke.ts (deleted 2026-08-23; git history) + MLX_BUN_SEG_MEM_LOG=1 probes.
|
|
133
134
|
|
|
134
135
|
/** Detach `a` into a graph-free LEAF holding its exact (evaluated) bytes, then
|
|
135
136
|
* dispose `a`. mlx retains the upstream graph after `eval`, so a segment
|
|
@@ -1516,6 +1517,8 @@ export class SegmentedBackwardOrpoGemma4 {
|
|
|
1516
1517
|
* and null for full layers; the window arg selects the sliding term. One per DONOR
|
|
1517
1518
|
* layer (sharers reuse donors' fetched KV inside runLayerRange). */
|
|
1518
1519
|
class Gemma4PrefixSharedSegCache implements Cache {
|
|
1520
|
+
/** Training-only adapter; never admitted, merged, or persisted. */
|
|
1521
|
+
signature(): string { return "train:gemma4-prefix-shared-seg"; }
|
|
1519
1522
|
offset = 0;
|
|
1520
1523
|
constructor(private readonly P: number, private readonly Rc: number, private readonly Rr: number) {}
|
|
1521
1524
|
updateAndFetch(k: MlxArray, v: MlxArray): [MlxArray, MlxArray] {
|
package/src/train/trainer.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
import { MlxArray, pinnedBufferCount } from "../mlx/array";
|
|
12
12
|
import { clearCache, peakMemory, activeMemory, cacheMemory, resetPeakMemory } from "../mlx/ffi";
|
|
13
|
+
import { runtimeValue } from "../runtime-config";
|
|
13
14
|
|
|
14
|
-
const MEM_LOG =
|
|
15
|
+
const MEM_LOG = runtimeValue("MLX_BUN_MEM_LOG") === "1";
|
|
15
16
|
const gbStr = (b: number) => `${(b / 1e9).toFixed(2)}GB`;
|
|
16
17
|
import { ValueAndGrad } from "../mlx/autograd";
|
|
17
18
|
import * as ops from "../mlx/ops";
|
|
@@ -81,7 +82,7 @@ export interface TrainConfig {
|
|
|
81
82
|
* beats per-layer checkpointing at long context, where naive checkpointing
|
|
82
83
|
* holds every layer's recompute activations at once and crashes. B=1 SFT
|
|
83
84
|
* only (the responseOnlyCe path); mutually exclusive with gradCheckpoint.
|
|
84
|
-
* Numerically identical to off. See docs/design/
|
|
85
|
+
* Numerically identical to off. See docs/design/orpo-training.md. */
|
|
85
86
|
segmentSize: number;
|
|
86
87
|
/** Keep ALL eval-step checkpoints (full mountable adapters under
|
|
87
88
|
* checkpoints/step-<NNNNN>-val<loss>/) + write metrics.json. Off by default
|
|
@@ -439,12 +440,12 @@ export async function trainLora(
|
|
|
439
440
|
|
|
440
441
|
// ---------------------------------------------------------------------------
|
|
441
442
|
// Segment planning: uniform planSegmentsBySize only. A full-attention
|
|
442
|
-
// ISOLATION planner (kernel-review backlog #2 /
|
|
443
|
+
// ISOLATION planner (kernel-review backlog #2 / docs/design/orpo-training.md
|
|
443
444
|
// §5) was built and A/B-measured 2026-07-02: ZERO peak win — mlx's sdpa
|
|
444
445
|
// backward is O(L²) for EVERY layer (~3.5 GB/layer @8K e4b), sliding included,
|
|
445
446
|
// so the worst segment is set by layer count alone and segment_size is the
|
|
446
447
|
// whole knob (seg1 = 14.59 GB @8K, +3% step time — fits the 24 GB M4 Pro).
|
|
447
|
-
// Evidence:
|
|
448
|
+
// Evidence: seg-isolation-smoke.ts (deleted 2026-08-23; git history); note in segmented.ts.
|
|
448
449
|
// ---------------------------------------------------------------------------
|
|
449
450
|
|
|
450
451
|
// ---------------------------------------------------------------------------
|
|
@@ -472,7 +473,7 @@ async function sftLoop(
|
|
|
472
473
|
// Segmented backward: stream the SFT backward segment-by-segment (only one
|
|
473
474
|
// segment's activations live at a time). Phase A is MiniCPM5 SFT B=1 only;
|
|
474
475
|
// it replaces the single value_and_grad below and is mutually exclusive with
|
|
475
|
-
// gradient checkpointing (see docs/design/
|
|
476
|
+
// gradient checkpointing (see docs/design/orpo-training.md).
|
|
476
477
|
const useSegmented = cfg.segmentSize > 0;
|
|
477
478
|
let segmented: SegmentedBackward | SegmentedBackwardGemma4 | null = null;
|
|
478
479
|
if (useSegmented) {
|
|
@@ -531,19 +532,19 @@ async function sftLoop(
|
|
|
531
532
|
// hand-rolled flash kernel is an opt-in (MLX_BUN_TRAIN_ATTN=flash) O(L)-memory
|
|
532
533
|
// path for memory-bound long context — now correct (its dK-transpose and
|
|
533
534
|
// dQ-causal-barrier bugs were fixed; FD-validated in
|
|
534
|
-
//
|
|
535
|
+
// flash-fd-check.ts (deleted 2026-08-23; git history)), though ~30× slower than ops.sdpa.
|
|
535
536
|
// Cleared in finally.
|
|
536
537
|
//
|
|
537
538
|
// GEMMA GUARD (same convention as the launcher's env sanitization in
|
|
538
539
|
// cli.ts / job.ts, but enforced at the trainer): e4b on this path SIGTRAPed
|
|
539
540
|
// (uncatchable native crash) at multi-K sequence lengths (>=2K, reproduced in
|
|
540
|
-
//
|
|
541
|
+
// segmented-grad-test-e4b.ts (deleted 2026-08-23; git history); docs/reference/training.md)
|
|
541
542
|
// and has NOT been re-validated at that scale since the two kernel fixes —
|
|
542
543
|
// the regression tests stop at T<=256. cli.ts even defaults e4b seq to 8192,
|
|
543
544
|
// so a stale `export MLX_BUN_TRAIN_ATTN=flash` from a MiniCPM5 experiment
|
|
544
545
|
// would otherwise ride silently into a crash mid-run. Refuse it for Gemma
|
|
545
546
|
// until the >=2K re-validation lands; MiniCPM5 stays allowed.
|
|
546
|
-
if (
|
|
547
|
+
if (runtimeValue("MLX_BUN_TRAIN_ATTN") === "flash") {
|
|
547
548
|
if (model instanceof Gemma4Model)
|
|
548
549
|
throw new Error(
|
|
549
550
|
"MLX_BUN_TRAIN_ATTN=flash is disabled for Gemma models: e4b SIGTRAPs on this " +
|
package/src/vision/preprocess.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// 1/255 → patchify into 48×48 patch vectors with 2D grid positions →
|
|
7
7
|
// pad to the 280 soft-token budget.
|
|
8
8
|
//
|
|
9
|
-
// Decode strategy (Bun ≥1.
|
|
9
|
+
// Decode strategy (Bun ≥1.4.0): PNG goes straight through fast-png
|
|
10
10
|
// (exact, lossless — the parity-golden path). Everything else (JPEG,
|
|
11
11
|
// HEIC, AVIF, WebP, TIFF, GIF, BMP) is transcoded to lossless PNG by
|
|
12
12
|
// Bun.Image — native OS codecs (ImageIO on macOS), EXIF auto-orient,
|
package/src/vision/prompt.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// n = min(ceil(duration_ms/40), 750) (processing_gemma4.py) — embed the full
|
|
9
9
|
// sequence, then overwrite the soft-token rows with the towers' features.
|
|
10
10
|
//
|
|
11
|
-
// Attention semantics (
|
|
11
|
+
// Attention semantics (docs/design/generic-model-support.md §3.3, resolved vs the oracle):
|
|
12
12
|
// - image runs attend bidirectionally among themselves (bidirMask), BUT
|
|
13
13
|
// any audio token in the prompt disables the vision overlay entirely —
|
|
14
14
|
// mixed image+audio prompts run fully causal (bidirMask = null);
|
|
@@ -26,7 +26,7 @@ import type { LoadedTokenizer } from "../tokenizer";
|
|
|
26
26
|
import type { AudioTower } from "../audio/conformer";
|
|
27
27
|
import { audioSoftTokenCount, decodeAudio } from "../audio/decode";
|
|
28
28
|
import { extractMelFeatures } from "../audio/features";
|
|
29
|
-
import { fetchMediaBytes } from "../media-fetch";
|
|
29
|
+
import { fetchMediaBytes, videoMediaFetchPolicy } from "../media-fetch";
|
|
30
30
|
|
|
31
31
|
/** Common contract for both vision towers (encoder-free gemma4_unified in
|
|
32
32
|
* ./embedder.ts and the SigLIP encoder in ./siglip.ts): preprocess image
|
|
@@ -117,6 +117,52 @@ export async function extractImages(
|
|
|
117
117
|
return { messages: out, images };
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/** Extract video bytes from content parts, rewriting to the template's
|
|
121
|
+
* {type:"video"} form. Accepts {type:"video_url", video_url:{url}} (data:
|
|
122
|
+
* or http(s), same SSRF guard as images with the larger video body cap)
|
|
123
|
+
* and {type:"video"} with base64 `data`. Decode to frames happens later
|
|
124
|
+
* (vision/video-frames.ts — the AVFoundation sidecar). */
|
|
125
|
+
export async function extractVideos(
|
|
126
|
+
messages: ChatMessage[],
|
|
127
|
+
): Promise<{ messages: ChatMessage[]; videos: Uint8Array[] }> {
|
|
128
|
+
const videos: Uint8Array[] = [];
|
|
129
|
+
const out: ChatMessage[] = [];
|
|
130
|
+
for (const m of messages) {
|
|
131
|
+
if (!Array.isArray(m.content)) {
|
|
132
|
+
out.push(m);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const parts: Array<Record<string, unknown>> = [];
|
|
136
|
+
for (const part of m.content) {
|
|
137
|
+
if (part.type === "video_url") {
|
|
138
|
+
const url = (part.video_url as { url: string } | undefined)?.url
|
|
139
|
+
?? (part.video_url as unknown as string);
|
|
140
|
+
if (typeof url !== "string") throw new Error("video_url part missing url");
|
|
141
|
+
videos.push(await fetchMediaBytes(url, "video"));
|
|
142
|
+
parts.push({ type: "video" });
|
|
143
|
+
} else if (part.type === "video") {
|
|
144
|
+
if (typeof part.data === "string") {
|
|
145
|
+
// Same cap as fetched/data:-URL video bodies — the inline base64
|
|
146
|
+
// form must not be the uncapped route.
|
|
147
|
+
const cap = videoMediaFetchPolicy().maxBytes;
|
|
148
|
+
if (part.data.length * 0.75 > cap)
|
|
149
|
+
throw new Error(
|
|
150
|
+
`video part exceeds the ${Math.round(cap / 1024 / 1024)} MB cap`,
|
|
151
|
+
);
|
|
152
|
+
videos.push(Uint8Array.from(Buffer.from(part.data, "base64")));
|
|
153
|
+
parts.push({ type: "video" });
|
|
154
|
+
} else {
|
|
155
|
+
throw new Error("video part requires base64 `data`");
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
parts.push(part);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
out.push({ ...m, content: parts });
|
|
162
|
+
}
|
|
163
|
+
return { messages: out, videos };
|
|
164
|
+
}
|
|
165
|
+
|
|
120
166
|
/** Extract audio bytes from OpenAI-style content parts, rewriting the parts
|
|
121
167
|
* to the template's {type:"audio"} form. Accepts the OpenAI-canonical
|
|
122
168
|
* {type:"input_audio", input_audio:{data:<b64>, format:...}} plus optiq's
|