mlx-bun 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1453 -88
- package/THIRD_PARTY_NOTICES.md +882 -0
- package/bin/mlx-bun.convert.mjs +4 -0
- package/bin/mlx-bun.fuse.mjs +4 -0
- package/bin/mlx-bun.generate.mjs +4 -0
- package/bin/mlx-bun.lora.mjs +4 -0
- package/bin/mlx-bun.mjs +13 -21
- package/bin/mlx-bun.server.mjs +4 -0
- package/bin/mlx-bun.upload.mjs +4 -0
- package/dist/web/app.js +9584 -0
- package/package.json +50 -53
- package/src/cli/ane-install.ts +76 -0
- package/src/cli/args.ts +179 -0
- package/src/cli/engine-entry.ts +68 -0
- package/src/cli/inference.ts +214 -0
- package/src/cli/job-entry.ts +97 -0
- package/src/cli/library-host.ts +117 -0
- package/src/cli/main.ts +57 -0
- package/src/cli/memory-engine.ts +163 -0
- package/src/cli/memory.ts +36 -0
- package/src/cli/mlx-lm-aliases.ts +309 -0
- package/src/cli/model-choice.ts +33 -0
- package/src/cli/model-selection.ts +84 -0
- package/src/cli/module-host.ts +11 -0
- package/src/cli/module-verbs.ts +50 -0
- package/src/cli/numerical-policy.ts +12 -0
- package/src/cli/perplexity.ts +89 -0
- package/src/cli/serve-host.ts +423 -0
- package/src/cli/serve-isolated.ts +217 -0
- package/src/cli/serve-options.ts +106 -0
- package/src/cli/serve-state.ts +205 -0
- package/src/cli/serve.ts +500 -0
- package/src/cli/served-model-host.ts +102 -0
- package/src/cli/server-entry.ts +148 -0
- package/src/cli/serving-unit.ts +177 -0
- package/src/{tui.ts → cli/terminal.ts} +13 -8
- package/src/cli/worker-adapters.ts +34 -0
- package/src/cli/worker-entry.ts +272 -0
- package/src/cli/worker-unit.ts +179 -0
- package/src/engine/adapter-operation.ts +26 -0
- package/src/engine/cache-services.ts +114 -0
- package/src/engine/completion.ts +39 -0
- package/src/engine/generation-gateway.ts +358 -0
- package/src/engine/index.ts +59 -0
- package/src/engine/kv-budget.ts +120 -0
- package/src/engine/media-preparation.ts +232 -0
- package/src/engine/model-binding.ts +24 -0
- package/src/engine/model-host.ts +513 -0
- package/src/engine/model-serving.ts +89 -0
- package/src/{serve → engine}/preparation.ts +10 -8
- package/src/{serve → engine}/session-completion-engine.ts +6 -6
- package/src/engine/telemetry.ts +109 -0
- package/src/hub/downloads.ts +116 -0
- package/src/jobs/db.ts +16 -7
- package/src/jobs/events.ts +29 -0
- package/src/jobs/executable.ts +5 -0
- package/src/jobs/host.ts +51 -0
- package/src/jobs/in-process.ts +55 -0
- package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
- package/src/jobs/runner.ts +150 -231
- package/src/jobs/service.ts +75 -0
- package/src/jobs/sse.ts +59 -23
- package/src/jobs/worker-memory.ts +46 -0
- package/src/jobs/worker-process.ts +163 -0
- package/src/jobs/worker-supervisor.ts +258 -0
- package/src/modules.ts +58 -0
- package/src/publishing/catalog-hub.ts +18 -0
- package/src/publishing/credentials.ts +31 -0
- package/src/publishing/upload.ts +37 -0
- package/src/residency/leased-adapters.ts +21 -0
- package/src/residency/local-records.ts +16 -0
- package/src/residency/model-residency.ts +405 -0
- package/src/residency/record-index.ts +28 -0
- package/src/residency/resident-estimate.ts +50 -0
- package/src/{anthropic.ts → server/anthropic.ts} +3 -81
- package/src/server/cache-routes.ts +36 -0
- package/src/{serve → server}/chat-request.ts +12 -10
- package/src/{serve → server}/chat-stage.ts +27 -22
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +42 -42
- package/src/server/decision-body.ts +55 -0
- package/src/server/decision-routes.ts +134 -0
- package/src/server/decision-wire.ts +228 -0
- package/src/{serve → server}/discovery-routes.ts +42 -83
- package/src/server/generated-token-history.ts +57 -0
- package/src/{serve → server}/http.ts +25 -13
- package/src/{serve → server}/inference-request.ts +5 -5
- package/src/server/job-routes.ts +20 -0
- package/src/server/media-prompt.ts +63 -0
- package/src/server/memory-completion-client.ts +46 -0
- package/src/server/model-routes.ts +192 -0
- package/src/{serve → server}/openai-wire.ts +3 -2
- package/src/{serve → server}/pipeline.ts +1 -1
- package/src/server/prompt-builder.ts +13 -0
- package/src/server/prompt-contracts.ts +17 -0
- package/src/server/proxy-routes.ts +187 -0
- package/src/server/publishing-routes.ts +41 -0
- package/src/{serve → server}/request-plan.ts +8 -8
- package/src/{serve → server}/request-prep.ts +82 -68
- package/src/{serve → server}/responses-client.ts +30 -13
- package/src/{responses.ts → server/responses.ts} +12 -93
- package/src/server/routes.ts +205 -0
- package/src/server/start.ts +72 -0
- package/src/server/status-routes.ts +108 -0
- package/src/{serve → server}/text-completion-stage.ts +25 -4
- package/src/server/text-prompt.ts +12 -0
- package/src/{serve → server}/token-streams.ts +36 -38
- package/src/server/worker-routes.ts +311 -0
- package/src/storage/paths.ts +61 -0
- package/src/web/assets.ts +37 -0
- package/src/web/{src → browser}/api.ts +5 -23
- package/src/web/browser/chat-host.ts +17 -0
- package/src/web/browser/installed-panels.ts +6 -0
- package/src/web/browser/main.ts +55 -0
- package/src/web/browser/markdown.ts +279 -0
- package/src/web/browser/memory-panel.ts +9 -0
- package/src/web/browser/palette.ts +64 -0
- package/src/web/browser/protocol.ts +13 -0
- package/src/web/browser/shell.ts +467 -0
- package/src/web/{src → browser}/status.ts +32 -36
- package/src/web/build.ts +51 -0
- package/src/web/public/app.html +1054 -0
- package/src/web/{sw.js → public/sw.js} +4 -3
- package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
- package/src/web/{vendor → public/vendor}/hljs.js +2 -2
- package/THIRD_PARTY_LICENSES.md +0 -51
- package/docs/README.md +0 -94
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
- package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
- package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
- package/docs/archive/investigations/curve-bisector-routing.md +0 -123
- package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
- package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
- package/docs/archive/investigations/dspark-handoff.md +0 -224
- package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
- package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
- package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
- package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
- package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
- package/docs/archive/investigations/lab-build-journal.md +0 -157
- package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
- package/docs/archive/investigations/openjarvis-fit.md +0 -198
- package/docs/archive/investigations/openwiki-evaluation.md +0 -249
- package/docs/archive/investigations/optimization_plan.md +0 -346
- package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
- package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
- package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
- package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
- package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
- package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
- package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
- package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
- package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
- package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
- package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
- package/docs/archive/planning/chat-ui-vision.md +0 -50
- package/docs/archive/planning/chunk-task-roadmap.md +0 -77
- package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
- package/docs/archive/planning/journal.md +0 -316
- package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
- package/docs/archive/planning/pi-integration-review.md +0 -178
- package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
- package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
- package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
- package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
- package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
- package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
- package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
- package/docs/archive/planning/web-ui-pass-plan.md +0 -213
- package/docs/archive/planning/website-readme-pass-plan.md +0 -224
- package/docs/design/batching.md +0 -1841
- package/docs/design/decode-speed-program.md +0 -2349
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -705
- package/docs/design/kv-cache.md +0 -824
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -1990
- package/docs/design/turboquant.md +0 -2212
- package/docs/design/unified-engine-frontier-plan.md +0 -1880
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -594
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/release-notes-v0.4.0.md +0 -45
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3613
- package/docs/reference/cli.md +0 -585
- package/docs/reference/distribution.md +0 -355
- package/docs/reference/environment.md +0 -398
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -674
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -334
- package/docs/reference/server-api.md +0 -1775
- package/docs/reference/server-config.md +0 -846
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/conformer.ts +0 -647
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/transcode.ts +0 -67
- package/src/backends/mlx/assistant-target.ts +0 -46
- package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
- package/src/backends/mlx/autoregressive.ts +0 -108
- package/src/backends/mlx/batch-group.ts +0 -1790
- package/src/backends/mlx/cache-attachment.ts +0 -67
- package/src/backends/mlx/cache-layout.ts +0 -31
- package/src/backends/mlx/checkpoint-state.ts +0 -53
- package/src/backends/mlx/continuation-persistence.ts +0 -106
- package/src/backends/mlx/continuation-request.ts +0 -43
- package/src/backends/mlx/continuation.ts +0 -77
- package/src/backends/mlx/diffusion.ts +0 -39
- package/src/backends/mlx/draft-target.ts +0 -32
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -45
- package/src/backends/mlx/full-kv-row-append.ts +0 -32
- package/src/backends/mlx/full-kv-row-donor.ts +0 -54
- package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
- package/src/backends/mlx/gateway-binding.ts +0 -130
- package/src/backends/mlx/graph.ts +0 -38
- package/src/backends/mlx/kv-codec.ts +0 -9
- package/src/backends/mlx/kv-maintenance.ts +0 -133
- package/src/backends/mlx/kv-tensor-rows.ts +0 -212
- package/src/backends/mlx/memory-client.ts +0 -189
- package/src/backends/mlx/methods.ts +0 -90
- package/src/backends/mlx/model-prompt.ts +0 -164
- package/src/backends/mlx/model-serving.ts +0 -79
- package/src/backends/mlx/prefill-cohort.ts +0 -89
- package/src/backends/mlx/prefill-rows.ts +0 -200
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -41
- package/src/backends/mlx/rollback.ts +0 -89
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -242
- package/src/backends/mlx/speculative-group.ts +0 -359
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -114
- package/src/backends/mlx/state-rows.ts +0 -104
- package/src/backends/mlx/state-views.ts +0 -46
- package/src/backends/mlx/target-layout-capability.ts +0 -35
- package/src/backends/mlx/text-engine.ts +0 -73
- package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3168
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -60
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -259
- package/src/contracts/prefix-cache.ts +0 -23
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -45
- package/src/contracts/tsconfig.json +0 -14
- package/src/dataset/generators.ts +0 -1087
- package/src/dataset/index.ts +0 -12
- package/src/dataset/job.ts +0 -81
- package/src/dataset/llm.ts +0 -71
- package/src/dataset/registry.ts +0 -528
- package/src/diffusion/diffusion-generate.ts +0 -507
- package/src/download.ts +0 -505
- package/src/embed.ts +0 -77
- package/src/engine/admission.ts +0 -59
- package/src/engine/cancellation.ts +0 -38
- package/src/engine/engine.ts +0 -56
- package/src/engine/execution-coordinator.ts +0 -70
- package/src/engine/execution-plan.ts +0 -53
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -72
- package/src/engine/session.ts +0 -247
- package/src/eval/README.md +0 -130
- package/src/eval/ifeval.ts +0 -81
- package/src/eval/kl-prompts.ts +0 -29
- package/src/eval/kl.ts +0 -590
- package/src/eval/perplexity.ts +0 -164
- package/src/eval/quality-db.ts +0 -92
- package/src/eval/reference-logits.ts +0 -207
- package/src/eval/runner.ts +0 -124
- package/src/eval/score.ts +0 -49
- package/src/eval/tasks/bfcl.ts +0 -535
- package/src/eval/tasks/gsm8k.ts +0 -98
- package/src/eval/tasks/hashhop.ts +0 -139
- package/src/eval/tasks/humaneval.ts +0 -275
- package/src/eval/tasks/ifeval.ts +0 -525
- package/src/eval/tasks/mmlu.ts +0 -157
- package/src/eval/ultrafeedback.ts +0 -60
- package/src/evaldb.ts +0 -199
- package/src/expert-io.ts +0 -393
- package/src/expert-offload-build.ts +0 -77
- package/src/expert-offload.ts +0 -76
- package/src/expert-residency.ts +0 -1134
- package/src/expert-usage.ts +0 -415
- package/src/fill/echo-index.ts +0 -188
- package/src/fill/fill-session.ts +0 -452
- package/src/fill/proposal.ts +0 -68
- package/src/fill/schema-rows.ts +0 -506
- package/src/fill/tool-boundary.ts +0 -103
- package/src/fit.ts +0 -249
- package/src/generate.ts +0 -1346
- package/src/grammar.ts +0 -591
- package/src/harness-pi.ts +0 -184
- package/src/hf-push.ts +0 -628
- package/src/hub-rest.ts +0 -242
- package/src/index.ts +0 -63
- package/src/inference/denoising.ts +0 -17
- package/src/inference/draft-acceptance.ts +0 -41
- package/src/inference/draft-output.ts +0 -49
- package/src/inference/graph.ts +0 -33
- package/src/inference/prefill.ts +0 -39
- package/src/inference/rollback.ts +0 -7
- package/src/jobs/index.ts +0 -31
- package/src/jobs/job-entry.ts +0 -107
- package/src/jobs/task-client.ts +0 -19
- package/src/jobs/types.ts +0 -2
- package/src/kv-scheme.ts +0 -257
- package/src/kv-store.ts +0 -1099
- package/src/lab/README.md +0 -18
- package/src/lab/curve/curve-designer.html +0 -303
- package/src/lab/curve/curve-sampler.ts +0 -122
- package/src/lab/expert-trace/expert-trace.ts +0 -69
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
- package/src/lab/paged-kv/paged-kv.ts +0 -270
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -49
- package/src/media-fetch.ts +0 -442
- package/src/memory/article.ts +0 -558
- package/src/memory/chunk-validation.ts +0 -150
- package/src/memory/chunk.ts +0 -318
- package/src/memory/cluster.ts +0 -351
- package/src/memory/coverage.ts +0 -134
- package/src/memory/crosslink.ts +0 -0
- package/src/memory/db.ts +0 -253
- package/src/memory/entity.ts +0 -203
- package/src/memory/gate.ts +0 -187
- package/src/memory/history.ts +0 -152
- package/src/memory/ingest.ts +0 -335
- package/src/memory/model.ts +0 -183
- package/src/memory/normalize.ts +0 -671
- package/src/memory/parse.ts +0 -22
- package/src/memory/pipeline.ts +0 -275
- package/src/memory/prompts.ts +0 -65
- package/src/memory/query.ts +0 -334
- package/src/memory/reconcile.ts +0 -734
- package/src/memory/redirect.ts +0 -108
- package/src/memory/reindex.ts +0 -325
- package/src/memory/resolve.ts +0 -307
- package/src/memory/rest.ts +0 -245
- package/src/memory/route.ts +0 -272
- package/src/memory/schedule.ts +0 -165
- package/src/memory/stages.ts +0 -777
- package/src/memory/synthesize.ts +0 -1638
- package/src/memory/tools.ts +0 -749
- package/src/memory/vault.ts +0 -1194
- package/src/memory/wikify.ts +0 -1064
- package/src/mlx/array.ts +0 -388
- package/src/mlx/autograd.ts +0 -304
- package/src/mlx/checkpoint.ts +0 -149
- package/src/mlx/compile.ts +0 -168
- package/src/mlx/custom-vjp.ts +0 -188
- package/src/mlx/ffi.ts +0 -512
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/ops.ts +0 -1021
- package/src/mlx/quantized-rows.ts +0 -36
- package/src/mlx/token-bitmask.ts +0 -52
- package/src/mlx/turboquant-kv-decode.ts +0 -82
- package/src/mlx/turboquant-kv-inverse.ts +0 -122
- package/src/mlx/turboquant-ops.ts +0 -861
- package/src/mlx/turboquant-tables.ts +0 -237
- package/src/mmap.ts +0 -90
- package/src/model/artifact-identity.ts +0 -73
- package/src/model/batched-kv.ts +0 -235
- package/src/model/batched-mask.ts +0 -279
- package/src/model/batched-quant.ts +0 -212
- package/src/model/batched-quantized-kv.ts +0 -144
- package/src/model/batched-rotating-quant.ts +0 -353
- package/src/model/batched-rotating-state.ts +0 -149
- package/src/model/batched-rotating.ts +0 -338
- package/src/model/batched-row-storage.ts +0 -179
- package/src/model/batched-ssm.ts +0 -52
- package/src/model/batched-turboquant-kv.ts +0 -93
- package/src/model/compiled-decode.ts +0 -712
- package/src/model/decoded-kv-donor.ts +0 -12
- package/src/model/delayed-quantized-kv.ts +0 -72
- package/src/model/delayed-rotating-quantized-kv.ts +0 -93
- package/src/model/delayed-turboquant-kv.ts +0 -55
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -189
- package/src/model/fingerprint.ts +0 -33
- package/src/model/flash-attention.ts +0 -694
- package/src/model/full-prefill-padding.ts +0 -56
- package/src/model/full-prefill-row.ts +0 -105
- package/src/model/gemma4-base.ts +0 -2351
- package/src/model/gemma4.ts +0 -1315
- package/src/model/generated/gemma4-12b.ts +0 -429
- package/src/model/generated/gemma4-26b.ts +0 -448
- package/src/model/generated/gemma4-e4b.ts +0 -717
- package/src/model/generated/index.ts +0 -18
- package/src/model/glm52-atlas.ts +0 -511
- package/src/model/glm52-cache.ts +0 -792
- package/src/model/glm52-config.ts +0 -262
- package/src/model/glm52-container.ts +0 -305
- package/src/model/glm52-coupling.ts +0 -388
- package/src/model/glm52-dsa.ts +0 -606
- package/src/model/glm52-expert-layout.ts +0 -253
- package/src/model/glm52-layout.ts +0 -152
- package/src/model/glm52-memory.ts +0 -500
- package/src/model/glm52-mla.ts +0 -792
- package/src/model/glm52-moe.ts +0 -223
- package/src/model/glm52-pilot.ts +0 -537
- package/src/model/glm52-reference.ts +0 -445
- package/src/model/glm52-residency.ts +0 -557
- package/src/model/glm52-resident-weights.ts +0 -135
- package/src/model/glm52-streamed-experts.ts +0 -453
- package/src/model/glm52-streamed-metal.ts +0 -610
- package/src/model/glm52-weights.ts +0 -503
- package/src/model/glm52.ts +0 -1132
- package/src/model/implementation.ts +0 -69
- package/src/model/kv-attention-view.ts +0 -67
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -443
- package/src/model/qwen-append.ts +0 -12
- package/src/model/qwen-conv.ts +0 -52
- package/src/model/qwen3-delta-state.ts +0 -74
- package/src/model/qwen3-delta.ts +0 -451
- package/src/model/qwen3-moe.ts +0 -404
- package/src/model/qwen3-mrope.ts +0 -252
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -819
- package/src/model/rotating-kv-donor.ts +0 -35
- package/src/model/rotating-kv-layout.ts +0 -262
- package/src/model/rotating-row-transaction.ts +0 -35
- package/src/model/speculative-rotating-kv.ts +0 -101
- package/src/model/ssm-prefill-padding.ts +0 -39
- package/src/model/support.ts +0 -102
- package/src/model/trellis-balanced-scatter.ts +0 -51
- package/src/model/trellis-linear.ts +0 -672
- package/src/model/trellis-shared-m.ts +0 -151
- package/src/model/trellis-shared-scatter.ts +0 -144
- package/src/model/trellis-splitk-prefill.ts +0 -158
- package/src/model/trellis-tiled-prefill.ts +0 -136
- package/src/model/trellis-vector-expand.ts +0 -62
- package/src/model/trellis-wide-prefill.ts +0 -94
- package/src/model/turboquant-codec.ts +0 -83
- package/src/model/universal/archs.ts +0 -332
- package/src/model/universal/dense.ts +0 -612
- package/src/model/universal/modules.ts +0 -170
- package/src/model/universal/rope.ts +0 -381
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native-pack.ts +0 -162
- package/src/pi-provider.ts +0 -53
- package/src/pi-session.ts +0 -81
- package/src/pi-terminal.ts +0 -274
- package/src/pi-web.ts +0 -1932
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -460
- package/src/quantize/allocator.ts +0 -627
- package/src/quantize/atomic-output.ts +0 -38
- package/src/quantize/calibration.ts +0 -181
- package/src/quantize/config-writer.ts +0 -145
- package/src/quantize/index.ts +0 -84
- package/src/quantize/job.ts +0 -162
- package/src/quantize/quantizer.ts +0 -666
- package/src/quantize/rotate.ts +0 -603
- package/src/quantize/safetensors-writer.ts +0 -249
- package/src/quantize/sensitivity.ts +0 -216
- package/src/quantize/trellis.ts +0 -586
- package/src/quantize/weight-transform.ts +0 -292
- package/src/registry.ts +0 -602
- package/src/runtime-config.ts +0 -81
- package/src/safetensors.ts +0 -158
- package/src/sampler.ts +0 -1011
- package/src/serve/admin-routes.ts +0 -184
- package/src/serve/assets/curve-terrain.html +0 -105
- package/src/serve/assets/training-inference-map.html +0 -575
- package/src/serve/aux-routes.ts +0 -132
- package/src/serve/batch-scheduler.ts +0 -8
- package/src/serve/checkpoint-identity.ts +0 -64
- package/src/serve/generation-gateway.ts +0 -496
- package/src/serve/isolate.ts +0 -609
- package/src/serve/kv-budget.ts +0 -14
- package/src/serve/lab-routes.ts +0 -341
- package/src/serve/lane-registry.ts +0 -45
- package/src/serve/model-admin-routes.ts +0 -155
- package/src/serve/model-binding.ts +0 -43
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -147
- package/src/serve/response-lease.ts +0 -24
- package/src/serve/session-search.ts +0 -326
- package/src/serve/static-routes.ts +0 -101
- package/src/server.ts +0 -1314
- package/src/spec/assistant-rows.ts +0 -92
- package/src/spec/assistant-source.ts +0 -126
- package/src/spec/cache-identity.ts +0 -22
- package/src/spec/deepspec-rows.ts +0 -29
- package/src/spec/deepspec-source.ts +0 -145
- package/src/spec/dflash-source.ts +0 -149
- package/src/spec/drafter.ts +0 -304
- package/src/spec/dspark/ab-stats.ts +0 -136
- package/src/spec/dspark/calibration.ts +0 -112
- package/src/spec/dspark/data-dflash.ts +0 -156
- package/src/spec/dspark/data.ts +0 -201
- package/src/spec/dspark/deepspec-module.ts +0 -776
- package/src/spec/dspark/generate-dflash.ts +0 -245
- package/src/spec/dspark/generate.ts +0 -290
- package/src/spec/dspark/loader.ts +0 -23
- package/src/spec/dspark/loss.ts +0 -213
- package/src/spec/dspark/module-dflash.ts +0 -560
- package/src/spec/dspark/module.ts +0 -540
- package/src/spec/dspark/quantize-drafter.ts +0 -91
- package/src/spec/dspark/sample.ts +0 -112
- package/src/spec/generate.ts +0 -276
- package/src/spec/glm52-mtp-graph.ts +0 -29
- package/src/spec/glm52-mtp-rows.ts +0 -132
- package/src/spec/glm52-mtp-source.ts +0 -317
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -204
- package/src/spec/projected-draft-rows.ts +0 -73
- package/src/spec/qwen-mtp-module.ts +0 -171
- package/src/spec/qwen-mtp-rows.ts +0 -219
- package/src/spec/qwen-mtp-source.ts +0 -383
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -585
- package/src/spec/source.ts +0 -215
- package/src/spec/two-model-rows.ts +0 -61
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -372
- package/src/ssd-durability.ts +0 -211
- package/src/tokenizer.ts +0 -335
- package/src/tool-approvals.ts +0 -131
- package/src/tool-call.ts +0 -695
- package/src/train/dataset.ts +0 -484
- package/src/train/diffusion-lora.ts +0 -216
- package/src/train/export.ts +0 -32
- package/src/train/flash-cce.ts +0 -1234
- package/src/train/forward.ts +0 -266
- package/src/train/fuse.ts +0 -243
- package/src/train/index.ts +0 -46
- package/src/train/job.ts +0 -205
- package/src/train/lora-params.ts +0 -254
- package/src/train/loss.ts +0 -1591
- package/src/train/merge.ts +0 -195
- package/src/train/optimizer.ts +0 -183
- package/src/train/prefix-shared.ts +0 -490
- package/src/train/rank.ts +0 -137
- package/src/train/segmented.ts +0 -1828
- package/src/train/steel-qmm-header.ts +0 -1461
- package/src/train/trainer.ts +0 -1221
- package/src/train/watch.ts +0 -542
- package/src/vision/diffusion-vision.ts +0 -620
- package/src/vision/embedder.ts +0 -168
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -373
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -196
- package/src/vision/qwen3vl-tower.ts +0 -555
- package/src/vision/siglip.ts +0 -599
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2143
- package/src/web/app.js +0 -5703
- package/src/web/skills/memory/SKILL.md +0 -120
- package/src/web/skills/web-research/SKILL.md +0 -46
- package/src/web/skills.ts +0 -97
- package/src/web/src/adapters-panel.ts +0 -288
- package/src/web/src/assistant.ts +0 -451
- package/src/web/src/chat.ts +0 -1057
- package/src/web/src/composer.ts +0 -959
- package/src/web/src/dataset.ts +0 -132
- package/src/web/src/finetune.ts +0 -267
- package/src/web/src/hub.ts +0 -428
- package/src/web/src/main.ts +0 -98
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +0 -572
- package/src/web/src/model-picker.ts +0 -159
- package/src/web/src/palette.ts +0 -346
- package/src/web/src/protocol.ts +0 -26
- package/src/web/src/quantize.ts +0 -167
- package/src/web/src/rag.ts +0 -274
- package/src/web/src/sessions.ts +0 -469
- package/src/web/src/shell.ts +0 -804
- package/src/web/src/ui-catalog.ts +0 -78
- package/src/web/vendor/README.md +0 -61
- package/src/web-assets.ts +0 -47
- package/src/web-tools.ts +0 -478
- package/src/weights.ts +0 -255
- /package/src/{serve → server}/completion-sink.ts +0 -0
- /package/src/web/{icon.svg → public/icon.svg} +0 -0
- /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
- /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
|
@@ -1,496 +0,0 @@
|
|
|
1
|
-
import { AdmissionPool } from "../engine/admission";
|
|
2
|
-
import { acquireReservation } from "./preparation";
|
|
3
|
-
import { cleanupFailure, disposeResources } from "../engine/resources";
|
|
4
|
-
// GenerationGateway is the scheduling seam between CompletionExecutor and
|
|
5
|
-
// the inference runtime. It declares one mechanism per request: the preserved
|
|
6
|
-
// strict/dedicated serial executor, or the continuous scheduler (`--batch N`).
|
|
7
|
-
// The scheduler itself chooses its B=1 fast path or B=N step from its active
|
|
8
|
-
// row count; placement does not predict a batch size. The executor owns each
|
|
9
|
-
// request's semantic token sink and passes its callback plus one immutable
|
|
10
|
-
// placement into run(). Each request keeps its own callback, so the scheduler
|
|
11
|
-
// can fan tokens out to the matching response stream.
|
|
12
|
-
//
|
|
13
|
-
// The two lanes are MUTUALLY EXCLUSIVE on the GPU (and on shared model state
|
|
14
|
-
// like loraState, which generate() mutates per-generation assuming a serialized
|
|
15
|
-
// queue). One AsyncMutex enforces it: a serial run holds it for its duration;
|
|
16
|
-
// the scheduler holds it for its whole active period (first admit → batch
|
|
17
|
-
// empties). So batched requests run concurrently with EACH OTHER (the point),
|
|
18
|
-
// but never alongside a serial-lane generation. A non-batchable request DRAINS
|
|
19
|
-
// the batch: while any serial-lane request is waiting, the scheduler stops
|
|
20
|
-
// admitting new rows (admissionHeld), finishes the running ones, and releases
|
|
21
|
-
// the mutex; the serial request runs solo, then kick() resumes admission.
|
|
22
|
-
// (mlx-lm's drain_batch semantics — without this, sustained batchable traffic
|
|
23
|
-
// starves the serial lane forever.) Non-generation GPU/model-state work (the
|
|
24
|
-
// curve endpoints, adapter mount/unmount) goes through runExclusive() so there
|
|
25
|
-
// is exactly ONE mutual-exclusion domain.
|
|
26
|
-
//
|
|
27
|
-
// Batchable gate (the rest → serial): batch>1 AND every model cache is a
|
|
28
|
-
// dynamic-B-capable built-in type or implements BatchableCache (mirrors mlx-lm
|
|
29
|
-
// server.py's all-caches-have-merge check). GLM's capability owns compressed
|
|
30
|
-
// MLA/DSA merge/extract/filter and byte projection; Qwen3.5's SSM cache owns
|
|
31
|
-
// its row state. The remaining request-shape exclusions include vision, LoRA,
|
|
32
|
-
// serial-only KV modes
|
|
33
|
-
// (reproducibility ⇒ solo, matching mlx-lm's _is_batchable). Temperature /
|
|
34
|
-
// top-p / top-k DO batch (each row samples with its own seed). Full-attention
|
|
35
|
-
// AND sliding-window (Gemma) models both batch — the scheduler assembles each
|
|
36
|
-
// layer's cache by type. Prompt-cache prefix reuse works on the batch lane
|
|
37
|
-
// too (Phase 3.2): joiners take() at admission; never-merged lone rows put()
|
|
38
|
-
// back zero-copy on finish; merged rows with ≥256 prompt tokens are extracted
|
|
39
|
-
// and put back by BatchScheduler.#extractAndPut (see docs/design/batching.md).
|
|
40
|
-
|
|
41
|
-
import { MlxArray } from "../mlx/array";
|
|
42
|
-
import type { RuntimeModel } from "../model/factory";
|
|
43
|
-
import type { GenerateOptions, GenerateStats, TokenLogprobs } from "../generate";
|
|
44
|
-
import type { KvScheme } from "../kv-scheme";
|
|
45
|
-
import { createRowSampling } from "../backends/mlx/row-sampling";
|
|
46
|
-
import { makeStepSampler } from "../sampler";
|
|
47
|
-
import type { RowPromptCache } from "../backends/mlx/batch-group";
|
|
48
|
-
import { bindMlxGateway, type MlxGatewayBinding, type MlxBatchGroup } from "../backends/mlx/gateway-binding";
|
|
49
|
-
import type { RuntimeConfig } from "../runtime-config";
|
|
50
|
-
import type { ExecutionRequirements, ResolvedExecution } from "../contracts/execution";
|
|
51
|
-
import type { PromptResponseTrace } from "./prompt-response-trace";
|
|
52
|
-
|
|
53
|
-
/** Async mutex: acquire() resolves to a release fn; releases run FIFO. */
|
|
54
|
-
class AsyncMutex {
|
|
55
|
-
#tail: Promise<void> = Promise.resolve();
|
|
56
|
-
/** Holders + waiters. > 0 means somebody owns or wants the engine. */
|
|
57
|
-
#pending = 0;
|
|
58
|
-
get locked(): boolean {
|
|
59
|
-
return this.#pending > 0;
|
|
60
|
-
}
|
|
61
|
-
acquire(signal?: AbortSignal): Promise<() => void> {
|
|
62
|
-
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
63
|
-
this.#pending++;
|
|
64
|
-
let release!: () => void;
|
|
65
|
-
const gate = new Promise<void>((r) => { release = r; });
|
|
66
|
-
const wait = this.#tail;
|
|
67
|
-
this.#tail = this.#tail.then(() => gate);
|
|
68
|
-
let released = false;
|
|
69
|
-
const unlock = () => {
|
|
70
|
-
if (released) return; // idempotent: a double release must not skew #pending
|
|
71
|
-
released = true;
|
|
72
|
-
this.#pending--;
|
|
73
|
-
release();
|
|
74
|
-
};
|
|
75
|
-
return new Promise((resolve, reject) => {
|
|
76
|
-
let settled = false;
|
|
77
|
-
const abort = () => {
|
|
78
|
-
if (settled) return;
|
|
79
|
-
settled = true;
|
|
80
|
-
signal?.removeEventListener("abort", abort);
|
|
81
|
-
// Release this waiter's gate, not its predecessor's. Later acquirers
|
|
82
|
-
// still wait for the active holder, preserving mutual exclusion.
|
|
83
|
-
unlock();
|
|
84
|
-
reject(signal!.reason);
|
|
85
|
-
};
|
|
86
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
87
|
-
wait.then(() => {
|
|
88
|
-
if (settled) return;
|
|
89
|
-
settled = true;
|
|
90
|
-
signal?.removeEventListener("abort", abort);
|
|
91
|
-
resolve(unlock);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** Embeddings-prefill payload for media prompts (vision and/or audio — the
|
|
98
|
-
* name predates audio). Any request carrying one routes to the serial lane
|
|
99
|
-
* (shape.hasVision) and prefills through generate()'s promptEmbeddings
|
|
100
|
-
* path, bypassing the prompt cache. */
|
|
101
|
-
export type Vision = {
|
|
102
|
-
embeddings: MlxArray;
|
|
103
|
-
/** bool [L] image-token mask for the bidirectional attention overlay.
|
|
104
|
-
* Absent when the prompt carries ANY audio — audio(-containing) prompts
|
|
105
|
-
* run fully causal (docs/design/generic-model-support.md §3.3 Q1). */
|
|
106
|
-
imageMask?: MlxArray;
|
|
107
|
-
/** bool [L] union multimodal soft-token mask (image | audio) for
|
|
108
|
-
* per-layer-input id zeroing. Absent on the legacy vision-only shape,
|
|
109
|
-
* where zeroing falls back to imageMask. */
|
|
110
|
-
multimodalMask?: MlxArray;
|
|
111
|
-
/** Qwen3.5/3.8 vision: the request's mRoPE positions + decode delta,
|
|
112
|
-
* installed on the model for exactly this serial run (server-side). */
|
|
113
|
-
mrope?: import("../model/qwen3-mrope").MropeRequestState;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
/** Per-token sink: returning `false` halts this generation (stop sequence).
|
|
117
|
-
* `logprobs` is populated on either lane when the request asked for
|
|
118
|
-
* logprobs capture (GenerateOptions.logprobs / topLogprobs). */
|
|
119
|
-
export type OnToken = (
|
|
120
|
-
token: number,
|
|
121
|
-
logprobs?: TokenLogprobs,
|
|
122
|
-
) => void | boolean | Promise<void | boolean>;
|
|
123
|
-
|
|
124
|
-
/** The serial lane — exactly today's runGeneration (prompt-cache reuse + the
|
|
125
|
-
* generate() pipeline). The gateway calls it under the mutex. */
|
|
126
|
-
export type SerialRun = (
|
|
127
|
-
promptIds: number[],
|
|
128
|
-
options: GenerateOptions & { stopSequences?: string[] },
|
|
129
|
-
onToken: OnToken,
|
|
130
|
-
vision?: Vision,
|
|
131
|
-
trace?: PromptResponseTrace,
|
|
132
|
-
execution?: ResolvedExecution,
|
|
133
|
-
) => Promise<GenerateStats>;
|
|
134
|
-
|
|
135
|
-
/** What the batchable decision needs from a request (cheap to compute). */
|
|
136
|
-
export interface RequestShape extends ExecutionRequirements {}
|
|
137
|
-
|
|
138
|
-
export type GenerationMechanism = "serial" | "continuous";
|
|
139
|
-
|
|
140
|
-
/** One immutable scheduling declaration for one exact request shape.
|
|
141
|
-
* `continuous` means scheduler admission, not that another row is present. */
|
|
142
|
-
export interface GenerationPlacement {
|
|
143
|
-
readonly shape: RequestShape;
|
|
144
|
-
readonly mechanism: GenerationMechanism;
|
|
145
|
-
readonly execution?: ResolvedExecution;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function disposeUnstartedRequest(options: GenerateOptions, vision?: Vision): void {
|
|
149
|
-
disposeResources([options.grammar, vision?.embeddings, vision?.imageMask,
|
|
150
|
-
vision?.multimodalMask, options.visionPixels].filter((resource) => resource != null));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export class GenerationGateway {
|
|
154
|
-
#closed = false;
|
|
155
|
-
readonly #runtime: RuntimeConfig;
|
|
156
|
-
readonly #binding: MlxGatewayBinding;
|
|
157
|
-
readonly #requests: AdmissionPool;
|
|
158
|
-
readonly #mutex = new AsyncMutex();
|
|
159
|
-
readonly #batch: number;
|
|
160
|
-
#scheduler: MlxBatchGroup | null = null;
|
|
161
|
-
#rowsSubmitted = 0;
|
|
162
|
-
/** Serial-lane requests waiting for / holding the mutex. While > 0 the
|
|
163
|
-
* scheduler pauses admission (drain) so they can't be starved. */
|
|
164
|
-
#serialWaiters = 0;
|
|
165
|
-
/** Lazy, memoized: can this model's caches do the dynamic-B ops? */
|
|
166
|
-
#cacheBatchable: boolean | null = null;
|
|
167
|
-
/** Lazy, memoized: can the configured KV scheme convert every named cache? */
|
|
168
|
-
#kvSchemeBatchable: boolean | null = null;
|
|
169
|
-
constructor(
|
|
170
|
-
model: RuntimeModel | MlxGatewayBinding,
|
|
171
|
-
batch: number,
|
|
172
|
-
private readonly serialRun: SerialRun,
|
|
173
|
-
private readonly opts: {
|
|
174
|
-
kvBudgetBytes?: number;
|
|
175
|
-
checkpoints?: boolean;
|
|
176
|
-
stateCodecs?: import("../kv-store").CacheCodecProvider;
|
|
177
|
-
/** The server-wide KV scheme (server.ts kvScheme) — threaded to the
|
|
178
|
-
* scheduler at construction when batchable (Phase 3.1). turboQuant is
|
|
179
|
-
* never threaded to the scheduler (always solo-only — see placement);
|
|
180
|
-
* it's here only so the gateway can see it's active. */
|
|
181
|
-
kvScheme?: KvScheme;
|
|
182
|
-
/** The server's prompt cache (Phase 3.2): batch-lane joiners take()
|
|
183
|
-
* the longest usable prefix at admission; never-merged rows put()
|
|
184
|
-
* back on finish. Safe to share with the serial lane — both use it
|
|
185
|
-
* only inside this gateway's mutual-exclusion domain. */
|
|
186
|
-
promptCache?: RowPromptCache;
|
|
187
|
-
adapterNamespace?: (adapters: string[]) => string;
|
|
188
|
-
} = {},
|
|
189
|
-
) {
|
|
190
|
-
this.#binding = "createBatchGroup" in model ? model : bindMlxGateway(model);
|
|
191
|
-
this.#runtime = this.#binding.runtime;
|
|
192
|
-
this.opts = Object.freeze({ ...opts });
|
|
193
|
-
this.#batch = Math.max(1, Math.floor(batch));
|
|
194
|
-
this.#requests = new AdmissionPool(this.#batch);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** True if `--batch N` (N>1) is on (batchability is then per-request). */
|
|
198
|
-
get batchingEnabled(): boolean {
|
|
199
|
-
return this.batchMode === "batch";
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** Truthful configured/model-capability mode for stats and discovery. */
|
|
203
|
-
get batchMode(): "off" | "serial" | "batch" {
|
|
204
|
-
if (this.#batch <= 1) return "off";
|
|
205
|
-
return this.#modelCachesBatchable() ? "batch" : "serial";
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** Rows currently decoding in the batch (0 if no scheduler / idle). */
|
|
209
|
-
get activeRows(): number {
|
|
210
|
-
return this.#scheduler?.activeRows ?? 0;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** Queued + mid-prefill rows waiting behind the batch (0 when idle). */
|
|
214
|
-
get pendingRows(): number {
|
|
215
|
-
return this.#scheduler?.pendingRows ?? 0;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/** True while ANY engine work is active or queued, on EITHER lane: the
|
|
219
|
-
* mutex is held/awaited (a serial generation, the batch scheduler's whole
|
|
220
|
-
* active period, curve endpoints, adapter mounts) or batch rows are
|
|
221
|
-
* running/pending. activeRows/pendingRows alone MISS the serial lane —
|
|
222
|
-
* a serial generation holds the mutex but shows zero rows. */
|
|
223
|
-
get busy(): boolean {
|
|
224
|
-
return this.#requests.active > 0 || this.#requests.queued > 0 ||
|
|
225
|
-
this.#mutex.locked || this.activeRows > 0 || this.pendingRows > 0;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
async close(): Promise<void> {
|
|
229
|
-
this.#closed = true;
|
|
230
|
-
this.#requests.close();
|
|
231
|
-
await this.#scheduler?.close();
|
|
232
|
-
await this.onIdle();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Observe idleness. Call runWhenIdle for background work that must also
|
|
236
|
-
* acquire ownership atomically with the idle check. */
|
|
237
|
-
async onIdle(pollMs = 20): Promise<void> {
|
|
238
|
-
while (this.busy) await new Promise<void>((r) => setTimeout(r, pollMs));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** Background work waits without requesting a batch drain. The final busy
|
|
242
|
-
* check and mutex acquisition have no await between them, so a foreground
|
|
243
|
-
* request cannot enter between the check and ownership registration. */
|
|
244
|
-
async runWhenIdle<T>(fn: () => Promise<T>, pollMs = 20): Promise<T> {
|
|
245
|
-
while (this.busy) await new Promise<void>(resolve => setTimeout(resolve, pollMs));
|
|
246
|
-
return this.runExclusive(fn);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/** Cumulative rows routed to the batch lane since server start. The serial
|
|
250
|
-
* lane never advances this — /stats' race-free lane-routing observable
|
|
251
|
-
* (active/pending are instantaneous and read 0 once a request finishes). */
|
|
252
|
-
get submittedRows(): number {
|
|
253
|
-
return this.#rowsSubmitted;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/** Projected aggregate KV bytes of admitted rows / the --kv-budget cap. */
|
|
257
|
-
get kvBytes(): { projected: number; budget: number | null } {
|
|
258
|
-
return {
|
|
259
|
-
projected: this.#scheduler?.projectedKvBytes ?? 0,
|
|
260
|
-
budget: this.#scheduler?.kvBudgetBytes ?? this.opts.kvBudgetBytes ?? null,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
#modelCachesBatchable(): boolean {
|
|
265
|
-
return this.#cacheBatchable ??= this.#binding.cachesBatchable();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
#kvBatchable(): boolean {
|
|
269
|
-
return this.#kvSchemeBatchable ??= !!this.opts.kvScheme && this.#binding.kvBatchable(this.opts.kvScheme);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
place(shape: RequestShape, options: GenerateOptions = {}): GenerationPlacement {
|
|
273
|
-
const frozenShape = Object.freeze(shape);
|
|
274
|
-
const execution = this.#binding.plan(frozenShape, options, {
|
|
275
|
-
continuous: this.batchingEnabled,
|
|
276
|
-
quantizedBatch: (shape.kvQuant || shape.turboQuant) && this.#kvBatchable(),
|
|
277
|
-
checkpoints: this.opts.checkpoints === true,
|
|
278
|
-
});
|
|
279
|
-
return Object.freeze({ shape: frozenShape, mechanism: execution.mechanism, execution });
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** Run `fn` with exclusive ownership of the GPU + shared model state (the
|
|
283
|
-
* serial lane's lock). THE single mutual-exclusion domain: the serial
|
|
284
|
-
* generation path, the curve /generate + /signal endpoints, and adapter
|
|
285
|
-
* mount/unmount all come through here, so nothing runs concurrently with
|
|
286
|
-
* batched decode steps (or with each other). Registers as a serial waiter
|
|
287
|
-
* so the scheduler drains (stops admitting) until `fn` has run. */
|
|
288
|
-
/** Shared by inference, preparation and managed GPU subprocesses. */
|
|
289
|
-
async acquireExecutionLease(
|
|
290
|
-
signal?: AbortSignal,
|
|
291
|
-
trace?: PromptResponseTrace,
|
|
292
|
-
): Promise<import("../contracts/resources").DisposableResource> {
|
|
293
|
-
if (this.#closed) throw new Error("generation gateway is closed");
|
|
294
|
-
this.#serialWaiters++;
|
|
295
|
-
const closeAdmission = trace?.begin("engine.admission_wait", { mechanism: "serial" });
|
|
296
|
-
const resume = () => {
|
|
297
|
-
this.#serialWaiters--;
|
|
298
|
-
if (this.#serialWaiters === 0) this.#scheduler?.kick();
|
|
299
|
-
};
|
|
300
|
-
try {
|
|
301
|
-
const release = await this.#mutex.acquire(signal);
|
|
302
|
-
let released = false;
|
|
303
|
-
return { dispose: () => {
|
|
304
|
-
if (released) return;
|
|
305
|
-
released = true;
|
|
306
|
-
release(); resume();
|
|
307
|
-
} };
|
|
308
|
-
} catch (error) { resume(); throw error; }
|
|
309
|
-
finally { closeAdmission?.(); }
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
async runExclusive<T>(
|
|
313
|
-
fn: () => Promise<T>,
|
|
314
|
-
trace?: PromptResponseTrace,
|
|
315
|
-
signal?: AbortSignal,
|
|
316
|
-
): Promise<T> {
|
|
317
|
-
const lease = await this.acquireExecutionLease(signal, trace);
|
|
318
|
-
try { return await fn(); } finally { lease.dispose(); }
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/** Run one generation on the appropriate lane. onToken is invoked per emitted
|
|
322
|
-
* token (its `false` halts); resolves with stats when the generation ends. */
|
|
323
|
-
async run(
|
|
324
|
-
promptIds: number[],
|
|
325
|
-
options: GenerateOptions & { stopSequences?: string[] },
|
|
326
|
-
onToken: OnToken,
|
|
327
|
-
vision: Vision | undefined,
|
|
328
|
-
shape: RequestShape,
|
|
329
|
-
placement: GenerationPlacement,
|
|
330
|
-
signal?: AbortSignal,
|
|
331
|
-
trace?: PromptResponseTrace,
|
|
332
|
-
): Promise<GenerateStats> {
|
|
333
|
-
let reservation;
|
|
334
|
-
try { reservation = await acquireReservation(this.#requests, signal); }
|
|
335
|
-
catch (error) { cleanupFailure(error, () => disposeUnstartedRequest(options, vision)); }
|
|
336
|
-
try { return await this.#run(promptIds, options, onToken, vision, shape, placement, signal, trace); }
|
|
337
|
-
finally { reservation.dispose(); }
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
async #run(
|
|
341
|
-
promptIds: number[],
|
|
342
|
-
options: GenerateOptions & { stopSequences?: string[] },
|
|
343
|
-
onToken: OnToken,
|
|
344
|
-
vision: Vision | undefined,
|
|
345
|
-
shape: RequestShape,
|
|
346
|
-
placement: GenerationPlacement,
|
|
347
|
-
signal?: AbortSignal,
|
|
348
|
-
trace?: PromptResponseTrace,
|
|
349
|
-
): Promise<GenerateStats> {
|
|
350
|
-
const disposeUnstarted = () => disposeUnstartedRequest(options, vision);
|
|
351
|
-
if (placement.shape !== shape) {
|
|
352
|
-
disposeUnstarted();
|
|
353
|
-
throw new Error("generation placement does not belong to this request shape");
|
|
354
|
-
}
|
|
355
|
-
try {
|
|
356
|
-
signal?.throwIfAborted();
|
|
357
|
-
} catch (e) {
|
|
358
|
-
// The gateway is the first component that accepts ownership of a
|
|
359
|
-
// compiled controller. An already-aborted request reaches neither lane.
|
|
360
|
-
disposeUnstarted();
|
|
361
|
-
throw e;
|
|
362
|
-
}
|
|
363
|
-
if (placement.mechanism === "serial") {
|
|
364
|
-
// Serial decode is an unbroken microtask chain (FFI + generator
|
|
365
|
-
// resumes): without a periodic macrotask hop the event loop starves for
|
|
366
|
-
// the WHOLE generation — /stats, /health, and new-connection accepts
|
|
367
|
-
// stall until the request finishes (measured 2.5 s on a 512-token cpm5
|
|
368
|
-
// run). Rate-limited to ≥25 ms — the SSE flush hop's budget, ~0.1% of
|
|
369
|
-
// decode — and applied HERE so every serial caller (streaming or not,
|
|
370
|
-
// all four API surfaces) is covered. The batch lane needs nothing: its
|
|
371
|
-
// drive loop yields per step (measured /stats ~8 ms mid-generation).
|
|
372
|
-
let lastHop = performance.now();
|
|
373
|
-
const hop = (): Promise<void> => new Promise<void>((r) => setImmediate(r));
|
|
374
|
-
const hoppingOnToken: OnToken = (token, lp) => {
|
|
375
|
-
signal?.throwIfAborted();
|
|
376
|
-
const r = onToken(token, lp);
|
|
377
|
-
if (r === false) return false;
|
|
378
|
-
if (performance.now() - lastHop < 25) return r;
|
|
379
|
-
lastHop = performance.now();
|
|
380
|
-
if (r instanceof Promise)
|
|
381
|
-
return r.then(async (v) => {
|
|
382
|
-
if (v === false) return false;
|
|
383
|
-
signal?.throwIfAborted();
|
|
384
|
-
await hop();
|
|
385
|
-
signal?.throwIfAborted();
|
|
386
|
-
return v;
|
|
387
|
-
});
|
|
388
|
-
return hop().then(() => {
|
|
389
|
-
signal?.throwIfAborted();
|
|
390
|
-
return r;
|
|
391
|
-
});
|
|
392
|
-
};
|
|
393
|
-
let started = false;
|
|
394
|
-
return this.runExclusive(async () => {
|
|
395
|
-
signal?.throwIfAborted();
|
|
396
|
-
started = true;
|
|
397
|
-
const stats = await this.serialRun(
|
|
398
|
-
promptIds, signal ? { ...options, signal } : options, hoppingOnToken, vision, trace, placement.execution,
|
|
399
|
-
);
|
|
400
|
-
signal?.throwIfAborted();
|
|
401
|
-
return stats;
|
|
402
|
-
}, trace, signal)
|
|
403
|
-
// Covers a serial waiter aborted before serialRun takes ownership.
|
|
404
|
-
// generate() also disposes defensively; the operation is idempotent.
|
|
405
|
-
.finally(() => {
|
|
406
|
-
if (started) options.grammar?.dispose();
|
|
407
|
-
else disposeUnstarted();
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const adapters = options.adapters?.length ? [...options.adapters] : undefined;
|
|
412
|
-
const adapterKey = adapters ? JSON.stringify(adapters) : "";
|
|
413
|
-
const cacheNamespace = adapters
|
|
414
|
-
? () => this.opts.adapterNamespace?.(adapters) ?? adapterKey : "";
|
|
415
|
-
const context = adapters
|
|
416
|
-
? this.#binding.bindAdapterContext?.(adapters, `adapters:${adapterKey}`) : undefined;
|
|
417
|
-
|
|
418
|
-
// The scheduler owns grammar ready/accept sequencing. StepSampler owns the
|
|
419
|
-
// shared processors -> mask -> logprobs -> sample -> history contract.
|
|
420
|
-
const method = this.#binding.methodRequest?.(placement.execution, options);
|
|
421
|
-
const continuation = method ? undefined : this.#binding.continuationRequest?.(placement.execution, options, promptIds, onToken);
|
|
422
|
-
const sampling = method ? undefined : continuation ?? createRowSampling(makeStepSampler(options, {
|
|
423
|
-
tokenRepresentation: "device", grammarWait: "external",
|
|
424
|
-
historyUpdate: "after-sample", initialHistory: promptIds,
|
|
425
|
-
captureSelectedLogprob: options.logprobs === true,
|
|
426
|
-
captureTopLogprobs: options.topLogprobs,
|
|
427
|
-
}), onToken);
|
|
428
|
-
|
|
429
|
-
let st;
|
|
430
|
-
this.#rowsSubmitted++;
|
|
431
|
-
const closeAdmission = trace?.begin("engine.admission_wait", {
|
|
432
|
-
mechanism: "continuous",
|
|
433
|
-
});
|
|
434
|
-
try {
|
|
435
|
-
st = await this.#ensureScheduler().submit({
|
|
436
|
-
promptIds, context, cacheNamespace, prefillChunkSize: options.prefillChunkSize,
|
|
437
|
-
continuation: continuation?.continuation,
|
|
438
|
-
statePolicy: this.#binding.statePolicy?.(placement.execution, options, promptIds.length + (options.maxTokens ?? 512)),
|
|
439
|
-
compiledDecode: placement.execution?.compiledDecode,
|
|
440
|
-
maxTokens: options.maxTokens ?? 512,
|
|
441
|
-
eosTokenIds: options.eosTokenIds ?? this.#binding.config.eosTokenIds,
|
|
442
|
-
...(method ? { method, onToken } : { sample: sampling!.sample,
|
|
443
|
-
plainGreedy: sampling!.plainGreedy, onToken: sampling!.onToken }),
|
|
444
|
-
onAdmitted: closeAdmission,
|
|
445
|
-
trace,
|
|
446
|
-
...(signal ? { signal } : {}),
|
|
447
|
-
// B1: pass the per-row grammar controller through. The scheduler drives
|
|
448
|
-
// accept/ready/terminate; this gateway OWNS disposal (finally below)
|
|
449
|
-
// across resolve, reject, eviction, and the whole-batch-drop error path.
|
|
450
|
-
...(options.grammar ? { grammar: options.grammar } : {}),
|
|
451
|
-
// Stable cache boundary → the scheduler's trim-free prompt-prefix
|
|
452
|
-
// snapshot (same invariant as the serial lane's snapshotAt).
|
|
453
|
-
...(options.snapshotAt !== undefined ? { snapshotAt: options.snapshotAt } : {}),
|
|
454
|
-
});
|
|
455
|
-
} finally {
|
|
456
|
-
closeAdmission?.();
|
|
457
|
-
sampling?.dispose();
|
|
458
|
-
// The scheduler never owns per-row grammar state.
|
|
459
|
-
options.grammar?.dispose();
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return {
|
|
463
|
-
promptTokens: st.promptTokens,
|
|
464
|
-
cachedTokens: st.cachedTokens,
|
|
465
|
-
generatedTokens: st.generatedTokens,
|
|
466
|
-
finishReason: st.finishReason,
|
|
467
|
-
prefillMs: st.prefillMs,
|
|
468
|
-
decodeMs: st.decodeMs,
|
|
469
|
-
prefillTps: st.prefillMs > 0 ? ((st.promptTokens - st.cachedTokens) / st.prefillMs) * 1000 : 0,
|
|
470
|
-
decodeTps: st.decodeMs > 0 && st.generatedTokens > 1 ? ((st.generatedTokens - 1) / st.decodeMs) * 1000 : 0,
|
|
471
|
-
cacheTokens: [],
|
|
472
|
-
...(st.spec ? { spec: st.spec } : {}),
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
#ensureScheduler(): MlxBatchGroup {
|
|
477
|
-
if (!this.#scheduler)
|
|
478
|
-
this.#scheduler = this.#binding.createBatchGroup({
|
|
479
|
-
runtime: this.#runtime,
|
|
480
|
-
maxBatch: this.#batch,
|
|
481
|
-
stateCodecs: this.opts.stateCodecs,
|
|
482
|
-
kvBudgetBytes: this.opts.kvBudgetBytes,
|
|
483
|
-
// Phase 3.1: the batchable kvConfig composition is applied by the
|
|
484
|
-
// scheduler (solo rows convert at serial chunk boundaries, then
|
|
485
|
-
// merge as quantized triples). Only threaded when the scheme
|
|
486
|
-
// passed #kvBatchable — otherwise those requests never reach here.
|
|
487
|
-
kvScheme: this.#kvBatchable() ? this.opts.kvScheme : undefined,
|
|
488
|
-
promptCache: this.opts.promptCache,
|
|
489
|
-
lock: { acquire: () => this.#mutex.acquire() },
|
|
490
|
-
// Drain: pause admission while any serial-lane request waits; the
|
|
491
|
-
// runExclusive finally-block kick()s the loop back awake.
|
|
492
|
-
admissionHeld: () => this.#serialWaiters > 0,
|
|
493
|
-
});
|
|
494
|
-
return this.#scheduler;
|
|
495
|
-
}
|
|
496
|
-
}
|