从零开始理解上下文压缩:Pi 如何继续长会话

来源:小墨同学于 2026-10-04 分享的 X 文章《从零开始理解上下文压缩》。英文原作是 Earendil Engineering 于 2026-08-13 发布的 How Compaction Works in Pi,中文翻译与适配由小墨同学完成,可在 Pi 学习蓝皮书 阅读。

本文依据中文译文重新组织、改写为学习笔记,保留核心机制说明;例子、概念对照表和实践建议为本笔记补充。中文译文及适配部分按 CC BY 4.0 发布,本文对这些内容的改写沿用该许可并注明修改;英文原文版权归 Earendil 所有。本文不复制原文配图。

使用编程 Agent 时,一次修复可能持续几十轮:先读代码、再查报错、修改文件、运行测试,最后还要处理提交与部署。聊天记录看起来只是不断往下延伸,模型每次请求能接收的材料却有上限。

上下文压缩(Compaction)把较早的工作整理成摘要,让模型带着关键状态和近期细节继续任务。 理解它,需要先看清楚一次 Agent 会话如何增长。

1. 上下文是每次请求交给模型的材料

模型生成回复时,依赖本次请求中实际提供的上下文。在本文讨论的连续会话里,材料通常包括系统提示、已加载的项目说明、工具定义,以及用户消息、助手回复和工具结果。

第一次请求可以简化为:

[系统提示与项目说明][工具定义][用户要求]

假设用户让 Agent 修复登录问题,模型先要求读取文件。Agent 程序执行工具,再把结果加入后续请求:

[初始材料][助手:读取文件][工具:文件内容]

随后可能继续修改代码、运行测试:

[此前材料][助手:修改代码][工具:修改结果]
[助手:运行测试][工具:测试输出][助手:汇报]

所以,用户的一次要求可能带来多次模型请求。即使只聊了几句话,大文件与长日志也可能占用大量空间。聊天界面保留的记录,与某一刻实际发送给模型的内容,也不必完全相同。

原文用这样的过程解释溢出:历史持续增长,最终下一次请求超过模型允许的范围,得到类似 Request exceeds the maximum size 的错误。

2. 装不下时,怎样继续?

可以重新开一段会话,也可以压缩已有上下文。

新会话提供了空出来的空间,但先前的目标、限制、决定和尚未完成的工作,需要重新交代。如果仍在处理同一项任务,压缩可以把这些状态带过去。

常见实现是再调用一次模型,请它总结较早的历史。也可以用确定性规则筛选内容;“压缩”描述的是缩小后续请求所携带的历史,并不限定某一种算法。

这里的摘要会筛选与改写信息,无法保证逐字恢复原来的对话。它的价值在于让后续工作能够接上,质量取决于有没有保留真正需要的线索。

3. Pi 保留近期消息,总结早期历史

原文描述的 Pi 会将上下文分成两个部分:较早的内容接受总结,近期消息尽量保持原样。

压缩前:
[系统与工具][较早历史........................][近期消息]

压缩后:
[系统与工具][工作摘要][近期消息][新消息]

这样既能缩小输入,又能保留正在处理的工作细节。最近的报错、刚改过的代码和最新要求,往往仍然需要原始信息。

Pi 使用可配置的 token 预算决定保留范围。原文写作时默认保留约 20,000 token,并用“约 5 到 20 个轮次”帮助理解。这个轮次数只是粗略估计:读一份大文件与简短问答消耗的空间不同,token 也不能直接等同于汉字数。

用户可以通过 /compact 手动压缩,程序也会在上下文接近上限时自动处理。

版本补充(2026-10-05 核对): 原文主要描述轮次结束后检查,以及溢出时的中途恢复。当前 Pi 官方 Compaction 文档 还明确描述了工具结果追加后、下一次助手响应前的检查,以及新用户请求前的检查。不要把原文的时机描述当作所有版本的固定规则。

压缩改变的是下一次模型请求使用的历史表示。按当前官方文档,摘要以压缩记录追加到会话中,再用摘要和保留消息重建上下文;原始记录仍可存储在会话里。“模型不再收到全部旧消息”与“磁盘上的历史被删除”是两件事。 具体条目与切点可继续看 [[Pi/Pi Compaction:上下文压缩的完整流程|Pi Compaction:上下文压缩的完整流程]](博客阅读入口)。

4. 好摘要是一份可以接手的工作交接

原文把摘要比作工作交接:接手者需要知道目标、进度、关键决定,以及下一步该做什么。

Pi 为此构造独立的摘要请求,使用面向上下文总结的提示,并要求结构化结果。待总结的历史会作为材料交给它;“独立请求”指重新组织提示与输入,并不表示它无需读取历史,也不表示没有 token 成本。这种组织方式也允许通过定制机制选用其他模型。

