模型为什么会“忘记”前面的对话?
从一条丢失的播放约定出发,看看聊天记录怎样变成这一轮模型输入。
一段对话聊了很久,模型却突然违背了最开始的要求。往上翻,那句话明明还在。
这种情况容易被理解成“模型忘了”。但往下排查,要先分开两件事:聊天界面保存了什么,以及这一轮请求实际交给模型的是什么。它们可能并不相同。
从一条要求开始
拿一个做博客的对话举例。开头先约定:视频由读者点击播放,不自动播放。 后面讨论了排版、配色、图片尺寸,又加入新的文章。到了最后,提出“在文章里放一个视频预览”,生成的页面却带上了自动播放。
这时有两个可能的方向:早先的约定没有进入这一轮输入;或者它仍在输入中,但模型没有正确执行。两者的处理方法不同。
先看第一种。聊天记录可以长期保存在应用里,而模型每一轮能使用的上下文有容量限制。应用需要从记录中选择内容,再组织成这次请求。
因此,面对这个例子,第一步应当检查发出的请求,而不是继续强调“我已经说过了”。
模型看到的是组织后的序列
在常见的自回归聊天模型中,应用里的消息列表会按模型需要的模板,转成包含角色标记的 Token 序列。用户消息、助手回答和工具结果由相应格式区分。不同模型的模板可能不同。[1]
下面是这个例子希望保留的输入结构:
长期约定:视频由读者点击播放,不自动播放。
当前页面:个人博客的文章详情页。
当前任务:加入十五秒的视频预览。
这份记录把当前任务需要的信息单独保留下来。播放约定短,但直接影响结果;已经结束的配色讨论长,却不一定有必要继续占用位置。
工具结果也会占用上下文。一次读取几千行文件、反复追加同样的日志,都可能让重要要求更难被选入或利用。上下文整理需要同时考虑信息量和用途。
对话变长以后,怎样保留历史
最直接的办法是保留全部历史。对话较短时,它让前后过程保持完整;随着内容增加,输入会越来越大。
另一种做法是只保留最近几轮。它简单,但这个例子里的播放约定恰好在最开头,就容易被窗口挤掉。
摘要能把较早的讨论压缩成短段落,不过它也可能改变含义。“文章需要视频展示”和“视频必须由读者点击播放”是两种不同的记录。只留下前者,关键约束就丢了。
检索记忆则在需要时取回相关记录。它适合分散在较长历史中的信息,但能不能找对,仍取决于保存方式和检索结果。[2]
实际应用可以组合这些方式:近期消息保留原文,已完成的讨论形成摘要,需要时再取回旧资料。像“不自动播放”这样的明确约束,适合从普通聊天中提取出来,作为任务状态单独维护。
摘要应该留下决定,而不只是话题
继续看视频的例子。下面两份摘要都很短,但效果会不同:
讨论了博客布局、配色和视频展示。
采用纸白朱红配色。文章视频由读者点击播放。接下来加入视频预览。
第二份记录保留了能指导下一步的决定。若后面又改成允许自动播放,状态也需要更新,不能让两条互相冲突的约定一直并列存在。
我会把这类状态分成三部分:已经确认的要求、当前做到哪里、下一步要处理什么。原始聊天仍可以保存,整理后的状态用于推进任务。
要求已经带上,仍然答错怎么办
把信息放进输入,不保证模型一定能正确使用。此时需要看它有没有理解约束、有没有被互相冲突的内容干扰,以及输出是否经过检查。
《Lost in the Middle》在多文档问答和键值检索实验中观察到,相关信息在长输入中的位置会影响所测试模型的表现。[3] 这不能直接推断所有模型、所有任务的结果,但足以提醒我们:上下文容量与有效利用上下文是两个问题。
在视频例子中,程序还可以直接检查生成的 HTML 是否含有 autoplay。明确的规则有机会变成确定性的检查;不用把每次纠错都交给另一轮提示。
排查时,按这三步走
- 看输入。 最初的要求有没有进入这一轮请求?摘要有没有把它改写丢失?
- 看状态。 新旧决定是否冲突?当前任务是不是仍然沿用过期信息?
- 看输出。 信息齐全时,模型有没有执行约束?能否用程序检查结果?
如果第一步就发现播放约定不在输入里,扩大模型能力并不能直接修好应用的记录方式。如果约定完整保留却仍生成了自动播放,则应当检查提示组织与输出校验。
“忘记”是一个观察到的现象。沿着记录、输入和输出走一遍,才能找到它发生的地方。
参考资料
- Hugging Face · Chat templates:消息列表如何变成模型使用的序列。
- Anthropic · Effective context engineering for AI agents:上下文选择、压缩、笔记与按需读取。
- Lost in the Middle: How Language Models Use Long Contexts:长上下文中信息位置与任务表现的实验。