AI 工程基础体系 · 第 13/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。

大语言模型生命周期:预训练、指令微调、对齐、推理和版本评测

大语言模型(Large Language Model,LLM)不是“训练完成后调用接口”的单一软件包,而是一条持续运行的生产链路:

数据预训练指令微调对齐发布推理评测与监控下一版本\text{数据} \rightarrow \text{预训练} \rightarrow \text{指令微调} \rightarrow \text{对齐} \rightarrow \text{发布} \rightarrow \text{推理} \rightarrow \text{评测与监控} \rightarrow \text{下一版本}

其中,预训练决定模型能否学习语言、代码和知识的统计结构;指令微调决定模型能否按照任务格式回答;对齐处理有用性、安全性、诚实性和偏好之间的取舍;推理是模型在给定输入下生成输出的运行过程;版本评测则决定一个新模型是否真的比旧模型更适合生产。

这些阶段共享同一组生产约束:数据是否有权限使用,模型是否可部署,输出是否可接受,延迟和成本是否可控,以及升级后是否会破坏已有能力。


一、先区分几个容易混淆的概念

1. 训练、推理和评测不是同一件事

**训练(training)**通过数据和优化算法改变模型参数。给定参数 θ\theta,训练的目标是找到一组更合适的参数:

θ\*=argminθL(θ)\theta^\* = \arg\min_\theta \mathcal{L}(\theta)

**推理(inference)**固定参数 θ\theta,只根据输入计算输出,不更新模型参数。例如:

Pθ(yx)P_\theta(y\mid x)

表示参数固定时,模型在输入 xx 下生成输出 yy 的概率。

**评测(evaluation)**不应改变模型参数,而是使用固定的数据、提示词、评分规则和版本配置,测量模型在某些任务上的表现。评测结果不是模型本身的属性,而是:

Score=f(model version,prompt,dataset,decoding,grader)\text{Score} = f(\text{model version},\text{prompt},\text{dataset},\text{decoding},\text{grader})

因此,同一个模型更换系统提示词、采样参数或工具权限后,结果可能不同。

2. 语言模型建模的是 token 序列

大语言模型通常不是直接处理“字”或“词”,而是处理 tokenizer 产生的 token 序列:

x1,x2,,xTx_1,x_2,\ldots,x_T

一个 token 可以是一个汉字、一个英文词片段、标点,或多个字符的组合。tokenizer 将文本映射为整数 ID:

text(x1,,xT)\text{text} \rightarrow (x_1,\ldots,x_T)

再由模型预测下一个 token:

Pθ(xtx<t)P_\theta(x_t\mid x_{<t})

中文、代码、数字、URL 和混合语言的 token 化方式差异很大。上下文长度、计费、显存占用和训练样本数量通常都与 token 数量有关,而不是与字符数或“句子数”直接相关。

一个常见误解是“token 越少,模型一定越好”。更短的 token 序列可能降低计算成本,但如果 tokenizer 对代码、数学表达式或中文分词不合适,模型学习难度可能上升。因此 tokenizer 是数据、模型架构和成本之间的共同边界。


二、完整生命周期和状态变化

下面的流程把数据、模型、评测和发布状态放在一起:

flowchart LR
    A[原始数据] --> B[授权与治理]
    B --> C[清洗 去重 脱敏 质量过滤]
    C --> D[预训练数据集]
    D --> E[预训练模型]
    E --> F[指令数据与监督微调]
    F --> G[对齐训练]
    G --> H[候选模型注册]
    H --> I[离线评测]
    I --> J{是否通过门槛}
    J -- 否 --> K[诊断 回滚或重新训练]
    K --> F
    J -- 是 --> L[灰度发布]
    L --> M[在线推理]
    M --> N[日志 反馈 安全监控]
    N --> I

这里至少有四类状态需要持久化:

  1. 数据状态:来源、许可证、版本、清洗规则、去重结果、敏感信息处理记录。
  2. 模型状态:权重、配置、tokenizer、训练步数、优化器状态、随机种子。
  3. 推理状态:上下文窗口、KV Cache、采样配置、工具调用状态。
  4. 评测状态:数据集版本、提示词版本、评分器版本、硬件和服务端配置。

