Q1:Agent 意图识别输出什么?结构化输出协议怎么设计?
🎯 面试话术
Agent 意图识别不只输出一个意图标签,更完整的输出是一套结构化协议。简单来说就是除了意图标签,还要输出子任务列表、独立意图、已抽取的参数槽位、缺失的参数,以及硬约束和软约束。另外还有两类证据字段------已验证事实和暂定证据,用来区分用户当前轮明确说的和历史画像推断出来的。
其中 hard_constraints 是必须满足的约束如 「不超过 100 块」 ,soft_constraints 是努力满足但不强制的偏好如 「最好是牛仔裤」,两者要贯穿一轮对话的全过程。missing_slots 字段记录缺失参数触发澄清追问。
识别不出来有两个出口:unsupported 表示意图不在候选范围内需要拒识,unclear 表示意图混淆或参数不够需要澄清。拒识和澄清的关键是区分误拒和漏拒------误拒是用户意图在范围内但被拒了,漏拒是不在范围内但硬猜了。
多意图场景要先区分过程性描述和真多意图------过程性描述中多个动作是同一任务的不同步骤,真多意图才需要用 independent_intents 并行处理。Prompt 写法的核心是让模型在受控的业务意图空间里完成分类和结构化输出,意图特别多时用层次意图或检索先缩小候选集合。
评估不要只看 Top1 准确率------还要看 TopK Recall、分类别准确率、拒识准确率、澄清收敛率和槽位准确率,其中约束识别准确率是当下 Agent 做得最差的一块。
📖 详细讲解

