基于 transformers 与 peft 对 TransNormerLLM-7B 进行 LoRA 微调:从环境配置到甄嬛风格对话模型实战
发布时间:2026/9/12 16:16:56 作者:尧图编辑部 阅读量:1,286

基于 transformers 与 peft 对 TransNormerLLM-7B 进行 LoRA 微调从环境配置到甄嬛风格对话模型实战【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm导读本文是《开源大模型食用指南》中 TransNormerLLM 系列教程的 LoRA 微调篇完整讲解如何基于transformers、peft、datasets等框架对线性注意力大模型 TransNormerLLM358M/1B/7B进行高效参数微调LoRA。教程以甄嬛风格对话为实战目标使用仓库自带的 huanhuan.json 指令数据集从环境搭建、指令集构建、数据格式化、模型加载、LoRA 配置、训练到微调后权重推理给出全程可复制运行的代码。读完本文你将掌握一套适用于任何 Chat 类开源模型的 LoRA 微调标准流程并了解如何基于目标人物/领域语料构建个性化 LLM。同目录的 04-TransNormerLLM-7B-chat-Lora.ipynb 提供了可逐格运行的 Notebook 版本可与本文对照学习。一、微调对象TransNormerLLM-7B 与 LoRA 思路TransNormerLLM 是一个基于线性注意力的大语言模型在准确性上可与基于 softmax 注意力的传统模型媲美同时具备更高的训练与推理效率提供 385M、1B、7B 等多个参数规模版本。其核心架构改进包括带指数衰减的 LRPE 线性化相对位置编码、门控式线性注意力GLA与 Simple GLUSGLU门控机制、SimpleRMSNormSRMSNorm张量归一化等整体结构可参考 01-TransNormerLLM-7B FastApi 部署调用.md 中的架构图。图 1TransNormerLLM 的架构图其中 GLA门控线性注意力与 SGLU门控线性单元是理解 LoRAtarget_modules选择的关键图片来源01-TransNormerLLM-7B FastApi 部署调用.md从 04-TransNormerLLM-7B-chat-Lora.ipynb 中打印出的模型结构可以看到TransnormerForCausalLM由 30 层TransnormerDecoderLayer堆叠而成每层包含token_mixerNormLinearAttention内含qkvu_proj4096→16384与out_proj4096→4096即注意力部分的 Q/K/V/O 投影channel_mixerGLU内含l1/l24096→11008与l311008→4096三个线性层对应门控前馈网络嵌入层词表大小为 64000隐藏维度 4096lm_head输出维度 64000。正是基于这一结构后续LoraConfig中target_modules才能精确指定到各投影层。LoRA 微调的核心思想冻结原始预训练权重仅在需要适配的线性层旁注入低秩分解矩阵$B \times A$训练时只更新这部分极小的参数推理时把增量合并回原权重从而以极低的显存与算力开销完成领域适配。其缩放系数为lora_alpha / r对微调效果影响显著下文会结合配置详解。二、环境配置依赖安装与国内源加速在完成基础环境配置和本地模型部署参见同目录 FastApi/WebDemo 教程后还需要安装微调所需的第三方库。官方推荐在 AutoDL 等平台上租用 3090/4090 等 24G 显存机器镜像选择 PyTorch 2.0.0 / Python 3.8 / CUDA 11.8 及以上均可。安装依赖前先升级 pip 并切换到国内镜像源避免下载超时# 升级pip python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple方式一逐行安装推荐新手逐条确认pip install modelscope1.11.0 pip install transformers4.37.0 pip install streamlit1.24.0 pip install sentencepiece0.1.99 pip install accelerate0.24.1 pip install transformers_stream_generator0.0.4 pip install datasets2.18.0 pip install peft0.10.0 pip install deepspeed pip install triton2.0.0 pip install einops MAX_JOBS8 pip install flash-attn --no-build-isolation或合并为一行pip install modelscope1.11.0 transformers4.37.0 streamlit1.24.0 sentencepiece0.1.99 accelerate0.24.1 transformers_stream_generator0.0.4 datasets2.18.0 peft0.10.0 deepspeed triton2.0.0 einops MAX_JOBS8 pip install flash-attn --no-build-isolation方式二requirements.txt 批量安装用 vim 将如下内容写入requirements.txt后执行pip install -r requirements.txtmodelscope1.11.0 transformers4.37.0 streamlit1.24.0 sentencepiece0.1.99 accelerate0.24.1 transformers_stream_generator0.0.4 datasets2.18.0 peft0.10.0 deepspeed triton2.0.0 einops随后单独安装 flash-attnMAX_JOBS8 pip install flash-attn --no-build-isolation注意flash-attn需要本地编译安装比较慢大概需要十几分钟请耐心等待。MAX_JOBS8用于限制并行编译任务数避免内存不足导致编译失败。各依赖在本教程中的角色transformers提供模型与训练器Trainer、peft提供 LoRA 实现LoraConfig/PeftModel、datasets负责数据集加载与映射、accelerate支撑device_mapauto的自动设备分配、sentencepiece与triton服务于分词与加速内核、flash-attn加速注意力计算TransNormerLLM 的线性注意力实现依赖自定义 CUDA kernel 时通常需要。三、指令集构建从对话数据到 (instruction, input, output)LLM 的微调一般指指令微调SFT即让模型学会理解并遵循用户指令。本教程使用的微调数据形如{ instruction: 回答以下用户问题仅输出答案。, input: 11等于几?, output: 2 }字段含义instruction用户指令告知模型需要完成的任务input用户输入是完成任务所必需的输入内容可以为空字符串output模型应该给出的标准输出。指令集构建的核心原则是针对目标任务定制目标是什么角色/能力就构造对应的指令。例如本教程的目标是训练一个模拟甄嬛说话风格的个性化 LLM因此构造的指令形如{ instruction: 你是谁, input: , output: 家父是大理寺少卿甄远道。 }本节使用的微调数据集是位于仓库根目录的 huanhuan.jsonJSON 数组格式共 3729 条数据源自合作者开源的Chat-甄嬛项目详见 examples/Chat-嬛嬛/readme.md。该项目的思路是从《甄嬛传》剧本中抽取甄嬛相关台词整理成问答对通过 LoRA 微调得到模仿甄嬛语气的聊天模型。除甄嬛语料外也可直接使用alpaca_data.json52,002 条指令数据重新格式化后可用于 SFT 演示。说明huanhuan.json之外仓库还提供 huanhuan.jsonl逐行 JSON 格式与 huanhuan-100.json小样本版本便于快速验证流程三份数据内容同源。四、数据格式化编码输入与标签LoRA 训练前文本必须格式化为模型可接受的 token 序列输入文本编码为input_ids输出文本编码为labels用于计算损失同时生成attention_mask。熟悉 PyTorch 训练流程的同学都清楚编码后的结果是多维向量因此先定义预处理函数对每个样本编码输入、输出文本并返回编码字典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 }这段代码有四个关键设计Prompt 模板TransNormerLLM-7B 采用 ChatML 风格的Prompt Template格式|im_start|system You are a helpful assistant.|im_end| |im_start|user 你是谁|im_end| |im_start|assistant 我是一个有用的助手。|im_end|add_special_tokensFalse保证不在文本开头额外插入特殊 token模板由我们自己完整拼装。标签掩码-100instruction部分对应的 labels 全部置为-100这是 PyTorch 交叉熵损失的标准忽略索引——模型只在回答部分assistant之后的output计算损失不会学习用户提问部分。Pad token 处理序列末尾补上tokenizer.pad_token_idattention_mask对应位置补1因为 eos/pad token 也属于需要关注的序列一部分。注意在使用前需显式设置tokenizer.pad_token tokenizer.eos_tokenNotebook 中已包含该步骤因为 TransNormerLLM 的 tokenizer 默认未定义 pad token。截断MAX_LENGTH 384超出部分直接切片截断。中文按字切分 token 较多因此最大长度要适当放宽。数据加载与映射参考同目录 Notebook 的 Step.2数据加载与格式化过程为import pandas as pd import torch from datasets import Dataset df pd.read_json(./huanhuan.json) ds Dataset.from_pandas(df) tokenizer AutoTokenizer.from_pretrained(/root/autodl-tmp/OpenNLPLab/TransNormerLLM-7B/, use_fastFalse, trust_remote_codeTrue) tokenizer.pad_token tokenizer.eos_token tokenized_id ds.map(process_func, remove_columnsds.column_names)Dataset.map会对全部 3729 条样本执行process_funcremove_columns会移除原始列最终得到仅含input_ids、attention_mask、labels三列的训练集。可用tokenizer.decode(tokenized_id[0][input_ids])验证格式化结果应能看到完整还原的 system/user/assistant 对话模板。五、加载 tokenizer 与半精度模型模型以半精度bfloat16加载如果你的显卡较新可以优先使用torch.bfloat16显存占用约为 fp32 的一半且训练更稳定tokenizer AutoTokenizer.from_pretrained(/root/autodl-tmp/OpenNLPLab/TransNormerLLM-7B/, use_fastFalse, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(/root/autodl-tmp/OpenNLPLab/TransNormerLLM-7B/, trust_remote_codeTrue, device_mapauto, torch_dtypetorch.bfloat16)两点务必注意trust_remote_codeTrue必须指定TransNormerLLM 属于自定义模型架构其模型定义、tokenizer 实现以远程代码形式随权重发布必须信任并执行远程代码才能正确加载device_mapauto由 accelerate 自动将模型权重分配到可用 GPU/CPU 显存上可有效规避单卡显存不足导致的 OOM。Notebook 中模型加载时的日志We will use 90% of the memory on device 0...正是 accelerate 自动切分的结果。从 Notebook 打印结果看模型共 3 个 checkpoint shards分片权重加载后得到完整的TransnormerForCausalLM结构这是后续配置 LoRAtarget_modules的直接依据。六、定义 LoraConfig核心参数与缩放原理LoraConfig中可以设置的参数很多但核心就几个分别说明task_type任务类型。因果语言建模文本生成选TaskType.CAUSAL_LMtarget_modules需要注入 LoRA 的层名即注意力与前馈网络的投影层。TransNormerLLM 中即q_proj、k_proj、v_proj、o_proj注意力四投影对应架构中的qkvu_proj/out_proj以及gate_proj、up_proj、down_proj门控前馈对应架构中的GLU三层。可以传数组、字符串或正则表达式rLoRA 的秩rank即低秩分解矩阵的维度决定新增可训练参数量与表达能力lora_alphaLoRA 缩放因子lora_dropout注入层的 Dropout 比例用于防止过拟合。一个关键问题LoRA 的缩放系数是什么不是r秩而是lora_alpha / r。以下面配置为例缩放系数为32 / 8 4即注入的低秩增量在合并时会放大 4 倍from peft import LoraConfig, TaskType, get_peft_model 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 alpha缩放系数 lora_alpha/r 4 lora_dropout0.1 # Dropout 比例 ) model get_peft_model(model, config) model.print_trainable_parameters() # 打印可训练参数量实践要点r增大可提升适配能力但增加参数量与过拟合风险lora_alpha与r的比值控制注入强度。7B 模型在r8时新增参数量通常仅占原模型的 0.1% 左右可用print_trainable_parameters()验证这正是高效微调的体现。inference_modeFalse表示当前处于训练模式。七、自定义 TrainingArguments训练超参配置TrainingArguments封装了训练器所需的全部超参数源码对每个参数都有详细注释这里重点说明本教程用到的几个output_dir模型输出路径checkpoint 保存目录per_device_train_batch_size单卡 batch sizegradient_accumulation_steps梯度累加步数。显存较小时可把 batch_size 调小、梯度累加调大等效扩大 batch sizelogging_steps每多少步输出一次训练日志num_train_epochs训练轮数save_steps每多少步保存一次 checkpointlearning_rate学习率gradient_checkpointing梯度检查点以少量计算换大量显存。一旦开启模型必须执行model.enable_input_require_grads()否则反向传播会因输入张量无梯度而报错这一点在 examples/Chat-嬛嬛/train.py 中有对应实现原理可自行深入探索。from transformers import TrainingArguments args TrainingArguments( output_dir./output/TransNormerLLM-7B-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 )注同目录 04-TransNormerLLM-7B-chat-Lora.ipynb 与 Markdown 中output_dir均写为./output/DeepSeek这是早期复制其他模型教程时遗留的命名实际训练时应统一改为./output/TransNormerLLM-7B-Lora避免与 LoRA 加载路径混淆见第九节。八、使用 Trainer 开始训练基于transformers的Trainer训练代码非常简洁。DataCollatorForSeq2Seq负责在 batch 内对不同长度的样本做 padding 对齐from transformers import Trainer, DataCollatorForSeq2Seq trainer Trainer( modelmodel, argsargs, train_datasettokenized_id, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue), ) trainer.train()训练流程说明Trainer内部自动完成前向、损失计算、反向传播、优化器更新与 checkpoint 保存由于启用了gradient_checkpointing务必在Trainer之前调用model.enable_input_require_grads()训练完成后LoRA 权重会按save_steps周期保存到output_dir自动保存策略下无需手动保存。至此一个具备甄嬛说话风格的 TransNormerLLM-7B 微调模型就训练完成了。九、加载 LoRA 权重进行推理训练完成后用PeftModel.from_pretrained将 LoRA 增量权重加载到基座模型上即可对话。注意必须先加载原始基座模型再叠加 LoRA 权重from transformers import AutoModelForCausalLM, AutoTokenizer import torch from peft import PeftModel mode_path /root/autodl-tmp/OpenNLPLab/TransNormerLLM-7B/ lora_path ./output/TransNormerLLM-7B-Lora # 即 TrainingArguments 中的 output_dir # 加载tokenizer tokenizer AutoTokenizer.from_pretrained(mode_path) # 加载基座模型 model AutoModelForCausalLM.from_pretrained(mode_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)几点说明tokenizer.apply_chat_template会根据模型模板自动组装 system/user 消息并追加 assistant 生成提示符add_generation_promptTrue推理时使用与训练一致的模板与 system 提示现在你要扮演皇帝身边的女人--甄嬛否则微调效果无法充分发挥generated_ids中截取input_ids之后的部分避免重复输出用户提问若为展示推理结果在 Jupyter Notebook 中运行可参考同目录 Notebook 的 Step.4 完整单元格若希望以 HTTP API 方式对外提供微调后模型的对话服务可参考同目录 01-TransNormerLLM-7B FastApi 部署调用.md 的 FastAPI 封装思路将model.generate逻辑移植到 POST 接口中。十、常见问题与调参建议显存不足OOM优先启用gradient_checkpointingTrue并调用model.enable_input_require_grads()再将per_device_train_batch_size调小如 2 或 1并同步增大gradient_accumulation_steps如 8 或 16以保持等效 batch size同时使用torch.bfloat16半精度加载。输出风格不像目标角色检查数据质量与数量本教程为 3729 条可考虑扩充语料、适当增大num_train_epochs如 3→5或提高r与lora_alpha。中文回复乱码或截断确认MAX_LENGTH384是否足够中文 token 化较费长度检查tokenizer.pad_token tokenizer.eos_token是否已设置。推理时加载路径不一致lora_path必须指向训练时output_dir保存的 checkpoint 目录含adapter_config.json与adapter_model.bin不要与基座模型路径混淆。trust_remote_code缺失TransNormerLLM 为自定义架构加载 tokenizer 与模型时都必须传入trust_remote_codeTrue。结语本文以 04-TrasnNormerLLM-7B Lora 微调.md 为主线完整走通了 TransNormerLLM-7B 的 LoRA 微调全流程并结合 04-TransNormerLLM-7B-chat-Lora.ipynb 的源码级细节模型结构、数据加载、可训练参数做了纵深补充。这套指令集构建 → 数据格式化 → LoraConfig → TrainingArguments → Trainer 训练 → PeftModel 推理的方法论同样适用于其他 Chat 类开源模型——只需替换模型路径、Prompt 模板与target_modules即可。若想进一步了解模型本身的部署调用与知识库接入可继续阅读同目录的 FastApi 部署、LangChain 接入 与 WebDemo 教程。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考