mlx-bun 0.2.0 → 0.4.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 -588
- package/docs/README.md +94 -0
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/archive/investigations/openjarvis-fit.md +198 -0
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
- package/docs/design/batching.md +1841 -0
- package/docs/design/decode-speed-program.md +2346 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +655 -334
- package/docs/design/kv-cache.md +824 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1990 -0
- package/docs/design/turboquant.md +2212 -0
- package/docs/design/unified-engine-frontier-plan.md +1833 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +50 -1
- package/docs/planning/release-notes-v0.4.0.md +45 -0
- package/docs/planning/video-series.md +2 -2
- package/docs/reference/benchmarks.md +3613 -0
- package/docs/reference/cli.md +434 -160
- package/docs/reference/distribution.md +328 -182
- package/docs/reference/environment.md +398 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +566 -168
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +113 -6
- package/docs/reference/server-api.md +944 -429
- package/docs/reference/server-config.md +740 -338
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +158 -0
- package/package.json +9 -4
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/assistant-target.ts +46 -0
- package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1790 -0
- package/src/backends/mlx/cache-attachment.ts +67 -0
- package/src/backends/mlx/cache-layout.ts +31 -0
- package/src/backends/mlx/checkpoint-state.ts +53 -0
- package/src/backends/mlx/continuation-persistence.ts +106 -0
- package/src/backends/mlx/continuation-request.ts +43 -0
- package/src/backends/mlx/continuation.ts +77 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +32 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/full-kv-row-append.ts +32 -0
- package/src/backends/mlx/full-kv-row-donor.ts +54 -0
- package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
- package/src/backends/mlx/gateway-binding.ts +130 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/kv-codec.ts +9 -0
- package/src/backends/mlx/kv-maintenance.ts +133 -0
- package/src/backends/mlx/kv-tensor-rows.ts +212 -0
- package/src/backends/mlx/memory-client.ts +189 -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-cohort.ts +89 -0
- package/src/backends/mlx/prefill-rows.ts +200 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/projected-context-rows.ts +72 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/request-state-policy.ts +41 -0
- package/src/backends/mlx/rollback.ts +89 -0
- package/src/backends/mlx/row-sampling.ts +49 -0
- package/src/backends/mlx/serial-executor.ts +242 -0
- package/src/backends/mlx/speculative-group.ts +359 -0
- package/src/backends/mlx/speculative-round.ts +161 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-rows.ts +104 -0
- package/src/backends/mlx/state-views.ts +46 -0
- package/src/backends/mlx/target-layout-capability.ts +35 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
- package/src/cli.ts +66 -58
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +60 -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/prefix-cache.ts +23 -0
- package/src/contracts/resources.ts +25 -0
- package/src/contracts/sampling.ts +23 -0
- package/src/contracts/scheduling.ts +45 -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 +53 -0
- package/src/engine/resources.ts +53 -0
- package/src/engine/scheduler.ts +72 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +236 -3
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +8 -96
- 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 +30 -16
- package/src/generate.ts +709 -417
- package/src/grammar.ts +12 -7
- package/src/harness-pi.ts +14 -33
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +7 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/draft-acceptance.ts +41 -0
- package/src/inference/draft-output.ts +49 -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 +12 -12
- 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 +70 -12
- package/src/kv-store.ts +177 -63
- 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} +5 -5
- package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
- package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +1 -1
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +30 -169
- 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 +1 -3
- package/src/mlx/array.ts +11 -11
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +58 -11
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +33 -13
- 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/artifact-identity.ts +73 -0
- package/src/model/batched-kv.ts +235 -0
- package/src/model/batched-mask.ts +20 -6
- package/src/model/batched-quant.ts +9 -3
- package/src/model/batched-quantized-kv.ts +144 -0
- package/src/model/batched-rotating-quant.ts +78 -17
- package/src/model/batched-rotating-state.ts +76 -0
- package/src/model/batched-rotating.ts +65 -23
- package/src/model/batched-row-storage.ts +52 -0
- package/src/model/batched-ssm.ts +52 -0
- package/src/model/batched-turboquant-kv.ts +93 -0
- package/src/model/compiled-decode.ts +8 -2
- package/src/model/decoded-kv-donor.ts +12 -0
- package/src/model/delayed-quantized-kv.ts +72 -0
- package/src/model/delayed-rotating-quantized-kv.ts +93 -0
- package/src/model/delayed-turboquant-kv.ts +55 -0
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +76 -33
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/full-prefill-padding.ts +56 -0
- package/src/model/full-prefill-row.ts +105 -0
- package/src/model/gemma4-base.ts +179 -80
- package/src/model/gemma4.ts +40 -32
- package/src/model/generated/gemma4-12b.ts +6 -3
- package/src/model/generated/gemma4-26b.ts +6 -3
- package/src/model/generated/gemma4-e4b.ts +6 -3
- package/src/model/glm52-cache.ts +80 -4
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +1 -1
- package/src/model/glm52-mla.ts +12 -6
- package/src/model/glm52.ts +19 -40
- package/src/model/implementation.ts +69 -0
- package/src/model/kv-attention-view.ts +67 -0
- package/src/model/minicpm5.ts +17 -15
- package/src/model/profile.ts +12 -2
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta-state.ts +74 -0
- package/src/model/qwen3-delta.ts +59 -36
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +202 -78
- package/src/model/rotating-kv-donor.ts +35 -0
- package/src/model/rotating-kv-layout.ts +262 -0
- package/src/model/rotating-row-transaction.ts +35 -0
- package/src/model/speculative-rotating-kv.ts +101 -0
- package/src/model/ssm-prefill-padding.ts +39 -0
- 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/turboquant-codec.ts +83 -0
- package/src/model/universal/dense.ts +15 -14
- package/src/model/universal/modules.ts +8 -1
- package/src/native-pack.ts +6 -5
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +8 -315
- package/src/preflight.ts +31 -15
- package/src/prompt-cache.ts +110 -69
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/config-writer.ts +10 -3
- package/src/quantize/rotate.ts +4 -4
- package/src/quantize/trellis.ts +586 -0
- package/src/responses.ts +28 -1
- package/src/runtime-config.ts +18 -4
- package/src/sampler.ts +40 -29
- package/src/serve/batch-scheduler.ts +8 -1671
- 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 +15 -7
- package/src/serve/discovery-routes.ts +12 -13
- package/src/serve/generation-gateway.ts +183 -213
- 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/lab-routes.ts +3 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +7 -5
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +511 -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/request-plan.ts +23 -18
- package/src/serve/request-prep.ts +344 -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 +5 -5
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +335 -2711
- package/src/spec/assistant-rows.ts +92 -0
- package/src/spec/assistant-source.ts +31 -55
- package/src/spec/cache-identity.ts +22 -0
- package/src/spec/deepspec-rows.ts +29 -0
- package/src/spec/deepspec-source.ts +16 -14
- package/src/spec/dflash-source.ts +36 -12
- package/src/spec/drafter.ts +153 -142
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +97 -122
- 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 +129 -172
- 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-graph.ts +29 -0
- package/src/spec/glm52-mtp-rows.ts +132 -0
- package/src/spec/glm52-mtp-source.ts +54 -137
- package/src/spec/glm52-mtp-state.ts +33 -0
- package/src/spec/ngram-source.ts +93 -21
- package/src/spec/projected-draft-rows.ts +73 -0
- package/src/spec/qwen-mtp-module.ts +171 -0
- package/src/spec/qwen-mtp-rows.ts +219 -0
- package/src/spec/qwen-mtp-source.ts +147 -195
- package/src/spec/qwen-mtp-state.ts +30 -0
- package/src/spec/serve-loop.ts +201 -201
- package/src/spec/source.ts +110 -13
- package/src/spec/two-model-rows.ts +61 -0
- package/src/spec/two-model.ts +44 -102
- package/src/ssd-cache.ts +99 -19
- package/src/ssd-durability.ts +36 -20
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +2 -2
- package/src/train/forward.ts +6 -0
- package/src/train/loss.ts +1 -1
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +5 -3
- package/src/train/trainer.ts +6 -6
- package/src/vision/prompt.ts +1 -1
- package/src/vision/qwen3vl-tower.ts +52 -10
- package/src/web/app.html +1 -1
- package/src/web/app.js +62 -60
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +4 -4
- 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 +55 -9
- package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/archive/investigations/hlg-ab.html +0 -34
- package/docs/archive/investigations/hlg-explorer.html +0 -238
- package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
- package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/archive/investigations/hlg-report.html +0 -262
- package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- 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 -318
- 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-serving-execution-seam.md +0 -81
- 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 -231
- 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 -415
- 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/turboquant-weights.md +0 -467
- 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/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -101
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -11
- /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
- /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
- /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
- /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
- /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
- /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
package/src/grammar.ts
CHANGED
|
@@ -33,6 +33,7 @@ import xgrammar, {
|
|
|
33
33
|
import { readFileSync } from "node:fs";
|
|
34
34
|
import { MlxArray } from "./mlx/array";
|
|
35
35
|
import * as ops from "./mlx/ops";
|
|
36
|
+
import { applyTokenBitmask } from "./mlx/token-bitmask";
|
|
36
37
|
import { runtimeValue } from "./runtime-config";
|
|
37
38
|
import type { LoadedTokenizer } from "./tokenizer";
|
|
38
39
|
|
|
@@ -52,7 +53,7 @@ export interface GrammarRequest {
|
|
|
52
53
|
guided_grammar?: string;
|
|
53
54
|
/** vLLM/oMLX: regex. Compiled via `root ::= <regex>` EBNF embedding, so
|
|
54
55
|
* only the regex∩EBNF subset works (the F5 gap — real regex→EBNF or
|
|
55
|
-
* structural-tag RegexFormat is the tracked fix,
|
|
56
|
+
* structural-tag RegexFormat is the tracked fix, docs/reference/server-api.md). */
|
|
56
57
|
guidedRegex?: string;
|
|
57
58
|
guided_regex?: string;
|
|
58
59
|
/** vLLM/oMLX: restrict output to one of these strings (enum). */
|
|
@@ -80,7 +81,7 @@ export interface CompiledGrammarResult {
|
|
|
80
81
|
/** Module-level serializer for ALL xgrammar WASM calls. The WASM instance is
|
|
81
82
|
* single-threaded; CONCURRENT async calls corrupt emscripten's binding
|
|
82
83
|
* layer (BindingError: Expected null or instance of VectorInt, got an
|
|
83
|
-
* instance of VectorInt — reproduced in tests/grammar.test.ts B1 test, which
|
|
84
|
+
* instance of VectorInt — reproduced in tests/parity/grammar.test.ts B1 test, which
|
|
84
85
|
* fires 4 overlapping compiles + fills). Under `--batch N` the scheduler
|
|
85
86
|
* fires N accept()s (each kicks an async fill) then awaits ready() on all;
|
|
86
87
|
* and the server compiles grammar for concurrent requests. Without
|
|
@@ -119,7 +120,7 @@ let cachedTokenizerInfo: {
|
|
|
119
120
|
* - decoder is Sequence w/ ByteFallback → byte_fallback (Gemma/SP)
|
|
120
121
|
* - otherwise → raw
|
|
121
122
|
* prependSpace is true for byte_level (ByteLevel pretokenizers add a leading
|
|
122
|
-
* space). Validated in
|
|
123
|
+
* space). Validated in xgrammar-spike.ts (deleted 2026-08-23; git history) across Gemma
|
|
123
124
|
* (byte_fallback, 256k), Llama-3 / Qwen2.5 (byte_level, 128k/151k). */
|
|
124
125
|
function loadVocab(tokenizerJsonPath: string): {
|
|
125
126
|
vocab: string[];
|
|
@@ -207,6 +208,7 @@ export class GrammarController {
|
|
|
207
208
|
private pending: Promise<void> | null;
|
|
208
209
|
private terminated = false;
|
|
209
210
|
private disposed = false;
|
|
211
|
+
private readonly metalMask = runtimeValue("MLX_BUN_TOKEN_MASK") === "metal";
|
|
210
212
|
/** Tokens emitted via jumpForward() this generation — telemetry/test hook. */
|
|
211
213
|
jumpedTokens = 0;
|
|
212
214
|
|
|
@@ -238,6 +240,7 @@ export class GrammarController {
|
|
|
238
240
|
* Sync — the mask is already materialized. Returns a NEW array (caller
|
|
239
241
|
* disposes the input). Mirrors oMLX's apply_token_bitmask_mlx. */
|
|
240
242
|
applyMask(logits: MlxArray): MlxArray {
|
|
243
|
+
if (this.metalMask) return applyTokenBitmask(logits, this.readyMask);
|
|
241
244
|
// Build a -inf/0 additive float mask on device from the int32 bitmask.
|
|
242
245
|
// Each int32 bit b (little-endian within the word) gates token
|
|
243
246
|
// word*32 + b. Set = valid (xgrammar convention). Adding -inf → -inf,
|
|
@@ -255,7 +258,9 @@ export class GrammarController {
|
|
|
255
258
|
const valid = (w >>> bit) & 1;
|
|
256
259
|
maskArr[id] = valid ? 0 : -Infinity;
|
|
257
260
|
}
|
|
258
|
-
const
|
|
261
|
+
const raw = MlxArray.fromFloat32(maskArr, [1, V]);
|
|
262
|
+
const mask = raw.astype(logits.dtype);
|
|
263
|
+
raw.dispose();
|
|
259
264
|
const out = ops.add(logits, mask);
|
|
260
265
|
mask.dispose();
|
|
261
266
|
return out;
|
|
@@ -285,7 +290,7 @@ export class GrammarController {
|
|
|
285
290
|
* time: a controller disposed while its fill is still queued (an exception
|
|
286
291
|
* between accept/jumpForward and ready()) must not call into the deleted
|
|
287
292
|
* WASM matcher — that BindingError poisons the module-wide wasmChain for
|
|
288
|
-
* every later grammar request (found by tests/grammar-jump.test.ts). */
|
|
293
|
+
* every later grammar request (found by tests/parity/grammar-jump.test.ts). */
|
|
289
294
|
private fireFill(): Promise<void> {
|
|
290
295
|
return wasmQueue(() =>
|
|
291
296
|
this.disposed
|
|
@@ -458,7 +463,7 @@ export async function compileGrammarRequest(
|
|
|
458
463
|
if (!degradeHint) degradeHint = resolved.degradeDescription ?? "grammar compile failed";
|
|
459
464
|
// The compiler is the cached per-TokenizerInfo instance (F4) — a failed
|
|
460
465
|
// compile must NOT dispose it; the WASM abort is catchable and the
|
|
461
|
-
// compiler state survives (verified in tests/grammar.test.ts).
|
|
466
|
+
// compiler state survives (verified in tests/parity/grammar.test.ts).
|
|
462
467
|
// Return the hint (NOT bare null): it drives the degrade path's
|
|
463
468
|
// system-prompt injection + Warning header. Dropping it here served
|
|
464
469
|
// unconstrained output with no Warning at all (found 2026-07-07 sweep).
|
|
@@ -539,7 +544,7 @@ function resolveGrammarRequest(req: GrammarRequest):
|
|
|
539
544
|
kind: "json_schema",
|
|
540
545
|
schema,
|
|
541
546
|
strict: js?.strict,
|
|
542
|
-
// Whitespace-stall escape hatch (
|
|
547
|
+
// Whitespace-stall escape hatch (docs/reference/server-api.md known gaps):
|
|
543
548
|
// any_whitespace=false compiles the schema with xgrammar's compact
|
|
544
549
|
// separators — no whitespace choice points, so a whitespace-
|
|
545
550
|
// degenerate base model can't greedily tab-loop to max_tokens.
|
package/src/harness-pi.ts
CHANGED
|
@@ -13,7 +13,9 @@ import { homedir } from "node:os";
|
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
14
14
|
|
|
15
15
|
export const PI_EXTENSION_FILENAME = "mlx-bun-provider.ts";
|
|
16
|
-
|
|
16
|
+
import { PI_PROVIDER_ID, PI_LOCAL_MODEL_ID, PI_API_KEY, PI_API, piModelDefinition,
|
|
17
|
+
DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS } from "./contracts/pi-provider";
|
|
18
|
+
export { PI_PROVIDER_ID, PI_LOCAL_MODEL_ID } from "./contracts/pi-provider";
|
|
17
19
|
/** Stable pi-facing model id. The server runs exactly one model at a time
|
|
18
20
|
* (memory: the 26B alone is 18 GB) and which one varies run-to-run, so
|
|
19
21
|
* advertising the real, changing repo id makes pi's persisted default go
|
|
@@ -21,7 +23,7 @@ export const PI_PROVIDER_ID = "mlx-bun";
|
|
|
21
23
|
* model is loaded; the real model is carried in the `name` field, and the
|
|
22
24
|
* server still reports the true id in /v1/models and responses. Gives a
|
|
23
25
|
* clean `mlx-bun/local` handle instead of `mlx-bun/mlx-community/…`. */
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
// 127.0.0.1 (the server's actual default bind), not "localhost": the generated
|
|
26
28
|
// extension runs under the USER'S pi (node/jiti, not Bun), so don't depend on
|
|
27
29
|
// how that runtime's resolver maps localhost.
|
|
@@ -89,8 +91,8 @@ export async function fetchServerModels(baseUrl: string, timeoutMs = 3000): Prom
|
|
|
89
91
|
if (!served) return [];
|
|
90
92
|
return [{
|
|
91
93
|
id: served.id,
|
|
92
|
-
contextWindow: served.context_window ??
|
|
93
|
-
maxTokens:
|
|
94
|
+
contextWindow: served.context_window ?? DEFAULT_CONTEXT_WINDOW,
|
|
95
|
+
maxTokens: DEFAULT_MAX_TOKENS,
|
|
94
96
|
reasoning: !!served.reasoning,
|
|
95
97
|
vision: !!served.vision,
|
|
96
98
|
}];
|
|
@@ -120,6 +122,7 @@ export function renderPiExtension(baseUrl: string, fallbackModels: ServerModel[]
|
|
|
120
122
|
// is the fallback when the server isn't running.
|
|
121
123
|
const BASE_URL = ${JSON.stringify(baseUrl)};
|
|
122
124
|
const FALLBACK_MODELS = ${fallback};
|
|
125
|
+
const modelEntry = ${piModelDefinition.toString()};
|
|
123
126
|
|
|
124
127
|
export default async function (pi: any) {
|
|
125
128
|
let models = FALLBACK_MODELS;
|
|
@@ -131,27 +134,19 @@ export default async function (pi: any) {
|
|
|
131
134
|
// The SERVED model is the row with the capability extras (first);
|
|
132
135
|
// the rest are servable-but-not-served registry entries.
|
|
133
136
|
const served = data.find((m: any) => m.context_window !== undefined) ?? data[0];
|
|
134
|
-
models = [{
|
|
135
|
-
id: ${JSON.stringify(PI_LOCAL_MODEL_ID)},
|
|
137
|
+
models = [modelEntry({
|
|
136
138
|
name: \`\${served.id} (mlx-bun local)\`,
|
|
137
|
-
reasoning: !!served.reasoning,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
...(served.reasoning ? { thinkingFormat: "qwen-chat-template" } : {}),
|
|
141
|
-
},
|
|
142
|
-
input: served.vision ? ["text", "image"] : ["text"],
|
|
143
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
144
|
-
contextWindow: served.context_window ?? 32768,
|
|
145
|
-
maxTokens: 8192,
|
|
146
|
-
}];
|
|
139
|
+
reasoning: !!served.reasoning, vision: !!served.vision,
|
|
140
|
+
contextWindow: served.context_window,
|
|
141
|
+
})];
|
|
147
142
|
}
|
|
148
143
|
}
|
|
149
144
|
} catch {}
|
|
150
145
|
if (models.length === 0) return; // nothing to register
|
|
151
146
|
pi.registerProvider(${JSON.stringify(PI_PROVIDER_ID)}, {
|
|
152
147
|
baseUrl: BASE_URL,
|
|
153
|
-
apiKey:
|
|
154
|
-
api:
|
|
148
|
+
apiKey: ${JSON.stringify(PI_API_KEY)},
|
|
149
|
+
api: ${JSON.stringify(PI_API)},
|
|
155
150
|
models,
|
|
156
151
|
});
|
|
157
152
|
}
|
|
@@ -159,21 +154,7 @@ export default async function (pi: any) {
|
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
function modelEntry(m: ServerModel) {
|
|
162
|
-
return {
|
|
163
|
-
id: PI_LOCAL_MODEL_ID,
|
|
164
|
-
name: `${m.id} (mlx-bun local)`,
|
|
165
|
-
reasoning: !!m.reasoning,
|
|
166
|
-
// Kept aligned with buildPiProvider (src/pi-provider.ts): the system
|
|
167
|
-
// prompt must arrive as `system`, not `developer`.
|
|
168
|
-
compat: {
|
|
169
|
-
supportsDeveloperRole: false,
|
|
170
|
-
...(m.reasoning ? { thinkingFormat: "qwen-chat-template" } : {}),
|
|
171
|
-
},
|
|
172
|
-
input: m.vision ? ["text", "image"] : ["text"],
|
|
173
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
174
|
-
contextWindow: m.contextWindow,
|
|
175
|
-
maxTokens: m.maxTokens,
|
|
176
|
-
};
|
|
157
|
+
return piModelDefinition({ ...m, name: `${m.id} (mlx-bun local)` });
|
|
177
158
|
}
|
|
178
159
|
|
|
179
160
|
export interface InstallResult {
|
package/src/hub-rest.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Axis 3 "Hub" row). Same posture as src/memory/rest.ts: pure (request|url)
|
|
4
4
|
// => Response handlers with no `ctx` dependency, dispatched from
|
|
5
5
|
// src/server.ts by path+method, so they're unit-testable without booting a
|
|
6
|
-
// model context (see tests/hub-rest.test.ts).
|
|
6
|
+
// model context (see tests/serve/hub-rest.test.ts).
|
|
7
7
|
//
|
|
8
8
|
// Three sources, same as optiq Lab's Hub, plus the hardware-fit column optiq
|
|
9
9
|
// lacks:
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// - POST /api/hub/serve — model-swap investigation (see the doc header
|
|
20
20
|
// above the handler): today this ALWAYS returns
|
|
21
21
|
// { ok:false, restart_required:true, command } — see
|
|
22
|
-
// docs/
|
|
22
|
+
// docs/reference/server-config.md for why no in-process swap seam is
|
|
23
23
|
// reachable from the web chat's serving path today.
|
|
24
24
|
|
|
25
25
|
import { loadModelConfig } from "./config";
|
|
@@ -43,7 +43,7 @@ function jsonErr(error: string, status = 400): Response {
|
|
|
43
43
|
* fixed 8k context (the same "typical" context /fit and /library use, so
|
|
44
44
|
* the three surfaces never disagree). `reg`/`hubDir` are injectable so
|
|
45
45
|
* tests can point at a synthetic hub dir instead of the real
|
|
46
|
-
* ~/.cache/huggingface/hub (matching tests/registry-fit.test.ts's pattern);
|
|
46
|
+
* ~/.cache/huggingface/hub (matching tests/unit/registry-fit.test.ts's pattern);
|
|
47
47
|
* the live server route omits both and gets the real registry. */
|
|
48
48
|
export async function handleHubLocal(
|
|
49
49
|
opts: { reg?: Registry; hubDir?: string } = {},
|
|
@@ -210,7 +210,7 @@ export async function handleHubDownload(request: Request): Promise<Response> {
|
|
|
210
210
|
|
|
211
211
|
// ---- POST /api/hub/serve --------------------------------------------------
|
|
212
212
|
|
|
213
|
-
/** Model-swap investigation (docs/
|
|
213
|
+
/** Model-swap investigation (docs/reference/server-config.md): the web
|
|
214
214
|
* chat's `/ws/chat` is explicitly NOT proxied even under `--isolate`
|
|
215
215
|
* (src/serve/isolate.ts serves it a 501 with a pointer back to the direct,
|
|
216
216
|
* non-isolated server) and `--isolate` itself is opt-in, not the default —
|
package/src/index.ts
CHANGED
|
@@ -16,9 +16,15 @@ export {
|
|
|
16
16
|
createModel,
|
|
17
17
|
openGlm52RuntimeModel,
|
|
18
18
|
openModel,
|
|
19
|
+
type ModelOpenOptions,
|
|
19
20
|
type Glm52RuntimeOpenOptions,
|
|
20
21
|
type RuntimeModel,
|
|
21
22
|
} from "./model/factory";
|
|
23
|
+
export { ModelImplementationRegistry, type ModelImplementation, type ModelImplementationProvider } from "./model/implementation";
|
|
24
|
+
export type { ModelServingBinding, ModelPromptBuilder, BuiltPrompt, ServedModelInfo } from "./serve/model-binding";
|
|
25
|
+
export type { ServingContext, ModelHostSource, AdapterService } from "./serve/model-host";
|
|
26
|
+
export type { MlxGatewayBinding, MlxBatchGroup } from "./backends/mlx/gateway-binding";
|
|
27
|
+
export type { MlxSerialServices, MlxSerialBinding } from "./backends/mlx/serial-executor";
|
|
22
28
|
export { Qwen3Model } from "./model/qwen3";
|
|
23
29
|
export { configFingerprint } from "./model/fingerprint";
|
|
24
30
|
export {
|
|
@@ -49,6 +55,7 @@ export { downloadModel } from "./download";
|
|
|
49
55
|
export { Registry } from "./registry";
|
|
50
56
|
export {
|
|
51
57
|
createServer,
|
|
58
|
+
shutdownServer,
|
|
52
59
|
loadContext,
|
|
53
60
|
type LoadContextOptions,
|
|
54
61
|
type ServerContext,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GraphDescriptor } from "./graph";
|
|
2
|
+
|
|
3
|
+
/** Denoising has canvas state and feedback, independent of AR token caches.
|
|
4
|
+
* Returned tensors/state are owned by the run. Inputs remain borrowed. A
|
|
5
|
+
* fused method may bypass this graph and implement InferenceMethod directly. */
|
|
6
|
+
export interface DenoisingGraph<Tensor, State> {
|
|
7
|
+
readonly descriptor: GraphDescriptor;
|
|
8
|
+
readonly vocabSize: number;
|
|
9
|
+
readonly canvasLength: number;
|
|
10
|
+
readonly embedScale: number;
|
|
11
|
+
prefill(promptIds: number[], vision?: Tensor): State;
|
|
12
|
+
extendPrefill(tokens: Tensor, state: State): void;
|
|
13
|
+
decoderLogits(canvas: Tensor, state: State, feedback: Tensor | null): Tensor;
|
|
14
|
+
dequantEmbedWeight(): Tensor;
|
|
15
|
+
softEmbeddings(logits: Tensor, weight: Tensor): Tensor;
|
|
16
|
+
closeState(state: State): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** One request's exact-token speculative acceptance walk. The backend owns
|
|
2
|
+
* logits and sampling; this state owns only the accepted prefix and stop facts.
|
|
3
|
+
* A group advances each live walk independently, regardless of batch size. */
|
|
4
|
+
export class DraftAcceptance {
|
|
5
|
+
position = 0;
|
|
6
|
+
accepted = 0;
|
|
7
|
+
correction: number | null = null;
|
|
8
|
+
readonly emitted: number[] = [];
|
|
9
|
+
sawEos = false;
|
|
10
|
+
grammarDone = false;
|
|
11
|
+
done = false;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
readonly drafts: readonly number[],
|
|
15
|
+
readonly remaining: number,
|
|
16
|
+
readonly eosTokenIds: readonly number[],
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
/** Supply one target sample after its sampler has updated request history
|
|
20
|
+
* and grammar. Once done, this request needs no further target samples. */
|
|
21
|
+
accept(token: number, grammarDone = false): void {
|
|
22
|
+
const matches = this.position < this.drafts.length && token === this.drafts[this.position];
|
|
23
|
+
this.position++;
|
|
24
|
+
if (matches) {
|
|
25
|
+
this.accepted++;
|
|
26
|
+
if (this.eosTokenIds.includes(token)) {
|
|
27
|
+
this.sawEos = this.done = true;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.emitted.push(token);
|
|
31
|
+
this.grammarDone = grammarDone;
|
|
32
|
+
this.done = grammarDone || this.emitted.length >= this.remaining;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.correction = token;
|
|
36
|
+
this.sawEos = this.eosTokenIds.includes(token);
|
|
37
|
+
if (!this.sawEos) this.emitted.push(token);
|
|
38
|
+
this.grammarDone = grammarDone;
|
|
39
|
+
this.done = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Cancellation, CancelReason, GenerationOutput, TokenLogprobs } from "../contracts/generation";
|
|
2
|
+
import type { DraftAcceptance } from "./draft-acceptance";
|
|
3
|
+
|
|
4
|
+
export interface DraftOutputRow {
|
|
5
|
+
readonly acceptance: DraftAcceptance;
|
|
6
|
+
readonly logprobs?: readonly (TokenLogprobs | undefined)[];
|
|
7
|
+
readonly output: Pick<GenerationOutput, "commit">;
|
|
8
|
+
readonly cancellation?: Cancellation;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Counts apply to this round. Accepted counts describe processed proposed
|
|
12
|
+
* inputs, excluding an unprocessed correction/bonus and any unpublished EOS.
|
|
13
|
+
* Failed/cancelled requests must be discarded, never checkpointed. */
|
|
14
|
+
export type DraftOutputResult = { readonly generated: number; readonly accepted: number } & (
|
|
15
|
+
| { readonly kind: "continue"; readonly pending: number }
|
|
16
|
+
| { readonly kind: "stop" | "length" }
|
|
17
|
+
| { readonly kind: "cancelled"; readonly reason: CancelReason }
|
|
18
|
+
| { readonly kind: "failed"; readonly error: unknown }
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/** Deliver verified content through the output interface before resolving
|
|
22
|
+
* retained state. A stopped or failed consumer affects only its own request.
|
|
23
|
+
* Token-sized publications preserve callbacks that stop inside a draft burst. */
|
|
24
|
+
export async function deliverDraftOutputs(rows: readonly DraftOutputRow[]): Promise<DraftOutputResult[]> {
|
|
25
|
+
const results: DraftOutputResult[] = [];
|
|
26
|
+
for (const row of rows) results.push(await deliver(row));
|
|
27
|
+
return results;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function deliver(row: DraftOutputRow): Promise<DraftOutputResult> {
|
|
31
|
+
const { acceptance } = row;
|
|
32
|
+
let generated = 0;
|
|
33
|
+
const retained = () => ({ generated, accepted: Math.min(generated, acceptance.accepted) });
|
|
34
|
+
try {
|
|
35
|
+
for (const token of acceptance.emitted) {
|
|
36
|
+
const reason = row.cancellation?.reason;
|
|
37
|
+
if (reason) return { kind: "cancelled", reason, generated, accepted: 0 };
|
|
38
|
+
const metadata = row.logprobs?.[generated];
|
|
39
|
+
const more = await row.output.commit([token], metadata ? [metadata] : undefined);
|
|
40
|
+
generated++;
|
|
41
|
+
if (more === false) return { kind: "stop", ...retained() };
|
|
42
|
+
}
|
|
43
|
+
const reason = row.cancellation?.reason;
|
|
44
|
+
if (reason) return { kind: "cancelled", reason, generated, accepted: 0 };
|
|
45
|
+
if (acceptance.sawEos || acceptance.grammarDone) return { kind: "stop", ...retained() };
|
|
46
|
+
if (generated >= acceptance.remaining) return { kind: "length", ...retained() };
|
|
47
|
+
return { kind: "continue", pending: acceptance.correction!, ...retained() };
|
|
48
|
+
} catch (error) { return { kind: "failed", error, generated, accepted: 0 }; }
|
|
49
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Describes an implementation's ABI, not a claim of oracle parity or speed. */
|
|
2
|
+
export interface GraphDescriptor {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly backend: string;
|
|
5
|
+
readonly graphAbi: string;
|
|
6
|
+
readonly stateAbi: string;
|
|
7
|
+
readonly artifact: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type LogitSelection =
|
|
11
|
+
| { readonly type: "all" }
|
|
12
|
+
| { readonly type: "last" }
|
|
13
|
+
| { readonly type: "range"; readonly start: number; readonly end: number };
|
|
14
|
+
|
|
15
|
+
/** Backend-bound graph. Tensor/State/Inputs stay concrete within the binding.
|
|
16
|
+
* Inputs and hidden are borrowed until the returned lazy work completes;
|
|
17
|
+
* returned hidden/logits are owned by the caller. The graph appends to state.
|
|
18
|
+
* Hidden is [batch, positions, hidden-width]; logits are [batch, selected
|
|
19
|
+
* positions, vocabulary]. Selection precedes the vocabulary projection.
|
|
20
|
+
* Dtypes and evaluation/fence semantics belong to the declared backend ABI.
|
|
21
|
+
* Per-run masks, positions, media, taps, and adapters belong in Inputs or in
|
|
22
|
+
* a bound graph context; they are not mutable session fields. */
|
|
23
|
+
export interface AutoregressiveGraph<Tensor, State, Inputs> {
|
|
24
|
+
readonly descriptor: GraphDescriptor;
|
|
25
|
+
forwardHidden(inputs: Inputs, state: State): Tensor | Promise<Tensor>;
|
|
26
|
+
projectLogits(hidden: Tensor, selection: LogitSelection): Tensor;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A fused InferenceMethod can bypass this graph interface entirely. It need
|
|
30
|
+
* only satisfy the method's output, cancellation, and ownership contracts. */
|
|
31
|
+
export interface GraphFactory<Artifact, Binding, Graph> {
|
|
32
|
+
open(artifact: Artifact, binding: Binding): Promise<{ graph: Graph; close(): Promise<void> }>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface PrefillPosition {
|
|
2
|
+
readonly length: number;
|
|
3
|
+
readonly position: number;
|
|
4
|
+
readonly chunkSize: number;
|
|
5
|
+
readonly tailSplit: boolean;
|
|
6
|
+
readonly snapshotAt?: number | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PrefillStep {
|
|
10
|
+
readonly start: number;
|
|
11
|
+
readonly end: number;
|
|
12
|
+
readonly kind: "drain" | "final";
|
|
13
|
+
readonly snapshot: boolean;
|
|
14
|
+
/** Batch admission may finish a short last drain and token zero in one tick.
|
|
15
|
+
* Serial execution still yields between every drain and the next forward. */
|
|
16
|
+
readonly batchYield: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Shared serial/solo-batch prefill program. No tensors, runtime policy reads,
|
|
20
|
+
* or sampling. Advance position only after executing the returned step. */
|
|
21
|
+
export function nextPrefillStep(input: PrefillPosition): PrefillStep {
|
|
22
|
+
const { length, position, chunkSize, tailSplit, snapshotAt } = input;
|
|
23
|
+
if (!Number.isSafeInteger(length) || !Number.isSafeInteger(position) ||
|
|
24
|
+
!Number.isSafeInteger(chunkSize) || chunkSize < 1 || position < 0 || position >= length)
|
|
25
|
+
throw new Error("invalid prefill position or chunk size");
|
|
26
|
+
if (snapshotAt != null && (!Number.isSafeInteger(snapshotAt) || snapshotAt < 0 || snapshotAt > length))
|
|
27
|
+
throw new Error("invalid prefill snapshot boundary");
|
|
28
|
+
if (snapshotAt != null && snapshotAt > position && snapshotAt < length) {
|
|
29
|
+
const end = Math.min(position + chunkSize, snapshotAt);
|
|
30
|
+
return { start: position, end, kind: "drain", snapshot: end === snapshotAt, batchYield: true };
|
|
31
|
+
}
|
|
32
|
+
const remaining = length - position;
|
|
33
|
+
if (remaining > (tailSplit ? 1 : chunkSize)) {
|
|
34
|
+
const end = position + (tailSplit ? Math.min(chunkSize, remaining - 1) : chunkSize);
|
|
35
|
+
return { start: position, end, kind: "drain", snapshot: false,
|
|
36
|
+
batchYield: !tailSplit || remaining - 1 > chunkSize };
|
|
37
|
+
}
|
|
38
|
+
return { start: position, end: length, kind: "final", snapshot: false, batchYield: false };
|
|
39
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A complete transaction over every participating target state layer.
|
|
2
|
+
* A failed begin/resolve invalidates the run; its state must be discarded. */
|
|
3
|
+
export interface SpeculativeTransaction<Acceptance = number> {
|
|
4
|
+
canBegin(drafts: number): boolean;
|
|
5
|
+
begin(drafts: number): void;
|
|
6
|
+
resolve(accepted: Acceptance): void;
|
|
7
|
+
}
|
package/src/jobs/db.ts
CHANGED
|
@@ -55,6 +55,10 @@ export class JobStore {
|
|
|
55
55
|
this.dbPath = dbPath;
|
|
56
56
|
this.logsDir = logsDir;
|
|
57
57
|
this.db = new Database(dbPath);
|
|
58
|
+
// Parent submissions and child progress updates share this WAL database.
|
|
59
|
+
// Wait for a short writer transaction instead of failing a valid job with
|
|
60
|
+
// SQLITE_BUSY while the other process commits its terminal event.
|
|
61
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
58
62
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
59
63
|
this.db.exec(SCHEMA);
|
|
60
64
|
this.migrate();
|
package/src/jobs/index.ts
CHANGED
package/src/jobs/job-entry.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// the runner, runs it with a log-appending emit, sets terminal status, and
|
|
8
8
|
// exits 0 (done) / 1 (failed).
|
|
9
9
|
|
|
10
|
+
import { createJobTaskClient } from "./task-client";
|
|
10
11
|
import { JobStore } from "./db";
|
|
11
12
|
import { getRunner, makeEmit } from "./runner";
|
|
12
13
|
import type { JobRunner } from "./types";
|
|
@@ -16,9 +17,9 @@ import { runtimeValue } from "../runtime-config";
|
|
|
16
17
|
* kinds are built by parallel efforts; importing the module is expected to
|
|
17
18
|
* call `registerRunner(kind, ...)` at top level. Missing module ⇒ the job
|
|
18
19
|
* fails cleanly (see resolveRunner). */
|
|
19
|
-
const KIND_MODULES: Record<string,
|
|
20
|
-
quantize: "../quantize/job
|
|
21
|
-
finetune: "../train/job
|
|
20
|
+
const KIND_MODULES: Record<string, () => Promise<unknown>> = {
|
|
21
|
+
quantize: () => import("../quantize/job"),
|
|
22
|
+
finetune: () => import("../train/job"),
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
/** Resolve a runner for `kind`. Test kinds (noop/crash) are pre-registered in
|
|
@@ -28,19 +29,19 @@ async function resolveRunner(kind: string): Promise<JobRunner> {
|
|
|
28
29
|
const existing = getRunner(kind);
|
|
29
30
|
if (existing) return existing;
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
32
|
+
const load = KIND_MODULES[kind];
|
|
33
|
+
if (load) {
|
|
33
34
|
try {
|
|
34
|
-
await
|
|
35
|
+
await load();
|
|
35
36
|
} catch (e) {
|
|
36
37
|
throw new Error(
|
|
37
|
-
`kind "${kind}": failed to load runner module ${
|
|
38
|
+
`kind "${kind}": failed to load runner module ${kind} ` +
|
|
38
39
|
`(${e instanceof Error ? e.message : String(e)})`,
|
|
39
40
|
);
|
|
40
41
|
}
|
|
41
42
|
const loaded = getRunner(kind);
|
|
42
43
|
if (loaded) return loaded;
|
|
43
|
-
throw new Error(`kind "${kind}": module ${
|
|
44
|
+
throw new Error(`kind "${kind}": module ${kind} did not register a runner`);
|
|
44
45
|
}
|
|
45
46
|
throw new Error(`no runner registered for kind "${kind}"`);
|
|
46
47
|
}
|
|
@@ -49,8 +50,7 @@ function nowIso(): string {
|
|
|
49
50
|
return new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
async function
|
|
53
|
-
const jobId = process.argv[2];
|
|
53
|
+
export async function runJobEntry(jobId = process.argv[2]): Promise<void> {
|
|
54
54
|
if (!jobId) {
|
|
55
55
|
console.error("usage: bun job-entry.ts <jobId>");
|
|
56
56
|
process.exit(2);
|
|
@@ -87,7 +87,7 @@ async function main(): Promise<void> {
|
|
|
87
87
|
|
|
88
88
|
try {
|
|
89
89
|
const runner = await resolveRunner(row.kind);
|
|
90
|
-
const result = await runner(
|
|
90
|
+
const result = await createJobTaskClient(runner).run(config, emit);
|
|
91
91
|
const out = result?.outputPath;
|
|
92
92
|
if (out) store.setOutputPath(jobId, out);
|
|
93
93
|
store.setProgress(jobId, 1);
|
|
@@ -104,4 +104,4 @@ async function main(): Promise<void> {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
main();
|
|
107
|
+
if (import.meta.main) void runJobEntry();
|