Agent 意图识别不只输出一个 intent 标签,更完整的输出是一套结构化输出协议。比如用户说「我要买一条不超过 200 块的裤子,最好是牛仔裤」,应该输出:
json
{
"intent": "product_recommendation",
"sub_tasks": ["search_products"],
"independent_intents": [],
"slots": {
"category": "服装",
"subcategory": "裤子"
},
"missing_slots": ["size", "color"],
"hard_constraints": {"budget_max": 200},
"soft_constraints": {"preferred_material": "denim"},
"verified_evidence": [
{"source": "current_turn", "content": "不超过200块", "field": "budget_max"}
],
"provisional_evidence": [
{"source": "user_profile", "content": "历史偏好:牛仔裤", "field": "preferred_material"}
]
}
结构化输出协议各字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
| intent | string | 主意图标签,从候选意图集合中选取 |
| sub_tasks | list | 主意图下的子任务序列(过程性描述时用) |
| independent_intents | list | 真多意图场景下,互相独立的并行意图 |
| slots | dict | 已抽取到的参数值 |
| missing_slots | list | 缺失的必填参数,触发澄清追问 |
| hard_constraints | dict | 必须满足的约束(如预算上限、日期限制),模型无论如何不能违反 |
| soft_constraints | dict | 努力满足但不强制的偏好(如材质偏好、颜色偏好),不满足时降级而非拒绝 |
| verified_evidence | list | 当前对话中用户明确说过或工具确认的事实,可作为硬约束来源 |
| provisional_evidence | list | 从历史画像、历史对话推断的信息,不能自动升级为硬约束 |
Slot Filling 的核心要点:
- 定义清楚每个意图需要哪些参数------如商品推荐需要 category、budget_max、usage_scenario 等
- 区分硬约束和软偏好 ------hard_constraints 是模型无论如何必须满足的,soft_constraints 是「努力满足但不强制」。约束要贯穿一轮对话的整个过程------即使用户中途补充了新条件,也要更新而非覆盖之前的约束
- missing_slots 字段------记录缺失参数,触发澄清追问
- 多轮 Slot 补全------在 ReAct/Think-Action-Observation 循环中逐步补全所有槽位,确保 missing_slots 为空
拒识与澄清机制------什么时候追问、什么时候降级、误拒 vs 漏拒:
| 出口 | 含义 | 处理方式 |
|---|---|---|
| unsupported | 用户意图不在候选意图中 | 拒识------超出系统能力范围,礼貌告知用户能力边界 |
| unclear | 意图混淆(候选间距过小)或参数不够(missing_slots 非空) | 澄清------追问缺失信息或让用户在候选意图间选择 |
拒识和澄清的关键是区分两类错误:
| 错误类型 | 定义 | 危害 | 优化方向 |
|---|---|---|---|
| 误拒(False Reject) | 用户意图在系统范围内,但被错误地判为 unsupported | 用户觉得「这也不行那也不行」,体验极差 | 放宽拒识阈值,增加 fallback 意图 |
| 漏拒(False Accept) | 用户意图不在范围内,但系统硬猜了一个意图去执行 | 执行了不该执行的操作,可能造成不可逆后果 | 收紧拒识阈值,增加硬约束校验 |
什么时候追问、什么时候降级:
- 追问:missing_slots 中有必填参数缺失,且该参数缺失会导致后续工具调用无法执行或执行结果严重偏差
- 降级:missing_slots 中的参数虽缺失,但有合理默认值或可以缩小搜索范围后给出泛化回答
- 原则:能降级解决的不追问------追问会打断用户流;但必填硬约束缺失必须追问------否则执行后大概率出错
多意图的处理策略------过程性描述 vs 真多意图:
| 类型 | 定义 | 例子 | 处理方式 |
|---|---|---|---|
| 过程性描述 | 多个动作是同一任务的不同步骤 | 「帮我查下订单顺便退一下」→ 查订单是为了确认要退哪个 | 识别为主意图「退款」,查订单作为 sub_tasks 自动执行 |
| 真多意图 | 多个意图互相独立,用户确实想并行处理 | 「帮我订个会议室,再帮我查下明天的天气」 | 输出 independent_intents,用 Plan 机制 分别处理 |
真多意图场景的 Plan 机制:将多个独立意图拆成子任务,可以并行执行(如「订会议室」和「查天气」无依赖关系)或串行执行(如「查完天气再根据天气决定是否提醒带伞」),并在输出中用 independent_intents 字段标识哪些是并行的。
Prompt 怎么写?
Agent 意图识别 Prompt 的核心是让模型在一个受控的业务意图空间里完成分类和结构化输出:
- 定义清楚候选意图 ------列出系统支持的所有意图及其边界描述,不允许模型自己发明意图
- 定义清楚意图边界------容易混淆的意图必须明确区分(如「推荐」vs「查询」vs「比较」)
- 定义清楚参数(Slot)------每个意图需要抽取哪些参数,是否必选,默认值
- 加入 few-shot ------关键是覆盖容易混淆的边界 ,正反两方面例子。进阶用动态 few-shot:每次从案例库检索最相似的案例注入
- 意图特别多怎么办 ------用层次意图 (先分大类再分小类)或检索先缩小候选集合(从几百个意图中召回 top-K 再分类)
一句话总结:Agent 意图识别不是为了给用户输入贴标签,而是为了决定 Agent 后面应该怎么想、加载什么上下文、调用什么工具、进入哪个业务流程。
Q2:什么是 slot-filling?它和 Agent 意图识别是什么关系?
🎯 面试话术
slot-filling 就是把用户输入里的关键信息填到预定义的结构化槽位里。它不是 Agent 意图识别的附属品,而是 Agent 意图识别的「下半场」------意图告诉你「用户想做什么」,slot 告诉你「这件事还需要哪些参数才能执行」。
举个例子,用户说「查一下上个月广州参保人的平均缴费」。意图是「业务指标查询」,slot 包括时间(上个月)、城市(广州)、指标(平均缴费)、业务域。这些槽位缺一个,SQL 都跑不出来。
slot 和 Agent 意图识别的结合方式是同一次结构化输出里同时完成:模型输出 intent 的同时,输出 slots、missing_slots、hard_constraints、soft_constraints。在实际落地中就是这样做的------先识别意图,再立刻检查必填槽位,缺失就触发澄清,而不是等到后面调工具时才报错。
设计 slot 有三个要点。第一,每个意图独立定义 slot ,不同意图的同名 slot 含义可能不同------「城市」在业务查询里是参保地,在物流查询里是收货地。第二,区分必填和选填 ,必填缺失必须澄清,选填缺失可以带默认值执行。第三,slot 要直接对应到工具参数,避免出现「模型抽到了城市名,但工具要的是行政区划 code」这种断层。
📖 详细讲解

