☰
LLM 微调实战(10):端到端实战:从 0 训练一个行业客服模型并跑通
2026/10/1 6:34:58 网站建设 项目流程

承接:最后一课不讲新机制,只把项目走一遍

第九课把知识的存放位置分完拣——事实进库、行为进权重、改写独立成层——系列的组件就全齐了。终章把它们装上整车:一家家电售后公司(空调/冰箱/洗衣机 400 热线加几万名安装维修师傅的派单网络)立项"装修助手",从 0 训一个行业客服模型并推到生产。本篇按第一篇的立项算账、第二/五篇的数据、第三/四篇的训练、第六篇的评测、第七篇的防遗忘、第八篇的上线、第九篇的混合架构走一条完整流水线;两个实验承担"排期"和"过程监控"这两件在真实项目里最容易拍脑袋的事。本机以确定性模拟演示,生产用 PyTorch/PEFT 与真实训练集群,机制一致。

第 0 步:先算账,再动数据

立项评审只问三个问题,全在第一篇的框架里回答:知识变得快不快(配件价格每季度调、活动话术每周调——快变内容一律走检索库,RAG 底座保留);行为要不要稳定("先安抚→问型号→给上门时段→超范围转人工"这套处置骨架是九万条真实工单里长出来的,prompt 里写三千字也压不稳,进权重);钱够不够(续训 + LoRA 的量级,第一篇算过是继续预训练的几十分之一)。拍板结论:基座 + LoRA 行为层 + RAG 知识层。

数据侧按第二/五篇的流水线走一遍,只列关键数字:48,000 条 SFT 样本 = 12,000 条真实工单改写(保留口语残缺、情绪、报错型号这些"像真实业务"的毛边)+ 30,000 条合成(模板数 12 套起步,第二篇的坍塌实验要求)+ 6,000 条通用保持数据(第七篇的防遗忘配额)。MinHash-LSH 在 0.60 阈值下做语义级去重,规则瀑布过滤后保留约 77.5%,混合配比用第五篇的水填充采样、投诉类顶到安全上限。评测集 150 题从第六篇 bootstrap 结论里选:只用于"过/不过"门禁够用,但要论证 +0.04 级别的小增益得上 600 题——这次上线只需要门禁,150 题锁死后从训练数据物理隔离。

实验一:把排期算出来,不是猜出来

硬件是采购部批下来的一张 4090——第四篇的 QLoRA 预算表里 7B 模型 4bit 基座 + r32 adapter 峰值约 5.5GB,显存没有悬念,悬念全在时间:老板问"什么时候能看效果",得有一张排期表。训练超谱是标准配方:线性 warmup 一百步防开局崩塌,之后 cosine 衰到峰值的十分之一;ETA 用第一篇的 6ND 公式折算有效算力。

"""端到端排期: 训练预算与学习率调度表(线性 warmup + cosine), 确定性算术。"""importmath SAMPLES,SEQ=48000,1024BS,GA,EPOCHS=4,8,2EFF=BS*GA STEPS=SAMPLES//EFF*EPOCHS# 优化器步数PEAK_LR,WARMUP,MIN_RATIO=2e-4,STEPS//30,0.1deflr_at(step):ifstep<WARMUP:returnPEAK_LR*(step+1)/WARMUP prog=(step-WARMUP)/max(1,STEPS-WARMUP)c=0.5*(1+math.cos(math.pi*prog))returnPEAK_LR*(MIN_RATIO+(1-MIN_RATIO)*c)N,TF,UTIL=7e9,165e12,0.35# 4090 bf16 峰值 165T, 有效占用 35%tokens=0.0print("数据 %d 条 x %d token, 有效 batch %d, 共 %d 步, warmup %d 步"%(SAMPLES,SEQ,EFF,STEPS,WARMUP))print("%6s %10s %12s %10s"%("step","lr","累计token","ETA小时"))forstepinrange(1,STEPS+1):tokens+=EFF*SEQifstep<=3orstep%(STEPS//10)==0orstep==WARMUP:secs=6*N*tokens/(TF*UTIL)print("%6d %10.2e %12s %9.1f"%(step,lr_at(step),"%.1fM"%(tokens/1e6),secs/3600))total_secs=6*N*tokens/(TF*UTIL)print("总预算: %.1fM token | %.1f 单卡小时 | 每 300 步存 checkpoint 共 %d 个"%(tokens/1e6,total_secs/3600,STEPS//300))

运行输出:

