背景痛点:规则引擎的“天花板”
去年双十一,公司客服系统被用户吐槽“像复读机”——“退货进度”四个字能触发三条不同答案,甚至把“我要退货”当成“我要睡觉”。根源是早期用正则+关键词的“规则引擎”:
- 意图覆盖全靠人工堆规则,新增一个场景要改 30+ 条正则,维护成本指数级上涨
- 多轮对话靠 if-else 硬编码,上下文超过 3 轮就“失忆”
- 高峰期并发 200 QPS 时,规则匹配 CPU 飙到 80%,平均响应 1.8 s,用户直接挂断
一句话:规则引擎在“长尾问题+高并发”面前彻底失灵。
技术选型:Rasa、Dialogflow 与 LangChain 的“三角恋”
我把主流方案拉到一起跑分,结论先给:
- Rasa 开源可私有部署,意图识别 F1 0.91,但中文预训练模型弱,需要 5 k+ 标注样本才能收敛
- Dialogflow 自带 Google 全家桶,上下文保持优秀,单轮 120 ms,可云端黑盒+按调用收费,日均 10 k 次就要 400 元,且国内网络延迟 300 ms 起跳
- LangChain 不绑定模型,换 ChatGLM3、Baichuan 都行,链式写法把“意图识别+槽位抽取+答案召回”拆成三块,代码级可调试,最合“AI 辅助开发”口味
最终拍板:LangChain + ChatGLM3-6B + 自研插件,成本可控,调试透明。
核心实现:LangChain 链式流水线
1. 意图识别链
# intent_chain.py import asyncio from langchain.chains import LLMChain from langchain.prompts import ChatPromptTemplate from langchain.chat_models import ChatOpenAI template = """ 你是客服意图识别器,把用户问题映射到以下类别之一: - 退货进度 - 修改地址 - 优惠券使用 - 其他 只返回类别名,不要解释。 用户:{query} """ prompt = ChatPromptTemplate.from_template(template) llm = ChatOpenAI(temperature=0, max_tokens=10) intent_chain = LLMChain(llm=llm, prompt=prompt) async def recognize_intent(query: str) -> str: """异步意图识别,防止 I/O 阻塞""" return await intent_chain.arun(query)2. 对话状态管理(Redis 缓存会话)
# session_store.py import redis.asyncio as aioredis import json class SessionStore: def __init__(self): self.pool = aioredis.from_url("redis://localhost:6379/1", decode_responses=True) async def get_state(self, uid: str) -> dict: data = await self.pool.hget("chat_session", uid) return json.loads(data) if data else {"hist": [], "slots": {}} async def set_state(self, uid: str, state: dict, ex: int = 1800): await self.pool.hset("chat_session, mapping={uid: json.dumps(state)}, ex=ex)把用户 ID 当 key,hist 存最近 4 轮对话,slots 存槽位,TTL 30 min,内存占用 < 2 G。
3. 异步编排入口
# main.py async def chat(uid: str, query: str): state = await session_store.get_state(uid) intent = await recognize_intent(query) answer = await dispatch(intent, query, state) # 下游链略 state["hist"].append({"q": query, "a": answer}) await session_store.set_state(uid, state) return answeruvicorn 4 worker 压测,单机 QPS 稳在 280,P95 延迟 420 ms,比规则引擎快 4 倍。
生产考量:压测、加密与合规
性能数据
JMeter 5.5,200 线程循环 5 min:
- QPS 峰值 312,CPU 68%,GPU 42%
- 平均响应 380 ms,P99 650 ms
- 内存占用 3.8 G,显存 5.2 G(ChatGLM3-6B INT4)
安全方案
- 传输:TLS 1.3 + AES-256-GCM,HSTS 强制
- 存储:PII 字段(手机、地址)AES 加密,密钥放 Hashicorp Vault,轮换周期 90 天
- 合规:PCI DSS 3.2.1 要求“支付卡数据不存储”,对话侧仅保留 token 化后的订单号,正则脱敏如下:
import re def mask_sensitive(text: str) -> str: text = re.sub(r"\d{15,16}", "****", text) # 银行卡 text = re.sub(r"1[3-9]\d{9}", "****", text) # 手机号 return text避坑指南:冷启动与敏感词
FAQ 知识库向量化优化
冷启动没数据,向量检索召回率只有 42%。解法:
- 把历史 5 万条客服记录清洗后做 EDA,提取 1 200 高频标准问
- 用 text2vec-base-chinese 一次性编码,存入 FAISS IndexFlatIP,余弦相似度 Top5 命中率提到 78%
- 每周增量微调模型,学习率 2e-5,3 个 epoch,召回率再涨 6 个百分点
敏感信息过滤
除正则外,再挂一层敏感词库 1.3 万条,DFA 算法 0.3 ms 内完成匹配,误杀率 < 0.5%。
延伸思考:Fine-tuning 让回答更“垂直”
通用 LLM 对“延保换新”政策回答得太泛,Fine-tuning 后准确率从 64% → 89%。流程:
- 标注 2 200 条“场景-问题-标准答案”三元组,按 8:1:1 切
- LoRA 微调,rank=8,alpha=16,batch=4,训练 3 h,显存 11 G
- 评测集 BLEU 提升 5.4,人工抽检满意度 +17%
如果数据量再大,可试 RLHF,把“用户是否点赞”当奖励,持续迭代。
整套流程跑下来,最深刻的体会:LLM 不是“万能答案机”,而是“超级乐高”。把意图链、状态机、向量召回、安全合规这些小积木拼好,才能在高并发场景里既稳又快。下一步,想把多模态能力也接进来,让用户直接甩图就能问“这款鞋有 42 码吗?”——客服的终局,大概是“无感”吧。