由于水平原因,博客大部分内容摘抄于网络,如有错误或者侵权请指出,本人将尽快修改

模型微调

LLaMA-Factory 大模型微调实操指南(实战版)

本指南基于实际项目经验编写,覆盖 环境安装 → 数据准备 → YAML 配置 → 训练启动 → 模型测试 → 合并导出 全流程。所有命令可直接执行,每个关键步骤附带预期输出。


下载微调工具LlamaFactory:https://github.com/hiyouga/LlamaFactory.git

1 环境安装

1.1 基础环境确认

# 确认 CUDA
cd ~
nvcc -V

预期输出:

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Cuda compilation tools, release 12.2, V12.2.140

1.2 创建虚拟环境

conda create -n llama_factory python=3.10
conda activate llama_factory

1.3 安装 PyTorch

conda install pytorch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 pytorch-cuda=12.1 -c pytorch -c nvidia

1.4 安装 LLaMA-Factory

cd ~
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
# 以可编辑模式安装当前目录下的 Python 包,并额外安装 torch 和 metrics 相关的依赖。
pip install -e ".[torch,metrics]"

预期输出:

Successfully installed llamafactory-0.x.x ...

1.5 验证安装

python -m llamafactory.cli train -h

预期输出(节选):

usage: llamafactory-cli train [-h] [ARGS...]

training arguments:
  --stage {pt,sft,rm,ppo,dpo,kto}
  --do_train {True,False}
  --model_name_or_path MODEL_NAME_OR_PATH
  ...

说明: python -m llamafactory.clillamafactory-cli 更兼容,即使环境变量 PATH 没配好也能跑。


2 数据准备

2.1 创建数据集

cd ~/LLaMA-Factory/data
# 创建你的数据集文件
touch my_data.json

SFT 数据格式(Alpaca):

[
  {
    "instruction": "你是谁",
    "input": "",
    "output": "我是甄嬛,家父是大理寺少卿甄远道"
  },
  {
    "instruction": "帮我写一封请假条",
    "input": "",
    "output": "尊敬的张老师:\n\n您好!因身体不适,特向您请假一天..."
  }
]

DPO 偏好数据格式:

[
  {
    "instruction": "写一段关于春天的描写",
    "input": "",
    "chosen_output": "春风拂过柳梢,桃花映红了小桥流水,燕子在檐下呢喃。",
    "rejected_output": "春天来了,花开了,树绿了。"
  }
]

2.2 注册数据集

编辑 ~/LLaMA-Factory/data/dataset_info.json

{
  "my_data": {
    "file_name": "my_data.json"
  },
  "my_data_dpo": {
    "file_name": "my_data_dpo.json",
    "ranking": true
  }
}

关键: DPO 数据必须加 "ranking": true,否则 LLaMA-Factory 不会识别 chosen/rejected。


3 创建 YAML 配置文件

YAML 配置是最推荐的训练方式,可复用、可版本管理。

3.1 SFT 配置示例

创建 ~/LLaMA-Factory/my_train.yaml

### model
model_name_or_path: Qwen/Qwen2.5-3B-Instruct
trust_remote_code: true

### method
stage: sft
do_train: true
finetuning_type: lora
lora_rank: 8
lora_target: all

### dataset
dataset: my_data
template: qwen
cutoff_len: 1024
max_samples: 500
overwrite_cache: true

### output
output_dir: saves/my_model/lora/sft
logging_steps: 10
save_steps: 500
plot_loss: true
overwrite_output_dir: true
report_to: none

### train
per_device_train_batch_size: 1
gradient_accumulation_steps: 4
learning_rate: 1.0e-4
num_train_epochs: 3.0
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true

3.2 DPO 配置示例

### model
model_name_or_path: Qwen/Qwen2.5-3B-Instruct
adapter_name_or_path: saves/my_model/lora/sft   # 基于 SFT 的 LoRA 继续训练
trust_remote_code: true

### method
stage: dpo
do_train: true
finetuning_type: lora
lora_rank: 8
lora_target: all

### dataset
dataset: my_data_dpo
template: qwen
cutoff_len: 1024
max_samples: 500
overwrite_cache: true

### output
output_dir: saves/my_model/lora/dpo
logging_steps: 10
save_steps: 500
plot_loss: true
overwrite_output_dir: true
report_to: none

### train
per_device_train_batch_size: 1
gradient_accumulation_steps: 4
learning_rate: 5.0e-5
num_train_epochs: 2.0
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true

### dpo
dpo_beta: 0.1

3.3 核心参数详解

