基于 transformers 与 peft 对 Qwen2-7B-Instruct 进行 LoRA 高效微调从数据构建到推理部署全流程【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm本文以《开源大模型食用指南》self-llm仓库中的 Qwen2-7B-Instruct LoRA 微调教程为骨架系统讲解如何基于transformers、peft、modelscope等框架从模型下载、环境配置、指令集构建、数据格式化、LoraConfig/TrainingArguments配置到Trainer训练与 LoRA 权重加载推理的完整闭环。文中所有代码均可直接复制运行并结合 05-Qwen2-7B-Instruct Lora.ipynb 的运行结果与 dataset/huanhuan.json 真实数据做了源码级佐证。学完本文你将具备对 Qwen2 系列因果语言模型做角色化指令微调并落地部署的完整实战能力。一、为什么选择 LoRA 微调 Qwen2-7B-Instruct大模型微调通常指指令微调Instruction Tuning其目标是让模型具备理解并遵循用户指令的能力。Qwen2-7B-Instruct 是一个约 76 亿参数的因果语言模型若做全参数微调显存与算力开销巨大且容易灾难性遗忘而LoRALow-Rank Adaptation通过在原始权重旁注入低秩可训练矩阵把待训练参数量压缩到极小规模从而实现一张消费级显卡也能微调 7B 模型。以本教程的配置r8对 7 个线性投影层注入 LoRA为例Notebook 中model.print_trainable_parameters()的实际输出为trainable params: 20,185,088 || all params: 7,635,801,600 || trainable%: 0.26434798934534914即只需要训练约 0.26% 的参数约 2018 万即可完成一次角色化微调这正是 LoRA 被称为高效微调的原因。若想深入了解 LoRA 的数学原理低秩分解、缩放系数等可参阅 peft 官方文档中的理论章节本文第 6 节也会结合LoraConfig展开说明其核心机制。二、前置准备模型下载与环境配置2.1 使用 modelscope 下载模型Qwen2-7B-Instruct 的权重约 15GB推荐使用modelscope的snapshot_download函数下载。在/root/autodl-tmp路径下新建model_download.py并写入以下内容import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir snapshot_download(qwen/Qwen2-7B-Instruct, cache_dir/root/autodl-tmp, revisionmaster)然后运行python /root/autodl-tmp/model_download.py参数说明第一个参数qwen/Qwen2-7B-Instruct为模型仓库名称cache_dir/root/autodl-tmp为模型下载缓存路径请按你的实际磁盘空间修改revisionmaster指定拉取的分支。下载完成后模型权重会存放在/root/autodl-tmp/qwen/Qwen2-7B-Instruct/目录下后续的 tokenizer 与模型加载代码都将引用该路径。提示如果磁盘紧张或网络不佳也可以参考仓库 General-Setting/03-模型下载.md 中提供的换源与多线程加速方案。2.2 安装第三方依赖在完成基础 PyTorch/CUDA 环境配置后还需要安装以下库版本以本教程实测为准python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.9.5 pip install transformers4.39.0 pip install streamlit1.24.0 pip install sentencepiece0.1.99 pip install accelerate0.27 pip install transformers_stream_generator0.0.4 pip install datasets2.18.0 pip install peft0.10.0 # 可选 MAX_JOBS8 pip install flash-attn --no-build-isolation几点说明peft是 LoRA 的实现库datasets用于加载与映射微调数据集accelerate提供device_mapauto所需的底层支持flash-attn为可选项能显著加速注意力计算并降低显存占用但编译安装较慢大概需要十几分钟请耐心等待若在 AutoDL 等云平台部署也可直接使用仓库提供的 Qwen2 环境镜像该镜像适用于本仓库除 Qwen-GPTQ 与 vLLM 之外的所有 Qwen2 部署环境省去逐项安装的麻烦。2.3 配套文件一览本教程涉及的关键仓库资源如下建议先通读一遍再动手资源路径作用微调文档models/Qwen2/05-Qwen2-7B-Instruct Lora 微调.md本文主体内容来源可执行 Notebookmodels/Qwen2/05-Qwen2-7B-Instruct Lora.ipynb与文档一一对应的可运行代码含真实运行输出微调数据集dataset/huanhuan.json3729 条甄嬛体指令数据示例项目examples/Chat-嬛嬛/readme.mdChat-甄嬛 个性化 LLM 的完整落地流程三、指令集构建构造角色化训练数据LLM 微调所用数据形如{ instruction: 回答以下用户问题仅输出答案。, input: 11等于几?, output: 2 }instruction用户指令告知模型需要完成的任务input完成指令所必需的输入内容可为空字符串output模型应给出的标准输出。指令集必须围绕目标任务针对性构建。本教程采用作者合作开源的 Chat-甄嬛 项目思路目标是构建一个能模拟甄嬛对话风格的个性化 LLM因此构造的指令形如{ instruction: 你是谁, input: , output: 家父是大理寺少卿甄远道。 }全部指令数据存放于仓库根目录的 dataset/huanhuan.json3729 条字段为instruction/input/output另有 100 条的精简版 dataset/huanhuan-100.json 可用于快速实验。关于如何从《甄嬛传》剧本原始文本一步步清洗出这样的 QA 数据角色台词提取 → 目标角色筛选 → 格式转换可参考 examples/Chat-嬛嬛/readme.md 中的 Step 2。四、数据格式化把文本编码成模型可学习的张量LoRA 训练前需要将文本样本编码为input_ids把输出文本编码为labels。以下预处理函数对每个样本完成这一转换def process_func(example): MAX_LENGTH 384 # Llama分词器会将一个中文字切分为多个token因此需要放开一些最大长度保证数据的完整性 input_ids, attention_mask, labels [], [], [] instruction tokenizer(f|im_start|system\n现在你要扮演皇帝身边的女人--甄嬛|im_end|\n|im_start|user\n{example[instruction] example[input]}|im_end|\n|im_start|assistant\n, add_special_tokensFalse) # add_special_tokens 不在开头加 special_tokens response tokenizer(f{example[output]}, add_special_tokensFalse) input_ids instruction[input_ids] response[input_ids] [tokenizer.pad_token_id] attention_mask instruction[attention_mask] response[attention_mask] [1] # 因为eos token咱们也是要关注的所以 补充为1 labels [-100] * len(instruction[input_ids]) response[input_ids] [tokenizer.pad_token_id] if len(input_ids) MAX_LENGTH: # 做一个截断 input_ids input_ids[:MAX_LENGTH] attention_mask attention_mask[:MAX_LENGTH] labels labels[:MAX_LENGTH] return { input_ids: input_ids, attention_mask: attention_mask, labels: labels }这段代码里有几个关键设计值得展开Prompt TemplateQwen2 采用 ChatML 风格的模板process_func中手工拼接的正是这一格式|im_start|system 现在你要扮演皇帝身边的女人--甄嬛|im_end| |im_start|user 你是谁|im_end| |im_start|assistant 我是一个有用的助手。|im_end|注意add_special_tokensFalse避免在拼接中间额外插入 BOS 等特殊 token格式完全由我们自己控制。labels 的-100掩码instruction部分system 提示与 user 输入的标签全部置为-100表示不参与损失计算只有responseassistant 输出的 token 参与训练。这正是指令微调只学回答、不学提问的底层实现。尾部补充 pad_token_id在序列末尾追加tokenizer.pad_token_id作为结束标记attention_mask对应位置补1因为 EOS token 也是需要模型关注的。MAX_LENGTH 截断Qwen2 分词器会将一个中文字切分为多个 tokenNotebook 中加载的 Qwen2Tokenizer 词表大小约 15 万model_max_length131072因此将最大长度放宽到 384 以保住数据完整性超长部分直接截断。加载数据集并映射from datasets import Dataset import pandas as pd df pd.read_json(../../dataset/huanhuan.json) ds Dataset.from_pandas(df) tokenized_id ds.map(process_func, remove_columnsds.column_names)Notebook 实际运行结果显示num_rows: 3729与数据集规模一致。映射后可用tokenizer.decode验证编码是否正确——例如第一条样本解码后即为|im_start|system 现在你要扮演皇帝身边的女人--甄嬛|im_end| |im_start|user 小姐别的秀女都在求中选唯有咱们小姐想被撂牌子菩萨一定记得真真儿的——|im_end| |im_start|assistant 嘘——都说许愿说破是不灵的。|endoftext|对labels过滤掉-100后解码可确认仅 assistant 输出参与了监督。五、加载 Tokenizer 与半精度模型tokenizer AutoTokenizer.from_pretrained(/root/autodl-tmp/qwen/Qwen2-7B-Instruct/, use_fastFalse, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(/root/autodl-tmp/qwen/Qwen2-7B-Instruct/, device_mapauto, torch_dtypetorch.bfloat16)半精度加载torch_dtypetorch.bfloat16将模型以 bf16 半精度加载显存占用约为 fp32 的一半如果你的显卡较新也可以直接用 bf16 训练trust_remote_codeTrueQwen2 在 Transformers 中已有原生支持但为兼容自定义代码官方文档建议保留该参数use_fastFalse关闭 fast tokenizer确保与模型发布时的分词行为一致device_mapauto由 accelerate 自动分配层到可用设备多卡或 CPU offload 场景下非常方便。加载后可以从 Notebook 输出中确认 Qwen2-7B 的结构细节28 层Qwen2DecoderLayer每层含Qwen2SdpaAttentionq_proj/k_proj/v_proj/o_proj与Qwen2MLPgate_proj/up_proj/down_proj归一化使用Qwen2RMSNormMLP 激活函数为SiLU。值得注意的是注意力模块采用 GQA 设计q_proj输入输出均为 3584 维而k_proj/v_proj输出仅 512 维这直接决定了第 6 节target_modules的选择范围。模型加载后还需执行一行关键代码model.enable_input_require_grads() # 开启梯度检查点时要执行该方法这是因为TrainingArguments中开启了gradient_checkpointingTrue梯度检查点会丢弃前向激活、反向时重算此时输入层需要保留梯度必须调用该方法。六、定义 LoraConfig决定动哪些层LoraConfig是 peft 中配置 LoRA 的核心类主要参数如下参数取值本教程含义task_typeTaskType.CAUSAL_LM模型类型因果语言模型target_modules[q_proj,k_proj,v_proj,o_proj,gate_proj,up_proj,down_proj]需要注入 LoRA 的层名主要对应 attention 与 MLP 部分r8LoRA 的秩rank控制低秩矩阵的宽度lora_alpha32LoRA 缩放系数lora_dropout0.1Dropout 比例inference_modeFalse训练模式config LoraConfig( task_typeTaskType.CAUSAL_LM, target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], inference_modeFalse, # 训练模式 r8, # Lora 秩 lora_alpha32, # Lora alaph具体作用参见 Lora 原理 lora_dropout0.1# Dropout 比例 )这里重点澄清一个高频误解LoRA 的缩放系数不是r而是lora_alpha / r。本配置中即32 / 8 4倍。target_modules中的 7 个名字与第 5 节模型结构一一对应——q/k/v/o_proj是自注意力投影gate/up/down_proj是 MLP 投影覆盖了 Transformer 层中除归一化与 embedding 外的全部线性层。不同模型的层命名不同切换模型时需按对应源码调整peft 也支持传入正则表达式匹配。将 LoRA 注入模型并打印可训练参数from peft import LoraConfig, TaskType, get_peft_model model get_peft_model(model, config) model.print_trainable_parameters()输出trainable params: 20,185,088 || all params: 7,635,801,600 || trainable%: 0.26434798934534914从LoraConfig的完整打印见 Notebook还可以看到biasnone、use_rsloraFalse、init_lora_weightsTrue等默认项它们分别表示不训练偏置、不使用 rank-stabilized LoRA、以高斯分布初始化低秩矩阵——这些默认值在大多数场景下无需修改。七、配置 TrainingArguments训练超参TrainingArguments常用参数说明参数本教程取值含义output_dir./output/Qwen2_instruct_lora模型与 checkpoint 输出路径per_device_train_batch_size4每张卡上的 batch sizegradient_accumulation_steps4梯度累加步数logging_steps10每多少步输出一次 lognum_train_epochs3训练轮数save_steps100每多少步保存一次 checkpointlearning_rate1e-4学习率save_on_each_nodeTrue每个节点都保存权重gradient_checkpointingTrue梯度检查点节省显存args TrainingArguments( output_dir./output/Qwen2_instruct_lora, per_device_train_batch_size4, gradient_accumulation_steps4, logging_steps10, num_train_epochs3, save_steps100, learning_rate1e-4, save_on_each_nodeTrue, gradient_checkpointingTrue )显存不足的应对思路gradient_accumulation_steps与per_device_train_batch_size配合可等效放大 batch size——如果显存小就把batch_size调小、gradient_accumulation_steps调大例如batch_size1配合accumulation16训练效果近似而峰值显存大幅降低gradient_checkpointingTrue则以时间换显存进一步压低峰值占用。注意Notebook 演示版为了快速跑通将save_steps设为 10正式训练建议按文档设为 100。八、使用 Trainer 启动训练from transformers import Trainer, DataCollatorForSeq2Seq trainer Trainer( modelmodel, argsargs, train_datasettokenized_id, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue), ) trainer.train()data_collator使用DataCollatorForSeq2SeqpaddingTrue会在批内将序列补齐到等长并正确生成对应labels的 padding同样以-100掩码避免 padding 参与损失训练完成后output_dir下会生成checkpoint-{step}目录其中保存了 LoRA 适配器权重adapter_model.safetensors、adapter_config.json体积通常只有几十 MB与全量模型相比极轻量。九、加载 LoRA 权重进行推理训练完成后将 LoRA 适配器叠加回原始基座模型即可推理from transformers import AutoModelForCausalLM, AutoTokenizer import torch from peft import PeftModel model_path /root/autodl-tmp/qwen/Qwen2-7B-Instruct/ lora_path lora_path # 例如 ./output/Qwen2_instruct_lora/checkpoint-10 # 加载tokenizer tokenizer AutoTokenizer.from_pretrained(model_path) # 加载模型 model AutoModelForCausalLM.from_pretrained(model_path, device_mapauto, torch_dtypetorch.bfloat16) # 加载lora权重 model PeftModel.from_pretrained(model, model_idlora_path, configconfig) prompt 你是谁 messages [ {role: system, content: 现在你要扮演皇帝身边的女人--甄嬛}, {role: user, content: prompt} ] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) model_inputs tokenizer([text], return_tensorspt).to(cuda) generated_ids model.generate( model_inputs.input_ids, max_new_tokens512 ) generated_ids [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response tokenizer.batch_decode(generated_ids, skip_special_tokensTrue)[0] print(response)要点lora_path需指向训练输出中具体的 checkpoint 目录如./output/Qwen2_instruct_lora/checkpoint-10并替换为你实际训练的步数通过apply_chat_template(..., add_generation_promptTrue)复用 Qwen2 的 ChatML 模板构造 prompt比手工拼接更不易出错推理时模型仍以torch.bfloat16加载PeftModel.from_pretrained负责把适配器合并/装载进基座模型裁剪generated_ids中属于输入的部分只对新增生成 token 解码并skip_special_tokensTrue去除特殊标记。Notebook 中实际运行后的效果示例输入你是谁system 设定为甄嬛人设臣妾是大理寺少卿甄远道之女大理寺少卿甄远道之女家父现任大理寺少卿家母是大理寺少卿甄远道之妻。可以看到模型已经学会了以臣妾家父等甄嬛式的口吻作答说明角色化指令微调生效。十、完整流程回顾与常见问题10.1 端到端流程总结下载基座模型snapshot_download(qwen/Qwen2-7B-Instruct, cache_dir/root/autodl-tmp)准备数据按instruction/input/output三元组组织任务指令集格式化process_func拼接 ChatML 模板、编码、-100掩码、截断加载模型bf16 半精度 device_mapauto开启梯度检查点前调用enable_input_require_grads()配置 LoRALoraConfig选定target_modules、r、lora_alpha仅训练 0.26% 参数训练TrainerDataCollatorForSeq2Seq产出 checkpoint推理PeftModel.from_pretrained装载适配器apply_chat_template构造 prompt 后generate。10.2 常见问题与注意事项flash-attn安装慢属正常现象编译约需十几分钟可用MAX_JOBS8并行编译加速或先跳过不装。显存不足调小per_device_train_batch_size、调大gradient_accumulation_steps并保持gradient_checkpointingTrue。忘记enable_input_require_grads()开启梯度检查点后不调用会报梯度相关错误。save_steps过小Notebook 演示用 10正式训练建议 100避免 checkpoint 过多占用磁盘。修改人设与数据集换人设只需改process_func中的 system 内容与训练数据仓库中的 dataset/huanhuan-100.json 可用于小规模快速验证。扩展阅读微调完成后可继续参考本仓库中 Qwen2 系列的其他部署文档将微调模型接入线上服务例如 01-Qwen2-7B-Instruct FastApi 部署调用.md、02-Qwen2-7B-Instruct Langchain 接入.md 与 03-Qwen2-7B-Instruct WebDemo部署.md完整的角色化微调项目背景可参阅 examples/Chat-嬛嬛/readme.md。同一套流程稍作改动即可复用于本仓库中其他模型的 LoRA 微调如 LLaMA、Qwen1.5、Qwen2.5 等各模型的target_modules与 Prompt Template 需按源码调整。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考