slot-filling 的本质是把非结构化用户输入映射到预定义结构化参数。它是对话系统中经典的任务,在大模型时代变成了「Agent 意图识别 + 参数抽取」的一体化输出。
用户输入:查一下上个月广州参保人的平均缴费
│
▼
Agent 意图识别 ──→ intent = "业务指标查询"
│
▼
slot filling
├──→ slots: {time: "上个月", city: "广州", metric: "平均缴费", domain: "业务"}
├──→ missing_slots: []
├──→ hard_constraints: {domain: "业务"}
└──→ soft_constraints: {preferred_time_range: "最近一年"}
slot 定义的四个维度:
| 维度 | 说明 | 例子 |
|---|---|---|
| 名称 | slot 的字段名,通常直接映射到工具参数 | city、time_range、metric |
| 类型 | 字符串、数字、枚举、日期、布尔 | city: string,budget_max: number |
| 必填性 | 是否必须填,缺了能否执行 | 必填:city;选填:sort_by |
| 候选值 | 是否来自封闭集合,要不要做语义映射 | region=440105 对应「海珠区」 |
不同意图的 slot 可能同名但含义不同:
| 意图 | slot: city | 实际含义 |
|---|---|---|
| 业务查询 | city | 参保地/待遇领取地 |
| 物流查询 | city | 收货地 |
| 酒店预订 | city | 入住城市 |
所以 slot 不能脱离意图单独理解,必须在意图命名空间下定义。
slot 缺失的处理策略:
| 缺失类型 | 处理方式 | 例子 |
|---|---|---|
| 必填 slot 缺失 | 触发澄清,反问用户 | 「您想查询哪个城市的参保数据?」 |
| 选填 slot 缺失 | 使用默认值或合理推断 | 默认查最近一年 |
| 多个 slot 缺失 | 优先问影响最大的 | 先问城市,再问时间 |
| slot 值模糊 | 给出候选让用户确认 | 「您指的是广州市还是广州市白云区?」 |
slot 与约束的关系:
slot 是事实参数 ,约束是规则限制。比如:
- slot:
budget_max=200(用户说的) - hard_constraint:
budget_max <= 200(系统必须遵守) - soft_constraint:
preferred_material=denim(尽量满足)
在政务场景中,slot 是「广州、上个月、平均缴费」,hard_constraint 可能是「只能访问授权业务域」「禁止写操作」。slot 填完只是参数齐了,不代表约束一定满足。
如何避免 slot 不完整?
- Prompt 里明确列出每个意图的 slot 清单和必填性
- 输出 JSON Schema 强制校验,让模型必须输出 missing_slots 字段
- 多轮补全:在 Think-Action-Observation 循环中,每轮都检查 missing_slots,直到为空
- 默认值 + 澄清结合:能推断的slot用默认值,不能推断的必须澄清
一句话总结:slot-filling 不是 Agent 意图识别的后续步骤,而是同一套结构化输出协议的一部分------意图决定走哪条路,slot 决定这条路能不能走通。
Q3:Agent 意图识别怎么评估?有哪些指标?
🎯 面试话术
Agent 意图识别的评估不能只看 Top1 准确率,要覆盖四大维度:基础指标(Top1、TopK Recall)、分意图指标(分类别准确率,防止高频意图掩盖低频)、拒识/澄清指标(误拒率、漏拒率、澄清收敛率)、Slot 指标(槽位准确率、必填槽完整率、约束识别准确率)。其中约束识别准确率是当下 Agent 做得最差的一块------很多 Agent 把 hard 和 soft 混为一谈。
专属领域 Agent Top1 做到 99%+ 很正常,通用 Agent 在 80%-90% 之间比较真实。关键在于给解释--太高要说明是专属领域+意图少+用户输入规范;太低要说明正在优化。
📖 详细讲解

