一个真正可用的知识问答系统,很少只回答单轮问题。在多数实际场景中,用户会进行连续追问、澄清、或切换话题,这就要求系统能够记住之前的对话内容,并基于已有上下文给出连贯、准确的回应。上下文记忆管理,就是 RAG 系统中负责存储、召回和组织对话历史,使得多轮交互成为可能的那一部分设计。
1. 为什么需要显式管理记忆
大语言模型本身是“无状态”的,每次调用看到的只是从外部传入的提示词。如果不做任何处理,第 10 轮提问时,模型根本不知道前 9 轮聊了什么。单靠用户每次手动复述是不现实的。
好的记忆管理能让系统:
- 理解指代和省略:用户说“它支持 5G 吗?”,系统需要知道“它”指的是上一轮提到的某款产品。
- 避免重复检索或回答:已提供过完整答案的问题如果再次以不同方式问出,系统能给出简短确认而非冗长重复。
- 支持渐进式信息获取:用户逐步补充条件,系统能累积意图,最后给出精准答复。
- 在适当时候“遗忘”无关内容:切换话题后,过时的上下文不再污染当前回答。
2. 常见的管理粒度
记忆管理的粒度取决于应用场景的复杂度和对成本的容忍度:
- 全量对话缓存
最直接的方式是将每一轮“用户提问+系统回答”原样追加到提示词末尾,构成完整的历史记录。实现简单,小型对话完全够用。但上下文窗口有限,长对话会超出模型限制,同时也会让每次调用的 token 消耗持续增长,成本逐渐失控。
- 滑动窗口
只保留最近 N 轮对话。超过 N 轮的旧信息直接丢弃。有效控制了长度,但可能丢失关键背景信息,适合短会话或明确的话题切换场景。
- 摘要式记忆
在对话进行到一定长度时,调用模型自动生成一段简洁的对话摘要,替代原始历史。之后的回答基于摘要+最新几轮对话。既能压缩信息,又保留核心背景。实践中,可以设定一个触发阈值(如超过 10 轮或总 token 数超过 3000 时生成摘要),在成本和连贯性之间取得平衡。
- 混合方案
将遥远的对话生成摘要,近期的几轮保留原文,同时两者的组合会放入提示词。这样,早期的关键决策、偏好等不会丢失,近期细节也保持清晰。这是目前多轮智能体系统中较常用的做法。
3. 多轮对话中的 RAG 检索策略
记忆管理还会影响检索环节的行为。常见策略包括:
- 仅用最新问题检索:简单高效,但在用户使用指代时(“这个呢?”),单独的“这个呢”无法检索到任何有价值的内容。
- 结合上下文重写查询:在检索前,先调用一次小模型或直接通过规则,利用记忆中的上下文,将“这个呢?”改写为“这款手机的内存是多少?”,再进行检索。这是效果和复杂度折中的好方案。
- 会话级检索记忆:部分场景下,可以为当前会话维护一个“已使用过的文档片段集合”,当用户再次指向时直接调取,避免重复检索,同时保持引用的一致性。
4. 会话状态存储的选择
记忆的持久化落盘方式也影响系统可用性:
- 内存存储:用字典等结构保存在进程内存中,读写极快,但服务重启即丢失。适合原型或低风险内部工具。
- 外部缓存(Redis 等):将对话历史序列化为 JSON 存入 Redis,可设置过期时间,自动清理长时间无活动的会话。对生产环境而言,这是轻量且可靠的选择。
- 数据库持久化:存入 MySQL 或 MongoDB 等,适合需要长期保留对话记录以备审计或数据分析的场景。成本稍高,但提供了完整的查询和管理能力。
5. 实用经验与避坑指南
- 设置合理的会话超时:通常 30 分钟无活动可视为会话结束,及时释放资源。用户再次发消息时,系统应给出“开始新对话”的提示,避免混淆上下文。
- 标记信息来源的持久性:在多轮中引用的文档片段若在对话中途被更新,可能出现“回答前后不一致”的尴尬。因此对可能变动的知识(如股价、库存),最好在每轮回答前进行轻量级重检,或至少不带入过旧的检索缓存。
- 保护用户隐私:上下文可能包含敏感信息,落盘聊天记录时须注意脱敏和合规。设定自动清理策略,避免无限制留存。
- 显式提供重置能力:为用户或前端提供“清除上下文”“开始新会话”的按钮或指令,让记忆管理的结果可被用户感知和控制。
总的来说,上下文记忆管理是一个看似基础、实则处处需要权衡的设计点。合适的记忆策略能让 RAG 系统从“一问一答的工具”升级为“连贯交流的助手”,在维护简洁和成本控制的同时,确保用户感觉到对话的自然与智能。