跳转至

第 13 章:参数高效微调:LoRA / QLoRA / PEFT

1. 本章要解决的问题

第 12 章里,我们已经把 SFT 的基本逻辑讲清楚了:

  • 预训练模型已经具备语言能力和知识能力
  • SFT 用高质量示范把这些能力塑造成“会按指令完成任务”的行为
  • 从训练目标上看,SFT 仍然是 next-token prediction,只是训练分布换成了任务示范

但一旦你真的准备动手做微调,就会立刻撞上一个非常现实的问题:

全量微调太贵了。

如果模型只有几亿参数,也许问题还不明显;但当底座模型来到 7B、13B,甚至更大时,事情马上会变得不一样:

  • 模型参数本身占显存
  • 反向传播还要保存梯度
  • 优化器状态往往还要额外占一大块内存
  • 每做一个任务都保存一整份新模型,存储成本也很高

这时我们会发现,很多团队并不是“不想做 SFT”,而是:

想做,但做不起;或者做得起一次,做不起很多次。

这就是 LoRA、QLoRA、PEFT 出现的背景。

从全书结构上看,这一章有三个作用:

  • 它承接第 12 章,把“可以做 SFT”推进到“怎样更省资源地做 SFT”
  • 它把“训练目标”进一步落到“参数该怎么更新、显存怎么省、权重怎么保存”这些工程问题上
  • 它也为第 14 章的偏好对齐铺路,因为很多对齐训练在工程上同样依赖 PEFT,而不是每次都全量改整个底座模型

如果第 12 章回答的是:

当我们有了指令数据,怎样教会模型按示范回答。

那么这一章要回答的就是:

当底座模型已经很大、算力预算又有限时,怎样以更低成本完成这类微调。

2. 你学完后应该会什么

  • 能解释为什么全量微调在大模型时代往往不划算
  • 能理解 PEFT 这个总思路到底在省什么
  • 能说清 LoRA 的核心直觉:冻结大权重,只训练一个低秩增量
  • 能理解 rank、alpha、dropout、target modules 分别在控制什么
  • 能说清 QLoRA 和 LoRA 的区别,以及 4-bit quantization 在这里扮演什么角色
  • 能搭建一个最小可用的 LoRA / QLoRA 微调流程
  • 能理解 adapter 的保存、加载、merge 各是什么意思
  • 能知道什么时候该用 PEFT,什么时候不该盲目用

3. 为什么全量微调越来越不现实

先把最重要的判断讲清楚:

LoRA 不是因为“更高级”才流行,而是因为它更符合大模型时代的资源现实。

3.1 全量微调到底贵在哪里

很多初学者会把“7B 模型”理解成“只要能放进显存里就能训”,但训练和推理不是一回事。

推理时你主要需要:

  • 模型权重
  • KV cache
  • 少量运行时缓存

训练时除此之外还要额外承担:

  • 梯度
  • 优化器状态
  • 激活保存

尤其如果你用的是 AdamW 这类优化器,参数之外还会维护一阶矩、二阶矩等状态。于是实际训练显存远远大于“模型权重本体”。

所以真正的问题不是:

这个模型能不能加载进来。

而是:

这个模型能不能在反向传播和优化时活下来。

3.2 存储成本也会很快爆炸

即使你显存够,全量微调还有另一个容易被忽视的成本:

每个任务都要保存一整份新权重。

想象你有一个 7B 底座模型,之后要做:

  • 中文客服版
  • 医疗问答版
  • 代码解释版
  • 数据分析助手版

如果每个任务都产出一整份完整 checkpoint,那么模型管理会非常笨重。你会很快遇到:

  • 磁盘占用高
  • 分发成本高
  • 版本管理复杂
  • 回滚和比较麻烦

3.3 很多任务其实不需要“重写整个模型”

更关键的是,很多下游任务并不要求你把底座模型的全部知识重新学一遍。

很多时候你只是想让它:

  • 学会某种回答风格
  • 掌握某类格式约束
  • 对某个领域任务更稳定
  • 对某些特定模式更敏感

这类变化未必需要改动全部参数。

