EndNote参考文献样式安装与微调全指南:从下载到排错
2026/9/25 4:52:45
谛听客服智能体开发实战:AI辅助开发中的架构设计与性能优化
去年双十一,我们内部客服系统被瞬间 3w+ 并发搞到崩溃:
核心矛盾就三件事:
我们把 21 个月的真实日志(2.4M 条)按 7:1:2 切成训练、验证、测试,在同一台 2080Ti 上跑三种方案:
| 方案 | 准确率 | TP99 延迟 | 代码行数 | 备注 |
|---|---|---|---|---|
| 规则引擎(Esper + DSL) | 72% | 120ms | 3.2k | 规则>400 条后冲突爆炸 |
| 传统 ML(FastText + LR) | 81% | 45ms | 1.1k | 特征工程占 60% 工作量 |
| Fine-tune BERT-base | 91.4% | 280ms | 380 | 后面会降到 90ms |
结论:
@startuml !define MS(name,desc) rectangle name as "desc" <<MicroService>> MS(gateway,API Gateway) -> MS(dm,Dialog Manager) MS(dm) -> MS(nlu,NLU Service) MS(nlu) -> MS(cache,Redis Cache) MS(dm) -> MS(state,State Store) MS(nlu) -> MS(bert,BERT Inference) MS(bert) -> GPU @enduml下面这段代码同时解决“重复请求”和“缓存”两个问题,基于 Flask 2.2 + gevent,单进程 QPS 从 200 提到 800。
# middleware.py import hashlib, json, redis, gevent from flask import Flask, request, jsonify from functools import wraps r = redis.Redis(host='127.0.0.1', decode_responses=True) app = Flask(__name__) def cache_key(uid, text): return f"nlu:{uid}:{hashlib.md5(text.encode()).hexdigest()}" def async_cache(ttl=60): def decorator(f): @wraps(f) def wrapper(*args, **kwargs): uid = request.json['uid'] text = request.json['text'] key = cache_key(uid, text) ret = r.get(key) if ret: return jsonify(json.loads(ret)) # 异步防重 lock = f"lock:{key}" if r.set(lock, 1, nx=True, ex=5): resp = f(*args, **kwargs) r.setex(key, ttl, json.dumps(resp)) r.delete(lock) return jsonify(resp) else: # 轮询等待 while not r.get(key): : gevent.sleep(0.05) return jsonify(json.loads(r.get(key))) return wrapper return decorator @app.route('/nlu', methods=['POST']) @async_cache(ttl=120) def nlu(): # 实际调用 BERT 推理 return {'intent':'Refund','slots':{'order_id':None}}时间复杂度:
数据增强:
类别不平衡:
# train.py from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer, BertForSequenceClassification, AdamW import torch, json, random, numpy as np from sklearn.utils.class_weight import compute_class_weight class IntentDataset(Dataset): def __init__(self, path): with open(path) as f: self.data = [json.loads(l) for l in f] self.tok = BertTokenizer.from_pretrained('bert-base-chinese') def __len__(self): return len(self.data) def __getitem__(self, idx): text, label = self.data[idx]['text'], self.data[idx]['label'] enc = self.tok(text, padding='max_length', truncation=True, max_length=64, return_tensors='pt') return enc['input_ids'].squeeze(), enc['attention_mask'].squeeze(), label def focal_loss(y_true, y_pred, gamma=2.0, alpha=None): ce_loss = torch.nn.functional.cross_entropy(y_pred, y_true, reduction='none') p_t = torch.exp(-ce_loss) loss = alpha[ y_true ] * (1 - p_t) ** gamma * ce_loss return loss.mean() train = IntentDataset('intent_train.json') weights = compute_class_weight('balanced', classes=np.unique([d[2] for d in train]), y=[d[2] for d in train]) alpha = torch.tensor(weights, dtype=torch.float32) model = BertForSequenceClassification.from_pretrained('bert-base-chinese', num_labels=35) opt = AdamW(model.parameters(), lr=2e-5) dl = DataLoader(train, batch_size=64, shuffle=True) for epoch in range(3): for bid, (ids, mask, lbl) in enumerate(dl): opt.zero_grad() logits = model(input_ids=ids, attention_mask=mask).logits loss = focal_loss(lbl, logits, gamma=2.0, alpha=alpha) loss.backward() opt.step() torch.save(model.state_dict(), f'bert_intent_ep{epoch}.pt')训练耗时:2080Ti 上 3epoch ≈ 50min,最终准确率 91.4%,比交叉熵基线高 4.3%。
Lua 脚本保证“读-改-写”原子性,避免并发覆盖:
-- update_slots.lua local key = KEYS[1] local new = cjson.decode(ARGV[1]) local old = redis.call('GET', key) if not old then old = '{}' end old = cjson.decode(old) for k,v in pairs(new) do old[k]=v end redis.call('SET', key, cjson.encode(old), 'EX', 1800) return old在 DM 里调用:
slots = r.evalsha(redis.script_load(lua), 1, f"state:{uid}", json.dumps(new_slots))实验环境:T4 * 1,CUDA 11.8,torch 2.1
| batch_size | GPU-Util | 平均推理延迟 | 吞吐 |
|---|---|---|---|
| 1 | 22% | 280ms | 3.6/s |
| 8 | 65% | 95ms | 84/s |
| 16 | 83% | 90ms | 177/s |
| 32 | 89% | 92ms | 350/s |
线上最终选 16:延迟 <100ms,吞吐够用,留 10% GPU 给滚动发布。
BERT 小模型在封闭场景够用,但开放域外问题(“你们和竞品差在哪”)立马露馅。下一步计划:
把谛听从 0 到 1 推上线,最大的感受是:
如果你也在做客服智能体,希望这篇笔记能帮你少踩几个坑。代码已放到内部 GitLab,有需要随时交流,一起把 AI 真正落到业务一线。