上下文压缩的隐藏代价:Keep-Everything 在 87% 缓存命中率下反而最便宜 · 干货攻略

  • 链接:https://x.com/omarsar0/status/2106927371366596692
  • 分类:x-tips
  • 来源:X @omarsar0
  • 作者:Jay
  • 更新:2026-10-11

这是什么

UT Austin 三位研究者(Prasoon Sinha、Akiho Kawada、Neeraja J. Yadwadkar)发表了一篇系统性论文——"Beyond Token Savings: A Systematic Study of Context Compression in LLM Agents"(arXiv:2609.32961),对上下文压缩策略进行了迄今为止最大规模的实证研究。

研究团队在 SWE-bench Verified 和 Terminal-Bench 1.0 上跑了 近 35,000 次 agent 运行,系统地拆解了压缩策略的三个独立维度:

  1. 如何压缩(PP,Primitive):保留、摘要、重写……
  2. 何时触发(TT,Trigger):每步压缩、阈值触发、无压缩
  3. 压缩多少(DD,Depth): aggressive(猛删)vs. light(轻删)

三个维度组合出的策略对三个开源模型(Qwen 系列等)分别做了消融实验,测指标包括:任务成功率、token 用量、端到端延迟、估算 API 成本。


为什么值得关注

直觉告诉我们:压缩上下文 → token 更少 → 更快更便宜。但论文的核心发现把这个直觉完全拧过来了。

核心反直觉结论

Token 越少,不等于越快,也不等于越便宜。

具体数字来自论文(已在 X 上由 @omarsar0 总结):

  • 在 Terminal-Bench 上,Qwen 模型下,用大约 1/3 token 量的压缩策略,延迟反而高出 20%–80%。
  • Step-triggered 策略(每步都压缩)切得最狠,但需要 多花 10%–27% 的模型调用次数——因为压缩本身引入 LLM 开销,且丢信息导致轨迹更长。
  • Threshold-triggered 策略(上下文超阈值才压缩)切 22%–55% 的 token,调用次数接近 full context 基线,但仍然更慢(重写前缀破坏缓存,见下文)。

缓存经济学:Keep-Everything 反而最省

来自另一项独立研究(louisbouchard.ai 的 Context Engineering 综述,引用同一方向数据):

策略 每轮平均 token 每轮成本 缓存命中率
Full History(全部保留) ~296K $0.0063 97%
Aggressive Preset(激进压缩) ~少 41% $0.0133 低于 50%
Summarizing Preset(摘要压缩) ~少 41% $0.0196 极低

Full History(keep-everything)烧了最多的 token(296K/轮),却反而最便宜——原因正是 prefix caching:保留完整历史 = 前缀完全不变 = 每次请求都命中缓存折扣(约 90% off)。而任何会改写前缀的操作(摘要、压缩、重排)都会让缓存失效,走全价输入计费。

叠加效应:删掉工具输出后 agent 会重新抓取同类信息——付了压缩费,又付了一次抓取费,等于双重付账。

模型间结论不迁移

研究还发现一个关键陷阱:对 Qwen 表现好的策略,套到 Devstral 上,成功率直接掉到 38.7%,且更慢。这意味着压缩策略必须 per-model/per-task 单独调参,不能套用别人的配置。


核验过程

