mlx-bun 0.5.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 +1449 -109
- 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 +7 -5
- 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 +10 -10
- package/src/{serve → server}/chat-stage.ts +14 -14
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +33 -41
- 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 +25 -82
- 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 +6 -8
- package/src/{serve → server}/request-prep.ts +47 -50
- 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 -107
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +0 -3617
- 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/release-notes-v0.4.0.md +0 -45
- package/docs/archive/planning/release-notes-v0.5.0.md +0 -37
- 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 -2054
- package/docs/design/decode-speed-program.md +0 -2404
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -821
- package/docs/design/kv-cache.md +0 -993
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -2129
- package/docs/design/turboquant.md +0 -2225
- package/docs/design/unified-engine-frontier-plan.md +0 -1987
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -593
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/public-readiness-handoff.md +0 -244
- package/docs/planning/public-readiness.md +0 -149
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3587
- package/docs/reference/cli.md +0 -646
- package/docs/reference/distribution.md +0 -380
- package/docs/reference/environment.md +0 -494
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -688
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -346
- package/docs/reference/server-api.md +0 -1945
- package/docs/reference/server-config.md +0 -973
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/audiotoolbox.ts +0 -112
- package/src/audio/conformer.ts +0 -655
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/mic-capture.ts +0 -98
- package/src/audio/silero-vad.ts +0 -379
- package/src/audio/transcode.ts +0 -67
- package/src/audio/whisper-decode.ts +0 -774
- package/src/audio/whisper-fast.ts +0 -732
- package/src/audio/whisper-format.ts +0 -73
- package/src/audio/whisper-mel.ts +0 -185
- package/src/audio/whisper-timing.ts +0 -274
- package/src/audio/whisper-tokenizer.ts +0 -239
- package/src/audio/whisper-transcribe.ts +0 -410
- 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 -129
- package/src/backends/mlx/batch-group.ts +0 -1874
- 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 -107
- 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/encoder-cache.ts +0 -25
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -58
- package/src/backends/mlx/fill-group.ts +0 -497
- 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 -174
- 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 -161
- 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/mixed-iteration.ts +0 -62
- package/src/backends/mlx/model-prompt.ts +0 -178
- package/src/backends/mlx/model-serving.ts +0 -80
- package/src/backends/mlx/paged-cache-codec.ts +0 -27
- package/src/backends/mlx/prefill-cohort.ts +0 -100
- package/src/backends/mlx/prefill-policy.ts +0 -26
- package/src/backends/mlx/prefill-rows.ts +0 -244
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/prompt-input.ts +0 -29
- package/src/backends/mlx/qwen-prompt-input.ts +0 -40
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -54
- package/src/backends/mlx/rollback.ts +0 -92
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -251
- package/src/backends/mlx/speculative-group.ts +0 -438
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -131
- 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 -173
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3490
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -70
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/object-cache.ts +0 -8
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -261
- package/src/contracts/prefix-cache.ts +0 -33
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -54
- 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 -64
- package/src/engine/execution-tasks.ts +0 -44
- package/src/engine/namespaced-cache.ts +0 -13
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -92
- 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 -463
- 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 -1352
- package/src/grammar.ts +0 -604
- 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 -45
- 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 -279
- package/src/kv-store.ts +0 -1135
- package/src/lab/README.md +0 -22
- 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-attention.ts +0 -117
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -111
- package/src/lab/paged-kv/paged-kv.ts +0 -336
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -54
- 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 -425
- 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 -531
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/normalized-argmax.ts +0 -116
- package/src/mlx/ops.ts +0 -1108
- 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 -94
- 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 -57
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -215
- package/src/model/fingerprint.ts +0 -45
- 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 -2370
- package/src/model/gemma4.ts +0 -1395
- 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 -70
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -468
- package/src/model/quantized-append-attention.ts +0 -31
- 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 -250
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -881
- 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 -110
- package/src/model/token-groups.ts +0 -66
- 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 -89
- 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/model/whisper.ts +0 -435
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native/mic_capture.swift +0 -92
- package/src/native-pack.ts +0 -163
- 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 -1940
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -682
- 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 -77
- package/src/safetensors.ts +0 -165
- package/src/sampler.ts +0 -1012
- 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/audio-routes.ts +0 -323
- 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 -537
- 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 -49
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -161
- 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/serve/transcription-server.ts +0 -64
- package/src/serve/transcription-service.ts +0 -502
- package/src/server.ts +0 -1282
- package/src/spec/assistant-rows.ts +0 -93
- 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 -318
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -226
- 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 -230
- package/src/spec/qwen-mtp-source.ts +0 -386
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -587
- package/src/spec/source.ts +0 -228
- package/src/spec/two-model-rows.ts +0 -62
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -431
- package/src/ssd-durability.ts +0 -209
- package/src/storage/host-buffer.ts +0 -24
- package/src/storage/kv-writer.ts +0 -83
- package/src/storage/kv-writer.worker.js +0 -264
- package/src/storage/retention-policy.ts +0 -37
- package/src/tiered-prompt-cache.ts +0 -45
- 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 -176
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -409
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -233
- package/src/vision/qwen3vl-tower.ts +0 -566
- package/src/vision/siglip.ts +0 -607
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2155
- package/src/web/app.js +0 -5863
- 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 -1060
- package/src/web/src/composer.ts +0 -962
- 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/src/voice.ts +0 -141
- 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/{serve → server}/generated-token-history.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
package/src/lab/README.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# src/lab — quarantined, no-oracle code
|
|
2
|
-
|
|
3
|
-
Everything here is a Lab-tier module (docs/design/unified-engine-frontier-plan.md):
|
|
4
|
-
no external oracle, off by default, kept only while a measurement decides its
|
|
5
|
-
fate (PLAN.md "Maintainability program", D6 darlings). Rules, gate-enforced by
|
|
6
|
-
`scripts/check-hygiene.ts` (check 11):
|
|
7
|
-
|
|
8
|
-
- nothing outside `src/lab/` may import from `src/lab/` except the edges listed
|
|
9
|
-
in `LAB_IMPORT_ALLOWLIST` — those are recorded debt, not permission;
|
|
10
|
-
- a new production dependency on a Lab module is a decision, not a default:
|
|
11
|
-
either promote the module out of the lab with an oracle/measurement, or
|
|
12
|
-
route it through an option seam.
|
|
13
|
-
|
|
14
|
-
| module | flag / entry | oracle |
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| `curve/` (curve sampler + designer page) | `--curve-*`, `/curves` | none (Lab) |
|
|
17
|
-
| `paged-kv/` | `--paged-kv`; direct read via `MLX_BUN_PAGED_ATTN` | gathered storage is bit-exact; direct Metal is tolerance-tested, with paired M1/M4 measurements in benchmarks.md |
|
|
18
|
-
| `expert-trace/` | `MLX_BUN_EXPERT_TRACE` hook in gemma4 | closed study (expert-offload) |
|
|
19
|
-
|
|
20
|
-
The optional paged layout has a separate backend persistence codec. Its
|
|
21
|
-
allowlisted import keeps `kv-store` independent of row-execution modules and
|
|
22
|
-
preserves RAM/SSD reuse without promoting direct-attention numerics to L1.
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8">
|
|
2
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
3
|
-
<title>HLG Curve Designer</title>
|
|
4
|
-
<style>
|
|
5
|
-
:root{--text:#1f2937;--text2:#475569;--text3:#94a3b8;--bg:#f7f9fc;--card:#fff;--bd:#e2e8f0;
|
|
6
|
-
--accent:#2563eb;--accent2:#0891b2;--pos:#16a34a;--warn:#d97706;--danger:#dc2626;--grid:#eef2f7;}
|
|
7
|
-
*{box-sizing:border-box}
|
|
8
|
-
body{margin:0;background:var(--bg);color:var(--text);font:13.5px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
|
|
9
|
-
.wrap{max-width:1240px;margin:0 auto;padding:18px 20px 70px}
|
|
10
|
-
.head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:14px}
|
|
11
|
-
h1{font-size:19px;margin:0;letter-spacing:-.01em}
|
|
12
|
-
.head a.back{font-size:12px;color:var(--accent);text-decoration:none}
|
|
13
|
-
.head .desc{color:var(--text2);font-size:13px}
|
|
14
|
-
.engine{margin-left:auto;display:flex;align-items:center;gap:7px;font-size:12px}
|
|
15
|
-
.engine input{font:12px ui-monospace,Menlo,monospace;border:1px solid var(--bd);border-radius:7px;padding:6px 8px;width:230px;background:var(--card)}
|
|
16
|
-
.engine .dot{width:8px;height:8px;border-radius:50%;background:var(--text3)}
|
|
17
|
-
.engine .dot.ok{background:var(--pos)} .engine .dot.bad{background:var(--danger)}
|
|
18
|
-
.cols{display:grid;grid-template-columns:minmax(440px,1fr) 1fr;gap:18px;align-items:start}
|
|
19
|
-
@media(max-width:920px){.cols{grid-template-columns:1fr}}
|
|
20
|
-
.card{background:var(--card);border:1px solid var(--bd);border-radius:14px;padding:14px 16px;box-shadow:0 1px 2px rgba(15,23,42,.04),0 10px 30px -24px rgba(15,23,42,.2)}
|
|
21
|
-
.card h2{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--text2);margin:0 0 10px;display:flex;align-items:center;gap:10px}
|
|
22
|
-
svg.plot{width:100%;height:auto;display:block;touch-action:none;cursor:crosshair}
|
|
23
|
-
.slopes{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin:10px 0 4px}
|
|
24
|
-
.slopes .s{background:var(--grid);border-radius:9px;padding:6px 8px}
|
|
25
|
-
.slopes .s .k{font-size:9px;text-transform:uppercase;letter-spacing:.03em;color:var(--text3)}
|
|
26
|
-
.slopes .s .v{font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
|
|
27
|
-
.slopes .s .t{font-size:9.5px}
|
|
28
|
-
.copyrow{display:flex;gap:7px;align-items:center;margin-top:12px}
|
|
29
|
-
.copyrow input{flex:1;font:11px ui-monospace,Menlo,monospace;border:1px solid var(--bd);border-radius:7px;padding:7px 8px;background:var(--grid)}
|
|
30
|
-
button.primary{background:var(--accent);color:#fff;border:0;border-radius:9px;padding:9px 16px;font:700 13px inherit;cursor:pointer}
|
|
31
|
-
button.primary:disabled{opacity:.55;cursor:default}
|
|
32
|
-
button.ghost{background:var(--card);border:1px solid var(--bd);border-radius:8px;padding:7px 11px;font:600 12px inherit;color:var(--text2);cursor:pointer}
|
|
33
|
-
.prompt{width:100%;font:13px inherit;border:1px solid var(--bd);border-radius:9px;padding:9px 10px;resize:vertical;min-height:54px;background:var(--card)}
|
|
34
|
-
.pchips{display:flex;gap:6px;flex-wrap:wrap;margin:8px 0}
|
|
35
|
-
.pchips button{font:600 11px/1 inherit;padding:6px 9px;border:1px solid var(--bd);background:var(--grid);border-radius:7px;cursor:pointer;color:var(--text2)}
|
|
36
|
-
.genrow{display:flex;gap:10px;align-items:center;margin:10px 0;flex-wrap:wrap}
|
|
37
|
-
.genrow .mini{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text2)}
|
|
38
|
-
.genrow .mini input{width:56px;font:12px inherit;border:1px solid var(--bd);border-radius:6px;padding:5px 6px}
|
|
39
|
-
.samples{display:flex;flex-direction:column;gap:8px;margin-top:6px}
|
|
40
|
-
.samp{font-size:13.5px;background:var(--grid);border-radius:9px;padding:9px 11px;border-left:3px solid var(--accent);white-space:pre-wrap}
|
|
41
|
-
.samp.junk{border-left-color:var(--danger);background:#fef6f6}
|
|
42
|
-
.samp .tag{font-size:10px;font-weight:700;color:var(--danger);float:right}
|
|
43
|
-
.status{font-size:12px;color:var(--text3);min-height:16px}
|
|
44
|
-
.note{font-size:11.5px;color:var(--text3);margin-top:10px;line-height:1.5}
|
|
45
|
-
.testcard{border:1px solid var(--bd);border-radius:12px;padding:13px 15px;margin:6px 0;background:linear-gradient(180deg,#f4f8ff,#fff)}
|
|
46
|
-
.testcard .opt{font-size:14px;background:var(--card);border:1px solid var(--bd);border-radius:9px;padding:10px 12px;margin:7px 0;cursor:pointer;display:flex;gap:9px;transition:border-color .12s}
|
|
47
|
-
.testcard .opt:hover{border-color:var(--accent2)}
|
|
48
|
-
.testcard .opt .lab{font-weight:800;color:var(--accent2);flex:none}
|
|
49
|
-
.testcard .opt.picked{border-color:var(--accent2);box-shadow:0 0 0 2px rgba(8,145,178,.15)}
|
|
50
|
-
.testcard .opt .reveal{margin-left:auto;font-size:11px;font-weight:700;flex:none;align-self:center}
|
|
51
|
-
.testcard .q{font-size:12.5px;font-weight:600;margin:4px 0 2px}
|
|
52
|
-
.testcard .verdict{font-size:13px;font-weight:700;margin-top:8px;min-height:18px}
|
|
53
|
-
</style></head>
|
|
54
|
-
<body><div class="wrap">
|
|
55
|
-
<div class="head">
|
|
56
|
-
<h1>HLG Curve Designer</h1>
|
|
57
|
-
<a class="back" href="/" id="backLink" style="display:none">← mlx-bun</a>
|
|
58
|
-
<span class="desc">Drag the curve over the signal → generate → read prose → adjust.</span>
|
|
59
|
-
<span class="engine"><span class="dot" id="engdot"></span>engine <input id="engine"></span>
|
|
60
|
-
</div>
|
|
61
|
-
<div class="cols">
|
|
62
|
-
<div class="card">
|
|
63
|
-
<h2>Transfer curve <span style="font-weight:400;text-transform:none;letter-spacing:0;color:var(--text3)">x = p_in, y = p_out (log) · diagonal = temperature 1 · the gray histogram is the real next-token signal</span></h2>
|
|
64
|
-
<svg class="plot" id="plot" viewBox="0 0 460 360"></svg>
|
|
65
|
-
<div class="slopes" id="slopeReadout"></div>
|
|
66
|
-
<div id="baselineHint" style="font-size:11.5px;font-weight:600;margin:4px 0 0"></div>
|
|
67
|
-
<div class="copyrow"><input id="cfgField" readonly><button class="ghost" id="copyBtn">Copy values</button><button class="ghost" id="resetBtn">Reset</button><span id="copyOk" style="color:var(--pos);font-weight:700;font-size:11px"></span></div>
|
|
68
|
-
<div class="note">Five movable control points; drag any of them (including the corners). It always stays a smooth monotone curve. <b>Above the diagonal</b> raises those tokens, <b>below</b> lowers them; drag a point down over the histogram's tail to gate it.</div>
|
|
69
|
-
</div>
|
|
70
|
-
<div class="card">
|
|
71
|
-
<h2>Generate</h2>
|
|
72
|
-
<textarea class="prompt" id="prompt">Write the first sentence of a short story about a lighthouse keeper who discovers something strange in the fog.</textarea>
|
|
73
|
-
<div class="pchips" id="pchips"></div>
|
|
74
|
-
<div class="genrow">
|
|
75
|
-
<button class="primary" id="genBtn">Generate</button>
|
|
76
|
-
<button class="primary" id="testBtn" style="background:var(--accent2)" title="One sentence from the default recipe, one from your curve — unlabeled. Guess which is which.">Test (blind)</button>
|
|
77
|
-
<button class="ghost" id="sigBtn">↻ load signal</button>
|
|
78
|
-
<button class="ghost" id="copyTextBtn" style="display:none">Copy text</button>
|
|
79
|
-
<span class="mini">N <input id="nSamp" type="number" min="1" max="8" value="4"></span>
|
|
80
|
-
<span class="mini">seed <input id="seed" type="number" value="100"></span>
|
|
81
|
-
<span class="status" id="status"></span>
|
|
82
|
-
</div>
|
|
83
|
-
<div id="testArea"></div>
|
|
84
|
-
<div class="samples" id="samples"></div>
|
|
85
|
-
<div class="note">Samples are a <b>feel-check</b>, not evidence — easy to overfit. The blind two-judge eval stays the verdict.</div>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<script>
|
|
90
|
-
const ln=Math.log;
|
|
91
|
-
const UMIN=ln(1e-6); // bottom-left / plot floor (matches src/lab/curve/curve-sampler.ts CURVE_UMIN)
|
|
92
|
-
const ENGINE_BASE = location.protocol.startsWith("http") ? location.origin : "http://localhost:8080";
|
|
93
|
-
// ---- curve state: 5 movable control points, sorted ascending in p_in ----
|
|
94
|
-
function identityPoints(){ return [{x_pct:1e-4,y_pct:1e-4},{x_pct:0.1,y_pct:0.1},{x_pct:1,y_pct:1},{x_pct:9,y_pct:9},{x_pct:100,y_pct:100}]; }
|
|
95
|
-
let C = { space:"logprob", points:identityPoints(), monotonic:true };
|
|
96
|
-
let SIGNAL=null; // {bins:[], vocab}
|
|
97
|
-
let LAST=null; // {prompt, curve, samples} of the most recent generation
|
|
98
|
-
const PROMPTS=[
|
|
99
|
-
"Write the first sentence of a short story about a lighthouse keeper who discovers something strange in the fog.",
|
|
100
|
-
"In one sentence, what causes the seasons on Earth?",
|
|
101
|
-
"Give one unusual but genuinely plausible use for a paperclip, in a sentence.",
|
|
102
|
-
"Describe the feeling of a city at 3am in one vivid sentence.",
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
// ---- math: monotone cubic (PCHIP), IDENTICAL to src/lab/curve/curve-sampler.ts ----
|
|
106
|
-
const Lp=pt=>[ln(Math.max(pt.x_pct,1e-9)/100),ln(Math.max(pt.y_pct,1e-9)/100)];
|
|
107
|
-
function knotArrays(c){ const k=c.points.map(Lp).sort((a,b)=>a[0]-b[0]); return {X:k.map(q=>q[0]),Y:k.map(q=>q[1])}; }
|
|
108
|
-
function secants(c){ const {X,Y}=knotArrays(c),s=[]; for(let i=X.length-1;i>0;i--)s.push((Y[i]-Y[i-1])/(X[i]-X[i-1])); return s; }
|
|
109
|
-
function monotone(c){ return secants(c).every(s=>s>=-1e-12); }
|
|
110
|
-
// identity = every control point on the diagonal ⇒ generate with the model's DEFAULT
|
|
111
|
-
// chat recipe (the real "what you'd get chatting" baseline), not a literal temp-1 curve.
|
|
112
|
-
function isIdentity(c){ return c.points.every(p=>Math.abs(ln(Math.max(p.x_pct,1e-9))-ln(Math.max(p.y_pct,1e-9)))<0.03); }
|
|
113
|
-
function cubicInU(x0,h,y0,y1,m0,m1){ const c0=y0,c1=h*m0,c2=-3*y0-2*h*m0+3*y1-h*m1,c3=2*y0+h*m0-2*y1+h*m1; const s=1/h,s2=s*s,s3=s2*s; let A=c0,B=0,C=0,D=0; B+=c1*s;A+=-c1*s*x0; C+=c2*s2;B+=-2*x0*c2*s2;A+=x0*x0*c2*s2; D+=c3*s3;C+=-3*x0*c3*s3;B+=3*x0*x0*c3*s3;A+=-x0*x0*x0*c3*s3; return {A,B,C,D}; }
|
|
114
|
-
function buildSpline(c){ const {X,Y}=knotArrays(c),n=X.length,D=[];
|
|
115
|
-
for(let i=0;i<n-1;i++)D.push((Y[i+1]-Y[i])/(X[i+1]-X[i]));
|
|
116
|
-
const M=new Array(n); M[0]=D[0]; M[n-1]=D[n-2];
|
|
117
|
-
for(let i=1;i<n-1;i++){ if(D[i-1]*D[i]<=0){M[i]=0;continue;} const h1=X[i]-X[i-1],h2=X[i+1]-X[i],w1=2*h2+h1,w2=h2+2*h1; M[i]=(w1+w2)/(w1/D[i-1]+w2/D[i]); }
|
|
118
|
-
const segs=[]; for(let i=0;i<n-1;i++)segs.push(cubicInU(X[i],X[i+1]-X[i],Y[i],Y[i+1],M[i],M[i+1])); return {X,Y,M,segs}; }
|
|
119
|
-
function evalSpline(sp,u){ const n=sp.X.length;
|
|
120
|
-
if(u<sp.X[0])return sp.Y[0]+Math.max(sp.M[0],1)*(u-sp.X[0]);
|
|
121
|
-
if(u>sp.X[n-1])return sp.Y[n-1]+sp.M[n-1]*(u-sp.X[n-1]);
|
|
122
|
-
let i=sp.segs.length-1; while(i>0&&u<sp.X[i])i--; const s=sp.segs[i]; return s.A+s.B*u+s.C*u*u+s.D*u*u*u; }
|
|
123
|
-
|
|
124
|
-
// ---- plot mapping ----
|
|
125
|
-
const VBW=460,VBH=360,PL=46,PR=14,PT=14,PB=34, FLOOR=1e-4;
|
|
126
|
-
// The data domain [UMIN,0] maps EXACTLY onto the box, so its corners ARE the data
|
|
127
|
-
// extremes: the first control point lives in the bottom-left corner, the last in
|
|
128
|
-
// the top-right. Dragging an endpoint keeps it welded to the box edge — its X is
|
|
129
|
-
// pinned (see clampPoint) and Y slides along that edge, like a tone-curve endpoint.
|
|
130
|
-
const px=u=>PL+(1-u/UMIN)*(VBW-PL-PR), py=u=>PT+(u/UMIN)*(VBH-PT-PB);
|
|
131
|
-
const uX=mx=>UMIN*(1-(mx-PL)/(VBW-PL-PR)), uY=my=>UMIN*((my-PT)/(VBH-PT-PB)), pct=u=>Math.exp(u)*100;
|
|
132
|
-
const TICKS=[100,10,1,0.1,0.01,0.001,0.0001]; // 0.0001% = UMIN = the box floor/left edge, so the corner is labeled
|
|
133
|
-
const PCOL=["#94a3b8","#0891b2","#7c3aed","#2563eb","#94a3b8"]; // endpoint, knee, center, shoulder, endpoint
|
|
134
|
-
|
|
135
|
-
function draw(){
|
|
136
|
-
let s=`<defs><clipPath id="plotclip"><rect x="${PL}" y="${PT}" width="${VBW-PL-PR}" height="${VBH-PT-PB}"/></clipPath></defs>`;
|
|
137
|
-
// signal histogram (behind)
|
|
138
|
-
if(SIGNAL&&SIGNAL.bins){ const b=SIGNAL.bins,NB=b.length,maxc=Math.max(...b,1),hz=(VBH-PT-PB)*0.55,base=VBH-PB;
|
|
139
|
-
for(let i=0;i<NB;i++){ if(!b[i])continue; const x0=px(UMIN*(1-i/NB)),x1=px(UMIN*(1-(i+1)/NB)); const hgt=ln(1+b[i])/ln(1+maxc)*hz;
|
|
140
|
-
s+=`<rect x="${Math.min(x0,x1)}" y="${base-hgt}" width="${Math.abs(x1-x0)+0.4}" height="${hgt}" fill="var(--text3)" opacity="0.26"/>`; } }
|
|
141
|
-
for(const p of TICKS){ const u=ln(p/100);
|
|
142
|
-
s+=`<line x1="${px(u)}" y1="${PT}" x2="${px(u)}" y2="${VBH-PB}" stroke="var(--grid)"/><line x1="${PL}" y1="${py(u)}" x2="${VBW-PR}" y2="${py(u)}" stroke="var(--grid)"/>`;
|
|
143
|
-
s+=`<text x="${px(u)}" y="${VBH-PB+13}" text-anchor="middle" font-size="8.5" fill="var(--text3)">${p}%</text>`;
|
|
144
|
-
s+=`<text x="${PL-9}" y="${py(u)+3}" text-anchor="end" font-size="8.5" fill="var(--text3)">${p}%</text>`; }
|
|
145
|
-
s+=`<text x="${(PL+VBW-PR)/2}" y="${VBH-3}" text-anchor="middle" font-size="10" fill="var(--text2)">p_in (model's true probability)</text>`;
|
|
146
|
-
s+=`<line x1="${px(UMIN)}" y1="${py(UMIN)}" x2="${px(0)}" y2="${py(0)}" stroke="var(--text3)" stroke-width="1.4" stroke-dasharray="5 4"/>`;
|
|
147
|
-
// smooth clipped curve
|
|
148
|
-
const sp=buildSpline(C); let d="";
|
|
149
|
-
for(let i=0;i<=240;i++){ const u=UMIN*(1-i/240); const v=Math.max(Math.min(evalSpline(sp,u),0),UMIN*1.25); d+=(i?"L":"M")+px(u).toFixed(1)+" "+py(v).toFixed(1)+" "; }
|
|
150
|
-
s+=`<g clip-path="url(#plotclip)"><path d="${d}" fill="none" stroke="var(--accent)" stroke-width="2.6"/></g>`;
|
|
151
|
-
// 5 control points
|
|
152
|
-
C.points.forEach((p,i)=>{ const u=Lp(p); const col=PCOL[Math.min(i,PCOL.length-1)];
|
|
153
|
-
s+=`<circle class="kp" data-i="${i}" cx="${px(u[0])}" cy="${py(u[1])}" r="7" fill="${col}" stroke="#fff" stroke-width="2" style="cursor:grab"/>`; });
|
|
154
|
-
document.getElementById("plot").innerHTML=s;
|
|
155
|
-
bindDrag(); drawSlopes(); document.getElementById("cfgField").value=cfgJSON();
|
|
156
|
-
document.getElementById("baselineHint").innerHTML = isIdentity(C)
|
|
157
|
-
? '<span style="color:var(--pos)">● identity</span> — Generate uses the model’s <b>default chat recipe</b> (temp + top-p + top-k): the real baseline.'
|
|
158
|
-
: '<span style="color:var(--accent)">● custom curve</span> — Generate replaces temperature+softmax with your curve.';
|
|
159
|
-
}
|
|
160
|
-
function drawSlopes(){
|
|
161
|
-
const sc=secants(C); const names=["head","upper-mid","lower-mid","shadows"];
|
|
162
|
-
const cell=(k,sl)=>{ const t=sl<0.97?"flatten":sl>1.03?"sharpen":"≈ identity", col=sl<0.97?"var(--pos)":sl>1.03?"var(--danger)":"var(--text2)";
|
|
163
|
-
return `<div class="s"><div class="k">${k}</div><div class="v">${sl.toFixed(2)}</div><div class="t" style="color:${col}">${t}</div></div>`; };
|
|
164
|
-
document.getElementById("slopeReadout").innerHTML=sc.slice(0,4).map((sl,i)=>cell(names[i]||("seg"+i),sl)).join("");
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function clampPoint(i){
|
|
168
|
-
const P=C.points, n=P.length, lo=i>0?P[i-1]:null, hi=i<n-1?P[i+1]:null;
|
|
169
|
-
if(i===0) P[i].x_pct=FLOOR; // first point welded to the LEFT edge of the box
|
|
170
|
-
else if(i===n-1) P[i].x_pct=100; // last point welded to the RIGHT edge of the box
|
|
171
|
-
else P[i].x_pct=Math.max(lo.x_pct*1.03, Math.min(hi.x_pct*0.97, P[i].x_pct));
|
|
172
|
-
P[i].y_pct=Math.max(lo?lo.y_pct*1.03:FLOOR, Math.min(hi?hi.y_pct*0.97:100, P[i].y_pct));
|
|
173
|
-
}
|
|
174
|
-
function bindDrag(){
|
|
175
|
-
const svg=document.getElementById("plot");
|
|
176
|
-
svg.querySelectorAll(".kp").forEach(el=>{
|
|
177
|
-
el.addEventListener("pointerdown",ev=>{ ev.preventDefault(); el.setPointerCapture(ev.pointerId);
|
|
178
|
-
clearGeneratedState();
|
|
179
|
-
const i=+el.dataset.i, rect=svg.getBoundingClientRect();
|
|
180
|
-
const move=e=>{ const mx=(e.clientX-rect.left)*(VBW/rect.width), my=(e.clientY-rect.top)*(VBH/rect.height);
|
|
181
|
-
C.points[i].x_pct=Math.min(100,Math.max(FLOOR,pct(uX(mx)))); C.points[i].y_pct=Math.min(100,Math.max(FLOOR,pct(uY(my)))); clampPoint(i); draw(); };
|
|
182
|
-
const up=()=>{ try{el.releasePointerCapture(ev.pointerId)}catch(_){}; window.removeEventListener("pointermove",move); window.removeEventListener("pointerup",up); };
|
|
183
|
-
window.addEventListener("pointermove",move); window.addEventListener("pointerup",up);
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
function cfgJSON(){ return JSON.stringify({space:"logprob",points:C.points.map(p=>({x_pct:+p.x_pct.toFixed(4),y_pct:+p.y_pct.toFixed(5)})),monotonic:true}); }
|
|
188
|
-
function clearGeneratedState(status=""){
|
|
189
|
-
document.getElementById("samples").innerHTML="";
|
|
190
|
-
document.getElementById("testArea").innerHTML="";
|
|
191
|
-
document.getElementById("copyTextBtn").style.display="none";
|
|
192
|
-
document.getElementById("status").textContent=status;
|
|
193
|
-
LAST=null; TESTST=null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// ---- server calls ----
|
|
197
|
-
const engBase=()=>document.getElementById("engine").value.replace(/\/(generate|signal)\/?$/,"");
|
|
198
|
-
async function probe(){ const dot=document.getElementById("engdot");
|
|
199
|
-
try{ const r=await fetch(engBase()+"/v1"); dot.className="dot "+(r.ok?"ok":"bad"); }catch(_){ dot.className="dot bad"; } }
|
|
200
|
-
async function loadSignal(){
|
|
201
|
-
const st=document.getElementById("status");
|
|
202
|
-
try{ const r=await fetch(engBase()+"/signal",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({prompt:document.getElementById("prompt").value})});
|
|
203
|
-
if(!r.ok)return; const j=await r.json(); SIGNAL=j; draw(); st.textContent="signal loaded ("+(j.vocab||"?")+" tokens)"; setTimeout(()=>{if(st.textContent.startsWith("signal"))st.textContent=""},1800);
|
|
204
|
-
}catch(_){ /* engine not up — no histogram */ }
|
|
205
|
-
}
|
|
206
|
-
async function generate(){
|
|
207
|
-
const btn=document.getElementById("genBtn"), st=document.getElementById("status"), out=document.getElementById("samples");
|
|
208
|
-
clearGeneratedState();
|
|
209
|
-
if(!monotone(C)){ st.textContent="curve not monotone."; return; }
|
|
210
|
-
btn.disabled=true; const baseline=isIdentity(C); st.textContent=baseline?"generating (model default)…":"generating…"; out.innerHTML="";
|
|
211
|
-
const payload={ prompt:document.getElementById("prompt").value,
|
|
212
|
-
n:Math.max(1,Math.min(8,+document.getElementById("nSamp").value||4)), seed:+document.getElementById("seed").value||100, max_tokens:90,
|
|
213
|
-
...(baseline?{default:true}:{curve:JSON.parse(cfgJSON())}) };
|
|
214
|
-
try{
|
|
215
|
-
const r=await fetch(engBase()+"/generate",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(payload)});
|
|
216
|
-
const j=await r.json();
|
|
217
|
-
if(!r.ok){ st.textContent="engine error: "+(j.error||r.status); btn.disabled=false; return; }
|
|
218
|
-
const tag = j.mode==="default"&&j.recipe ? `model default · T=${j.recipe.temperature} top-p=${j.recipe.topP} top-k=${j.recipe.topK}` : "your curve";
|
|
219
|
-
st.textContent=`${tag} · ${j.samples.length} samples · seed ${j.seed}`;
|
|
220
|
-
out.innerHTML=j.samples.map((x,i)=>`<div class="samp${x.junk?" junk":""}">${x.junk?'<span class="tag">JUNK</span>':""}<b>${i+1}.</b> ${esc(x.text)}</div>`).join("");
|
|
221
|
-
LAST={ prompt:payload.prompt, mode:j.mode, recipe:j.recipe, curve:cfgJSON(), samples:j.samples };
|
|
222
|
-
document.getElementById("copyTextBtn").style.display="inline";
|
|
223
|
-
}catch(e){ st.textContent="cannot reach engine — is the server running? "+e.message; }
|
|
224
|
-
btn.disabled=false;
|
|
225
|
-
}
|
|
226
|
-
function esc(s){ return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); }
|
|
227
|
-
|
|
228
|
-
// ---- blind test: 1 sentence from the default recipe + 1 from the curve, unlabeled, guess which ----
|
|
229
|
-
async function postGen(payload){
|
|
230
|
-
const r=await fetch(engBase()+"/generate",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(payload)});
|
|
231
|
-
const j=await r.json(); if(!r.ok) throw new Error(j.error||r.status); return j;
|
|
232
|
-
}
|
|
233
|
-
let TESTST=null; // {prompt, opts:[A,B], curveSlot, guessed}
|
|
234
|
-
async function runTest(){
|
|
235
|
-
const tb=document.getElementById("testBtn"), st=document.getElementById("status"), area=document.getElementById("testArea");
|
|
236
|
-
if(!monotone(C)){ st.textContent="curve not monotone."; return; }
|
|
237
|
-
if(isIdentity(C)){ st.textContent="shape the curve first — identity IS the default, nothing to compare."; return; }
|
|
238
|
-
tb.disabled=true; st.textContent="testing (default vs curve)…"; area.innerHTML="";
|
|
239
|
-
const prompt=document.getElementById("prompt").value, fld=+document.getElementById("seed").value||0;
|
|
240
|
-
// Fresh INDEPENDENT seeds each run, so repeated Tests give a new pair (not the same
|
|
241
|
-
// two sentences with their A/B position flipped). Combined with the coin flip below
|
|
242
|
-
// this makes the randomness self-evident — no fixed "curve sentence" to track.
|
|
243
|
-
const seedD=fld+Math.floor(Math.random()*1e6), seedC=fld+Math.floor(Math.random()*1e6);
|
|
244
|
-
try{
|
|
245
|
-
const [d,c]=await Promise.all([
|
|
246
|
-
postGen({prompt,default:true,n:1,seed:seedD,max_tokens:60}),
|
|
247
|
-
postGen({prompt,curve:JSON.parse(cfgJSON()),n:1,seed:seedC,max_tokens:60}),
|
|
248
|
-
]);
|
|
249
|
-
const dText=d.samples[0].text, cText=c.samples[0].text, curveFirst=Math.random()<0.5;
|
|
250
|
-
TESTST={ prompt, opts:[ curveFirst?cText:dText, curveFirst?dText:cText ], curveSlot: curveFirst?0:1, guessed:false };
|
|
251
|
-
renderTestCard(); st.textContent="blind pair ready — which is your curve?";
|
|
252
|
-
}catch(e){ st.textContent="test failed: "+e.message; }
|
|
253
|
-
tb.disabled=false;
|
|
254
|
-
}
|
|
255
|
-
function renderTestCard(){
|
|
256
|
-
const area=document.getElementById("testArea"), T=TESTST;
|
|
257
|
-
area.innerHTML=`<div class="testcard">
|
|
258
|
-
<div class="opt" data-s="0"><span class="lab">A</span><span>${esc(T.opts[0])}</span><span class="reveal" id="rv0"></span></div>
|
|
259
|
-
<div class="opt" data-s="1"><span class="lab">B</span><span>${esc(T.opts[1])}</span><span class="reveal" id="rv1"></span></div>
|
|
260
|
-
<div class="q">Which came from <b>your curve</b>? (the other is the model's default recipe)</div>
|
|
261
|
-
<div style="display:flex;gap:8px"><button class="ghost" data-g="0">It's A</button><button class="ghost" data-g="1">It's B</button><button class="ghost" id="copyPairBtn" style="margin-left:auto">Copy pair (blind)</button></div>
|
|
262
|
-
<div class="verdict" id="verdict"></div></div>`;
|
|
263
|
-
area.querySelectorAll("button[data-g]").forEach(b=>b.addEventListener("click",()=>guess(+b.dataset.g)));
|
|
264
|
-
area.querySelector("#copyPairBtn").addEventListener("click",copyPair);
|
|
265
|
-
}
|
|
266
|
-
function guess(slot){
|
|
267
|
-
const T=TESTST; if(!T||T.guessed)return; T.guessed=true;
|
|
268
|
-
document.getElementById("rv"+T.curveSlot).innerHTML='<span style="color:var(--accent2)">← your curve</span>';
|
|
269
|
-
document.getElementById("rv"+(1-T.curveSlot)).innerHTML='<span style="color:var(--text3)">← model default</span>';
|
|
270
|
-
document.querySelectorAll(".testcard .opt")[slot].classList.add("picked");
|
|
271
|
-
document.getElementById("verdict").innerHTML = slot===T.curveSlot
|
|
272
|
-
? '<span style="color:var(--pos)">✓ Correct — you picked your curve.</span>'
|
|
273
|
-
: '<span style="color:var(--danger)">✗ Nope — that was the model default; your curve was '+(T.curveSlot===0?"A":"B")+'.</span>';
|
|
274
|
-
}
|
|
275
|
-
function copyPair(){
|
|
276
|
-
const T=TESTST; if(!T)return;
|
|
277
|
-
const txt="Prompt: "+T.prompt+"\n\nA: "+T.opts[0]+"\nB: "+T.opts[1]+"\n\n(one is a custom log-prob sampling curve, the other the model's default recipe — which is which?)";
|
|
278
|
-
const v=document.getElementById("verdict"), prev=v.innerHTML, done=()=>{v.innerHTML='<span style="color:var(--pos)">pair copied ✓ (blind — paste to a judge)</span>';setTimeout(()=>{v.innerHTML=prev},1700);};
|
|
279
|
-
if(navigator.clipboard)navigator.clipboard.writeText(txt).then(done,done); else { const ta=document.createElement("textarea"); ta.value=txt; document.body.appendChild(ta); ta.select(); try{document.execCommand("copy")}catch(_){}; ta.remove(); done(); }
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// ---- wiring ----
|
|
283
|
-
document.getElementById("engine").value=ENGINE_BASE+"/generate";
|
|
284
|
-
if(location.protocol.startsWith("http")) document.getElementById("backLink").style.display="inline";
|
|
285
|
-
document.getElementById("pchips").innerHTML=PROMPTS.map((p,i)=>`<button data-i="${i}">${p.slice(0,38)}…</button>`).join("");
|
|
286
|
-
document.getElementById("pchips").querySelectorAll("button").forEach(b=>b.addEventListener("click",()=>{document.getElementById("prompt").value=PROMPTS[+b.dataset.i];clearGeneratedState();loadSignal();}));
|
|
287
|
-
document.getElementById("genBtn").addEventListener("click",generate);
|
|
288
|
-
document.getElementById("testBtn").addEventListener("click",runTest);
|
|
289
|
-
document.getElementById("sigBtn").addEventListener("click",loadSignal);
|
|
290
|
-
document.getElementById("copyTextBtn").addEventListener("click",()=>{ if(!LAST)return;
|
|
291
|
-
const sampler = LAST.mode==="default"&&LAST.recipe ? "Sampler: model default recipe (T="+LAST.recipe.temperature+", top-p="+LAST.recipe.topP+", top-k="+LAST.recipe.topK+")" : "Curve: "+LAST.curve;
|
|
292
|
-
const txt="Prompt: "+LAST.prompt+"\n"+sampler+"\n\n"+LAST.samples.map((s,i)=>(i+1)+". "+(s.junk?"[JUNK] ":"")+s.text).join("\n\n");
|
|
293
|
-
const st=document.getElementById("status"), done=()=>{st.textContent="text copied ✓";setTimeout(()=>{if(st.textContent==="text copied ✓")st.textContent=""},1500);};
|
|
294
|
-
if(navigator.clipboard)navigator.clipboard.writeText(txt).then(done,done); else { const ta=document.createElement("textarea"); ta.value=txt; document.body.appendChild(ta); ta.select(); try{document.execCommand("copy")}catch(_){}; ta.remove(); done(); } });
|
|
295
|
-
document.getElementById("resetBtn").addEventListener("click",()=>{C.points=identityPoints();draw();clearGeneratedState();});
|
|
296
|
-
document.getElementById("copyBtn").addEventListener("click",()=>{ const f=document.getElementById("cfgField"); f.select();
|
|
297
|
-
const ok=document.getElementById("copyOk"), done=()=>{ok.textContent="Copied!";setTimeout(()=>ok.textContent="",1500);};
|
|
298
|
-
if(navigator.clipboard)navigator.clipboard.writeText(f.value).then(done,()=>{document.execCommand("copy");done();}); else {document.execCommand("copy");done();} });
|
|
299
|
-
document.getElementById("engine").addEventListener("change",()=>{clearGeneratedState();probe();loadSignal();});
|
|
300
|
-
document.getElementById("prompt").addEventListener("change",()=>{clearGeneratedState();loadSignal();});
|
|
301
|
-
draw(); probe(); loadSignal();
|
|
302
|
-
</script>
|
|
303
|
-
</body></html>
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
// curve-sampler.ts — the v2 log-prob transfer-curve sampler. Replaces the whole
|
|
2
|
-
// temperature+softmax stage with a drawn MONOTONE CUBIC curve in log-probability
|
|
3
|
-
// space:
|
|
4
|
-
//
|
|
5
|
-
// p_out_i = exp(curve(log p_in_i)) / Σ_j exp(curve(log p_in_j))
|
|
6
|
-
//
|
|
7
|
-
// `lp` reaching the sampler is already log p_in (toLogprobs = logits − logsumexp),
|
|
8
|
-
// so the curve maps it directly and an identity curve reproduces temperature 1.
|
|
9
|
-
// The curve is a Fritsch–Carlson monotone cubic Hermite (PCHIP) through N movable
|
|
10
|
-
// control points in nat log-prob space (DaVinci-curves style — the endpoints start
|
|
11
|
-
// at the corners but are draggable too). Smooth, never overshoots, monotone. A
|
|
12
|
-
// control point dragged below the diagonal suppresses those tokens; the gate is
|
|
13
|
-
// emergent from the curve shape, not a separate threshold.
|
|
14
|
-
//
|
|
15
|
-
// Reading the curve: at a given p_in, ABOVE the diagonal raises those tokens,
|
|
16
|
-
// BELOW lowers them (renorm makes the literal number an intent); the SLOPE across
|
|
17
|
-
// a region sets how evenly the tokens inside it spread (flat<1 even, steep>1 separated).
|
|
18
|
-
|
|
19
|
-
import { MlxArray } from "../../mlx/array";
|
|
20
|
-
import * as ops from "../../mlx/ops";
|
|
21
|
-
|
|
22
|
-
export interface CurvePoint { x_pct: number; y_pct: number; }
|
|
23
|
-
export interface CurveParams {
|
|
24
|
-
space?: "logprob";
|
|
25
|
-
points: CurvePoint[]; // ≥2 control points, all movable; first/last are the endpoints
|
|
26
|
-
monotonic?: boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Bottom-left default anchor / plot floor (p = 1e-6). */
|
|
30
|
-
export const CURVE_UMIN = Math.log(1e-6);
|
|
31
|
-
const L = (pt: CurvePoint): [number, number] => [Math.log(Math.max(pt.x_pct, 1e-9) / 100), Math.log(Math.max(pt.y_pct, 1e-9) / 100)];
|
|
32
|
-
|
|
33
|
-
/** Control points in nat log-prob space, sorted ascending in x. */
|
|
34
|
-
function knotArrays(p: CurveParams): { X: number[]; Y: number[] } {
|
|
35
|
-
const k = p.points.map(L).sort((a, b) => a[0] - b[0]);
|
|
36
|
-
return { X: k.map((q) => q[0]), Y: k.map((q) => q[1]) };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Consecutive-point secants, top→bottom (region slopes; what the editor readout shows). */
|
|
40
|
-
export function curveSecants(p: CurveParams): number[] {
|
|
41
|
-
const { X, Y } = knotArrays(p);
|
|
42
|
-
const s: number[] = [];
|
|
43
|
-
for (let i = X.length - 1; i > 0; i--) s.push((Y[i]! - Y[i - 1]!) / (X[i]! - X[i - 1]!));
|
|
44
|
-
return s;
|
|
45
|
-
}
|
|
46
|
-
/** True iff every consecutive-point secant is ≥ 0 (monotone non-decreasing). */
|
|
47
|
-
export function isMonotone(p: CurveParams): boolean {
|
|
48
|
-
return p.points.length >= 2 && curveSecants(p).every((s) => s >= -1e-12);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
interface Seg { A: number; B: number; C: number; D: number } // cubic in u: A+Bu+Cu²+Du³
|
|
52
|
-
export interface Spline { X: number[]; Y: number[]; M: number[]; segs: Seg[] }
|
|
53
|
-
|
|
54
|
-
function cubicInU(x0: number, h: number, y0: number, y1: number, m0: number, m1: number): Seg {
|
|
55
|
-
const c0 = y0, c1 = h * m0;
|
|
56
|
-
const c2 = -3 * y0 - 2 * h * m0 + 3 * y1 - h * m1;
|
|
57
|
-
const c3 = 2 * y0 + h * m0 - 2 * y1 + h * m1;
|
|
58
|
-
const s = 1 / h, s2 = s * s, s3 = s2 * s;
|
|
59
|
-
let A = c0, B = 0, C = 0, D = 0;
|
|
60
|
-
B += c1 * s; A += -c1 * s * x0;
|
|
61
|
-
C += c2 * s2; B += -2 * x0 * c2 * s2; A += x0 * x0 * c2 * s2;
|
|
62
|
-
D += c3 * s3; C += -3 * x0 * c3 * s3; B += 3 * x0 * x0 * c3 * s3; A += -x0 * x0 * x0 * c3 * s3;
|
|
63
|
-
return { A, B, C, D };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Monotone cubic (Fritsch–Carlson) over the N control points. */
|
|
67
|
-
export function buildSpline(p: CurveParams): Spline {
|
|
68
|
-
const { X, Y } = knotArrays(p);
|
|
69
|
-
const n = X.length;
|
|
70
|
-
const Dsec: number[] = [];
|
|
71
|
-
for (let i = 0; i < n - 1; i++) Dsec.push((Y[i + 1]! - Y[i]!) / (X[i + 1]! - X[i]!));
|
|
72
|
-
const M = new Array<number>(n);
|
|
73
|
-
M[0] = Dsec[0]!; M[n - 1] = Dsec[n - 2]!;
|
|
74
|
-
for (let i = 1; i < n - 1; i++) {
|
|
75
|
-
if (Dsec[i - 1]! * Dsec[i]! <= 0) { M[i] = 0; continue; }
|
|
76
|
-
const h1 = X[i]! - X[i - 1]!, h2 = X[i + 1]! - X[i]!;
|
|
77
|
-
const w1 = 2 * h2 + h1, w2 = h2 + 2 * h1;
|
|
78
|
-
M[i] = (w1 + w2) / (w1 / Dsec[i - 1]! + w2 / Dsec[i]!);
|
|
79
|
-
}
|
|
80
|
-
const segs: Seg[] = [];
|
|
81
|
-
for (let i = 0; i < n - 1; i++) segs.push(cubicInU(X[i]!, X[i + 1]! - X[i]!, Y[i]!, Y[i + 1]!, M[i]!, M[i + 1]!));
|
|
82
|
-
return { X, Y, M, segs };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Scalar eval (editor preview / tests). Extrapolates linearly past both endpoints. */
|
|
86
|
-
export function evalSpline(sp: Spline, u: number): number {
|
|
87
|
-
const n = sp.X.length;
|
|
88
|
-
if (u < sp.X[0]!) return sp.Y[0]! + Math.max(sp.M[0]!, 1) * (u - sp.X[0]!); // deep tail: slope ≥1, stays gated
|
|
89
|
-
if (u > sp.X[n - 1]!) return sp.Y[n - 1]! + sp.M[n - 1]! * (u - sp.X[n - 1]!);
|
|
90
|
-
let i = sp.segs.length - 1;
|
|
91
|
-
while (i > 0 && u < sp.X[i]!) i--;
|
|
92
|
-
const s = sp.segs[i]!;
|
|
93
|
-
return s.A + s.B * u + s.C * u * u + s.D * u * u * u;
|
|
94
|
-
}
|
|
95
|
-
export function curveAt(p: CurveParams, u: number): number { return evalSpline(buildSpline(p), u); }
|
|
96
|
-
|
|
97
|
-
/** Apply the monotone-cubic transfer to normalized logprobs `lp` [.., V] (on-device). */
|
|
98
|
-
export function applyCurve(lp: MlxArray, p: CurveParams): MlxArray {
|
|
99
|
-
const sp = buildSpline(p);
|
|
100
|
-
const n = sp.X.length;
|
|
101
|
-
const tmp: MlxArray[] = [];
|
|
102
|
-
const k = <T extends MlxArray>(a: T): T => { tmp.push(a); return a; };
|
|
103
|
-
const C = (v: number): MlxArray => k(ops.scalarLike(v, lp));
|
|
104
|
-
const lp2 = k(ops.mul(lp, lp));
|
|
105
|
-
const lp3 = k(ops.mul(lp2, lp));
|
|
106
|
-
const seg = (s: Seg): MlxArray => k(ops.add(
|
|
107
|
-
k(ops.add(C(s.A), k(ops.mulScalar(lp, s.B)))),
|
|
108
|
-
k(ops.add(k(ops.mulScalar(lp2, s.C)), k(ops.mulScalar(lp3, s.D)))),
|
|
109
|
-
));
|
|
110
|
-
// below the bottom point: slope ≥ 1 (deep tail stays gated)
|
|
111
|
-
const lowSlope = Math.max(sp.M[0]!, 1);
|
|
112
|
-
let out: MlxArray = k(ops.add(C(sp.Y[0]! - lowSlope * sp.X[0]!), k(ops.mulScalar(lp, lowSlope))));
|
|
113
|
-
for (let i = 0; i < sp.segs.length; i++) {
|
|
114
|
-
const next = ops.where(k(ops.greaterEqual(lp, C(sp.X[i]!))), seg(sp.segs[i]!), out);
|
|
115
|
-
tmp.push(next); out = next;
|
|
116
|
-
}
|
|
117
|
-
// above the top point: linear extrapolation with the top tangent (if it was dragged left of 100%)
|
|
118
|
-
const aboveExt = k(ops.add(C(sp.Y[n - 1]! - sp.M[n - 1]! * sp.X[n - 1]!), k(ops.mulScalar(lp, sp.M[n - 1]!))));
|
|
119
|
-
const result = ops.where(k(ops.greaterEqual(lp, C(sp.X[n - 1]!))), aboveExt, out);
|
|
120
|
-
for (const a of tmp) a.dispose();
|
|
121
|
-
return result;
|
|
122
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// E0 expert-routing tracer (PLAN Phase 19 — expert offload).
|
|
2
|
-
//
|
|
3
|
-
// Records every MoE router decision as JSONL — one record per router call:
|
|
4
|
-
// { c: callSeq, l: layerIdx, s: [B, L, k], i: [flattened uint32 expert ids] }
|
|
5
|
-
// Analyse with analyze-expert-trace.ts (deleted 2026-08-23; git history) (coverage curve, working-set
|
|
6
|
-
// size, within-task stability, cross-task specialisation).
|
|
7
|
-
//
|
|
8
|
-
// Two ways to drive it:
|
|
9
|
-
// - env: `MLX_BUN_EXPERT_TRACE=<path> mlx-bun serve ...` (auto-starts here)
|
|
10
|
-
// - programmatic: beginExpertTrace(path) / endExpertTrace() per domain
|
|
11
|
-
// (run-expert-trace.ts (deleted 2026-08-23; git history) uses this to trace several domains from
|
|
12
|
-
// one model load).
|
|
13
|
-
//
|
|
14
|
-
// Recording adds a per-call GPU->host sync (it reads the routed indices back),
|
|
15
|
-
// so a traced run decodes slower — it's a MEASUREMENT tool, not a serving
|
|
16
|
-
// path. When no trace is active, isExpertTracing() is false and the hook in
|
|
17
|
-
// Router.forward is a single branch (zero overhead) — inert by default, same
|
|
18
|
-
// discipline as the slots flag.
|
|
19
|
-
|
|
20
|
-
import { Dtype } from "../../mlx/ffi";
|
|
21
|
-
import type { MlxArray } from "../../mlx/array";
|
|
22
|
-
import { runtimeValue } from "../../runtime-config";
|
|
23
|
-
|
|
24
|
-
let sink: Bun.FileSink | null = null;
|
|
25
|
-
let seq = 0;
|
|
26
|
-
let written = 0;
|
|
27
|
-
|
|
28
|
-
export function beginExpertTrace(path: string): void {
|
|
29
|
-
if (sink) endExpertTrace();
|
|
30
|
-
sink = Bun.file(path).writer();
|
|
31
|
-
seq = 0;
|
|
32
|
-
written = 0;
|
|
33
|
-
sink.write(JSON.stringify({ meta: "mlx-bun-expert-trace-v1", note: "one record per router call" }) + "\n");
|
|
34
|
-
process.stderr.write(`[expert-trace] recording -> ${path}\n`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function endExpertTrace(): void {
|
|
38
|
-
if (!sink) return;
|
|
39
|
-
sink.flush();
|
|
40
|
-
sink.end();
|
|
41
|
-
process.stderr.write(`[expert-trace] wrote ${written} records (${seq} calls)\n`);
|
|
42
|
-
sink = null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Alias kept for the process-exit handler / env callers. */
|
|
46
|
-
export const finishExpertTrace = endExpertTrace;
|
|
47
|
-
|
|
48
|
-
export function isExpertTracing(): boolean {
|
|
49
|
-
return sink !== null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Record one router decision. `indices` is [B, L, k] uint32 (expert ids). */
|
|
53
|
-
export function recordRouting(layer: number, indices: MlxArray): void {
|
|
54
|
-
if (!sink) return;
|
|
55
|
-
const shape = indices.shape; // [B, L, k]
|
|
56
|
-
const f = indices.astype(Dtype.float32); // ids <=127 are exact in f32
|
|
57
|
-
const data = f.toFloat32();
|
|
58
|
-
f.dispose();
|
|
59
|
-
const ids = new Array<number>(data.length);
|
|
60
|
-
for (let i = 0; i < data.length; i++) ids[i] = Math.round(data[i]!);
|
|
61
|
-
sink.write(JSON.stringify({ c: seq++, l: layer, s: shape, i: ids }) + "\n");
|
|
62
|
-
if (++written % 2000 === 0) sink.flush();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const expertTracePath = runtimeValue("MLX_BUN_EXPERT_TRACE");
|
|
66
|
-
if (expertTracePath) beginExpertTrace(expertTracePath);
|
|
67
|
-
|
|
68
|
-
process.on("exit", () => { try { endExpertTrace(); } catch { /* best-effort */ } });
|
|
69
|
-
process.on("SIGINT", () => { endExpertTrace(); process.exit(0); });
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { MlxArray } from "../../mlx/array";
|
|
2
|
-
import { Dtype } from "../../mlx/ffi";
|
|
3
|
-
import { MetalKernel } from "../../mlx/metal-kernel";
|
|
4
|
-
import * as ops from "../../mlx/ops";
|
|
5
|
-
import type { KvAttentionView, Mask } from "../../model/gemma4-base";
|
|
6
|
-
import { disposeResources } from "../../engine/resources";
|
|
7
|
-
import type { BlockPool } from "./paged-kv";
|
|
8
|
-
|
|
9
|
-
// Each SIMD group reduces one query/head over a bounded sequence partition.
|
|
10
|
-
// Only partial output vectors and normalizers materialize, never gathered KV.
|
|
11
|
-
const partialSpec = { name: "paged_attention_partial", ensureRowContiguous: true,
|
|
12
|
-
inputNames: ["q", "keys", "values", "table", "scale"], outputNames: ["out", "normal"], source: `
|
|
13
|
-
uint lane = thread_position_in_threadgroup.x;
|
|
14
|
-
uint hq = threadgroup_position_in_grid.y % HQ;
|
|
15
|
-
uint query = threadgroup_position_in_grid.y / HQ;
|
|
16
|
-
uint part = threadgroup_position_in_grid.z;
|
|
17
|
-
uint hk = hq / (HQ / HK);
|
|
18
|
-
float accum[(DV + 31) / 32];
|
|
19
|
-
for (uint j = 0; j < (DV + 31) / 32; ++j) accum[j] = 0;
|
|
20
|
-
float maximum = -INFINITY, total = 0;
|
|
21
|
-
uint length = uint(scale[1]);
|
|
22
|
-
uint count = (length + PART - 1) / PART;
|
|
23
|
-
uint end = min(uint(length - N + query + 1), (part + 1) * PART);
|
|
24
|
-
for (uint token = part * PART; token < end; ++token) {
|
|
25
|
-
uint physical = table[token / BS];
|
|
26
|
-
uint keyBase = ((physical * HK + hk) * BS + token % BS) * DK;
|
|
27
|
-
float score = 0;
|
|
28
|
-
for (uint d = lane; d < DK; d += 32)
|
|
29
|
-
score += float(q[(hq * N + query) * DK + d]) * float(keys[keyBase + d]);
|
|
30
|
-
score = simd_sum(score) * scale[0];
|
|
31
|
-
float next = max(maximum, score);
|
|
32
|
-
float previous = exp(maximum - next), weight = exp(score - next);
|
|
33
|
-
uint valueBase = ((physical * HK + hk) * BS + token % BS) * DV;
|
|
34
|
-
for (uint j = 0; j < (DV + 31) / 32; ++j) {
|
|
35
|
-
uint d = j * 32 + lane;
|
|
36
|
-
if (d < DV) accum[j] = accum[j] * previous + weight * float(values[valueBase + d]);
|
|
37
|
-
}
|
|
38
|
-
total = total * previous + weight; maximum = next;
|
|
39
|
-
}
|
|
40
|
-
uint base = ((hq * N + query) * count + part);
|
|
41
|
-
for (uint j = 0; j < (DV + 31) / 32; ++j) {
|
|
42
|
-
uint d = j * 32 + lane;
|
|
43
|
-
if (d < DV) out[base * DV + d] = accum[j];
|
|
44
|
-
}
|
|
45
|
-
if (lane == 0) { normal[base * 2] = maximum; normal[base * 2 + 1] = total; }
|
|
46
|
-
` };
|
|
47
|
-
const partial = new MetalKernel(partialSpec);
|
|
48
|
-
const quantizedPartial = new MetalKernel({ ...partialSpec, name: "paged_attention_affine_partial",
|
|
49
|
-
inputNames: [...partialSpec.inputNames, "ks", "kb", "vs", "vb"],
|
|
50
|
-
source: partialSpec.source
|
|
51
|
-
.replace("float(keys[keyBase + d])", "float(InT(float(ks[(keyBase+d)/GROUP]) * float((keys[(keyBase+d)/PACK] >> (((keyBase+d)%PACK)*BITS)) & ((1u<<BITS)-1u)) + float(kb[(keyBase+d)/GROUP])))")
|
|
52
|
-
.replace("float(values[valueBase + d])", "float(InT(float(vs[(valueBase+d)/GROUP]) * float((values[(valueBase+d)/PACK] >> (((valueBase+d)%PACK)*BITS)) & ((1u<<BITS)-1u)) + float(vb[(valueBase+d)/GROUP])))"),
|
|
53
|
-
});
|
|
54
|
-
const merge = new MetalKernel({ name: "paged_attention_merge", inputNames: ["parts", "normal"], outputNames: ["out"], source: `
|
|
55
|
-
uint d = thread_position_in_grid.x;
|
|
56
|
-
uint row = thread_position_in_grid.y;
|
|
57
|
-
if (d >= DV) return;
|
|
58
|
-
uint count = normal_shape[2];
|
|
59
|
-
float maximum = -INFINITY;
|
|
60
|
-
for (uint part = 0; part < count; ++part) maximum = max(maximum, normal[(row * count + part) * 2]);
|
|
61
|
-
float sum = 0, value = 0;
|
|
62
|
-
for (uint part = 0; part < count; ++part) {
|
|
63
|
-
uint base = row * count + part;
|
|
64
|
-
float weight = exp(normal[base * 2] - maximum);
|
|
65
|
-
sum += normal[base * 2 + 1] * weight;
|
|
66
|
-
value += parts[base * DV + d] * weight;
|
|
67
|
-
}
|
|
68
|
-
out[row * DV + d] = OutT(value / sum);
|
|
69
|
-
` });
|
|
70
|
-
|
|
71
|
-
/** Independent immutable view: later appends or row retirement cannot alter it. */
|
|
72
|
-
export function pagedAttentionView(pool: BlockPool, blockTable: number[], length: number,
|
|
73
|
-
direct: boolean): KvAttentionView {
|
|
74
|
-
const keys = ops.contiguous(pool.keys), values = ops.contiguous(pool.values);
|
|
75
|
-
const table = MlxArray.fromInt32(Int32Array.from(blockTable), [blockTable.length]);
|
|
76
|
-
const bs = pool.blockSize, quantization = pool.quantization;
|
|
77
|
-
const extra = quantization ? [pool.keyScales!, pool.keyBiases!, pool.valueScales!, pool.valueBiases!].map(a => ops.contiguous(a)) : [];
|
|
78
|
-
const dkStored = pool.headDim, dvStored = pool.vHeadDim;
|
|
79
|
-
const dtype = pool.dtype;
|
|
80
|
-
return {
|
|
81
|
-
attend(q: MlxArray, scale: number, mask: Mask): MlxArray {
|
|
82
|
-
const [, hq, n, dk] = q.shape as [number, number, number, number];
|
|
83
|
-
const hk = keys.shape[1]!, dv = dvStored;
|
|
84
|
-
// Long prefill and explicit masks use the established attention oracle.
|
|
85
|
-
// This is shape dispatch within one attention interface, not scheduling.
|
|
86
|
-
if (!direct || n > 8 || mask.mode === "array") {
|
|
87
|
-
const gather = (tensor: MlxArray) => {
|
|
88
|
-
using picked = ops.takeAxis(tensor, table, 0);
|
|
89
|
-
using transposed = ops.transposeAxes(picked, [1, 0, 2, 3]);
|
|
90
|
-
using flat = ops.reshape(transposed, [1, hk, blockTable.length * bs, tensor.shape[3]!]);
|
|
91
|
-
return flat.slice([0, 0, 0, 0], [1, hk, length, tensor.shape[3]!]);
|
|
92
|
-
};
|
|
93
|
-
using k = gather(keys), v = gather(values);
|
|
94
|
-
if (!quantization) return ops.sdpa(q, k, v, scale, mask.mode, mask.arr);
|
|
95
|
-
using ks = gather(extra[0]!), kb = gather(extra[1]!), vs = gather(extra[2]!), vb = gather(extra[3]!);
|
|
96
|
-
using kd = ops.dequantize(k, ks, kb, { ...quantization, mode: "affine" });
|
|
97
|
-
using vd = ops.dequantize(v, vs, vb, { ...quantization, mode: "affine" });
|
|
98
|
-
return ops.sdpa(q, kd, vd, scale, mask.mode, mask.arr);
|
|
99
|
-
}
|
|
100
|
-
const part = 64, parts = Math.ceil(length / part);
|
|
101
|
-
using multiplier = MlxArray.fromFloat32(new Float32Array([scale, length]), [2]);
|
|
102
|
-
const [out, normal] = (quantization ? quantizedPartial : partial).apply([q, keys, values, table, multiplier, ...extra], {
|
|
103
|
-
outputs: [{ shape: [hq, n, parts, dv], dtype: Dtype.float32 }, { shape: [hq, n, parts, 2], dtype: Dtype.float32 }],
|
|
104
|
-
grid: [32, hq * n, parts], threadGroup: [32, 1, 1],
|
|
105
|
-
templateDtypes: quantization ? { InT: dtype } : {},
|
|
106
|
-
templateInts: { HQ: hq, HK: hk, N: n, DK: dkStored, DV: dv, BS: bs, PART: part,
|
|
107
|
-
...(quantization ? { BITS: quantization.bits, GROUP: quantization.groupSize, PACK: 32 / quantization.bits } : {}) },
|
|
108
|
-
});
|
|
109
|
-
try {
|
|
110
|
-
return merge.apply([out!, normal!], { outputs: [{ shape: [1, hq, n, dv], dtype: q.dtype }],
|
|
111
|
-
grid: [Math.ceil(dv / 32) * 32, hq * n, 1], threadGroup: [32, 1, 1],
|
|
112
|
-
templateDtypes: { OutT: q.dtype }, templateInts: { DV: dv } })[0]!;
|
|
113
|
-
} finally { disposeResources([out!, normal!]); }
|
|
114
|
-
},
|
|
115
|
-
dispose() { disposeResources([keys, values, table, ...extra]); },
|
|
116
|
-
};
|
|
117
|
-
}
|