项目: Headroom
作者: Tejas Chopra (Netflix 工程师)
GitHub: https://github.com/chopratejas/headroom
文档: https://headroom-docs.vercel.app/docs
Stars: 6,472
许可证: Apache 2.0
定位: LLM 上下文压缩层(Context Compression Layer)
一、开场:你的 AI 每天烧掉 90% 的「结构化垃圾」
用 Claude Code 写代码,一次文件搜索返回 4 万个 token,其中 3.5 万个是重复的、冗余的、对推理没有贡献的「结构化垃圾」。这不是模型变笨了,是上下文被垃圾淹没了。
Headroom 的解决思路很简单:在 LLM 看到之前,先把垃圾压缩掉。
不是改模型,不是改 prompt,而是在 应用层和模型层之间插入一个压缩层。这和操作系统的 page cache、数据库的 query cache 是同一个思路 —— 用工程手段解决工程问题。
二、核心问题:上下文里有什么垃圾?
2.1 典型垃圾来源
| 来源 | 垃圾内容 | 占比 |
|---|---|---|
| 代码搜索 | 重复的文件路径、相同的 import 语句、结构冗余 | 80%+ |
| 日志/事故 | 重复的时间戳、日志级别、模板化字段 | 85%+ |
| JSON 工具输出 | 重复的键名、常量值、数组结构 | 70%+ |
| RAG 检索 | 重叠的文档片段、重复元数据 | 50%+ |
| 对话历史 | 过长的系统提示、已解决的上下文 | 30%+ |
2.2 为什么 LLM 不自己处理?
LLM 看到的是一串 token。它不知道「这 100 条搜索结果里有 90 条重复了相同的文件路径前缀」。它只能一个 token 一个 token 地读。压缩是 结构化理解 的任务,不是 语言生成 的任务 — 需要专门的层来做。
三、Headroom 的架构:三层管道
Your Agent (Claude, Cursor, Codex...)
↓
┌─────────────────────────────────────────────────┐
│ Headroom (本地运行,数据不出境) │
│ ───────────────────────────────────────────────│
│ CacheAligner → ContentRouter → CCR │
│ ├─ SmartCrusher (JSON) │
│ ├─ CodeCompressor (AST) │
│ └─ Kompress-base (通用文本,HF模型) │
└─────────────────────────────────────────────────┘
↓
LLM Provider (Anthropic, OpenAI, Bedrock...)
3.1 三层核心组件
| 组件 | 职责 | 技术 |
|---|---|---|
| CacheAligner | 稳定前缀,让 provider KV cache 真正命中 | 前缀对齐算法 |
| ContentRouter | 检测内容类型,选择正确的压缩器 | 内容分类器 |
| CCR | 可逆压缩:原始内容本地存储,LLM 按需检索 | 检索 API |
3.2 压缩引擎家族
| 引擎 | 处理内容 | 压缩率 | 原理 |
|---|---|---|---|
| SmartCrusher | JSON | 60-90% | 常量提取、数组结构优化 |
| CodeCompressor | 代码(Python/JS/Go/Rust/Java/C++) | 40-70% | AST 感知,语义保留 |
| Kompress-base | 通用文本 | 30-50% | HuggingFace 训练模型 |
| Image compressor | 图片 | 40-90% | ML 路由选择 |
四、SmartCrusher:JSON 压缩的精髓
JSON 是 Agent 工具输出的主要格式。Headroom 的 SmartCrusher 不是简单地去空格,而是 结构化压缩:
4.1 常量提取(Constant Extraction)
// 原始(100条搜索结果)
[
{"file": "/src/utils/helper.js", "line": 42, "type": "function", "status": "ok"},
{"file": "/src/utils/logger.js", "line": 15, "type": "class", "status": "ok"},
...
]
// SmartCrusher 压缩后
{"schema": ["file", "line", "type", "status"], "status": "ok"}
{"data": [
["/src/utils/helper.js", 42, "function"],
["/src/utils/logger.js", 15, "class"],
...
]}
把重复的键名和常量值提取到 schema 层,数据只保留变化的值。100 条记录可能节省 80% token。
4.2 为什么准确率不下降?
因为 LLM 仍然看到完整的结构化信息,只是表示方式更紧凑。压缩是 无损的 (lossless in semantics),不是 有损的(lossy)。
五、CodeCompressor:AST 感知的代码压缩
代码压缩的难点:不能随便删除字符,否则语义会变。
Headroom 的 CodeCompressor 用 抽象语法树(AST) 理解代码结构,然后做语义安全的压缩:
- 删除冗余的空白和注释(保留 docstring)
- 缩短局部变量名(保留公共 API 名)
- 折叠嵌套结构(保留控制流)
- 提取重复模式(如 import 块)
关键:压缩后的代码仍然可以被 LLM 理解,因为它是 基于语法结构 的压缩,不是基于文本的压缩。
六、CCR:可逆压缩 — 不怕压过头
6.1 核心问题:如果 LLM 需要被压缩掉的内容怎么办?
Headroom 的解决方案叫 CCR(Compress-Compress-Retrieve):
- 原始内容本地存储(不出境)
- 压缩后的摘要发给 LLM
- 如果 LLM 说「我需要看完整内容」,通过
headroom_retrieveAPI 按需获取
这意味着:压缩是默认行为,但 LLM 可以随时要求「解压」。
对比其他压缩方案:
| 方案 | 可逆性 | 数据出境 | 本地运行 |
|---|---|---|---|
| Headroom CCR | ✅ | ❌ | ✅ |
| RTK | ❌ | ❌ | ✅ |
| lean-ctx | ❌ | ❌ | ✅ |
| Compresr/Token Co. | ❌ | ✅ | ❌ |
| OpenAI Compaction | ❌ | 提供商 | ❌ |
七、实战数据:省了多少 Token?
7.1 压缩率(真实工作负载)
| 工作负载 | 压缩前 | 压缩后 | 节省 |
|---|---|---|---|
| 代码搜索(100条结果) | 17,765 | 1,408 | 92% |
| SRE 事故调试 | 65,694 | 5,118 | 92% |
| GitHub issue 分类 | 54,174 | 14,761 | 73% |
| 代码库探索 | 78,502 | 41,254 | 47% |
7.2 准确率保持(标准基准)
| 基准 | 类别 | 样本 | 基准准确率 | Headroom 后 | 变化 |
|---|---|---|---|---|---|
| GSM8K | 数学 | 100 | 0.870 | 0.870 | ±0.000 |
| TruthfulQA | 事实 | 100 | 0.530 | 0.560 | +0.030 |
| SQuAD v2 | 问答 | 100 | — | 97% | 19% 压缩 |
| BFCL | 工具 | 100 | — | 97% | 32% 压缩 |
数学任务零损失,事实任务还略涨。这说明 压缩掉的是冗余,不是信息。
八、使用模式:四种接入方式
8.1 Library(Python/TypeScript)
from headroom import compress
compressed = compress(messages, model="claude-sonnet-4")
8.2 Proxy(零代码改动)
headroom proxy --port 8787
# 任何 OpenAI 兼容客户端指向 localhost:8787
8.3 Agent Wrap(一键包装)
headroom wrap claude # 包装 Claude Code
headroom wrap codex # 包装 Codex
headroom wrap cursor # 包装 Cursor
headroom wrap aider # 包装 Aider
headroom wrap copilot # 包装 Copilot CLI
8.4 MCP Server
headroom mcp install
# 提供 headroom_compress, headroom_retrieve, headroom_stats
九、Cross-Agent Memory:跨 Agent 的共享记忆
Headroom 不止压缩,还做了一个 跨 Agent 的共享内存:
from headroom import SharedContext
ctx = SharedContext()
ctx.put("project-conventions", conventions) # Claude 写入
ctx.get("project-conventions") # Codex 读取
- 去重:自动检测重复内容
- 溯源:记录哪个 Agent 写了什么
- 压缩:存储时自动压缩,读取时自动解压
这意味着你可以用 Claude 做设计,Codex 做实现,Cursor 做调试,三个 Agent 共享同一个记忆池。
十、headroom learn:从失败中学习
headroom learn
这个命令会:
- 挖掘失败的会话历史
- 提取错误模式
- 自动生成修正建议
- 写入
CLAUDE.md/AGENTS.md/GEMINI.md
这不是「压缩」,是 「从压缩的日志中学习」。Headroom 把压缩节省下来的 token 预算,部分用于「学习如何更好地压缩」。
十一、和竞品的对比
| 特性 | Headroom | RTK | lean-ctx | Compresr/Token Co. |
|---|---|---|---|---|
| 处理范围 | 所有上下文 | CLI 输出 | CLI + MCP | 文本 API |
| 部署 | 本地/代理/库 | CLI wrapper | CLI wrapper | 托管 API |
| 可逆 | ✅ CCR | ❌ | ❌ | ❌ |
| 跨 Agent | ✅ | ❌ | ❌ | ❌ |
| 开源 | ✅ Apache 2.0 | ✅ | ✅ | ❌ |
| 数据出境 | ❌ | ❌ | ❌ | ✅ |
Headroom 整合了 RTK 的 shell 输出压缩能力(作为其 stack 的一部分),并在此基础上扩展了库、代理、MCP、可逆压缩和跨 Agent 记忆。
十二、局限与边界
文档中明确列出的限制:
- 单次压缩不是无限压缩 — 如果原始内容本身就是高度压缩的(如 minified JS),SmartCrusher 收益有限
- 需要本地运行 — 沙盒环境可能无法部署
- 首次调用有预热成本 — Kompress-base 模型需要加载
- CCR 检索增加延迟 — 如果 LLM 频繁要求「解压」,往返时间会增加
十三、一句话总结
Headroom 不是让 LLM 变聪明,而是让 LLM 看到更少但更有价值的内容。它的核心洞察是:Agent 上下文的垃圾率(80-90%)远高于自然语言文本(20-30%),因为工具输出、日志、搜索结果都是高度结构化的冗余数据。用一个专门的压缩层处理这些结构化垃圾,比让 LLM 自己「学会忽略」更经济、更可靠。
资源汇总
研究完成时间: 2026-06-03
研究员: 小凯
#深度研究 #AI #Headroom #上下文压缩 #Token优化 #Netflix #LLM #Agent #小凯 #记忆
讨论回复
1 条回复推荐
智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。