于是一个很自然的问题就出现了:

有没有办法保留大模型原有能力,只用很少一部分新增参数来表达“这次任务需要的偏移量”?

LoRA 的答案就是:有。

4. PEFT:参数高效微调到底在省什么

PEFT 是 Parameter-Efficient Fine-Tuning 的缩写。

它不是单一算法,而是一大类思路的总称。它们的共同目标是:

尽量少更新参数、尽量少增加显存开销,同时保留接近全量微调的任务适配能力。

4.1 它省的不是一步,而是整条链路

当我们说 PEFT 更省资源时,通常是在同时节省几样东西:

  • 可训练参数数量
  • 梯度和优化器状态
  • 每个任务需要额外保存的权重体积
  • 多任务切换时的部署成本

注意这里有一个常见误区:

PEFT 不一定让前向计算本身便宜很多,但它往往能显著降低训练和存储成本。

4.2 常见 PEFT 方法里,LoRA 为什么最流行

PEFT 不是只有 LoRA。

历史上还出现过各种方法,例如:

  • 只训练 bias
  • prefix tuning
  • prompt tuning
  • adapter tuning

但 LoRA 之所以广泛流行,是因为它在几个维度上取得了很好的平衡:

  • 原理直观
  • 改动小
  • 与 Transformer 结构天然兼容
  • 参数量低
  • 实践中效果稳定
  • 工具链成熟

所以今天很多人提到“做 PEFT”,实际默认说的就是“做 LoRA 或 QLoRA”。

5. LoRA 的核心直觉:不要重训整个矩阵,只学一个低秩增量

这一节是整章最关键的原理部分。

先从线性层开始。

假设模型里有一个权重矩阵:

W ∈ R^(d_out × d_in)

全量微调的做法是直接更新整个 W。也就是训练后得到:

W' = W + ΔW

这里的 ΔWW 一样大,所以你本质上还是在训练一整个大矩阵。

LoRA 的想法是:

也许这个任务需要的改动,本质上并不需要一个满秩的大矩阵来表达。

于是它把增量写成两个小矩阵的乘积:

ΔW = B A

其中:

  • A ∈ R^(r × d_in)
  • B ∈ R^(d_out × r)
  • r 远小于 d_ind_out

于是新的权重变成:

W' = W + B A

而训练时:

  • 原始权重 W 冻结
  • 只训练 AB

这就是 LoRA 最核心的结构。

5.1 为什么叫 low-rank

因为 BA 的秩最多不会超过 r

r 很小时,这个增量矩阵就只能表达一个相对低维的变化子空间。直觉上就是:

我们不允许模型朝任意方向大改,只允许它在一个低维增量空间里做任务适配。

这听起来像是在“限制模型”,但实际经验发现:

很多下游适配任务,本来就不需要改那么多自由度。

5.2 一个非常重要的直觉

LoRA 并不是说原始权重不重要,恰恰相反:

原始预训练权重非常重要,所以我们尽量不碰它,只在旁边加一个小修正。

可以把它理解成:

  • 预训练底座负责提供通用能力
  • LoRA 增量负责把能力轻推到某个任务方向

这也是为什么 LoRA 往往特别适合:

  • 指令跟随增强
  • 领域化适配
  • 风格迁移
  • 小规模数据上的快速定制

6. LoRA 到底插在哪些地方

LoRA 理论上可以加在很多线性层上,但在 Transformer 里,最常见的是加在 attention 和 MLP 的投影层上。

6.1 最常见的 target modules

不同模型命名会不一样,但经常能看到这些模块:

  • q_proj
  • k_proj
  • v_proj
  • o_proj
  • up_proj
  • down_proj
  • gate_proj

其中最常见的起点通常是:

  • 先打在 attention 的 q_projv_proj
  • 或者同时覆盖大部分主要线性层

6.2 为什么不是所有层都必须加

因为 LoRA 追求的是“足够表达任务偏移”,不是“尽可能多改”。

如果 target modules 选得太保守,可能:

  • 参数太少
  • 模型适配能力不够

但如果选得太激进,也可能:

  • 可训练参数显著上升
  • 训练更慢
  • 更容易过拟合小数据