只保存一个模型权重文件,无法完整复现实验。比如 tokenizer 变化会导致相同字符串映射到不同 token;提示词变化会改变输入模板;采样温度变化会改变输出分布。


三、预训练:让模型学习语言分布

3.1 自回归语言模型的目标

主流生成式 LLM 通常使用自回归语言建模。给定 token 序列:

x1,x2,,xTx_1,x_2,\ldots,x_T

根据概率链式法则:

P(x1,,xT)=t=1TP(xtx1,,xt1)P(x_1,\ldots,x_T)=\prod_{t=1}^{T}P(x_t\mid x_1,\ldots,x_{t-1})

训练时,每个位置都使用真实前缀预测下一个 token。交叉熵损失为:

LLM=1Tt=1TlogPθ(xtx<t)\mathcal{L}_{\text{LM}} = -\frac{1}{T} \sum_{t=1}^{T} \log P_\theta(x_t\mid x_{<t})

其中:

  • TT 是序列长度;
  • x<tx_{<t} 表示位置 tt 之前的 token;
  • PθP_\theta 是模型输出的概率;
  • log\log 通常使用自然对数;
  • 损失越小,表示真实下一个 token 获得的概率越高。

这个目标并没有直接告诉模型“什么是事实”“什么是礼貌”或“什么是安全”。它只要求模型拟合训练语料中的 token 分布。模型可能因此学到语法、代码模式、事实关联、推理模板,也可能学到错误信息、偏见和训练数据中的不良行为。

3.2 一个完整的交叉熵算例

假设词表只有:

V={,,,睡觉}V=\{\text{猫},\text{狗},\text{在},\text{睡觉}\}

训练样本是“猫 在 睡觉”,输入输出对可以写成:

输入前缀 目标 token
<BOS>
<BOS> 猫
<BOS> 猫 在 睡觉

假设模型在三个位置给出的概率分别为:

  • 预测“猫”:0.50.5
  • 预测“在”:0.80.8
  • 预测“睡觉”:0.250.25

则平均损失为:

L=log0.5+log0.8+log0.2530.636\mathcal{L} = -\frac{\log 0.5+\log 0.8+\log 0.25}{3} \approx 0.636

如果第三步把“睡觉”的概率从 0.250.25 提高到 0.50.5,损失会下降。梯度下降会调整参数,使真实 token 的概率整体提高,同时通常降低其他 token 的相对概率。

**困惑度(perplexity)**是交叉熵的指数:

PPL=eL\text{PPL}=e^{\mathcal{L}}

在上例中:

e0.6361.89e^{0.636}\approx 1.89

困惑度可理解为模型在平均意义上面对的“有效候选数量”。但不同 tokenizer、语料领域和分词方式下的 PPL 不能简单横向比较。代码数据和自然语言数据也不应直接共用一个无解释的 PPL 门槛。

3.3 Transformer 如何计算下一个 token

Transformer 以 token embedding 作为输入。对输入矩阵 XX,单个注意力头计算:

Q=XWQ,K=XWK,V=XWVQ=XW_Q,\quad K=XW_K,\quad V=XW_V

注意力权重为:

A=softmax(QKdk+M)A=\operatorname{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}+M\right)

输出为:

O=AVO=AV

其中:

  • QQ 是查询;
  • KK 是键;
  • VV 是值;
  • dkd_k 是键向量维度;
  • MM 是掩码矩阵;
  • dk\sqrt{d_k} 用于避免点积随维度增大而导致 softmax 过于尖锐。

在自回归模型中,位置 tt 不能看到未来位置 t+1,,Tt+1,\ldots,T。因此因果掩码满足:

Mt,j={0,jt,j>tM_{t,j}= \begin{cases} 0,&j\le t\\ -\infty,&j>t \end{cases}

加上 -\infty 后,softmax 对未来位置的概率近似为零。

注意力子层通常还会与残差连接和归一化结合:

H=Norm(H+Attention(H))H'=\operatorname{Norm}(H+\operatorname{Attention}(H))

随后经过前馈网络:

H=Norm(H+FFN(H))H''=\operatorname{Norm}(H'+\operatorname{FFN}(H'))

