上下文压缩

上下文窗口装满之后,agent 要么在硬上限处崩溃、要么随窗口超出有效工作范围而劣化(context rot)。压缩是它终究进得太多时你能做的事;本篇展开谱系、触发、保留、自定义调优、度量、跨框架参考。

为什么压缩重要

长时 Agent 会把上下文窗口塞满。不做压缩时,Agent 要么在硬上限处崩溃,要么随着窗口超出模型有效工作范围而逐渐劣化(context rot)。压缩用更紧凑的表示替换窗口里的部分内容,让 Agent 能继续工作。

本章节其他所有技术 —— 缓存、即时加载、子 Agent 隔离 —— 都在减少进入窗口的量。压缩是它终究进得太多时你能做的事。

设计决策一览 (Design Decisions at a Glance)

一份压缩设计由七个决策塑形,大致按这个顺序:

  1. 你需要压缩吗? —— 用量画像。短任务经常不用。
  2. 用谱系的哪几层? → § 压缩谱系
  3. 触发策略 —— 固定阈值、自主、任务边界、还是混合? → § 触发策略
  4. 保留政策 —— 什么原样保留、什么紧凑引用、什么丢? → § 保留政策
  5. 自定义指令 —— 怎么把政策编成 prompt 文本? → § 自定义指令调优
  6. 情景专属扩展 —— 多 Agent、缓存、恢复? → § 设计扩展
  7. 度量 —— 怎么验证它真的起作用? → § 度量

按顺序读后续;每一节都建立在前一节之上。


压缩谱系

压缩不是一个操作,而是一条代价-保真度折衷尖锐不同的技术谱系。选能奏效的最轻那个,不够再升级。

压缩谱系 (Compaction Spectrum) 四种压缩技术 —— 用能奏效的最轻那个;每下一层都是最后手段 保真度损失 技术 计算成本 ① 工具结果清除 (Tool Clearing) 清掉已消费的工具输出内容 —— 保留指针,丢掉负载 若 Agent 已越过该轮次,则无损 O(1) 清除不够时 ② 工具结果截断 (Tool Truncation) 用短摘要替换工具输出 —— 截到 N 字符 / 保留首尾 有损 —— 尾部细节丢失 O(1) 截断不够时 ③ 轮级替换 (Round-Level Replacement) 把较早的对话轮次替换为预生成摘要 有损 —— 摘要只抓大意 写入时付一次 最后手段 ④ 完整对话摘要 (Full Summarization) LLM 重读整段对话,产出新起点 最有损 —— 叙事端到端被压 一次完整 LLM 调用

技术做什么保真度损失计算成本
工具结果清除把已消费工具输出的内容清掉若 Agent 已推进过,无损
工具结果截断工具输出截到 N 字符;保留首 + 尾有损 —— 中段细节丢失
轮级替换把较早的轮次替换为预生成摘要有损 —— 摘要抓大意写入时付一次
完整对话摘要LLM 重读整段对话、写出新起点最有损 —— 叙事端到端被压缩一次完整 LLM 调用

哪一层适用何时

启用哪几层取决于你的 Agent 多长、工具多密:

  • 短对话、工具使用适度 —— 层 1(清除)单独就够
  • 长对话、工具使用中等 —— 层 1 + 2(清除 + 截断)
  • 长对话、工具输出密集 —— 层 1 + 2 + 3(加轮级替换)
  • 很长、反复逼近上限 —— 四层全开,完整摘要作为最后手段

从最轻开始、按需升级比永远跑完整摘要便宜。但不要等到最后一刻 —— 重型压缩需要空间才能把工作做好,触发时窗口已 98% 满意味着摘要本身没余裕。

选择性截断 vs 均一截断

把每个工具输出截到同一字符数既便宜又浪费。50 行的文件读可以原样保留;50,000 行的数据库 dump 需要激进修剪。按工具调 —— 让每个工具声明自己的截断策略(保头、保尾、保摘要)。

“先召回、后精度” 的配方

从最大化召回率开始 —— 确保压缩提示词捕获每条相关信息。然后迭代提高精确度 —— 消除冗余的工具输出和消息。—— Effective Context Engineering for AI Agents, Anthropic, 2026

把你的压缩搭成“宁留勿缺”的形态。等看到 Agent 压缩后实际在重读什么,再修剪。反过来做 —— 一开始就紧、看到丢失才放 —— 会失败,因为你看不到丢失,直到几周后用户投诉。

