上下文污染:Agent 的对话历史太长反而导致表现下降——怎么解决

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

AI technology illustration

你可能觉得,换一个上下文窗口更大的模型不就行了?我一开始也是这么想的。换成 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

(0)
上一篇 4天前
下一篇 4天前

相关推荐