残差连接提供了较稳定的梯度路径;归一化控制中间激活的尺度;多头注意力允许不同头关注不同的依赖关系,例如局部语法、长距离引用或结构标记。具体使用 LayerNorm、RMSNorm、Pre-Norm 或其他变体,取决于模型架构,不能把所有 Transformer 实现视为完全相同。

3.4 预训练数据决定了能力上限和风险面

预训练数据通常包含网页、书籍、代码、文档、对话或领域语料。数据处理不是简单删除空行,而至少包括:

  • 来源和许可证记录;
  • 文档解析与格式规范化;
  • 语言和领域分类;
  • 近重复与精确重复去重;
  • 个人信息、凭证和机密内容处理;
  • 恶意指令、垃圾页面和低质量页面过滤;
  • 训练集与评测集去重,防止数据泄漏;
  • 每个数据子集的采样权重和版本记录。

数据泄漏会使评测分数失真。例如,一个问答测试集被原样收录进预训练数据,模型可能只是记忆答案,而不是获得可迁移的能力。

数据权限也不能由“数据能下载”推出“数据能训练”。需要区分公开可访问、允许内部使用、允许商业训练、允许再分发和允许生成衍生模型等不同权利。生产系统应记录数据来源、处理依据和删除机制;如果用户数据用于改进模型,还必须遵循具体产品的授权、隐私和保留政策,不能用“模型训练”作为默认理由。

3.5 预训练的优化状态

一个训练 checkpoint 不仅是模型参数,还可能包括:

  • optimizer state,例如 Adam 的一阶、二阶矩;
  • learning-rate scheduler 状态;
  • 当前 global step;
  • 数据加载器位置;
  • 混合精度 scaler;
  • 随机数状态;
  • tokenizer 和模型配置。

若只保存权重,通常可以继续做推理或从近似参数开始微调,但不能保证从训练中断处无缝恢复。恢复训练时,如果数据顺序、学习率或优化器状态不一致,损失曲线可能出现突变。

常见训练失败包括:

  • 损失突然变成 NaN:可能与学习率过高、溢出、异常数据或数值精度有关;
  • 训练损失下降而验证损失上升:过拟合、数据分布不一致或验证集泄漏检查有误;
  • loss 正常但生成重复:数据重复、解码配置、位置编码或训练目标存在问题;
  • 某语言或领域能力退化:数据混合权重发生变化,或后续训练产生灾难性遗忘。

四、指令微调:让基础模型学会“按任务完成请求”

4.1 指令微调是什么

**指令微调(Instruction Fine-Tuning)**通常指使用输入—输出示例,对预训练模型进行监督微调(Supervised Fine-Tuning,SFT)。

一条样本可以表示为:

{
  "messages": [
    {"role": "user", "content": "把 12 摄氏度转换为华氏度"},
    {"role": "assistant", "content": "12 摄氏度约等于 53.6 华氏度。"}
  ]
}

训练时,模型仍然预测下一个 token,但通常只对 assistant 回复部分计算损失。设完整序列为 z1,,zTz_1,\ldots,z_T,assistant token 的位置集合为 SS,则:

LSFT=1StSlogPθ(ztz<t)\mathcal{L}_{\text{SFT}} = -\frac{1}{|S|} \sum_{t\in S} \log P_\theta(z_t\mid z_{<t})

这样做的因果是:模型学习“在给定用户输入和对话上下文后,应该生成怎样的回答”,而不是把用户问题本身当作需要模仿的输出。

如果错误地对整段对话所有 token 平均计算损失,模型仍可能训练成功,但优化目标会把大量容量用于复现用户消息、角色标记和模板,而减少对 assistant 任务输出的直接学习。是否只计算回答损失取决于训练框架和数据格式,但必须明确 mask 规则。

4.2 SFT 数据的质量比数量更重要

一条指令数据至少应定义:

  • 用户意图;
  • 输入字段和边界;
  • 合法输出;
  • 不应声称的内容;
  • 需要拒绝的条件;
  • 工具或引用要求;
  • 评分标准。

例如“回答公司报销政策”不能只提供答案,还要说明政策版本和适用范围。否则模型可能把过期规定学习成无条件事实。