参数 作用 建议值 说明
model_name_or_path 基础模型 Qwen/Qwen2.5-3B-Instruct 自动从 ModelScope 下载
trust_remote_code 信任远程代码 true Qwen 系列需要
stage 训练阶段 sft / dpo / pt
finetuning_type 微调方式 lora 个人练习首选
lora_rank LoRA 秩 8 效果与显存的平衡点
lora_target 作用层 all 初学者用 all,只作用注意力层用 q_proj,v_proj
dataset 数据集名称 my_data 对应 dataset_info.json 中的 key
template 提示词模板 qwen 必须与模型匹配
cutoff_len 最大序列长度 1024 根据数据长度调整
learning_rate 学习率 1e-4 (LoRA) / 5e-5 (DPO) LoRA 用较大学习率
num_train_epochs 训练轮数 3 数据量 1000 条左右时 3 轮
per_device_train_batch_size 单卡 batch 1 显存有限时设为 1
gradient_accumulation_steps 梯度累积 4 等效 batch = 1×4=4
bf16 bfloat16 精度 true Ampere 架构(30系/40系/A100)支持
dpo_beta DPO KL 系数 0.1 越大越保守

3.4 15GB 显存配置要点

# 15GB 显存稳妥配置
model_name_or_path: Qwen/Qwen2.5-3B-Instruct   # 3B 模型约 6GB
finetuning_type: lora                           # LoRA 约 2GB
per_device_train_batch_size: 1                  # 1GB
gradient_accumulation_steps: 4                  # 不增加显存
cutoff_len: 1024                                # 序列长度
bf16: true                                      # 省显存
# 总计约 10GB,留 5GB 余量

15GB 跑 3B 模型很稳。想上 7B 需要 QLoRA(quantization_bit: 4),但效果会打折。


4 启动训练

4.1 使用 ModelScope 下载模型(国内网络必备)

export USE_MODELSCOPE_HUB=1
cd ~/LLaMA-Factory
python -m llamafactory.cli train my_train.yaml

预期输出(首次运行会自动下载模型):

[INFO] Using ModelScope Hub
[INFO] Downloading model Qwen/Qwen2.5-3B-Instruct from ModelScope...
[INFO] Loading dataset my_data from data/my_data.json
[INFO] trainable params: 9,994,240 || all params: 3,000,000,000 || trainable%: 0.33
...
{'loss': 2.3451, 'learning_rate': 9.95e-05, 'epoch': 0.01}
{'loss': 1.8723, 'learning_rate': 9.50e-05, 'epoch': 0.05}
...
{'loss': 0.5891, 'learning_rate': 5.00e-07, 'epoch': 1.00}
...
***** train metrics *****
  train_loss = 0.9876
  train_runtime = 0:25:32

关键: USE_MODELSCOPE_HUB=1 让模型自动从 ModelScope(国内)下载,不走 HuggingFace(需要FQ)。

4.2 中断后继续训练

在 YAML 中增加:

resume_from_checkpoint: saves/my_model/lora/sft/checkpoint-500

或在命令行指定:

python -m llamafactory.cli train my_train.yaml \
    --resume_from_checkpoint saves/my_model/lora/sft/checkpoint-500

4.3 多卡训练

CUDA_VISIBLE_DEVICES=0,1 python -m llamafactory.cli train my_train.yaml

LLaMA-Factory 会自动使用 PyTorch DDP 分布式训练。


5 测试微调后的模型

5.1 使用 transformers + peft 测试(推荐,可集成到代码)

创建 ~/LLaMA-Factory/test_my_model.py

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
import torch

# 基础模型路径(从 ModelScope 缓存或本地)
BASE_PATH = "/root/.cache/modelscope/hub/models/Qwen/Qwen2___5-3B-Instruct"
ADAPTER_PATH = "saves/my_model/lora/sft"

# 加载 tokenizer
tokenizer = AutoTokenizer.from_pretrained(BASE_PATH, trust_remote_code=True)

# 加载基础模型
model = AutoModelForCausalLM.from_pretrained(
    BASE_PATH,
    torch_dtype=torch.bfloat16,
    device_map="cuda",
    trust_remote_code=True,
)

# 加载 LoRA 权重
model = PeftModel.from_pretrained(model, ADAPTER_PATH)
model.eval()

# 测试
prompt = "你是谁"
messages = [
    {"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
    {"role": "user", "content": prompt},
]

# 构建 prompt
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)

# 编码输入
inputs = tokenizer(text, return_tensors="pt").to("cuda")

