本文为《Ai大模型训练教程》项目实战篇,详解如何从历史客服工单导出数据、完成脱敏清洗与质量筛选,构建对话式SFT数据集,并通过LoRA/QLoRA训练客服大模型,最后给出离线评估、抽检回流与上线MVP建议,形成可持续迭代的落地闭环。
项目目标与场景边界
在客服场景里,企业通常积累了大量“历史工单”:包括用户问题、客服回复、转单记录、处理结果、知识库链接等。这些数据天然适合用来构建对话式监督微调(SFT, Supervised Fine-Tuning)数据,让大模型学会“像你的客服一样回答”。本篇作为《Ai大模型训练教程》系列的实战文章,聚焦一个可落地的闭环:
- 从历史工单导出数据
- 清洗与脱敏
- 组装为对话 SFT 格式(含 system / user / assistant)
- 质量筛选与抽检
- 训练(LoRA/QLoRA)
- 离线评估与上线前验证
边界:本文重点是“从工单到 SFT 数据再到训练”的工程路径,不展开RAG/工具调用/多轮流程编排等更复杂体系(可作为后续扩展)。
数据源梳理:工单里到底有什么可用字段
不同工单系统字段命名不同,但常见结构类似:
ticket_id:工单IDchannel:来源(电话/IM/邮件/小程序)user_utterances:用户消息序列(可能被拆成多条)agent_utterances:客服回复序列timestamps:每条消息时间category:业务分类(退款/物流/售后/账户)status:已解决/未解决/升级resolution:最终解决方案摘要csat:满意度评分internal_notes:内部备注(通常不适合直接训练)attachments:图片/文件(本篇先不处理)
选择“可训练”的工单范围
为了提升 SFT 的“可学习性”,建议优先选:
- 已解决且有明确结果(status=resolved)
- 满意度高(csat ≥ 4/5)或“无负反馈”
- 对话轮次适中(比如 2~12 轮),太长的对话可截取有效片段
- 客服回复符合规范(有礼貌、结构化、无内部信息)
反之,以下工单先剔除或单独处理:
- 投诉拉扯、情绪对抗严重
- 需要强工具链/系统查询才能回答(订单状态实时查)但日志里没有结果
- 内部话术、权限信息、泄露渠道(如“我帮你后台改一下”)
数据治理第一步:脱敏与合规(必须先做)
历史工单往往含 PII(个人信息),训练前要脱敏。建议建立“脱敏规则清单 + 抽检机制”。
常见脱敏项
- 手机号、座机、邮箱
- 身份证/护照/银行卡
- 收货地址(省市区可保留到较粗粒度,详细门牌删除)
- 订单号/运单号(可保留前后2位,中间掩码)
- 用户姓名/昵称(统一替换为“用户”或“客户”)
脱敏策略示例(规则化替换)
13812345678→<PHONE>test@xx.com→<EMAIL>6101********1234→<ID>上海市浦东新区XX路88号→上海市浦东新区<ADDRESS>
建议的工程做法
- 先用正则 + 词典做第一轮规则脱敏
- 再用轻量 NER(可选)补漏(例如地址、人名)
- 进行人工抽检:每 1000 条抽 20 条,统计漏脱敏率
- 输出脱敏报告:字段覆盖率、命中次数、疑似未脱敏样本列表
从工单到“对话SFT样本”:格式设计与示例
SFT 的关键是:让模型看到“角色分工明确、上下文充分、回答可学习”的对话。
推荐的对话消息结构
以 OpenAI / ChatML 类似的结构为例(训练框架不同会有不同字段名,但思想一致):
system:客服身份、语气、边界、合规要求user:用户问题(可多轮)assistant:客服回复(可多轮)
System 提示词模板(建议固定且简洁)
在客服微调里,system 不宜写成过长“说明书”,否则模型容易学到冗余文本。建议:
- 角色:某品牌客服
- 原则:礼貌、先确认信息、给步骤
- 安全:不泄露内部、遇到不确定建议转人工
示例:
你是某电商平台的在线客服。请用简洁、友好、可执行的方式回答用户问题。若需要用户提供订单号等信息,请明确说明。不要编造政策或物流信息;不确定时建议转人工或说明查询路径。
工单转样本:一条完整示例
假设工单原始片段:
- 用户:我买的耳机左边没声音怎么办?
- 客服:您好,请问订单号是多少?我帮您确认售后政策。
- 用户:订单号 2024010203040506
- 客服:已为您查询在7天无理由期外,但在一年质保内。建议您先尝试重置和更换设备测试…如无改善可申请换新…
脱敏与结构化后:
- 订单号 →
<ORDER_ID>
最终 SFT 样本(逻辑示例,字段可按你训练框架调整):
- system:固定模板
- user:我买的耳机左边没声音怎么办?
- assistant:先致歉 + 询问订单号/排查步骤
- user:订单号
<ORDER_ID> - assistant:给出查询结论(如果日志里确实有)、排查步骤、售后路径、补充注意事项
单轮还是多轮?如何切分
建议优先多轮,因为客服场景常见“追问补信息”。切分策略:
- 按时间顺序合并同角色连续消息(避免碎片化)
- 以“已解决”节点或“给出最终方案”节点作为截断点
- 单条样本的总长度建议控制在模型可接受上下文(如 2k~4k tokens)内
质量筛选:让训练集“更像优秀客服”
历史工单质量参差不齐,SFT 对噪声非常敏感。建议建立可量化的过滤规则。
建议的过滤维度
- 可读性:过多口头禅、乱码、表情堆叠、纯截图说明
- 完整性:用户问了问题但客服没有给方案就结束
- 一致性:客服前后矛盾(例如先说可退后说不可退)
- 合规性:是否包含内部系统信息、绕过流程、违规承诺
- 可学习性:回复是否包含明确步骤/条件/路径
可操作的自动过滤规则(示例)
- 回复长度 < 15 字:剔除(多数是“好的”“收到”)
- 包含敏感词(如“后台给你改”“走个内部渠道”):剔除或进入黑名单
csat <= 2或投诉标签:剔除- user/assistant 轮次 < 2 且无解决方案:剔除
- assistant 中包含大量模板但无个性化信息:降低采样权重
人工抽检:最低成本保证质量
建议每轮数据处理完成后:
- 训练集随机抽检 100 条
- 按“是否能直接发给用户”标准打分(1~5)
- 统计低分原因:常见会是“缺前因”“结论缺依据”“含敏感信息”
- 迭代规则:把低分原因转换成新的过滤/修正规则
构建数据集文件:JSONL 与字段规范
多数训练工具(LLaMA-Factory、Axolotl、TRL等)支持 JSON/JSONL。建议使用 JSONL:一行一个样本,便于流式处理。
字段建议
id: ticket_id 或 hashmessages: 角色序列meta: 可选(category、channel、csat、时间范围)
这样你可以在训练时做“按类目分桶采样”或“错误分析回溯到工单”。
类目均衡(很关键)
客服数据常出现头部类目过多(例如物流占 40%)。如果直接训练,模型会偏向物流回答。
建议:
- 统计各 category 占比
- 对头部类目下采样,对长尾类目上采样
- 或者给长尾类目做“定向补数”(例如人工补写少量高质量样本)
训练方案选择:LoRA/QLoRA 更适合大多数客服项目
对于客服大模型微调,绝大多数团队选择 LoRA 或 QLoRA:成本低、迭代快、可回滚。
推荐配置思路(通用原则)
- 模型:优先选择对中文友好的基座(如 Qwen/Llama 中文增强版等)
- 训练方式:QLoRA(4bit)在单机也能跑较大模型
- 数据量:从 2k~20k 高质量样本起步,比“堆量”更重要
- 学习率:LoRA 通常 1e-4 ~ 2e-4(视 batch 与数据质量)
- epoch:2~5,观察验证集 loss 与实际回答质量
- 序列长度:建议 2048 起步,若工单长再加
数据划分
- train 90% / val 10%
- 关键:按
ticket_id或用户维度去重,避免同一会话泄漏到验证集
训练落地步骤(以“常见开源训练框架思路”为例)
下面给出不绑定某个工具的通用步骤,你可以映射到 LLaMA-Factory / Axolotl / TRL 任一实现。
Step 1:准备数据
- 导出工单到 CSV/Parquet
- 清洗合并消息(按时间排序,合并连续同角色)
- 脱敏
- 过滤低质量
- 转成 JSONL:
{id, messages, meta}
Step 2:准备训练环境
- GPU:建议至少 24GB 显存(7B QLoRA 更稳),或多卡
- 安装:PyTorch + transformers + peft + bitsandbytes(QLoRA)
Step 3:选择模板与特殊token
不同模型的对话模板不同(system/user/assistant 的拼接方式)。要点:
- 使用与基座模型一致的 chat template
- 确认 assistant 的输出部分参与 loss(只对 assistant 计算 loss)
Step 4:训练与监控
训练过程中重点看三类信号:
- 训练/验证 loss 是否同步下降(验证不降可能过拟合或数据噪声)
- 生成质量:每隔 N step 固定用一组“客服测试题”做生成对比
- 安全与合规:是否开始编造、是否输出不该说的内部信息
建议准备一份 eval_prompts.json,包含高频问题与高风险问题,例如:
- 物流查询(但不给订单号)
- 退款政策边界
- 要求客服“走内部渠道”的诱导
- 让模型编造“领导特批”的诱导
Step 5:导出与合并
- 保存 LoRA adapter
- 若推理框架需要可合并权重(merge)
- 记录版本号:数据集版本、基座版本、训练超参、评估结果
离线评估:别只看loss,要看“能不能当客服用”
建立一个小而硬的评估集
从真实线上问题中抽取 200~500 条,覆盖:
- TOP10 高频类目
- 典型追问链路(多轮)
- 反作弊/越权诱导
- 模糊问题(信息不足时是否会追问)
评估指标建议包含:
- 正确性:回答是否符合政策/事实(可由业务方评审)
- 完整性:是否给出步骤、条件、路径
- 礼貌与情绪安抚:是否先共情再解决
- 不编造:不确定时是否承认并建议查询/转人工
- 合规:不泄露内部信息,不承诺做不到的事
给业务团队可执行的打分表
每条对话打分:
- 0:不可用(错误/违规)
- 1:勉强可用(缺步骤/表达差)
- 2:可用(基本正确)
- 3:优秀(结构清晰、主动追问、体验好)
把“0分样本”回流:
- 若是知识缺失:补充知识或加入高质量示例
- 若是格式问题:修正模板或数据拼接
- 若是过拟合话术:降低模板化样本比例
常见坑与修复建议(非常实战)
坑1:工单里客服回复依赖“内部系统查询”,但日志没记录查询结果
表现:模型学会说“我已为您查询”,但给不出具体信息,甚至编造。
修复:
- 把这类工单剔除,或
- 重写 assistant:改成“我这边需要您提供订单号/截图,我为您核实后反馈”,避免虚构“已查询”
坑2:数据里大量“套话模板”,模型输出千篇一律
修复:
- 降低模板样本采样权重
- 增加包含具体步骤的优质样本
- 在 system 中强调“先确认问题要点,再给步骤”,并用数据体现
坑3:多轮切分错误,上下文缺失
表现:用户问A,模型答B,因为关键上下文在上一条被切掉。
修复:
- 以“问题-澄清-方案”为最小闭环
- 任何“给出最终方案”的 assistant 前至少保留最后一次用户提问
坑4:训练后模型变得“过度拒答”或“过度承诺”
修复:
- 过度拒答:检查 system 是否过于保守;加入“可回答范围内给出建议”的样本
- 过度承诺:增加边界样本(明确不能做什么)、剔除历史中的违规承诺工单
上线前的最小可行方案(MVP)建议
如果你希望两周内出一个能用的客服模型版本,建议按以下优先级:
- 先做 5k 条高质量 SFT(已解决 + 高满意度 + 过滤严格)
- 覆盖 5~8 个核心类目(物流/退款/售后/账户/发票等)
- 用 QLoRA 在 7B/14B 上训练 2~3 epoch
- 用 200 条评估集做人工评审 + 诱导测试
- 只在“低风险入口”灰度(例如“建议与指引类问题”),保留转人工兜底
当模型稳定后,再扩展:
- 引入更多轮次、更多类目
- 加入知识库链接引用规范
- 结合 RAG 提升时效性与事实性
小结:一条可复用的工单SFT生产流水线
从历史工单训练客服大模型,成功关键不在“训练参数多花哨”,而在于:
- 数据闭环:导出→脱敏→清洗→过滤→抽检→训练→评估→回流
- 质量优先:宁要 5k 条精品,不要 50k 条噪声
- 边界清晰:不确定就追问/转人工,坚决避免编造
按本文流程搭建起流水线后,你可以持续按周迭代数据与模型版本,让客服大模型逐步具备你业务的“专属表达与解决方案能力”。
Prev:项目实战:训练一个面向企业知识库的指令模型(SFT+RAG+评测闭环)