背景痛点:规则引擎的“天花板”
做智能客服的同学都懂,早期用正则+关键词的“小水管”方案,遇到“超长尾”问题就堵死。
- 用户一句“我昨天买的那台白色带烘干功能的洗衣机,门封圈发霉了能换货吗?”——实体多、属性多,规则瞬间爆炸。
- 多轮对话更惨,状态机写到 200+ 节点后,维护成本指数级上升;稍有改动,QA 同学就要重新跑全量回归。
浅层 AI(FastText、TextCNN)虽然把意图识别 F1 从 86% 拉到 90%,但仍旧靠人工标注“喂”数据,一旦业务上新,模型又得重新训。响应延迟也卡在 600 ms 下不去——GPU 利用率低,batch 小,CPU 预处理又重。
一句话:规则维护累、模型迭代慢、长尾覆盖差、多轮状态乱。
技术选型:让大模型“跑分”
我们把 GPT-3.5-Turbo、Claude-v1.3、自研 6B 中文模型放在同一赛道,用 1 万条真实在线日志做 benchmark,指标如下:
| 模型 | 意图准确率 | 实体抽取 F1 | 平均延迟 | 输入+输出 Token/轮 | 幻觉率 |
|---|---|---|---|---|---|
| GPT-3.5 | 94.2% | 91.7% | 850 ms | 180 | 3.1% |
| Claude | 93.8% | 90.4% | 720 ms | 165 | 2.4% |
| 自研 6B | 91.5% | 89.0% | 380 ms | 140 | 5.8% |
业务对延迟敏感,最终采用“Claude+缓存”做主力,GPT 做兜底,自研模型当“灰度探针”继续迭代。
核心实现:FastAPI + LangChain + 状态机
1. 异步推理服务骨架
# main.py 类型注解 + 异常处理已补齐 from fastapi import FastAPI, HTTPException from pydantic import BaseModel import asyncio, time, logging from typing import List, Dict app = FastAPI(title="LLM-CS-Serving") class Query(BaseModel): uid: str text: str session_id: str @app.post("/chat") async def chat(q: Query) -> Dict[str, str]: try: ans = await llm_agenerate(q.text, q.session_id) # 异步生成 return {"answer": ans, "uid": q.uid} except Exception as e: logging.exception("llm error") raise HTTPException(status_code=500, detail=str(e)) async def llm_agenerate(text: str, sid: str) -> str: # 省略缓存查询,先直接调 Claude return await claude_client.acomplete(text)FastAPI 的async/await能把 I/O 等待降到 50 ms 以内,GPU 纯计算时间 300 ms,整体 P99 延迟 450 ms。
2. RAG 知识库增强
LangChain 负责召回+重排,代码片段如下:
# rag_chain.py from langchain.schema import Document from langchain.chains import RetrievalQA from langchain.vectorstores import FAISS from langchain.embeddings import HuggingFaceEmbeddings from langchain.llms import ClaudeLLM embed = HuggingFaceEmbeddings("shibing624/text2vec-base-chinese") vectordb = FAISS.load_local("faq_faiss", embed) retriever = vectordb.as_retriever(search_kwargs={"k": 5}) qa_chain = RetrievalQA.from_chain_type( llm=ClaudeLLM(), chain_type="stuff", retriever=retriever, return_source_documents=True ) def rag_answer(query: str) -> str: return qa_chain.run(query)时间复杂度:FAISS 检索 IP 距离为O(k·log n),k=5,n=30 万条 FAQ,单次 15 ms;重排再送 LLM,总耗时 120 ms。上线后“知识类” query 首句命中率提升 40%。
3. 分布式对话状态机
多轮状态不再靠单例字典,而是 Redis Hash + 事件溯源:
- key:
cs:state:${session_id} - field:
turn,slots,last_intent - 过期时间 30 min,自动清理。
状态转移函数写成无服务函数(OpenFaaS),水平扩容 500 pod 无压力。
性能优化:让 GPU 像“弹簧”
- 模型量化:Claude 官方已支持 8-bit,显存从 16 GB → 8 GB,单卡并发从 8 → 18。
- 结果缓存:对“订单查询”类模板化问题,用 Redis 缓存 <query, answer>,TTL=300 s,缓存命中率 28%,平均延迟再降 120 ms。
- 负载均衡:Nginx + Consistent load 策略,按 GPU 显存余量动态加权;高峰时 HPA 根据 QPS 自动扩容,30 s 内拉起新 Pod。
避坑指南:幻觉 & 合规
- 幻觉缓解:
- 温度系数 0.3 + Top-p 0.85,强制事实性提示模板“请根据以下已知信息回答”。
- 引入“自洽性”投票,同一问题推理 3 次,多数答案胜出,幻觉率再降 1.2%。
- 敏感过滤:
- 正则前置 + 敏感词树 10 万条,2 ms 内完成初筛;
- 再调“内容审核”小模型(2-layer CNN)做二分类,召回 99.3%,误杀 <0.5%。
- 日志脱敏:手机号、地址用正则打码,落库前再 AES 加密,合规审计直接拿“脱敏+加密”双保险。
实战小结
- 意图识别准确率从 90% → 94%+,长尾问题覆盖率提升 35%。
- 平均响应 450 ms,P99 800 ms,比旧系统快 30%。
- 标注成本下降 50%,新 FAQ 只需写文档,自动入库生效。
开放讨论
用户聊嗨了经常“意图漂移”——比如从“查订单”突然跳到“你们家洗衣机能不能洗球鞋”。你的系统是怎么及时发现并拉回主线的?欢迎留言聊聊你的方案!