用户澄清方案设计与实现要点

1. 为什么需要"用户澄清"

当用户使用自然语言输入业务信息时,LLM 抽取出来的往往只是原始表达,而不是系统可直接执行的标准主数据。

例如:

  • "华通" → 可能对应多个客户
  • "旗舰版" → 可能对应多个产品 SKU
  • "张总" → 可能对应多个联系人
  • "上次那个客户" → 强依赖上下文
  • "不是信息那个" → 需要基于候选上下文理解

如果系统在不确定时仍然直接采用某个结果,就会产生:

  • 错误客户
  • 错误产品
  • 错误联系人
  • 后续报价、审批、查询全链路错误

所以必须在"自动匹配不足够确定"时,引入一个受控的澄清流程:

用户澄清 = 在实体匹配不确定时,系统主动让用户确认最小必要信息,以保证后续业务执行的准确性。


2. 什么时候触发澄清

推荐把匹配结果统一分成三类:


2.1 confirmed

高置信唯一命中,可自动采用。

例如:

  • 用户说"华通科技有限公司"
  • 系统唯一命中 cust_001

策略:

  • 直接写入草稿
  • 不打断用户

2.2 ambiguous

存在多个合理候选,需要用户确认。

例如:

  • "华通" →
    • 华通科技有限公司
    • 华通信息技术有限公司

策略:

  • 进入用户澄清流程
  • 提供候选列表
  • 等待用户选择

2.3 failed

未找到候选,或候选置信度太低。

例如:

  • "至尊版"在产品库里不存在
  • "老王公司"无法匹配客户

策略:

  • 不进入"候选选择型澄清"
  • 而是提示用户补充更完整信息

3. 澄清流程整体设计

标准流程建议如下:

text 复制代码
用户输入
  ↓
字段抽取
  ↓
主数据匹配
  ↓
结果判断
  ├── confirmed → 自动采用并继续
  ├── ambiguous → 发起澄清
  └── failed → 请求补充

如果触发 ambiguous:

text 复制代码
系统生成候选问题
  ↓
保存 pending_resolution
  ↓
用户回复澄清信息
  ↓
解析用户选择
  ├── 解析成功 → 写回草稿并继续
  └── 解析失败 → 再提示用户

4. 澄清状态存储设计

用户澄清必须有显式状态,不能仅依赖聊天上下文。

推荐在 session / conversation context 里存:

json 复制代码
{
  "active_draft_id": "qd_123",
  "pending_resolution": {
    "entity_type": "customer",
    "raw_value": "华通",
    "candidates": [
      {"id": "cust_001", "name": "华通科技有限公司", "score": 0.91},
      {"id": "cust_002", "name": "华通信息技术有限公司", "score": 0.88}
    ]
  }
}

4.1 pending_resolution 的作用

它的作用是:

  1. 告诉系统:当前这一轮用户输入优先被解释为"候选澄清"
  2. 提供候选上下文,让 "1" / "第一个" / "科技那个" 有可解释对象
  3. 在澄清成功后,把正确实体写回草稿
  4. 在澄清失败时,引导用户继续澄清

5. 澄清优先级设计策略

这是整个澄清模块里非常关键的一部分。

如果一轮输入中同时出现多个歧义项,系统不能一次性全部抛给用户,而应采用:

一次只澄清一个最关键的歧义项

这就是"澄清优先级设计策略"。


5.1 为什么必须有优先级策略

假设用户输入:

给华通做报价,产品是标准服务包,联系人是张总

系统匹配后可能得到:

  • 客户 华通 → ambiguous
  • 产品 标准服务包 → ambiguous
  • 联系人 张总 → failed / ambiguous

如果没有优先级策略,系统可能同时问:

  • 客户选哪个?
  • 产品选哪个?
  • 联系人是谁?

这会带来几个问题:

  1. 用户认知负担太高
  2. 用户回复可能只回答其中一个,系统难以判断
  3. 多个问题混在一轮里,回复解析难度剧增
  4. 很多歧义其实存在依赖关系,应该先解上游

