别让 AI 客服把用户当猴耍:百来行 Python 把「转人工」做成一条高可用链路

9 月 1 日,GB/T 47746---2026《顾客联络服务 人工与智能客户服务协同要求》正式实施。这是国内第一个专门约束人机客服协同的国家标准,几条硬要求值得直接抄进需求文档:

  • 必须设置清晰、醒目的人工服务入口,严禁隐藏人工通道;
  • 用户明确要求转人工时,必须及时转接;
  • 切换后要同步客户信息,不得重复询问;
  • 涉及价格、折扣、退款、赔偿、合同变更等事项,AI 可以解释规则、收集材料、生成工单,最终确认应由人工或规范化流程完成。

  现实是落地两个月,媒体实测仍在翻车:某购票平台记者三次说「转人工」才接通,有人等 40 分钟未接通导致票作废,甚至有机器人在识别到用户坚持后直接挂断。中消协上半年数据里,售后服务投诉占 26.79%,「AI 客服不实承诺、人工接入困难」是新增热点。

  这些问题跟模型能力关系不大,几乎全是会话状态管理 和产品策略的问题。下面给一份能直接跑的骨架。

技术要点

  四个约束,决定了实现方式:

  1. 转人工必须是规则,不是模型判断。 意图识别交给人,兜底交给规则引擎。标准里写的「明确要求」「超时」「高风险场景」,本质都是可枚举的触发条件。   2. 会话要有状态计数。 兜底话术连续命中几次、总轮次到了几轮,都得记。大多数线上事故就是没有这两个计数器。   3. 风险词优先于业务词。 「投诉」「监管」「12315」「人身安全」这类词必须走独立通道,不能被「自助流程」吃掉。   4. 转接要带上下文。 转过去之后人工看不到历史记录,等于用户要把委屈再讲一遍,体验二次崩塌。

可运行示例

  纯标准库,复制即可跑。核心是一个 route() 函数,返回「继续聊」还是「转人工」。

python 复制代码
# 三段代码块按顺序拼接后可直接运行

from dataclasses import dataclass
from typing import Callable
# --- 明确要求转人工:命中即转(国标硬要求)---
ESCALATE_PATTERNS = ("转人工", "人工客服", "找真人", "真人客服", "我要人工")
# --- 风险词:命中即升级,优先级最高 ---
RISK_PATTERNS = ("投诉", "监管", "12315", "起诉", "曝光", "受伤", "人身", "诈骗")
MAX_TURNS = 4
MAX_REPEAT = 2
# --- 会话状态:三个计数器全在这儿 ---
@dataclass
class Session:
    sid: str
    turns: int = 0
    fail_hits: int = 0          # 兜底话术连续命中次数
    last_reply: str = ""
    history: list = None
    def __post_init__(self):
        self.history = []

def route(session: Session, text: str, reply_fn: Callable[[str], str]):
    """返回 (action, 回复文本)。"""
    text = (text or "").strip()
    session.turns += 1
    session.history.append(("user", text))
    # 1. 风险词最高优先级,不做任何自助挽留
    if any(k in text for k in RISK_PATTERNS):
        return "escalate", "已为您转接人工,请稍候。"
    # 2. 明确要求转人工:一次就转,不挽留
    if any(k in text for k in ESCALATE_PATTERNS):
        return "escalate", "正在为您转接人工客服。"
    # 3. 正常业务链路:模型只负责生成回复,永远不决定要不要转
    reply = reply_fn(text)
    if reply == session.last_reply:
        session.fail_hits += 1
    else:
        session.fail_hits = 0
    session.last_reply = reply
    session.history.append(("bot", reply))
    # 4. 兜底:重复话术 / 轮次超限,两个计数器任一命中
    if session.fail_hits >= MAX_REPEAT:
        return "escalate", "这个问题我处理不了,已为您转接人工。"
    if session.turns >= MAX_TURNS:
        return "escalate", "已经为您尝试多次,转接人工继续处理。"
    return "reply", reply

