技术博客
易源合一在对话式应用里的位置:意图层与执行层的切分方案

易源合一在对话式应用里的位置:意图层与执行层的切分方案

作者: 万维易源
2026-09-15
易源合一对话架构意图层会话状态延迟预算
# 易源合一在对话式应用里的位置:意图层与执行层的切分方案 > 接入点:3054-2 / 3054-1 / 3054-3 | 请求方式:POST | 返回格式:JSON(3054-3 为 SSE 分块) | 计费:各 5.5 厘/次,失败不扣费 | 最后实测核对:2026-09-15 ## 核心要点 - 易源合一是**单句无状态**的,请求参数只有 `text` 和 `args_list`,没有会话 ID、没有上下文参数。多轮对话的状态必须你自己维护。 - 三种放置方式:意图层前置(3054-2 先分流)、执行层直连(3054-1 一把梭)、流式直连终端(3054-3 推到前端)。 - 实测延迟预算:3054-2 单次 0.70~1.62 秒,3054-1 单次 0.65~2.32 秒,两者串联最坏接近 4 秒。 ## 先确定一件事:它不知道你们聊过什么 翻一遍 3054 三个接入点的请求参数,只有 `text` 和 `args_list`(图片用)。没有 `session_id`,没有 `history`,没有 `context`。 意味着这段对话: ``` 用户:昆明天气怎么样 机器人:昆明今天 24℃,多云 用户:那明天呢 ``` 第二句里的「那明天呢」如果直接丢给接口,`weather` 意图能识别出来,但 `args.area` 大概是抽不到的,因为「昆明」在上一条消息里。 要在多轮场景里用好它,你必须在自己的会话存储里维护最近提到的实体(城市名、快递单号),在调接口之前把它们拼回 `text`。比如把「那明天呢」重写成「昆明明天天气怎么样」再发出去。 这是架构上第一个必须先定的点。 ## 三种放置方式 **方式 A:意图层前置。** 3054-2 先判意图和置信度,你的业务层按意图分派,需要平台数据的才调 3054-1,答复由你自己拼。 ``` 用户消息 → [3054-2 意图分析] → 置信度分档 ├─ 低分 → 二次追问(不调 3054-1) ├─ 不支持的意图 → 兜底话术 └─ 高分且支持 → [3054-1 智能对话] → 你的回复层 ``` 适合:你已经有自己的业务系统,只想把「自然语言 → 结构化参数」这一步外包出去。你拿到 `args` 里的 `area`、`express_nu` 之后,可以塞进自己的查询链路。 **方式 B:执行层直连。** 用户消息直接发 3054-1,拿 `reply_msg.text` 展示。 ``` 用户消息 → [3054-1 智能对话] → reply_msg.text → 展示 ``` 适合:答案由平台生成就够用,你不想管业务分支。少一层调用,少 5.5 厘,但拿不到置信度,也分不清「没听懂」和「功能没做」。 **方式 C:流式直连终端。** 3054-3 走 SSE,分块推到前端。 ``` 用户消息 → [3054-3 流式] → SSE 分块 → 前端逐块渲染 ``` 适合:前端要边收边渲染,或者后面接了 TTS 需要尽早开口。要注意 3054-3 是透传模式,没有 `showapi_res_body` 外层封装,也没有计费字段。 ## 实测延迟预算 做架构决策前先知道每层大概要多久。2026-09-15 的实测数据: | 环节 | 实测区间 | 样本 | |------|---------|------| | 3054-2 意图分析 | 0.70 ~ 1.62 秒 | 9 次调用 | | 3054-1 智能对话(天气) | 1.62 秒 | 单次 | | 3054-1 智能对话(快递) | 2.31 秒 | 单次,需要串多家快递数据源 | | 3054-1 智能对话(新闻) | 1.89 秒 | 单次 | | 3054-1 失败返回 | 0.65 ~ 1.24 秒 | 2 次 | | 3054-3 流式(全程) | 1.58 秒 | 单次 | 方式 A 的延迟是两段相加,最坏能到 4 秒左右,对在线客服的体验偏慢。两个可行的缓解手段:把 3054-2 的结果按会话 + 消息内容缓存一段时间;或者只用 3054-2 处理低置信度分支,高分输入直接走 3054-1。 方式 B 的延迟就是单次 3054-1 的时间,1~2.3 秒,可接受。 ## 回复层的两个设计决定 **谁负责措辞。** 平台的 `reply_msg.text` 已经写好了话,直接展示最省事,但语气、称呼、是否加表情你控制不了。要品牌一致就别用它的文案,只取 `intent` 和 `result` 自己拼。 **`result` 要不要透给前端。** 天气的 `result` 带 `dayList` 逐日数据,够你画一个卡片;新闻的 `result` 带 20 条 `contentlist`,够你出列表。要自己画 UI 就走"取 `result` 自渲染"的路子,别让前端解析 `reply_msg.text` 里的 Markdown。 ## 一份分层实现 ```python import json, time, requests APP_KEY = "YOUR_APPKEY" SUPPORTED = {"weather", "query_express", "query_news"} class Session: """接口本身无状态,会话上下文自己在内存里维护。生产环境换成 Redis。""" def __init__(self): self.last_entities = {} def rewrite(self, text): """把「那明天呢」补全成「昆明明天天气怎么样」""" if self.last_entities.get("area") and ("呢" in text or "明天" in text or "后天" in text): return f"{self.last_entities['area']}{text}", True return text, False def absorb(self, args): for k in ("area", "express_nu"): if args.get(k): self.last_entities[k] = args[k] sessions = {} def handle(session_id, user_text, timeout=20): s = sessions.setdefault(session_id, Session()) text, rewritten = s.rewrite(user_text) t0 = time.time() # 意图层 r2 = requests.post(f"https://route.showapi.com/3054-2?appKey={APP_KEY}", data={"text": text}, timeout=timeout) b2 = r2.json().get("showapi_res_body", {}) if b2.get("ret_code") != 0: return {"reply": "没听懂,可以换个说法吗", "stage": "intent"} intent, conf = b2.get("intent"), b2.get("confidence") s.absorb(b2.get("args") or {}) if intent not in SUPPORTED: return {"reply": "这个能力还没上线", "intent": intent} if conf is not None and conf < 80: return {"reply": "你是想问天气、快递还是新闻?", "intent": intent, "confidence": conf} # 执行层 r1 = requests.post(f"https://route.showapi.com/3054-1?appKey={APP_KEY}", data={"text": text}, timeout=timeout) d1 = r1.json() b1 = d1.get("showapi_res_body", {}) if b1.get("ret_code") != 0: return {"reply": "查询失败,稍后再试", "reason": b1.get("ret_msg")} # 回复层 return { "reply": b1.get("reply_msg", {}).get("text", ""), "intent": intent, "confidence": conf, "entities": s.last_entities, "rewritten": rewritten, "elapsed_s": round(time.time() - t0, 2), "fee": d1.get("showapi_fee_num"), } print(handle("u1", "昆明天气怎么样")) print(handle("u1", "那明天呢")) ``` `absorb` 那一段是关键。实测 `intent.args` 里能直接抽到 `area` 和 `express_nu`,把它们存进会话,下一句才补得回来。 ## FAQ **Q1:易源合一支持多轮对话吗?** 不支持。实测请求参数只有 `text` 和 `args_list`,没有会话或上下文参数,每次调用都是独立的单句识别。多轮上下文要在你自己的会话存储里维护。 **Q2:3054-1 和 3054-2 该选哪个做入口?** 如果只需要意图标签,用 3054-2。如果需要平台整理好的答复文案和原始数据,用 3054-1。两者可以组合,代价是延迟和费用叠加。 **Q3:并发上有什么限制?** 接口的并发量标注为 10 次/秒。两段式架构会把请求数翻倍,如果你的入口峰值接近这个量级,考虑把 3054-2 的结果做短期缓存。 **Q4:流式接入点能不能直接给前端用?** 技术上可以,3054-3 返回的就是 SSE 格式的文本流。但它是透传模式,没有统一的计费字段,也没有 `showapi_res_body` 封装,前端拿到的 `data` 是嵌套的 JSON 字符串,需要再解析一层。 **Q5:答复文案能改吗?** `reply_msg.text` 是平台生成的,改不了。要控制文案就只用 `intent` 和 `result` 自己拼回复。 ## 下一步阅读 - [易源合一 3054-2 与 3054-1 的搭配方式:先判意图,再决定要不要发起对话](https://www.showapi.com/guides/united-api-intent-precheck-3054) - [易源合一流式接入点 3054-3:SSE 分块解析与选型取舍](https://www.showapi.com/guides/united-api-streaming-3054) - [易源合一接进客服机器人:一次接入拿到天气、快递、新闻三类答复](https://www.showapi.com/guides/united-api-chatbot-skill-3054) - **本系列共 12 篇**:查看[易源合一指南总目录](https://www.showapi.com/guides/united-api-guides-3054)