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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { MlxArray } from "../mlx/array";
|
|
2
|
+
import * as ops from "../mlx/ops";
|
|
3
|
+
import { materializeCopy } from "../mlx/materialize";
|
|
4
|
+
import { disposeResources, applyStateChanges } from "../engine/resources";
|
|
5
|
+
import type { PreparedStateChange } from "../contracts/resources";
|
|
6
|
+
import type { AssistantRowsTarget, DraftPrefillGroup, DraftRowGroup, DraftRowCheckpoint, GroupedDraftProvider } from "./source";
|
|
7
|
+
import type { GemmaAssistantDrafter } from "./drafter";
|
|
8
|
+
|
|
9
|
+
/** The assistant owns only its last true target hidden and coverage. Donor
|
|
10
|
+
* attention stays with target storage; checkpoints contain no duplicate KV. */
|
|
11
|
+
class AssistantRows implements DraftPrefillGroup, DraftRowGroup {
|
|
12
|
+
readonly prefillMode = "tail-split" as const;
|
|
13
|
+
readonly tapLayers: readonly number[] = [];
|
|
14
|
+
#hidden: MlxArray | null = null;
|
|
15
|
+
#processed: number[] = [];
|
|
16
|
+
constructor(readonly target: AssistantRowsTarget, readonly drafter: GemmaAssistantDrafter,
|
|
17
|
+
readonly namespace: string, checkpoints: readonly (DraftRowCheckpoint | null)[]) { this.append(checkpoints); }
|
|
18
|
+
get rowCount(): number { return this.#processed.length; }
|
|
19
|
+
append(checkpoints: readonly (DraftRowCheckpoint | null)[]): void {
|
|
20
|
+
if (checkpoints.length) applyStateChanges([() => this.prepareAppend(checkpoints)]);
|
|
21
|
+
}
|
|
22
|
+
prepareAppend(checkpoints: readonly (DraftRowCheckpoint | null)[]): PreparedStateChange {
|
|
23
|
+
const processed = [...this.#processed, ...checkpoints.map(checkpoint => checkpoint?.processedTokens ?? 0)];
|
|
24
|
+
const example = this.#hidden ?? checkpoints.find(checkpoint => checkpoint !== null)?.attachment.tensors[0];
|
|
25
|
+
const held: MlxArray[] = []; let hidden: MlxArray | null = null;
|
|
26
|
+
try {
|
|
27
|
+
for (const checkpoint of checkpoints) if (checkpoint && (checkpoint.attachment.schema !== "gemma-assistant-v1" ||
|
|
28
|
+
checkpoint.attachment.metadata.processedTokens !== checkpoint.processedTokens))
|
|
29
|
+
throw new Error("invalid assistant checkpoint alignment");
|
|
30
|
+
if (example) {
|
|
31
|
+
const zero = (rows: number) => { const value = ops.zeros([rows,1,this.target.hiddenSize],example.dtype); held.push(value); return value; };
|
|
32
|
+
hidden = ops.concatAxis([...(this.rowCount ? [this.#hidden ?? zero(this.rowCount)] : []),
|
|
33
|
+
...checkpoints.map(checkpoint => checkpoint?.attachment.tensors[0] ?? zero(1))],0);
|
|
34
|
+
}
|
|
35
|
+
} finally { disposeResources(held); }
|
|
36
|
+
return { commit: () => { const old = this.#hidden; this.#hidden=hidden; hidden=old; this.#processed=processed; },
|
|
37
|
+
dispose: () => { hidden?.dispose(); hidden=null; } };
|
|
38
|
+
}
|
|
39
|
+
filterRows(keep: readonly number[]): void {
|
|
40
|
+
if (!keep.length) { this.dispose(); return; }
|
|
41
|
+
using indices = ops.fromInt32([...keep],[keep.length]);
|
|
42
|
+
const next = this.#hidden && keep.length ? ops.takeAxis(this.#hidden,indices,0) : null;
|
|
43
|
+
this.#hidden?.dispose(); this.#hidden=next; this.#processed=keep.map(row=>this.#processed[row]!);
|
|
44
|
+
}
|
|
45
|
+
prefill(tokens: MlxArray, context?: MlxArray): void {
|
|
46
|
+
const [B,N] = tokens.shape as [number,number];
|
|
47
|
+
using tail = context!.slice([0,N-1,0],[B,N,context!.shape[2]!]);
|
|
48
|
+
const hidden = materializeCopy(tail);
|
|
49
|
+
this.#hidden?.dispose(); this.#hidden=hidden; this.#processed=this.#processed.map(count=>count+N);
|
|
50
|
+
}
|
|
51
|
+
materialize(): void { this.#hidden?.eval(); }
|
|
52
|
+
capture(row: number): DraftRowCheckpoint {
|
|
53
|
+
const processedTokens=this.#processed[row]!;
|
|
54
|
+
const hidden=this.#hidden!.slice([row,0,0],[row+1,1,this.target.hiddenSize]);
|
|
55
|
+
return { processedTokens, attachment: { schema:"gemma-assistant-v1",metadata:{processedTokens},tensors:[hidden] } };
|
|
56
|
+
}
|
|
57
|
+
draft(pending: readonly number[], depth: number, _steps: readonly number[]): number[][] {
|
|
58
|
+
if (!depth) return pending.map(()=>[]);
|
|
59
|
+
const B=pending.length, owned: MlxArray[]=[];
|
|
60
|
+
const donors=this.target.readDonors();
|
|
61
|
+
let ids=ops.fromInt32([...pending],[B,1]), hidden=this.#hidden!;
|
|
62
|
+
const tokens: MlxArray[]=[];
|
|
63
|
+
try {
|
|
64
|
+
for(let step=0;step<depth;step++) {
|
|
65
|
+
using emb=this.target.embed(ids);
|
|
66
|
+
const positions=donors.positions.map(position=>position+step);
|
|
67
|
+
const common=positions.every(position=>position===positions[0]);
|
|
68
|
+
using offsets=common ? null : ops.fromInt32(positions,[B]);
|
|
69
|
+
const next=this.drafter.forwardRows(emb,hidden,donors,offsets ?? positions[0]!);
|
|
70
|
+
owned.push(next.nextHidden); tokens.push(next.tokens); hidden=next.nextHidden;
|
|
71
|
+
ids.dispose(); ids=ops.reshape(next.tokens,[B,1]);
|
|
72
|
+
}
|
|
73
|
+
using packed=ops.concatAxis(tokens,0);
|
|
74
|
+
const values=packed.toIntTokens();
|
|
75
|
+
return pending.map((_,row)=>Array.from({length:depth},(_,step)=>values[step*B+row]!));
|
|
76
|
+
} finally { ids.dispose(); donors.dispose(); disposeResources([...owned,...tokens]); }
|
|
77
|
+
}
|
|
78
|
+
commit(accepted: readonly number[], context: MlxArray): void {
|
|
79
|
+
using indices=ops.fromInt32([...accepted],[accepted.length,1,1]);
|
|
80
|
+
const hidden=ops.takeAlongAxis(context,indices,1);
|
|
81
|
+
this.#hidden?.dispose(); this.#hidden=hidden;
|
|
82
|
+
this.#processed=this.#processed.map((count,row)=>count+accepted[row]!+1);
|
|
83
|
+
}
|
|
84
|
+
dispose(): void { this.#hidden?.dispose(); this.#hidden=null; this.#processed=[]; }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function assistantGroups(drafter: GemmaAssistantDrafter, namespace: string): GroupedDraftProvider {
|
|
88
|
+
return {
|
|
89
|
+
openPrefill: ({target,checkpoints}) => new AssistantRows(target.assistantRows!,drafter,namespace,checkpoints),
|
|
90
|
+
open: ({target,checkpoints}) => new AssistantRows(target.assistantRows!,drafter,namespace,checkpoints),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import * as ops from "../mlx/ops";
|
|
2
|
+
import { artifactIdentity } from "../model/artifact-identity";
|
|
3
|
+
import { assistantGroups } from "./assistant-rows";
|
|
1
4
|
// AssistantSource — the optiq KV-borrowing Gemma "-assistant" drafter
|
|
2
5
|
// (src/spec/drafter.ts) behind the serve-time DraftSource seam. L2 oracle:
|
|
3
6
|
// optiq spec_generate. This is the SAME drafter the standalone specGenerate
|
|
@@ -21,10 +24,8 @@
|
|
|
21
24
|
import { readdirSync, statSync } from "node:fs";
|
|
22
25
|
import { join } from "node:path";
|
|
23
26
|
import type { MlxArray } from "../mlx/array";
|
|
24
|
-
import * as ops from "../mlx/ops";
|
|
25
|
-
import { Gemma4Model, type Cache } from "../model/gemma4";
|
|
26
27
|
import { GemmaAssistantDrafter } from "./drafter";
|
|
27
|
-
import type { DraftProvider, DraftSource, TargetView } from "./source";
|
|
28
|
+
import type { DraftProvider, DraftSource, TargetView, AssistantRowsTarget } from "./source";
|
|
28
29
|
|
|
29
30
|
/** Sum of the drafter's on-disk safetensors — admission accounting only. */
|
|
30
31
|
function safetensorsBytes(dir: string): number {
|
|
@@ -34,36 +35,30 @@ function safetensorsBytes(dir: string): number {
|
|
|
34
35
|
return total;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
/** The target's LAST sliding and LAST full cache owners (port of optiq
|
|
38
|
-
* kv_view.find_donor_layers; mirrors donorIndices in generate.ts). */
|
|
39
|
-
function donorIndices(model: Gemma4Model): { sliding: number; full: number } {
|
|
40
|
-
let sliding = -1;
|
|
41
|
-
let full = -1;
|
|
42
|
-
for (let i = 0; i < model.numDonors; i++) {
|
|
43
|
-
if (model.layers[i]!.layerType === "sliding_attention") sliding = i;
|
|
44
|
-
else full = i;
|
|
45
|
-
}
|
|
46
|
-
if (sliding < 0 || full < 0) throw new Error("assistant drafter: missing donor layer type");
|
|
47
|
-
return { sliding, full };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
38
|
export class AssistantProvider implements DraftProvider {
|
|
51
39
|
readonly id: string;
|
|
52
40
|
readonly weightsBytes: number;
|
|
41
|
+
readonly grouped: import("./source").GroupedDraftProvider;
|
|
53
42
|
|
|
54
43
|
private constructor(
|
|
55
44
|
private readonly drafter: GemmaAssistantDrafter,
|
|
56
45
|
id: string,
|
|
57
|
-
weightsBytes: number,
|
|
46
|
+
weightsBytes: number, namespace: string,
|
|
58
47
|
) {
|
|
59
48
|
this.id = id;
|
|
60
49
|
this.weightsBytes = weightsBytes;
|
|
50
|
+
this.grouped = assistantGroups(drafter,namespace);
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
static async load(modelDir: string): Promise<AssistantProvider> {
|
|
64
54
|
const drafter = await GemmaAssistantDrafter.load(modelDir);
|
|
65
55
|
const id = modelDir.split("/").filter(Boolean).at(-1)!;
|
|
66
|
-
|
|
56
|
+
try {
|
|
57
|
+
const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
|
|
58
|
+
readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
|
|
59
|
+
.map(name => ({ name, path: join(modelDir, name) })));
|
|
60
|
+
return new AssistantProvider(drafter, id, safetensorsBytes(modelDir), `gemma-assistant-v1:${identity}`);
|
|
61
|
+
} catch (error) { drafter.dispose(); throw error; }
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
|
|
@@ -71,50 +66,31 @@ export class AssistantProvider implements DraftProvider {
|
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
dispose(): void {
|
|
74
|
-
|
|
69
|
+
this.drafter.dispose();
|
|
75
70
|
}
|
|
76
71
|
}
|
|
77
72
|
|
|
78
|
-
class AssistantSource implements DraftSource {
|
|
73
|
+
export class AssistantSource implements DraftSource {
|
|
79
74
|
readonly weightsBytes = 0; // provider-owned weights; per-request adds nothing
|
|
80
|
-
private readonly
|
|
81
|
-
private readonly caches: Cache[];
|
|
82
|
-
private readonly donors: { sliding: number; full: number };
|
|
75
|
+
private readonly target: AssistantRowsTarget;
|
|
83
76
|
|
|
84
|
-
constructor(private readonly drafter: GemmaAssistantDrafter, target: TargetView) {
|
|
85
|
-
if (!
|
|
86
|
-
throw new Error("assistant drafter requires a Gemma4 target");
|
|
87
|
-
this.
|
|
88
|
-
this.caches = target.caches;
|
|
89
|
-
this.donors = donorIndices(this.model);
|
|
77
|
+
constructor(private readonly drafter: Pick<GemmaAssistantDrafter, "forwardRows">, target: TargetView) {
|
|
78
|
+
if (!target.assistantRows)
|
|
79
|
+
throw new Error("assistant drafter requires a Gemma4 target with donor views");
|
|
80
|
+
this.target = target.assistantRows;
|
|
90
81
|
}
|
|
91
82
|
|
|
92
83
|
/** No own cache to prime — the drafter reads the target's live state. */
|
|
93
84
|
prefill(_promptIds: number[], _ctxML?: MlxArray): void {}
|
|
94
85
|
|
|
95
|
-
private embedScaled(token: number): MlxArray {
|
|
96
|
-
const ids = ops.fromInt32([token], [1, 1]);
|
|
97
|
-
const e = this.model.embed.encode(ids);
|
|
98
|
-
ids.dispose();
|
|
99
|
-
const s = ops.mulScalar(e, this.model.embedScale);
|
|
100
|
-
e.dispose();
|
|
101
|
-
return s;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private readDonors(): { sliding: [MlxArray, MlxArray]; full: [MlxArray, MlxArray] } {
|
|
105
|
-
const view = (i: number) =>
|
|
106
|
-
(this.caches[i] as unknown as { temporalView(): [MlxArray, MlxArray] }).temporalView();
|
|
107
|
-
return { sliding: view(this.donors.sliding), full: view(this.donors.full) };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
86
|
/** Draft n tokens against the target's donor K/V, conditioning the first
|
|
111
87
|
* step on the anchor (the last emitted token + its target hidden) and
|
|
112
88
|
* chaining the drafter's own post-projected hiddens after that — exactly
|
|
113
89
|
* specGenerate's 2a block. anchorHidden is borrowed; never disposed here. */
|
|
114
90
|
draft(feed: number[], n: number, _stepBase: number, anchorHidden?: MlxArray): number[] {
|
|
115
91
|
if (!anchorHidden) throw new Error("assistant drafter needs the target anchor hidden");
|
|
116
|
-
const
|
|
117
|
-
const
|
|
92
|
+
const shared = this.target.readDonors();
|
|
93
|
+
const position = shared.positions[0]!;
|
|
118
94
|
const drafts: number[] = [];
|
|
119
95
|
const ownedHiddens: MlxArray[] = [];
|
|
120
96
|
let dTok = feed[feed.length - 1]!; // the pending token (anchorHidden's token)
|
|
@@ -122,22 +98,22 @@ class AssistantSource implements DraftSource {
|
|
|
122
98
|
let emb: MlxArray | null = null; // hoisted so a mid-loop throw still frees it
|
|
123
99
|
try {
|
|
124
100
|
for (let k = 0; k < n; k++) {
|
|
125
|
-
|
|
126
|
-
|
|
101
|
+
using ids = ops.fromInt32([dTok], [1, 1]);
|
|
102
|
+
emb = this.target.embed(ids);
|
|
103
|
+
const step = this.drafter.forwardRows(emb, dHid, shared, position + k);
|
|
104
|
+
ownedHiddens.push(step.nextHidden);
|
|
105
|
+
let token: number;
|
|
106
|
+
try { token = ops.itemUint32(step.tokens); } finally { step.tokens.dispose(); }
|
|
127
107
|
emb.dispose();
|
|
128
108
|
emb = null;
|
|
129
|
-
drafts.push(
|
|
130
|
-
|
|
131
|
-
dTok = step.token;
|
|
109
|
+
drafts.push(token);
|
|
110
|
+
dTok = token;
|
|
132
111
|
dHid = step.nextHidden;
|
|
133
112
|
}
|
|
134
113
|
} finally {
|
|
135
114
|
emb?.dispose();
|
|
136
115
|
for (const a of ownedHiddens) a.dispose();
|
|
137
|
-
|
|
138
|
-
k.dispose();
|
|
139
|
-
v.dispose();
|
|
140
|
-
}
|
|
116
|
+
shared.dispose();
|
|
141
117
|
}
|
|
142
118
|
return drafts;
|
|
143
119
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GenerateOptions } from "../generate";
|
|
2
|
+
|
|
3
|
+
/** Snapshot numerical configuration when the request is bound. Caller-owned
|
|
4
|
+
* arrays must not change the graph or persistence identity after grouping. */
|
|
5
|
+
export function captureSpeculativeOptions(options: GenerateOptions): GenerateOptions {
|
|
6
|
+
return { ...options,
|
|
7
|
+
...(options.kvConfig ? { kvConfig: options.kvConfig.map(({ layerIdx, bits, groupSize }) =>
|
|
8
|
+
({ layerIdx, bits, groupSize })).sort((a, b) => a.layerIdx - b.layerIdx) } : {}),
|
|
9
|
+
...(options.turboQuant ? { turboQuant: { ...options.turboQuant } } : {}),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Existing namespaces remain byte-identical when no per-layer scheme is
|
|
14
|
+
* supplied. Execution and persistence consume the same captured settings. */
|
|
15
|
+
export function speculativePrefixNamespace(method: string | undefined, adapters: string | string[],
|
|
16
|
+
options: GenerateOptions): string {
|
|
17
|
+
return JSON.stringify({ method, adapters, kvBits: options.kvBits ?? null,
|
|
18
|
+
kvGroupSize: options.kvGroupSize ?? 64, quantizedKvStart: options.quantizedKvStart ?? null,
|
|
19
|
+
turboQuant: options.turboQuant ?? null,
|
|
20
|
+
...(options.kvConfig?.length ? { kvConfig: options.kvConfig } : {}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { projectedDraftGroups } from "./projected-draft-rows";
|
|
2
|
+
import type { GroupedDraftProvider, TargetView } from "./source";
|
|
3
|
+
import type { DeepspecDrafter } from "./dspark/deepspec-module";
|
|
4
|
+
|
|
5
|
+
/** Existing pairing requirements are checked once when the provider opens. */
|
|
6
|
+
export function bindDeepspecTarget(target: TargetView, drafter: Pick<DeepspecDrafter, "cfg">): void {
|
|
7
|
+
if (!target.gemmaTaps) throw new Error("DeepSpec drafter requires a Gemma4 target");
|
|
8
|
+
const layers = drafter.cfg.num_target_layers;
|
|
9
|
+
if (target.gemmaTaps.layerCount !== layers) throw new Error(
|
|
10
|
+
`DeepSpec drafter was trained for a ${layers}-layer target; ` +
|
|
11
|
+
`this model has ${target.gemmaTaps.layerCount} layers — wrong (target, drafter) pairing`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function deepspecGroups(drafter: DeepspecDrafter, namespace: string): GroupedDraftProvider {
|
|
15
|
+
return projectedDraftGroups(target => {
|
|
16
|
+
bindDeepspecTarget(target, drafter);
|
|
17
|
+
return {
|
|
18
|
+
namespace, schema: "deepspec-context-v1",
|
|
19
|
+
layers: drafter.cfg.num_hidden_layers, tapLayers: drafter.tapLayers,
|
|
20
|
+
project(hidden, positions) {
|
|
21
|
+
using projected = drafter.projectContext(hidden);
|
|
22
|
+
return drafter.projectContextKVRows(projected, positions);
|
|
23
|
+
},
|
|
24
|
+
draft(context, pending, positions, depth) {
|
|
25
|
+
return drafter.draftRows(context, pending, positions).tokens.map(row => row.slice(0, depth));
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// (github.com/deepseek-ai/DeepSpec, MIT); the module port with transcription
|
|
5
5
|
// notes lives in src/spec/dspark/deepspec-module.ts. Oracle: DeepSpec's eval
|
|
6
6
|
// at temperature 0 (RNG-free — verify degenerates to argmax token-match),
|
|
7
|
-
// scripts/oracle-dspark-deepspec.py →
|
|
7
|
+
// scripts/oracle/oracle-dspark-deepspec.py → dspark-deepspec-compare.ts (deleted 2026-08-23; git history).
|
|
8
8
|
//
|
|
9
9
|
// Seam mapping (why this fits without serve-loop changes): the reference
|
|
10
10
|
// recycles target hidden states from each verify pass into the drafter's
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
// Context rows are cached post-norm-post-rope — bit-equivalent to their
|
|
23
23
|
// in-round concat (per-row RMSNorm/RoPE; argued in projectContextKV's doc).
|
|
24
24
|
|
|
25
|
+
import { artifactIdentity } from "../model/artifact-identity";
|
|
26
|
+
import { deepspecGroups, bindDeepspecTarget } from "./deepspec-rows";
|
|
25
27
|
import { readdirSync, statSync } from "node:fs";
|
|
26
28
|
import { join } from "node:path";
|
|
27
29
|
import type { MlxArray } from "../mlx/array";
|
|
28
30
|
import * as ops from "../mlx/ops";
|
|
29
|
-
import { Gemma4Model } from "../model/gemma4";
|
|
30
31
|
import { DeepspecDrafter, type ContextKV } from "./dspark/deepspec-module";
|
|
31
32
|
import type { DraftProvider, DraftSource, TargetView } from "./source";
|
|
32
33
|
|
|
@@ -40,20 +41,27 @@ function safetensorsBytes(dir: string): number {
|
|
|
40
41
|
export class DeepspecProvider implements DraftProvider {
|
|
41
42
|
readonly id: string;
|
|
42
43
|
readonly weightsBytes: number;
|
|
44
|
+
readonly grouped: import("./source").GroupedDraftProvider;
|
|
43
45
|
/** Trained block width (config block_size, e.g. 7) — the server pins
|
|
44
46
|
* numDraftTokens to this. */
|
|
45
47
|
readonly gamma: number;
|
|
46
48
|
|
|
47
|
-
private constructor(private readonly drafter: DeepspecDrafter, id: string, weightsBytes: number) {
|
|
49
|
+
private constructor(private readonly drafter: DeepspecDrafter, id: string, weightsBytes: number, namespace: string) {
|
|
48
50
|
this.id = id;
|
|
49
51
|
this.weightsBytes = weightsBytes;
|
|
50
52
|
this.gamma = drafter.gamma;
|
|
53
|
+
this.grouped = deepspecGroups(drafter, namespace);
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
static async load(modelDir: string): Promise<DeepspecProvider> {
|
|
54
57
|
const drafter = await DeepspecDrafter.load(modelDir);
|
|
55
58
|
const id = modelDir.split("/").filter(Boolean).at(-1)!;
|
|
56
|
-
|
|
59
|
+
try {
|
|
60
|
+
const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
|
|
61
|
+
readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
|
|
62
|
+
.map(name => ({ name, path: join(modelDir, name) })));
|
|
63
|
+
return new DeepspecProvider(drafter, id, safetensorsBytes(modelDir), `deepspec-context-v1:${identity}`);
|
|
64
|
+
} catch (error) { drafter.dispose(); throw error; }
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
|
|
@@ -65,21 +73,15 @@ export class DeepspecProvider implements DraftProvider {
|
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
|
|
68
|
-
class DeepspecSource implements DraftSource {
|
|
76
|
+
export class DeepspecSource implements DraftSource {
|
|
69
77
|
readonly weightsBytes = 0; // provider-owned weights
|
|
70
78
|
readonly tapLayers: number[];
|
|
71
79
|
private ctxKV: ContextKV[] | null = null; // per-layer projected context rows
|
|
72
80
|
private ctxLen = 0; // context rows cached == the anchor's absolute position
|
|
73
81
|
|
|
74
|
-
constructor(private readonly drafter: DeepspecDrafter,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const nLayers = target.model.layers.length;
|
|
78
|
-
if (nLayers !== drafter.cfg.num_target_layers)
|
|
79
|
-
throw new Error(
|
|
80
|
-
`DeepSpec drafter was trained for a ${drafter.cfg.num_target_layers}-layer target; ` +
|
|
81
|
-
`this model has ${nLayers} layers — wrong (target, drafter) pairing`,
|
|
82
|
-
);
|
|
82
|
+
constructor(private readonly drafter: Pick<DeepspecDrafter,
|
|
83
|
+
"cfg" | "tapLayers" | "projectContext" | "projectContextKV" | "draftBlock">, target: TargetView) {
|
|
84
|
+
bindDeepspecTarget(target, drafter);
|
|
83
85
|
this.tapLayers = drafter.tapLayers;
|
|
84
86
|
}
|
|
85
87
|
|
|
@@ -18,14 +18,15 @@
|
|
|
18
18
|
// target verify decides). The richer rejection-sampling verify stays in the
|
|
19
19
|
// standalone dflashGenerate for the measure script.
|
|
20
20
|
|
|
21
|
+
import { artifactIdentity } from "../model/artifact-identity";
|
|
22
|
+
import { projectedDraftGroups } from "./projected-draft-rows";
|
|
21
23
|
import { readdirSync, statSync } from "node:fs";
|
|
22
24
|
import { join } from "node:path";
|
|
23
25
|
import type { MlxArray } from "../mlx/array";
|
|
24
26
|
import * as ops from "../mlx/ops";
|
|
25
|
-
import { Gemma4Model } from "../model/gemma4";
|
|
26
27
|
import type { DflashDrafter } from "./dspark/module-dflash";
|
|
27
28
|
import { loadDsparkDrafter } from "./dspark/loader";
|
|
28
|
-
import type { DraftProvider, DraftSource, TargetView } from "./source";
|
|
29
|
+
import type { DraftProvider, DraftSource, TargetView, DraftProjection } from "./source";
|
|
29
30
|
import { runtimeValue } from "../runtime-config";
|
|
30
31
|
|
|
31
32
|
function safetensorsBytes(dir: string): number {
|
|
@@ -38,20 +39,43 @@ function safetensorsBytes(dir: string): number {
|
|
|
38
39
|
export class DflashProvider implements DraftProvider {
|
|
39
40
|
readonly id: string;
|
|
40
41
|
readonly weightsBytes: number;
|
|
42
|
+
readonly grouped: import("./source").GroupedDraftProvider;
|
|
41
43
|
/** The trained block width — the server pins numDraftTokens to this so the
|
|
42
44
|
* serve loop never asks for more positions than the block was trained for. */
|
|
43
45
|
readonly gamma: number;
|
|
44
46
|
|
|
45
|
-
private constructor(private readonly drafter: DflashDrafter, id: string, weightsBytes: number) {
|
|
47
|
+
private constructor(private readonly drafter: DflashDrafter, id: string, weightsBytes: number, namespace: string) {
|
|
46
48
|
this.id = id;
|
|
47
49
|
this.weightsBytes = weightsBytes;
|
|
48
50
|
this.gamma = drafter.cfg.gamma;
|
|
51
|
+
this.grouped = projectedDraftGroups(target => {
|
|
52
|
+
if (!target.gemmaTaps) throw new Error("DSpark drafter requires a Gemma4 target");
|
|
53
|
+
const projection = target.gemmaTaps.projection;
|
|
54
|
+
const minConf = runtimeValue("MLX_BUN_DSPARK_MINCONF");
|
|
55
|
+
return {
|
|
56
|
+
namespace, schema: "dflash-context-v1",
|
|
57
|
+
layers: drafter.cfg.nLayers, tapLayers: drafter.cfg.tapLayers,
|
|
58
|
+
project: hidden => drafter.projectContextRows(hidden),
|
|
59
|
+
draft(context, pending, _positions, depth) {
|
|
60
|
+
return drafter.forwardRows(projection, null, pending, depth, {
|
|
61
|
+
collectLogits: false, collectConfidence: false,
|
|
62
|
+
thresholds: drafter.cfg.sts?.thresholds,
|
|
63
|
+
...(minConf ? { minConf: Number(minConf) } : {}),
|
|
64
|
+
}, context).tokens;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
});
|
|
49
68
|
}
|
|
50
69
|
|
|
51
70
|
static async load(modelDir: string): Promise<DflashProvider> {
|
|
52
71
|
const drafter = loadDsparkDrafter(modelDir); // variant dispatch (dspark|legacy dflash)
|
|
53
72
|
const id = modelDir.split("/").filter(Boolean).at(-1)!;
|
|
54
|
-
|
|
73
|
+
try {
|
|
74
|
+
const identity = await artifactIdentity(await Bun.file(`${modelDir}/dspark.json`).text(),
|
|
75
|
+
readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
|
|
76
|
+
.map(name => ({ name, path: join(modelDir, name) })));
|
|
77
|
+
return new DflashProvider(drafter, id, safetensorsBytes(modelDir), `dflash-context-v1:${identity}`);
|
|
78
|
+
} catch (error) { drafter.dispose(); throw error; }
|
|
55
79
|
}
|
|
56
80
|
|
|
57
81
|
open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
|
|
@@ -59,22 +83,22 @@ export class DflashProvider implements DraftProvider {
|
|
|
59
83
|
}
|
|
60
84
|
|
|
61
85
|
dispose(): void {
|
|
62
|
-
//
|
|
63
|
-
// materializes owned MlxArrays — free them on teardown.
|
|
86
|
+
// Provider-owned weights are released when the mounted draft is closed.
|
|
64
87
|
this.drafter.dispose();
|
|
65
88
|
}
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
class DflashSource implements DraftSource {
|
|
91
|
+
export class DflashSource implements DraftSource {
|
|
69
92
|
readonly weightsBytes = 0; // provider-owned weights
|
|
70
93
|
readonly tapLayers: number[];
|
|
71
|
-
private readonly model:
|
|
94
|
+
private readonly model: DraftProjection;
|
|
95
|
+
private readonly minConf = runtimeValue("MLX_BUN_DSPARK_MINCONF");
|
|
72
96
|
private hCtx: MlxArray | null = null; // [1, L, m*H] — grows with the accepted stream
|
|
73
97
|
|
|
74
|
-
constructor(private readonly drafter: DflashDrafter, target: TargetView) {
|
|
75
|
-
if (!
|
|
98
|
+
constructor(private readonly drafter: Pick<DflashDrafter, "cfg" | "forwardInfer">, target: TargetView) {
|
|
99
|
+
if (!target.gemmaTaps)
|
|
76
100
|
throw new Error("DSpark drafter requires a Gemma4 target");
|
|
77
|
-
this.model = target.
|
|
101
|
+
this.model = target.gemmaTaps.projection;
|
|
78
102
|
this.tapLayers = drafter.cfg.tapLayers;
|
|
79
103
|
}
|
|
80
104
|
|
|
@@ -94,7 +118,7 @@ class DflashSource implements DraftSource {
|
|
|
94
118
|
draft(feed: number[], n: number, _stepBase: number, _anchorHidden?: MlxArray): number[] {
|
|
95
119
|
if (!this.hCtx) throw new Error("DSpark drafter: draft before prefill");
|
|
96
120
|
const anchorTok = feed[feed.length - 1]!;
|
|
97
|
-
const envMin =
|
|
121
|
+
const envMin = this.minConf;
|
|
98
122
|
const block = this.drafter.forwardInfer(this.model, this.hCtx, anchorTok, n, {
|
|
99
123
|
thresholds: this.drafter.cfg.sts?.thresholds,
|
|
100
124
|
collectLogits: false, // serve loop runs its own verify lm-head, never reads this
|