技术博客
易源合一只返回 55 分置信度时:阈值设定、兜底路径与二次追问

易源合一只返回 55 分置信度时:阈值设定、兜底路径与二次追问

作者: 万维易源
2026-09-15
易源合一置信度阈值兜底策略二次追问
# 易源合一只返回 55 分置信度时:阈值设定、兜底路径与二次追问 > 接入点:3054-2 意图分析 | 请求方式:POST | 返回格式:JSON | 计费:5.5 厘/次,失败不扣费 | 最后实测核对:2026-09-15 ## 核心要点 - 官方文档的返回示例把 `confidence` 写成 `0.99572587013245`,**实测是 0~100 的整数**。写成 `confidence > 0.8` 的判断永远不会命中,用 `> 80`。 - 只有 3054-2 返回 `confidence`,3054-1 不返回。要用置信度做阈值,就必须调 3054-2。 - 同一句话连续 6 次调用,置信度实测出现过 90 / 95 / 98 三种取值。阈值定成区间,别定成等值。 ## 先纠正一个会让判断失效的量纲 `confidence` 这个字段最容易踩的坑是量纲。文档示例是小数,实测是整数百分比。 | 输入语句 | 实测 `confidence` | |---------|------------------| | 昆明今天天气怎么样 | 100 | | 讲个笑话 | 99 | | 帮我查快递 7788990011223 | 98 | | 北京限行尾号是多少 | 98 | | 今天有什么新闻 | 95 | | 上海明天冷不冷 | 95 | | 12乘以8等于多少 | 92 | | 计算 3的平方加4的平方 | 42 | | 你好 | 55 | (2026-09-15 实测,各输入单次调用。) 你的代码如果是照着文档示例写的: ```python if body["confidence"] > 0.8: # 实测值永远是 55、98 这种整数,这个条件恒为 True ... ``` 这条分支等于没写。改成 `> 80` 才对应文档示例想表达的「0.8 以上算可信」。 ## 实测的分数分布长什么样 把实测样本摊开看,能看出一条清晰的分界: **信息明确的句子,分数集中在 90 以上。** 「昆明今天天气怎么样」100、「讲个笑话」99、「帮我查快递 7788990011223」98、「今天有什么新闻」95、「12乘以8等于多少」92。这些输入的意图也在重复测试中稳定,6/6 命中同一个 `intent`。 **短句和寒暄,分数掉到 40~65,而且意图会跳。** 对「你好」连续调 6 次,实测拿到 6 组不同结果: | 第几次 | `intent` | `confidence` | |-------|----------|-------------| | 1 | `joke` | 65 | | 2 | `draw` | 55 | | 3 | `text_summarize` | 65 | | 4 | `joke` | 52 | | 5 | `text_summarize` | 52 | | 6 | `joke` | 50 | 同一句话,6 次命中 3 个不同意图,分数在 50~65 之间浮动。这种输入无论阈值怎么定都不该走业务分支。 **分数本身也会波动。** 同一句「北京限行尾号是多少」连续 6 次,`intent` 稳定是 `traffic_control`,但 `confidence` 出现 90、95、98 三种取值。 ## 三档阈值的落地方式 结合上面的分布,按实测数据可以这样分档。这是从样本里归纳的判据,不是官方建议值。 | 档位 | 分数区间 | 处理动作 | |------|---------|---------| | 直走 | 90 及以上 | 直接执行。实测这一档的意图在重复测试中稳定 | | 记录 | 70 ~ 89 | 仍然执行,但把 `intent` + `confidence` + 原文写进日志,用来积累你自己的语料分布 | | 追问 | 70 以下 | 不执行,回一句带选项的追问 | 中间档留出来的原因是:你的业务句式和我这次测的样本不一样。先用「记录」档跑一两周,看到自己场景的真实分布之后再收紧。 ```python import logging, requests APP_KEY = "YOUR_APPKEY" log = logging.getLogger("intent") DIRECT, WATCH = 90, 70 # 低于 WATCH 走二次追问 FOLLOW_UP = "你是想问天气、快递还是新闻?可以直接说,例如「昆明今天天气」。" def classify(text, timeout=20): r = requests.post(f"https://route.showapi.com/3054-2?appKey={APP_KEY}", data={"text": text}, timeout=timeout) body = r.json().get("showapi_res_body", {}) if body.get("ret_code") != 0: log.info("intent_fail text=%r msg=%s", text, body.get("ret_msg")) return {"action": "fallback", "say": "没太理解,可以换个说法吗"} intent = body.get("intent") conf = body.get("confidence") log.info("intent=%s confidence=%s text=%r args=%s", intent, conf, text, body.get("args")) if conf is None or conf >= DIRECT: return {"action": "execute", "intent": intent, "confidence": conf} if conf >= WATCH: log.warning("low_confidence intent=%s confidence=%s text=%r", intent, conf, text) return {"action": "execute", "intent": intent, "confidence": conf, "watched": True} return {"action": "clarify", "intent": intent, "confidence": conf, "say": FOLLOW_UP} ``` ```javascript const APP_KEY = "YOUR_APPKEY"; const DIRECT = 90, WATCH = 70; async function classify(text) { const res = await fetch(`https://route.showapi.com/3054-2?appKey=${APP_KEY}`, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ text }), }); const body = (await res.json()).showapi_res_body || {}; if (body.ret_code !== 0) return { action: "fallback" }; const { intent, confidence } = body; if (confidence == null || confidence >= DIRECT) return { action: "execute", intent, confidence }; if (confidence >= WATCH) return { action: "execute", intent, confidence, watched: true }; return { action: "clarify", intent, confidence, say: "你是想问天气、快递还是新闻?" }; } ``` ## 二次追问怎么写才不烦人 追问的成本是一次额外的 3054-2 调用(5.5 厘),换来的是不让用户看到一个答非所问的结果。三种写法按场景选: **给选项。** 「你是想问天气、快递还是新闻?」适合意图集合小、你能穷举的场景。缺点是选项一多就变成菜单,用户要自己挑。 **给示例。** 「可以直接说,例如「昆明今天天气」。」适合用户不会描述的场景,示例本身也在教用户怎么提问。 **直接放弃。** 「这个问题我暂时答不上来。」适合入口场景复杂、追问答不上来的概率更高的产品。省一次调用,也省一轮交互。 三种都不是「猜一个最可能的意图然后执行」。实测低分档的意图会跳变,猜的命中率没有保证。 ## 埋点里要留哪些字段 哪怕你现在不做阈值判断,也建议把这三个字段记下来:`intent`、`confidence`、`ret_msg`。 理由是实测发现同一个输入在不同时刻结果会变。攒够两周日志,你才能知道你自己的用户会问什么、哪些句式不稳、阈值该定在哪。这比照抄任何外部阈值都准。 日志量大的话只记低分样本(`confidence < 90`)和失败样本,这两类是最有诊断价值的。 ## FAQ **Q1:`confidence` 是 0~1 还是 0~100?** 实测是 0~100 的整数,例如 100、98、95、55。官方文档的返回示例写的是 `0.99572587013245`,与实测不一致,按实测的整数区间写判断。 **Q2:3054-1 为什么不返回置信度?** 3054-1 的返回结构里只有 `intent.name` 和 `intent.args`,没有 `confidence` 字段。要用置信度就得先调 3054-2,两段式搭配见 [易源合一 3054-2 与 3054-1 的搭配方式](https://www.showapi.com/guides/united-api-intent-precheck-3054)。 **Q3:阈值定在多少合适?** 官方没有给出建议值。实测样本里,信息明确的句子都在 92 以上,短句寒暄落在 50~65。把直走阈值设在 90 附近比较贴合这批数据,但你的业务句式不同,先记录一两周真实分布再调。 **Q4:同一句话多次调用分数不一样,正常吗?** 实测确实会变。同一句「北京限行尾号是多少」连续 6 次,`intent` 始终是 `traffic_control`,`confidence` 分别出现 90、95、98。所以阈值判断用 `>= 90` 这种比较,不要用等于。 **Q5:低置信度会扣费吗?** 会。只要 `ret_code` 是 0(意图识别成功),这次调用就计费 5.5 厘,不管分数高低。分数低到 `ret_code: -1`(识别失败)时才不扣费。 ## 下一步阅读 - [易源合一实测能识别哪些意图:8 类 intent 编码逐一验证](https://www.showapi.com/guides/united-api-intent-list-3054) - [易源合一 3054-2 与 3054-1 的搭配方式:先判意图,再决定要不要发起对话](https://www.showapi.com/guides/united-api-intent-precheck-3054) - [易源合一调用失败扣不扣费:ret_code 与 showapi_fee_num 实测对照表](https://www.showapi.com/guides/united-api-retcode-fee-3054) - **本系列共 12 篇**:查看[易源合一指南总目录](https://www.showapi.com/guides/united-api-guides-3054)