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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ExecutionCapabilities, ExecutionFeatures, ExecutionRequirements, ResolvedExecution } from "../contracts/execution";
|
|
2
|
+
|
|
3
|
+
/** Preserve the shipped support matrix. A configured draft still forces serial
|
|
4
|
+
* placement even when this request must use the ordinary AR method. */
|
|
5
|
+
export function resolveExecution(
|
|
6
|
+
request: ExecutionRequirements, capabilities: ExecutionCapabilities,
|
|
7
|
+
features: ExecutionFeatures = { pagedKv: false, fill: false },
|
|
8
|
+
): ResolvedExecution {
|
|
9
|
+
const reasons: string[] = [];
|
|
10
|
+
const continuousExclusions = [
|
|
11
|
+
[!capabilities.continuous, "continuous-unavailable"],
|
|
12
|
+
[capabilities.method !== "autoregressive", "method-requires-serial"],
|
|
13
|
+
[request.hasVision, "media-requires-serial"],
|
|
14
|
+
[request.hasAdapters, "adapters-require-serial"],
|
|
15
|
+
[request.wantsLogprobs, "logprobs-require-serial"],
|
|
16
|
+
[request.userSeed, "explicit-seed-requires-serial"],
|
|
17
|
+
[request.kvQuant && !capabilities.quantizedBatch, "kv-scheme-requires-serial"],
|
|
18
|
+
[request.turboQuant, "turbo-kv-requires-serial"],
|
|
19
|
+
[request.hasDraft, "configured-draft-requires-serial"],
|
|
20
|
+
[request.hasGrammar && !capabilities.grammarBatch, "grammar-batching-disabled"],
|
|
21
|
+
[features.pagedKv, "paged-kv-requires-serial"],
|
|
22
|
+
] as const;
|
|
23
|
+
for (const [excluded, reason] of continuousExclusions) if (excluded) reasons.push(reason);
|
|
24
|
+
const mechanism = reasons.length ? "serial" : "continuous";
|
|
25
|
+
const speculative = capabilities.method === "autoregressive" && request.hasDraft &&
|
|
26
|
+
!request.hasVision && !request.hasAdapters && !request.wantsLogprobs &&
|
|
27
|
+
(!request.kvQuant || capabilities.speculativeKvQuant === true) &&
|
|
28
|
+
!request.turboQuant && !features.pagedKv;
|
|
29
|
+
if (request.hasDraft && !speculative) reasons.push("draft-incompatible-with-request");
|
|
30
|
+
const method = speculative ? "speculative" : capabilities.method;
|
|
31
|
+
const pagedKv = features.pagedKv && !request.hasVision && !request.hasAdapters;
|
|
32
|
+
if (features.pagedKv && !pagedKv) reasons.push("paged-kv-bypassed-for-media-or-adapters");
|
|
33
|
+
const promptCache = method !== "speculative" && !request.hasVision && !pagedKv;
|
|
34
|
+
const fill = features.fill && method === "autoregressive" && mechanism === "serial" &&
|
|
35
|
+
!request.hasDraft && !request.hasVision && !request.userSeed && !request.hasGrammar &&
|
|
36
|
+
!request.wantsLogprobs && !request.kvQuant && !request.turboQuant;
|
|
37
|
+
if (features.fill && !fill) reasons.push("fill-incompatible-with-request");
|
|
38
|
+
const checkpoint = capabilities.checkpoints && method === "autoregressive" &&
|
|
39
|
+
mechanism === "serial" && promptCache && !request.hasGrammar &&
|
|
40
|
+
!features.fill && !request.wantsLogprobs;
|
|
41
|
+
const compiledDecode = features.compiledDecode === true && capabilities.compiledDecode === true &&
|
|
42
|
+
method === "autoregressive" && !request.hasAdapters && !pagedKv;
|
|
43
|
+
if (features.compiledDecode && !compiledDecode) reasons.push("compiled-decode-unavailable-for-request");
|
|
44
|
+
const grammarJump = features.grammarJump === true && request.hasGrammar &&
|
|
45
|
+
method === "autoregressive" && mechanism === "serial" && !request.wantsLogprobs;
|
|
46
|
+
if (features.grammarJump && request.hasGrammar && !grammarJump)
|
|
47
|
+
reasons.push("grammar-jump-incompatible-with-request");
|
|
48
|
+
return Object.freeze({ method, mechanism, pagedKv, promptCache, checkpoint, fill,
|
|
49
|
+
compiledDecode, grammarJump,
|
|
50
|
+
reasons: Object.freeze(reasons) });
|
|
51
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { DisposableResource, ResourceOwner } from "../contracts/resources";
|
|
2
|
+
|
|
3
|
+
export function ownResource<T>(value: T, release: (value: T) => void): ResourceOwner<T> {
|
|
4
|
+
let held: { value: T } | undefined = { value };
|
|
5
|
+
const borrow = () => {
|
|
6
|
+
if (!held) throw new Error("resource ownership has ended");
|
|
7
|
+
return held.value;
|
|
8
|
+
};
|
|
9
|
+
return {
|
|
10
|
+
borrow,
|
|
11
|
+
transfer() { const result = borrow(); held = undefined; return result; },
|
|
12
|
+
close() {
|
|
13
|
+
if (!held) return;
|
|
14
|
+
const result = held.value;
|
|
15
|
+
held = undefined;
|
|
16
|
+
release(result);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Attempt every release once. One failed destructor must not leak siblings. */
|
|
22
|
+
export function disposeResources(resources: Iterable<DisposableResource>): void {
|
|
23
|
+
const errors: unknown[] = [];
|
|
24
|
+
for (const resource of new Set(resources)) {
|
|
25
|
+
try { resource.dispose(); } catch (error) { errors.push(error); }
|
|
26
|
+
}
|
|
27
|
+
if (errors.length === 1) throw errors[0];
|
|
28
|
+
if (errors.length) throw new AggregateError(errors, "resource cleanup failed");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Used at failure boundaries to retain the execution error as well as cleanup. */
|
|
32
|
+
export function cleanupFailure(error: unknown, cleanup: () => void): never {
|
|
33
|
+
try { cleanup(); }
|
|
34
|
+
catch (cleanupError) { throw new AggregateError([error, cleanupError], "execution and cleanup failed"); }
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function withResource<T, R>(owner: Pick<ResourceOwner<T>, "borrow" | "close">, use: (value: T) => R): R {
|
|
39
|
+
try { return use(owner.borrow()); }
|
|
40
|
+
catch (error) { cleanupFailure(error, () => owner.close()); }
|
|
41
|
+
finally { owner.close(); }
|
|
42
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ExecutionGroup, SchedulingClock } from "../contracts/scheduling";
|
|
2
|
+
import { disposeResources } from "./resources";
|
|
3
|
+
|
|
4
|
+
/** Continuous scheduling policy. Each advance is a backend-defined safe unit;
|
|
5
|
+
* this driver neither handles native state nor forces pending work to evaluate. */
|
|
6
|
+
export async function driveExecutionGroup(
|
|
7
|
+
group: ExecutionGroup, clock: SchedulingClock, yieldAfterPreparation = false,
|
|
8
|
+
): Promise<void> {
|
|
9
|
+
let execution: (() => void) | undefined;
|
|
10
|
+
let residency: (() => void) | undefined;
|
|
11
|
+
let lastYield = 0;
|
|
12
|
+
let terminalError: unknown = new Error("scheduler closed");
|
|
13
|
+
const release = () => {
|
|
14
|
+
const releases = [execution, residency];
|
|
15
|
+
execution = residency = undefined;
|
|
16
|
+
disposeResources(releases.filter((fn): fn is () => void => !!fn).map((dispose) => ({ dispose })));
|
|
17
|
+
};
|
|
18
|
+
try {
|
|
19
|
+
while (!group.closed) {
|
|
20
|
+
group.pruneCancelled();
|
|
21
|
+
const held = group.admissionHeld;
|
|
22
|
+
if (!group.active && !group.preparing && (held || !group.queued)) {
|
|
23
|
+
release();
|
|
24
|
+
await group.waitForWork();
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
residency ??= group.reserveResidency();
|
|
28
|
+
if (!execution && group.acquireExecution) execution = await group.acquireExecution();
|
|
29
|
+
if (group.closed) break;
|
|
30
|
+
|
|
31
|
+
if (!group.preparing && !held && group.queued && group.active < group.maxActive)
|
|
32
|
+
group.admitNext();
|
|
33
|
+
if (group.preparing) {
|
|
34
|
+
const activeBefore = group.active;
|
|
35
|
+
await group.advancePreparation();
|
|
36
|
+
// A backend may emit its first output while preparing the first row.
|
|
37
|
+
// Flush a lone admission before decode; queued short admissions still
|
|
38
|
+
// group together. Re-enter policy after yielding to observe new work,
|
|
39
|
+
// cancellation, admission holds and shutdown.
|
|
40
|
+
if (yieldAfterPreparation && !activeBefore && !group.preparing &&
|
|
41
|
+
group.active === 1 && !group.queued) {
|
|
42
|
+
lastYield = clock.now();
|
|
43
|
+
await clock.yield();
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Finish short admissions before decode; long preparation interleaves
|
|
49
|
+
// with active work because the group still reports preparing=true.
|
|
50
|
+
if (!group.preparing && !held && group.queued && group.active < group.maxActive && group.canBurst())
|
|
51
|
+
continue;
|
|
52
|
+
if (group.active) {
|
|
53
|
+
try { await group.advance(); }
|
|
54
|
+
catch (error) { group.failActive(error); }
|
|
55
|
+
}
|
|
56
|
+
// Preserve the serial responsiveness budget for the single active run.
|
|
57
|
+
if (group.active === 1 && !group.queued && !group.preparing &&
|
|
58
|
+
!group.admissionHeld && clock.now() - lastYield < 25) continue;
|
|
59
|
+
lastYield = clock.now();
|
|
60
|
+
await clock.yield();
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
terminalError = error;
|
|
64
|
+
} finally {
|
|
65
|
+
disposeResources([{ dispose: () => group.failAll(terminalError) }, { dispose: release }]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Cancellation, CancelReason, ExecutionPlan, GenerationEvent, GenerationOutcome,
|
|
3
|
+
GenerationOutput, GenerationSession, MethodResult, MethodRun, RunControl,
|
|
4
|
+
SessionState, Timer, TokenLogprobs,
|
|
5
|
+
} from "../contracts/generation";
|
|
6
|
+
import { CancellationSource, throwIfCancelled } from "./cancellation";
|
|
7
|
+
|
|
8
|
+
export interface SessionResources {
|
|
9
|
+
readonly timer: Timer;
|
|
10
|
+
readonly idleTimeoutMs: number;
|
|
11
|
+
readonly maxQueuedEvents: number;
|
|
12
|
+
readonly maxQueuedTokens: number;
|
|
13
|
+
readonly maxTopLogprobs: number;
|
|
14
|
+
reserveOutput(tokens: number): { buffer: Uint32Array; release(): void };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Lifecycle and bounded delivery only. No graph, cache, sampler, or method branches. */
|
|
18
|
+
export class EngineSession<Metrics> implements GenerationSession<Metrics> {
|
|
19
|
+
readonly result: Promise<GenerationOutcome<Metrics>>;
|
|
20
|
+
readonly events: AsyncIterable<GenerationEvent>;
|
|
21
|
+
#state: SessionState = "created";
|
|
22
|
+
#cancel = new CancellationSource();
|
|
23
|
+
#settle!: (outcome: GenerationOutcome<Metrics>) => void;
|
|
24
|
+
#started = false;
|
|
25
|
+
#readerClaimed = false;
|
|
26
|
+
#reading = false;
|
|
27
|
+
#publishing = false;
|
|
28
|
+
#queue: GenerationEvent[] = [];
|
|
29
|
+
#queuedTokens = 0;
|
|
30
|
+
#committed = 0;
|
|
31
|
+
#sequence = 0;
|
|
32
|
+
#wakeReader: (() => void) | undefined;
|
|
33
|
+
#wakeProducer: (() => void) | undefined;
|
|
34
|
+
#stopTimer: (() => void) | undefined;
|
|
35
|
+
#unsubscribe: (() => void) | undefined;
|
|
36
|
+
#buffer: Uint32Array | undefined;
|
|
37
|
+
#limit = 0;
|
|
38
|
+
#outputStopped = false;
|
|
39
|
+
|
|
40
|
+
constructor(
|
|
41
|
+
readonly id: string,
|
|
42
|
+
private readonly prepare: (cancellation: Cancellation) => Promise<ExecutionPlan<Metrics>>,
|
|
43
|
+
private readonly control: RunControl,
|
|
44
|
+
private readonly resources: SessionResources,
|
|
45
|
+
private readonly onTerminal: () => void,
|
|
46
|
+
) {
|
|
47
|
+
this.result = new Promise((resolve) => { this.#settle = resolve; });
|
|
48
|
+
this.events = { [Symbol.asyncIterator]: () => this.#iterator() };
|
|
49
|
+
const unsubscribe = control.cancellation?.subscribe((reason) => { void this.cancel(reason); });
|
|
50
|
+
if (this.#state === "terminal") unsubscribe?.();
|
|
51
|
+
else this.#unsubscribe = unsubscribe;
|
|
52
|
+
if (this.#state !== "terminal") {
|
|
53
|
+
if (control.output !== "stream") this.#start();
|
|
54
|
+
else this.#armIdle();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get state(): SessionState { return this.#state; }
|
|
59
|
+
|
|
60
|
+
async cancel(reason: CancelReason = "requested"): Promise<void> {
|
|
61
|
+
if (this.#state !== "terminal") {
|
|
62
|
+
this.#cancel.cancel(reason);
|
|
63
|
+
this.#queue = [];
|
|
64
|
+
this.#queuedTokens = 0;
|
|
65
|
+
this.#wakeReader?.();
|
|
66
|
+
this.#wakeProducer?.();
|
|
67
|
+
this.#stopTimer?.();
|
|
68
|
+
if (!this.#started) this.#finish({ status: "cancelled", reason, committedTokens: 0 });
|
|
69
|
+
}
|
|
70
|
+
await this.result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
close(): Promise<void> { return this.cancel("consumer_closed"); }
|
|
74
|
+
|
|
75
|
+
#armIdle(): void {
|
|
76
|
+
this.#stopTimer?.();
|
|
77
|
+
this.#stopTimer = this.resources.timer.after(this.resources.idleTimeoutMs,
|
|
78
|
+
() => { void this.cancel("consumer_idle"); });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#iterator(): AsyncIterator<GenerationEvent> {
|
|
82
|
+
if (this.control.output !== "stream") throw new Error("collect sessions return output through result");
|
|
83
|
+
if (this.#readerClaimed) throw new Error("generation events have one consumer");
|
|
84
|
+
this.#readerClaimed = true;
|
|
85
|
+
return {
|
|
86
|
+
next: async () => {
|
|
87
|
+
if (this.#reading) throw new Error("concurrent next() is not supported");
|
|
88
|
+
this.#reading = true;
|
|
89
|
+
this.#stopTimer?.();
|
|
90
|
+
try {
|
|
91
|
+
this.#start();
|
|
92
|
+
while (!this.#queue.length && this.#state !== "terminal") {
|
|
93
|
+
await new Promise<void>((resolve) => { this.#wakeReader = resolve; });
|
|
94
|
+
this.#wakeReader = undefined;
|
|
95
|
+
}
|
|
96
|
+
const event = this.#queue.shift();
|
|
97
|
+
if (!event) return { done: true, value: undefined };
|
|
98
|
+
if (event.type === "committed") this.#queuedTokens -= event.tokenIds.length;
|
|
99
|
+
this.#wakeProducer?.();
|
|
100
|
+
if (this.#state !== "terminal") this.#armIdle();
|
|
101
|
+
return { done: false, value: event };
|
|
102
|
+
} finally { this.#reading = false; }
|
|
103
|
+
},
|
|
104
|
+
return: async () => { await this.close(); return { done: true, value: undefined }; },
|
|
105
|
+
throw: async (error) => { await this.close(); throw error; },
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#start(): void {
|
|
110
|
+
if (this.#started || this.#state === "terminal") return;
|
|
111
|
+
this.#started = true;
|
|
112
|
+
void this.#execute();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async #execute(): Promise<void> {
|
|
116
|
+
let run: MethodRun<Metrics> | undefined;
|
|
117
|
+
let reservation: ReturnType<SessionResources["reserveOutput"]> | undefined;
|
|
118
|
+
let result: MethodResult<Metrics> | undefined;
|
|
119
|
+
let failure: unknown;
|
|
120
|
+
let failed = false;
|
|
121
|
+
try {
|
|
122
|
+
this.#state = "preparing";
|
|
123
|
+
throwIfCancelled(this.#cancel);
|
|
124
|
+
const plan = await this.prepare(this.#cancel);
|
|
125
|
+
throwIfCancelled(this.#cancel);
|
|
126
|
+
if (!Number.isSafeInteger(plan.outputTokenLimit) || plan.outputTokenLimit < 0)
|
|
127
|
+
throw new Error("invalid planned output token limit");
|
|
128
|
+
this.#limit = plan.outputTokenLimit;
|
|
129
|
+
if (this.control.output === "collect") {
|
|
130
|
+
reservation = this.resources.reserveOutput(this.#limit);
|
|
131
|
+
this.#buffer = reservation.buffer;
|
|
132
|
+
}
|
|
133
|
+
run = await plan.method.createRun(this.#cancel);
|
|
134
|
+
throwIfCancelled(this.#cancel);
|
|
135
|
+
this.#state = "running";
|
|
136
|
+
const output: GenerationOutput = {
|
|
137
|
+
commit: (ids, logprobs) => this.#publish(ids, logprobs),
|
|
138
|
+
progress: (completed, total) => this.#progress(completed, total),
|
|
139
|
+
};
|
|
140
|
+
result = await run.execute(output, this.#cancel);
|
|
141
|
+
} catch (error) { failure = error; failed = true; }
|
|
142
|
+
this.#state = "settling";
|
|
143
|
+
// Terminal means resources are safe to release, not merely that JS stopped reading.
|
|
144
|
+
let cleanupFailed = false;
|
|
145
|
+
let cleanupError: string | undefined;
|
|
146
|
+
try { await run?.close(); }
|
|
147
|
+
catch (error) {
|
|
148
|
+
cleanupError = error instanceof Error ? error.message : String(error);
|
|
149
|
+
if (!failed) failure = error;
|
|
150
|
+
failed = true;
|
|
151
|
+
cleanupFailed = true;
|
|
152
|
+
}
|
|
153
|
+
reservation?.release(); // Completed output ownership transfers to the caller.
|
|
154
|
+
const common = { committedTokens: this.#committed,
|
|
155
|
+
...(this.#buffer ? { output: this.#buffer.subarray(0, this.#committed) } : {}) };
|
|
156
|
+
if (this.#cancel.reason && !cleanupFailed) {
|
|
157
|
+
this.#finish({ status: "cancelled", reason: this.#cancel.reason, ...common });
|
|
158
|
+
} else if (failed) {
|
|
159
|
+
this.#finish({ status: "failed", error: { code: cleanupFailed ? "cleanup_failed" : "execution_failed",
|
|
160
|
+
message: failure instanceof Error ? failure.message : String(failure),
|
|
161
|
+
...(cleanupError === undefined ? {} : { cleanupError }) }, ...common });
|
|
162
|
+
} else {
|
|
163
|
+
this.#finish({ status: "completed", result: result!, ...common });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async #publish(ids: readonly number[], logprobs?: readonly (TokenLogprobs | undefined)[]): Promise<void | false> {
|
|
168
|
+
if (this.#publishing) throw new Error("method must await each publication");
|
|
169
|
+
this.#publishing = true;
|
|
170
|
+
try {
|
|
171
|
+
throwIfCancelled(this.#cancel);
|
|
172
|
+
if (this.#state !== "running") throw new Error("publication outside method execution");
|
|
173
|
+
if (this.#outputStopped) throw new Error("method published after the consumer requested a stop");
|
|
174
|
+
if (ids.length > this.#limit - this.#committed) throw new Error("method exceeded planned output limit");
|
|
175
|
+
if (logprobs && logprobs.length !== ids.length) throw new Error("logprobs must align with committed tokens");
|
|
176
|
+
if (logprobs?.some((item) => (item?.top?.length ?? 0) > this.resources.maxTopLogprobs))
|
|
177
|
+
throw new Error("top logprobs exceed session delivery capacity");
|
|
178
|
+
for (const id of ids)
|
|
179
|
+
if (!Number.isInteger(id) || id < 0 || id > 0xffffffff) throw new Error("invalid committed token id");
|
|
180
|
+
if (this.control.output === "callback") {
|
|
181
|
+
this.#committed += ids.length;
|
|
182
|
+
const result = await this.control.onTokens(ids, logprobs);
|
|
183
|
+
if (result === false) this.#outputStopped = true;
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
if (this.#buffer) {
|
|
187
|
+
if (logprobs) throw new Error("token logprobs require stream consumption");
|
|
188
|
+
this.#buffer.set(ids, this.#committed);
|
|
189
|
+
this.#committed += ids.length;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
for (let offset = 0; offset < ids.length;) {
|
|
193
|
+
const length = Math.min(ids.length - offset, this.resources.maxQueuedTokens);
|
|
194
|
+
await this.#space(length);
|
|
195
|
+
// Snapshot producer-owned arrays; later scratch-buffer reuse cannot alter events.
|
|
196
|
+
const event: GenerationEvent = { type: "committed", sequence: this.#sequence++,
|
|
197
|
+
tokenIds: ids.slice(offset, offset + length),
|
|
198
|
+
...(logprobs ? { logprobs: logprobs.slice(offset, offset + length).map((item) => item && ({
|
|
199
|
+
...(item.logprob === undefined ? {} : { logprob: item.logprob }),
|
|
200
|
+
...(item.top ? { top: item.top.map((entry) => ({ id: entry.id, logprob: entry.logprob })) } : {}),
|
|
201
|
+
})) } : {}) };
|
|
202
|
+
this.#queue.push(event);
|
|
203
|
+
this.#queuedTokens += length;
|
|
204
|
+
this.#committed += length;
|
|
205
|
+
offset += length;
|
|
206
|
+
this.#wakeReader?.();
|
|
207
|
+
}
|
|
208
|
+
} finally { this.#publishing = false; }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async #progress(completed: number, total?: number): Promise<void> {
|
|
212
|
+
if (this.#publishing) throw new Error("method must await each publication");
|
|
213
|
+
this.#publishing = true;
|
|
214
|
+
try {
|
|
215
|
+
throwIfCancelled(this.#cancel);
|
|
216
|
+
if (this.#state !== "running") throw new Error("publication outside method execution");
|
|
217
|
+
if (!Number.isFinite(completed) || completed < 0 ||
|
|
218
|
+
(total !== undefined && (!Number.isFinite(total) || total < completed)))
|
|
219
|
+
throw new Error("invalid progress");
|
|
220
|
+
if (this.control.output !== "stream") return;
|
|
221
|
+
await this.#space(0);
|
|
222
|
+
this.#queue.push({ type: "progress", completed, ...(total === undefined ? {} : { total }) });
|
|
223
|
+
this.#wakeReader?.();
|
|
224
|
+
} finally { this.#publishing = false; }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async #space(tokens: number): Promise<void> {
|
|
228
|
+
while (this.#queue.length >= this.resources.maxQueuedEvents ||
|
|
229
|
+
this.#queuedTokens + tokens > this.resources.maxQueuedTokens) {
|
|
230
|
+
throwIfCancelled(this.#cancel);
|
|
231
|
+
this.#armIdle();
|
|
232
|
+
await new Promise<void>((resolve) => { this.#wakeProducer = resolve; });
|
|
233
|
+
this.#wakeProducer = undefined;
|
|
234
|
+
}
|
|
235
|
+
throwIfCancelled(this.#cancel);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#finish(outcome: GenerationOutcome<Metrics>): void {
|
|
239
|
+
if (this.#state === "terminal") return;
|
|
240
|
+
this.#state = "terminal";
|
|
241
|
+
this.#stopTimer?.();
|
|
242
|
+
this.#unsubscribe?.();
|
|
243
|
+
this.#settle(outcome);
|
|
244
|
+
this.#wakeReader?.();
|
|
245
|
+
this.onTerminal();
|
|
246
|
+
}
|
|
247
|
+
}
|
package/src/eval/README.md
CHANGED
|
@@ -29,6 +29,45 @@ repo rule: free-running greedy "measures chaos").
|
|
|
29
29
|
`KL(compat ‖ fused)` is literally "measure the output difference."
|
|
30
30
|
- **two-model (optiq-style absolute quality):** a separate reference model
|
|
31
31
|
(bf16 if it fits, else uniform-4bit), both resident.
|
|
32
|
+
- **saved-teacher (`--reference-logits <dir>`):** the reference is a
|
|
33
|
+
**dump on disk**, not a resident model — the only way to score against a
|
|
34
|
+
bf16 teacher on 32 GB. A Python-side script forwards the teacher once and
|
|
35
|
+
writes, per teacher-forced position, the top-2048 logits plus the
|
|
36
|
+
**full-vocab logsumexp**; every candidate is then scored through OUR
|
|
37
|
+
engine. Format (`format_version` 1, read by `reference-logits.ts`):
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
runs/kl-teacher/<tag>/
|
|
41
|
+
manifest.json {format_version, model, corpus_sha256, ctx_len, n_seqs,
|
|
42
|
+
top_k, positions_per_seq, created, notes}
|
|
43
|
+
tokens.bin int32 LE [n_seqs][ctx_len]
|
|
44
|
+
seq-<i>.bin record r (r = 0…ctx_len-2, the distribution over token
|
|
45
|
+
r+1, i.e. candidate POSITION r):
|
|
46
|
+
int32[top_k] indices, descending by logit
|
|
47
|
+
float16[top_k] reference logits
|
|
48
|
+
float32 full-vocab logsumexp
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`KL = Σ_{j∈topK} p_j·(log p_j − log q_j)`, `p_j = exp(ref_j − ref_lse)`,
|
|
52
|
+
`log q_j = cand_j − logsumexp(cand, full vocab)`, float32 throughout.
|
|
53
|
+
The sum is truncated to top-k, so the run also reports **captured mass**
|
|
54
|
+
`Σ_j p_j` (how much of `p` the number covers — a low-mass run is not a
|
|
55
|
+
comparable KL) and **top-1 agreement** (argmax over the full vocab).
|
|
56
|
+
The forward is the SERVING path (`makeCache` + chunked `forwardHidden` +
|
|
57
|
+
`logitsFromHidden` per chunk, `--chunk` positions at a time so a 4k
|
|
58
|
+
context's full-vocab logits never exist at once), **not** `trainForward` —
|
|
59
|
+
which is why this works on qwen3_5, where `mlx-bun perplexity` cannot go
|
|
60
|
+
(docs/design/turboquant.md, "Known engine gaps"). KV stays bf16: this is a
|
|
61
|
+
weights-only instrument.
|
|
62
|
+
|
|
63
|
+
Noise floor (measured, M1 Max, Qwen3.5-0.8B-OptiQ-4bit, 2×128 ctx,
|
|
64
|
+
top-64): scoring a dump against the model that produced it gives KL
|
|
65
|
+
**exactly 0** at the same `--chunk`, and mean 9.3e-6 / p95 8.3e-7 across
|
|
66
|
+
chunk 64 → 40. float16 storage is lossless for a bf16 teacher (bf16's
|
|
67
|
+
7 mantissa bits fit float16's 10, and logits sit far inside float16's
|
|
68
|
+
65504 range), so the residual is only the engine's own L-dependent bf16
|
|
69
|
+
rounding — the same effect that makes prefill chunk size ulp-visible
|
|
70
|
+
(`generate.ts`, prefill-tail-split). Compare candidates at one `--chunk`.
|
|
32
71
|
|
|
33
72
|
## Run (on a cleared machine — loads models, not from an agent session)
|
|
34
73
|
|
|
@@ -42,6 +81,10 @@ bun scripts/eval.ts kl --candidate e4b --self MLX_BUN_NO_FUSED_SDPA --ref-value
|
|
|
42
81
|
# optiq-style absolute drift vs a reference model:
|
|
43
82
|
bun scripts/eval.ts kl --candidate e4b --reference <bf16-or-4bit-id>
|
|
44
83
|
|
|
84
|
+
# vs a saved bf16 teacher-logits dump (--n caps sequences, --chunk positions
|
|
85
|
+
# per forward; the dump brings its own corpus, so --prompts-file/--seq don't apply):
|
|
86
|
+
bun scripts/eval.ts kl --candidate <model> --reference-logits runs/kl-teacher/<tag>
|
|
87
|
+
|
|
45
88
|
# higher-fidelity prompts (optiq's calibration mix):
|
|
46
89
|
bun scripts/eval.ts kl --candidate e4b --prompts-file \
|
|
47
90
|
/Users/joshrossi/Code/mlx-lm/.venv/.../optiq/calibration/data/optiq.jsonl
|
|
@@ -71,7 +114,7 @@ the throughput `runs` table). Each row records the active perf levers
|
|
|
71
114
|
perf levers (NO_FUSED_SDPA) actually bite.
|
|
72
115
|
- **M1 (done):** all six capability tasks ported + runtime-validated, plus
|
|
73
116
|
`capability` aggregation and the `smoketest` (KL + GSM8K-50) gate. Datasets
|
|
74
|
-
exported by `scripts/
|
|
117
|
+
exported by `scripts/oracle/export-datasets.py` → `~/.cache/mlx-bun/eval-data/`.
|
|
75
118
|
Tasks run through the real quantized-KV path (`runner.ts`). HumanEval executes
|
|
76
119
|
in a sandbox-exec + venv-python subprocess; HashHop reconstructs Magic AI's
|
|
77
120
|
generator (`MultiHopEval` isn't on PyPI). **Open quality checks** (need a real
|