首页
/ Headroom 基准测试指南:压缩性能、准确率验证与可复现的评测方法

Headroom 基准测试指南:压缩性能、准确率验证与可复现的评测方法

2026-09-06 18:24:57作者:董灵辛Dennis

Headroom 的核心承诺是"压缩上下文但不损失准确率"。本篇技术文章以仓库中 wiki/benchmarks.md 为骨架,完整讲解三类评测结果——压缩性能、HTML 抽取准确率、QA 准确率保持——以及 token 级 F1 等评测方法学,并基于仓库源码(headroom/evals/headroom/transforms/benchmarks/)说明每个指标是如何计算与验证的。读完之后,你可以自行在本仓库中复现全部基准数据,并判断 Headroom 在自己的工作负载下是否值得引入。

评测总览:两个正交的问题

一个上下文压缩方案必须同时回答两个问题:

  1. 压缩了多少:Token 节省比例、压缩延迟;
  2. 准确率是否保持:压缩后 LLM 对同一上下文还能否给出同样的答案。

Headroom 的评测围绕这两个问题展开,全部可以从仓库中复现。关键结论先行:在 Scrapinghub 文章抽取基准上,Headroom 的 HTMLExtractor 达到 98.2% Recall、94.9% 压缩率(F1 0.919,trafilatura 基线 0.958),且在 QA 任务上抽取后的内容准确率不降反升。


压缩性能:compress() 在不同内容类型上的表现

官方文档标注的测试环境为 Apple M 系列 CPU,headroom v0.5.18,每个测试对真实工具输出调用 compress()。完整数据如下:

内容类型 原始 token 压缩后 节省 比例 延迟
JSON 数组(100 项) 3,163 297 2,866 90.6% 1ms
JSON 数组(500 项) 9,526 1,614 7,912 83.1% 2ms
Shell 输出(200 行) 3,238 469 2,769 85.5% 1ms
构建日志(200 行) 2,412 148 2,264 93.9% 1ms
grep 结果(150 处命中) 2,624 2,624 0 0.0% <1ms
Python 源码(约 480 行) 2,958 2,958 0 0.0% <1ms
合计 23,921 8,110 15,811 66.1% 5ms

两个值得注意的 0% 行:

  • grep 结果与 Python 源码压缩率为 0——它们本身就是紧凑的结构化格式。SmartCrusher 只压缩 JSON 数组;代码走 passthrough 路径以保留正确性;
  • 延迟是 compress() SDK 调用的耗时,不包含完整代理链路的往返时间

从源码看:compress() 与默认管线

表格中的"压缩后"数字来自 compress() 这一个函数 API:无需代理、无需配置,传入 messages 即返回压缩后的 messages 与 tokens_savedcompression_ratio 等指标。从 headroom/compress.py 的管线初始化可以看到默认管线结构:

CacheAligner → ContentRouter
  • CacheAligner 稳定请求前缀,使上游 KV/prompt cache 能命中;
  • ContentRouter 按内容类型路由到具体压缩器——JSON 走 SmartCrusher,代码走 CodeCompressor,文本走 Kompress(ONNX 模型压缩)。

这也解释了表格中"为什么只有部分行有压缩":路由层按内容类型决定走哪个压缩器,紧凑格式直接透传。另外,compress() 内部有明确的保护逻辑:CompressConfig.min_tokens_to_compress 默认 250(低于该长度的消息不动)、protect_recent 默认 4(最近 4 条消息不压),并且在 token 数出现膨胀时直接回退原始消息(inflation guard,见 headroom/compress.py)——这与文档"短消息不压缩,因为开销大于收益"的表述一致。


准确率基准

HTML 抽取(Scrapinghub Article Extraction Benchmark)

  • 数据集:Scrapinghub Article Extraction Benchmark(HuggingFace 上的 allenai/scrapinghub-article-extraction-benchmark),181 个带 ground truth 正文的 HTML 页面;
  • 基线:trafilatura,0.958 F1。
指标 数值 含义
F1 0.919 与 ground truth 的 token 级重叠
Precision 0.879 抽取内容中相关的比例
Recall 0.982 ground truth 内容被覆盖的比例
Compression 94.9% 平均体积缩减

对 LLM 应用而言 Recall 是关键指标——98.2% 意味着几乎全部正文内容被保留;Precision 的轻微下降(带进一些额外内容)并不会伤害 LLM 准确率。

该基准的实现在 headroom/evals/html_oss_benchmarks.py 中:

  • evaluate_scrapinghub_benchmark() 逐样本调用 HTMLExtractor().extract(html, url=...)(抽取器位于 headroom/transforms/html_extractor.py),对每个样本计算 F1 与压缩率后取均值;
  • 结果对象 ExtractionBenchmarkResult 内置基线对比属性:matches_baseline(F1 与 0.958 相差 0.02 以内)和 beats_baseline(F1 超过基线),方便 CI 中做回归判定;
  • 对应的可执行测试在 tests/test_evals/test_html_oss_benchmarks.pytest_extraction_f1_quick(10 样本)、test_extraction_f1_medium(50 样本,要求 F1 > 0.85)、test_extraction_f1_full(全部 181 样本,标记为 @pytest.mark.slow,要求 F1 > 0.90),以及 test_compression_achieved(要求平均压缩率 > 50%)。整个模块用 pytest.importorskip("trafilatura") 守卫——trafilatura 未安装时自动跳过。

