决策路由族:问题分类 + 条件分支——工作流的骨架是分流,分流只能在分类节点出边完成
基于 Dify 1.16.1 与 Hermes Agent 实战实测(2026-08/09):意图分类 33% 失败率实测 + H3C 意图路由改造(18→15 节点)+ 8 组节点级实验
📖 摘要:工作流的骨架是分流:问题分类按意图路由、条件分支按条件分流。但分流有个硬规则——普通节点的出边无条件全走,只有分类节点和条件分支的出边是有条件的,所以分流必须在分类节点/条件分支的出边完成。本文实测:问题分类 33% 失败率的根因(instruction 没强制 JSON)与兜底设计、条件分支的 Unicode 运算符坑、分支完整性检查(为什么分支会成死代码)、意图路由改造(18 节点压缩到 15 节点)。
📌 本文要解决的核心痛点
- 问题分类经常分错(实测曾 33% 失败率),是模型问题还是配置问题?
- 两个下游都接到同一个普通节点后面,结果两个分支都执行了、回答拼成两段?
- 条件分支条件写对了,但就是走错分支——运算符为什么用
≥不是>=?- 设计文档说要分流成 3 个分支,跑起来只有 2 个在动,第三个成了死代码?
- 本文给分类节点和条件分支的权威配置、分流硬规则、分支完整性检查方法。
一、问题分类 + 条件分支是干什么的(先立规则)
分流是工作流的骨架——一个工作流好不好,先看它怎么分流。
| 节点 | 干什么 | 出边语义 |
|---|---|---|
| 问题分类(QC) | 按意图把请求分到不同处理链(客服/知识库/其他) | 有条件——每类一条出边,按分类结果走 |
| 条件分支(IF-ELSE) | 按条件真假分流 | 有条件——按条件结果走 |
⚠️ 分流硬规则(实测教训):普通节点的出边无条件全走——把两个下游都接到同一个普通节点(如知识检索)后面,该节点执行后两条出边都触发,两个分支都执行、回答拼接成两段。
| 正确姿势 | 错误姿势 |
|---|---|
| 分流在 QC/IF-ELSE 出边完成(每条出边独立链路) | 下游共享普通节点产生多分支 |
| 各分支用独立上游节点(每个分支自己的检索节点) | 一个检索节点喂两个 LLM 分支 |
二、设计模式
问题分类(QC)权威配置
| 字段 | 要求 | 实测依据 |
|---|---|---|
| model | 顶层配置(provider/name) | 三段式必填 |
| classes | 每类三字段(id/name/description) | 分类类目定义 |
| instruction | 必须强制 JSON 输出(「只输出 JSON,结构如下」) | 33% 失败率根因修复 |
| 出边 | sourceHandle = class id,每类一条 | 分类结果路由 |
instruction 是分类质量的关键:不强制 JSON,模型自由输出 → 分类结果解析失败/串类。强制 JSON + 类目边界描述(什么算什么)是稳定分类的前提。
条件分支(IF-ELSE)配置
| 字段 | 要求 |
|---|---|
| 条件四字段 | 变量选择器 / 比较运算符 / 比较值 / 变量类型 |
| 运算符 | 必须 Unicode(≥ 不是
>=、≠ 不是 !=) |
| 判空 | empty / not empty 操作符 |
| 值的位置 | 比较值放 value 字段(不是 right 字段) |
分支完整性(设计时就要查)
cases 数 = 文档设计的分支数——设计文档说 3 个分支,DSL 里必须有 3 个分支出口,每个分支的出口(end/answer/下一节点)存在。这是静态校验查不出、只有对照文档用例才暴露的缺陷(子代理漏分支的实测教训)。
三、实测踩坑(四个高频坑)
坑 1:问题分类 33% 失败率——instruction 没强制 JSON
现象:意图分类节点经常分错/分类结果解析失败。
实测:2026-08 Dify 意图分类实验——默认配置下失败率高达 33%。根因:instruction 没有强制 JSON 输出,模型自由发挥(输出自然语言而非结构化分类结果)。修复:instruction 显式「只输出 JSON,格式如下」+ 类目边界描述。
兜底设计:分类失败也要有兜底(默认分支/兜底回答)——分类是概率性节点,兜底是设计的一部分不是补救。
坑 2:普通节点多出边 → 多分支同时执行
现象:两个 LLM 下游都接到同一个知识检索节点后,检索节点执行后两条出边都触发,回答拼接成两段(knowledge 风格 + scenario 风格)。
根因:只有 QC 和 IF-ELSE 的出边是有条件的,普通节点出边无条件全走。
修复:各分支用独立上游节点(每个分支自己的检索节点,同 dataset),链路完全隔离;或先 IF-ELSE 分流再进各分支。
坑 3:条件分支运算符 ASCII → 分支走错
现象:条件写
>=,运行时分流结果不符合预期。
根因:Dify 条件分支的运算符必须是 Unicode
形式(≥ 非 >=),ASCII
写法不生效或报错。
修复:统一 Unicode 运算符(≥ /
≤ / ≠)。
坑 4:分支成死代码(漏分支)
现象:设计文档要求「输入质量检查」走 valid/invalid 两分支,生成的应用只有 valid 分支动了,invalid 分支逻辑完全没执行。
根因:生成时把检查节点直接连到分类器,reask(无效输入重问)分支成死代码——静态校验查不出(节点都有边、无孤立),只有跑文档用例才暴露。
修复:对每个「检查/校验/路由」类节点,确认文档要求的分支条件在 DSL 里有对应的分支出口,且每个分支可达。
四、节点级验证清单
| 验证点 | 怎么验 | 取证 |
|---|---|---|
| 分类准确率 | 每类至少 1 条用例 + 同输入多次采样 | 分类结果统计 |
| 分类兜底 | 分类失败输入(无匹配类)走默认分支 | 异常输入用例 |
| 分支互斥 | 多分支场景确认只走一条(不拼接) | 回答内容 + 节点执行记录 |
| 分支完整性 | cases 数 = 文档分支数,每分支可达 | 对照文档用例逐条跑 |
| 运算符 | 全表 Unicode 运算符检查 | 静态扫描 |
五、案例:意图路由改造(18 节点 → 15 节点)
场景:故障诊断助手——用户提问分三类:故障排查(problem)、配置查询(config)、其他(other)。
| 改造 | 做法 | 效果 |
|---|---|---|
| 原生分类节点 | 用 question-classifier 替代「LLM 模拟分类 + 归一化 code + 双 if-else」四节点 | 18 节点 → 15 节点 |
| 出边路由 | class 出边即路由(problem → 故障检索 / config → 配置检索 / other 不检索直接引导) | 一个 QC 替代四节点 |
| 独立检索链路 | 各分支独立检索节点(不共享) | 消除多分支同时执行 |
| 分支汇聚 | cd_merge 三入参引用未执行分支 result 安全 | 汇聚不报错 |
核心结论:分类节点是概率性节点——强制 JSON + 类目边界 + 兜底分支是稳定三件套;分流硬规则(普通节点不出多分支)是拓扑级纪律,违反它跑通了也是错的。
下一篇预告:《数据操作族:模板转换 + 代码执行 + 变量聚合/赋值 + 列表操作》——数据五件套怎么选。代码节点的正则双重转义坑、模板转换的空值防护、变量赋值的 10 种操作(含跨轮次记忆)、列表操作对 object 数组的限制。
- Dify 节点全景图:20 个节点、7 个功能族、3 个通用设计问题
- 内容生成族:LLM 节点怎么设计才稳定——六类 17 条自查清单 + 4 条进阶经验
- 知识接入族:知识检索节点——RAG 质量的三道闸门(分段 / 检索配置 / 清洗)
- 决策路由族:问题分类 + 条件分支——工作流的骨架是分流,分流只能在分类节点出边完成
- 数据操作族:模板转换 / 代码执行 / 变量聚合 / 变量赋值 / 列表操作——数据五件套的选型与契约
- 外部交互族:HTTP / 工具 / Agent 节点 / 外部数据源——与外部世界打交道的四种方式
- 流程编排族:迭代 / 循环 / 定时触发 / 子工作流 / 人工输入——复杂流程组织五件套
- 输入处理族:参数提取 + 文档提取器——非结构化输入结构化的两种方式
- 节点级验证方法论:每个节点怎么验——三层排查 + 验证清单总表