基于 transformers 与 peft 对 Qwen2.5-Coder-7B-Instruct 进行 LoRA 高效微调实战(Datawhale self-llm 篇)

发布时间:2026/9/20 3:43:27
基于 transformers 与 peft 对 Qwen2.5-Coder-7B-Instruct 进行 LoRA 高效微调实战(Datawhale self-llm 篇) 大模型人工智能教程本地部署微调【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址https://gitcode.com/datawhalechina/self-llm点击查看免费下载本篇技术指南以 Datawhale《开源大模型食用指南》仓库中的 Qwen2.5-Coder-7B-Instruct Lora 微调文档 为核心完整讲解如何基于transformers、peft、datasets等框架在 Linux 环境下使用 ModelScope 下载模型并对 Qwen2.5-Coder-7B-Instruct 执行 LoRA 指令微调。读者学完后将掌握指令数据集的构建与格式化、Qwen2.5 系列 ChatML 模板的正确拼接、LoRA 配置与训练参数的选择、Trainer 训练全流程以及训练后 LoRA 权重的加载与推理验证可直接复用到角色扮演、领域问答、代码风格迁移等个性化微调场景。一、前置准备与依赖环境微调本质上依赖完整的 PyTorch/CUDA 环境与本地模型部署基础。在开始前请确保已完成基本环境配置并在此基础上安装以下指定版本的第三方库版本锁定有助于复现本文结果python -m pip install --upgrade pip pip install modelscope1.20.0 pip install transformers4.46.2 pip install sentencepiece0.2.0 pip install accelerate1.1.1 pip install datasets3.1.0 pip install peft0.13.2各依赖的职责如下modelscope负责从 ModelScope 模型库拉取模型权重transformers提供模型、分词器加载与Trainer训练框架sentencepieceQwen 系列分词器Qwen2Tokenizer依赖的底层分词库accelerate支撑device_mapauto的模型加载与分布式训练datasets用于将 JSON 数据集转换为 HuggingFaceDataset对象peft提供LoraConfig、get_peft_model、PeftModel等 LoRA 核心 API。说明仓库同目录还提供了基于 SwanLab 的可视化微调版本其环境清单中额外引入了swanlab0.3.25可参见 05-Qwen2.5-Coder-7B-Instruct Lora 微调 SwanLab 可视化记录版.md。二、模型下载使用 ModelScope snapshot_download微调的第一步是把模型权重拉到本地。仓库统一采用 ModelScope 的snapshot_download函数第一个参数为模型名称cache_dir参数指定模型下载路径。在/root/autodl-tmp路径下新建model_download.py文件输入以下内容并保存import torch from modelscope import snapshot_download import os model_dir snapshot_download(Qwen/Qwen2.5-Coder-7B-Instruct, cache_dir/root/autodl-tmp, revisionmaster)然后执行下载python /root/autodl-tmp/model_download.py模型大小约 14.18GB仓库其他教程记录为 15GB 量级视网络情况下载约需数分钟。revisionmaster指定拉取 master 分支的最新权重。需要特别留意ModelScope 下载目录的命名转义规则下载后的模型目录名与模型 ID 略有差异Qwen/Qwen2.5-Coder-7B-Instruct在本地下沉为/root/autodl-tmp/Qwen/Qwen2___5-Coder-7B-Instruct/模型 ID 中的点.被替换为三个下划线___。这一规则在仓库的 FastApi 部署文档 与 SwanLab 可视化版 中均有体现后续加载模型时必须使用转义后的本地路径否则会报路径不存在。三、指令集构建让模型学会遵循指令LLM 的微调一般指指令微调Instruction Tuning。所谓指令微调是指我们使用的微调数据形如{ instruction: 回答以下用户问题仅输出答案。, input: 11等于几?, output: 2 }三个字段的含义instruction用户指令告知模型需要完成的任务input用户输入是完成指令所必需的上下文内容可为空字符串output模型应当给出的标准输出。核心训练目标是让模型具备理解并遵循用户指令的能力。因此在构建指令集时必须针对目标任务针对性构造。例如本节以构建一个能模拟甄嬛对话风格的个性化 LLM 为目标构造的指令形如{ instruction: 你是谁, input: , output: 家父是大理寺少卿甄远道。 }该示例所使用的完整指令数据集即仓库根目录下的 dataset/huanhuan.json数据以 JSON 数组形式组织全部为指令-输入-输出三元组共约 1.8 万行内容为甄嬛传风格的中文多轮对白。例如数据集中的真实样本{ instruction: 皇上驾到, input: , output: 皇上万福金安。 }仓库同目录还提供了 huanhuan-100.json约百条规模适合快速跑通流程与 huanhuan.jsonl逐行 JSON 格式两种变体。若只做流程验证可先用 100 条的小数据集追求对话效果则使用完整的huanhuan.json。四、数据格式化将文本编码为 input_ids 与 labelsLoRA 训练的数据需要经过格式化、编码之后再输入给模型。熟悉 PyTorch 训练流程的同学知道我们一般将输入文本编码为input_ids将输出文本编码为labels编码结果都是多维向量。首先定义一个预处理函数process_func对每个样本编码其输入、输出文本并返回编码字典def process_func(example): MAX_LENGTH 384 # 中文会被切分为多个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 }这段函数是 LoRA 微调中最重要的数据管线逐行拆解如下MAX_LENGTH 384Qwen 分词器会将一个中文字切分为多个 token因此放宽最大长度以保证数据完整性超长样本按 384 截断模板拼接instruction部分将 system 提示、user 指令/输入拼接成完整的 ChatML 模板文本后编码response部分单独编码output。两段编码均使用add_special_tokensFalse避免在拼接段中间重复插入特殊 tokeninput_ids由instruction response pad_token_id拼接而成pad token 用于标记序列结束attention_mask全部置 1含末尾的 pad 位置因为 pad/eos token 也是模型需要关注的labels这是训练目标的核心——instruction 部分全部用-100掩码掉-100是 PyTorch 交叉熵损失的忽略索引即不计算 prompt 部分的损失只有response部分的 token id 参与损失计算确保模型只学习如何作答而不是如何复述问题截断超长时对三个序列同步截断保证三者长度一致。Qwen2.5-Coder 采用的 Prompt TemplateChatML 格式如下|im_start|system You are Qwen, created by Alibaba Cloud. You are a helpful assistant.|im_end| |im_start|user {user_prompt}|im_end| |im_start|assistant {assistant_response}|im_end|其中|im_start|与|im_end|是 Qwen 系列模型新增的特殊 token用于分隔 system/user/assistant 三端。从仓库 Notebook 的运行输出可以确认Qwen2.5-Coder 的 tokenizer 词表大小为 151643eos_token为|im_end|pad_token为|endoftext|additional_special_tokens中注册了|im_start|、|im_end|以及 FIMFill-In-the-Middle代码补全相关的|fim_prefix|、|fim_middle|、|fim_suffix|等 token——这是其作为代码模型的重要特征微调时同样沿用这套词表。数据集应用该预处理函数时通过datasets的map完成批量转换并移除原字段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 中实际运行tokenized_id得到num_rows: 3729即完整数据集约 3729 条样本并可通过tokenizer.decode验证编码结果——例如对第一条样本解码可还原出完整的|im_start|system\n现在你要扮演皇帝身边的女人--甄嬛...|im_end|模板文本对 labels 过滤掉-100后解码可得到纯output内容这印证了上述格式化逻辑的正确性。五、加载 tokenizer 与半精度模型模型以半精度形式加载如果你的显卡比较新可以用torch.bfloat16形式加载。对于自定义模型如使用远程代码定义的模型一定要指定trust_remote_codeTruetokenizer 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)需要注意两点路径务必改为上一步实际的下载目录如/root/autodl-tmp/Qwen/Qwen2___5-Coder-7B-Instruct/原文档此处为笔误路径直接照抄会报错use_fastFalse使用慢速纯 Python分词器与 Qwen 官方 tokenizer 文件保持兼容。从 Notebook 的运行输出可以观察到该模型的底层结构Qwen2ForCausalLM共 28 层Qwen2DecoderLayer隐藏维度 3584注意力部分q_proj/o_proj为 3584→3584k_proj/v_proj为 3584→512MLP 部分gate_proj/up_proj为 3584→18944、down_proj为 18944→3584激活函数为 SiLU。这为下一步选择target_modules提供了直接依据。此外若训练时开启梯度检查点见后文gradient_checkpointingTrue则必须额外执行model.enable_input_require_grads()否则会因前向过程中输入无梯度而报错model.enable_input_require_grads() # 开启梯度检查点时要执行该方法六、定义 LoraConfigLoraConfig类可以设置很多参数但主要参数不多简单介绍如下task_type模型类型因果语言模型填TaskType.CAUSAL_LMtarget_modules需要训练的模型层名称主要是 attention 部分与 MLP 部分的投影层可传数组、字符串也支持正则表达式rLoRA 的秩rank决定低秩分解矩阵的维度lora_alphaLoRA 的缩放超参数lora_dropoutLoRA 分支的 Dropout 比例用于缓解过拟合inference_mode是否为推理模式训练时置False。关于LoRA 的缩放系数LoRA 前向的最终缩放是lora_alpha / r而不是r本身。在下述配置中lora_alpha32, r8缩放为 4 倍。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 比例 )target_modules中 7 个模块覆盖了两类投影层q_proj/k_proj/v_proj/o_proj是注意力四件套gate_proj/up_proj/down_proj是 Qwen2MLP 的三层对应上节模型结构中的Qwen2MLP正好与 Notebook 打印出的模型结构一一对应。对这两类层都注入 LoRA 适配器是 Qwen 系模型微调的标准做法。将配置应用到模型并统计可训练参数量from peft import LoraConfig, TaskType, get_peft_model model get_peft_model(model, config) model.print_trainable_parameters()Notebook 中的真实输出为trainable params: 20,185,088 || all params: 7,635,801,600 || trainable%: 0.2643即在约 76.36 亿参数的全模型中仅 2018 万参数可训练可训练占比约 0.26%——这正是 LoRA 高效微调的直观体现冻结原始权重只训练注入的低秩矩阵大幅降低显存占用与训练成本。七、自定义 TrainingArguments 参数TrainingArguments的源码中对每个参数都有说明这里介绍几个常用参数output_dir模型的输出路径checkpoint 保存目录per_device_train_batch_size单卡 batch_sizegradient_accumulation_steps梯度累加步数。显存较小时可调小 batch_size、调大梯度累加等效扩大 batchlogging_steps每隔多少步输出一次 lognum_train_epochs训练轮数save_steps每隔多少步保存一次 checkpointlearning_rate学习率save_on_each_node多节点训练时每节点都保存gradient_checkpointing梯度检查点。一旦开启模型必须执行model.enable_input_require_grads()见第五节。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 )参数组合的等效 batch size约为4batch× 4梯度累加 16条样本/更新步。若显存吃紧可将per_device_train_batch_size降至 2 并把gradient_accumulation_steps升至 8保持等效 batch 不变——仓库的 SwanLab 可视化版 正是采用batch_size2, gradient_accumulation_steps8的组合在 24GB 级显卡上完成训练的。此外开启梯度检查点后use_cache会自动置为FalseTransformers 会打印相应提示推理阶段若需要缓存加速需另行处理。八、使用 Trainer 训练将模型、参数、数据集与 DataCollator 组装进Trainer并启动训练trainer Trainer( modelmodel, argsargs, train_datasettokenized_id, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue), ) trainer.train()DataCollatorForSeq2Seq负责在 batch 内部将变长序列 padding 到相同长度右 padding保证批量前向计算可行。从仓库 Notebook 的实际运行记录可以观察到完整的训练收敛过程训练共699 步历时约23 分钟train_runtime: 1418s吞吐约 7.9 samples/s训练损失从第 10 步的3.97逐步下降到 2.12.4 区间最终training_loss ≈ 2.753 个 epoch 平均loss 整体呈稳定下降趋势未见明显发散训练结束后输出TrainOutput(global_step699, ...)并在./output/Qwen2_instruct_lora下按save_steps生成 checkpoint 目录如checkpoint-690。如果想在训练过程中监控 loss 曲线与超参数仓库提供了基于 SwanLab 的增强版——在Trainer的callbacks参数中挂载SwanLabCallback即可自动记录指标并支持在每个 epoch 结束时对测试样本做主观评测详见 SwanLab 可视化微调文档。九、加载 LoRA 权重进行推理训练完成后权重保存在output_dir的 checkpoint 目录中只包含 LoRA 适配器体积远小于全量权重。加载 LoRA 权重进行推理的方式如下from transformers import AutoModelForCausalLM, AutoTokenizer import torch from peft import PeftModel model_path Qwen/Qwen2.5-Coder-7B-Instruct lora_path lora_path # 改为你训练输出的 checkpoint 路径如 ./output/Qwen2_instruct_lora/checkpoint-690 # 加载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)关键点说明PeftModel.from_pretrained在基础模型之上挂载训练好的 LoRA 适配器model_id指向 checkpoint 目录无需传入config也能自动读取适配器配置通过tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue)将对话历史渲染成标准 ChatML 模板模板内嵌于 tokenizer 的chat_template中并附加生成提示符避免手工拼接出错model.generate采用贪婪/默认解码max_new_tokens512控制最大生成长度将生成的 token 减去输入部分的长度只解码新增内容并跳过特殊 token即可得到干净的回复Notebook 中微调后实测推理输出为我是甄嬛家父是大理寺少卿甄远道。说明模型已习得甄嬛人设——验证了整套微调流程的有效性。十、微调完成后的衔接部署与可视化微调产出的 LoRA 权重既可像上文那样直接以 PeftModel 形式加载使用也可与仓库中同模型的其他教程衔接成完整闭环FastAPI 部署将合并后的模型封装为 HTTP 服务见 01-Qwen2.5-Coder-7B-Instruct FastApi 部署调用.mdWebDemo 部署构建可交互的 Gradio 聊天界面见 03-Qwen2.5-Coder-7B-Instruct WebDemo部署.mdvLLM 部署面向高吞吐生产场景见 04-Qwen2.5-Coder-7B-Instruct vLLM 部署调用.mdSwanLab 可视化训练若希望在训练中实时观测 loss 曲线、超参数与逐 epoch 生成效果直接参考 SwanLab 可视化记录版。结语本文以 models/Qwen2.5-Coder/Qwen2.5-Coder-7B-Instruct Lora 微调.md 为骨架结合仓库中的 完整 Notebook 与 huanhuan 数据集 走通了数据构建 → 模板格式化 → LoRA 注入 → Trainer 训练 → 权重加载推理的完整链路。掌握这一流程后只需替换为领域数据集如法律问答、代码补全、角色对话即可低成本地把 Qwen2.5-Coder-7B-Instruct 定制成面向特定任务的专属模型。赞分享大模型人工智能教程本地部署微调【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址https://gitcode.com/datawhalechina/self-llm点击查看免费下载相关推荐self-llm 实战基于 transformers 与 peft 对 Qwen2.5-Coder-7B-Instruct 进行 LoRA 微调self llm 实战基于 transformers 与 peft 对 Qwen2.5 Coder 7B Instruct 进行 LoRA 微调 本教程是《开教程大模型本地部署微调Datawhale Self-LLM 实战基于 transformers 与 peft 的 InternLM3-8B-Instruct LoRA 微调教程Datawhale Self LLM 实战基于 transformers 与 peft 的 InternLM3 8B Instruct LoRA 微调教程 本大模型人工智能教程本地部署微调Datawhale self-llm 实战Baichuan2-7B-Chat LoRA 高效微调全流程指南transformers peftDatawhale self llm 实战Baichuan2 7B Chat LoRA 高效微调全流程指南transformers peft 本篇技术大模型人工智能教程本地部署微调创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考