去年我做客服 Agent 时,发现一个诡异的现象:前几轮对话,模型的表现好得惊人;聊到第 40 轮之后,它连用户刚说过的订单号都能搞混。我把日志拉出来一看,整个对话历史——包括所有寒暄、重复、无关话题——全被原封不动塞进了 prompt。上下文从 500 token 涨到 8000 token,模型的输出质量肉眼可见地下降。这不是模型变笨了,而是它被自己吃掉的历史噎住了。

你可能觉得,换一个上下文窗口更大的模型不就行了?我一开始也是这么想的。换成 64K 上下文模型后,问题反而更严重。
为什么上下文越长,Agent 越像失忆?
核心机制叫注意力稀释。Transformer 的注意力计算里,每个 token 都要跟其他所有 token 打个招呼,然后按相关性分配权重。所有 token 的注意力权重之和固定是 1。当上下文里有 8000 个 token,你的关键信息平均只能分到 1/8000 的注意力,而它身边还有几十个语义相似的干扰 token。模型不是没有注意你,而是它面前挤了太多人,它分不清谁重要。
这有一篇实证论文可以证明。研究者们在 Lost in the Middle 里测了多个 LLM,发现模型在长文档的开头和结尾表现很好,但中间部分的信息提取准确率明显下降。如果你的需求恰好被埋在对话历史中间,它大概率会丢。
所以别骂模型。它只是一个注意力机制,不是记忆系统。
更隐蔽的是:模型会混淆指令和旧对话
除了注意力稀释,上下文污染还有一个更隐蔽的问题:指令冲突。模型不会自动区分"用户过去说的话"和"系统提示词"。如果用户在第 10 轮说过"这个单子我不想要了",而系统提示要求"所有订单必须完成",模型就可能被旧对话带偏。
另外,长上下文里时间信息是隐式的。Transformer 的位置编码只能表达相对位置,不能表达"这条消息是几秒前还是三天前"的绝对时间。所以当历史很长时,模型会分不清哪些是最近的、哪些是过期的。
别把历史塞进上下文,把历史管起来
正确的思路是:把上下文窗口当成一次"快速阅读"的输入,而不是存储介质。你需要给 Agent 外置记忆系统。
方案一:摘要压缩,让模型看总结而不是看原始记录
最简单有效的手段:每过 N 轮,用 LLM 把前面的对话总结成一段摘要,然后只把摘要给模型。比如 20 轮对话压缩成三句话:"用户要求退款,原因为商品破损,退款流程已启动,等待物流签收"。这样上下文从 5000 token 变成 200 token,信噪比高了一个量级。
但摘要会丢细节。用户提及的尺码、日期、订单号,摘要可能记不住。所以摘要必须分层:把"事实"和"过程"分开。事实单独抽出来结构化存储。
方案二:动态记忆,模仿人的工作记忆和长期记忆
更结构化的做法是给 Agent 设计两层记忆。工作记忆只保留最近 3 到 5 轮对话的原文,用来理解当前意图;长期记忆抽取历史中的关键实体和状态,存成 JSON。比如 {"user_name": "张三", "pending_refund": true, "shoe_size": "42"}。每次新请求进来,模型看到的上下文是:系统提示 + 最近几轮 + 长期记忆。
这个方案比摘要更可靠,因为当某个事实在长期记忆里缺失时,你至少知道它没有被记住,而不是猜测它有没有被记住。
方案三:检索增强,只给模型看相关的历史
把每一轮对话切块,用向量数据库存起来。每次收到新消息,先做语义检索,找到最相关的 5 个历史片段,再拼进 prompt。这样模型每次阅读的都是"高浓度上下文",不会被无关历史稀释。
这个方案适合知识库型 Agent,但它依赖检索质量。如果 embedding 模型抓不住语义,检索结果就会很飘。
一张表说清四种方案的取舍
| 方案 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 全量历史 | 实现最简单,不丢信息 | 信噪比低,指令冲突,成本高 | 少于 10 轮演示 |
| 摘要压缩 | 上下文精简,信噪比高 | 细节丢失,实时性差 | 事实变化不频繁的客服、问答 |
| 动态记忆 | 可控性强,专业任务效果好 | 需要设计 schema,开发成本高 | 任务型 Agent、多步骤流程 |
| 检索增强 | 可扩展,不丢细节 | 受检索质量影响大,增加组件 | 知识密集型 Agent |
我最后用的是 2000 token 的混合上下文
在客服场景里,我最终采用了:最近 3 轮原文 + 每 10 轮生成一次摘要 + 长期记忆存储关键状态。prompt 总长度控制在 2000 token 左右。和全量历史相比,实测准确率从 68% 提高到 91%。这个数字不稀奇,换一个场景可能效果不同,但方向是一致的:上下文要"精炼",不要"完整"。
FAQ:关于上下文污染,你最可能想错的三件事
长上下文模型不是越来越强吗?为什么还需要压缩?
长上下文解决的是"塞得下"的问题,不是"记得住"的问题。模型在长输入上的表现衰减是实测存在的。除非未来模型真正做到线性注意力,否则压缩仍然必要。
摘要会不会丢掉关键事实?
会,所以摘要要和结构化抽取配合。把实体、数字、状态单独拎出来,摘要只管叙事脉络。
用 RAG 把历史全部索引起来,是不是就干净了?
不一定。RAG 只是把上下文变成动态检索,如果查询意图表达不清楚,检索结果照样会引入新噪声。我建议先做好记忆结构,再考虑 RAG。
我的判断:Agent 需要的是记忆管理,不是更大的窗口
上下文污染本质上是 Transformer 注意力机制在信噪比下降时的自然衰减,不是 bug。你不能要求模型在几万 token 里像人一样忽略噪声。所以未来的 Agent 框架一定会越来越像软件工程:显式的状态管理、模块化的记忆、健康的输入输出边界。别再把模型当成一个无限记忆聊天机器,把它当成一个"每次只能看一屏"的实习生。你的职责是决定哪一屏内容出现在它眼前。
这套方法什么时候会失效?如果你的任务要求历史中的每个 token 都有不可丢弃的信息(比如法律合同逐句审查),摘要、记忆、检索都会造成损失,你只能依赖更长的窗口或专门微调过的模型。了解这个边界,你才能选对工具。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/395.html