所以 target modules 本质上是在回答一个问题:

你希望任务信号主要通过哪些计算路径进入模型。

7. rank、alpha、dropout 分别在控制什么

LoRA 训练里最常见的几个超参数是:

  • r
  • lora_alpha
  • lora_dropout

理解它们,比死记推荐默认值重要得多。

7.1 r:低秩空间的容量

r 就是 rank,也就是低秩分解里的中间维度。

可以粗略理解成:

LoRA 适配器到底有多大的表达容量。

一般来说:

  • r 小:参数更少,更省,但表达能力更弱
  • r 大:表达能力更强,但训练成本更高,也更容易过拟合

它不是越大越好,而是要和任务复杂度、数据量一起看。

7.2 lora_alpha:对增量更新的缩放

LoRA 实际使用时,常会对 BA 再乘一个缩放系数,典型写法类似:

W' = W + (alpha / r) * B A

它的作用可以理解为:

控制 LoRA 增量注入主干权重时的强度。

如果 alpha 太小,适配器学到的变化即使存在,注入后影响也弱;如果太大,则可能让训练更不稳定。

7.3 lora_dropout:不是给底座加 dropout,而是给适配路径加 dropout

这点很多人第一次会混淆。

lora_dropout 一般是作用在 LoRA 支路上,而不是把整个底座模型都重新改成更强 dropout。

它主要是为了:

  • 减少小数据过拟合
  • 让 LoRA 增量不要过度依赖少量路径

如果你的数据量非常小,适当的 dropout 往往比一味增大 rank 更稳。

8. 从训练视角看,LoRA 到底省了什么

这里值得把账再算一遍。

8.1 可训练参数少了

原来一个大矩阵 W 全量训练要更新 d_out × d_in 个参数。

LoRA 只训练:

r × d_in + d_out × r

如果 r 很小,这个数量会比原矩阵小很多。

8.2 梯度和优化器状态也跟着少了

因为冻结的参数不需要维护梯度和优化器状态,所以真正省掉的不只是“参数文件大小”,而是训练期间最贵的一块内存负担。

这也是 LoRA 实际上非常有价值的地方:

它让“大模型适配”从只有高预算团队能做,变成个人或小团队也有机会做。

8.3 每个任务只需保存 adapter

训练结束后,你不一定要保存一整份大模型,而是只保存 LoRA adapter 权重。

这样做的好处非常直接:

  • 文件小很多
  • 多任务切换方便
  • 底座模型可复用
  • 分发和部署更轻

所以很多团队的做法是:

  • 维护一个稳定的 base model
  • 针对不同业务场景训练多个 adapter
  • 需要哪个任务,就加载哪个 adapter

9. QLoRA:为什么还要再加量化

LoRA 已经省了很多训练参数,但还有一个没解决的问题:

底座模型本身还是很大。

即使你冻结它,单是把它加载进显存,也可能已经很吃紧。

于是 QLoRA 更进一步:

既然底座模型冻结,那能不能把冻结权重用更低精度存起来,从而进一步节省显存?

答案就是 QLoRA。

9.1 QLoRA 的核心思路

可以把 QLoRA 概括成一句话:

把冻结的底座模型量化到 4-bit 附近,再在其上训练 LoRA adapter。

也就是说:

  • 底座模型:量化存储,减少显存
  • 可训练部分:仍然是 LoRA adapter
  • 反向传播:主要穿过 adapter 路径

因此,QLoRA 不是“量化后全量训练”,而是:

量化底座 + LoRA 微调。

9.2 为什么这件事成立

因为 LoRA 本来就不更新底座大权重。

既然底座只是前向时提供能力底盘,那么我们可以接受:

  • 用更紧凑的格式存它
  • 在计算时做必要的反量化或混合精度处理

这样就能在不显著牺牲效果的前提下,把训练资源门槛再往下压一大截。

9.3 常见关键词:4-bit、NF4、double quantization

你在 QLoRA 资料里经常会看到这些词:

  • 4-bit quantization
  • NF4
  • double quantization

