资讯动态

XTuner 自定义指令微调数据集实战:从 OpenAI SFT 格式到 QLoRA 微调全流程

发布时间:2026/9/18 9:05:35 来源:尧图企业网站定制
XTuner 自定义指令微调数据集实战从 OpenAI SFT 格式到 QLoRA 微调全流程【免费下载链接】xtunerA Next-Generation Training Engine Built for Ultra-Large MoE Models项目地址: https://gitcode.com/GitHub_Trending/xt/xtuner本篇指南以 XTuner 仓库中的 自定义指令微调数据集文档 为核心结合 internlm2_chat_7b_qlora_custom_sft_e1.py 配置文件及 XTuner 数据集处理源码系统讲解如何用自有数据完成 LLM 的指令微调SFT。读完本文你将掌握 XTuner 统一的自定义数据集格式与loss字段语义、config 的导出与修改方法、QLoRA/LoRA/全量三种训练模式切换、以及训练后模型转换、对话、合并与评测的完整闭环。一、统一的自定义数据集格式OpenAI SFT 格式XTuner 采用 OpenAI SFT 数据集格式作为所有自定义指令微调数据的统一标准。数据文件是一个 JSON 数组每个元素是一条样本样本内部通过messages字段组织多轮对话格式如下[{ messages: [ { role: system, content: xxx.}, { role: user, content: xxx. }, { role: assistant, content: xxx.} ] }, { messages: [ { role: system, content: xxx. }, { role: user, content: xxx. }, { role: assistant, content: xxx., loss: false}, { role: user, content: xxx. }, { role: assistant, content: xxx., loss: true} ] }]loss 字段精确控制哪些输出参与损失计算除了 OpenAI 标准格式中的role与content字段XTuner 额外扩充了一个loss字段用于控制某轮assistant输出是否计算 loss。默认规则如下system和user角色的loss默认为False系统提示与用户输入天然不参与 loss 计算只作为上下文assistant角色的loss默认为True模型回答是监督信号的主体若希望某轮assistant的内容不参与 loss 计算需要手动将该轮数据的loss字段设为false。这一机制在多轮对话场景中非常实用例如第一轮的回答希望模型参考但不模仿或者某轮回答本身就是错误的示范、仅作为后续对话的上下文铺垫时即可通过loss: false将其从监督信号中剔除。源码验证openai_map_fn 如何解析 messages数据格式的解析逻辑位于 openai_map_fn.py。该函数将原始messages结构转换为 XTuner 内部统一的conversation结构def openai_map_fn(example): messages example[messages] system input conversation [] while messages and messages[0][role] assistant: # Skip the first one if it is from assistant messages messages[1:] for msg in messages: if msg[role] system: system msg[content] elif msg[role] user: input msg[content] elif msg[role] assistant: output_with_loss msg.get(loss, True) output_with_loss str(output_with_loss) output_with_loss output_with_loss.lower() true conversation.append({ system: system, input: input, output: msg[content], output_with_loss: output_with_loss }) system input else: raise NotImplementedError return {conversation: conversation}从源码可以看出几个值得注意的细节函数会跳过开头的assistant消息避免样本以模型回答开头导致上下文不完整user消息被累积拼接到input中assistant消息则作为一轮对话的output记录同时携带output_with_loss标志loss字段通过字符串小写比较解析因此false、False、FALSE等写法均可被识别未被识别为system/user/assistant的角色会直接抛出NotImplementedError提示用户角色字段必须严格符合规范。二、数据加载与预处理流水线process_hf_datasetconfig 中train_dataset的核心是process_hf_dataset见 huggingface.py它串联了完整的数据预处理链路顺序为加载原始数据集build_origin_dataset通过datasets.load_dataset读取 JSON 文件支持DatasetDict的按 split 拼接字段映射map_dataset应用openai_map_fn把messages转为conversation套用对话模板add_template_to_dataset应用template_map_fn_factory生成的模板函数并过滤掉conversation为空的无效数据Tokenizationtokenize_dataset调用encode_fn将文本编码为input_ids与labels过滤无监督信号样本剔除labels中完全没有有效标签全为 IGNORE_INDEX的数据打包pack_dataset通过 Packer 将多条短样本拼接填充到max_length提升 GPU 利用率记录长度为每个样本附加length属性供 length-grouped sampler 使用。其中encode_fnutils.py严格实现了 loss 掩码逻辑input部分对应的labels全部填充IGNORE_INDEX-100而output部分仅在output_with_loss为 True 时保留真实 token id 作为监督标签否则同样填充IGNORE_INDEX。这也解释了第一节中loss字段的最终生效位置。需要特别说明的两点约束源码中有显式断言若use_varlen_attnTrue则pack_to_max_length必须为Truehuggingface.py若pack_to_max_lengthTrue而remove_unused_columnsFalseXTuner 会打印警告并强制置为True因为打包时不允许存在多余列huggingface.py。三、训练准备导出并修改 config步骤 1查看候选 config 并导出xtuner/configs/custom_dataset/sft目录下存放了 XTuner 支持的各类模型在自定义数据集上使用 QLoRA 算法训练的模板 config。可以通过以下命令查看候选xtuner list-cfg -p custom_sft随后将目标模板导出到当前目录xtuner copy-cfg internlm2_chat_7b_qlora_custom_sft_e1 .执行后当前目录下会生成新文件internlm2_chat_7b_qlora_custom_sft_e1_copy.py。该模板对应的原始文件位于 xtuner/configs/custom_dataset/sft/internlm/internlm2_chat_7b_qlora_custom_sft_e1.py同目录下还提供了internlm2_chat_1_8b、internlm2_chat_20b等不同规格的等价模板。步骤 2修改数据集路径修改PART 1 Settings中的data_files为你的 JSON 文件路径支持一次指定多个文件- data_files [/path/to/json/file.json] data_files [/path/to/custom_sft1.json, /path/to/custom_sft2.json, ...]步骤 3使用整个目录的 JSON 文件作为数据集若希望使用某目录下所有 JSON 文件可同时修改PART 1与PART 3两处。底层由 json_dataset.py 中的load_json_file辅助函数实现——它通过os.listdir枚举目录下全部文件并用concatenate_datasets合并为单一数据集####################################################################### # PART 1 Settings # ####################################################################### # Data - data_files [/path/to/json/file.json] data_dir /dir/to/custom_sft ####################################################################### # PART 3 Dataset Dataloader # ####################################################################### train_dataset dict( - datasetdict(typeload_dataset, pathjson, data_filesdata_files), datasetdict(typeload_dataset, pathjson, data_dirdata_dir), ...)四、切换训练算法QLoRA / LoRA / 全量参数模板默认采用 QLoRA4-bit 量化 LoRA 低秩适配。若期望改用 LoRA保留 fp16 精度、不做 4-bit 量化或全量参数微调只需修改PART 2 Model Tokenizer中的model配置。切换为 LoRA删除quantization_config配置块保留lora配置model dict( typeSupervisedFinetune, use_varlen_attnuse_varlen_attn, llmdict( typeAutoModelForCausalLM.from_pretrained, pretrained_model_name_or_pathpretrained_model_name_or_path, trust_remote_codeTrue, torch_dtypetorch.float16, - quantization_configdict( - typeBitsAndBytesConfig, - load_in_4bitTrue, - load_in_8bitFalse, - llm_int8_threshold6.0, - llm_int8_has_fp16_weightFalse, - bnb_4bit_compute_dtypetorch.float16, - bnb_4bit_use_double_quantTrue, - bnb_4bit_quant_typenf4) ), loradict( typeLoraConfig, r64, lora_alpha16, lora_dropout0.1, biasnone, task_typeCAUSAL_LM))切换为全量参数微调在 LoRA 基础上继续删除lora配置块此时整个llm的所有参数都将参与训练model dict( typeSupervisedFinetune, use_varlen_attnuse_varlen_attn, llmdict( typeAutoModelForCausalLM.from_pretrained, pretrained_model_name_or_pathpretrained_model_name_or_path, trust_remote_codeTrue, torch_dtypetorch.float16, - quantization_configdict( - typeBitsAndBytesConfig, - load_in_4bitTrue, - load_in_8bitFalse, - llm_int8_threshold6.0, - llm_int8_has_fp16_weightFalse, - bnb_4bit_compute_dtypetorch.float16, - bnb_4bit_use_double_quantTrue, - bnb_4bit_quant_typenf4) ), - loradict( - typeLoraConfig, - r64, - lora_alpha16, - lora_dropout0.1, - biasnone, - task_typeCAUSAL_LM) )模板中的关键训练超参速览internlm2_chat_7b_qlora_custom_sft_e1.py中其余重要配置项及其默认值如下可按需调整配置项默认值含义pretrained_model_name_or_pathinternlm/internlm2-chat-7b预训练模型名或路径prompt_templatePROMPT_TEMPLATE.internlm2_chat对话模板训练与推理必须保持一致max_length2048序列最大长度超出部分被截断pack_to_max_lengthTrue是否打包填充到max_lengthbatch_size1单卡每设备 batch sizeaccumulative_counts16梯度累积步数等效全局 bs 1 × 16max_epochs1训练轮数lr2e-4学习率warmup_ratio0.03warmup 比例save_steps500每多少步保存一次 checkpointsave_total_limit2最多保留的 checkpoint 数-1 表示不限evaluation_freq500训练中每多少步进行一次生成效果评估对话模板定义于 templates.py包含default、internlm_chat、internlm2_chat、llama2_chat、chatglm2/3、qwen_chat、baichuan_chat、llama3_chat等大量现成模板template_map_fntemplate_map_fn.py会在 tokenization 前将SYSTEM/INSTRUCTION/SUFFIX等片段拼接到对话文本中。选择模板时务必与模型匹配例如 InternLM2 系列应使用internlm2_chat。五、启动训练使用xtuner train命令开始训练NPROC_PER_NODE指定使用的 GPU 数量NPROC_PER_NODE8 xtuner train internlm2_chat_7b_qlora_custom_sft_e1_copy.py --deepspeed deepspeed_zero1几点说明训练日志与 checkpoint 默认保存在./work_dirs/可通过xtuner train --work-dir ${SAVE_PATH}指定保存路径--deepspeed指定 DeepSpeed 策略配置文件可选deepspeed_zero1、deepspeed_zero2、deepspeed_zero3等配置文件位于 xtuner/configs/deepspeed 目录另有 offload 变体xtuner train还支持--resume断点续训、--seed随机种子、--cfg-options命令行覆盖 config 字段等参数详见 train.py源码中的check_cfgtrain.py会在训练前做多项校验如use_varlen_attnTrue时要求batch_size1且安装flash_attn未启用 DeepSpeed 时不允许开启序列并行等。六、模型转换pth_to_hf训练完成后checkpoint 默认保存为 PTH 格式如iter_2000.pth若使用了 DeepSpeed则为同名文件夹。需要使用xtuner convert pth_to_hf将其转换为 HuggingFace 格式以便后续加载与使用xtuner convert pth_to_hf ${FINETUNE_CFG} ${PTH_PATH} ${SAVE_PATH} # 例如 xtuner convert pth_to_hf internlm2_chat_7b_qlora_custom_sft_e1_copy.py ./iter_2000.pth ./iter_2000_hf转换工具的更多参数pth_to_hf.py包括--fp32以 fp32 保存 LLM 权重默认 fp16、--max-shard-size分片大小默认 2GB、--safe-serialization使用 safe serialization、--save-formatLLaVA 模型可选择xtuner/official/huggingface三种格式。七、对话验证xtuner chat训练转换完成后可使用xtuner chat与微调后的模型交互。LoRA / QLoRA 微调后的对话xtuner chat ${NAME_OR_PATH_TO_LLM} --adapter {NAME_OR_PATH_TO_ADAPTER} --prompt-template ${PROMPT_TEMPLATE} [optional arguments] # 例如 xtuner chat internlm/internlm2-7b --adapter ./iter_2000_hf --prompt-template internlm2_chat全量微调后的对话xtuner chat ${PATH_TO_LLM} --prompt-template ${PROMPT_TEMPLATE} [optional arguments] # 例如 xtuner chat ./iter_2000_hf --prompt-template internlm2_chat其中${PROMPT_TEMPLATE}表示模型的对话模板必须与训练 config 中的prompt_template字段保持一致。以internlm2_chat_7b_qlora_custom_sft_e1_copy.py为例其设置为prompt_template PROMPT_TEMPLATE.internlm2_chatxtuner chat的其他可用参数chat.py包括--torch-dtype默认 fp16、--system/--system-template指定系统提示、--bits4/8 bit 加载、--with-plugins启用 calculate/solve/search 插件、--no-streamer关闭流式输出、--lagent使用 lagent 能力等。八、模型合并可选若使用 LoRA / QLoRA 微调转换后得到的是 adapter 参数并不包含原始 LLM 权重。如果希望获得可直接加载的合并权重例如用于后续评测、部署可使用xtuner convert mergextuner convert merge ${LLM} ${LLM_ADAPTER} ${SAVE_PATH}模型合并完成后即得到一个可通过AutoModelForCausalLM.from_pretrained直接加载的完整模型可在各种下游工具中直接使用无需再单独携带 adapter 权重。九、评测评测大语言模型推荐使用一站式平台 OpenCompass其目前已涵盖 50 数据集的约 30 万条题目。对于在自定义 SFT 数据集上微调得到的模型可将上述合并后的权重或 adapter 接入 OpenCompass 完成指令跟随、知识问答等维度的评估。XTuner 仓库本身也在 xtuner/evaluation 目录提供了 MMLU 等评估指标与evaluate_chat_hook的参考实现可结合使用。十、常见问题与注意事项角色字段必须合法messages中只允许system/user/assistant三种角色出现其他角色会触发NotImplementedErrorloss字段大小写不敏感false/False/FALSE均可被正确解析为不计算 loss对话模板一致性训练用prompt_template与推理时xtuner chat --prompt-template必须一致否则模型输入分布错位会导致效果劣化数据路径不要混淆data_files指向具体文件列表data_dir指向目录此时加载目录下所有文件两者只能二选一长序列场景若数据超长可适当增大max_length或参考 XTuner 的 varlen attention / 序列并行方案见 docs/zh_cn/acceleration 与 docs/zh_cn/user_guides/varlen_attention.md。通过以上九个步骤即可完整走通自定义数据 → QLoRA/LoRA/全量微调 → 权重转换 → 对话验证 → 合并 → 评测的 LLM 指令微调全流程将 XTuner 的 OpenAI SFT 格式数据能力应用于任意自有业务场景。【免费下载链接】xtunerA Next-Generation Training Engine Built for Ultra-Large MoE Models项目地址: https://gitcode.com/GitHub_Trending/xt/xtuner创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价