5.2 优先级策略的目标

澄清优先级策略的目标不是"把所有歧义都列出来",而是:

  • 在多个歧义项中找到下一步最值得问的一个
  • 让系统每一轮只推进一个最关键的不确定点
  • 保持对话简单、可控、可恢复

5.3 推荐优先级原则

推荐按以下思路确定优先级:

原则 A:先上游,后下游

如果某个实体的确认结果会影响其他实体匹配,就优先澄清它。

例如:

  • 客户会影响联系人匹配
  • 客户会影响产品可售范围
  • 客户会影响价格表

所以通常:

text 复制代码
customer > contact > product

或者:

text 复制代码
customer > product > contact

要根据你的业务来定。


原则 B:先主实体,后附属实体

报价场景里,通常主实体优先级更高:

  • customer
  • product
  • contact
  • delivery_location
  • remarks

原则 C:先阻断型歧义,后非阻断型歧义

如果某个歧义会阻止整个流程继续,那它优先级更高。

例如:

  • 客户没确认,不能继续建报价
  • 联系人没确认,也许还能先继续
  • remarks 不明确,可能完全不影响

原则 D:优先问"用户最容易回答"的问题

如果两个歧义都很关键,优先问更容易让用户直接选出的那一个。

例如:

  • 两个客户名差异明显,用户容易选
  • 两个产品版本差异复杂,用户不一定清楚

这种情况下可以优先问客户。


5.4 一个实用的默认优先级顺序

在报价类系统里,推荐默认优先级:

text 复制代码
1. customer
2. product
3. contact
4. delivery / address
5. other optional fields

原因:

  • 客户通常是报价上下文的根节点
  • 产品决定报价项主体
  • 联系人通常依赖客户
  • 其他字段很多时候不是阻断项

5.5 建议把"first_ambiguous"升级成策略函数

不要只把它理解成"返回第一个歧义项"。

更准确的设计应该是:

python 复制代码
get_next_resolution_target(bundle, current_draft, business_context)

它的职责是:

  • 从多个 ambiguous / failed 中选出当前应优先处理的目标
  • 依据业务优先级和依赖关系做决策

5.6 设计建议

建议 1:优先级策略由代码实现,不交给 LLM

因为这是业务流程控制,不是开放式推理。

建议 2:优先级策略要可配置

可以做成:

python 复制代码
PRIORITY_ORDER = ["customer", "product", "contact"]

建议 3:后续可以升级成规则引擎

比如:

  • 如果 contact 依赖 customer 未确认,则 contact 自动降级
  • 如果 product 依赖 pricebook,而 pricebook 依赖 customer,则 customer 必须先确认

5.7 一句话总结

澄清优先级设计策略的本质,是在多个待澄清项中,决定"下一轮只问哪一个最关键的问题"。


6. 用户澄清输入的典型形式

用户在澄清时通常不会总是说标准表达。常见输入可以分成四类:


6.1 序号类

  • 1
  • 2
  • 第一个
  • 第1个
  • 选第二个
  • 我选第一个

适合规则解析。


6.2 完整名称类

  • 华通科技有限公司
  • 标准服务包-高级版

适合规则解析。


6.3 部分名称类

  • 华通科技
  • 高级版

适合规则 + 子串 / 弱匹配。


6.4 模糊表达类

  • 科技那个
  • 不是信息那个
  • 我要第一个公司
  • 不是第二个
  • 上面做软件的那个

这类适合 LLM 兜底解析。


7. 用户澄清解析策略:规则优先 + LLM 兜底

这是推荐的总体方案:


7.1 第一层:规则解析

优先解析明确表达:

序号

  • 1
  • 第一个
  • 第1个

精确名称

  • 完整命中候选名称

唯一子串

  • 候选中只有一个包含该子串

规则优点:

  • 稳定
  • 可审计
  • 成本低

7.2 第二层:LLM 兜底解析

