背景痛点:传统客服的“三板斧”为啥不灵了
做客服系统的老同学都踩过这些坑:
- 关键词规则写到最后成“蜘蛛网”,用户一句“我密码好像不对,但好像又对了”直接原地爆炸。
- 多轮对话靠 if-else 硬写,用户中途插一句“等等,我先接个电话”,回来就找不到北。
- 知识库检索靠 Elasticsearch 关键词打分,Top10 里 8 条不相关,客服小姐姐被用户吐槽“答非所问”。
大模型带来的最大变革是“语义理解”从规则升维到向量,一句话:它听得懂人话,也能说人话。于是,我们终于可以把“写规则”变成“写提示”,把“穷举 FAQ”变成“向量召回+LLM 生成”,维护成本直线下降,对话体验指数级上升。
技术选型:三条路线谁更适合你
我踩坑三个月,把主流方案拉出来跑了一遍,结论先给:
| 维度 | Rasa+Transformer | LangChain+LLM API | 自研微调 |
|---|---|---|---|
| 成本 | 低(开源) | 中(按 token 计费) | 高(卡+人) |
| 效果 | 意图识别 85%,泛化一般 | 语义理解 95%,多轮顺滑 | 领域 98%,需大量标注 |
| 维护 | 状态机+规则,依旧复杂 | 提示即配置,热更新 | 数据回流+重训,周期长 |
| 适用场景 | 预算紧、私有化 | 90% 公司首选 | 头部大厂、强定制 |
结论:没 GPU 农场、没 10 人算法团队,直接选 LangChain+LLM API,省钱又快速。
核心实现:30 分钟跑通一条对话链
1. 对话状态机:用 LangChain 写比写 if-else 爽
# chat_agent.py from langchain.memory import ConversationBufferWindowMemory from langchain.chains import ConversationChain from langchain.prompts import PromptTemplate prompt = PromptTemplate( input_variables=["history", "input"], template=""" 你是客服小助手,请根据上下文回答,若需要查询订单请返回格式:@@查询订单{订单号}@@ 历史对话: {history} 用户:{input} 客服: """ ) memory = ConversationBufferWindowMemory(k=6) # 只保留最近 6 轮,省 token chain = ConversationChain( llm=chat_model, memory=memory, prompt=prompt, verbose=True )6 轮窗口是线上反复 AB 出来的 sweet spot:再长就爆 token,再短就失忆。
2. 异步 FastAPI 接口:高并发不崩的秘诀
# main.py from fastapi import FastAPI, Request, HTTPException from asyncio import wait_for, TimeoutError import chat_agent app = FastAPI() SE屁哦,Semaphore = asyncio.Semaphore(200) # 硬限流 200 并发 @app.post("/chat") async def chat(req: Request): body = await req.json() uid = body["uid"] query = body["query"] async with SE屁哦,Semaphore: try: answer = await wait_for( chat_agent.chain.arun(input=query), timeout=5.0 # 超过 5s 直接 503 ) return {"uid": uid, "answer": answer} except TimeoutError: raise HTTPException(status_code=503, detail="timeout")要点:
- 用信号量做“硬限流”,比后期扩容便宜。
- 5 秒超时是用户体验拐点,再长用户就挂机。
生产考量:真刀真枪上线要注意啥
1. 压力测试:1000 TPS 怎么跑
工具:locust + 自建 mock LLM(固定返回,节省 token 钱)。
脚本核心:
from locust import HttpUser, task, between class ChatUser(HttpUser): wait_time = between(0.1, 0.3) @task def chat(self): self.client.post("/chat", json={"uid": "u001", "query": "我的订单到哪了"})结果:
- 200 并发,P99 延迟 1.2s,错误率 0%
- 1000 并发,P99 延迟 4.8s,错误率 2%(超时)
优化:把 LLM 调用拆成独立微服务,再加一层 Redis 缓存热点问题,TPS 提到 1200 错误率降到 0.5%。
2. 安全:敏感词与数据脱敏双保险
敏感词:开源库“ahocorasick”+ 自定义词表 3000 条,CPU 增加 <1ms。
脱敏:正则手机号、身份证、银行卡,打码成“*”。注意先脱敏再送 LLM,否则模型日志里全是明文,等保审计直接挂。
避坑指南:省下的都是利润
1. Token 省钱三板斧
- 提示模板留空位,别让“你好谢谢”占 token。
- 动态压缩历史:用户闲聊 20 轮,只保留与业务实体相关的 6 轮(用语义相似度过滤)。
- 缓存高频问题:Redis 存“query→answer”键值,命中率 35%,直接省 35% token 钱。
2. 上下文窗口压缩策略
长对话用“摘要+最近 3 轮”组合:
from langchain.chains import LLMChain summary_chain = LLMChain( llm=chat_model, prompt=PromptTemplate( input_variables=["long_history"], template="把以下对话用 50 字总结:\n{long_history}" ) )先摘要,再拼 3 轮原文,长度砍半,效果不降。
3. 冷启动 FAQ 知识库怎么来
- 把旧客服 Excel 导出,一列问题一列答案,用 text-embedding-ada-002 批量向量化。
- 线上用户日志每周跑聚类,提取高频新意图,人工审核后入库,3 周就能把覆盖率从 60% 提到 85%。
下一步优化方向(思考题)
- 如何把“多模态”引入——用户上传截图找订单,系统直接 OCR+对话返回物流状态?
- 当 LLM API 成本再降 50%,是否还需要本地缓存?缓存命中率与实时性如何权衡?
- 如果公司要求 100% 私有化,开源模型(如 ChatGLM3)在 4 张 4090 上能否顶住 500 TPS?需要做哪些蒸馏或量化?
把这三个问题想透,你的智能客服就真正从“能用”进化到“好用”了。祝各位上线不踩坑,token 账单永远温柔。