作为本书这一阶段,你先抓住三点就够了:

  • 4-bit 的目标是压缩冻结权重占用
  • NF4 是一种更适合正态分布权重的 4-bit 表示方式
  • double quantization 是进一步减少量化常数本身的存储开销

这里你不需要先钻进所有量化数学细节,先理解工程目标更重要:

QLoRA 的第一价值,是让本来放不下、训不起的模型,变成“可以在更有限资源下做微调”。

10. LoRA 和 QLoRA 到底有什么区别

很多人会把这两个词混用,但最好明确区分。

10.1 LoRA 关注的是“怎么少训练”

LoRA 的重点是:

  • 冻结大权重
  • 只训练低秩增量

它解决的是:

训练参数太多、优化器状态太大、每任务存储太重。

10.2 QLoRA 关注的是“怎么让底座更省显存地被加载”

QLoRA 在 LoRA 基础上再加一层:

  • 把底座量化

它进一步解决的是:

即使不训练底座,它本身加载起来也太占显存。

所以可以把关系记成:

  • LoRA:参数高效微调
  • QLoRA:量化底座上的 LoRA 微调

换句话说:

QLoRA 不是 LoRA 的竞争者,而是 LoRA 在显存更紧场景下的一种更激进实现。

11. PEFT 工程实践里最常见的工作流

到这里,我们把概念转成操作流程。

一个最常见的 LoRA / QLoRA 微调链路通常长这样:

  1. 选择一个 instruction-tuned 或 base 模型作为底座
  2. 准备与第 12 章一致的 SFT 数据
  3. 加载 tokenizer 和 base model
  4. 如果做 QLoRA,则用 4-bit 方式加载冻结底座
  5. 配置 LoRA adapter,并指定 target modules
  6. 只训练 LoRA 参数
  7. 保存 adapter
  8. 推理时把 adapter 挂回底座,或在需要时 merge

11.1 最关键的心智模型

这条流程里,数据侧其实没有变。

第 12 章里你学会的:

  • 指令数据组织
  • chat template
  • labels 和 loss mask
  • 训练评估逻辑

在这一章仍然都成立。

真正变化的是模型侧:

不是改“训练目标”,而是改“哪些参数能动、底座以什么精度存在”。

12. 一个最小 LoRA 代码例子

下面给一个偏教学化的最小示意,帮助你看清楚 LoRA 是怎样接到 Hugging Face / PEFT 工作流里的。

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model

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

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

lora_config = LoraConfig(
    r=8,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj"],
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

这段代码做了几件事:

  • 加载原始 causal LM
  • 定义 LoRA 配置
  • 指定要插入 LoRA 的模块
  • 把普通模型包装成 PEFT 模型

这时如果你去看参数状态,会发现:

  • 底座绝大部分参数被冻结
  • 只有 LoRA 相关参数是可训练的

然后你的训练代码,原则上就可以继续沿用第 12 章那套 SFT 流程。

13. 一个最小 QLoRA 代码例子

如果切到 QLoRA,常见区别主要出现在模型加载阶段。

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
import torch

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

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=True,
    bnb_4bit_compute_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
)

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

要注意的是,这段代码只是最小示意,不代表所有模型都该照抄同一组 target modules 或超参数。

但它足够说明一个本质:

QLoRA 和普通 SFT 最大的工程差异,不在数据,而在“量化底座 + LoRA 包装”这一步。

14. 保存、加载、merge:adapter 生命周期怎么理解

这一节很实用,因为很多人第一次做完训练后,并不知道该怎么理解产物。

14.1 保存 adapter,不是保存整模型

在 LoRA / QLoRA 训练里,最常见的保存方式是:

只保存适配器权重。

因为真正变化的是 LoRA 参数,而不是整个 base model。

这意味着你的 checkpoint 通常会比全量微调小很多。

14.2 推理时需要“底座 + adapter”

如果你只保存了 adapter,那么推理时并不是单独加载它就够了,而是要:

  • 先加载与训练时一致的底座模型
  • 再把 adapter 挂上去

这背后的逻辑非常自然:

adapter 表达的是“相对底座的增量”,不是一个能独立存在的完整模型。