研究谱系:hard prompt vs soft prompt 压缩

上面四层全是 harness 层、自然语言的操作:丢弃、截断、或重新摘要消息内容,产物仍是可读文本——我们自己的压缩就在这一支上。学术界的 prompt 压缩文献另有两个相邻分支,它们不描述我们的机制,但为“压缩为什么有效、天花板在哪”提供理论背书:

分支机制代表需训练?
hard prompt小 LM 按 token 困惑度剪枝——删掉最不意外的 tokenLongLLMLingua否——用现成小 LM 即可
soft prompt把文本编码成少量特殊 token / KV 值,模型直接读取GIST → ICAE → 500xCompressor是——训练一个 encoder
  • hard prompt 的“问题感知”思想为本页两点背书:冗余上下文拉低性能(context rot 被量化),以及本页此前未覆盖的 position bias / lost-in-the-middle——给活下来的东西排序是保留政策之外的第二根杠杆。逐条启示见深读 LongLLMLingua
  • soft prompt 把文本压进特殊 token:ICAE 存这些 token 的 embedding(压缩比上限约 15×),500xCompressor 改存其 KV 值(信息密度更高,压缩比冲到 480×、仍留 62-72% 能力,类比 Prompt Tuning→Prefix Tuning)。它标出语言可压缩的天花板,但也是我们不采用的方向——soft token 是模型直读的向量,人不可读、不能 replay 验证、不能用 /compact 引导,与本页强调的可观测、人可介入直接冲突。这解释了为什么生产 agent 走自然语言压缩,而非 soft token。

触发策略

最难的问题不是“怎么压”,而是“何时压”。四种策略覆盖整个空间。

固定阈值

总 token 越过上下文窗口的固定比例(常见 60–85%)或绝对值(Anthropic API 默认 150,000、最低 50,000)时触发压缩。

  • 优势:可预测、易推理、不涉及模型判断。
  • 缺点:可能在糟糕的时刻触发 —— 推理中途、工具链中途、或 Agent 正要完成时。Agent 失去连续性,因为触发基于 token 数而非任务态。

自主触发

Agent 自己决定何时压。LangChain Deep Agents 和 Claude Code 都提供这种形态。Agent 通常在以下时刻触发:

  • 任务切换 —— 完成一个子目标之后

  • 提取之后 —— 刚从长文档或工具输出提取出结果

  • 摄入之前 —— 要拉一段大新上下文之前

  • 多步边界 —— 开始重构、迁移、分析之前

  • 优势:压缩发生在“失去的状态最少”的时刻。Agent 自己挑出逻辑工作单元之间的缝。

  • 缺点:模型判断会波动。Agent 可能压得太晚(拖到撞天花板)或压得太频(摘要的摘要会退化)。需要调优。

任务边界压缩

由 harness、而不是 Agent 或阈值声明压缩点。每个工作流阶段结束时压一次;摘要成为下一阶段的输入。流水线、多 Agent 交接、结构化工作流用这种。

  • 优势:压缩是架构的一部分,不是应急响应。没有意外触发、没有判断题、阶段之间有干净缝。
  • 缺点:只对有天然缝的工作流奏效。开放式 Agent 循环不具备。

不做(到上限就崩)

值得点名,因为许多早期 Agent 就是这样。无压缩、上下文塞满、模型报错或悄悄截断。唯一对策是“把对话保持短”。短命 Agent 可接受;能跑多于几轮的 Agent 不可接受。

生产默认是混合

多数生产系统组合使用:固定阈值作为安全网 + 自主或任务边界作为主力。阈值兜住主力没来得及触发的情况;主力避免固定阈值出名的“最糟时刻触发”。


保留政策

一旦你知道用哪层、何时触发,实质的设计问题是:什么存活? 这个决定对压缩后 Agent 是否连贯的影响比其他任何选择都大。

三层保留:

永远原样保留

  • 用户的当前任务轮(最近的 N 轮,通常 3–10 轮)
  • 当前打开的文件加它们的最新状态
  • 进行中的工具调用,还没返回的
  • 系统提示词和记忆索引 —— 这些本就不在压缩区内,点名是提醒你别不小心把它们压了

以紧凑引用保留

  • 约束未来行为的决策 —— 保决策、丢商议
  • 读过但没改的文件 —— 保路径、不保内容
  • 用户意图 —— 最初的请求和关键澄清,压缩但显著
  • 架构承诺 —— 技术选择、接口契约
  • 未决问题 —— 发现但未修的 bug、开放问题