当规则无法判断时,再走 LLM。

适合:

  • 科技那个
  • 不是信息那个
  • 我要做软件的那家
  • 不是第二个,是前面那个

LLM 的职责不是自由猜测,而是:

在给定候选列表中,做受限选择。


7.3 第三层:仍然无法确定就 unresolved

如果规则和 LLM 都无法可靠判断,就返回 unresolved,并再次提示用户。

原则:

宁可 unresolved,也不要误选。


8. LLM 兜底提示词设计


8.1 LLM 兜底提示词的设计目标

这个提示词的任务不是开放生成,而是一个受限选择任务

  • 输入:用户澄清语句 + 候选列表
  • 输出:在候选列表中选一个,或者 unresolved

所以 prompt 必须强调:

  1. 只能从候选列表中选
  2. 不能编造新的候选
  3. 不确定时返回 unresolved
  4. 输出必须结构化

8.2 中文提示词模板(推荐版)

text 复制代码
你是一个"候选项澄清解析模块"。

任务:
根据用户的澄清语句,从给定候选列表中判断用户指的是哪一个候选项。

请严格遵守以下规则:
1. 只能从候选列表中选择;
2. 不能编造新的候选项;
3. 如果无法可靠判断,必须返回 unresolved;
4. 不要凭空推断用户意图;
5. 输出必须是合法 JSON,且不能输出额外解释。

输出格式:
{
  "status": "confirmed | unresolved",
  "selected_id": "候选ID或null",
  "reason": "简短原因"
}

候选列表:
{{candidates}}

用户澄清语句:
{{user_input}}

8.3 更保守版提示词(推荐生产默认)

如果你想让系统更稳,可以用更保守的版本:

text 复制代码
你是一个"候选项澄清解析模块"。

你只能做以下两件事之一:
1. 从候选列表中明确选择一个候选项;
2. 返回 unresolved。

请严格遵守:
1. 只能使用候选列表和用户澄清语句中的信息;
2. 禁止根据常识扩展、脑补或猜测;
3. 如果用户表达不够明确,必须返回 unresolved;
4. 如果多个候选都可能符合,必须返回 unresolved;
5. 只返回 JSON,不要输出任何额外说明。

输出格式:
{
  "status": "confirmed | unresolved",
  "selected_id": "候选ID或null",
  "reason": "简短原因"
}

候选列表:
{{candidates}}

用户澄清语句:
{{user_input}}

8.4 示例

候选列表:

json 复制代码
[
  {"id": "cust_001", "name": "华通科技有限公司"},
  {"id": "cust_002", "name": "华通信息技术有限公司"}
]

用户说:

不是信息那个

期望输出:

json 复制代码
{
  "status": "confirmed",
  "selected_id": "cust_001",
  "reason": "用户排除了信息公司,因此选择科技公司"
}

如果用户说:

就那个吧

期望输出:

json 复制代码
{
  "status": "unresolved",
  "selected_id": null,
  "reason": "用户表达过于模糊,无法确定具体候选"
}

8.5 实现建议

LLM 兜底模块建议单独封装成:

python 复制代码
resolve_pending_choice_by_llm(user_input, candidates)

这样好处是:

  • 易于替换模型
  • 易于监控命中率
  • 易于统计哪些场景规则没覆盖
  • 后续容易持续优化

9. 用户澄清实现要点


9.1 保留 raw value 和 resolved value

例如:

json 复制代码
{
  "customer": {
    "raw_name": "华通",
    "resolved_id": "cust_001",
    "resolved_name": "华通科技有限公司",
    "resolution_status": "confirmed"
  }
}

这样便于:

  • 审计
  • 调试
  • 回显
  • 复盘错误

9.2 一次只澄清一个问题

这是最重要的交互原则之一。


9.3 高置信命中自动通过

不要让系统显得太"笨"。


9.4 候选数量要控制

一般建议:

  • 2~5 个
  • 超过这个数量,应该优化召回/重排,而不是让用户承担负担