SFT 不等于知识库导入。它适合学习稳定的行为模式、格式、术语和任务流程;对频繁变化的产品价格、库存、权限和内部记录,优先使用检索或工具调用。将大量动态事实硬编码到微调数据中,通常会增加更新成本和错误记忆风险。

4.3 LoRA 与全量微调

全量微调更新全部参数:

θ=θ+Δθ\theta'=\theta+\Delta\theta

LoRA 则冻结原始权重 WW,只学习低秩增量:

W=W+ΔW,ΔW=BAW'=W+\Delta W,\qquad \Delta W=BA

其中:

BRd×r,ARr×k,rmin(d,k)B\in\mathbb{R}^{d\times r},\quad A\in\mathbb{R}^{r\times k},\quad r\ll \min(d,k)

训练时只更新 A,BA,B。推理时可以把增量合并进权重,也可以保留为单独 adapter。

LoRA 降低了可训练参数量和显存需求,但不意味着“能力完全等价于全量微调”。当任务需要大范围改变模型知识、语言能力或行为边界时,低秩容量可能不足;当多个 adapter 叠加时,还会出现组合冲突和版本管理问题。

4.4 微调的反例:不该用 SFT 解决的问题

假设客服系统每天更新订单状态。团队收集昨天的订单问答并做 SFT。模型可能学会回答格式,却无法可靠知道今天的订单状态。更糟的是,它会用训练时的旧答案生成看似确定的回复。

正确的分工通常是:

用户问题
  -> 权限检查
  -> 查询订单系统
  -> 将授权后的结果放入上下文
  -> 模型生成解释

SFT 负责“如何表达和执行流程”,业务系统负责“当前事实是什么”。如果问题是知识变化,应优先更新检索索引、数据库或工具,而不是重新训练模型。


五、对齐:把“会生成”变成“在约束下工作”

5.1 对齐的含义和边界

**对齐(alignment)**不是一个单独算法,而是使模型输出符合人类、组织或产品目标的过程。这些目标至少包括:

  • 有用:完成用户任务;
  • 诚实:不把不确定内容说成确定事实;
  • 无害:降低危险、违法、隐私和滥用风险;
  • 可控:遵守权限、工具和业务边界;
  • 一致:在相似输入下行为稳定。

这些目标可能冲突。例如,用户希望模型直接给出答案,但系统要求先验证权限;用户要求完整解释危险操作,安全策略却要求拒绝具体执行步骤。对齐实际上是在定义和优化这些约束,而不是让模型“永远听话”。

5.2 RLHF 的基本过程

一种经典流程是 RLHF(Reinforcement Learning from Human Feedback):

  1. 对同一输入采集多个候选回答;
  2. 人类对回答排序或比较;
  3. 训练奖励模型 rϕ(x,y)r_\phi(x,y)
  4. 使用强化学习优化策略模型,同时约束其不要偏离参考模型过远。

如果人类偏好 y+yy^+\succ y^-,奖励模型常用 Bradley–Terry 形式:

P(y+yx)=σ(rϕ(x,y+)rϕ(x,y))P(y^+\succ y^-\mid x) = \sigma(r_\phi(x,y^+)-r_\phi(x,y^-))

对应损失:

LRM=logσ(rϕ(x,y+)rϕ(x,y))\mathcal{L}_{\text{RM}} = -\log \sigma(r_\phi(x,y^+)-r_\phi(x,y^-))

其中 σ\sigma 是 sigmoid 函数。这个损失会推动偏好回答的奖励高于不偏好回答。

策略优化常写成:

maxπEx,yπ[rϕ(x,y)βDKL(π(x)πref(x))]\max_\pi \mathbb{E}_{x,y\sim\pi} \left[ r_\phi(x,y) - \beta D_{\mathrm{KL}} \left(\pi(\cdot\mid x)\Vert \pi_{\text{ref}}(\cdot\mid x)\right) \right]

第一项鼓励高奖励输出,第二项限制新策略偏离参考模型过多,β\beta 控制约束强度。

RLHF 的风险在于奖励模型只是人类偏好的近似。如果评分标准不完整,模型可能学会“讨好评分器”:回答更长、更肯定、更像人工偏好的形式,但事实准确率反而下降。这称为奖励投机或 reward hacking。

