Skip to content

Commit 8b06983

Browse files
committed
feat(output-shaper): learn verbosity per-user + counterfactual savings + dashboard
Phase 2 of output-token reduction, built on the Phase 1 shaper: - learn --verbosity: mine Claude Code transcripts for behavioral signals (interrupts, length-adaptive fast-skips, echo ratio), recommend a verbosity level (heuristic prior + optional --llm-judge), and seed the savings baseline. Real data: 11% interrupt / 26% fast-skip -> L3, high confidence. - Counterfactual savings estimator (output_savings.py): per-stratum synthetic control (estimated) + A/B holdout (measured), signed-delta aggregate with a propagated 95% CI. Conversation-stable arm assignment (clean A/B + cache-safe). - AIMD verbosity controller: additive-increase / fast-back-off state machine with hysteresis; live signal emission gated off by default. - Shaper resolves the learned level (env > controller > learned > default); recording rides the existing transforms_applied label channel through the outcome funnel, so all response paths feed the ledger with no RequestOutcome changes. - CLI: headroom output-savings (reduction % + CI, measured vs estimated). - Dashboard: 'Output Tokens Saved' hero card (count, %, CI, measured/estimated). - Docs: simple-words user guide + design doc with the counterfactual methodology. - Tests: 94 new (estimator stats, signal extraction, controller, CLI), all green; 44 existing outcome/dashboard tests still pass. Opt-in: HEADROOM_OUTPUT_SHAPER=1; HEADROOM_OUTPUT_HOLDOUT=0.1 for a measured number.
1 parent 027e1c1 commit 8b06983

18 files changed