数据 48000 条 x 1024 token, 有效 batch 32, 共 3000 步, warmup 100 步 step lr 累计token ETA小时 1 4.00e-06 0.0M 0.0 2 6.00e-06 0.1M 0.0 3 8.00e-06 0.1M 0.0 100 2.00e-04 3.3M 0.7 300 1.98e-04 9.8M 2.0 600 1.87e-04 19.7M 4.0 900 1.68e-04 29.5M 6.0 1200 1.43e-04 39.3M 7.9 1500 1.15e-04 49.2M 9.9 1800 8.59e-05 59.0M 11.9 2100 5.95e-05 68.8M 13.9 2400 3.84e-05 78.6M 15.9 2700 2.47e-05 88.5M 17.9 3000 2.00e-05 98.3M 19.9 总预算: 98.3M token | 19.9 单卡小时 | 每 300 步存 checkpoint 共 10 个

三个工程结论直接从表里读。其一,近 20 个单卡小时意味着"晚上挂任务早上看评测"的节奏可行,评审会上给的承诺是 48 小时内交出第一版可评测权重(含导出与冒烟),而不是"下周"。其二,warmup 结束正好在 0.7 小时处——前十分钟是崩塌高危窗口,人必须在场看 loss,之后可以放心睡。其三,若排期超预算,砍的顺序有讲究:先上序列打包(padding 里的空转是白钱,第五篇说过),再降采样温度换的数据多样性(第二篇的坍塌实验),最后才考虑减 epoch——数据资产比机时贵,这条纪律从头贯彻到尾。每 300 步一个 adapter checkpoint,LoRA 权重按第三篇的合并等价性随时可并入导出,10 个候选点给实验二的回滚留足了余地。

实验二:过程监控的三个肌肉记忆

训练挂上之后真正的功夫在监控:坏批次要跳过、早停要触发、交付要用最优而不是最新。评测纪律来自第六篇——固定 150 题留出集、每 300 步跑一次、分桶看明细;本实验把这条纪律具象成决策日志:

"""训练过程监控: loss 曲线 + checkpoint 选择(坏批次跳过 + 早停 + 回滚最优), 确定性模拟。"""importmathimportrandom rnd=random.Random(487)STEPS,EVAL_EVERY,PATIENCE=3000,300,2SPIKES={450:3.4,1200:3.1}# 步号 -> 该批 loss, 脏数据批次deftrain_loss(step):base=0.62+1.45*math.exp(-step/1100)returnbase+rnd.uniform(-0.025,0.025)defvalid_loss(step):return0.78+0.30*((step-1800)/1400)**2+rnd.uniform(-0.004,0.004)best,best_step,bad_tail=float("inf"),0,0log=[]forstepinrange(EVAL_EVERY,STEPS+1,EVAL_EVERY):forsinrange(step-EVAL_EVERY+1,step+1):ifsinSPIKES:log.append("step %4d 检测到坏批次 loss=%.1f grad_norm 超阈 -> 跳过该批次更新"%(s,SPIKES[s]))vl=valid_loss(step)ifvl<best-1e-4:best,best_step,bad_tail=vl,step,0tag="<- 最优 ckpt-%d"%stepelse:bad_tail+=1tag="(连续 %d 次未改善)"%bad_tail log.append("ckpt-%4d valid=%.3f train=%.3f %s"%(step,vl,train_loss(step),tag))ifbad_tail>=PATIENCE:log.append("step %4d patience 耗尽 -> 早停"%step)breakprint("\n".join(log))print("最终交付: 回滚到 %d 步的 checkpoint (valid=%.3f), 而非最新权重"%(best_step,best))

运行输出:

ckpt- 300 valid=1.127 train=1.741 <- 最优 ckpt-300 step 450 检测到坏批次 loss=3.4 grad_norm 超阈 -> 跳过该批次更新 ckpt- 600 valid=1.001 train=1.451 <- 最优 ckpt-600 ckpt- 900 valid=0.907 train=1.244 <- 最优 ckpt-900 step 1200 检测到坏批次 loss=3.1 grad_norm 超阈 -> 跳过该批次更新 ckpt-1200 valid=0.837 train=1.110 <- 最优 ckpt-1200 ckpt-1500 valid=0.796 train=0.982 <- 最优 ckpt-1500 ckpt-1800 valid=0.783 train=0.901 <- 最优 ckpt-1800 ckpt-2100 valid=0.792 train=0.821 (连续 1 次未改善) ckpt-2400 valid=0.832 train=0.801 (连续 2 次未改善) step 2400 patience 耗尽 -> 早停 最终交付: 回滚到 1800 步的 checkpoint (valid=0.783), 而非最新权重