14.3 merge 的含义

有些时候你会看到 merge_and_unload() 这类操作。

它的意思通常是:

把 LoRA 增量真正并回主权重,得到一份不再依赖独立 adapter 的模型。

这样做的优点可能是:

  • 部署链路更简单
  • 某些推理框架兼容性更好

但代价是:

  • 失去“一个底座切多个 adapter”的轻量切换优势
  • 产物体积可能重新变大

所以是否 merge,不是固定答案,而是部署选择。

15. 一个可展示的微调项目应该怎么设计

如果你想把这一章真正落成作品,最好的方式不是只跑通训练脚本,而是做一个能讲清楚实验逻辑的小项目。

15.1 一个适合展示的项目结构

你可以选择一个足够具体、但又不至于太重的任务,例如:

  • 把通用模型微调成“机器学习概念讲解助手”
  • 把通用模型微调成“中文论文摘要助手”
  • 把通用模型微调成“SQL 问题解释助手”

项目里最好明确交代四件事:

  • 任务是什么
  • 数据怎么来、怎么清洗
  • 为什么选 LoRA 或 QLoRA
  • 微调前后有什么实际变化

15.2 最值得展示的不是 loss 曲线,而是行为变化

很多项目容易犯的错是:

  • 放一堆训练日志
  • 放一堆超参数表
  • 但看不出模型到底变好了什么

更好的展示方式是直接对比:

  • 微调前回答
  • 微调后回答
  • 哪些行为变稳了
  • 哪些问题仍然没解决

例如可以重点展示:

  • 是否更遵守输出格式
  • 是否更少答非所问
  • 是否更符合目标领域表达
  • 是否对关键术语解释更稳定

15.3 最小实验矩阵就够了

你不需要一上来做十几组实验。

一个很实用的最小矩阵是:

  • baseline:不微调
  • LoRA:较小 rank
  • LoRA:较大 rank
  • QLoRA:同任务、相近配置

你真正想回答的是:

在你的任务上,参数效率方案到底换来了什么,牺牲了什么。

16. LoRA / QLoRA 常见坑

这一节非常重要,因为很多人“跑通了”,但结果不稳定,往往是踩了工程坑。

16.1 target modules 选错或没覆盖

如果模型结构和你预想的不一样,而你照着别人的名字填 q_projv_proj,可能会出现:

  • 根本没插进去
  • 只插进了很少一部分层
  • 可训练参数数量异常

所以第一件事通常是检查模型模块名,而不是盲抄配置。

16.2 chat template 不一致

这一坑并不是 LoRA 独有,但在微调项目里非常常见。

如果训练时和推理时用的对话模板不一致,就会出现:

  • 格式变怪
  • 角色混乱
  • 输出风格偏移

这时很多人会误以为“LoRA 效果不好”,其实问题出在第 12 章讲过的数据拼接协议。

16.3 只看训练 loss,不看真实样本

LoRA 参数少,并不意味着它不会过拟合。

尤其当你的数据:

  • 很少
  • 很重复
  • 风格单一

模型可能很快把训练集模式学得很紧,但泛化并不好。

所以最值得坚持的做法仍然是:

  • 留出验证样本
  • 固定一组人工检查 prompt
  • 比较微调前后真实输出

16.4 量化配置和硬件精度不匹配

做 QLoRA 时,如果量化配置、计算 dtype、硬件支持没有协调好,可能会碰到:

  • 训练不稳定
  • 显存节省不如预期
  • 某些层报错

这类问题往往不是“理论错了”,而是工程栈兼容性问题。

16.5 以为 PEFT 可以无脑代替全量微调

这是另一个常见误区。

PEFT 很强,但不是对所有任务都一定最优。

如果你的任务需要:

  • 对模型内部能力做非常深层重塑
  • 大规模跨分布迁移
  • 极强的任务专门化

那么 LoRA 不一定总能替代全量微调。

正确理解应该是:

PEFT 是非常强的默认起点,但不是永远唯一答案。

17. LoRA / QLoRA 和第 14 章偏好对齐的关系