Lines changed: 2834 additions & 11 deletions

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Headroom compresses everything your AI agent reads — tool outputs, logs, RAG c
5252
- **MCP server**`headroom_compress`, `headroom_retrieve`, `headroom_stats` for any MCP client
5353
- **Cross-agent memory** — shared store across Claude, Codex, Gemini, auto-dedup
5454
- **`headroom learn`** — mines failed sessions, writes corrections to `CLAUDE.md` / `AGENTS.md`
55+
- **Output token reduction** — trims what the model *writes back* (not just what you send): drops ceremony/restated code and skips deep "thinking" on routine steps. See [Output token reduction](#output-token-reduction-cut-what-the-model-writes-back).
5556
- **Reversible (CCR)** — originals are cached for retrieval on demand
5657

5758
## How it works (30 seconds)
@@ -123,6 +124,54 @@ Granular extras: `[proxy]`, `[mcp]`, `[ml]`, `[code]`, `[memory]`, `[relevance]`
123124

124125
Reproduce: `python -m headroom.evals suite --tier 1` · [Full benchmarks & methodology](https://headroom-docs.vercel.app/docs/benchmarks)
125126

127+
## Output token reduction (cut what the model writes back)
128+
129+
Everything above shrinks the prompt you **send**. But you also pay for every
130+
token the model **writes back** — and on Opus-class models output costs 5× input.
131+
A lot of that output is waste: "Great, let me…" preambles, re-printing code you
132+
just showed it, and deep "thinking" on routine steps like reading a file.
133+
134+
Headroom can trim that too, from the proxy, without you changing any code:
135+
136+
- **Verbosity steering** — appends a short "be terse, don't restate context"
137+
note to the end of the system prompt (so your prompt cache still hits).
138+
- **Effort routing** — when a turn is just the model resuming after a tool result
139+
(a file read, a passing test), it dials the model's thinking effort down. New
140+
questions and errors keep full effort.
141+
142+
Turn it on:
143+
144+
```bash
145+
export HEADROOM_OUTPUT_SHAPER=1 # off by default
146+
headroom proxy --port 8787
147+
```
148+
149+
**Learn the right terseness for you.** People don't *say* how terse they want
150+
answers — they *show* it (they interrupt long replies, or move on before they
151+
could have read them). `headroom learn --verbosity` reads your past sessions and
152+
picks the level automatically:
153+
154+
```bash
155+
headroom learn --verbosity # preview what it found (dry run)
156+
headroom learn --verbosity --apply # save it; the proxy uses it from now on
157+
```
158+
159+
**See how many output tokens you saved.** Output savings are *counterfactual*
160+
we never see what the model *would* have written — so Headroom reports an honest
161+
**estimate with a confidence range**, never a made-up number:
162+
163+
```bash
164+
headroom output-savings
165+
# Reduction: 31.7% (95% CI 27.7% … 35.7%) [estimated]
166+
```
167+
168+
Want a *measured* number instead of an estimate? Leave 10% of conversations
169+
unshaped as a control group: `export HEADROOM_OUTPUT_HOLDOUT=0.1`. The dashboard
170+
shows an **Output Tokens Saved** card next to input compression, labelled
171+
`measured` or `estimated` with the confidence band.
172+
173+
→ Full write-up incl. the measurement methodology: [`docs/proposals/output-token-reduction.md`](docs/proposals/output-token-reduction.md)
174+
126175
<a href="https://www.star-history.com/?repos=chopratejas%2Fheadroom&type=date&legend=top-left">
127176
<picture>
128177
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=chopratejas/headroom&type=date&legend=top-left" />
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Output Token Reduction — User Guide
2+
3+
A plain-English guide to cutting the tokens the model **writes back**.
4+
5+
## Why this exists
6+
7+
Headroom normally shrinks the prompt you **send**. This feature shrinks what the
8+
model **returns**. That matters because:
9+
10+
- Output tokens cost **5× more** than input on Opus-class models.
11+
- A lot of model output is waste: "Great, let me help with that…" intros,
12+
re-printing code you already showed it, restating tool results, and long
13+
internal "thinking" even on trivial steps.
14+
15+
You don't change any code. It runs in the Headroom proxy.
16+
17+
## Turn it on
18+
19+
```bash
20+
export HEADROOM_OUTPUT_SHAPER=1 # off by default
21+
headroom proxy --port 8787
22+
```
23+
24+
That's it. Two things now happen on every request:
25+
26+
1. **Verbosity steering** — a short "be terse, don't restate context" instruction
27+
is added to the **end** of the system prompt. (The end, so your prompt cache
28+
still works.)
29+
2. **Effort routing** — if a turn is just the model continuing after a tool ran
30+
(e.g. it read a file and there were no errors), Headroom turns the model's
31+
"thinking effort" down for that one turn. Real questions and error-handling
32+
turns keep full effort.
33+
34+
## The verbosity dial (levels 0–4)
35+
36+
| Level | What the model is told | Good for |
37+
|------:|------------------------|----------|
38+
| 0 | (off) | disable steering |
39+
| 1 | Skip the intro/outro chit-chat | people who read everything |
40+
| 2 | Also: don't restate code/output already on screen | **default** — safe |
41+
| 3 | Also: conclusions only, skip the reasoning | people who skim |
42+
| 4 | Bare minimum, fragments OK | maximum savings, terse |
43+
44+
Set it by hand if you want:
45+
46+
```bash
47+
export HEADROOM_VERBOSITY_LEVEL=3
48+
```
49+
50+
Or — better — let Headroom learn it from your habits (next section).
51+
52+
## Let Headroom pick the level for you
53+
54+
People rarely *say* "be brief." They *show* it: they interrupt long answers, or
55+
reply so fast they couldn't have read the whole thing. `headroom learn
56+
--verbosity` reads your past sessions and picks a level from those signals.
57+
58+
```bash
59+
# Preview what it found (doesn't change anything)
60+
headroom learn --verbosity
61+
62+
# Save it — the proxy uses this level from now on
63+
headroom learn --verbosity --apply
64+
```
65+
66+
Example output:
67+
68+
```
69+
Verbosity — headroom
70+
Interrupts: 29 (11% of turns) ← push-back signal
71+
Fast-skips: 31 / 119 long answers (26% unread) ← strongest signal
72+
>> Recommended verbosity level: 3 (confidence: high)
73+
```
74+
75+
Add `--llm-judge` to have an LLM double-check the level (needs an API key).
76+
77+
## See how much you saved
78+
79+
Here's the honest part. We **can't directly measure** output savings — we never
80+
see what the model *would* have written without our nudge. So Headroom reports an
81+
**estimate with a confidence range**, never a fake exact number:
82+
83+
```bash
84+
headroom output-savings
85+
```
86+
87+
```
88+
Output-token reduction
89+
Method: ESTIMATED (synthetic control)
90+
Requests: 1,240 shaped
91+
Saved: ~410,000 output tokens
92+
Reduction: 28.0% (95% CI 24.1% … 31.9%)
93+
```
94+
95+
- **ESTIMATED** = compared against a baseline of your past (unshaped) sessions.
96+
- **MEASURED** = the gold standard, if you opt into a holdout (below).
97+
98+
### Want a *measured* number?
99+
100+
Leave a slice of traffic unshaped as a control group:
101+
102+
```bash
103+
export HEADROOM_OUTPUT_HOLDOUT=0.1 # 10% of conversations stay unshaped
104+
```
105+
106+
Now `headroom output-savings` compares shaped vs unshaped directly and reports a
107+
**measured** reduction. The trade-off: you give up the savings on that 10%.
108+
109+
## On the dashboard
110+
111+
Open `http://localhost:8787/dashboard`. Next to the input-compression card
112+
you'll see an **Output Tokens Saved** card showing the token count, the percent,
113+
a `measured`/`estimated` badge, and the confidence range.
114+
115+
## FAQ
116+
117+
**Will this make answers worse?**
118+
At level 2 (default), no — in our tests the model finds the same bugs and writes
119+
the same fixes; it just stops re-printing code and skipping the "let me…" intro.
120+
Levels 3–4 are terser by design; that's why learning the level per user matters.
121+
122+
**Does it break prompt caching?**
123+
No. The steering text is added at the *end* of the system prompt and is
124+
byte-stable, so your cached prefix is untouched.
125+
126+
**Is it safe with extended thinking / tool loops?**
127+
Yes. It never disables thinking outright (that can error), it only lowers effort
128+
on routine turns, and it never adds settings the model doesn't support.
129+
130+
**How do I turn it off?**
131+
Unset `HEADROOM_OUTPUT_SHAPER` (or set it to `0`) and restart the proxy. You can
132+
also send `x-headroom-bypass: true` on a request to skip it for that call.
133+
134+
---
135+
136+
Deep dive (design + the counterfactual math): [`proposals/output-token-reduction.md`](proposals/output-token-reduction.md)

0 commit comments

Comments
 (0)