mlx-bun 0.0.4
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/LICENSE +21 -0
- package/README.md +362 -0
- package/THIRD_PARTY_LICENSES.md +41 -0
- package/bin/mlx-bun.mjs +32 -0
- package/docs/curve-designer.html +303 -0
- package/docs/design/adapters-end-to-end.md +201 -0
- package/docs/design/compat-cli-surface-design.md +227 -0
- package/docs/design/docs-reorg-plan.md +152 -0
- package/docs/design/hlg-sampling.md +340 -0
- package/docs/design/memory-system.md +339 -0
- package/docs/design/optimization_plan.md +344 -0
- package/docs/design/parallel-slots.md +515 -0
- package/docs/design/runtime-isolation.md +247 -0
- package/docs/design/segmented-backward-training.md +508 -0
- package/docs/investigations/chunk-finetune-experiment.md +84 -0
- package/docs/investigations/curve-bisector-routing.md +123 -0
- package/docs/investigations/curve-runs/bisector-route.json +98 -0
- package/docs/investigations/curve-runs/bisector-trace.json +1393 -0
- package/docs/investigations/curve-runs/curve-terrain.json +1179 -0
- package/docs/investigations/curve-runs/curve-terrain.svg +42 -0
- package/docs/investigations/curve-terrain.html +105 -0
- package/docs/investigations/expert-offload-single-user-moe.md +292 -0
- package/docs/investigations/hlg-ab.html +34 -0
- package/docs/investigations/hlg-explorer.html +238 -0
- package/docs/investigations/hlg-figs/cliff.svg +1 -0
- package/docs/investigations/hlg-figs/cross.svg +1 -0
- package/docs/investigations/hlg-figs/edges.svg +1 -0
- package/docs/investigations/hlg-figs/k20-grids.svg +1 -0
- package/docs/investigations/hlg-figs/k20-peaks.svg +1 -0
- package/docs/investigations/hlg-figs/lw-curve.svg +1 -0
- package/docs/investigations/hlg-figs/terrain.svg +1 -0
- package/docs/investigations/hlg-report.html +262 -0
- package/docs/investigations/hlg-runs/hlg-ab.json +149 -0
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +87 -0
- package/docs/investigations/hlg-runs/hlg-blind.json +107 -0
- package/docs/investigations/hlg-runs/hlg-cliff.json +197 -0
- package/docs/investigations/hlg-runs/hlg-cross.json +505 -0
- package/docs/investigations/hlg-runs/hlg-edge.json +388 -0
- package/docs/investigations/hlg-runs/hlg-eval1.json +25 -0
- package/docs/investigations/hlg-runs/hlg-frontier.json +86 -0
- package/docs/investigations/hlg-runs/hlg-grid.json +242 -0
- package/docs/investigations/hlg-runs/hlg-grid2.json +343 -0
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +110 -0
- package/docs/investigations/hlg-runs/hlg-map.json +383 -0
- package/docs/investigations/hlg-runs/run0-original.log +159 -0
- package/docs/investigations/hlg-runs/runA-recommended.log +131 -0
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +26 -0
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +18 -0
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +25 -0
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +8 -0
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +51 -0
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +10 -0
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +16 -0
- package/docs/investigations/hlg-runs/runB-gain-variants.log +192 -0
- package/docs/investigations/hlg-runs/runC-pivots.log +162 -0
- package/docs/investigations/hlg-runs/runD-oetf.log +132 -0
- package/docs/investigations/hlg-runs/runE-eotf.log +162 -0
- package/docs/investigations/hlg-runs/runF-shaper-working.log +86 -0
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +101 -0
- package/docs/investigations/hlg-runs/runH-wsweep.log +176 -0
- package/docs/investigations/hlg-runs/runI-asweep.log +176 -0
- package/docs/investigations/hlg-runs/runJ-knobmap.log +49 -0
- package/docs/investigations/hlg-runs/runK-frontier.log +19 -0
- package/docs/investigations/hlg-runs/runL-widemap.log +65 -0
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +15 -0
- package/docs/investigations/hlg-runs/runN-verify.log +116 -0
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +15 -0
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +15 -0
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +15 -0
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +79 -0
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +33 -0
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +33 -0
- package/docs/investigations/hlg-runs/runU-cross-12b.log +33 -0
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +22 -0
- package/docs/investigations/hlg-runs/runW-lw-12b.log +22 -0
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +22 -0
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +26 -0
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +26 -0
- package/docs/investigations/hlg-sampling-investigation.md +970 -0
- package/docs/investigations/lab-build-journal.md +157 -0
- package/docs/investigations/pi-builtin-investigation.md +308 -0
- package/docs/investigations/starter-model-port-handoff.md +323 -0
- package/docs/planning/IDEAS.md +26 -0
- package/docs/planning/PRODUCT_ROADMAP.md +426 -0
- package/docs/planning/ResearchTopics.md +119 -0
- package/docs/planning/chunk-task-roadmap.md +77 -0
- package/docs/planning/journal.md +155 -0
- package/docs/reference/distribution.md +121 -0
- package/docs/reference/embedding.md +168 -0
- package/docs/reference/library-api.md +153 -0
- package/docs/reference/server-api.md +224 -0
- package/docs/reference/server-config.md +243 -0
- package/docs/segmented-backward-handoff.md +148 -0
- package/package.json +68 -0
- package/src/anthropic.ts +491 -0
- package/src/chat-template.ts +186 -0
- package/src/cli.ts +1075 -0
- package/src/config.ts +229 -0
- package/src/curve-sampler.ts +122 -0
- package/src/dataset/generators.ts +1087 -0
- package/src/dataset/index.ts +12 -0
- package/src/dataset/job.ts +81 -0
- package/src/dataset/llm.ts +71 -0
- package/src/dataset/registry.ts +528 -0
- package/src/download.ts +283 -0
- package/src/eval/README.md +86 -0
- package/src/eval/kl-prompts.ts +29 -0
- package/src/eval/kl.ts +294 -0
- package/src/eval/quality-db.ts +92 -0
- package/src/eval/runner.ts +102 -0
- package/src/eval/score.ts +49 -0
- package/src/eval/tasks/bfcl.ts +500 -0
- package/src/eval/tasks/gsm8k.ts +85 -0
- package/src/eval/tasks/hashhop.ts +109 -0
- package/src/eval/tasks/humaneval.ts +252 -0
- package/src/eval/tasks/ifeval.ts +354 -0
- package/src/eval/tasks/mmlu.ts +145 -0
- package/src/evaldb.ts +199 -0
- package/src/expert-offload-build.ts +77 -0
- package/src/expert-offload.ts +61 -0
- package/src/expert-trace.ts +67 -0
- package/src/fit.ts +254 -0
- package/src/generate.ts +451 -0
- package/src/harness-pi.ts +177 -0
- package/src/hf-push.ts +628 -0
- package/src/index.ts +22 -0
- package/src/jobs/db.ts +139 -0
- package/src/jobs/index.ts +29 -0
- package/src/jobs/job-entry.ts +106 -0
- package/src/jobs/runner.ts +304 -0
- package/src/jobs/sse.ts +114 -0
- package/src/jobs/types.ts +58 -0
- package/src/kv-store.ts +185 -0
- package/src/lora.ts +314 -0
- package/src/md-modules.d.ts +7 -0
- package/src/mlx/array.ts +237 -0
- package/src/mlx/autograd.ts +267 -0
- package/src/mlx/checkpoint.ts +116 -0
- package/src/mlx/compile.ts +158 -0
- package/src/mlx/custom-vjp.ts +140 -0
- package/src/mlx/ffi.ts +433 -0
- package/src/mlx/metal-kernel.ts +130 -0
- package/src/mlx/ops.ts +707 -0
- package/src/mmap.ts +90 -0
- package/src/model/batched-mask.ts +204 -0
- package/src/model/batched-rotating.ts +300 -0
- package/src/model/compiled-decode.ts +681 -0
- package/src/model/factory.ts +27 -0
- package/src/model/fingerprint.ts +33 -0
- package/src/model/flash-attention.ts +674 -0
- package/src/model/fused-decode-kernel.ts +305 -0
- package/src/model/fused-geglu-kernel.ts +87 -0
- package/src/model/gemma4-base.ts +1616 -0
- package/src/model/gemma4.ts +1012 -0
- package/src/model/generated/gemma4-12b.ts +526 -0
- package/src/model/generated/gemma4-26b.ts +500 -0
- package/src/model/generated/gemma4-e4b.ts +757 -0
- package/src/model/generated/index.ts +18 -0
- package/src/model/minicpm5.ts +278 -0
- package/src/model/qwen3-delta.ts +224 -0
- package/src/model/qwen3_5.ts +429 -0
- package/src/model/support.ts +46 -0
- package/src/native-pack.ts +152 -0
- package/src/pi-provider.ts +95 -0
- package/src/pi-terminal.ts +264 -0
- package/src/pi-web.ts +924 -0
- package/src/preflight.ts +123 -0
- package/src/prompt-cache.ts +113 -0
- package/src/quantize/allocator.ts +627 -0
- package/src/quantize/calibration.ts +180 -0
- package/src/quantize/config-writer.ts +132 -0
- package/src/quantize/index.ts +57 -0
- package/src/quantize/job.ts +136 -0
- package/src/quantize/quantizer.ts +462 -0
- package/src/quantize/safetensors-writer.ts +171 -0
- package/src/quantize/sensitivity.ts +234 -0
- package/src/registry.ts +336 -0
- package/src/responses.ts +774 -0
- package/src/safetensors.ts +158 -0
- package/src/sampler.ts +517 -0
- package/src/serve/batch-scheduler.ts +362 -0
- package/src/serve/generation-gateway.ts +160 -0
- package/src/server.ts +1891 -0
- package/src/spec/drafter.ts +261 -0
- package/src/spec/generate.ts +221 -0
- package/src/status-page.html +497 -0
- package/src/tokenizer.ts +38 -0
- package/src/tool-call.ts +242 -0
- package/src/train/dataset.ts +461 -0
- package/src/train/export.ts +32 -0
- package/src/train/forward.ts +229 -0
- package/src/train/index.ts +43 -0
- package/src/train/job.ts +148 -0
- package/src/train/lora-params.ts +194 -0
- package/src/train/loss.ts +342 -0
- package/src/train/merge.ts +195 -0
- package/src/train/optimizer.ts +176 -0
- package/src/train/rank.ts +101 -0
- package/src/train/segmented.ts +520 -0
- package/src/train/trainer.ts +600 -0
- package/src/tui.ts +161 -0
- package/src/vision/embedder.ts +168 -0
- package/src/vision/preprocess.ts +247 -0
- package/src/vision/prompt.ts +158 -0
- package/src/vision/siglip.ts +599 -0
- package/src/web/app.html +2471 -0
- package/src/web/skills/web-research/SKILL.md +44 -0
- package/src/web/skills.ts +59 -0
- package/src/web-tools.ts +426 -0
- package/src/weights.ts +91 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# HLG sampling — a piecewise tone curve on the logits
|
|
2
|
+
|
|
3
|
+
Status: **design + phasing** (no code yet; this doc is the contract)
|
|
4
|
+
Owner: sampling layer (`src/sampler.ts`)
|
|
5
|
+
Default: **off** (`--hlg-sampling off` = today's temperature sampler, untouched)
|
|
6
|
+
|
|
7
|
+
> This is the canonical **design/rationale** for HLG sampling. Live
|
|
8
|
+
> **status/tracking** (checkboxes, findings) lives in PLAN.md under
|
|
9
|
+
> "Phase 19 — HLG sampling". The user-facing flag/param reference lives in
|
|
10
|
+
> [docs/reference/server-config.md](../reference/server-config.md) and
|
|
11
|
+
> [docs/reference/server-api.md](../reference/server-api.md) once shipped.
|
|
12
|
+
|
|
13
|
+
## Goal
|
|
14
|
+
|
|
15
|
+
Add a sampling transform — gated entirely behind `--hlg-sampling on` and a
|
|
16
|
+
per-request `hlg` object — that replaces temperature's single global slope
|
|
17
|
+
with a **pivoted, region-aware contrast curve** on the per-token
|
|
18
|
+
log-probabilities.
|
|
19
|
+
|
|
20
|
+
The move is a **cross-domain transplant**: take a mathematical structure that is
|
|
21
|
+
standard in one field — a piecewise nonlinear transfer function — and apply it
|
|
22
|
+
in one that has never used it. HLG (Hybrid Log-Gamma) is the structure we lift:
|
|
23
|
+
where a plain gamma is one power curve, HLG is **piecewise**, shaping the low,
|
|
24
|
+
middle, and high range of a signal under separate constraints. A logit
|
|
25
|
+
distribution is another such signal. The hypothesis is that shaping its three
|
|
26
|
+
regions independently buys something a single global temperature cannot — and
|
|
27
|
+
that claim is settled by measurement in *this* domain, not by the structure's
|
|
28
|
+
track record in its original one.
|
|
29
|
+
|
|
30
|
+
This is a post-inference, **model-agnostic** transform — it operates on the
|
|
31
|
+
logits vector after the forward pass, so it applies identically to every model
|
|
32
|
+
(MiniCPM5 + the three Gemma-4 quants) and every lane (serial + `--batch N`)
|
|
33
|
+
with **zero per-model code**. It is the first sampling feature in the project
|
|
34
|
+
that has **no oracle ancestor** (neither mlx-lm nor optiq does this), so it is
|
|
35
|
+
gated by KL + quality + diversity, not parity — with one exception that makes
|
|
36
|
+
it safe to ship: see [Correctness](#correctness--evaluation).
|
|
37
|
+
|
|
38
|
+
## Why temperature isn't enough (the thesis)
|
|
39
|
+
|
|
40
|
+
Temperature scales every logit by the same factor: `logit / T`. In tone-curve
|
|
41
|
+
terms it is a **single straight line through the origin** — one global slope.
|
|
42
|
+
Lower `T` steepens it everywhere (sharper, more confident); higher `T` flattens
|
|
43
|
+
it everywhere (more diverse).
|
|
44
|
+
|
|
45
|
+
Its limitation is a **coupling**: the only way temperature loosens the model's
|
|
46
|
+
grip on its top token is by raising `T`, which *simultaneously* lifts the tail.
|
|
47
|
+
You cannot, with one slope, reduce top-token dominance **and** keep a soft floor
|
|
48
|
+
under the tail. Raise the temperature to get novelty and you also import
|
|
49
|
+
low-probability noise; lower it to suppress noise and you re-collapse onto the
|
|
50
|
+
single most likely token. One number cannot move two regions independently.
|
|
51
|
+
|
|
52
|
+
The fix is structural, not a better choice of `T`: make the slope **depend on
|
|
53
|
+
the region of the distribution**. This is precisely what nonlinear transfer
|
|
54
|
+
functions do in signal and color encoding — a single piecewise curve shapes the
|
|
55
|
+
low, middle, and high range under separate constraints. The cross-domain idea
|
|
56
|
+
here is to transplant that apparatus onto a logit distribution, which is just
|
|
57
|
+
another value distribution. Mapped onto the three regions of a token
|
|
58
|
+
distribution, the curve's response is:
|
|
59
|
+
|
|
60
|
+
- **High-probability region** (the model's most confident tokens) →
|
|
61
|
+
**shoulder**: roll the slope off so the top values compress toward their
|
|
62
|
+
neighbours. The model stops being *so fixed* on its favourite answer.
|
|
63
|
+
- **Mid-probability region** (where novelty and interest live) → **gain > 1**:
|
|
64
|
+
steepen the slope. The local-contrast boost separates the
|
|
65
|
+
plausible-and-interesting from the merely-mediocre.
|
|
66
|
+
- **Low-probability tail** → **toe**: gently reduce the slope toward a soft
|
|
67
|
+
floor. Suppress the tail *smoothly* — unlike top-p/top-k, which hard-clip it
|
|
68
|
+
to `-inf`, and unlike high temperature, which inflates it.
|
|
69
|
+
|
|
70
|
+
The payoff is the **decoupling** temperature cannot achieve: roll off the high
|
|
71
|
+
end *and* hold a soft floor under the tail at the same time — a region of
|
|
72
|
+
sampling behaviour no single-knob method reaches. Whether that decoupling is
|
|
73
|
+
*useful* is an empirical question, settled in [Correctness](#correctness--evaluation),
|
|
74
|
+
not by the pedigree of the curve.
|
|
75
|
+
|
|
76
|
+
## The transfer function
|
|
77
|
+
|
|
78
|
+
We operate in **log-probability space**, the natural "stops" axis for a
|
|
79
|
+
probability distribution (the sampler already computes `toLogprobs`,
|
|
80
|
+
[src/sampler.ts:127](../../src/sampler.ts)). Let `ℓ_i` be each token's log-prob
|
|
81
|
+
and `μ` the pivot (middle grey — see [Pivot](#the-pivot--middle-grey)). Define
|
|
82
|
+
the centered coordinate
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
z_i = ℓ_i − μ
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
and remap it with a **C¹ log-toe / linear-mid / log-shoulder** curve. The
|
|
89
|
+
piecewise form is deliberate — it honours HLG's own breakpoints (HLG literally
|
|
90
|
+
switches from a gamma segment to a log segment at E = 1/12):
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
⎧ −m·w − m·β_t·ln(1 + (−z − w)/β_t) z < −w (toe / shadows)
|
|
94
|
+
g(z) = ⎨ m·z |z| ≤ w (gain / mids)
|
|
95
|
+
⎩ m·w + m·β_h·ln(1 + ( z − w)/β_h) z > w (shoulder / highlights)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The remapped logits are `ℓ'_i = g(z_i)`. The `+μ` constant shift cancels under
|
|
99
|
+
softmax, so we drop it and feed `g(z_i)` straight to the existing
|
|
100
|
+
`randomCategorical` draw.
|
|
101
|
+
|
|
102
|
+
Properties that matter:
|
|
103
|
+
|
|
104
|
+
- **Slope** is `m` at the pivot and decays as `m·β / (β + d)` a distance `d`
|
|
105
|
+
past each knot — continuous at the knots (C¹), monotone, and always positive.
|
|
106
|
+
- **Monotone ⇒ ranking-preserving.** `g` never reorders tokens: it is a pure
|
|
107
|
+
contrast/tone operation, not a re-ranker. Pairwise orderings and the argmax
|
|
108
|
+
are invariant. (Tested — see [Correctness](#correctness--evaluation).)
|
|
109
|
+
- **`-inf` safe.** A token masked by top-p/top-k (`ℓ_i = -inf`) lands in the toe
|
|
110
|
+
branch and maps to `-inf` — masking survives the remap, no NaN.
|
|
111
|
+
|
|
112
|
+
### Knobs → what each controls
|
|
113
|
+
|
|
114
|
+
| Param | Controls | Effect |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
| `pivot` μ | center of the curve | where the contrast boost is anchored in the distribution (see below) |
|
|
117
|
+
| `gain` m | mid-region slope | `m > 1` sharpens mid-probability tokens; folds temperature (`m = 1/T`) |
|
|
118
|
+
| `width` w | extent of the mid region | how many nats around the pivot count as "mids" |
|
|
119
|
+
| `shoulder` β_h | high-prob rolloff | small = compresses the top tokens fast → top-token diversity |
|
|
120
|
+
| `toe` β_t | low-prob rolloff | small = quick gentle fade of the tail; large = keep more tail |
|
|
121
|
+
|
|
122
|
+
All knobs are in **nats** (the log-prob unit), so they are scale-free across
|
|
123
|
+
models and contexts.
|
|
124
|
+
|
|
125
|
+
### The degeneracies are the safety anchors
|
|
126
|
+
|
|
127
|
+
The curve is a **strict generalization of temperature**, and that is what makes
|
|
128
|
+
a no-oracle path safe to ship — the default and neutral paths reduce *exactly*
|
|
129
|
+
to today's sampler:
|
|
130
|
+
|
|
131
|
+
- `m = 1`, rolloff off (`w → ∞`, or `β → ∞`) ⟹ `g(z) = z` ⟹ **bit-exact the
|
|
132
|
+
current sampler at T = 1**.
|
|
133
|
+
- rolloff off (`w → ∞`), any `m` ⟹ `g(z) = m·z` ⟹ **bit-exact temperature
|
|
134
|
+
`T = 1/m`** (the existing `mulScalar(cur, 1/temperature)` step).
|
|
135
|
+
|
|
136
|
+
So there is a configuration in which HLG is provably identical to temperature,
|
|
137
|
+
down to the bit. That is the parity-equivalent gate (below).
|
|
138
|
+
|
|
139
|
+
### Greedy is untouched
|
|
140
|
+
|
|
141
|
+
Under greedy decoding (`temperature === 0`) the sampler returns `argmax`
|
|
142
|
+
([src/sampler.ts:78](../../src/sampler.ts)). Because `g` is monotone it cannot
|
|
143
|
+
change the argmax, so **HLG is a no-op at temperature 0 by construction** and is
|
|
144
|
+
only engaged for `temperature > 0`. The greedy parity gate is therefore
|
|
145
|
+
trivially preserved.
|
|
146
|
+
|
|
147
|
+
## The pivot
|
|
148
|
+
|
|
149
|
+
Choosing the pivot is the genuinely interesting part: the curve's center has to
|
|
150
|
+
mean something across distributions as different as a near-deterministic next
|
|
151
|
+
token and a wide-open one. Three modes, all cheap, exposed as `pivot_mode`
|
|
152
|
+
(default **top-anchored**). The other two ship as documented opt-in modes —
|
|
153
|
+
losing experiments become flags, never deletions.
|
|
154
|
+
|
|
155
|
+
The pivot is computed from the **full, normalized log-prob vector before any
|
|
156
|
+
top-p/top-k masking**, so masked `-inf` entries never contaminate it.
|
|
157
|
+
|
|
158
|
+
1. **`top` — top-anchored (DEFAULT).** `μ = ℓ_max − c`. The curve centers `c`
|
|
159
|
+
nats below the most-probable token. Predictable, scale-free, one `max`
|
|
160
|
+
reduction. `c` is the meaningful knob; default calibration-pending (Piece 5
|
|
161
|
+
sweep).
|
|
162
|
+
2. **`entropy` — entropy-anchored.** `μ = Σ p_i ℓ_i = −H`, the distribution's
|
|
163
|
+
center of mass in tonal space. Auto-exposure: confident contexts (low
|
|
164
|
+
entropy) pull the pivot up near the top; flat contexts push it down. One
|
|
165
|
+
dot-product, information-theoretically natural, less predictable.
|
|
166
|
+
3. **`median` — mass-median.** `μ` = the log-prob at the 50% cumulative-mass
|
|
167
|
+
boundary (literal auto-levels / histogram median). Most adaptive; reuses the
|
|
168
|
+
sort top-p already performs.
|
|
169
|
+
|
|
170
|
+
`width` may likewise be a fixed nat value or, in a later increment, auto-derived
|
|
171
|
+
from the log-prob spread (an "auto-contrast" mode). Default fixed for now.
|
|
172
|
+
|
|
173
|
+
## Temperature semantics
|
|
174
|
+
|
|
175
|
+
When `hlg` is active, the request's `temperature` **folds into the mid gain**:
|
|
176
|
+
`m = 1 / T`. Temperature *is* the mid-tone contrast, and HLG adds the toe and
|
|
177
|
+
shoulder on top of it. This avoids double-applying a slope and preserves the
|
|
178
|
+
intuition that "temperature" still means "how punchy the mids are." With
|
|
179
|
+
rolloff off, `m = 1/T` and `g(z) = z/T` — exactly temperature, as above.
|
|
180
|
+
|
|
181
|
+
## Where it lands in the code
|
|
182
|
+
|
|
183
|
+
Sampling is fully model-agnostic and shared by every model and lane
|
|
184
|
+
([src/sampler.ts](../../src/sampler.ts), post-inference), so this is a single
|
|
185
|
+
transform with no per-model branches.
|
|
186
|
+
|
|
187
|
+
- **The transform** — a new `applyHlg(lp, params)` in
|
|
188
|
+
[src/sampler.ts](../../src/sampler.ts). HLG is a **replacement sampler**:
|
|
189
|
+
`makeSampler` branches `if (hlg.enabled)` → the curve is the *whole*
|
|
190
|
+
post-logits step (its toe does the tail control), `else` → exactly what we
|
|
191
|
+
used to do (top-p, top-k, then `mulScalar(cur, 1/temperature)`). The two are
|
|
192
|
+
mutually exclusive — when HLG is on, top-p/top-k are **not** applied, because
|
|
193
|
+
the smooth toe is their replacement, not a layer on top of them. Branchless:
|
|
194
|
+
compute the toe / mid / shoulder expressions and select on `z` vs `±w` with
|
|
195
|
+
`where`. Follows the file's strict `owned[]` → `dispose()` discipline (every
|
|
196
|
+
intermediate freed; only the chosen token id crosses to JS).
|
|
197
|
+
- **Sampler options** — extend `SamplerOptions`
|
|
198
|
+
([src/sampler.ts:11](../../src/sampler.ts)) with an optional `hlg` sub-object;
|
|
199
|
+
`makeSampler` builds the HLG step when present, else the existing path
|
|
200
|
+
verbatim.
|
|
201
|
+
|
|
202
|
+
Three sampler **construction** sites pass the params through; the
|
|
203
|
+
degeneracy guarantees keep every existing parity gate green:
|
|
204
|
+
|
|
205
|
+
- **Serial** — `makeSampler(options)` in
|
|
206
|
+
[src/generate.ts:218](../../src/generate.ts).
|
|
207
|
+
- **Batched per-row** — `makeSampler(options)` in
|
|
208
|
+
[src/serve/generation-gateway.ts:127](../../src/serve/generation-gateway.ts).
|
|
209
|
+
Each row already owns its sampler closure, so `hlg` params batch per-request
|
|
210
|
+
for free; the draw site in
|
|
211
|
+
[src/serve/batch-scheduler.ts:276](../../src/serve/batch-scheduler.ts) is
|
|
212
|
+
unchanged beyond construction.
|
|
213
|
+
|
|
214
|
+
### MLX op feasibility
|
|
215
|
+
|
|
216
|
+
All elementwise: `exp`, `sub`, `mul`/`mulScalar`, `where`, plus `log` / `log1p`.
|
|
217
|
+
The pivot needs one `max` (top), one dot-product (entropy), or the existing sort
|
|
218
|
+
(median). Cost is O(V) per token — the same order as the existing top-p step,
|
|
219
|
+
negligible against the forward pass, but measured (Piece 5). If `mlx_log1p`
|
|
220
|
+
isn't already bound, bind it from the header first — read the full signature to
|
|
221
|
+
avoid the trailing-stream-arg footgun (CLAUDE.md).
|
|
222
|
+
|
|
223
|
+
## Flag, config, and API surface
|
|
224
|
+
|
|
225
|
+
Conventions per [docs/reference/server-config.md](../reference/server-config.md)
|
|
226
|
+
and `serverRuntimeFlags()` ([src/cli.ts](../../src/cli.ts)).
|
|
227
|
+
|
|
228
|
+
- **CLI**: `--hlg-sampling on|off` (default **off**), plus `--hlg-width`,
|
|
229
|
+
`--hlg-shoulder`, `--hlg-toe`, and the top-anchor offset `--hlg-pivot-offset`
|
|
230
|
+
(the `c` above). There is **no `--hlg-gain`**: the mid gain folds from
|
|
231
|
+
`--temperature` (`m = 1/T`), so temperature stays the one contrast knob and a
|
|
232
|
+
second one would be redundant. `--hlg-pivot top|entropy|median` arrives with
|
|
233
|
+
the alternate pivot modes in Piece 4 (top-anchored is the only mode until
|
|
234
|
+
then). Parsed with the existing `onOff` / `numFlag` helpers; validated (exit
|
|
235
|
+
on bad value); defaults onto `ServerOptions`.
|
|
236
|
+
- **ServerOptions** ([src/server.ts](../../src/server.ts)): an `hlg?` config
|
|
237
|
+
object, resolved in `toOptions` with the standard precedence
|
|
238
|
+
(request > CLI default > model config > built-in), exactly like the existing
|
|
239
|
+
sampling defaults.
|
|
240
|
+
- **Per-request**: an `hlg` object on `ChatRequest` (unknown fields are already
|
|
241
|
+
tolerated), so it works over OpenAI `/v1/chat/completions`, Anthropic
|
|
242
|
+
`/v1/messages`, and `/v1/responses` with no protocol-specific plumbing.
|
|
243
|
+
Example:
|
|
244
|
+
```jsonc
|
|
245
|
+
{
|
|
246
|
+
"temperature": 0.7, // becomes the mid gain m = 1/T
|
|
247
|
+
"hlg": {
|
|
248
|
+
"enabled": true,
|
|
249
|
+
"pivot": "top", "pivot_offset": 6.0,
|
|
250
|
+
"width": 4.0, "shoulder": 4.0, "toe": 6.0
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Correctness & evaluation
|
|
256
|
+
|
|
257
|
+
This is a novel path with **no oracle ancestor**, so it is gated by KL +
|
|
258
|
+
quality + diversity rather than parity — except for the degeneracy gates, which
|
|
259
|
+
*are* parity gates and must be bit-exact.
|
|
260
|
+
|
|
261
|
+
1. **Neutrality gate (bit-exact)** — `tests/hlg-sampling-parity.test.ts`:
|
|
262
|
+
- flag-off ⟹ the sampler code path is byte-identical to today's (`makeSampler`
|
|
263
|
+
unchanged when `hlg` absent);
|
|
264
|
+
- `hlg` in *identity config* (`gain = 1`, rolloff off) reduces to the current
|
|
265
|
+
sampler with `maxDiff === 0`;
|
|
266
|
+
- `hlg` rolloff-off, `gain = 1/T` reduces to temperature `T` bit-exact.
|
|
267
|
+
Run across **all four models** and **both lanes** (serial + batched) — the
|
|
268
|
+
param plumbing differs per lane, the math does not.
|
|
269
|
+
2. **Monotonicity / ranking preservation** — property test over random logits:
|
|
270
|
+
`g` never reorders tokens; argmax invariant; every pairwise ordering held.
|
|
271
|
+
3. **KL characterization** — reuse [src/eval/kl.ts](../../src/eval/kl.ts)
|
|
272
|
+
`evaluateKlSelfFlag` (env lever off vs on) to *characterize* (not pass/fail)
|
|
273
|
+
how far each knob moves the distribution from temperature-only. Output: a
|
|
274
|
+
KL-vs-knob curve per model, recorded for the design log. The distribution is
|
|
275
|
+
*supposed* to move; the point is to map the knob space, not to bound drift.
|
|
276
|
+
4. **Capability guardrail** — `bun scripts/eval.ts capability --candidate e4b`
|
|
277
|
+
(and 12B, the reference target) with HLG on vs off. The six tasks
|
|
278
|
+
(GSM8K / MMLU / IFEval / BFCL / HumanEval / HashHop) are accuracy-shaped, so
|
|
279
|
+
they measure the **cost**: does shaping the distribution break reasoning or
|
|
280
|
+
tool-calling? That is the guardrail HLG must not regress materially.
|
|
281
|
+
5. **Diversity lens (the benefit)** — the six tasks won't show the upside, since
|
|
282
|
+
the whole point is mid-tone novelty. Add a small open-ended eval
|
|
283
|
+
(`src/eval/tasks/diversity.ts`): distinct-n / self-BLEU / cross-sample
|
|
284
|
+
entropy on a creative-prompt set, **HLG vs temperature matched to the same
|
|
285
|
+
output entropy**. The thesis is confirmed iff, at equal entropy, HLG yields
|
|
286
|
+
higher diversity without the tail-garbage temperature would import.
|
|
287
|
+
6. **Perf A/B** — a `bench-compat-vs-perf`-style env-lever A/B plus a
|
|
288
|
+
`./benchmark.sh` row: decode tok/s + TTFT, on vs off, to show ~0 decode
|
|
289
|
+
regression. Lands in [benchmarks/RESULTS.md](../../benchmarks/RESULTS.md) §3.
|
|
290
|
+
|
|
291
|
+
## Phasing (the "piece N" increments)
|
|
292
|
+
|
|
293
|
+
1. **Pure curve + neutrality tests** — `applyHlg(lp, params)` in `sampler.ts`,
|
|
294
|
+
top-anchored pivot only; degeneracy + monotonicity tests green across all
|
|
295
|
+
four models. (No flag wired yet — pure, fully-tested function.)
|
|
296
|
+
2. **Serial wiring** — CLI flags + `ServerOptions` + `toOptions`; live on the
|
|
297
|
+
serial server; per-request `hlg`.
|
|
298
|
+
3. **Batched wiring** — gateway/scheduler sampler construction; batched
|
|
299
|
+
neutrality test.
|
|
300
|
+
4. **Pivot modes 2 & 3** — entropy + median, behind `--hlg-pivot`.
|
|
301
|
+
5. **Eval + benchmark** — KL characterization, capability guardrail, diversity
|
|
302
|
+
lens, perf A/B; set shipped defaults from the sweep; RESULTS.md row.
|
|
303
|
+
6. **Docs** — finalize this doc, the investigation write-up, PLAN/STATUS,
|
|
304
|
+
server-config / server-api / README, and a memory note.
|
|
305
|
+
|
|
306
|
+
## Open questions / risks
|
|
307
|
+
|
|
308
|
+
- **Default knob values** are calibration-pending — set empirically by the
|
|
309
|
+
Piece 5 sweep, not guessed. Initial exploration points: `c ≈ 6`, `w ≈ 4`,
|
|
310
|
+
`β_h ≈ 4`, `β_t ≈ 6` nats; confirm or replace with measured values.
|
|
311
|
+
- **Pivot for very low-entropy distributions** (one token ~1.0): the curve has
|
|
312
|
+
almost nothing to shape; verify it degrades gracefully to "near-greedy" rather
|
|
313
|
+
than amplifying numerical noise in the tail.
|
|
314
|
+
- **HLG replaces top-p/top-k** (resolved, not a rail). When HLG is on it *is*
|
|
315
|
+
the sampler — no top-p/top-k underneath; the toe is the smooth cousin of
|
|
316
|
+
min-p and does the tail control. Open question is whether the soft toe
|
|
317
|
+
suppresses the tail *enough* on a 262k vocab to match the hard cutoffs, or
|
|
318
|
+
whether garbage leaks — exactly what the `hlg-compare` harness probes.
|
|
319
|
+
- **Does the benefit survive the capability tasks?** If HLG measurably helps
|
|
320
|
+
diversity but dents GSM8K/BFCL, it ships default-off with a documented
|
|
321
|
+
use-case (creative/open-ended), not as a global default — consistent with the
|
|
322
|
+
project's default-off-flags ethos.
|
|
323
|
+
|
|
324
|
+
## Provenance — and why the source domain doesn't justify it
|
|
325
|
+
|
|
326
|
+
This is a **cross-domain transplant**. Nonlinear transfer functions are a mature
|
|
327
|
+
apparatus in signal and color encoding for reshaping a value distribution under
|
|
328
|
+
region-dependent constraints; a logit distribution is just another value
|
|
329
|
+
distribution, so the apparatus carries over. HLG (Hybrid Log-Gamma, ARIB
|
|
330
|
+
STD-B67 / ITU-R BT.2100) is the specific structure we lift — a gamma segment for
|
|
331
|
+
the lower range and a logarithmic segment for the upper range, joined at a
|
|
332
|
+
breakpoint — because its piecewise shape maps cleanly onto "boost the mids, roll
|
|
333
|
+
off the extremes."
|
|
334
|
+
|
|
335
|
+
The provenance is where the *structure* comes from; it is **not** the argument
|
|
336
|
+
for it. That a transfer function is standard practice in another domain says
|
|
337
|
+
nothing about whether it helps token sampling — that is decided only by
|
|
338
|
+
measurement (the KL characterization, the capability guardrail, and the
|
|
339
|
+
diversity lens in [Correctness](#correctness--evaluation)). The full empirical
|
|
340
|
+
write-up goes in `docs/investigations/hlg-sampling-investigation.md` once run.
|