目录

LoRA + LLaMA-Factory 实战教程: 用3090实现微调Qwen2.5-7B

LoRA + LLaMA-Factory 是现在微调经典配套,如果你想用一张 3090 或者单卡环境做一个实用性很强的自己模型,那实在没法避免这套技术组合。

我将体系地分 10 步,手把手教你如何实现 LoRA 微调、合并权重、数据转换和数据包装,并将运行后的模型部署到 Ollama 进行本地推理。

  • LoRA:Low-Rank Adaptation,用于高效微调,只训练小量参数,节省资源,效果也不错
  • LLaMA-Factory:支持 LoRA/全量/给账/声援/女门/控调各种经典微调方法,支持 CLI + WebUI

用好它,直接能完成从 HuggingFace 拉模型、对接自己数据、模型调教、部署 Ollama 的全链路。

  • Python >= 3.10
  • PyTorch >= 2.0 (GPU version)
  • CUDA & cuDNN
  • NVIDIA RTX3090 / 4090 (16G 显存起)
git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -r requirements.txt

如果被 transformers 版本问题卡住,建议使用 transformers==4.35.0


以 Qwen2.5-7B Instruct 为例:

python src/download_model.py --model_name qwen2_5

或者手动 HuggingFace 下载:

from huggingface_hub import snapshot_download
snapshot_download(repo_id="Qwen/Qwen2.5-7B-Instruct")

HuggingFace 有时需要 token,在国内环境可能需要代理


格式类似 OpenAI-style,JSON数组

[
  {
    "instruction": "请解释相对论",
    "input": "",
    "output": "相对论是..."
  }
]

如果来源是 CSV / Excel / Markdown,自己写 Python 脚本转换


model_type: qwen2_5
finetuning_type: lora
lora_rank: 64
lora_alpha: 128
lora_dropout: 0.1
output_dir: ./saves/qwen2_5_lora
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
learning_rate: 5e-5
num_train_epochs: 3
logging_steps: 10
save_steps: 500

如 batch size 过大,3090 很容易 OOM


LoRA 微调训练命令

python src/train_bash.py \
  --stage sft \                         # 训练阶段:SFT(监督式微调)是最常用的微调方式
  --do_train \                         # 表示要执行训练任务
  --model_name_or_path /path/to/qwen2_5 \  # 指定原始模型路径,比如你本地的 Qwen2.5-7B 模型
  --dataset_dir data \                 # 数据集目录,里面放你的 .json 数据文件
  --dataset my_dataset \               # 数据集名称,对应 data/my_dataset.json 文件名
  --template qwen \                    # 使用哪个模板来处理输入输出格式,这里选的是 Qwen 自带的模板
  --finetuning_type lora \             # 指定使用 LoRA 微调方法
  --output_dir ./saves/qwen2_5_lora \  # 权重保存路径,训练完后会在这里生成 adapter_model.bin 等文件
  --overwrite_cache \                  # 覆盖缓存数据,避免因旧缓存导致训练失败
  --per_device_train_batch_size 1 \    # 每个设备上的 batch size,显存小就设为 1
  --gradient_accumulation_steps 8 \    # 梯度累积步数,用来弥补小 batch 的影响,总 batch = 1 * 8 = 8
  --learning_rate 5e-5 \               # 学习率,别太大,不然容易不收敛或崩溃
  --num_train_epochs 3 \               # 总共训练轮数,LoRA 不需要太多轮,3~5 就够了
  --lr_scheduler_type cosine \         # 学习率调度器类型,cosine 效果较好
  --logging_steps 10 \                 # 每训练多少步打印一次日志,方便观察训练状态
  --save_steps 500 \                   # 每训练多少步保存一次 checkpoint,防止断电等意外
  --plot_loss                          # 可视化损失曲线,训练完会在 output_dir 下生成 loss.png
参数关键作用注意事项
--finetuning_type指定是否使用 LoRA必须为 lora 才能启用 LoRA 微调
--lora_rank--lora_alpha控制 LoRA 的秩和缩放因子推荐 rank=64, alpha=128
--learning_rate学习率太大会导致训练不稳定建议在 5e-5 ~ 1e-4 之间尝试
--gradient_accumulation_steps显存不够时救命稻草可以适当调大,但别超过 16
--num_train_epochs训练轮数不要过多LoRA 一般 3~5 轮就够了,多了容易过拟合

首次运行可加上 --max_steps 10,先演练一段进行添诊


训练完成后有一个 adapter_model.bin,必须合并到原始模型中:

python src/export_model.py \
  --model_name_or_path /path/to/qwen2_5 \      # 原始模型路径,必须和训练时一致
  --adapter_name_or_path ./saves/qwen2_5_lora \  # LoRA 权重路径,即训练完成后保存的 adapter_model.bin 所在目录
  --export_dir ./merged_model \                # 导出后的完整模型保存路径
  --finetuning_type lora                       # 同样指定为 lora,确保正确加载适配器权重
  1. 必须使用相同的模型路径和 LoRA 配置

    • 如果你在训练时用了某个版本的 Qwen2.5,那导出时也必须用这个版本,否则会报错“权重不匹配”。
    • LoRA 参数(如 rank、alpha)也要一致,否则合并出来的模型推理效果可能有问题
  2. 合并后的模型可以直接给 Ollama 用吗?

    • 可以,但你要先把它转换成 GGUF 格式,再通过 Modelfile 加载进 Ollama
    • 否则你会发现 Ollama 无法识别 LoRA 模型,因为它是基于全量权重设计的
  3. 导出模型推理慢?

    • 有用户反馈用 LLaMA-Factory 导出的模型比自己手动导出慢几十秒,可能是某些优化没开
    • 建议检查是否启用了 --use_fast_tokenizer 或者做了量化压缩

