千问大模型二次LoRA‑SFT指令微调指南
大模型微调是实现模型领域定制的核心方案。本文基于 Ubuntu 22.04 服务器环境,依托 NVIDIA RTX 家用高性能显卡,选用千问 Qwen3.5‑0.8B‑Instruct 指令模型,完整演示二次 LoRA‑SFT 微调全流程,包含环境搭建、模型选型、ChatML 数据集制作校验、LoRA 参数配置、SFT 训练、效果验证、权重合并,附带可直接运行的工程脚本,便于开发者快速实现千问模型轻量化定制与上线部署。

在开展Qwen模型微调实操前,需提前配置好服务器软硬件运行环境,本文所有实操流程均基于以下稳定运行的本机环境,读者可直接参考对齐配置,适配复现:
- 操作系统:Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-187-generic x86_64)
- 框架版本:torch 2.13.0 + CUDA 12.8.1 + Python 3.10.12
- 显卡驱动:NVIDIA ≥ 570.133.07
- 显卡类型:NVIDIA RTX 4090 24GB GPU
- CPU核心:INTEL(R) XEON(R) GOLD 6530
- 内存:64GB DDR5
- 存储:50GB(系统盘)+100GB(数据盘)
基础知识
两种训练
大模型行业落地场景中,通用预训练模型难以适配垂直领域专属知识、定制化对话风格与专属业务指令需求,模型微调成为轻量化、低成本实现模型能力定制的核心手段。
模型的微调训练包含两种主流模式:
第一种:基于Base预训练基座模型开展从零SFT微调,该类模型仅完成通用预训练,无官方指令对齐能力,无法原生理解对话指令,需人工构建对话格式、手动拼接对话文本及监督数据集,从零学习指令跟随与对话能力,多用于全新模型定制与二次预训练任务,该模式消耗算力大,一般不会使用此方式微调。
第二种:指令模型二次 LoRA‑SFT 微调,也是本文的核心内容,千问 Instruct 指令模型由 Base 基座经过官方 SFT 监督微调、DPO/RLHF 偏好对齐得到,原生具备指令理解与多轮对话能力。在此成熟对齐模型基础上开展二次 LoRA‑SFT 微调,可在保留模型通用知识与基础对话能力的前提下,低成本注入领域专属能力或知识,规避基座从零训练的数据门槛与对齐成本,是工程落地与轻量化模型定制的最优方案。
进行微调前需要判别模型底座,模型名称带有‑Base后缀的为预训练裸基座;模型目录中包含chat_template.jinja文件,则说明是 Instruct 指令模型,该类模型已经完成 SFT、DPO、RLHF 等指令对齐流程。现实中原始预训练基模较少对外开源,公开可获取的大多是经过完整后训练的成品权重。
LoRA/QLoRA
LoRA 与 QLoRA 是目前主流的参数高效微调方法。LoRA 通过冻结主干模型,仅训练注意力层的低秩适配器,在几乎不损失模型性能的前提下降低训练参数量,适合显存条件较好的硬件环境。QLoRA 在 LoRA 基础上引入 4/8 比特权重量化,将主干模型以量化形式加载,以此来压缩显存占用,使大模型微调可以在消费级显卡上完成,但会引入少量量化噪声,可能对最终效果带来轻微影响。
| 项目 | LoRA | QLoRA |
|---|---|---|
| 核心机制 | 低秩适配器 | 低秩适配器 + INT4/INT8 权重量化 |
| 模型主干精度 | FP16/BF16 | INT4/INT8 量化冻结 |
| 显存消耗 | 较低 | 更低 |
| 精度损失 | 几乎无 | 存在轻微量化损失 |
| 工程复杂度 | 低,稳定通用 | 较高,存在量化适配问题 |
| 适用场景 | 显存条件较好,8B‑14B,追求微调效果 | 显存受限,超大模型 (27B+),消费级显卡 |
LoRA 与 QLoRA 的选择主要依据硬件设备显存条件确定。对于 8B 规模模型,当显卡显存大于 24GB 时,优先采用 LoRA 微调;针对 14B、27B 等更大规模模型或显存资源受限场景,则选用 QLoRA 并开启 4 比特量化加载以降低显存压力。本文选用体量较小的 Qwen3.5‑0.8B‑Instruct 作为实验对象,模型参数量小,便于流程演示,因此直接采用 LoRA 开展二次 SFT 指令微调。
- 完整实验链路为:环境准备 → 数据集准备(train.json) → 加载基座模型(Qwen3.5‑0.8B‑Instruct) → LoRA 参数配置 → SFTTrainer 执行微调训练 → 本地推理效果验证 → LoRA 适配器与主模型权重合并导出
微调实验
环境安装
1、创建独立 Python 虚拟环境,隔离项目依赖,避免和系统 Python 包冲突。
root@localhost:~/# sudo apt install -y python3-full python3-venv tmux git tree |
2、激活进入虚拟环境,使用腾讯云镜像源加速深度学习、微调相关全套依赖包。
root@localhost:~/# pip3 install -i https://mirrors.cloud.tencent.com/pypi/simple/ torch torchvision trl datasets peft accelerate bitsandbytes wandb transformers sentencepiece huggingface_hub protobuf modelscope |
下载底座模型
使用 modelscope 下载 Qwen/Qwen3.5‑0.8B‑Instruct 已经预 SFT 完成的底座模型,该模型原生支持 ChatML 对话模板,不需要自己修改 tokenizer,适合直接二次 LoRA 微调;不要手动复制网页,使用 modelscope 下载保证文件完整,避免文件缺失导致训练报错。
https://www.modelscope.cn/models/icyfenix/Qwen3.5-0.8B-Instruct
root@localhost:~/# mkdir data |
准备 SFT 微调数据集
采用 Qwen 标准 ChatML 格式,json 数组格式,每一条样本包含conversation数组,数组内是多轮对话,角色仅允许system/user/assistant,文件保存到/root/data/train.json中。
此处为小样本演示数据集,适合跑通流程;真实业务建议扩充到几百~几千条,太少容易过拟合。
[ |
数据集校验
数据集校验脚本,提前拦截 JSON 语法错误、字段缺失、非法 role 角色;同时调用分词器apply_chat_template渲染对话,检查 ChatML 标签<|im_start|>/<|im_end|>输出是否正常。
很多训练失败根源是数据集格式错误,训练前必须运行该脚本,全部校验通过再进入训练。
import json |
检查通过后可看到如下所示输出内容:
root@localhost:~/data# python check.py |
分词器加载与验证脚本
验证底座模型分词器加载是否正常,查看特殊 token(<|im_start|>、<|im_end|>、eos/pad token)ID,验证编码解码、对话模板输出。很多训练 loss 爆炸、生成乱码来自分词器配置错误;Qwen 系列需要把pad_token设置等于eos_token,padding_side=right。
from datasets import load_dataset, concatenate_datasets |
检查通过后可看到如下所示输出内容:
重点检查:
pad_token不为 None,padding_side=right,apply_chat_template输出包含正确 im 标签。
root@localhost:~/data# python check.py |
LoRA‑SFT 训练脚本
加载本地 Qwen3.5‑0.8B‑Instruct 基座模型,冻结主干,使用 LoRA 做轻量化微调;读取本地 json 对话数据集,经过 chat 模板格式化、分词、过滤、划分训练验证集;使用 Trainer 执行 step 式训练,保存 LoRA 适配器,最后加载 LoRA 做简单推理验证。
import os |
训练结束输出产物:/root/data/qwen_lora,里面是 LoRA 适配器,体积很小(几十 MB)不是完整模型;包含adapter_model.safetensors、adapter_config.json以及 checkpoint 中间快照。
root@localhost:~/data# python qwen_lora.py |
适配器合并完整权重
LoRA 适配器不能直接用于 llama.cpp、GGUF 导出;需要把 LoRA 权重合并进底座模型权重,输出完整 HF 格式模型。
脚本merge_lora.py将 LoRA 低秩矩阵和基础模型权重矩阵做矩阵相加,输出完整独立模型,不再依赖 peft 库;合并后可以直接 vLLM 推理,也可以转 GGUF。
import torch |
输出目录/root/data/qwen3.5‑0.8B‑lora‑merged
root@localhost:~/data# python lora‑merged.py |
完整模型推理测试
不依赖 peft 库,直接加载合并完成完整 HF 模型,验证对话生成效果;调用apply_chat_template构建 prompt,设置 temperature、top_p 采样参数做生成。
import torch |
运行后输出测试效果如下:
root@localhost:~/data# python test.py |
底座和LoRA合并模型对比测试,同时加载原始底座模型、微调合并后的模型,输入同一个问题对比输出,直观确认微调是否生效。
import torch |
运行后输出测试效果如下:
现象:底座回答偏向通用百科;微调后的输出风格、话术会贴近训练集的回答内容。
root@localhost:~/data# python test.py |