5.3 DPO 的直接偏好优化

DPO(Direct Preference Optimization)使用偏好对直接优化策略,不显式运行完整的在线强化学习过程。典型目标为:

LDPO=logσ(β[logπθ(y+x)πref(y+x)logπθ(yx)πref(yx)])\mathcal{L}_{\text{DPO}} = -\log \sigma\left( \beta \left[ \log\frac{\pi_\theta(y^+\mid x)} {\pi_{\text{ref}}(y^+\mid x)} - \log\frac{\pi_\theta(y^-\mid x)} {\pi_{\text{ref}}(y^-\mid x)} \right] \right)

其中:

  • πθ\pi_\theta 是当前策略;
  • πref\pi_{\text{ref}} 是参考模型;
  • y+y^+ 是偏好回答;
  • yy^- 是非偏好回答;
  • β\beta 控制相对参考模型的约束。

DPO 的工程优势是训练链路较简单,但它仍依赖高质量偏好数据。如果“偏好回答”只是更长而不是更正确,DPO 会忠实地学习这种偏好。

5.4 对齐不是安全过滤器的替代品

模型内在对齐、输入输出安全分类器、权限系统和工具沙箱解决的是不同问题:

  • 模型对齐:改变一般行为倾向;
  • 安全过滤:检测输入或输出风险;
  • 权限控制:决定用户能否访问资源;
  • 工具沙箱:限制模型实际能执行的动作;
  • 审计日志:记录谁在什么时间执行了什么操作。

不能因为模型经过对齐,就让它直接拥有数据库写权限。模型输出是一种建议或动作请求,真正的权限检查必须在模型之外执行。


六、推理:从上下文到逐 token 生成

6.1 一次生成发生了什么

给定输入 token:

x1,,xnx_1,\ldots,x_n

模型先进行一次 prefill,计算完整上下文的隐藏状态和注意力键值。随后进入 decode 阶段,每次生成一个 token:

  1. 将上一步生成的 token 输入模型;
  2. 读取最后位置的 logits;
  3. 经过温度、top-k 或 top-p 等处理;
  4. 采样或选择下一个 token;
  5. 更新上下文和 KV Cache;
  6. 直到生成停止 token、达到长度上限或触发外部停止条件。

logits lil_i 转成概率:

P(i)=eli/Tjelj/TP(i)=\frac{e^{l_i/T}}{\sum_j e^{l_j/T}}

其中 TT 是温度:

  • T<1T<1:分布更尖锐,输出更确定;
  • T>1T>1:分布更平坦,输出更多样;
  • T0T\to 0:接近选择最大 logit 的贪心解码。

注意,低温度不等于事实正确;它只减少随机性。

6.2 完整解码算例

假设下一个 token 的 logits 为:

token logit
A 2.0
B 1.0
C 0.0

温度 T=1T=1 时:

P(A)0.665,P(B)0.245,P(C)0.090P(A)\approx0.665,\quad P(B)\approx0.245,\quad P(C)\approx0.090

T=2T=2,先将 logits 除以 2:

token 新 logit
A 1.0
B 0.5
C 0.0

概率约为:

P(A)0.506,P(B)0.307,P(C)0.186P(A)\approx0.506,\quad P(B)\approx0.307,\quad P(C)\approx0.186

温度升高后,低概率 token 的机会增加。若再使用 top-p,系统会从最高概率开始累加,保留累计概率达到阈值 pp 的最小 token 集合,然后在其中重新归一化采样。top-k 则固定保留概率最高的 kk 个 token。

反例:对要求精确 JSON 的输出使用过高温度,模型可能生成额外解释或破坏括号;对开放式创作使用贪心解码,可能导致文本僵硬和重复。解码配置必须与任务目标匹配,并纳入评测版本。

6.3 KV Cache 的作用和代价

在自回归生成时,旧 token 的 KKVV 不会改变。若每生成一个 token 都重新计算全部历史 token,计算量会很高。KV Cache 保存各层历史的键和值,使新 token 只需计算新的 Q,K,VQ,K,V,再让新 QQ 与缓存的 KK 做注意力。