官方来源(论文本身)

  • arXiv 2609.32961(https://arxiv.org/abs/2609.32961):论文摘要明确写着 "nearly 35,000 agent runs",三个维度的消融设计,以及 "policies using roughly one-third as many tokens can take 20–80% longer" 的具体结论。
  • 作者信息:Prasoon Sinha、Akiho Kawada、Neeraja J. Yadwadkar,单位 The University of Texas at Austin——与帖子描述完全吻合。
  • 数据点 S1(缓存经济学):来自 louisbouchard.ai 的 Context Engineering 综述,该文引用了 DeepSeek API 的 prefix caching 定价机制(cache hit ~10% input price)与 Full History 策略的实测数据。

交叉验证

  • X 原帖(@omarsar0)数据:35,000 次运行、SWE-bench+Terminal-Bench、Qwen 延迟 +20%–80%、step-triggered +10%–27% calls、threshold-triggered -22%–55% tokens、Devstral -38.7%——全部与论文摘要一致。
  • GitHub Copilot 规模数据:44.2% 的生产会话涉及 compaction,median removal 72.8%——来自论文引用的大规模生产 trace,说明这不只是学术问题,业界已经踩坑很久了。
  • DeepSeek 官方文档(https://deepseek.day/en/blog/deepseek-api-context-caching):明确说明 "cache hits require byte-identical prefix from start",与"摘要破坏缓存"的机制解释完全吻合。

官方文档与原帖说法的对齐

原帖的"token 越多越快越便宜"说法,经核验来自缓存经济学机制,与 arXiv 论文和 DeepSeek 文档一致。


上手步骤

1. 先确认你的 API 支持 Prefix Caching

厂商 机制 关键要求
Anthropic cache_control breakpoints 精确前缀匹配,最多 4 个断点
OpenAI 自动缓存(GPT-4o+) 前缀完全相同
DeepSeek 自动缓存,cache read $0.30/M(vs input $3/M) 同样需字节级前缀匹配

不支持前缀缓存的 API(如某些自部署场景),压缩策略的代价收益比完全不同。

2. 冷启动:不压缩,测基线

# 用 DeepSeek Flash(带 prefix caching)的示例
messages = [
    {"role": "system", "content": SYSTEM_PROMPT},   # 固定 → 每次命中缓存
    {"role": "user",   "content": query}
]
# 追踪第一轮的 cache_read_input_tokens
# 如果 > 0,说明系统 prompt 被缓存了

在多轮 agent 循环里:

history = []
while not done:
    # 关键:不要每轮都重建 system prompt!
    messages = [system_prompt] + history + [user_turn]
    resp = client.chat.completions.create(
        model="deepseek-flash",
        messages=messages
    )
    # 下一轮直接 append resp → 前缀不变,cache hit
    history.append(user_turn)
    history.append(resp.choices[0].message)

3. 如果必须压缩:用 Tail-Cut 而非前缀改写

来自 Hermes Agent 的最佳实践(NousResearch,https://hermes-agent.nousresearch.com/docs/developer-guide/context-compression-and-caching):

# ❌ 错误:摘要时重建整个 prompt,前缀被改写,缓存全灭
summary_req = build_standalone_summary_prompt(whole_transcript)
# → 与会话共享 0 token 前缀 → 全价计费

# ✅ 正确:保持前缀,只对 tail 下手
messages = [
    *existing_conversation_prefix,   # 和会话完全相同 → 缓存命中
    {"role": "user", "content": "Summarize the following..."},
    *transcript_tail                  # 摘要目标
]
# → 前缀命中缓存,只对 tail 部分付全价

4. 按模型/任务选策略(论文结论)

# 伪代码:threshold-triggered 而非 step-triggered
def should_compress(context_tokens, threshold_pct=0.5):
    max_tokens = model_context_limit * threshold_pct
    return context_tokens > max_tokens  # 不超阈值就不动

# 不要迷信"激进=高效":论文显示 aggressive 策略在 Devstral 上导致 -38.7% 成功率
# 先在小样本上 A/B test 以下两个指标:
#  - task_success_rate(任务成功率)
#  - cost_per_success(每个成功案例的 API 花费)

坑与适用边界

不适用 keep-everything 的场景: - 模型 context window 快触顶了(硬约束,无法回避压缩) - 工具输出存在极度重复的冗余(如日志大量复制粘贴),且缓存命中率本身就很低 - Prompt Caching 完全不可用的 API(请先确认)

Step-triggered 策略是重灾区: 每步压缩 = 每步都触发 LLM summarization 调用 + 改写前缀 = 双重损失(summary 本身要钱 + 缓存失效)。论文数据显示额外 +10%–27% 模型调用,是最差选择。

模型差异陷阱(最容易被忽略): 论文结论强烈建议:per-model eval——在你自己用的模型上跑成功率 + 延迟 + 成本这三个指标,而不是照搬别人的策略配置。

缓存 TTL 边界: 各厂商缓存都有 TTL(如 Anthropic 的 cache_control 有时效),在长任务中途缓存过期会导致突发全价账单,需要监控 cache_read_input_tokens 字段来实时感知。


一句话结论

上下文压缩的收益取决于前缀缓存是否被破坏——如果你的压缩策略会改写历史前缀,keep-everything(保持完整历史)在现代 API 的 prefix caching 下反而更便宜、更快;实在需要压缩时,用 threshold-triggered + tail-cut 而非 step-triggered + 摘要,且必须在目标模型上实测 per-task 的成功率与成本。


核验来源: - 论文:arXiv:2609.32961(UT Austin,https://arxiv.org/abs/2609.32961) - X 原帖:@omarsar0(https://x.com/omarsar0/status/2106927371366596692) - 缓存机制:DeepSeek API Context Caching 官方文档(https://deepseek.day/en/blog/deepseek-api-context-caching) - Context Engineering 综述:louisbouchard.ai(https://www.louisbouchard.ai/context-engineering-2026) - Hermes Agent 最佳实践:NousResearch(https://hermes-agent.nousresearch.com/docs/developer-guide/context-compression-and-caching)