本地复现:

pip install "headroom-ai[html]" datasets
pytest tests/test_evals/test_html_oss_benchmarks.py::TestExtractionBenchmark -v -s

JSON 压缩(SmartCrusher)

  • 测试:100 条生产日志条目,关键错误位于第 67 位;
  • 任务:找出错误、错误码、解决方案与受影响数量。
指标 基线 Headroom
输入 token 10,144 1,260
答对题数 4/4 4/4
压缩率 87.6%

SmartCrusher 的保留策略是:前 N 项(承载 schema/结构信息)、后 N 项(新近性)、全部异常项(error/warning)与统计分布。仓库中还提供了一个公平的三方对比基准 benchmarks/compression_benchmark.py,在"截断(保留前 N 项)"、"LLM 摘要"、"Kompress(ModernBERT 本地推理)"与"Headroom SmartCrusher"四种方案上,用带 ground truth 问题的日志/文件搜索/时序指标三类场景同时度量 token 节省与答题准确率,并记录 LLM 摘要的额外成本。其中 Headroom 侧的配置示例为:

config = SmartCrusherConfig(
    enabled=True,
    min_items_to_analyze=5,      # 至少分析 5 项才触发统计压缩
    variance_threshold=2.0,      # 异常判定阈值
    max_items_after_crush=20,    # 压缩后最多保留 20 项
    preserve_change_points=True, # 保留变化点(趋势拐点)
)
crusher = SmartCrusher(config)

QA 准确率保持

指标 原始 HTML 抽取后 Delta
F1 0.85 0.87 +0.02
Exact Match 60% 62% +2%

抽取有时会提高准确率:去掉 HTML 结构噪音后,LLM 反而更能聚焦相关内容。

对应实现在 evaluate_qa_accuracy_preservation():将 QA 数据集的上下文包进一个带 <nav>/<footer> 噪音的最小 HTML 骨架,对原始 HTML 与抽取内容分别调用同一个 answer_fn 作答,再对比 F1 与 exact match。"准确率是否保持"的判定标准写得很明确:accuracy_preserved = avg_f1_ext >= avg_f1_orig - 0.02(抽取后 F1 不低于原始 F1 减 2 个百分点即算保持)。测试类 TestQAAccuracyPreservation 使用 OpenAI 的 gpt-4o-mini 作为答题函数,且仅在设置了 OPENAI_API_KEY 时执行(否则 skip)。


方法学:指标是怎么算的

Token 级 F1

Precision = |predicted ∩ ground_truth| / |predicted|
Recall    = |predicted ∩ ground_truth| / |ground_truth|
F1        = 2 * (Precision * Recall) / (Precision + Recall)

实现上先分词再统计词频交集:Counter 求取两侧 token 计数的按量截断交集(多出的重复词不计),分别除以预测/真值 token 总数得到 P/R。核心函数 compute_f1()headroom/evals/html_oss_benchmarks.py

此外,通用评测指标库 headroom/evals/metrics.py 提供了更全的工具集:compute_exact_matchcompute_f1compute_bleucompute_rouge_lcompute_semantic_similarity(基于 sentence-transformers 的余弦相似度)以及综合判定函数 compute_answer_equivalence(exact match / F1 ≥ 0.7 / 语义相似度 ≥ 0.85 / 双方都包含 ground truth,四者居一即判"等价")。值得注意的实现细节:该文件的分词器是 CJK 感知的——中日韩连续字符段会被切成重叠的双字 bigram(单字则保留 unigram),否则中文这类无空格语言在 token 级 F1/Recall 上会退化成"整串全对或全错"的判定。

压缩率

Compression = 1 - (compressed_size / original_size)

94.9% 压缩意味着输出只有原始大小的 5.1%。


局限性:Headroom 不压缩什么

不会压缩的内容

  • 短消息(< 300 token)——处理开销大于节省;
  • 源码——默认原样透传以保证正确性(除非启用 tree-sitter AST 压缩);
  • grep/搜索结果——本身已是紧凑结构化格式;
  • 图片——按固定 token 成本(约 1,600 token)计入,不作为文本压缩;
  • 系统提示词——为保持前缀缓存兼容性而保留。

已知的开销来源

开销来源 P90 延迟 说明
Token 计数 16ms 压缩前后各跑一次 tiktoken
Tree-sitter AST 解析 886ms 大代码文件开销显著
Kompress ONNX 576ms CPU 上跑 ML 推理做文本压缩
内容检测(Magika) ML 分类内容类型

从源码结构看,这些开销对应管线中各阶段:token 计数服务于节省统计与 inflation guard,Magika 服务于 ContentRouter 的类型路由,Kompress 的 ONNX 推理只作用于文本型内容,而 tree-sitter 只在大代码文件启用 AST 压缩路径时出现。