可以自由丢弃

  • 已被读取且综合进决策的工具输出
  • 导致已提交决策的中间推理
  • 被抛弃的探索分支
  • 例行应答 —— “好,我查一下……”
  • 被取代的决策 —— 被更新版本覆盖的旧计划

线划在哪里

“永远原样保留”和“紧凑引用”之间的边界是压缩 bug 最多的地方。一个安全的经验法则:

  • 用户会明显察觉丢失的东西 → 原样层
  • Agent 需要记得但必要时能重建的东西 → 紧凑引用
  • 其他一切 → 可丢弃

自定义指令调优

你的保留政策是“什么”存活。自定义指令是“怎么” —— 把政策编码成给摘要 LLM 的实际 prompt 文本。默认压缩 prompt 为通用对话而优化,经常把你的用例搞错:丢掉架构决策、保留例行工具交换、忘掉用户陈述的偏好。

每个正经压缩系统都暴露替换或增补默认 prompt 的途径:

  • Anthropic API —— instructions 参数完全替换默认 prompt
  • Claude Code —— /compact "focus on the recent database migration" 追加用户指引
  • LangChain Deep Agents —— middleware 层配置摘要 prompt
  • OpenAI Agents SDK —— session 配置里的自定义摘要器函数

怎么写好自定义指令

把上一节的每个保留层翻译成 prompt 文本:

  • 原样层 —— 明确列出:“保留用户原始请求原文。最近 N 轮不变。保留当前文件编辑态。”
  • 紧凑引用层 —— 描述压缩形式:“每个架构决策压成一句话。未决问题每条列一行。即便内容被压了也保留文件路径。”
  • 丢弃层 —— 说明要丢什么:“省略例行应答、被抛弃的探索分支、以及已被综合进已提交决策的工具输出。”

prompt 要保持短而规定性。嵌套规则多的长摘要 prompt 会让较小的摘要模型困惑;干净的“保留什么 / 丢什么”清单比段落式指引表现更好。

用 Replay 验证

在生产里信任一条自定义压缩 prompt 之前,用 replay 测:拿一个已知良好的长任务、在不同点强制压缩、从压缩态继续执行、检查继续的工作是否匹配未压缩的基线。这里的失败就是你的 prompt 丢了不该丢的东西的信号。

这也是 § 度量 里正式化的回路 —— 在这里提一下,是因为它是你对自定义指令、保留政策、触发策略做的每一次改动的验证步骤。


设计扩展

基础设计(谱系 + 触发 + 保留 + 自定义指令)处理单 Agent、不带缓存、无长时恢复需求的 setup。下面三个扩展只在你的情境匹配时适用 —— 不是每个 Agent 都需要。

多 Agent 协调

适用场景:多个 Agent 共享上下文(共同对话、共享状态)或它们的压缩决策互相影响。

每个 Agent 有自己的上下文窗口。压缩设计要决定:每个 Agent 独立压、还是有个协调者?

分散式压缩(常见默认) —— 每个 Agent 独立压。简单、不用协调者。Agent 上下文基本独立时工作良好(主 Agent 委托给子、子回传压缩摘要)。

  • 劣势:Agent 共享大量上下文时,每个都重复压一次,且可能压成略有差异的摘要,造成漂移。

集中式压缩(AutoGen 的模式) —— 一个协调者压缩共享对话、广播给所有 Agent。AutoGen 的 CompressibleGroupManager 是公开的例子。

  • 优势:单一真相源。所有 Agent 对“说过什么、意思如何”达成一致。
  • 劣势:需要协调者角色、在高负载下成为瓶颈。

指导:独立 Agent → 分散式。共享对话(协作编辑、共享线程)→ 集中式。父子配干净交接 → 分散式(父只看子的摘要)。

Prompt 缓存集成

缓存只命中稳定前缀,而压缩会改写内容,两者的互动有一条铁律:压缩只能替换缓存头部(工具 + 系统提示词)之后的历史,绝不碰头部本身——否则整段前缀在下一轮全废。摘要块自己也值得缓存(Anthropic API 允许在 compaction block 上放 cache_control,写时缓存、后续便宜读)。

这条坐标轴的完整展开——四个断点位置、失效级联、真实成本——见 缓存点设计

可恢复性与再压缩

