你的聊天机器人在前十五轮对话中运行完美。然后,问题出现了。它与之前的决定相矛盾。它询问用户已经提供过的信息。它丢失了对话开始时明确定义的多步骤任务的脉络。对话历史在技术层面上还在那里——你没有删除任何内容——但模型的行为却好像它不存在一样。
这就是上下文腐化(context rot):随着对话历史增长,输出质量逐渐下降的现象。2024 年对 18 个最先进模型进行的评估,涵盖近 20 万次受控调用,发现即使在名义上拥有更大窗口的模型中,可靠性在超过 30,000 个 Token 后也会显著下降。在扩展对话中,高性能模型会变得和小得多的模型一样不可靠。问题不在于你的上下文窗口耗尽了,而在于 Transformer 注意力机制是二次方的——100,000 个 Token 意味着 100 亿对关系——模型被迫将注意力分散得如此稀薄,以至于重要的早期内容实际上被忽略了。
当团队遇到这个瓶颈时,通常会采用两种解决方案之一:截断或摘要。这两种方法都会以可预见的方式让情况变得更糟。
为什么截断和朴素摘要都会失败
硬截断——当上下文填满时丢弃最旧的消息——是最简单的方法,也是最明显存在缺陷的方法。模型会丢失早期决策背后的推理逻辑。一个用户花了十分钟在第一至第五轮建立的约束条件,就这样被悄然丢弃。当矛盾浮出水面时,用户看到的不是"上下文已截断",而是一个没有认真听讲的 AI。
朴素摘要看起来更聪明一些。当上下文填满时,用一个压缩摘要替换旧消息。历史记录被保留下来,只是以更紧凑的形式存在。然而在实践中,它引入了三种随时间累积的不同错误类型:
捏造事实。 摘要是生成的,而不是复制的。模型在总结一段长对话时,偶尔会引入隐含而非明确陈述的信息,或者是合理推断而非实际存在的内容。一旦这种捏造进入摘要,它就成为所有后续轮次的"基本事实"。
错误关系。 摘要将顺序推理压缩为并列事实。一个条件决策("如果 API 速率限制被证明是个问题,那么使用缓存")变成了一个扁平陈述("正在使用缓存")。条件性——以及背后的推理——消失了。
遗漏关键细节。 摘要优化的是显著性,而不是完整性。小但重要的细节——用户指出的特定边缘案例、被拒绝的替代方案及其原因——会在压缩过程中被剔除,因为它们在摘要时看起来不够核心。当四十轮后出现相关问题时,它们就变得至关重要了。
每次压缩传递都会略微降低摘要质量。长期运行下来,你得到的是一个"记住"了经过净化的、通用版本对话的 Agent——自信、流畅,但是错误的。
滚动替换模式
解决方案不是避免压缩,而是增量压缩而非一次性全量压缩。
在滚动替换中,你维护上下文的两个区域:
- 热区(Hot region):最近 N 轮原始对话轮次,逐字保留(通常为 10–20 轮)。
- 暖区(Warm region):比热区更旧的所有内容的持久化结构化摘要。
当新轮次到来且热区溢出时,你不会从头重新摘要所有内容。你识别出即将从热区边缘滑落的轮次,仅对该轮次(或一小批)进行摘要,然后将这个新的迷你摘要合并到持久化的暖区摘要中。持久摘要以增量方式增长,而不是被整体替换。
这种锚定迭代方法——更新摘要而非重建摘要——避免了全量重建的复合错误。暖区摘要永远不必"记住"它从未被直接告知的内容。每个增量都是对少数几轮特定对话的小型、可验证的摘要。
热区为即时推理提供连续性。暖区提供背景上下文和决策历史。关键是,两个区域都不会完全消失——你是在压缩,而不是在删除。
设计保留决策理由的摘要 Schema
团队在摘要 Schema 上犯的最大错误是将其视为事实提取器。一个只捕获"决定了什么"的摘要 Schema 在最重要的测试中会失败:解释为什么。
当 AI 会话跨越复杂任务的 40 多轮时,模型经常需要对早期选择进行推理。"我应该使用方法 A 还是方法 B?"——如果 A 在十二轮前被考虑并拒绝,模型需要知道这一点以及原因,而不仅仅是 B 目前正在使用。
生产级摘要 Schema 应明确分离四类信息:
决策及其理由。 不只是"我们选择了 X",而是"我们选择 X 是因为 Y;替代方案 A 和 B 因为 Z 被拒绝。"推理链与结论同等重要。
活跃约束和用户陈述的需求。 用户说过必须为真的事情。这些是最危险的遗漏——违反它们会产生用户体验为 AI"没有认真听讲"的回应。
已探索和被拒绝的路径。 已经尝试过但没有效果的内容。这防止模型重新探索死胡同,在已经排除的选项上浪费轮次。
开放性问题和依赖关系。 什么尚未解决,什么依赖于什么。复杂任务通常有相互依赖关系;丢失这些的摘要会在后续轮次中产生不连贯的规划。
注意这个 Schema 中缺少什么:对话纹理的摘要、寒暄、复述,或者没有产生新信息的澄清交流。这些内容可以安全地积极压缩。不安全压缩的是决策逻辑。
Mem0 和 LlamaIndex 的内存块架构明确地结构化了这一点,将语义记忆(提取的事实)、情节记忆(带有时间上下文的特定决策)和程序记忆(会话期间建立的规则和模式)分离开来。情节与程序之间的区别对于多步骤 Agent 特别有用:一个程序("在修改资源之前始终检查权限")应该比一个情节("用户询问了账单页面")经历更多的压缩周期。
检测压缩引起的质量漂移
上下文退化的阴险之处在于,你在它成为问题之前看不到它。模型继续生成流畅、自信的回应;质量下降体现在准确性和一致性上,而不是表面连贯性上。
用于滚动压缩的有效评估框架测试三件事:
决策召回。 在第 30 轮,模型能否正确解释为什么在第 8 轮做出的决定优于其替代方案?这需要维护决策及其陈述理由的基准日志。压缩后,用正确答案依赖于保留的决策理由的问题来探测模型。
约束一致性。 在早期引入约束("在不解释原因的情况下,永远不要推荐第三方库"),然后定期检查模型是否仍然遵守它们。失败的约束表明摘要丢弃了它。
矛盾率。 定期要求模型重述其对关键事实的当前理解。与原始日志中的早期陈述进行比较。仅在压缩事件后出现的矛盾将压缩确定为原因。
目标不是零退化——压缩总会丢失一些东西——而是检测损失何时从可接受跨越到重要。一个好的基准:压缩后的模型能否以与拥有完整原始历史的模型相同的准确性回答关于第 1–10 轮的事实性问题?如果差距超过 10–15%,摘要 Schema 保留的内容不够充分。
Chroma 2024 年关于上下文腐化的研究将 30,000 Token 标记确定为质量退化明显加速的拐点。这提供了一个实用触发器:在目标阈值的 70–80% 时开始压缩,而不是在极限时,这样你就不会在退化区域中运行。
实践中的样子
LangChain 的 ConversationSummaryBufferMemory 实现了这种混合模式的一个版本:它将最近的消息逐字保留到 Token 限制,然后将较旧的内容摘要为一个持续运行的摘要。关键参数是 max_token_limit——较小的值导致更频繁的压缩调用(成本更高,但每次事件的质量损失更低);较大的值减少调用,但在触发之前存在质量退化的风险。
LlamaIndex 的内存块架构使分层明确:ChatMemoryBuffer 用于原始近期轮次,ChatSummaryMemoryBuffer 用于摘要的较旧内容,向量内存用于遥远但相关历史的语义检索。
Anthropic 推荐的扩展会话 Agent 方法是服务器端压缩——让 API 处理上下文管理——结合对工具密集型工作流的显式上下文编辑(在处理完工具结果后清除它们,因为原始工具输出通常很大且很少需要重新读取)。
这些都不是魔法。共同点是它们将上下文窗口视为具有明确策略的托管资源,规定什么保持原始状态、什么被压缩、什么被丢弃——而不是一个要么填满要么定期清空的缓冲区。
质量下限在 Schema 中
在长会话质量上挣扎的团队通常将其框架化为上下文窗口问题:通过扩大窗口来修复它。真正的问题是他们将决策逻辑与对话噪声一起压缩了,而模型无法区分两者。
上下文窗口决定了你能放多少内容。压缩 Schema 决定了什么在压缩中存活下来。一个明确保留决策理由的精心设计的 Schema——不只是结论,而是其背后的推理——即使在有效窗口小得多的情况下,也会始终优于朴素摘要。锚定迭代摘要,结合用于决策捕获的显式 Schema,是在会话规模扩展到四十、六十或一百轮时保持质量的模式。
评估很简单:要求模型解释为什么它做出了早期决策。如果它做不到,你的 Schema 没有保留正确的内容。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部