何时价值最大 / 何时价值有限

价值最大

  • 积累了大量工具输出的长 agent 会话;
  • JSON 密集型工作流(API 响应、数据库查询)——见压缩性能表中 JSON 行;
  • 构建/测试输出——见 Shell/Build log 行;
  • 多工具 agent——每次调用的节省随工具结果累积而复利。

价值有限

  • 短对话——小 payload 下开销可能超过节省;
  • 纯代码读写会话——代码走透传;
  • 单轮请求——没有累积上下文可压。

复现全部结果

以下命令均在仓库根目录执行:

# 安装评测依赖
pip install -e ".[evals,html]"

# 运行全部评测
pytest tests/test_evals/ -v -s

# 单次压缩冒烟测试
python -c "from headroom import compress; print(compress([{'role':'user','content':'test'}]))"

# 本地代理模式基准(无 API 调用)
python benchmarks/proxy_mode_benchmark.py --turns 12 --show-real-harness

# 回放本地 Claude Code 转录(无 API 调用)
python benchmarks/claude_session_mode_benchmark.py --workers 1

# 在同一本地 Claude 转录语料上对比两个 git ref
python benchmarks/claude_session_branch_compare.py --left-ref upstream/main --right-ref HEAD --recent-turns-per-session 200 --workers 1

# 确定性的 cache-bust 证明用例
python benchmarks/synthetic_token_cache_bust_report.py

# 完整的本地报告包
python benchmarks/cache_validation_bundle.py --workers 1 --output-dir benchmark_results/cache_validation_bundle_full
# 本机私有审查时可带上真实内容摘录
python benchmarks/cache_validation_bundle.py --workers 1 --include-content

各脚本的定位:

benchmarks/proxy_mode_benchmark.py —— 在同一合成对话上对比 tokencache 两种代理模式:token 模式压缩率应更高;cache 模式保持前轮前缀稳定,在 prefix-cache 复用充分的长会话中可能胜出。--show-real-harness 只打印用 Claude Code 复跑同一对比的可选步骤,默认不调用任何 API。

benchmarks/claude_session_mode_benchmark.py —— 回放 ~/.claude/projects 下的本地转录,分别以 baselinetokencache 三种模式重放,估算 raw token、cache read/write token、计费 input/output 成本,并在两种假设下比较 prompt 窗口占用:

  • 假设一:cached token 计入模型上下文窗口;
  • 假设二:cache read 不计入模型窗口。

注意事项:输出写入 gitignored 的 benchmark_results/;脚本对内存使用刻意保守,全语料回放建议 --workers 1;由于只使用转录中可见的消息(隐藏的 Claude Code 系统/工具 schema 不在本地 .jsonl 中),数字是对比性估算而非精确的供应商账单复刻。

benchmarks/claude_session_branch_compare.py —— 在隔离的 worktree 中针对两个 git ref 各跑一次真实本地会话回放,用于同一转录切片上的 PR vs main 对比。产物:

  • 各 ref 的回放输出:benchmark_results/branch_compare/<label>/
  • 合并对比报告:benchmark_results/branch_compare/

benchmarks/synthetic_token_cache_bust_report.py —— 确定性 cache-bust 证明:强制 token 模式在第二轮回溯性改写上一轮工具结果(触发缓存击穿),而 cache 模式保持稳定。用它验证模拟器能区分:

  • token:history rewrite + cache bust;
  • cache:无改写 + 无击穿。

benchmarks/cache_validation_bundle.py —— 组合生成可复现的本地报告包,内容涵盖真实会话回放汇总、仅本地的处理后真实输入/输出摘录、合成 token 击穿证明与合成长文压力测试。默认输出对分享是脱敏安全的(真实报告摘录转录内容、manifest 路径均被 redact),加 --include-content 才在本机私有审查时保留内容摘录。产物结构:

  • index.html / index.md:顶层汇总与链接;
  • bundle_manifest.json:运行时元数据 + 语料指纹;
  • real/:完整真实会话回放报告;
  • real_processed/:真实转录的处理前后摘录;
  • synthetic_token_bust/:最小显式 cache-bust 证明;
  • synthetic_long_suite/:长确定性改写/TTL 场景。

检查点(checkpoint)作用域限定在 bundle 输出目录内,并按所选语料打指纹,避免过期运行结果污染新结果。


小结

Headroom 的评测体系覆盖三层:单函数 compress() 的压缩率与延迟(按内容类型分列)、抽取/压缩后的 LLM 准确率保持(token 级 F1、exact match、QA 保留率),以及代理模式级别的缓存稳定性证明(token vs cache 模式)。所有数字都可通过仓库内的 pytest 与 benchmarks/ 脚本复现;局限部分也如实给出了不压缩清单与 P90 开销来源——在决定是否为特定工作流启用 Headroom 前,建议先按其"何时价值最大"清单对号入座,再跑一轮本地回放基准确认收益。

登录后查看全文
热门项目推荐
相关项目推荐