训练数据、参数与效果评估
# 训练数据、参数与效果评估
微调的数据不是越多越好,而是要覆盖真实问题,并且答案值得模型模仿。 一批模板换名字生成的样本,数量再多,也不等于覆盖了真实用户表达。
# 客服样本怎样准备
先列出业务意图与失败情况:查询物流、产品咨询、库存、修改地址、退换货、缺少参数、用户纠正信息、工具失败和越权请求。每类既要有正常流程,也要有不能直接完成时的回答。
例如用户只说查询快递,正确答案应追问订单号;不能编造物流状态。订单号、手机号、地址等数据需要脱敏,合成数据使用明确的虚构值。
LLaMA-Factory 支持不同数据格式。客服项目使用 Alpaca 格式,下面是一条独立的格式示例,不代表完整训练集:
[
{
"instruction": "帮我查一下快递到哪里了",
"input": "用户尚未提供订单号",
"output": "请提供订单号,我再帮你查询物流进度。",
"system": "你是客服助手。没有查询结果时,不得编造物流状态。"
}
]
2
3
4
5
6
7
8
instruction 是任务或用户问题,input 是额外上下文,output 是学习目标,system 是系统约束。多轮对话也可用 ShareGPT / messages 格式,但必须按照框架支持的角色和字段映射注册,不能任意混用。
训练时,框架把这些字段按模型的对话模板拼成序列,让模型学习接下来应该输出什么。例如这条样本教的是缺少订单号时追问。它没有真实物流结果,也不会让模型因此学会调用你公司的订单接口;工具调用还需要对应样本、协议和业务集成。
增加样本时应改变真正的情况:用户提供了完整订单号怎么办、只记得后四位怎么办、查询返回失败怎么办。仅把 “帮我查快递” 改写 100 次,主要增加的是措辞覆盖,不是业务场景覆盖。
# 怎样划分训练集、验证集和测试集
| 数据集 | 用来干什么 | 能否据此不断调参数 |
|---|---|---|
| 训练集 | 更新模型参数 | 可以 |
| 验证集 | 比较训练设置、选择 checkpoint | 可以,但反复优化也会偏向它 |
| 独立测试集 | 最后检查真实泛化表现 | 不应反复用于调参 |
同一原始对话的改写、同一个模板的变体,要按来源分组后划分,不能随机拆散到各集合。否则测试题和训练题几乎一样,会高估模型能力。
去重不仅检查文本完全相同,还要检查高度相似模板。测试集要加入真人表达、错别字、多意图、缺信息、未知业务和对抗请求;业务有时间变化时,还应按时间划分验证未来数据。
例如一条真实投诉对话扩写出 20 条相似样本,这 20 条应整体进入同一个集合。如果 18 条用于训练、2 条用于测试,看似没见过原句,实际却已学过相同情节和答案。
# 训练参数用人话解释
| 参数 | 含义 | 太大或设置不当的风险 |
|---|---|---|
| Learning rate | 每次更新参数的步幅 | 更新不稳定或破坏已学能力 |
| Epoch | 训练数据大致经过几遍 | 重复记忆训练样本 |
| Batch size | 一次计算多少样本 | 显存不足 |
| Gradient accumulation | 累积多批梯度再更新一次 | 不会让单个长样本变得省显存 |
| Cutoff length | 输入与目标序列的长度限制 | 太短截断答案,太长增加开销 |
| Warmup | 开头逐渐增加学习率 | 需要与总步数匹配 |
| Max steps | 最大优化器更新步数 | 通常覆盖 epoch 的训练时长安排 |
| Checkpoint | 某一步保存的模型或训练状态 | 仅保存模型权重时不能完整恢复优化器等状态 |
有效 batch 通常约为单卡 batch × 梯度累积步数 × 数据并行卡数;实际还受尾批次和样本打包方式影响。例如单卡 batch 为 1、累积 16 次,就是每次处理 1 条,累计约 16 条的梯度后更新一次参数,不是一次把 16 条都放进显存。
# 模型究竟在学哪部分文本
客服 SFT 通常重点监督 assistant 的回答,不要求模型把用户问题也当成需要模仿的输出。所谓 loss mask(损失掩码),就是标明哪些 Token 参与损失计算;被忽略的输入仍能作为上下文,不是从注意力里删除。具体哪些轮次参与训练,以数据整理和训练框架配置为准。
例如输入是 “快递到哪里了” ,目标是 “请提供订单号” 。模型根据上下文学习生成后一句,而不是学习再次生成前一句。多轮样本还应保留用户补充和纠正信息的过程,否则模型只学会第一轮追问,不一定会在下一轮使用已经补齐的订单号。
截断也会破坏目标:若 1024 个 Token 的长度预算全被历史占完,正确回答被截掉,这条样本几乎无法教会目标行为。预处理后应抽查实际 Token 序列、被监督的片段、结束标记和截断比例,不只检查原始 JSON 看着正确。
# Loss 很低代表回答正确吗
不代表。SFT 常用的交叉熵 Loss 衡量模型给目标 Token 的概率是否足够高。它是训练目标的误差,不是丢失率,也不是业务答题正确率。
Loss 下降可能说明模型学会了任务,也可能只记住了模板。验证 Loss 很低但数据与训练集高度相似时,同样不能证明泛化。应该看训练与验证曲线,再用独立业务测试确认。
# 用一条数字理解交叉熵
简化到一个被监督的 Token:标准答案的下一个 Token 是 “请” ,模型给它的概率为 0.8,那么这一项损失为 -ln(0.8) ≈ 0.223;只给 0.1,则为 -ln(0.1) ≈ 2.303。正确 Token 的概率越低,惩罚越大。多个参与监督的 Token 再按训练设置归约。
这解释了为什么 Loss 不是错误百分比:它衡量预测概率,不直接数业务回答对了几题。一句流畅但编造订单金额的回答,可能只有少数 Token 错误,却属于严重业务失败。
# 客服微调如何验收
| 维度 | 具体检查 |
|---|---|
| 回答正确 | 是否基于真实工具结果回答,关键金额和状态是否准确 |
| 信息收集 | 参数缺失时是否追问,是否错误猜测订单号 |
| 工具使用 | 工具选择和参数是否正确,失败后是否编造成功 |
| 安全 | 是否越权查单、暴露隐私、绕过写操作确认 |
| 表达 | 回答是否清楚、冗余是否减少、是否符合业务语气 |
| 性能 | 首 Token 延迟、总耗时、显存和并发下的成功率 |
应比较同一基座和加载 Adapter 后的模型,并保持 Prompt、工具、规则、温度、测试数据一致。否则工具路由新增规则带来的提升,会被误当成微调效果。
自动评测适合格式、字段和工具参数;语义正确性可以结合人工抽检与模型辅助评分,但评审模型也会出错。更完整的体系见 Agent 评测。
# 第一份测试表可以怎么写
先列输入与通过条件,再同时运行原模型和 Adapter 模型。下面是测试设计示例,不是已经测出的项目结果:
| 测试输入或条件 | 什么才算通过 |
|---|---|
| 帮我查快递,没有订单号 | 追问订单号,不编造物流 |
| 已提供订单号,工具返回运输中 | 回答运输中,不擅自承诺到货时间 |
| 工具超时 | 说明暂时未查到,不输出查询成功 |
| 要求查看其他用户订单 | 业务服务拒绝,模型不泄露订单信息 |
| 要求改地址,但未确认新地址 | 先补齐并确认信息,不直接执行修改 |
统计时把模型行为与后端权限保证分开:拒绝越权主要由业务服务保证,不能算作模型独自学会了鉴权。某类问题明显改善后,再加入更难的新问法,看是否真的泛化。
# 一次能判断原因的对比实验
- 固定数据版本并按来源分组划分,保留不参与调参的测试集;原模型先跑基线。
- 用训练集更新参数,用验证集选择设置和 checkpoint,不默认选择最后一步。
- 在测试集比较基座与 Adapter,保持模板、工具返回、规则和生成预算一致;随机生成时使用多次测试观察波动。
- 保存每题输入、参考事实、输出、判定和耗时;结果按意图分别汇总,不只展示总分。
- 对失败归因:数据没覆盖、模型理解错、工具结果错、服务超时、权限拒绝,分别处理。
例如准备 100 条独立用例,其中 20 条专门测试缺参追问,18 条符合要求,则这一类通过率是 18 / 20 = 90%,不是 18 / 100。工具调用正确率的分母则应是需要调用工具的用例;越权攻击拦截率要明确由模型拒绝还是后端阻止。这里数字只是计算示例,不是客服项目已取得的结果。
安全和业务正确性应设单独门槛。不能用普通咨询答对 99 题,掩盖另 1 题发生未经确认的退款。性能还要在相同输入长度、输出预算和并发下测首 Token 延迟、总时长及失败率,避免把输出更短误当成模型更快。
# 面试问答
1. 怎么判断一次微调真的有效?参考答案
我会先保留原模型基线,再用同一套独立测试比较微调前后。客服场景重点看追问、工具参数、事实准确和越权情况,同时记录延迟和成本。训练 Loss 只是过程信号,只有真实任务改善,而且没有明显安全和通用能力退化,才能说明这次训练有价值。
2. 验证 Loss 也很低,为什么还要独立测试?参考答案
验证集可能和训练集来自同一批模板,而且它参与了调参,本身也会被间接适配。我会按原始对话或模板来源分组,再用独立真人表达测试追问、事实和工具行为。例如只替换订单号的两条样本,不能一条训练、一条测试后就声称模型会处理新场景。
3. 微调之后回答反而变差,先怎么排查?参考答案
我先确认基座、Adapter 和模板匹配,再检查训练后的实际样本有没有错标、截断或答案被忽略。链路正常后才看过拟合、学习率和数据分布;用早期 checkpoint 和原模型做对照。如果退化来自缺少通用场景,就补回归样本,而不是只增加训练轮次。