if __name__ == "__main__":
    FALLBACK = "非常理解您的心情,请您耐心等待。"
    def fake_llm(text: str) -> str:
        # 模拟一个只会答非所问的机器人
        if "退" in text:
            return FALLBACK
        return "您可以在订单详情页自助操作。"
    def run(cases, label):
        s = Session(sid=label)
        print(f"--- {label} ---")
        for i, q in enumerate(cases, 1):
            action, msg = route(s, q, fake_llm)
            print(f"[{i}] {q} -> {action}: {msg}")
            if action == "escalate":
                print(f"    升级时携带 {len(s.history)} 条上下文")
                break
    # 三条路径各跑一遍
    run(["我要退两张电影票", "退不了", "还是退不了", "算了"], "兜底话术重复触发")
    run(["这个优惠券怎么用不了", "我要投诉"], "风险词触发")
    run(["这个优惠券怎么用不了", "转人工"], "明确要求触发")

  三条路径各跑一遍:兜底重复那条在第 3 句升级,风险词和明确要求都在第 2 句升级。也就是说,不需要模型多聪明,只要三个计数器有一个响了,人就能被捞出来。

  如果要接大模型生成兜底话术,建议把「生成」和「决策」拆开:模型只负责 reply_fn,升级与否永远由 route() 决定。我平时调这类多模型兜底,统一入口切换的,省掉给每家单独对接 SDK 的功夫,也不用为了几个备用模型各开一份订阅。关键路径上别用单一供应商,这点比选哪个模型重要。

踩坑提示

  坑一:把「人工」「0」当触发词。 很多系统对单字识别不准,「人工」两个字经常被当成业务词吃掉。要么匹配完整短语,要么维护一张同义词表,别指望模糊匹配。

  坑二:情绪识别做反了。 有团队上了情绪打分,用户越急越触发「安抚话术」分支,结果把人困得更久。正确做法是情绪升级直接降权自助流程、提权转人工,不是加一段安慰。

  坑三:把「转人工率」当负向 KPI。 这是根子上的问题。一旦转人工率高要被扣绩效,产品经理就会去藏入口,工程侧再漂亮也白搭。指标至少要成对看:转人工率 + 转人工后一次解决率 + 平均接通时长。

  坑四:转接丢上下文。 国标明确要求切换后同步客户信息、不重复询问。实现上给工单附一段结构化摘要就够:用户诉求、已尝试动作、订单号、情绪标记。别把整段对话原样丢过去,人工读不完。

  坑五:AI 的承诺没留痕。 中消协的态度很明确,经营者自己部署的 AI 客服,输出内容属于服务的一部分,「AI 说的不算」这种甩锅站不住。会话记录必须可检索、可导出,退款赔偿类承诺要落工单。

总结

  转人工难的解法,八分在工程,两分在决心。工程部分是这几个计数器和一个优先级队列,一个下午能写完;决心部分是愿不愿意在「省人工」和「别把人逼疯」之间选后者。标准已经给了标尺,接下来谁先改,谁少挨骂。

相关推荐
属于自己的天空1 小时前
Claude Code 插件完全指南:官方市场怎么用,怎么自己写(v2.1.269+)
后端
Tokenfree1 小时前
给大模型调用加一个熔断器:60 行代码,三个阈值
后端
Jason_chen1 小时前
Linux 进程调度器深入解析与实时性优化指南(基于 Linux 5.10+)
后端
136096757231 小时前
三个 Agent 干同一个活,职责边界到底该怎么划
后端
房西杭1 小时前
GM 指令:修改玩家属性
后端
胡写代码1 小时前
删掉的数据还占着唯一键:逻辑删除 + 唯一索引的四次取舍
spring boot·后端
IT_陈寒2 小时前
React的useEffect依赖数组把我坑惨了
前端·人工智能·后端
用户8356290780512 小时前
Python 调整 Excel 工作表显示设置
后端·python
ServBay2 小时前
API Key 泄露如何在 10 分钟内止血?AI 密钥管理必备
后端·ai编程