← 返回文章列表

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

1. 业务场景

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

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

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

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

2. 场景痛点

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

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

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

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

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

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

4. 整体架构

graph TD start["开始:用户输入 sys.query"] --> qc{"问题分类器 qc_main:product / order / return / human"} qc -- "product" --> kbp["知识库 kb_product:single 检索 TopK=3"] kbp --> lmp["LLM lm_product"] lmp --> ap["回复 ans_product"] qc -- "order" --> cdo["代码 cd_order:正则提取订单号 + 模拟订单 API"] cdo --> lmo["LLM lm_order"] lmo --> ao["回复 ans_order"] qc -- "return" --> cdr["代码 cd_return:退换货规则判断"] cdr --> cr{"条件分支 cond_return"} cr -- "case_auto" --> lmr["LLM lm_return"] lmr --> ar["回复 ans_return"] cr -- "case_human" --> cdt["代码 cd_ticket:生成工单"] cdt --> cdn["代码 cd_notify:通知客服"] cdn --> ah["回复 ans_human"] qc -- "human" --> cdt

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

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 开头的订单号:

def main(order_id):

    import re

    m = re.search(r"OD\d{6,}", order_id or "")

    oid = m.group(0) if m else ""

    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" if oid in mock_orders else "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 条作为上下文,让人工客服不用用户重复描述:

def main(user_query, conversation_history):

    import time

    history = conversation_history if isinstance(conversation_history, list) else []

    ticket_id = "TK-{}".format(int(time.time()))

    priority = "high" if "投诉" in (user_query or "") else "normal"

    ctx = ";".join(history[-3:]) if history else "(无历史记录)"

    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 实测)
代码节点返回 boolean can_return 在 if-else 变量选择器不可见,分支配不上 boolean 展平为 "true"/"false" 字符串,条件用 is 比较
知识库分段不自包含 single 检索单段命中,LLM 拿到的片段缺上下文,答不全 入库分段时保证每段自含答案(自包含分段,检索 TopK 才有效)
转人工不带上下文 人工客服看不到用户之前说了什么,用户重复描述 工单代码引用 conversation_history 最近 3 条拼进 context(dify103_03 实测)

8. 实验文档及源码获取

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

联系我

15088711270

手机端点击号码可直接拨打 · 桌面端可复制

微信二维码

扫码加微信 · 备注「门户」更快通过