背景痛点:人工客服的“三座大山”
去年双十一,我们团队的小程序订单量翻了 4 倍,客服同学却“原地爆炸”——
- 高峰期 2000+ 并发,人工坐席 30 人,平均排队 8 分钟,退款类投诉直接飙升。
- 新人培训 2 周才能上岗,但话术不统一,用户上午问“能改地址吗?”得到“可以”,下午再问就变成“不行”,体验翻车。
- 夜间只有 1 人值班,70% 是“查物流”“开发票”这类重复问题,却要守着屏幕到凌晨 3 点。
老板一句“降本增效”,我们把目光投向了 AI。调研后发现,传统方案各有硬伤:
- 关键词规则:穷举“改地址”的同义词,一周就膨胀到 800 条,维护噩梦。
- 机器学习模型:意图识别准,但多轮对话、上下文、业务动作都要自己搭,工期直接 +50%。
- 智能体(Agent):自带对话状态跟踪、工具调用、记忆管理,听起来像“外包员工”,能直接上手?
于是,我们决定用“智能体”重构整个客服链路,目标只有一个:让人工只处理“钱”和“情绪”,其余全部自动化。
技术选型:规则 vs 模型 vs 智能体
先放结论:没有银弹,只有“最适合”。
| 维度 | 规则引擎 | ML 模型 | 智能体 |
|---|---|---|---|
| 开发速度 | 1 天可上线 | 1 周训练+1 周工程 | 2 天搭骨架,1 周调优 |
| 多轮对话 | 需外挂状态机 | 需自写 DST* | 内置 DST |
| 工具调用 | if/else 硬编码 | 额外写 API 适配 | Function Calling 原生 |
| 维护成本 | 规则爆炸 | 数据回流重训 | Prompt+样本即可 |
| 线上风险 | 100% 可解释 | 黑盒 | 半黑盒,可日志回放 |
*DST:Dialogue State Tracking,对话状态跟踪。
一句话总结:
规则是“写死 if”,模型是“猜概率”,智能体是“会思考+能动手”。对小程序客服这种“高频、多轮、要查订单”的场景,智能体最对胃口。
核心实现:让智能体“长”在小程序里
1. 系统总览
我们把整个链路拆成三层:
- 接入层:小程序原生 button → 微信官方客服消息 → 自建网关(Node.js)
- 智能体层:LangChain 驱动,负责意图识别、记忆、工具调用
- 数据层:订单/物流/退款接口统一封装成 OpenAPI,智能体按需查询
2. 对话管理设计
智能体内部用“槽位+记忆”双保险:
- 槽位(Slot):定义业务必填字段,如 orderId、refundReason。
- 记忆(Memory):把 5 轮内用户/助手明文写入 Redis,带 TTL 10 min,解决“用户中途改口”问题。
伪代码片段(Python):
class CustomerServiceAgent: def __init__(self, tools, memory): self.tools = {t.name: t for t in tools} self.memory = memory # RedisChatMessageHistory def run(self, user_input: str, openid: str): # 1. 拉取历史 history = self.memory.messages(openid) # 2. LLM 生成下一步动作 action = self.llm.plan(history + [HumanMessage(user_input)]) # 3. 如果动作需要调用工具 if action.tool_name in self.tools: tool = self.tools[action.tool_name] output = tool(**action.tool_input) action.observation = output # 4. 返回自然语言回复 reply = self.llm.format(action) self.memory.add(openid, HumanMessage(user_input)) self.memory.add(openid, AIMessage(reply)) return reply3. 意图识别 & 上下文保持
- NLU 用 LLM 自带的 zero-shot,Prompt 里直接写“请从【查物流|申请退款|修改地址|人工客服】中选一个意图”,92% 准确,够用了。
- 关键信息抽取用 Pydantic 结构体,LLM 自动填槽,失败就问“请问订单号后 6 位是?”——把对话拉回正轨。
4. 与小程序前端对接
微信限制:客服消息只能由用户主动点击触发,且 48 h 内可回 5 条。我们做了两件事:
- 把“联系客服”按钮改成“AI 客服”,用户无感。
- 网关收到 xml 后,立即回一句“正在输入…”,再把 openid+内容塞给智能体,超时 4 s 必返,避免微信重试。
代码示例:Node.js 网关 + Python 智能体
1. 网关(Node.js)
// gateway.js const express = require('express'); const axios = require('axios'); const { logger } = require('./utils'); const app = express(); app.use(express.raw({ type: 'text/xml' })); app.post('/wechat', async (req, res) => { const xml = req.body.toString(); const { openid, content } = parseXml(xml); try { // 1. 立即回微信“success”防重试 res.send('success'); // 2. 调用智能体 const { data } = await axios.post('http://agent:8000/chat', { openid, content }); // 3. 主动发客服消息 await sendCustomerServiceMsg(openid, data.reply); } catch (e) { logger.error(e); await sendCustomerServiceMsg(openid, '系统开小差了,转人工中>>'); } });2. 智能体(Python)
# agent.py from pydantic import BaseModel, Field from langchain.llms import ChatOpenAI from langchain.agents import Tool, AgentExecutor from langchain.memory import RedisChatMessageHistory class RefundTool(BaseModel): order_id: str = Field(description="订单号") reason: str = Field(description="退款原因") def apply_refund(order_id: str, reason: str) -> str: """调用内部退款接口""" try: r = requests.post(refund_api, json={"orderId": order_id, "reason": reason}) return r.json().get("msg", "success") except Exception as e: logger.exception("Refund API error") return "退款接口异常,已通知工程师" tools = [ Tool( name="apply_refund", func=apply_refund, description="帮助用户申请退款,需要订单号和原因" ) ] llm = ChatOpenAI(temperature=0) agent = initialize_agent( tools=tools, llm=llm, agent="conversational-react-description", memory=RedisChatMessageHistory(session_id="openid"), verbose=True )异常与日志:
- 所有 tool 统一 try/except,返回字符串而非抛错,防止 LLM“懵”。
- 关键步骤打结构化日志(openid、意图、槽位、耗时),方便回滚。
生产考量:并发、冷启动与安全
- 并发:单容器 2 vCPU+4 G 可扛 200 QPS,LLM 调用平均 600 ms。再往上就加副本,网关层无状态,横向扩容即可。
- 冷启动:LangChain 首次 import 重,用 gunicorn
--preload预加载,P99 从 3 s 降到 300 ms。 - 安全:
- 敏感词过滤:接公司自研 DFA 算法,100 μs 级,命中直接拒答“亲亲,涉及敏感信息,已转人工”。
- 接口鉴权:智能体→内部服务走内网 + JWT,网关→微信走明文+签名验证,杜绝公网裸奔。
- 日志脱敏:订单号、手机号中间 4 位打星,合规审计无压力。
避坑指南:我们踩过的 5 个深坑
微信 5 条消息限制
用户连续点 5 次“AI 客服”后,第 6 条微信直接拒收。解决:前端计数,达 4 条时弹窗“是否需要人工?”。LLM 幻觉乱承诺
早期 Prompt 没加“禁止承诺不可兑现的话”,AI 直接说“马上退全款”,结果财务没审核,被投诉。修复:Prompt 末尾加“若需退款,必须走审核,2 小时内答复”。工具返回太长撑爆 Token
物流接口返回 2 k 字段,LLM 摘要失败。解决:tool 侧先清洗,只保留“时间+地点+状态”,Token 降 70%。Redis 内存暴涨
记忆无上限,用户聊 50 轮后 Value 达 30 kB,1 万用户就把 2 G 打满。解决:LRU 保留最近 5 轮,老消息异步落盘。多意图混淆
用户一句“我要退款,顺便改地址”,LLM 只调了退款。解决:在 Prompt 里加“若同时出现多个动作,请按列表顺序执行”,并返回 JSON List,for 循环调用工具。
结尾:智能体的边界在哪里?
把客服 80% 的重复劳动砍掉后,我们反而开始思考:
当 AI 能查订单、能退款、能道歉,用户是否还需要“真人”?
如果 LLM 在某种极端场景下给出错误承诺,责任归谁?
当智能体学会“情绪安抚”,会不会为了满意度而过度让利,导致公司亏损?
这些问题没有标准答案,却决定了智能体能否从“降本工具”升级为“可信伙伴”。
你在业务里落地智能体时,会给它设哪些“伦理红线”?欢迎留言一起碰撞。
(完)