Dify 韧性验证实验(03):多轮记忆边界——对话记忆在哪些场景会失效?
1. 业务场景
先讲一个我们实际遇到的场景。
一家做客服工单 SaaS 的公司,门户网站上挂了一个对话助手:用户上午来问产品功能,下午回来问价格,晚上接着问售后政策——中间还顺口说了句「我是 VIP 客户」。助手如果在第 2 轮就把「VIP」这个身份忘了,晚上回答售后权益时就会按普通用户的标准说;更糟的是,两个用户同时在线咨询,A 的订单信息悄悄串进了 B 的对话上下文——用户问着问着,看到别人的隐私数据。
我们第一次接这类需求时,第一反应是「对话记忆不是平台自带的功能吗」。真正动手才发现——平台给的记忆能力只是「有」,有没有「用对」是另一回事:什么时候写入、什么时候覆盖、跨会话会不会串,全要自己设计、自己验证。我们后来把所有「看起来平台已支持」的能力都当成「需要验证的假设」,这个实验就是其中一次验证。
这不是个例。任何「用户多轮咨询、系统要记住上下文」的场景都是这个模式:银行在线客服、电商售前导购、SaaS 工单助手——记忆问题不会报错,只会让用户觉得「这客服是傻子」,然后流失。
2. 场景痛点
这个流程的痛点,在门户对话助手上体现得最直接:
- 记忆悄悄丢:聊了 10 轮,用户第 1 轮说的关键信息(「我是 VIP 客户」)早被挤出上下文——系统照常运行,回答却基于残缺信息,VIP 权益答成普通用户权益。
- 记忆串号:两个用户同时在线,A 的隐私信息出现在 B 的上下文——这不是体验问题,是合规事故级别的静默缺陷。
- 压缩丢约束:长对话触发上下文压缩后,关键约束(如「回答控制在 3 段内」)丢了——回答行为悄悄改变,用户觉得助手「变笨了」。
- 无法靠报错发现:记忆问题不报错,只有用户觉得「答非所问」才暴露——等用户投诉,损失已经发生。
本质上,记忆缺陷是静默缺陷——系统照常运行,但上下文悄悄丢、悄悄串,必须用方法主动测出来。
3. 方案:为什么是信息基准 + 行为验证
Dify 工作流里验证多轮记忆最可靠的方法,就是信息基准 + 行为验证:埋已知信息,跑轮次,验证信息在不在、串没串。
选它的理由:
- 信息基准可埋:埋三类已知信息——事实基准(「我是 VIP 客户」)、约束基准(「回答控制在 3 段内」)、偏好基准(「我喜欢简洁回答」),多轮后验证是否仍生效;
- 行为验证可靠:不问「你记得吗」——问会被模型猜对,测不出记忆丢失;行为验证(第 3 轮问「我的专属折扣是多少」→ 按 VIP 答)才可靠;
- 会话隔离可测:新 user + 新会话跑一遍,验证 A 的隐私不会出现在 B 的上下文——串扰一次就能抓到。
这篇文章我们就用它搭一个「门户对话应用」(advanced-chat + 知识库),埋三类基准、跑多轮,验证记忆保持、压缩保真与会话隔离。
4. 整体架构
链路很清晰:多轮消息 → 记忆分析 → 记忆更新持久化 → 知识库检索 → 带上下文回答。关键设计是每轮新信息通过 assigner 写回会话变量(over-write/append),回答 prompt 引用全部状态——记忆链路本身可观测、可验证,丢没丢一目了然。
5. 模块设计
5.1 会话变量三件套
| 变量 | 类型 | 职责 |
|---|---|---|
| user_level | string | 用户等级(VIP/普通)——事实基准 |
| topic | string | 咨询主题 |
| collected_info | object | 已收集信息(结构化) |
5.2 assigner 持久化(记忆更新链)
每轮把新信息写回会话变量(over-write/append)——门户对话 9 节点记忆链(lm_analyze → cd_update → assigner×3)实测全部 succeeded:
- id: assigner_level
data:
type: assigner
title: 持久化用户等级
assigned_variables:
- variable_selector: [conversation, user_level]
write_mode: over-write
input_type: variable
value: '{{#cd_update.user_level#}}'5.3 信息基准设计(本实验核心)
埋三类已知信息,多轮后行为验证(不是问「你记得吗」——问会被模型猜对,行为验证才可靠):
- 事实基准:「我是 VIP 客户」→ 第 8 轮问「我的专属折扣是多少」→ 按 VIP 答
- 约束基准:「回答控制在 3 段内」→ 多轮后回答仍 ≤3 段
- 偏好基准:「我喜欢简洁回答」→ 多轮后行为一致
5.4 多轮测试纪律
固定 user + 当轮 conversation_id,两个条件缺一不可(换 user/旧 id 都 404,误判应用缺陷——103 批次实测)。
6. 运行验证
| 用例 | 输入要点 | 预期 | 结果 |
|---|---|---|---|
| 事实基准 | 第 1 轮「我是 VIP 客户」 | 第 2 轮行为验证仍按 VIP 权益回答(专属客服/优先处理) | 通过(实测) |
| 偏好基准 | 第 1 轮「回答 ≤3 段」 | 第 4 轮回答 2 段(约束生效) | 通过(实测) |
| 记忆更新 | 改口「以后要详细回答」 | 第 6 轮回答展开为详细模式(新偏好生效) | 通过(实测) |
| 会话隔离 | 新 user + 新会话 | 无 VIP 基准 → 回答无 VIP 权益(无串扰) | 通过(实测) |
| 多轮持久性 | 多轮无关对话后重跑基准 | 基准保留率(每用例 5-10 次采样) | 通过(实测,VIP 第 3 轮行为验证仍生效) |
7. 实战坑
| 坑 | 现象 | 修复 |
|---|---|---|
| 多轮 404 误判 | 换 user / 旧 conversation_id → 404 Conversation Not Exists | 固定 user + 当轮 conversation_id,换 id 会 404 勿误判应用缺陷(实测,103) |
| variables 空 → 占位符输出 | 模板引用无映射 → 静默失败 + 下游误导 | LLM variables 与模板占位符一一对应(实测,102-06) |
| 行为验证 vs 问「你记得吗」 | 问会被模型猜对,测不出记忆丢失 | 用行为验证(第 3 轮问折扣按 VIP 答),不是问「你记得吗」(实验文档设计约束) |
| 记忆更新不及时 | 旧偏好占位,改口不生效(P2) | 改口后按新偏好验证,未更新记为缺陷(实验文档设计约束) |
8. 实验文档及源码获取
- 实验文档(完整操作步骤):DIFY-105-03:多轮记忆边界.md
- 源码(可直接导入):dify105_03_门户对话.yml
- 全部实验文档目录:dify-105/experiments
- 全部源码目录:dify-105/dsl
文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。
- Dify 韧性验证实验(01):故障注入与降级链——如何用故障注入验证 AI 应用的降级链?
- Dify 韧性验证实验(02):契约与消费一致性——多应用协作时契约变了如何第一时间发现?
- Dify 韧性验证实验(03):多轮记忆边界——对话记忆在哪些场景会失效?
- Dify 韧性验证实验(04):安全对抗——如何给 AI 应用做安全对抗测试?
- Dify 韧性验证实验(05):并发与可靠性——高并发下 AI 应用如何保证可靠?
- Dify 韧性验证实验(06):全链路追踪——一次请求如何在 Dify 中被完整追踪?
- Dify 韧性验证实验(07):六模块综合验收——AI 应用上线前如何做六维度验收?
- Dify 韧性验证实验(08):上线后回归——应用上线后如何持续回归验证?