Dify 中级实验(02):问题分类器——智能路由引擎如何四路分发?
1. 业务场景
先讲一个我们实际遇到的场景。
一家做企业 SaaS 的公司,客服团队每天要处理几百条用户消息:有人问「API 返回 500 错误怎么办」——这是技术问题;有人问「你们报价多少」——这是商务问题;有人喊「我要退货」——这是售后问题。所有消息涌进同一个入口,客服要先读懂、再判断、再手动转给对应团队,高峰期消息排队,用户越等越急。
我们第一次接这类需求时,第一反应也是「写一组关键字规则,命中哪个算哪类」。真正动手才发现——用户的话千奇百怪,「我要退货!」和「东西坏了想退掉」没有一个字是一样的,规则永远追着新说法跑。后来翻 Dify 的节点列表才发现:平台原生的 Question Classifier(问题分类器) 就是干这个的——LLM 理解语义,按预设类别做多路路由,直接决定后续走哪个分支。
这不是个例。任何「用户问题需要先分类、再走不同流程」的业务场景都是这个模式:工单系统里故障报修要先分给对应运维组,FAQ 导航里用户要先选问题大类,邮件中心里咨询、投诉、合作邮件要先分流给不同部门处理。
2. 场景痛点
这个流程的痛点,在客服团队身上体现得最直接:
- 人工分类慢:每条消息先读一遍、再判归属、再转派,高峰期消息堆积,用户等回复的时间被拉长——分类本身不产生价值,却卡在流程最前面。
- 分类口径全凭个人:「报价多少」有人归商务、有人归售后,同一个词在不同客服手里走向不同流程,业务数据从此对不上——口径漂移比慢更隐蔽:数据对不上,统计和考核全部失真。
- 混合问题容易漏判:「API 报错还扣了钱,怎么退」这种消息,人工经常只处理一半——技术问题答了,售后问题没人管,用户二次投诉。
- 经验沉淀在人脑里:老客服知道「退换货」归售后,新人只能猜——分类质量跟着人员流动波动,团队越大越不稳定。
本质上,分类这件事没有技术含量,却决定后面所有流程走哪条路——分错一次,整条处理链都跟着错。分类的确定性不该靠每个客服的个人手感,该靠一份可复用的规则。
3. 方案:为什么是问题分类器
选问题分类器的理由,我们实际对比过:
- 比 IF-ELSE 智能:IF-ELSE 只能做关键字/数值判断,分类器靠 LLM 理解语义——「我要退货!」和「东西坏了想退掉」都能归到售后类;
- 类别可配示例词表:每个类别配 5-8 个业务示例词(报价/合同/合作),分类准确率有保障;
- 有兜底有置信度:设计一个
other兜底类别,模糊问题不会被硬塞进业务类别;分类结果带置信度,可接后续判断。
这篇文章我们就用它搭一个「企业智能助手」,四类问题(技术/商务/售后/其他)四路分发,每类走各自的处理流程。
4. 整体架构
链路很清晰:入口收问题 → 分类路由 →
四路独立处理。关键点:分类器的边直接用类别 ID 作为
sourceHandle——tech/business/after_sale/other
四条边从分类节点分出去,不需要中间再挂 IF-ELSE。
5. 模块设计
5.1 分类类别配置
classes:
- id: tech
name: 技术问题
- id: business
name: 商务问题
- id: after_sale
name: 售后问题
- id: other
name: 其他5.2 分类指令(instruction)——决定分类质量的灵魂
分类器靠 LLM 理解,指令写得好不好直接决定分类准确率:
instruction: |
对用户的问题进行分类,只能归为以下四类之一:
- 技术问题(tech):产品技术咨询、代码问题、系统 BUG、API 文档、错误信息
- 商务问题(business):报价、合同、合作、采购、价格
- 售后问题(after_sale):退换货、投诉、保修、维修、退款
- 其他(other):不属于以上三类的任何问题
只输出类别 ID,不要输出其他内容。要点:
- 每个类别给足示例词——「报价/合同/合作」这种业务词表是分类准确率的保障
- 明确「只能归为以下四类之一」+「只输出类别 ID」——防止 LLM 自由发挥
- 设计一个
other兜底类别——没有它,所有模糊问题都会被硬塞进前三类
5.3 分支处理
每个分支独立成链。技术分支(知识库检索)注意:知识库结果传给代码节点参数类型用
list,提取用
item.get("content", ""):
def main(results: list) -> dict:
docs = [r.get("content", "") for r in results if isinstance(r, dict)]
return {"docs_text": "\n\n".join(f"[{i+1}] {d}" for i, d in enumerate(docs))}6. 运行验证
四类典型输入实测:
| 输入 | 预期分类 | 结果 |
|---|---|---|
| 「API 返回 500 错误怎么办?」 | tech | ✅ 走知识库检索 + 技术问答 |
| 「你们报价多少?」 | business | ✅ 走价格查询 + 商务接待 |
| 「我要退货!」 | after_sale | ✅ 生成工单 + 售后处理 |
| 「今天天气怎么样?」 | other | ✅ 通用问答 |
混合问题(如「API 报错还扣了钱,怎么退」)——分类器会按置信度归入最匹配类别。
7. 实战坑
| 坑 | 现象 | 修复 |
|---|---|---|
| 类别没有示例词表 | 分类准确率低(「报价」被分到售后) | instruction 里每类给 5-8 个示例词 |
| 没有 other 兜底类别 | 无关问题被硬塞进业务类别 | 加 other 类 + 「不属于以上三类」 |
| 分类后接 IF-ELSE 再判断 | 多一层无谓判断(分类器已给结果) | 直接用类别 ID 做出边(sourceHandle) |
| 知识库结果直接给 LLM | object 不可见 / 引用格式乱 | 先代码节点转 docs_text 编号文本 |
8. 实验文档及源码获取
- 实验文档(完整操作步骤):DIFY-03:问题分类器——智能路由引擎.md
- 源码(可直接导入):dify102_03_智能分类路由.yml
文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。
- Dify 中级实验(01):参数提取器实战——如何从自然语言中提取结构化数据?
- Dify 中级实验(02):问题分类器——智能路由引擎如何四路分发?
- Dify 中级实验(03):模板转换实战——如何用零 Token 完成文本加工?
- Dify 中级实验(04):迭代进阶——如何批量处理数据并守住性能边界?
- Dify 中级实验(05):并行执行——如何让多路任务同时跑?
- Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?
- Dify 中级实验(07):子工作流——如何把公共逻辑做成可复用积木?
- Dify 中级实验(08):代码节点进阶——如何用标准库处理文件与数据?
- Dify 中级实验(09):HTTP 节点进阶——如何搞定认证、分页与错误重试?
- Dify 中级实验(10):知识库深度调优——如何科学评估检索质量?
- Dify 中级实验(11):高级 RAG 流水线——如何搭建多路检索与精排?
- Dify 中级实验(12):Agent 深度配置——如何让智能体自主调用工具?
- Dify 中级实验(13):多 Agent 协作——如何编排多个智能体分工干活?
- Dify 中级实验(14):对话变量与状态管理——如何让工作流记住多轮对话的状态?
- Dify 中级实验(15):条件分支高阶策略——多条件路由如何避免分支爆炸?
- Dify 中级实验(16):错误处理与降级——工作流如何有尊严地失败?
- Dify 中级实验(17):调试监控与性能优化——响应慢和 Token 超支如何定位?
- Dify 中级实验(18):插件开发入门——如何把工作流变成 Agent 可调用的工具?
- Dify 中级实验(19):综合实战——如何把 19 个实验串成一条生产级流水线?
- Dify 中级实验(20):综合实战——自动化报告生成流水线如何从数据到周报一步到位?