三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Dify 高级实验(03):智能客服——如何让 AI 自动应答并把疑难问题转人工?

Dify 高级实验(03):智能客服——如何让 AI 自动应答并把疑难问题转人工?

Dify 高级实验(03):智能客服——如何让 AI 自动应答并把疑难问题转人工?

Dify 实验系列 · 高级 03/10 | 实验编号:DIFY-103-03
基于 Dify 1.16.1 实测(2026-08)

1. 业务场景

先讲一个我们实际遇到的场景。

一家电商公司每天要接几千条客服咨询,其中一大半是重复问题:「这个手机多少钱?」「我的订单到哪了?」「怎么退货?」。客服团队 30 个人三班倒,还是经常排队,高峰期用户等十几分钟才被接起。公司想过用 AI 全自动应答,但又不敢全放开——真遇到投诉、纠纷,AI 答不好反而火上浇油。于是客服主管的诉求很明确:能自动处理的自动处理,处理不了的带着完整上下文转人工,别让用户重复描述第二遍。

我们第一次接这类需求时,第一反应也是「全自动 AI 客服嘛,套个知识库就完事了」。真正动手才发现——知识库只能覆盖「商品咨询」这一路,订单查询要对接系统、退换货要按规则判定、转人工要生成工单,自动应答和转人工兜底是两套工程,少了哪一套,这个客服系统都立不住。

这不是个例。任何「客服量大的企业」都是这个模式:银行网点问答、运营商话费查询、SaaS 厂商工单支持——常见问题重复回答是常态,但完全用 AI 替代人工又不放心,难点从来不是「要不要用 AI」,而是「AI 接得住多少、接不住时怎么优雅地交给人工」。

2. 场景痛点

这个流程的痛点,在客服团队身上体现得最直接:

  • 重复咨询吃掉人力:一半以上的会话是同类问题,客服每天把同样的答案说几十遍——人力成本高,回答质量还随状态波动,累了就敷衍。
  • 高峰期排队流失用户:大促、活动期间咨询量翻倍,用户排队等几分钟就关页面走人,可能直接去竞品下单——每一次排队都是一次流失风险。
  • 转人工要用户重复描述:AI 答不了转人工时,用户得把问题从头再说一遍,体验极差,客服还要重新理解上下文——「我已经说过了」是客服场景最常见的抱怨。
  • 疑难问题无兜底:投诉、纠纷这类问题没有可靠的升级通道,AI 硬答容易激化矛盾,漏接则直接变成客诉事件。

本质上,客服的困境不是「AI 能不能替代人」,而是「常见问题自动化 + 疑难问题兜底」这套分工体系没搭起来——该自动的没自动,该转的没转好。

3. 方案:为什么是这套智能客服架构

Dify 的Chatflow(对话型应用)里用「问题分类 → 多分支路由 → 自动应答 → 转人工兜底」的架构,正好把「自动 + 兜底」两件事同时解决。

选它的理由,我们实际对比过:

  • 问题分类器原生路由:不用手写意图识别,配置好商品咨询/订单查询/退换货/转人工四类示例,LLM 自动把用户问题分到对应分支;
  • 确定性问题不用 LLM:订单查询用正则提取订单号、退换货按规则判断,代码节点搞定——确定性规则交给代码,省 token 且结果稳定;
  • 转人工带上下文:对话变量conversation_history自动累积,转人工时取最近 3 条随工单带走,人工接手不用用户重新描述。

这篇文章我们就用它搭一个「电商智能客服」:商品咨询走知识库、订单查询走模拟 API、退换货按规则自动判定,用户说「转人工」则生成工单并通知客服。

4. 整体架构

product

order

return

case_auto

case_human

human

开始:用户输入 sys.query

问题分类器 qc_main:product / order / return / human

知识库 kb_product:single 检索 TopK=3

LLM lm_product

回复 ans_product

代码 cd_order:正则提取订单号 + 模拟订单 API

LLM lm_order

回复 ans_order

代码 cd_return:退换货规则判断

条件分支 cond_return

LLM lm_return

回复 ans_return

代码 cd_ticket:生成工单

代码 cd_notify:通知客服

回复 ans_human

链路很清晰:入口收用户消息 → 分类路由 → 各分支自动应答 → 疑难问题转人工。分类器是这个架构的枢纽——分错类,后面所有分支的努力都白费;所以分类器必须写清示例、并强制「用户明确要求人工时一定归入转人工」。

5. 模块设计

5.1 问题分类器 qc_main

单标签分类,四类指令必须写清示例,并强制兜底转人工

class_list:-商品咨询 product:商品信息、规格、库存、价格(例:这个手机多少钱?)-订单查询 order:订单状态、物流、配送(例:我的订单到哪了?)-退换货 return:退货、换货、退款(例:我要退货)-转人工 human:用户主动要求找人工客服(例:转人工、找客服)instruction:用户明确要求人工时一定要归入"转人工",避免漏接。