9.5 记录解析来源

建议在结果中保留:

json 复制代码
"source": "rule:index"

或:

json 复制代码
"source": "llm"

这样便于:

  • 监控
  • 调优
  • 审计
  • 回放问题

9.6 澄清成功后必须清理 pending_resolution

否则下一轮会误判。


9.7 澄清完成后要回到主业务流程

也就是:

  • 写回 draft
  • 重新 validate
  • 继续输出摘要 / 等待确认

10. 常见坑


坑 1:把所有澄清都交给 LLM

问题:

  • 成本高
  • 延迟高
  • 不可控
  • 难审计

坑 2:没有 pending_resolution

问题:

  • 下一轮 1 不知道在选什么
  • 系统状态混乱

坑 3:一次问多个歧义问题

问题:

  • 用户负担大
  • 回复难解析
  • 流程变脆

坑 4:规则和 LLM 都无法判断时仍然强选

问题:

  • 这是业务系统里的高风险错误

坑 5:不区分 ambiguous 和 failed

问题:

  • 有候选和没候选,本质上是两种不同交互

坑 6:不保留 raw value

问题:

  • 后续很难解释"为什么系统匹配成这个实体"

11. 推荐模块划分

建议分成四层:


11.1 Resolver Tools

负责主数据匹配。

11.2 ResolutionService

负责:

  • 汇总匹配结果
  • 判断 confirmed / ambiguous / failed
  • 应用澄清优先级策略
  • 处理 pending_resolution
  • 调用规则或 LLM 完成候选确认

11.3 SessionStore

负责:

  • active_draft_id
  • pending_resolution

11.4 ChatOrchestrator

负责:

  • 判断当前是在正常业务流程还是澄清流程
  • 调用 ResolutionService
  • 把确认结果写回草稿
  • 恢复主流程

12. 一句话总结

用户澄清的核心设计,是在主数据匹配不够确定时,通过"澄清优先级设计策略"选出当前最关键的待确认实体,用 pending_resolution 保存上下文,并通过"规则优先 + LLM 兜底"的方式解析用户回复,在确认后把标准化结果写回草稿,再继续主业务流程。


13. 极简落地 checklist

如果你要快速落地,最少做到这 8 条:

  1. 匹配结果区分 confirmed / ambiguous / failed
  2. session 中保存 pending_resolution
  3. 一次只澄清一个实体
  4. 明确实现 澄清优先级设计策略
  5. 用户澄清解析采用 规则优先
  6. 规则失败后采用 LLM 兜底提示词
  7. 无法确定时返回 unresolved
  8. 成功确认后写回 draft,并清理 pending 状态
相关推荐
Sailing4 小时前
🚀🚀CLI 为什么在 2025 年突然复兴?看懂 Agent、Skill、MCP、CLI 四层架构
前端·agent·ai编程
louisliao_19814 小时前
Agent 项目常用 Prompt(中文版)模板
prompt·agent
小曾不摆烂4 小时前
Agent经典论文——ReAct框架
人工智能·自然语言处理·大语言模型·agent
今天你TLE了吗4 小时前
HelloAgents学习:PartⅠChapterⅠ初识智能体
人工智能·笔记·学习·agent·智能体
老唐7774 小时前
30分钟手搓 Agent:LLM + Tools + Loop + Memory 跑通最小闭环
人工智能·ai·语言模型·agent·llama·智能体
lihaozecq5 小时前
我用 1 个月写了一个 Web AI Coding Agent,今天开源 —— code-artisan
前端·agent·ai编程
ToTensor6 小时前
Mem0 深度解析:智能记忆层的架构原理
人工智能·agent·memory
龙侠九重天6 小时前
什么是多 Agent 系统?——从单体 AI 到群体智能
人工智能·ai·大模型·llm·agent·多智能体·multi-agent
Jangchengyu17 小时前
Agent Python学习篇:多线程——让你的AI助手不再“排队等号”
agent