下面是本笔记补充的交接例子:

目标:修复登录后仍停留在登录页的问题。
限制:保留现有认证方案,不改注册流程。
已完成:检查回调路由;修复跳转条件;相关测试通过。
关键决定:复用现有会话状态,避免增加第二套状态来源。
当前工作:浏览器中验证登录后的实际跳转。
下一步:验证通过后提交;若失败,检查回调响应与页面日志。
关键线索:修改文件路径、测试命令与结果、仍未解决的报错。

如果只留下“讨论过登录问题,继续修复”,后续模型很可能重复排查。反过来,如果把每条工具输出都照搬进摘要,又难以节省空间。

好的交接保留的是继续行动所需的事实与证据。尤其要区分“已修改”“测试通过”和“实际验证通过”,避免在压缩时把尚未确认的结果写成完成状态。

Pi 以纯文本保存摘要,使人能够检查交接内容,也便于后续切换模型时继续使用;摘要本身仍可能遗漏信息。

5. 压缩为什么会影响提示缓存?

压缩与提示缓存解决的问题不同。压缩让输入变短;缓存让重复输入的计算得到复用。

原文讨论的缓存依赖相同的输入前缀。连续会话通常在已有内容后追加消息,因此先前相同的开头有机会命中缓存。压缩把早期历史换成摘要,输入从该位置开始变化:

压缩前:
[系统与工具][旧历史][近期消息]

压缩后首次请求:
[系统与工具][摘要][近期消息][新消息]
可能复用 ↑ 从这里开始,前缀发生变化

近期消息即使一字没改,它们前面的材料已经不同,对应的旧计算状态也无法直接沿用。 未变化的系统与工具前缀仍可能命中缓存,实际效果取决于提供商的机制和缓存有效期。

后续请求继续在压缩后的输入末尾追加内容,又可以逐渐受益于新的缓存。因此,压缩不意味着以后永远没有缓存,只是重建了后续请求所沿用的输入基础。

这一点也解释了为什么不能只根据“摘要更短”判断当次费用:生成摘要要消耗 token,压缩后的首次请求还可能减少缓存命中。是否降低总体成本,需要看后续请求和提供商计费。

6. 把几个概念放在一起

概念 主要作用 需要记住的边界
上下文窗口 限制一次请求可处理的材料范围 聊天界面能显示更多历史,不等于模型本次全都收到
上下文压缩 用较短表示替换部分历史 摘要会筛选信息,可能丢失细节
近期保留消息 带上当前工作的原始细节 保留范围受 token 预算影响
压缩提示 指导交接内容与结构 应保留目标、限制、进度、决定与下一步
提示缓存 复用相同输入前缀的计算 命中缓存不会扩大上下文窗口

7. 对实际使用的启发

以下是本笔记的实践补充。

长任务中,可以在阶段结束时明确写出当前目标、已完成事项、验证结果与下一步。这些状态越清楚,摘要越容易形成可靠交接。重要文件路径、错误信息与检查结果也应留下可追查的入口。

压缩后,如果 Agent 忘记了某个约束,可以直接补回该约束及其关联决定;若需要精确的代码或日志,让它重新读取实际材料比依赖摘要回忆更可靠。换到不同任务时,则可以整理必要背景后开启新会话。

原文还指出,Pi 允许通过 Extension 自定义压缩机制。可以针对自己的任务调整摘要关注点,例如调试时突出排除过的原因和未验证的假设。定制时应关注接手后的行动是否准确,而不仅是摘要是否更短。

与这篇入门文章衔接的两篇笔记:

  • [[Pi/Pi Architecture:拆解 Coding Agent 的内部架构|Pi Architecture:理解模型、工具与 Agent Loop 怎样配合]](博客阅读入口)。
  • [[Pi/Pi Compaction:上下文压缩的完整流程|Pi Compaction:进一步理解切点、会话条目、分支摘要与扩展钩子]](博客阅读入口)。

来源与许可

  • 小墨同学的 X 帖子与 X 长文:本次整理的入口。
  • 小墨同学中文译文:Pi 中的压缩机制:主要整理依据,中文译文及适配部分采用 CC BY 4.0。
  • Earendil Engineering:How Compaction Works in Pi:英文原作,发表于 2026-08-13。
  • Pi 官方 Compaction 文档:2026-10-05 核对版本差异与会话保存方式。

本文是对授权中文译文的结构重组与改写,并加入明确标注的补充;不是原文的逐字转载。术语有歧义时,可对照英文原文;具体运行行为以所使用的 Pi 版本为准。