评估指标体系:
| 指标类别 | 具体指标 | 说明 |
|---|---|---|
| 基础指标 | Top1 Accuracy | 最常用------系统输出的第一个意图是否正确 |
| Top-K Recall | 前 K 个候选中有标准答案就算命中------反映系统的召回能力,即使 Top1 错了也能通过澄清救回 | |
| 分意图指标 | 分类别准确率 | 防止高频意图掩盖低频意图的识别差------Top1 做到 99% 不代表每个意图都 99% |
| 拒识/澄清指标 | 拒识准确率 | 拒掉的输入中,真正应该被拒的比例------防止误拒 |
| 误拒率(False Reject Rate) | 在范围内的意图被错误拒掉的比例 | |
| 漏拒率(False Accept Rate) | 不在范围内的意图被硬猜了的比例 | |
| 澄清触发准确率 | 触发澄清的 case 中,确实需要澄清的比例 | |
| 澄清后收敛率 | 澄清后用户补充信息、任务顺利推进的比例------反映澄清是否有效 | |
| Slot 指标 | 槽位准确率 | 抽取的参数值是否正确 |
| 槽位召回率 | 应抽取的参数中实际抽到了多少 | |
| 必填槽完整率 | missing_slots 是否最终清空 | |
| 约束识别准确率 | 硬约束和软偏好是否识别正确------这是当下 Agent 做得最差的一块,很多 Agent 把 hard 和 soft 混为一谈 |
面试中怎么说准确率:
- 专属领域 Agent :Top1 做到 99%+ 很正常------总共就几个意图,用户输入规范
- 通用 Agent :Top1 在 80%-90% 之间比较真实
- 关键在于给解释------太高要说明是专属领域+意图少+用户输入规范;太低要说明正在优化
- 不要只看准确率------拒识、澄清也是合理的策略,不是永远追求猜中
一句话总结:评估要覆盖四大维度(基础、分意图、拒识/澄清、Slot),不能只看 Top1 准确率。
Q4:Agent 意图识别的置信度是什么?阈值怎么设?
🎯 面试话术
模型输出的 confidence 本质上是 softmax 之后的相对排序分数,不是模型真的有 85% 把握。即使模型完全在猜,softmax 也会输出一个看似合理的分布,比如 0.85, 0.14------但这个 0.85 只是「比第二高多少」,不是绝对可信度。
所以阈值不能只看 confidence 一个数,要结合候选间距、规则校验、槽位完整性、硬约束风险 一起判。路由可以分三档:大于 0.85 直接接受,0.6 到 0.85 进入仲裁或澄清,小于 0.6 交给更强的深度推理模型。
📖 详细讲解

confidence 为什么不等于概率?
大模型输出 confidence 时经过 softmax:
logits = [2.0, 0.5, -1.0]
softmax → [0.79, 0.18, 0.04]
这个 0.79 只是相对排序结果,不代表模型有 79% 的把握。具体问题有三:
- 归一化假象:即使 logits 都很接近,softmax 也会拉开差距
- 过度自信:大模型在分布外(OOD)输入上 confidence 依然很高
- 间距丢失:0.85 可能是 0.85, 0.14(明显领先),也可能是 0.85, 0.84(几乎并列)
所以 confidence 只能当排序信号 ,不能当真实概率。
阈值设定的三个来源:
| 来源 | 做法 | 适用场景 |
|---|---|---|
| 测试集校准 | 在标注测试集上画 PR 曲线,找误拒和漏拒的平衡点 | 通用方法 |
| 业务风险 | 高副作用意图(退款、删除)收紧阈值,低副作用放宽 | 资金/写操作 |
| 候选间距 | top1 与 top2 差距过小,即使 confidence 高也进澄清 | 边界模糊 |
路由决策表:
| confidence | 候选间距 | 槽位完整 | 决策 |
|---|---|---|---|
| > 0.85 | 大 | 完整 | 直接执行 |
| > 0.85 | 小 | 完整 | 仲裁/低置信澄清 |
| 0.6-0.85 | - | 不完整 | 澄清补 slot |
| < 0.6 | - | - | 交给深度模型或 fallback |
一句话总结:confidence 是 softmax 后的相对排序而非真实概率;阈值要结合候选间距、规则校验和槽位完整性分档设定。