技术博客
易源合一 3054-2 与 3054-1 的搭配方式:先判意图,再决定要不要发起对话

易源合一 3054-2 与 3054-1 的搭配方式:先判意图,再决定要不要发起对话

作者: 万维易源
2026-09-15
易源合一两段式调用意图预判成本核算架构
# 易源合一 3054-2 与 3054-1 的搭配方式:先判意图,再决定要不要发起对话 > 接入点:3054-2 意图分析 + 3054-1 智能对话 | 请求方式:POST | 返回格式:JSON | 计费:各 5.5 厘/次,失败不扣费 | 最后实测核对:2026-09-15 ## 核心要点 - 两段式调用(先 3054-2 判意图,再决定要不要调 3054-1)**不会省钱**,实测每次最多多花 5.5 厘。 - 它买的是「决策前置」:拿到 `intent` 和 `confidence` 之后再决定走业务分支、走二次追问,还是直接兜底。 - 实测有一个必须两段式才能处理的场景:`traffic_control` 意图在 3054-2 能稳定识别,但 3054-1 稳定不接通。 ## 先把它当成两个不同的东西 3054-1 智能对话是端到端的,一句话进去,答复和原始数据一起出来,但它不告诉你置信度,失败也只给一句含糊的话。 3054-2 意图分析只做分类,返回意图编码、中文解释、抽取到的参数、以及置信度。它不执行任何业务。 给客服机器人加个查询能力时,你大概率会遇到这几个决策点:这句话该不该走业务链路?置信度这么低要不要追问?这个意图我根本没做,是回「暂不支持」还是回「没听懂」? 3054-1 一个人答不上来这些问题,3054-2 就是补上这块的。 ## 两段式不省钱,别拿它当成本优化 先把账算清楚,免得按错的理由选方案。 | 路径 | 成功且有用 | 失败或答非所问 | |------|-----------|--------------| | 只调 3054-1 | 5.5 厘 | 失败不扣费(0) | | 先 3054-2 再 3054-1 | 11 厘 | 5.5 厘(意图分析成功,对话这一步失败不扣费) | 3054-1 失败本来就不扣费,所以两段式的成本**只会更高**,不会更低。最高一次多花 5.5 厘。 真正需要两段式的是下面三种情况,都跟省钱无关。 **情况一:你要在调 3054-1 之前就做 UI 决策。** 置信度低的时候你想先反问一句「你是想问昆明的天气吗」,这个反问不该调 3054-1,因为 3054-1 不返回置信度。 **情况二:你要给不同意图配不同的超时和降级。** 天气 3 秒超时可以接受,快递要查物流你可能给到 8 秒。前置分流比拿到结果后再判断更直接。 **情况三:你要区分「没听懂」和「没做这个功能」。** 这两种情况的用户提示语完全不同,下一节展开。 ## 实测反例:意图能识别,不等于对话能执行 这是本次实测中最值得记下来的一条。 同一句话「北京限行尾号是多少」,两个接入点的表现分叉: | 接入点 | 重复次数 | 结果 | |--------|---------|------| | 3054-2 意图分析 | 6 次 | 6/6 命中 `traffic_control`(车牌限行),`confidence` 在 90 / 95 / 98 之间波动 | | 3054-1 智能对话 | 6 次 | 6/6 返回 `ret_code: -1`,`ret_msg` 为 `抱歉,您的问题我还没有学会,请等待我的更新和完善1` | 意图分析说「我认得这是限行问题,98 分」,智能对话说「我还没学会」。两条信息同时成立。 这对产品的影响很直接。只调 3054-1 的话,你的代码无法区分「用户表达得太模糊」和「这个能力平台还没接」。两段式就能分开处理,前者提示用户换个说法,后者提示「该功能暂未开通」。 另一种必须两段式兜住的场景是短句。对「你好」重复调用 6 次,3054-1 实测拿到 4 种结果:2 次命中 `joke`、1 次命中 `query_news`、2 次 `ret_code: -1` + `must input content field`、1 次 `调用失败:推理失败3`。同一时段 3054-2 对「你好」也给不出稳定答案,6 次分别命中 `joke`(65)、`draw`(55)、`text_summarize`(65)、`joke`(52)、`text_summarize`(52)、`joke`(50)。 低信息量的输入,两个接入点都不稳。差别在于 3054-2 会明确告诉你「我只给了 55 分」,而 3054-1 会直接给你一个笑话。 ## 落地写法 先定义你自己的业务分流表,把「支持的意图」「不支持的意图」「需要追问的区间」三档分开。 ```python import requests APP_KEY = "YOUR_APPKEY" SUPPORTED = {"weather", "query_express", "query_news"} # 你真正做了业务逻辑的意图 CONF_THRESHOLD = 80 # 阈值自己按语料定,实测明确语句在 92 以上 def detect(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: return None, None, body.get("ret_msg") return body.get("intent"), body.get("confidence"), None def reply(text, timeout=20): intent, conf, err = detect(text) if intent is None: return {"action": "fallback", "say": "没太理解你的意思,可以换个说法吗"} if intent not in SUPPORTED: return {"action": "unsupported", "say": f"这个能力暂未开通(识别到意图:{intent})"} if conf is not None and conf < CONF_THRESHOLD: return {"action": "clarify", "say": "你是想问这个吗?", "intent": intent, "confidence": conf} # 到这里才真花钱调 3054-1 r = requests.post(f"https://route.showapi.com/3054-1?appKey={APP_KEY}", data={"text": text}, timeout=timeout) data = r.json() body = data.get("showapi_res_body", {}) if body.get("ret_code") != 0: return {"action": "fail", "say": body.get("ret_msg"), "billed": data.get("showapi_fee_num", 0)} return {"action": "ok", "say": body.get("reply_msg", {}).get("text", ""), "raw": body.get("result")} print(reply("北京限行尾号是多少")) print(reply("帮我查快递 7788990011223")) ``` ```javascript const APP_KEY = "YOUR_APPKEY"; const SUPPORTED = new Set(["weather", "query_express", "query_news"]); const CONF_THRESHOLD = 80; const post = (point, text) => fetch(`https://route.showapi.com/${point}?appKey=${APP_KEY}`, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ text }), }).then((r) => r.json()); async function reply(text) { const d2 = await post("3054-2", text); const b2 = d2.showapi_res_body || {}; if (b2.ret_code !== 0) return { action: "fallback" }; if (!SUPPORTED.has(b2.intent)) return { action: "unsupported", intent: b2.intent }; if (b2.confidence < CONF_THRESHOLD) return { action: "clarify", intent: b2.intent, confidence: b2.confidence }; const d1 = await post("3054-1", text); const b1 = d1.showapi_res_body || {}; if (b1.ret_code !== 0) return { action: "fail", reason: b1.ret_msg }; return { action: "ok", text: b1.reply_msg.text }; } ``` 注意两段式的请求数翻倍。接口并发限制是 10 次/秒,如果你的入口 QPS 本来就接近这个量级,把 3054-2 的判定结果按用户会话缓存一段时间。同一用户重复问同一句话的概率不低。 ## FAQ **Q1:只调 3054-1 行不行?** 行,前提是你不关心置信度、也不需要在调之前分流。如果「没听懂」和「功能没做」对你是同一句提示语,3054-1 单独用就够。 **Q2:两段式会增加多少延迟?** 实测 3054-2 单次 0.70~1.62 秒,3054-1 单次 0.65~2.32 秒。两段式是串行叠加,最坏情况下总延迟接近 4 秒。对延迟敏感的场景,可以考虑把 3054-2 的结果缓存,或者只对低置信度的输入才走 3054-1。 **Q3:能不能只用 3054-2 当分类器?** 可以。如果你只需要知道「用户这句话属于哪个业务域」,3054-2 单独用就完成了任务,不需要再调 3054-1 拿答复。这时候单次成本就是 5.5 厘。 **Q4:3054-2 判出来的意图,3054-1 一定支持吗?** 不一定。实测反例:`traffic_control` 在 3054-2 稳定识别(6/6,置信度 90~98),在 3054-1 稳定返回 `ret_code: -1`。两边的能力集合不保证一致,上生产前请对你要用的每个意图各跑一遍 3054-1 验证。 **Q5:两个接入点可以用不同的请求方式吗?** 3054-2 的文档标注支持 POST/GET,3054-1 和 3054-3 只标了 POST。混用容易在排查问题时多一个变量,建议统一 POST。 ## 下一步阅读 - [易源合一实测能识别哪些意图:8 类 intent 编码逐一验证](https://www.showapi.com/guides/united-api-intent-list-3054) - [易源合一只返回 55 分置信度时:阈值设定、兜底路径与二次追问](https://www.showapi.com/guides/united-api-low-confidence-3054) - [易源合一在对话式应用里的位置:意图层与执行层的切分方案](https://www.showapi.com/guides/united-api-dialog-architecture-3054) - **本系列共 12 篇**:查看[易源合一指南总目录](https://www.showapi.com/guides/united-api-guides-3054)