# 生成
with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=200,
        do_sample=True,
        temperature=0.7,
        top_p=0.9,
    )

# 解码输出(只取新生成的部分)
response = tokenizer.decode(
    outputs[0][inputs["input_ids"].shape[1]:],
    skip_special_tokens=True
)
print(response)

运行:

cd ~/LLaMA-Factory
python test_my_model.py

预期输出:

我是甄嬛,家父是大理寺少卿甄远道。

代码要点:

  • device_map="cuda" 直接放 GPU(也可以 "auto" 自动分配)
  • trust_remote_code=True Qwen 系列必须加
  • outputs[0][inputs["input_ids"].shape[1]:] 只取新生成的 token,不重复输入

5.2 使用 LLaMA-Factory 命令行测试

CUDA_VISIBLE_DEVICES=0 python -m llamafactory.cli chat \
    --model_name_or_path Qwen/Qwen2.5-3B-Instruct \
    --adapter_name_or_path saves/my_model/lora/sft \
    --template qwen \
    --finetuning_type lora

预期交互:

User> 你是谁
Assistant> 我是甄嬛,家父是大理寺少卿甄远道

6 合并导出

LoRA 权重需要合并到基础模型才能独立使用。

6.1 使用 LLaMA-Factory 合并

CUDA_VISIBLE_DEVICES=0 python -m llamafactory.cli export \
    --model_name_or_path Qwen/Qwen2.5-3B-Instruct \
    --adapter_name_or_path saves/my_model/lora/sft \
    --template qwen \
    --finetuning_type lora \
    --export_dir ./my-merged-model \
    --export_size 2 \
    --export_device cpu \
    --export_legacy_format False

预期输出:

[INFO] Loading model from Qwen/Qwen2.5-3B-Instruct
[INFO] Loading adapter from saves/my_model/lora/sft
[INFO] Merging adapter weights into model
[INFO] Saving merged model to ./my-merged-model
model-00001-of-00002.safetensors
model-00002-of-00002.safetensors
config.json
tokenizer.json

6.2 合并后测试

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

MODEL_PATH = "./my-merged-model"

tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_PATH,
    torch_dtype=torch.bfloat16,
    device_map="cuda",
    trust_remote_code=True,
)
model.eval()

# 直接推理,不需要 peft
messages = [{"role": "user", "content": "你是谁"}]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to("cuda")

with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=200)

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

7 完整流程速查

# Step 1: 准备数据
cd ~/LLaMA-Factory/data
vim my_data.json          # 写入数据
vim dataset_info.json     # 注册数据集

# Step 2: 写 YAML 配置
cd ~/LLaMA-Factory
vim my_train.yaml         # 写入训练配置

# Step 3: 启动训练
export USE_MODELSCOPE_HUB=1
python -m llamafactory.cli train my_train.yaml

# Step 4: 测试
python test_my_model.py

# Step 5: 合并导出
python -m llamafactory.cli export \
    --model_name_or_path Qwen/Qwen2.5-3B-Instruct \
    --adapter_name_or_path saves/my_model/lora/sft \
    --template qwen --finetuning_type lora \
    --export_dir ./my-merged-model --export_device cpu

8 常见问题

Q: 模型下载慢或失败?

  • 确保加了 export USE_MODELSCOPE_HUB=1
  • 或使用 ModelScope SDK 手动下载:snapshot_download('qwen/Qwen2.5-3B-Instruct')

Q: trust_remote_code=True 有什么用?

  • Qwen、ChatGLM 等非标准架构的模型需要加载自定义模型类,必须设为 true
  • 标准架构模型(Llama、Mistral)不需要

Q: 显存溢出?

  • 减小 cutoff_len(如 512)
  • 减小 per_device_train_batch_size(设为 1)
  • 增大 gradient_accumulation_steps(如 8)
  • 换更小的模型(3B → 1.5B)

Q: 测试时输出乱码?

  • 检查 template 是否与模型匹配(Qwen 用 qwen,Llama 用 llama3
  • 检查 apply_chat_template 的参数是否正确
  • 检查 tokenizer 的 eos_token 是否设置正确

Q: DPO 训练报错找不到 chosen/rejected?

  • 检查 dataset_info.json 中是否设置了 "ranking": true
  • 检查数据文件字段名是否正确

Q: bf16: true 报错不支持?

  • 只有 Ampere 架构(RTX 30系/40系、A100、A10、H100)支持 bf16
  • 老显卡(RTX 20系、V100)改用 fp16: true
posted @ 2026-07-03 22:40  小纸条  阅读(13)  评论(0)    收藏  举报