资讯动态

XTuner 多轮对话 SFT 数据 pipeline 完全指南:从 HuggingFace Hub 与自定义数据集到可训练 Config

发布时间:2026/9/18 6:53:46 来源:尧图企业网站定制
XTuner 多轮对话 SFT 数据 pipeline 完全指南从 HuggingFace Hub 与自定义数据集到可训练 Config【免费下载链接】xtunerA Next-Generation Training Engine Built for Ultra-Large MoE Models项目地址: https://gitcode.com/GitHub_Trending/xt/xtuner本文围绕 XTuner 的多轮对话指令微调数据管线展开系统讲解如何将 HuggingFace Hub 开源数据集或自定义 JSON 数据集通过 map function 映射、模板拼接与打包转换为可直接驱动 SFT 训练的train_dataset。读完本文你将掌握 XTuner 多轮对话标准数据格式、process_hf_dataset底层处理流程、oasst1_map_fn等内置映射函数的实现原理以及从xtuner list-cfg到xtuner train的完整落地步骤。多轮对话 SFT 与 XTuner 数据 pipeline 概览多轮对话指令微调Supervised FineTuneSFT旨在提升模型的多轮对话能力。与单轮对话不同多轮对话数据由多轮指令问题 对应 GroundTruth 回答组成模型需要学会在延续上下文的前提下逐轮应答。XTuner 在数据处理阶段需要将原始数据转换为其内置支持的数据集格式整体支持两条数据来源路径HuggingFace Hub 数据集直接通过datasets.load_dataset加载核心工作是把不同数据集的原始格式映射为 XTuner 定义的多轮对话数据格式自定义数据集推荐用户直接按照多轮对话数据格式构造 JSON 数据集从而免去映射步骤。两条路径殊途同归最终都会汇入 XTuner 统一的数据后处理入口process_hf_dataset定义于 xtuner/dataset/huggingface.py依次完成原始数据加载 → map function 格式映射 → prompt 模板拼接 → tokenize → pack 打包的流水线处理。多轮对话数据格式XTuner 的标准格式理解标准格式是使用多轮对话数据的前提。XTuner 为统一增量预训练、单轮对话、多轮对话三种数据集格式引入了system、input、output三个核心字段见 数据集格式文档system、input保存不参与 loss 计算的文本例如系统提示词和用户指令output保存需要计算 loss的文本即指令对应的 GroundTruth 回答。在训练过程中一条数据内的多组system/input/output会被拼接后整体输入模型并行计算每个 token 位置的 loss但只有output部分的 loss 参与梯度回传指令部分不参与权重更新。多轮对话数据集中conversation键对应的值是一个列表列表中每个元素保存一轮对话。列表长度为 n 即可容纳 n 轮对话因此增量预训练与单轮对话数据集可以看作conversation列表长度为 1 的特例。一个典型的多轮对话数据集长这样[{ conversation:[ { system: You are an AI asssistant., input: Hello?, output: Hello! How can I help you? }, { input: Whats the date today?, output: Today is Monday, August 14, 2023. }, { input: Thank you!, output: You are welcome. } ] }, { conversation:[ { system: You are an AI asssistant., input: Hello?, output: Hello! How can I help you? }, { input: Hows the weather today in Rosso?, output: The weather in Rosso on Wednesday, August 16th, is going to be cloudy for most of the day, together with moderate rain around noon. }, { input: Thank you!, output: You are welcome. } ] }]注意system字段仅在首轮出现后续轮次可省略缺省为空字符串。EOS、BOS等特殊 token 由模板与 tokenizer 在后续阶段统一处理。三种主流多轮对话训练方法对比针对一条多轮对话数据如何用于训练业界存在两种常见做法而 XTuner 采取了更充分高效的方式详见 dataset_format.md方法 1仅末轮参与训练将 System、User1User3 全部视为输入仅把 Assistant3 作为预测目标。弊端是 Assistant1、Assistant2 完全未参与训练数据利用率低方法 2拆分多条将一条 n 轮对话拆成 n 条独立数据每轮都参与训练。缺点是需要把数据量膨胀为原来的 n 倍训练效率下降为 1/nXTuner 方法整段拼接 掩码回传将多轮对话整体拼接后输入模型并行计算每个位置的 loss仅output部分的 loss 参与回传。既保证了每一轮回答都参与训练又不需要拆分数据兼顾数据利用率与训练效率。这也是 XTuner 多轮对话数据格式采用conversation列表结构的原因。路径一使用 HuggingFace Hub 数据集当目标数据集托管在 HuggingFace Hub 上时如 oasst1、alpaca、open_orca 等你需要把其原始字段映射为 XTuner 标准格式。下面以 oasst1 数据集为例走完全部流程。Step 1映射原始数据集为标准格式由于不同数据集的字段与组织方式千差万别XTuner 通过map function实现格式映射。先观察 oasst1 的原始格式 from datasets import load_dataset ds load_dataset(pathtimdettmers/openassistant-guanaco) ds[train] Dataset({ features: [text], num_rows: 9846 }) ds[train][0][text] ### Human: xxx ### Assistant: xxx ###Human: xxx ###Assistant: xxx可以看到oasst1 每一条样本是一个以### Human:/### Assistant:分隔标记的纯文本天然携带多轮对话信息。这样的数据既可以当作增量预训练语料也可以处理后作为多轮对话数据集。通过下面的 map function即可把text解析为conversation列表# 假设将该函数存放在 ./map_fn.py 文件中 SYSTEM_OASST1 # oasst1 并未使用 system 字段 def custom_map_fn(example): r Example before preprocessing: example[text] ### Human: Can you explain xxx ### Assistant: Sure! xxx ### Human: I didnt understand how xxx ### Assistant: It has to do with a process xxx. Example after preprocessing: example[conversation] [ { input: Can you explain xxx, output: Sure! xxx }, { input: I didnt understand how xxx, output: It has to do with a process xxx. } ] data [] for sentence in example[text].strip().split(###): sentence sentence.strip() if sentence[:6] Human:: data.append(sentence[6:].strip()) elif sentence[:10] Assistant:: data.append(sentence[10:].strip()) if len(data) % 2: # The last round of conversation solely consists of input # without any output. # Discard the input part of the last round, as this part is ignored in # the loss calculation. data.pop() conversation [] for i in range(0, len(data), 2): system SYSTEM_OASST1 if i 0 else single_turn_conversation { system: system, input: data[i], output: data[i 1]} conversation.append(single_turn_conversation) return {conversation: conversation}该函数的关键逻辑按###分隔文本并去掉首尾空白依据Human:/Assistant:前缀归类到data列表若data长度为奇数说明最后一轮只有提问没有回答直接pop丢弃——因为该部分在 loss 计算中会被忽略保留无意义两两配对组装成{system, input, output}字典仅在首轮写入 system 字段。这一逻辑与仓库内置的官方实现 xtuner/dataset/map_fns/dataset_map_fns/oasst1_map_fn.py 完全一致你可以直接对比阅读。除 oasst1 外xtuner/dataset/map_fns/dataset_map_fns/目录下还提供了alpaca_map_fn、openorca_map_fn、wizardlm_map_fn、sql_map_fn、code_alpaca_map_fn等二十余个内置映射函数覆盖常见开源 SFT 数据集。Step 2列出候选模型名字XTuner 提供多个开箱即用的配置文件可通过以下命令查看xtuner list-cfg -p internlm-p为模糊查找参数若想训练其他模型将internlm替换为 XTuner 支持的其他模型名称即可例如baichuan、llama、qwen、chatglm、deepseek等完整列表可查看 xtuner/configs 目录。Step 3复制 config 文件如果现有配置文件不能满足需求先将其导出到本地再进行修改xtuner copy-cfg ${CONFIG_NAME} ${SAVE_DIR}例如将名为internlm_7b_qlora_oasst1_e3的 config 导出至当前目录xtuner copy-cfg internlm_7b_qlora_oasst1_e3 .该配置的原始版本位于 xtuner/configs/internlm/internlm_7b/internlm_7b_qlora_oasst1_e3.py导出的文件将以拷贝形式落在当前目录供你编辑。Step 4修改 config 文件对 Step 3 复制得到的 config 文件需要做三处修改导入 Step 1 中实现的映射函数custom_map_fn用custom_map_fn替换train_dataset中的dataset_map_fn调整原始数据集的路径load_dataset的具体用法可参考 HuggingFace datasets 官方文档的 loading 章节。完整 diff 如下from xtuner.dataset import process_hf_dataset from datasets import load_dataset - from xtuner.dataset.map_fns import oasst1_map_fn, template_map_fn_factory from xtuner.dataset.map_fns import template_map_fn_factory from mmengine.config import read_base with read_base(): from .map_fn import custom_map_fn ... ####################################################################### # PART 1 Settings # ####################################################################### - data_path timdettmers/openassistant-guanaco data_path path/to/your/data ... ####################################################################### # STEP 3 Dataset Dataloader # ####################################################################### train_dataset dict( typeprocess_hf_dataset, datasetdict(typeload_dataset, pathdata_path), tokenizertokenizer, max_lengthmax_length, - dataset_map_fnoasst1_map_fn, dataset_map_fncustom_map_fn, template_map_fndict( typetemplate_map_fn_factory, templateprompt_template), remove_unused_columnsTrue, shuffle_before_packTrue, pack_to_max_lengthpack_to_max_length) ...Step 5检查数据集可选修改配置文件后可以运行检查脚本验证数据集是否正确构建xtuner check-custom-dataset $CONFIG其中$CONFIG是 Step 4 修改过的 config 文件路径。该命令对应脚本 xtuner/tools/check_custom_dataset.py它会依次打印dataset_map_fn映射后的conversation、加入模板后的结果、tokenize 后的input_ids/labels以及 pack 到max_length之后的结果方便你逐环节核对数据是否正确。路径二使用自定义数据集当数据是自己构造的例如业务场景私有对话数据时推荐直接按 XTuner 标准格式构造数据集。若你的自定义数据集是 oasst1 等其他格式则参考上一节使用 HuggingFace Hub 数据集的做法编写 map function 即可。Step 1数据集准备按照多轮对话数据格式准备自定义 JSON 数据[{ conversation:[ { system: xxx, input: xxx, output: xxx }, { input: xxx, output: xxx } ] }, { conversation:[ { system: xxx, input: xxx, output: xxx }, { input: xxx, output: xxx } ] }]Step 2列出候选模型名字xtuner list-cfg -p internlm-p为模糊查找如需训练其他模型将internlm替换为 XTuner 支持的其他模型名称。Step 3复制 config 文件xtuner copy-cfg internlm_7b_qlora_oasst1_e3 .Step 4修改 config 文件自定义数据集场景下需要两处修改调整原始数据集的路径由于数据集已是 XTuner 标准格式需将train_dataset中的dataset_map_fn置为None并将load_dataset的path指定为json以加载本地 JSON 文件from xtuner.dataset import process_hf_dataset from datasets import load_dataset - from xtuner.dataset.map_fns import oasst1_map_fn, template_map_fn_factory from xtuner.dataset.map_fns import template_map_fn_factory ... ####################################################################### # PART 1 Settings # ####################################################################### - data_path timdettmers/openassistant-guanaco data_path path/to/your/json/data ... ####################################################################### # STEP 3 Dataset Dataloader # ####################################################################### train_dataset dict( typeprocess_hf_dataset, - datasetdict(typeload_dataset, pathdata_path), datasetdict( typeload_dataset, pathjson, data_filesdict(traindata_path)), tokenizertokenizer, max_lengthmax_length, - dataset_map_fnoasst1_map_fn, dataset_map_fnNone, template_map_fndict( typetemplate_map_fn_factory, templateprompt_template), remove_unused_columnsTrue, shuffle_before_packTrue, pack_to_max_lengthpack_to_max_length) ...Step 5检查数据集可选xtuner check-custom-dataset $CONFIG其中$CONFIG是 Step 4 修改过的 config 文件路径。该脚本还会自动做两项合法性校验见 xtuner/tools/check_custom_dataset.py若数据不是标准格式且dataset_map_fn为None会报错提示你需要提供dataset_map_fn完成格式映射若数据已是标准格式但dataset_map_fn非空会报错提示你将其置为None避免重复映射。因此写自定义数据集时务必保证dataset_map_fn的设置与数据实际格式严格匹配。底层机制process_hf_dataset 数据处理流水线理解process_hf_dataset的底层实现源码见 xtuner/dataset/huggingface.py有助于你精准排错和调优。一次完整的多轮对话数据处理会经历以下阶段构建原始数据集build_origin_dataset通过注册器BUILDER.build执行 config 中dataset的构造逻辑若结果是DatasetDict且未指定split会将其各 split 拼接为一个数据集格式映射map_dataset调用dataset_map_fn将原始字段转换为conversation标准格式。dataset_map_fn既可以是函数也可以是注册在MAP_FUNC中的字符串名称映射时通过dataset.map(dataset_map_fn, num_procmap_num_proc)并行执行模板拼接add_template_to_dataset调用template_map_fn为每一轮对话套上 prompt 模板随后过滤掉conversation为空的数据tokenizetokenize_dataset调用encode_fn把文本编码为input_ids与labels并依据input_ids_with_output决定是否保留 GroundTruth 输出随后过滤掉labels中完全没有有效标签全部小于 0的数据打包若pack_to_max_length为 True先按shuffle_before_pack决定是否打乱再用Packer将多条短样本拼接到max_length以提升 GPU 利用率、缩短训练时间附加长度信息为每条样本计算length字段供长度分组采样等模块使用。其中template_map_fn的实现位于 xtuner/dataset/map_fns/template_map_fn.py它逐轮处理conversation用template.INSTRUCTION格式化input并在存在非空system时用template.SYSTEM把系统提示词拼到最前面若模板定义了SUFFIX如eos后缀将其追加到output末尾为每轮写入need_eos_token与sep字段控制本轮回答是否需要补 EOS token 及轮与轮之间的分隔符。train_dataset中常用参数的作用如下参数默认值作用dataset_map_fnNone将原始数据映射为conversation标准格式的函数或注册名template_map_fnNone拼接 prompt 模板template_map_fn_factory按template参数构造max_length必填序列最大长度tokenize 与 pack 阶段的上限max_dataset_lengthNone若数据量过大可随机抽取指定条数参与映射以节省时间splittrain加载的数据划分pack_to_max_length为 True 时只能取train或Noneremove_unused_columnsFalse是否移除训练中不用的列pack_to_max_length为 True 时会被强制置为 Trueshuffle_before_packTruepack 前是否打乱样本pack_to_max_lengthTrue是否将样本打包至max_length通常能提升 GPU 利用率input_ids_with_outputTrue是否把 GroundTruth 输出写入数据集训练时为 True、测试时通常为 Falsemap_num_proc32映射阶段的最大并行进程数值得注意的是在分布式训练场景下process_hf_dataset只在 rank 0 上执行完整处理随后通过broadcast_object_list将结果广播到其他 rank并用XTUNER_DATASET_TIMEOUT默认 60 分钟控制同步超时避免各卡重复预处理。实操示例examples/demo_data/multi_turn_1仓库在 examples/demo_data/multi_turn_1 提供了可直接运行的多轮对话演示数据完整覆盖数据 map 函数 config三件套data.json使用messages字段承载轮次内部是toy_system/toy_input/toy_output命名的字段map_fn.pymulti_turn_1_map_fn将messages逐条转换为{system, input, output}并组装为conversation列表def multi_turn_1_map_fn(example): messages example[messages] conversation [] for msg in messages: conversation.append({ system: msg[toy_system], input: msg[toy_input], output: msg[toy_output] }) return {conversation: conversation}config.py基于internlm_7b_qlora_json_e3派生关键改动是用read_base导入multi_turn_1_map_fn作为dataset_map_fn、把data_path指向./data.json其余训练超参数max_length2048、pack_to_max_lengthTrue、QLoRA 4bit 量化、r64的 LoRA 等保持可用状态。启动训练只需cd ./examples/demo_data/multi_turn_1 xtuner train config.py常见问题与排错建议数据格式与dataset_map_fn不匹配xtuner check-custom-dataset会主动检测非标准格式但未提供 map 函数或标准格式却设置了 map 函数两种错误请据此调整 configpack 与 split 冲突pack_to_max_lengthTrue时split只能为train或None否则会直接断言失败pack 时未清理多余列pack_to_max_lengthTrue会强制remove_unused_columnsTrue无需手动处理但若你显式设置了False会收到警告多轮数据末轮无回答这是正常现象用户最后一轮往往没有回答映射函数会将其丢弃因为该部分不参与 loss 计算system 字段的轮次语义XTuner 约定system只在首轮出现若你的原始数据每轮都带 system请只在第一轮保留避免模板重复拼接系统提示词。通过本文的两种路径与底层原理讲解你可以根据自己的数据形态选择内置 map 函数/HuggingFace Hub或标准格式自定义 JSON任一路径快速搭建多轮对话 SFT 训练管线并借助check-custom-dataset在训练前完成数据质量验证。【免费下载链接】xtunerA Next-Generation Training Engine Built for Ultra-Large MoE Models项目地址: https://gitcode.com/GitHub_Trending/xt/xtuner创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

免费获取报价