适用场景:你的 Agent 跑得足够长需要考虑失败恢复,或一段对话可能被压缩多次。

压缩是有损的。若执行在压缩之后、任务完成之前失败,你能恢复吗?

三种机制:

  • 压缩前日志 —— 压缩触发前把完整压缩前状态记录到持久存储。失败时加载、尝试不同策略。
  • 压缩 Checkpoint —— 压缩输出包含对压缩前状态的引用。恢复时载入摘要、保留引用以便必要时再展开。
  • 并行恢复通道 —— 独立的、始终追加的 artifact(记忆、笔记、auto-memory)独立于压缩区地捕获关键决策。Claude Code 的 Auto Memory 就是这种。

为再压缩而设计:某一刻,压缩过的摘要本身需要被再压缩(摘要的摘要)。每一次都丢保真度。预期到这点:

  • 给任何一次对话的压缩次数设上限;超过 N 就开新会话带显式交接
  • 保留一个“核心身份”区永不被再摘要 —— 用户意图、架构决策
  • 对更早、多次压缩过的摘要在质量指标里加权更轻

度量

压缩风险高:在长时状态上做的有损操作。它比多数上下文工程主题都更奖励仔细测量。

要跟踪的五个信号:

信号告诉你什么
压缩比输入 token / 摘要 token。过高 = 过度压缩。过低 = 白干。
触发精度压缩中确实需要的比例。低 = 触发太早。
压缩后回归任务中途强制压缩、重放。只在压缩后失败的任务指出压缩器该保留的东西。
摘要的摘要退化第 N 次再压缩时保真度怎么掉。陡的话就限制再压缩次数。
压缩成本摊销摘要调用成本 ÷ 到下次压缩的轮数。决定这一层压缩是否值得其计算。

合成回归套件

最有价值的单一测试:保留 10-20 个历史成功的长任务。在固定和变化点强制压缩。重放。标出任何回归。

每次改压缩逻辑都跑一遍(自定义指令、触发策略、保留政策)。它抓住的问题比任何其他度量手段都多。


跨框架参考

主要框架如何暴露压缩的概览。对照业界实践做校准用,不是规定。

框架触发方式保留自定义多 Agent恢复
Anthropic API固定阈值(可配)自动或手动 pause_afterinstructions 参数按会话compaction block + cache_control
Claude CodeAuto + /compact 命令最近轮次 + auto memory/compact "focus on ..."按会话Auto Memory 并行通道
LangChain Deep自主(模型决定)最近 10% + middleware 规则摘要 middleware按 Agent历史的虚拟文件系统
OpenAI Agents丢弃或摘要最后 N 轮原样自定义摘要器函数按会话Session 存储
CrewAIrespect_context_windowsummarize_messages() 分块有限按 Agent共享 memory class
AutoGen按 manager共享对话压缩Group manager 配置集中式(独一份)委托给协调者

每个框架代表的设计赌注

没有框架是“最好” —— 它们反映不同的设计选择:

  • AutoGen 赌协调式多 Agent —— Agent 共享上下文多时值
  • LangChain 赌 Agent 判断 —— 负载可变的自主 Agent 值
  • OpenAI 赌简洁 —— 两个选项(丢 / 摘),清晰心智模型
  • Anthropic 赌可配置的服务端原语 —— 基础设施,不是策略
  • CrewAI 赌“一个设置解决”的简洁 —— 观点化默认、无选择瘫痪
  • Claude Code 赌开发者 in-the-loop —— /compact + 用户指令、少自主

如果你带着压缩考虑选框架,先点名哪种赌注匹配你的 Agent 形态。其他都跟着来。


相关阅读

  • Zapvol 的压缩引擎 —— 本设计空间的具体实现:不可变记录的投影模型、四级 reduce ladder、真实 token 校准。
  • 总览 —— 回到章节枢纽。
  • 上下文管理 —— 运行时纪律的其余部分:注意力预算、即时上下文、子 Agent 隔离、checkpoint。压缩是这些技术触到极限时启动的操作。
  • 记忆设计 —— 结构化笔记和记忆和压缩互补:窗口之外持久的内容不需要被压缩,只需要被召回。
  • 从案例到范式 → 第二部分 —— “方法在哪里触顶”点明了Agent 需要“压缩入设计”而非应急处理的时刻。

来源

prompt 压缩的两篇研究背书(LongLLMLingua、500xCompressor)的来源见各自的深读章节。

这页有帮助吗?