# Modelfile 内容
FROM ./merged_model
ollama create qwen2_5_lora -f Modelfile
ollama run qwen2_5_lora

Ollama 不支持 LoRA 直接识别,必须合并后重新包装 GGUF


这是我最常遇到的问题之一。

现象: 运行 export_model.py 报错,提示找不到模型文件、权重加载失败、参数不匹配等。

原因:

  • --model_name_or_path 写错了(不是训练用的原始模型)
  • --adapter_name_or_path 指向的是空目录 or 不是训练输出的 adapter 文件夹
  • finetuning_type 没有设为 lora,导致无法识别适配器

解决方法: 确保以下三点一致:

  • 原始模型路径和训练时完全一样
  • LoRA 权重路径指向训练输出的 output_dir
  • --finetuning_type 设置为 lora

我有一次导出的时候,忘记改 --adapter_name_or_path,结果合并出来的模型完全没有变化……还以为是训练没生效,后来才发现是导出漏掉了权重路径。


现象: 训练过程中突然报错 CUDA out of memory 或者卡住不动。

原因:

  • per_device_train_batch_size 设置太高(比如 4)
  • 没有用梯度累积(gradient_accumulation_steps

解决方法:

  • per_device_train_batch_size 设为 1
  • 同时设置 gradient_accumulation_steps=8 或更高,这样总 batch size 还是 8,但显存压力小很多

我一开始图省事直接设成 batch_size=4,结果直接炸了显存。后来改成 1+8 的组合,稳如老狗。


现象: 训练完的模型在训练阶段表现不错,但导出后推理效果变差,甚至跟原模型差不多。

原因:

  • LoRA 没有正确合并到主模型中
  • 使用了量化模型做合并(LLaMA-Factory 不支持)

解决方法:

  • 确保使用原始非量化模型进行合并
  • 检查 export_model.py 是否正确执行,并确认输出目录中有合并后的权重文件

有人反馈说用了量化模型做合并,结果推理慢得离谱还不准,最后发现是因为某些层没合并进去。


现象: 运行 webui.py 报错,提示找不到模块、导入错误等。

原因:

  • Python 包版本不对(比如 transformers、gradio、bitsandbytes 等)
  • 安装命令没按官方推荐执行,自己乱装了一堆

解决方法:

  • 严格按照文档安装依赖,最好新建一个虚拟环境
  • 如果还是不行,可以试试手动降级某些包,比如:
pip install transformers==4.35.0

我之前就因为 pip 自动升级了 gradio,结果页面打不开,控制台一堆 TypeError,最后靠回滚才搞定。


现象: 训练完成之后,模型表现没有明显提升,甚至还不如原模型。

原因:

  • lora_ranklora_alpha 设置太低 or 不合理
  • 学习率过高 or 过低,导致模型不收敛或过拟合

解决方法:

  • 推荐配置:lora_rank=64, lora_alpha=128
  • 学习率控制在 5e-5 ~ 1e-4 之间尝试
  • 训练轮数不要太多,一般 3~5 轮足够

有个朋友用 rank=8 做训练,结果模型几乎没变化……后来改成 64 才有点起色。


现象: 导出 GGUF 格式时报错,或者 Ollama 加载模型失败。

原因:

  • LLaMA-Factory 导出的模型格式不是标准 HF 格式
  • 需要额外转换步骤才能给 llama.cpp 使用

解决方法:

  • 使用 convert_hf_to_gguf.py 脚本进行转换
  • 确保模型结构和 llama.cpp 支持的格式兼容

我试过直接丢进 Ollama,结果它说不认识这个模型类型……后来才知道中间还要走一步转换流程。


现象: 想用 LongLoRA 扩展上下文长度,结果训练完反而效果更差。

原因:

  • LongLoRA 对位置编码敏感
  • 某些实现方式可能引入噪声 or 破坏原有结构

解决方法:

  • 先用普通 LoRA 跑通基础效果
  • 再逐步尝试 LongLoRA,并做充分验证
  • 别一上来就上长序列,容易翻车

GitHub 上还有人专门提 issue 说用了 LongLoRA 后效果比原模型还差……所以这玩意儿真不是万能的。

问题原因解决建议
导出失败路径/参数不一致检查 model path、adapter path、finetuning_type
显存爆炸Batch size 太大降低 batch size + 开梯度累积
推理效果差LoRA 没合并好用原始模型合并,别用量化模型
Web UI 报错依赖冲突新建虚拟环境,按推荐版本装
LoRA 效果不好参数设置不合理lora_rank=64, alpha=128,lr=5e-5 左右
GGUF 导出失败格式不对需要先转成 HF 格式,再用 llama.cpp 转换
LongLoRA 效果差实现不稳定先跑通普通 LoRA,再尝试扩展上下文

  • LoRA + LLaMA-Factory 非常适合单卡环境展示性、小型实用、内部定制场景
  • 配合 Ollama 可实现本地推理、接入 WebUI 或 API 调用

相关内容