因此:

  • prefill 主要处理输入上下文;
  • decode 主要逐 token 处理输出;
  • 长输入会增加 prefill 延迟;
  • 长输出会增加 decode 时间;
  • 并发请求会竞争 GPU 计算和 KV Cache 显存。

KV Cache 的内存大致随以下因素增长:

memorylayers×sequence length×KV heads×head dimension×bytes per value\text{memory} \propto \text{layers}\times \text{sequence length}\times \text{KV heads}\times \text{head dimension}\times \text{bytes per value}

实际布局还受 batch、张量并行、Paged Attention、MQA/GQA 等实现影响。上下文长度不是免费的:它既消耗计算,也占用缓存,可能降低同一 GPU 的并发容量。

6.4 生产推理的请求状态

一个完整请求通常包含:

request_id
model_version
input_messages
tokenizer_version
generation_config
user_identity
authorization_context
tool_state
deadline
stream_state

推理服务至少要处理:

  • 输入超出上下文窗口;
  • 请求取消和客户端断开;
  • 模型加载失败;
  • GPU 显存不足;
  • 工具调用超时;
  • 流式输出中途失败;
  • 上游限流或配额耗尽;
  • 输出包含不允许泄露的内容。

流式输出提升首 token 体验,但它改变了错误处理:服务可能已经发送部分答案,不能再简单返回一个完整的 HTTP 错误。客户端需要区分“正常结束”“被截断”“工具失败”和“服务异常”,服务端也应记录结束原因。


七、一个最小的本地推理示例

下面示例使用 Hugging Face Transformers 的常见接口运行一个因果语言模型。具体模型名称、显存需求和 chat template 是否存在取决于所选模型,因此不能把示例中的模型替换为任意 checkpoint 后都视为必然可运行。

python -m venv .venv
source .venv/bin/activate
pip install -U torch transformers

示例代码:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "Qwen/Qwen2.5-0.5B-Instruct"

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype="auto",
    device_map="auto",
)
model.eval()

messages = [
    {"role": "system", "content": "你是一个严谨的技术助手。"},
    {"role": "user", "content": "用一句话解释什么是 KV Cache。"},
]

if hasattr(tokenizer, "apply_chat_template") and tokenizer.chat_template:
    inputs = tokenizer.apply_chat_template(
        messages,
        add_generation_prompt=True,
        return_tensors="pt",
        return_dict=True,
    )
else:
    prompt = "系统:你是一个严谨的技术助手。\n用户:用一句话解释什么是 KV Cache。\n助手:"
    inputs = tokenizer(prompt, return_tensors="pt")

inputs = {k: v.to(model.device) for k, v in inputs.items()}

with torch.inference_mode():
    outputs = model.generate(
        **inputs,
        max_new_tokens=80,
        do_sample=False,
        pad_token_id=tokenizer.eos_token_id,
    )

new_tokens = outputs[0, inputs["input_ids"].shape[1]:]
print(tokenizer.decode(new_tokens, skip_special_tokens=True))

预期会得到类似“KV Cache 是在自回归生成中缓存历史 token 的 Key 和 Value,以避免重复计算”的回答,但具体文字不保证完全一致。

每一步的原因是:

  1. AutoTokenizer 必须与 checkpoint 配套,否则 token ID 和特殊 token 可能不匹配。
  2. apply_chat_template 将角色消息转换成模型训练时使用的格式;直接拼接普通字符串可能损失指令模型的行为能力。
  3. model.eval() 关闭训练阶段的随机行为。
  4. torch.inference_mode() 减少推理期间不必要的 autograd 开销。
  5. max_new_tokens 限制输出长度,防止异常生成无限增长。
  6. do_sample=False 使用确定性较强的解码,便于复现;开放式任务可以改用采样,但必须同时记录随机种子和采样参数。
  7. 只解码新生成的 token,避免把原始 prompt 再打印一次。

风险包括模型下载来源、许可证、显存占用和模型代码安全。加载第三方 checkpoint 前,应检查其模型卡、许可证和是否需要执行自定义代码;不能仅因为模型文件可下载,就认为它适合商业部署。


八、版本评测:比较的不是一个数字

8.1 建立版本身份

一个可评测的模型版本应至少绑定:

model weights
model config
tokenizer
chat template
system prompt
decoding parameters
tool definitions
safety policy
retrieval index
evaluation dataset version
grader version