5.2 商品咨询分支:知识库 + LLM

kb_productretrieval_mode: single(单路检索)、top_k: 3score_threshold: 0.0必须绑定真实知识库dataset_ids填实际库 ID,query_variable_selector绑用户查询);lm_productcontext 模式引用检索结果(context: {enabled: true, variable_selector: [kb_product, result]}),prompt 里用{{#context#}}占位符——由平台把检索结果注入上下文(引用溯源/上下文管理交给平台),而不是手动把{{#kb_product.result#}}拼进提示词。系统提示词要求仅依据检索结果回答、不编造规格价格:

你是电商客服助手小 D,负责商品咨询。请根据知识库检索到的商品信息回答用户问题。 用户问题:{{#sys.query#}} 商品资料: {{#context#}} 要求: 1. 仅根据检索到的商品资料回答,不要编造规格、价格和库存 2. 如果检索结果为空或不足以回答,诚实说明,并建议用户转人工客服 3. 回答简洁友好

5.3 订单查询分支:正则提取订单号

用户句子是「我的订单 OD202607002 到哪了?」,不能整句查表,必须先正则提取OD开头的订单号:

defmain(order_id):importre m=re.search(r"OD\d{6,}",order_idor"")oid=m.group(0)ifmelse""mock_orders={"OD202607002":{"status":"配送中","logistics":"中通 ZT9876543210","eta":"2026-07-23"},"OD202607003":{"status":"已签收","logistics":"圆通 YT5555555555","eta":"2026-07-20"},}order=mock_orders.get(oid,{"status":"未找到","logistics":"","eta":""})return{"found":"true"ifoidinmock_orderselse"false","order_id":oid,"status":order["status"],"logistics":order["logistics"],"eta":order["eta"]}

5.4 退换货分支:规则判断 + 条件分支

确定性规则用代码节点(不用 LLM),boolean 展平为字符串;cond_return的 case_auto 用 OR 组合:

cd_return 输出:can_return / can_exchange 均为 "true"|"false" 字符串case_auto:cd_return.can_return is "true" OR cd_return.can_exchange is "true"case_human:cd_return.can_return is "false" AND cd_return.can_exchange is "false"

5.5 转人工分支:工单 + 通知 + 上下文

cd_ticket生成工单号、按是否含「投诉」定优先级,并带上对话变量conversation_history最近 3 条作为上下文,让人工客服不用用户重复描述:

defmain(user_query,conversation_history):importtime history=conversation_historyifisinstance(conversation_history,list)else[]ticket_id="TK-{}".format(int(time.time()))priority="high"if"投诉"in(user_queryor"")else"normal"ctx=";".join(history[-3:])ifhistoryelse"(无历史记录)"return{"ticket_id":ticket_id,"priority":priority,"context":ctx,"message":"已为您转接人工客服,工单号:{}。客服将在 5 分钟内联系您。".format(ticket_id)}

6. 运行验证

输入期望行为实测
「这个手机多少钱?」分类为 product,知识库检索后回答商品信息与预期一致
「我的订单 OD202607002 到哪了?」正则提取订单号,返回「配送中 + 物流单号」与预期一致
「我要退货,刚收到 3 天」规则判定可退货,走 case_auto 自动回复与预期一致
「投诉!你们物流太慢了,转人工」分类 human,工单优先级 high,通知客服与预期一致,工单上下文含历史记录

7. 实战坑

现象修复
分类器漏「转人工」兜底用户说「找客服」被分到商品咨询,AI 答非所问且无法转人工指令明确「用户明确要求人工时一定要归入转人工」+ 给示例(dify103_03 实测)
订单号整句查表「我的订单 OD202607002 到哪了」查不到(含多余文字)代码节点先re.search(r"OD\d{6,}")提取订单号再查(dify103_03 实测)
代码节点返回 booleancan_return在 if-else 变量选择器不可见,分支配不上boolean 展平为"true"/"false"字符串,条件用is比较
知识库分段不自包含single 检索单段命中,LLM 拿到的片段缺上下文,答不全入库分段时保证每段自含答案(自包含分段,检索 TopK 才有效)
转人工不带上下文人工客服看不到用户之前说了什么,用户重复描述工单代码引用conversation_history最近 3 条拼进 context(dify103_03 实测)

8. 实验文档及源码获取

  • 实验文档(完整操作步骤):DIFY-103-03:智能客服系统.md
  • 源码(可直接导入):dify103_03_智能客服系统.yml

文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。


下一篇:Dify 高级实验(04):RAG 增强问答——如何让知识库问答更准还能多轮追问?

💬 你在这个实验的场景里踩过什么坑?欢迎评论区分享你的实战经验。

← 返回列表