What Is Prompt Compression?
Prompt compression reduces the number of tokens sent to a large language model while preserving the information needed for a correct answer. Unlike summarization by the same LLM you are about to call, compression usually runs through a smaller model, classifier, or structure-aware algorithm before the expensive inference step.
Targets include:
- Long system prompts and few-shot examples (redundant phrasing, low-information demonstrations)
- RAG retrieved chunks (overlapping passages, boilerplate headers)
- Agent tool outputs (JSON blobs, logs, search hits, file dumps)
- Conversation history (stale turns that still fit in window but waste budget)
Compression is distinct from context window extension (e.g. sliding windows, memory stores). It makes existing context denser. It is complementary to KV-cache optimization, quantization, and smaller models.
Refer: Prompt Compression Survey · LLMLingua paper
Why It Matters
- Cost - API pricing is per token; input tokens dominate RAG and agent workloads.
- Latency - prefill time scales with prompt length; shorter prompts mean faster time-to-first-token (TTFT).
- Context limits - even 128k windows fill up in agent loops; compression buys headroom for reasoning and tools.
- Signal-to-noise - models attend better when redundant tokens are removed (related to lost-in-the-middle effects in bloated context).
- Downstream model choice - aggressive compression can let a cheaper model handle tasks that previously needed a frontier model.
How Compression Works (General)
Methods fall into several families:
| Family | Idea | Examples |
|---|---|---|
| Perplexity / information filtering | Remove tokens a small LM finds predictable (low surprise) | LLMLingua v1, SelectiveContext |
| Token classification | Classifier predicts keep/drop per token | LLMLingua-2 |
| Query-aware selection | Reorder or filter context based on the user question | LongLLMLingua |
| Structure-aware crushing | Preserve schema, signatures, errors; compress boilerplate | Headroom SmartCrusher, CodeAwareCompressor |
| Extractive summarization | LLM or SLM produces shorter paraphrase | Various; higher latency, risk of hallucinated drops |
Most production stacks compress before the target LLM call and treat the compressor as a separate service with its own CPU/GPU budget.
When to Use Compression
Good fits
- RAG with many retrieved chunks (10+ passages, repeated doc templates)
- Few-shot prompts with long demonstrations
- Agents that dump full JSON API responses, CI logs, or repo search results into context
- High-volume chat with long histories where older turns are low value
- Cost-sensitive batch jobs (classification, extraction) with repetitive instructions
Poor fits
- Short prompts already near minimum tokens
- Tasks requiring verbatim quotes, legal text, or exact code diff fidelity without retrieval fallback
- Highly entangled reasoning where every token carries nuance (some math proofs, subtle policy interpretation)
- When you have not validated compression on your domain (medical, financial, locale-specific jargon)
When to combine tools
Use LLMLingua for natural-language prompt bodies (instructions + demonstrations + question). Use Headroom for agent pipelines heavy on tool outputs, logs, JSON, and code. Many agent stacks run Headroom on tool results and LLMLingua on the final assembled prompt.
LLMLingua (Microsoft Research)
LLMLingua is a research-backed prompt compression framework. It works with black-box LLMs because compression uses an external small language model; only the shortened text is sent to GPT-4, Claude, etc.
LLMLingua (v1)
Coarse-to-fine pipeline on prompts structured as {Instruction, Demonstrations, Question}:
- Budget controller - allocates compression budget across prompt parts (few-shot examples compressed more aggressively than core instructions).
- Demonstration-level filtering - small LM perplexity scores sentences; low-surprise (predictable) content is dropped first.
- Iterative token-level compression - remaining segments compressed token-by-token using conditional perplexity, preserving interdependent phrases better than one-shot filtering.
- Distribution alignment - optional tuning so compressed prompts align with target LLM behavior.
Reported results: up to 20x compression with small accuracy loss on benchmarks like GSM8K, BBH, ShareGPT. Best when prompts contain redundant natural language and long ICL examples.
LongLLMLingua
Extends LLMLingua for long-context RAG. Query-aware compression reorders and prioritizes chunks so question-relevant evidence sits where the target LLM attends reliably, mitigating lost-in-the-middle. Use when retrieved context spans thousands of tokens and the user question is known at compression time.
LLMLingua-2
Task-agnostic compression formulated as token classification. A bidirectional encoder (e.g. XLM-RoBERTa-sized) trained via distillation from GPT-4 labels which tokens to keep. Typically 3-6x faster than v1 and stronger on out-of-domain text. Recommended default for new projects unless you specifically need LongLLMLingua query routing.
Key features
- Configurable compression
rate(target fraction of tokens to keep) force_tokensto preserve punctuation, newlines, or domain delimitersdrop_consecutiveto collapse repeated tokens after compression- Works without white-box access to the downstream LLM
- Open-source Python package:
pip install llmlingua
How to use LLMLingua
pip install llmlingua
from llmlingua import PromptCompressor
# LLMLingua-2 (recommended starting point)
compressor = PromptCompressor(
model_name="microsoft/llmlingua-2-xlm-roberta-large-meetingbank",
use_llmlingua2=True,
)
long_prompt = """
Instruction: Answer using the examples below.
...
[thousands of tokens of few-shot examples and context]
...
Question: What is the refund policy for enterprise tier?
"""
result = compressor.compress_prompt(
long_prompt,
rate=0.5, # keep ~50% of tokens
force_tokens=["\n", ".", "?"],
drop_consecutive=True,
)
compressed = result["compressed_prompt"]
print(result["origin_tokens"], "->", result["compressed_tokens"])
LongLLMLingua example (RAG)
compressor = PromptCompressor(
model_name="NousResearch/Llama-2-7b-hf",
use_llmlingua2=False,
)
compressed = compressor.compress_prompt(
context=retrieved_documents, # long multi-doc string
question=user_query,
rate=0.55,
condition_in_question="after_condition",
reorder_context="sort",
dynamic_context_compression_ratio=0.3,
)
LLMLingua pros and cons
| Pros | Cons |
|---|---|
| Strong on NL prompts and few-shot bloat; well-studied academically | Extra SLM load (memory, latency) before main LLM call |
| Black-box compatible with any API model | Compressor tokenizer may differ from target model |
| LLMLingua-2 is fast and task-agnostic | Can drop rare but critical tokens (IDs, uncommon entity names) |
| LongLLMLingua helps long RAG contexts | Less specialized for raw JSON/logs than Headroom |
Headroom
Headroom is an open-source context compression layer for AI agents. It targets tool outputs, logs, RAG chunks, files, and conversation history before they reach the LLM. Typical savings: 60-95% on JSON/search results, 15-70% on code-heavy agent traces, with a focus on preserving errors, stack traces, and structurally important fields.
Refer: Headroom GitHub · Headroom docs
What makes Headroom different
- Content-aware routing - detects JSON, code, logs, search results, HTML, plain text and picks a specialized compressor.
- CCR (Compress-Cache-Retrieve) - aggressive compression with originals stored; LLM gets a
headroom_retrievetool to fetch full content on demand. Nothing is permanently destroyed. - CacheAligner - stabilizes static prefixes so provider prompt caching (e.g. Anthropic cached reads) still hits while dynamic tail is compressed.
- Live-zone compression - compresses newest tool results and user turns without rewriting the cache-hot system prompt and tool definitions.
- Agent-first integrations - library, HTTP proxy, MCP server, one-command wraps for Claude Code, Cursor, Codex, etc.
Compression pipeline
- CacheAligner - separates dynamic tokens (dates, session vars) from static system prompt prefix.
- ContentRouter - routes each message block to a compressor:
| Content type | Compressor | Typical reduction | Preserves |
|---|---|---|---|
| JSON arrays / API payloads | SmartCrusher | 70-90% | Keys, structure, high-variance values |
| Source code | CodeAwareCompressor | 40-70% | Signatures, imports, AST-critical spans |
| grep / search results | SearchCompressor | 80-95% | Matching lines, file paths |
| Build / CI logs | LogCompressor | 85-95% | Errors, stack traces, FATAL lines |
| Plain text | Text utilities / LLMLingua | 60-80% | High-entropy tokens |
IntelligentContext (optional) scores messages by recency, relevance, and error signals to drop lowest-value history when still over budget.
Integration modes
1. Python library
pip install headroom-ai
from headroom import compress
messages = [
{"role": "system", "content": "You are a debugging assistant."},
{"role": "user", "content": "Why did deploy fail?"},
{"role": "tool", "content": huge_ci_log_string},
]
optimized, stats = compress(messages)
print(stats.tokens_before, stats.tokens_after, stats.compression_ratio)
2. Transparent proxy
pip install "headroom-ai[proxy]"
headroom proxy --port 8787 --mode token
# Point your OpenAI/Anthropic client base URL to localhost:8787
# Requests are compressed automatically before forwarding
--mode token maximizes compression. --mode cache freezes prior turns to preserve provider prefix-cache bytes on long conversations.
3. Compression-only HTTP API
# POST http://localhost:8787/v1/compress
# Body: {"messages": [...]}
# Returns tokens_before, tokens_after, compressed messages
4. MCP server
Tools: headroom_compress, headroom_retrieve, headroom_stats for any MCP-compatible agent client.
5. Agent wrap
headroom wrap claude # one-command wrapper for supported agents
headroom unwrap claude
Headroom + RAG example
from headroom import compress
rag_chunks = load_retrieved_chunks() # 40k tokens of HTML + metadata
tool_message = format_chunks_as_tool_output(rag_chunks)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_question},
{"role": "tool", "content": tool_message},
]
compressed_messages, stats = compress(
messages,
enable_ccr=True, # store originals for headroom_retrieve
)
response = llm.invoke(compressed_messages)
# Model can call headroom_retrieve if it needs a full passage
Headroom pros and cons
| Pros | Cons |
|---|---|
| Excellent on agent tool output, logs, JSON, search hits | Another moving part in the agent stack (proxy/service to operate) |
| CCR gives reversible compression; model can pull originals | CCR store needs sizing, retention, and security policies |
| CacheAligner pairs well with provider prompt caching | Savings vary; short prompts see little benefit |
| Drop-in proxy, MCP, and agent wrappers | Code-aware mode needs optional headroom-ai[code] extra |
| Apache 2.0, local-first, auditable | Less research literature than LLMLingua for pure NL few-shot |
LLMLingua vs Headroom
| Dimension | LLMLingua | Headroom |
|---|---|---|
| Primary focus | Natural-language prompt compression | Agent context and tool outputs |
| Best input | Instructions, few-shot, long NL context | JSON, logs, code, RAG chunks, search results |
| Reversibility | Lossy by default | CCR store + retrieve tool |
| Query-aware RAG | LongLLMLingua | Content routing + optional context scoring |
| Deployment | Python library in your app | Library, proxy, MCP, agent wrap |
| Prompt cache optimization | Not a core feature | CacheAligner built in |
| Typical stack role | Pre-LLM prompt shrinker | Middleware on agent message list |
They are complementary, not mutually exclusive.
Production Patterns
RAG Q&A API
- Retrieve top-k chunks (hybrid search + rerank).
- Run LongLLMLingua or LLMLingua-2 on assembled context with the user question.
- Optionally run Headroom if chunks include HTML tables, JSON metadata, or logs.
- Call target LLM with compressed context; log compression ratio and faithfulness scores.
Coding agent
- Wrap agent with Headroom proxy or
compress()on each tool result. - Enable CCR so the model can retrieve full files when diffs reference missing lines.
- Use
--mode cacheon long sessions to protect prefix-cache discounts.
High-volume extraction
- Fixed instruction prefix (cached at provider).
- Compress variable few-shot block with LLMLingua-2 at rate tuned on eval set.
- Batch requests; track $/successful extraction.
Evaluation Checklist
- Build a golden set (50-200 examples) with task-specific success criteria.
- Sweep compression rates (0.3, 0.5, 0.7) and measure accuracy, not just tokens.
- Track latency end-to-end: compression + LLM; compression can add 50-500ms.
- Log failure modes: dropped numbers, wrong entity, missed tool argument.
- A/B in shadow mode before enabling compression for all traffic.
- For Headroom CCR, test that retrieve tool is invoked when answers need verbatim detail.
Summary: What, Why, How, When
| LLMLingua | Headroom | |
|---|---|---|
| What | SLM/classifier-based NL prompt compressor | Agent context compression layer with typed compressors + CCR |
| Why | Cut tokens on instructions, ICL, long NL context | Cut tokens on tool output, logs, JSON, code, RAG blobs |
| How | PromptCompressor.compress_prompt() | compress(), proxy, MCP, or agent wrap |
| When | RAG NL passages, few-shot bloat, batch templates | Agents, devtools, log-heavy workflows, structured API dumps |