传统客服的“三座大山”
做 ToB 售后系统三年,最怕听到的就是“客户又投诉排队 5 分钟没人理”。
传统人工客服的痛点其实就三句话:
- 响应延迟:排队 + 查知识库,平均 30 s 起步,高峰期直奔 3 min。
- 人力成本:一线坐席年包 10 w+,夜班、节假日双倍工资,毛利直接被吃掉。
- 服务时段:肉身下班就下线,全球客户时区不同,只能“望单兴叹”。
AIGC 火了以后,老板一句“能不能让模型顶 80% 咨询?”——于是就有了这套实战笔记。
一、选型:GPT-3.5/4、Claude 还是“小而美”本地模型?
先给出我们在 200 QPS 场景下跑出的横向对比,指标取 Intent-F1 + 延迟 P99,硬件统一 A10。
| 模型 | 意图 F1 | 首 token 延迟 | 成本(1k query) | 备注 |
|---|---|---|---|---|
| GPT-4 | 0.965 | 1.8 s | 60 $ | 贵,但少样本就能到 99% |
| GPT-3.5 | 0.941 | 0.9 s | 4 $ | 性价比首选,需微调 prompt |
| Claude-v1.3 | 0.948 | 1.2 s | 5 $ | 长上下文好,审核松 |
| ChatGLM3-6B(本地) | 0.924 | 120 ms | 0.3 $ | 需要 4×A10,支持私有化 |
结论:
- 对公 SaaS 优先 3.5,遇到“刁钻长单”再路由到 4。
- 金融、医疗私有化必须本地,ChatGLM3-6B + LoRA 微调 2 k 条就能追平 0.94 F1。
二、系统总览:一张图看懂链路
- Gateway:统一鉴权、灰度、流控。
- 预处理:分句、敏感词、指代消解。
- 意图中心:向量检索 + 精排模型,输出 TOP-3 意图 + 置信度。
- 对话引擎:多轮状态管理,槽位提取,调用业务 API。
- 回答生成:Prompt 模板 + 动态 Few-shot,支持“安全复读”兜底。
- 反馈闭环:用户点踩/点赞 → 回流标注池,日更微调。
三、核心代码:Python 可运行版
下面给出最简化的“对话系统骨架”,依赖 openai>=1.0,fastapi,uvicorn。
把业务敏感部分抽掉,保留“预处理 → 模型 → 后处理”三段,可直接python main.py跑起。
# main.py import asyncio, time, os from fastapi import FastAPI, HTTPException from pydantic import BaseModel import openai openai.api_key = os.getenv("OPENAI_KEY") app = FastAPI(title="AIGC-CS-Demo") class Msg(BaseModel): uid: str text: str history: list[str] = [] # 1. 预处理:敏感词 + 长度截断 def pre_process(text: str) -> str: blacklist={"暴雷","垃圾"} # 真实场景用 DFA 树 for w in blacklist: text=text.replace(w,"*") return text[:500] # 2. 意图识别(这里简化掉向量检索,直接让 GPT 出意图) async def get_intent(text: str) -> str: resp = await openai.ChatCompletion.acreate( model="gpt-3.5-turbo", messages=[{"role":"system","content":"你是一名客服意图识别器,只输出下列之一:订单|退款|账户|其他"}, {"role":"user","content":text}], temperature=0.0, max_tokens=5 ) return resp.choices[0].message.content.strip() # 3. 回答生成(带历史) async def generate_answer(text: str, hist: list[str], intent: str) -> str: hist_str = "\n".join(hist[-4:]) # 只取最近 4 轮 prompt = f"你是客服机器人。\n历史对话:{hist_str}\n用户问:{text}\n请用友好语气回答,字数≤150。" resp = await openai.ChatCompletion.acreate( model="gpt-3.5-turbo", messages=[{"role":"system","content":prompt[:1500]}], temperature=0.5, max_tokens=150 ) return resp.choices[0].message.content # 4. 总入口 @app.post("/chat") async def chat(msg: Msg): try: t0 = time.time() text = pre_process(msg.text) intent = await get_intent(text) answer = await generate_answer(text, msg.history, intent) # 记录耗时 cost = int((time.time()-t0)*1000) return {"intent":intent,"answer":answer,"cost_ms":cost} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) # 5. 启动 if __name__=="__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)跑通后,用locust一压,空载 P99 延迟 650 ms;加缓存后直接砍到 120 ms,后面会说细节。
四、性能优化三板斧
- 缓存:
- Redis 缓存“意图 → 答案”模板,TTL 300 s,命中率 42%。
- 向量缓存,FAISS 索引放内存,10 w 条 FAQ 搜 5 ms。
- 异步:
- 所有外部 IO(SQL、API)走
asyncio.gather,线程池 size=200,防止任何同步阻塞。
- 所有外部 IO(SQL、API)走
- 负载均衡:
- K8s HPA 按 GPU 利用率 70% 扩容;
- 同地域多可用区 + 一致性冷备,防止云厂商级故障。
再上一个进阶技巧——流式返回:
把stream=True打开,前端拿到首包 200 ms 就能渲染“输入中”动画,体感延迟再降 30%。
五、生产环境踩坑实录
- 模型冷启动:
容器镜像里提前torch.compile导出.pt2,启动从 90 s → 12 s;再配合preStophook 延迟下线,实现平滑发布。 - 敏感词:
仅用正则误杀高,采用“DFA 树 + 人工复核队列”,日活 50 w 消息误杀率压到 0.05%。 - 版本灰度:
按用户尾号灰度 5%,对比点踩率 >0.8% 立即回滚,防止“模型幻觉”导致公关事件。 - 日志别省钱:
把 prompt、回答、耗时、用户反馈全落盘,S3 存 30 天,方便后续微调 & 审计。
六、三个开放问题,留给深夜思考
- 多轮对话状态爆炸:当槽位超过 15 个、可跳过时,如何既保准又不让用户填表?
- 小样本冷启动:新客户只有 200 条对话,如何结合数据增强 + Prompt 学习把 F1 拉到 0.95?
- 模型“答非所问”检测:除了置信度,还有无实时指标能 100 ms 内发现“幻觉”并触发人工接管?
七、小结
把 AIGC 塞进客服,不是“调个接口”那么简单;从选模型、搭链路、压性能到守合规,每一步都是填坑。
上面这套方案已在我们内部扛住日均 80 w 消息,平均响应 180 ms,意图准确率 99.1%,替一线同学省出 60% 人力。
如果你也在做智能客服,欢迎交流更好的点子——毕竟模型一日千里,今天的 SOTA 明天就可能被拍在沙滩上。祝各位调试顺利,少踩坑,多下班。