本节摘要:状态追踪是 DM 的基础——记录"对话进行到哪、已收集什么"。本节讲清状态的数据结构(槽位 + 历史 + 用户信息)、追踪流程、状态更新与置信度,以及"状态是 DM 的记忆"的核心理解。
阅读完本节,你应当能够:
"系统怎么记得对话到哪一步?"——靠状态追踪:一个结构化的"进度表",记录已收集的槽位、对话历史、用户信息。每次用户说话,状态更新一次。状态就是 DM 的"记忆",没有它,对话就"失忆"。
NLU 结果 → 更新槽位 → 记录历史 → 更新进度 → 交给策略
💡 关键直觉:状态 = 对话的"便签本"——所有决策都看便签本:还缺什么就问,齐了就执行。便签本记得好,决策才准。
| 情况 | 处理 |
|---|---|
| 新槽位值 | 直接更新 |
| 槽位改口 | 覆盖更新 |
| 值不确定 | 记录置信度 |
| 用户反悔 | 回退状态 |
⚠️ 常见坑:状态只有"最后一轮"没有"历史"。用户改口需要知道之前的值——状态要保留"当前值 + 变更记录",才能正确处理改口。
槽位值带置信度 低置信 → 澄清确认 高置信 → 直接采用
覆盖所有必需槽位吗 能处理改口吗 用户信息有地方存吗 状态能持久化吗(跨会话)
状态记住了,下一节学决策——对话策略学习。
"状态 = 槽位 + 历史 + 用户信息 + 进度",这里展开两个工程细节:状态怎么表示、置信度怎么影响决策。
状态的两种表示方式:一种是显式的槽位键值表(前文那种字典形式),简单直观,适合规则与状态机;另一种是概率分布形式——每个槽位的候选值带一个概率(如日期"周五 0.8 / 周六 0.2"),适合统计对话状态追踪与强化学习策略。生产系统常从显式起步,遇到槽位识别不稳定时再引入置信度:
# 概念示意:带置信度的槽位 slots = { "date": {"value": "周五", "confidence": 0.9}, "origin": {"value": "北京", "confidence": 0.85}, "dest": {"value": None, "confidence": 0.0}, # 缺失 }
置信度的使用规则:并不是"分数低就一定要澄清"——低分澄清和高分采用之间需要一条明确的线,同时考虑槽位对任务的重要性:
置信度 ≥ 0.9 且槽位非敏感 → 直接采用,不问 置信度 0.6~0.9 且槽位关键 → 顺带确认("周五出发,对吗?") 置信度 < 0.6 → 单独追问该槽位 槽位敏感(金额、账号、时间) → 必须确认,无论分数
状态更新语义要同时处理好三种情况:新增(第一次填)、覆盖(改口)、否定(用户说"算了"清掉该槽或整个任务)。每次更新保留变更记录,便于回退与审计。状态还要能持久化——跨会话场景(如用户隔天继续办理)需要把状态存到会话存储里,而不是只放在内存。
检查清单:状态是否覆盖全部必需槽位;改口能否正确处理;敏感槽位是否强制确认;状态能否跨会话持久化;多轮结束时状态是否被正确归档。这些检查在开发期做完,线上多轮对话的质量就有保障。
用一段真实对话练手,逐轮更新对话状态并记录每步的更新语义。对话:"帮我订周五去北京的票" → "出发时间有要求吗?没有,都行" → "那改成周六吧" → "算了,不用了"。请逐轮写出:本轮 NLU 输出了哪些槽位、任务状态里哪些字段被新增/覆盖/清空、系统下一步该问什么。对照答案检查三点:第二轮的"没有,都行"应清空或确认出发时间槽位;第三轮"改成周六"应覆盖 date 而不应新增一个意图;第四轮"不用了"应清空任务状态并结束流程。能准确走完这四个回合,说明你对"状态更新语义"的理解已经可以支撑实际开发——这正是对话状态追踪在日常工程里的全部应用。