04 压缩与新纪元的衔接 本节摘要:前三节讲了压缩的触发、检查点结构、边界约束,这一节讲最后一个衔接——压缩完成为何开启新纪元(Epoch)。原因是:压缩重写了历史(旧对话变摘要),作为模型缓存前缀的「基准」变了,旧缓存必然失效。所以必须开新纪元重建缓存。本节把这个衔接讲透,并完成第 9 章对压缩机制的完整闭环。 一、压缩改变了「基准」 回忆第 8 章:基准(System Context baseline)是模型缓存的前缀,纪元内冻结。基准的前面是系统上下文,后面是历史消息。压缩发生时,「历史」被重写了——旧对话变成摘要。这导致什么? 关键洞察:虽然系统上下文(基准的主要来源)可能没变,但「历史被重写」让整个请求的前缀发生了变化。
本节摘要:前三节讲了压缩的触发、检查点结构、边界约束,这一节讲最后一个衔接——压缩完成为何开启新纪元(Epoch)。原因是:压缩重写了历史(旧对话变摘要),作为模型缓存前缀的「基准」变了,旧缓存必然失效。所以必须开新纪元重建缓存。本节把这个衔接讲透,并完成第 9 章对压缩机制的完整闭环。
回忆第 8 章:基准(System Context baseline)是模型缓存的前缀,纪元内冻结。基准的前面是系统上下文,后面是历史消息。压缩发生时,「历史」被重写了——旧对话变成摘要。这导致什么?
关键洞察:虽然系统上下文(基准的主要来源)可能没变,但「历史被重写」让整个请求的前缀发生了变化。模型缓存是按「前缀逐字节」匹配的,前缀一变(哪怕只是历史部分变),缓存命中点就挪了,旧缓存大面积失效。
压缩前: [系统上下文 + 旧历史(几十回合)] ← 旧缓存命中到这里 压缩后: [系统上下文 + 摘要 + 近期] ← 前缀变了 ← 旧缓存失效,需重建
因为前缀变了、旧缓存失效,继续用旧纪元没意义(缓存命不中)。所以压缩完成后开启新纪元——新纪元里,基准重新建立,模型重新缓存新前缀。
纪元 N(旧基准 + 旧历史) │ ▼ 压缩发生,历史被重写 │ ▼ 旧纪元 N 的缓存失效 │ ▼ 开启新纪元 N+1 │ ▼ 新基准(基于压缩后的状态)建立 │ ▼ 模型在新纪元里重新缓存
这是第 8 章纪元机制的另一个「结束触发条件」——除了「某上下文源变化」和「会话移动」,「压缩」也会结束纪元。
新纪元开启后,模型会重新建立缓存:
所以压缩后会有一次「缓存重建成本」(多付一点),但重建后后续回合又恢复低成本。这是压缩的隐性代价之一——除了「信息有损」,还有「一次缓存重建」。
💡 代价权衡:压缩的代价是「信息有损 + 一次缓存重建」,收益是「腾出空间让会话继续」。在长对话里,不压缩会直接爆窗口(会话中断),压缩的代价比中断小得多,所以压缩是划算的。
第 8 章还讲了「对话中途系统消息」——上下文源变化时在安全边界插一条消息。压缩和中途消息会同时发生吗?
答案是:压缩本身会触发新纪元,而新纪元开始时如果有未生效的上下文源变化,它们会在新纪元里一并处理。也就是说,压缩是个「重置点」——它把累积的变化(包括被阻塞的中途消息,第 8 章 04 节的 blocked 态)一起清掉,在新纪元里重新建立干净状态。
压缩发生 │ ▼ 开新纪元 │ ▼ 新纪元里: ├─ 重新建立基准(含所有当前上下文源的最新事实) └─ 累积的 blocked 变化一并消化
所以压缩不仅是「腾空间」,还是「清理累积状态」的机会。
把第 9 章四节合起来,压缩的全貌是:
| 方面 | 情况 |
|---|---|
| 触发 | 估算 token >= 可用额度 |
| 产物 | 滚动摘要 + token 受限近期上下文 |
| 约束 | 原生消息不切割 |
| 衔接 | 开新纪元重建缓存 |
| 代价 | 信息有损 + 一次缓存重建 |
| 收益 | 腾出空间让会话继续 |
这是个「有损但必要」的机制——不完美(会忘细节),但没它长对话就断了。OpenCode 的做法是尽量让有损可控(结构化摘要保重点),并提供长期记忆补细节(OpenWork 教程第 7 章记忆库)。
读完第 9 章,你掌握了 Agent 长对话不爆的完整机制:
三者协作,让 OpenCode 能撑住马拉松式长对话:循环跑、上下文管好、快爆就压、压完重建。这是 Agent 能持续工作的关键能力。
第 9 章结束。下一章讲 MCP 集成——Agent 如何标准化地连接外部世界。