这一节是为了把全书主线接起来。

第 12 章我们讲 SFT,本质是在学:

给定指令,什么叫“像样的回答”。

第 13 章我们讲 LoRA / QLoRA,本质是在学:

怎样更省资源地完成这种微调。

而第 14 章要继续往前走,讨论的是:

如果“像样的回答”不只取决于标准答案,而更多取决于偏好比较,我们该怎么训练?

所以顺序非常自然:

  1. 先有预训练底座
  2. 再用 SFT 学会基本指令跟随
  3. 再用 PEFT 把这件事做得更现实、更省钱
  4. 最后进入偏好对齐,学习更细粒度的“哪种回答更好”

更重要的是,在实际工程里:

很多 DPO、RLHF、RLAIF 实验,底层也会继续使用 LoRA 或 QLoRA。

因为偏好对齐本身通常也不便宜,而 PEFT 能显著降低试验门槛。

18. 常见误区

18.1 “LoRA 就是蒸馏”

不是。

蒸馏强调的是:

  • 用一个教师模型指导学生模型

LoRA 强调的是:

  • 在同一个底座模型上,用低秩适配器完成参数高效微调

两者解决的问题不同。

18.2 “做了 LoRA,就等于不需要高质量数据”

也不是。

LoRA 只是降低参数更新成本,并不会自动提高数据质量。

如果训练数据本身:

  • 风格混乱
  • 标注不一致
  • 任务边界不清

那 LoRA 一样会学歪。

18.3 “rank 越大效果一定越好”

不成立。

更大的 rank 确实增加表达能力,但也带来:

  • 更多参数
  • 更多显存
  • 更大过拟合风险

它是容量旋钮,不是无脑拉满的指标。

18.4 “QLoRA 一定和 LoRA 一样稳”

也不能这么说。

QLoRA 的资源效率更高,但因为引入了量化,工程复杂度通常也更高。你需要在:

  • 显存预算
  • 训练稳定性
  • 工具链兼容性

之间做平衡。

19. 面试问题

19.1 为什么 LoRA 能省显存

因为它冻结大部分底座参数,只训练少量低秩适配器参数,因此可训练参数、梯度和优化器状态都显著减少。

19.2 LoRA 和全量微调的核心区别是什么

全量微调直接更新原模型全部或大部分参数;LoRA 保留原始权重不动,只学习一个低秩增量并叠加到指定线性层上。

19.3 QLoRA 比 LoRA 多做了什么

QLoRA 在 LoRA 基础上把冻结底座模型量化到更低比特数,从而进一步降低底座加载时的显存占用。

19.4 LoRA 的 rank 是什么

rank 是低秩分解的中间维度,决定适配器的表达容量。rank 越大,参数更多、容量更强,但成本和过拟合风险也会上升。

19.5 adapter 为什么可以单独保存

因为 LoRA 学到的是相对底座权重的增量,而底座本身没有被改动,所以每个任务只需要单独保存这组增量参数。

19.6 为什么做 LoRA 仍然需要关心第 12 章的数据模板

因为 LoRA 只是改变“怎么训练参数”,并没有改变“模型到底在学什么输入输出分布”。如果 chat template、labels 或 loss mask 出错,LoRA 一样会学坏。

20. 小结

这一章最重要的结论可以压缩成四句话:

  • 第 12 章解决的是“怎样做 SFT”,这一章解决的是“怎样更省资源地做 SFT”
  • LoRA 的核心是冻结底座,只训练低秩增量
  • QLoRA 的核心是在 LoRA 基础上,把冻结底座进一步量化来省显存
  • PEFT 改变的主要是参数更新方式,不改变第 12 章那套数据、模板和训练目标的基本逻辑

如果说第 12 章让我们第一次具备了“把模型训练成助手”的能力,那么这一章真正带来的,是把这件事从“理论上能做”推进到“预算有限时也能做”。

下一章我们继续往前走。

当模型已经会按指令回答,而且我们也知道怎样低成本地训练它后,新的问题就会变成:

两条回答都看起来合理时,模型到底该更偏向哪一种?

这就是偏好对齐要处理的问题。