这道题其实是在问,当对话从单轮变成多轮,模型怎么保持记忆和一致性。核心矛盾是,大模型本身是无状态的,每轮输入都要靠我们帮它把历史信息组织好。
先说挑战。最典型的是指代消解,用户说“这个”、“刚才说的”,模型得跨轮去猜。再一个是话题漂移,用户可能聊着聊着突然问别的,过一会儿又回来,模型能不能识别这是插话还是真切换。还有就是长程依赖,用户开头说“用简洁风格”,过了十轮模型就忘了,开始长篇大论。最后是一致性冲突,模型前面否定了一个东西,后面又肯定,或者人设前后不统一。
怎么解决呢,我按层级来说。首先是上下文管理,最粗暴的是[[滑动窗口]],但窗口外的东西就丢了。所以一般会加摘要压缩,用轻量模型每几轮生成一个摘要,把历史浓缩一下。但摘要也有信息损失,所以更靠谱的是分层记忆,把工作记忆和长期记忆分开。工作记忆存最近几轮对话,长期记忆存用户画像、关键事实这些。
再一个是状态跟踪,也就是 对话状态表,结构化地跟踪当前实体、意图、约束条件。比如客服场景,用户说“我要退昨天买的那个红色T恤”,状态表里就记下“订单号、退款原因、商品属性”。这样后面再问“什么时候能到账”,模型能关联到退款流程,而不是当成新问题。
但状态表有个问题,它只适合结构化场景,像客服、订票这种领域明确、槽位固定的任务。如果用户聊得很开放,状态表就不好维护了。这时候会用 [[RAG]],检索历史相关片段,动态找回上下文。比如用户突然问“那刚才说的满减政策还适用吗”,RAG能去历史里把之前讨论的政策片段捞出来。
训练层面,[[SFT]] 和 [[RLHF]] 也能针对性优化。SFT 用多轮对话数据让模型学会看历史,RLHF 则用偏好对齐,让模型避免前后矛盾。但训练成本高,而且模型学了也不一定稳定,所以落地时我更倾向用推理侧的手段兜底。
具体到业务场景,比如电商客服的退款流程。用户第一轮说“我要退款”,第二轮说“订单号是123”,第三轮问“钱什么时候退”。模型如果没记住退款意图,第三轮可能当成新问题去查订单物流,那就错了。所以我的做法是:用摘要压缩保留对话脉络,同时用状态表维护退款意图和订单号,最后在prompt里注入一个“已确认事实”列表,让模型每次回答前自检是否冲突。这里有个坑,就是状态表如果维护不好,比如槽位填错了,后面全错。所以上线我会特别关注状态表的准确率,加一个显式验证环节,关键决策前让模型自检“这个回答和之前说的矛盾吗”。
不过,状态表虽然好用,但维护成本很高,特别是槽位多、值不确定的时候。我最近在关注一种思路,就是用 [[Self-RAG]] 让模型自己学会反思,而不是靠外部状态表强控,这样泛化性更好。
所以总结一下,我会把多轮对话的优化看成一套组合拳:上下文管理保证记忆不丢,状态表保证结构化跟踪,RAG解决非线性依赖,训练和prompt工程做一致性兜底。没有银弹,关键是看场景选方案。