如果只记录“模型 v2”,却没有记录提示词和检索索引,后续无法判断分数变化来自权重、上下文还是外部系统。

版本可以分为:

  • 模型版本:权重和配置变化;
  • 应用版本:提示词、工具编排、检索和权限变化;
  • 评测版本:题目、参考答案和评分器变化;
  • 部署版本:推理引擎、量化方式、硬件和并发配置变化。

生产发布应使用不可变版本标识。人类可读的 latest 可以作为别名,但不应作为审计或回滚依据。

8.2 评测数据的分层

单一总分会掩盖失败,因此至少应分为:

  1. 能力集:知识、推理、代码、数学、长上下文、结构化输出;
  2. 业务集:真实脱敏样本和高价值用户流程;
  3. 安全集:越权、提示注入、隐私泄露、危险请求;
  4. 回归集:历史上曾经失败、修复或高风险的案例;
  5. 压力集:超长输入、并发、超时、工具失败和异常格式。

评测集必须和训练数据隔离。对于会持续更新的业务集,应冻结快照,并记录抽样规则。否则每次评测样本变化,分数差异就无法归因。

8.3 自动指标、人工评分和模型评分

不同任务需要不同指标:

  • 分类或路由:准确率、召回率、F1;
  • 抽取:字段级准确率、精确率、召回率;
  • 代码:测试通过率,而不是只比较文本;
  • JSON:语法有效率、字段正确率和约束满足率;
  • 检索增强生成:引用覆盖率、事实一致性和拒答正确率;
  • 对话:任务完成率、用户满意度、升级人工比例;
  • 推理服务:首 token 延迟、总延迟、吞吐、错误率和单位成本。

“模型评分模型”可以帮助处理开放式答案,但评分器会有偏差,尤其容易偏爱更长、更有礼貌、更像标准答案的文本。高风险任务应使用程序化验证、人类复核或业务事实校验,不能把单一 LLM judge 当作规范保证。

8.4 版本比较的统计方法

假设旧版本和新版本都在同一批 nn 个样本上评测,定义每个样本的差值:

di=sinewsioldd_i=s_i^{\text{new}}-s_i^{\text{old}}

平均提升为:

dˉ=1ni=1ndi\bar d=\frac{1}{n}\sum_{i=1}^n d_i

如果样本近似独立,差值标准差为 sds_d,则平均差的标准误为:

SE=sdnSE=\frac{s_d}{\sqrt n}

近似的 95% 置信区间为:

dˉ±1.96SE\bar d \pm 1.96SE

对同一题目比较两个版本时,配对比较通常比各算一个总准确率更有效。对分类任务还可以使用 McNemar 检验;对生成任务则应按业务定义选择 bootstrap、分层抽样或人工盲评。

完整算例:旧版本在 1000 个样本上正确 820 个,新版本正确 835 个。仅看总分,提升为 1.5 个百分点。但逐题比较后发现:

  • 新旧都正确:805;
  • 旧正确、新错误:15;
  • 旧错误、新正确:30;
  • 新旧都错误:150。

新版本净提升是 3015=1530-15=15 题。它可能真实变好,但还应检查这 15 个样本是否集中在一个简单子类,以及退化的 15 个样本是否属于高风险流程。平均分通过,不代表可以无条件发布。

8.5 评测门槛应包括非功能指标

模型能力提升可能伴随成本和延迟上升。一个发布门槛可以是:

通过    {Δ业务成功率0Δ高风险错误率0P95 延迟L单位请求成本C服务错误率E\text{通过} \iff \begin{cases} \Delta \text{业务成功率} \ge 0\\ \Delta \text{高风险错误率} \le 0\\ \text{P95 延迟} \le L\\ \text{单位请求成本} \le C\\ \text{服务错误率} \le E \end{cases}

这不是通用标准,而是组织根据风险制定的发布条件。关键是不能只比较离线准确率而忽略权限越界、工具误调用、延迟、成本和回滚能力。


九、权限、数据安全和成本必须进入生命周期

9.1 模型不应直接决定权限

权限判断必须在模型外部完成。一个安全的数据流是:

用户身份
  -> 业务服务验证权限
  -> 只查询允许的数据
  -> 对结果做字段过滤和脱敏
  -> 将最小必要上下文交给模型
  -> 模型生成解释

模型可以提出“查询订单”的工具调用,但工具服务必须重新验证用户身份、资源归属、参数范围和操作类型。不能把权限信息写进系统提示词后就视为访问控制,因为用户输入、检索文档或工具返回值都可能包含提示注入。

9.2 成本的主要组成

生成式系统的单位成本通常来自:

Crequest=Cinput tokens+Coutput tokens+Cretrieval+Ctool+Ccompute+CobservabilityC_{\text{request}} = C_{\text{input tokens}} + C_{\text{output tokens}} + C_{\text{retrieval}} + C_{\text{tool}} + C_{\text{compute}} + C_{\text{observability}}

托管 API 主要按输入和输出 token、模型档位及具体产品规则计费;自托管则还要考虑 GPU 折旧或租赁、空闲容量、存储、网络和运维。实际价格和参数必须以当前服务商文档为准,不能把某个时间点的价格写成永久规则。

减少成本不能只截断上下文。截断可能删除权限条件、合同例外或用户约束,导致模型产生错误答案。应结合摘要、检索、缓存、批处理、模型路由和输出上限,并用业务成功率验证节省是否值得。


十、常见失败表现与诊断路径

1. 模型“知道但不会按要求回答”

可能原因是基础模型具备知识,但没有经过足够的指令格式训练,或者 chat template 与训练格式不一致。诊断时固定 tokenizer、模板和解码参数,分别测试基础模型与 SFT 模型,并检查 assistant loss mask。

2. 微调后格式变好,但事实变差

可能是 SFT 数据存在错误、领域过窄、样本重复或学习率过高,导致原有能力被覆盖。应比较通用回归集、领域集和事实核验集,而不是只看训练任务的格式准确率。必要时降低训练强度、混入通用数据,或改用检索提供事实。

3. 对齐后模型频繁拒答

安全偏好数据覆盖过宽,或奖励模型把“拒绝”当作低风险捷径。需要把安全测试拆成应拒绝、应回答、应澄清三类,并分别统计拒答精确性,而不是只统计“拒答率”。

4. 离线分数上升,线上满意度下降

线上 prompt、用户分布、工具状态和流量结构可能与离线不一致,也可能出现延迟上升、输出过长或引用缺失。应使用固定回归集加灰度流量,记录完整的模型、提示词、检索和工具版本,并按用户场景分层分析。

5. 生成内容重复或突然截断

重复可能来自高概率循环、训练语料重复、解码设置或停止 token 配置;截断可能来自 max_new_tokens、上下文窗口、客户端断开或服务端超时。日志中应记录结束原因、输入输出 token 数、采样配置和请求取消状态。


十一、从模型训练到生产发布的最小闭环

一个可复现的发布闭环可以按以下顺序执行:

  1. 定义目标:把“更聪明”改写为具体任务、风险指标和成本上限。
  2. 冻结基线:固定旧模型、tokenizer、提示词、解码参数和评测集。
  3. 治理数据:记录来源、权限、清洗、去重、脱敏和数据版本。
  4. 选择改进方式:动态事实优先检索或工具;稳定行为再考虑 SFT、LoRA 或偏好优化。
  5. 训练并保存状态:保存权重、配置、tokenizer、优化器状态、随机种子和数据版本。
  6. 做分层评测:能力、业务、安全、回归和系统性能分别测量。
  7. 审查权限和成本:验证工具权限、数据最小化、单位成本和峰值容量。
  8. 灰度发布:保留旧版本路由和快速回滚开关。
  9. 观察线上反馈:记录失败样本,但先脱敏并控制访问范围。
  10. 将确认过的失败加入回归集:形成下一次版本评测的可追踪输入。

这条闭环的关键不是“每次都训练更大的模型”,而是让每一次数据变化、训练变化、推理配置变化和发布决策都能够被解释、比较和恢复。预训练提供通用能力,指令微调提供任务行为,对齐提供目标约束,推理把能力转化为服务,版本评测则验证这种转化是否真的改善了生产系统。


系列导航与关联阅读

官方资料

本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。