第三章:基础模型选择——基座模型 vs 指令微调模型、开源模型选型与下载加载

好,咱们进入第三章。说实话,这一章是很多同学容易忽略、但实际踩坑最多的地方。你想想看,模型选错了,后面整个RLHF流水线都得推倒重来。我当年第一次搭流水线时,就因为在基座模型和指令微调模型之间选错了,白白浪费了两周算力。嗯,今天咱们就把这事彻底聊透。

3.1 基座模型 vs 指令微调模型:到底该选谁?

先问个问题:你手头有一个基座模型(Base Model)和一个指令微调模型(Instruct/Chat Model),你选哪个作为RLHF的起点?

我个人习惯是:绝大多数场景下,选基座模型。为什么?

  • 基座模型:只在大量文本上做过预训练,没经过任何指令对齐。它的输出分布更“原始”,RLHF的奖励模型和策略优化可以自由地塑造它的行为,不受之前SFT(监督微调)的约束。
  • 指令微调模型:已经经过SFT对齐,输出已经偏向某种“听话”模式。你再用RLHF去优化,相当于在已经画好的画上再改,容易产生分布偏移,甚至出现“过拟合”到奖励模型的问题。

核心原则:RLHF的目的是让模型学会你的偏好,而不是继承别人的偏好。基座模型是一张白纸,指令微调模型是一张已经画了草稿的纸。

不过,也有例外。我记得有一次项目时间特别紧,团队直接拿一个开源的Chat模型做RLHF,效果居然还不错。后来分析发现,那个Chat模型的SFT数据和我们RLHF的偏好数据高度一致。所以,如果你能确认SFT阶段的数据分布和RLHF阶段的目标高度重合,用指令微调模型也能省不少事。

避坑指南:我曾经在某个项目中,直接用Chat模型做RLHF,结果模型在训练初期就出现了“奖励黑客”现象——它学会了说一些看似合理但实际空洞的套话,因为SFT阶段教会了它“礼貌”,而RLHF的奖励模型恰好喜欢这种风格。最后不得不回退到基座模型重新开始。

3.2 开源模型选型:LLaMA、Qwen、Mistral 怎么挑?

现在开源模型多如牛毛,我帮你梳理一下主流选择。直接上表格,一目了然:

模型系列 特点 适合场景 我的经验
LLaMA (Meta) 社区生态最丰富,训练稳定,中文支持一般 英文为主的RLHF实验,学术研究 我最早用的就是LLaMA,文档和工具链最成熟
Qwen (阿里) 中文能力极强,多语言支持好,有专门的RLHF版本 中文场景、多语言任务 做中文项目时,Qwen是我的首选,省去很多中文对齐的麻烦
Mistral (Mistral AI) 推理效率高,参数量小但性能强,MoE架构 资源受限、需要快速迭代的场景 我记得有一次用Mistral 7B做RLHF,效果居然和LLaMA-13B差不多,但训练速度快了一倍
Falcon (TII) 开源早,但社区活跃度下降 历史兼容性需求 现在不太推荐了,生态不如前三者

选型时,我建议你考虑三个维度:

  1. 语言覆盖:你的RLHF数据主要是中文还是英文?中文无脑选Qwen,英文选LLaMA或Mistral。
  2. 算力预算:如果你只有单卡A100 80G,Mistral 7B或Qwen-7B是安全牌。LLaMA-13B以上就需要多卡了。
  3. 社区支持:LLaMA的HuggingFace生态最全,各种RLHF工具(如TRL、DeepSpeed)都优先支持它。Qwen和Mistral的兼容性也在快速追赶。

小技巧:我个人习惯先选一个7B左右的模型做快速原型验证,跑通整个RLHF流水线后,再换更大的模型做正式训练。这样能快速发现数据或代码中的bug,避免浪费大算力。

3.3 模型下载与加载:别让这一步卡住你

模型下载看似简单,但坑不少。我直接给你一个最稳的流程:

第一步:用HuggingFace Hub下载

# 推荐使用 snapshot_download,避免断点续传问题
from huggingface_hub import snapshot_download

# 下载Qwen-7B基座模型
snapshot_download(
    repo_id="Qwen/Qwen-7B",
    local_dir="./models/Qwen-7B-base",
    local_dir_use_symlinks=False,
    resume_download=True  # 断点续传,我经常用
)

注意:我曾经在下载LLaMA-2时,因为网络不稳定,下载了一半的文件损坏。后来加载模型时各种报错,排查了半天才发现是权重文件不完整。所以,resume_download=Truelocal_dir_use_symlinks=False 这两个参数一定要加上。

第二步:加载模型和Tokenizer

from transformers import AutoModelForCausalLM, AutoTokenizer

model_path = "./models/Qwen-7B-base"

# 加载模型,注意设置 torch_dtype 和 device_map
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype="auto",          # 自动选择float16或bfloat16
    device_map="auto",           # 自动分配到多GPU
    trust_remote_code=True       # Qwen等模型需要这个
)

# 加载Tokenizer
tokenizer = AutoTokenizer.from_pretrained(
    model_path,
    trust_remote_code=True,
    padding_side="left"          # RLHF中生成时,padding在左边很重要
)

关键点padding_side="left" 是RLHF训练中容易忽略的细节。因为我们在生成响应时,需要把prompt放在左边,padding在左边才能保证生成的位置正确。我见过好几个同学因为默认的right padding导致生成结果错位。

3.4 Tokenizer配置:细节决定成败

Tokenizer看似简单,但配置不对,整个RLHF训练都会出问题。我总结几个必查项:

  • 特殊Token:检查模型是否有 <|im_start|><|im_end|> 等对话模板token。Qwen和ChatGLM都有自己的一套,加载时一定要用对应的tokenizer。
  • Vocabulary Size:确保tokenizer的vocab_size和模型配置中的一致。不一致会导致embedding层维度不匹配,加载时报错。
  • Padding Token:很多基座模型没有默认的padding token。你需要手动设置:tokenizer.pad_token = tokenizer.eos_token 或者添加一个新的 [PAD] token。
# 检查并设置padding token
if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token
    # 或者添加新的pad token
    # tokenizer.add_special_tokens({'pad_token': '[PAD]'})
    # model.resize_token_embeddings(len(tokenizer))

我的习惯:每次加载新模型,我都会先打印tokenizer的所有特殊token,确认一遍:print(tokenizer.special_tokens_map)。这一步能避免很多后续的坑。

3.5 本章知识体系总览

下面这张图,帮你把本章的核心逻辑串起来:

基础模型选择核心流程 选模型类型 基座模型 vs 指令微调模型 选模型系列 LLaMA / Qwen / Mistral 下载模型 snapshot_download 加载模型 AutoModel + device_map 配置Tokenizer padding_side / 特殊token 验证可用性 打印special_tokens_map 选对基座模型 → 下载完整权重 → 正确加载 → 配置Tokenizer 每一步都验证,避免后期返工

嗯,以上就是第三章的全部内容。模型选型和加载是RLHF流水线的地基,地基不稳,后面全是白费。我个人建议你花点时间,把每个模型的加载流程都跑一遍,打印出tokenizer和模型配置,做到心中有数。

专注资料整理