compression with a quality contract

Output & I/O

Distil now compresses both sides of the bill: input tokens going in, and output tokens coming back. This page covers output compression, real-trace ingestion, and the performance benchmark.

Distil compresses both input and output tokens

Both sides of the bill

Classic context compression only addresses the input side — the tokens you send to the model. That leaves half the invoice untouched. Distil's output compression closes the loop:

Input side

Context compression

Tier-0/1 lossless transforms + cache-aware pruning. Cuts input tokens by ~30%, losslessly, without busting the prefix cache. Always on.

Output side

Generation shaping

A gated role:"system" directive shapes verbosity before generation. A/B measured: −72.5% output tokens (95% CI 67.5–77.1%), answer preserved 100%.

Combined effect: for a typical agentic workload where input and output costs are roughly equal, compressing both sides can cut total API spend by 50%+ per run — without any change to application logic.

Output compression

Module: distil/output.py

Output compression has two mechanisms that work together:

Generation-side shaping (--shape-output)

Before the request is forwarded to the model, the proxy injects a role:"system" directive that instructs the model to be concise. Two modes:

PAYG-only: output shaping requires a pay-as-you-go API key. The proxy detects subscription keys and silently skips injection — it never attempts to shape output in a context where injecting a system directive would be disallowed or ineffective.
# Start the proxy with aggressive output shaping
$ python -m distil.proxy --port 8788 --shape-output aggressive
distil proxy listening on http://127.0.0.1:8788
  → upstream: https://api.anthropic.com
  → output shaping: aggressive (PAYG-only; will verify key tier on first request)

Lossless re-entry digest

When the model's output is long and is about to be re-injected as history in the next turn, Distil compresses it using the same Tier-1 digest mechanism used for input blocks: the full output is stored in the local RestoreStore under an 8-hex handle, and only the handle is forwarded as history. The model never sees the full prior output again — it sees the digest. On demand, the original expands from the handle.

This is fully lossless and transparent to the application. The output digest is re-expanded on any path that reads history (e.g. certify, replay, or export).

Measuring output savings

$ distil output-savings --mode aggressive
output-token A/B — mode=aggressive | runner=anthropic | n=8 turns

  baseline mean output tokens:   487
  shaped   mean output tokens:   134

  reduction: 72.5%  [95% CI: 67.5%–77.1%]
  answer preserved: 100%  (semantic match gate, n=8)

note: realized savings require --runner anthropic (live model).
      offline --runner deterministic gives a lower-bound proxy only.
Honest note on measurement: the 72.5% figure is a live A/B result from --runner anthropic. The offline deterministic runner cannot measure output length because generation is not simulated — it uses ground-truth markers. Always verify output savings with a live run against your own workload.

Real-trace ingestion

Module: distil/ingest.py · Command: distil ingest

Distil ships with a bundled synthetic corpus, but your production workload may differ significantly. distil ingest converts your own recorded API request logs into a Distil corpus so you can measure savings on real traffic.

Supported formats

The format is auto-detected from the first record; pass --format anthropic or --format openai to override.

Grouping into trajectories

Ingest groups records into trajectories by session_id (or x-session-id header if present in metadata). Records without a session ID are each treated as a single-turn trajectory.

$ distil ingest --input prod.jsonl --out ./mycorpus
ingesting prod.jsonl → ./mycorpus

  format detected: anthropic
  records read:    1,204
  trajectories:       42  (grouped by session_id)
  skipped:             3  (malformed or missing messages field)

corpus written to ./mycorpus/

Benchmarking real traces

Real-trace corpora have no DECISION labels, so the offline non-inferiority gate cannot run. Use --savings-only to get input-token savings; certify quality with a live runner:

# Savings-only gate on real traces (no DECISION labels needed)
$ distil bench --corpus ./mycorpus --savings-only
corpus gate — 42 trajectories | savings-only (no DECISION labels)

  aggregate savings: 28.3%  [95% CI: 25.1%–31.6%]
  note: certify with --runner anthropic for a live quality gate.

# Live quality gate on a single trajectory from your corpus
$ distil certify --trajectory ./mycorpus/session_abc123.json --runner anthropic
certifying strategy 'distil' on 'session_abc123' (runner=anthropic)
  ...
VERDICT: PASS  (certified non-inferior)

Performance benchmark

Module: distil/perf.py · Command: distil perf

Distil is designed to add negligible latency to the critical path. The performance benchmark measures the raw compression throughput and the per-request overhead of the in-process adapter.

~27k/s
distil-compressions per second
0.006ms
in-process adapter p50 latency
0.018ms
in-process adapter p99 latency
$ distil perf
distil performance benchmark

  compressor throughput:   ~27,000 distil-compressions/sec
  in-process adapter p50:  0.006 ms
  in-process adapter p95:  0.011 ms
  in-process adapter p99:  0.018 ms

  (measured on Apple M-series, CPython 3.12, bundled sre-disk-incident trajectory)

At 0.006 ms p50, the in-process adapter adds less than 1% to a typical LLM round-trip (which is measured in seconds). The proxy path adds a small additional network hop but the compression itself is the same cost.

What the benchmark measures: the bundled sre-disk-incident trajectory (4 turns, ~8,000 tokens) is compressed in a tight loop with no warm-up exclusion. The throughput number reflects realistic multi-turn context, not a trivial microbenchmark. Run distil perf on your own hardware to get a machine-specific baseline.

Quick reference

Command / FlagWhat it does
distil output-savingsMeasure realized output-token reduction via live A/B
proxy --shape-output light|aggressiveEnable generation-side verbosity shaping (PAYG-only)
distil ingest --input <file> --out <dir>Convert production API logs into a Distil corpus
bench --corpus <dir> --savings-onlySavings gate on a real-trace corpus (no labels required)
distil perfThroughput and latency benchmark