日志里三处都值得停一下。450 步和 1200 步的 loss 尖峰对应两个漏网的脏数据批次(第二批的瀑布过滤漏了一条超长截断工单、一条含内部测试标记的样本)——梯度范数超阈跳过更新的兜底必须有,因为过滤永远有漏网之鱼,而一个坏批次足以把 adapter 拖进坏 basin 且事后极难归因。1800 步之后训练 loss 一路还在降(0.901→0.801)、valid 却回头爬升——这条 U 形曲线就是第六篇说的记忆反超泛化的影子,只看训练曲线的人会在这里兴高采烈地跑满 3000 步。patience=2 在 2400 步止损,省下的 600 步约 4 个单卡小时是小事,重要的是交付决策:上线的是 ckpt-1800 的哈希,不是"最新"——第八篇 MANIFEST 三件套里 model 条目从此有了准确含义。

流水线的后半段:每一步都引用前面的编号

ckpt-1800 并入基座导出 bf16 后,六道关卡按系列编号依次过:第六篇三层评测(格式合规率 100%→ROUGE-L→rubric 均分,投诉与转人工两桶单看明细,防止均分掩盖短板);第七篇回归——通用 50 题小集测得闲聊与改写能力下降约一成、未消失,在混训 12% 保持数据下符合预期,若还要叠加英文文案能力就回到任务算术的 λ 扫描;第八篇发布——LoRA 合并导出、SHA256 清单入版本库,本次属于"数据配方小改 + 模板未动"定 minor 版本,vLLM 上线后按连续批处理容量表压到 P95 达标;第九篇分工验收——配件价格一律走检索引用、回答里带出处编号,权重里查不到任何一条原文政策。灰度 5% 流量一周:金丝雀题集每日复测、抽检 5% 人审,转人工率从 RAG 基线的 31% 降到 17%,端到端解决率抬升十几个点,全量放行。

十个常见坑总登记表

  • 排期靠猜:不做 6ND 预算就承诺"下周上线",或反过来把砍预算的刀落在数据上(实验一的反面)。
  • 只看训练 loss:U 形拐点之后多训的每一小时都在加深过拟合(实验二现场演示)。
  • 交付"最新权重":不回填最优 checkpoint,回滚时无哈希可指(第八篇纪律)。
  • 聚合指标糊弄门禁:均分达标、投诉桶崩盘,分桶明细才是真相(第六篇)。
  • 把 FAQ 背进权重:知识库改版即作废,第二版训练开始就输了(第九篇)。
  • 坏批次只报警不跳过:grad_norm 尖峰后 loss 长期抬升,事后查不到原因(第二篇过滤 + 本篇兜底)。
  • 通用能力不做回归:客服答得很好,但内部同事让它写周报时全线胡说(第七篇)。
  • 模板/数据配方不进版本管理:三周后没人说得清 0.783 和 0.832 差在哪(第八篇 MANIFEST)。
  • 评测集被合成数据污染:同模板生成物漂进留出集,分数虚高(第二篇去重的另一重动机)。
  • 上线即散场:金丝雀与抽检断档,漂移在第四周才被客户发现(第九篇季度复审)。

系列收束:微调是五本账,不是一个技巧

十篇走完,回到第一篇的那个问题——什么时候该微调——现在有了完整答案:微调买的不是"更聪明的模型",而是稳定的行为,代价要用五本账结清:算力账(第一/三/四篇:6ND、LoRA 省优化器态、QLoRA 省权重)、数据账(第二/五篇:去重阈值、过滤通过率、模板多样性与配比)、评测账(第六篇:固定护城河题集、置信区间、分桶明细)、遗忘账(第七篇:保持数据配额、混训与合并的取舍)、运维账(第八/九篇:版本清单、KV 容量、预填充税与窗口预算)。会算账的团队在第一次评审就杀掉不该做的微调,不会算账的团队在第十次事故复盘会上才明白为什么模型"越训越怪"。愿这十篇陪你走完从 0 到 1,也陪你省下来自学费的那三笔弯路。

参考来源

  • Hugging Face TRL · SFT Trainer 文档:https://huggingface.co/docs/trl/en/sft_trainer
  • The Llama 3 Herd of Models(后训练全流程工程报告):https://arxiv.org/abs/2407.21783
  • OpenAI Fine-tuning 使用指南:https://platform.openai.com/docs/guides/fine-tuning
  • Stanford CS336 Language Modeling from Scratch:https://cs336.stanford.edu/
  • vLLM 部署与量化推理文档:https://docs.vllm.ai/en/stable/

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询