LLM 微调数据集整理实战指南:格式选择、模板掩码、序列打包与数据集卡片(dataset-curation)
2026/9/10 17:15:51 网站建设 项目流程

LLM 微调数据集整理实战指南:格式选择、模板掩码、序列打包与数据集卡片(dataset-curation)

【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents

导读

dataset-curation是 llm-finetuning 插件在微调生命周期 Phase 2(数据集准备阶段)的核心技能,负责把原始示例(演示数据、偏好判定或任务提示词)转化为格式正确、完成打包、通过验证的 JSONL 数据集,并产出一张完整的数据集卡片。本文以该技能文档为主体,结合仓库内的格式与模板参考、合成数据参考以及/finetune命令的 Phase 2 调用链,系统讲解数据格式如何按微调方法选择、聊天模板与损失掩码如何避免"静默失败"、序列打包如何省算力、合成数据如何防坍缩,以及数据集卡片六字段为何是启动训练前的硬性闸门。读完本文,你将能独立完成一次可被/finetune接受的、可复现可审计的微调数据集构建。

技能定位:从方法选择路由到数据准备

dataset-curation技能的前置条件非常明确——finetuning-method-selection已经把路由决策传到这里,本阶段的任务是准备数据而不是选择方法。该技能在 SKILL.md 中定义的输入输出契约是:

  • 输入:原始示例(demonstrations、preference judgments 或 task prompts)加上来自finetuning-method-selection的路由决策;
  • 输出:一份格式化、打包、验证过的 JSONL 数据集,外加一张填写完整的数据集卡片——这是/finetune在启动训练前检查的 Phase 2 交付物。

在仓库的调用链中,这一点可以精确印证:/finetune命令的 Phase 2: Dataset Preparation 明确要求训练工程师"按dataset-curation的格式表构建数据集,在任何拼接或打包之前应用聊天模板,若启用打包则必须解码并人工检查 5–10 条打包序列,写出包含全部六个必填字段的数据集卡片并完整走查 Phase 2 Exit Checklist"。而 llm-finetuning-training-engineer agent 的能力清单中,数据集准备与验证也正是由dataset-curation负责。这意味着本技能是 Phase 2 的事实标准——方法选型(Phase 1)的产出(training-brief.md)经由它落地为可训练的数据,而后面的lora-qlora-recipespreference-optimizationvision-sft等训练技能则直接消费它产出的数据集。

按目标方法选择数据格式

SKILL.md的 Format Selection 表给出了五种微调方法各自要求的数据形态,这是构建数据集的第一个决策点:

方法数据形态行数要求
SFT(单轮)Instruct(instruction/responseprompt/completion约 1,000+ 起步
SFT(多轮)Conversation / ChatMLmessages列表约 1,000+ 起步
DPO / ORPO偏好对(promptchosenrejected视方法而定,见preference-optimization
KTO无配对(promptcompletionlabel视方法而定,见preference-optimization
GRPO / RLVR仅提示词(prompt+ verifier 元数据)视方法而定,见grpo-rlvr-training

关于行数,文档给出了一个容易被误解的关键澄清:约 1,000+ 行是 SFT 的推荐下限,不是目标。低于这个下限时,少数几条低质量或重复样本就可能主导梯度;高于下限后,质量优先于数量——一份更小但经过验证、去重的集合胜过一份更大但嘈杂的集合。

为便于读者建立直观印象,SKILL.md给出了 ChatML 形态的最小示例:

{"messages": [ {"role": "user", "content": "..."}, {"role": "assistant", "content": "..."} ]}

其余四种格式的具体 JSONL 行示例、ShareGPT 转换说明都集中在 references/formats-and-templates.md,下面按格式逐一展开。

Instruct(SFT 单轮):两种键值对二选一

每行一个示例,两种键对任选其一,但全数据集必须保持一致

{"instruction": "Summarize the following text in one sentence.", "input": "Q3 revenue grew 14% year-over-year, driven primarily by...", "output": "Q3 revenue grew 14% YoY on strong core-segment demand."}
{"prompt": "Summarize the following text in one sentence: Q3 revenue grew 14%...", "completion": "Q3 revenue grew 14% YoY on strong core-segment demand."}

ChatML 多轮对话:messages列表

每行一个messages列表,这是SFTTrainer原生支持模板化与损失掩码的形态。多轮示例中,掩码后只有最后两个assistant轮次的 content token 承载损失:

{"messages": [ {"role": "system", "content": "You are a concise technical assistant."}, {"role": "user", "content": "What does a KV cache do?"}, {"role": "assistant", "content": "It stores attention keys/values from prior tokens so decoding doesn't recompute them each step."}, {"role": "user", "content": "Does it grow with context length?"}, {"role": "assistant", "content": "Yes, linearly — that's why long-context serving is memory-bound on cache size, not compute."} ]}

DPO / ORPO:chosen/rejected 配对

{"prompt": "Explain why the sky is blue.", "chosen": "Sunlight scatters off air molecules; shorter (blue) wavelengths scatter more, so blue dominates what reaches your eyes from all directions.", "rejected": "Because the sky reflects the ocean."}

注意:chosenrejected都是对同一个prompt的完整回答,不是 diff 也不是排序分数。如何从评分轨迹集中挑选rejected(参考文档指出是从奖励分布中取 μ−2σ,而非朴素地取最低分),属于preference-optimization的 Pair Construction 部分。

KTO:无配对二元反馈

{"prompt": "Draft a one-line commit message for a null-check fix.", "completion": "Fix null pointer exception in user lookup", "label": true}
{"prompt": "Draft a one-line commit message for a null-check fix.", "completion": "misc changes", "label": false}

KTO 不要求也不期望行与行之间配对——label: true标记期望行为,label: false标记不期望行为。一个健康的 KTO 数据集必须同时包含两种 label。

GRPO / RLVR:仅提示词

{"prompt": "Solve: 17 * 24 = ?", "answer": "408", "verifier": "exact_match"}

GRPO 不存储回答——训练时从策略中采样补全,并通过命名 verifier(或奖励函数)对照answer打分。奖励函数设计与 GRPO 运行前的人工检查要求在grpo-rlvr-training中展开。

聊天模板与损失掩码:训练前必须避开的静默失败

SKILL.md在本节给出了一个顺序铁律:必须在任何拼接或打包之前应用目标模型的聊天模板,绝不能之后。对打包后的整体文本做模板化会破坏轮次边界,使角色标记相对各示例落到错误位置。

三个核心要点:

  1. 只对 assistant 回答训练损失。在 labels 张量中对 system/user 轮次及模板自身的角色标记掩码(用-100),只有 assistant 轮次的内容 token 贡献损失。
  2. 模板/分词器不匹配是头号静默失败模式。用一套聊天模板训练、却用另一套模板做推理或评估的模型,会"无报错地劣化"。必须验证训练、推理、评估三处使用的是同一个模板字符串
  3. 把数据集保持在messages形态,让训练器去做模板化与掩码(当前 TRL 中是assistant_only_loss=True)。预渲染成扁平文本字段会摧毁掩码所需的轮次边界。

训练前的 sanity-check 代码(解码仅未被掩码的位置,期望只看到 assistant 文本):

keep = batch["labels"][0] != -100 print(tokenizer.decode(batch["input_ids"][0][keep]))

当前 TRL API 下的模板应用代码

references/formats-and-templates.md 给出了符合当前 TRL 约定的完整代码骨架。要点是:保持数据集为messages形态,让SFTTrainer应用模板——不要预渲染对话为扁平文本字段。当前 TRL 会对每个示例(在任何打包拼接之前,正好满足"模板先于拼接"规则)应用分词器的聊天模板,并在assistant_only_loss=True时把损失掩码到 assistant 片段:

from transformers import AutoTokenizer from trl import SFTConfig, SFTTrainer tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL) sft_args = SFTConfig( output_dir="./outputs-sft", max_length=2048, packing=True, # 启用前先看 SKILL.md 的 Packing 一节 assistant_only_loss=True, # 损失仅掩码到 assistant 轮次 ) trainer = SFTTrainer( model=BASE_MODEL, args=sft_args, train_dataset=dataset, # messages 形态——不要预渲染文本字段 processing_class=tokenizer, # 当前 TRL 写法,不是 tokenizer= )

两个值得注意的细节:

  • processing_class(而非旧的tokenizer=)是当前 TRL 的参数名,完整的 Unsloth↔TRL kwargs 映射见 lora-qlora-recipes 的 references/unsloth-trl-mapping.md。
  • assistant_only_loss=True要求分词器的聊天模板标记 assistant 片段({% generation %}关键字)。如果模板缺少该标记,TRL 会主动报错而非静默地对全部内容训练——此时应修复模板,而不是退回扁平文本。

参考文档还明确指出:apply_chat_template(..., tokenize=False)仍然适用于检查模板产出(如打包序列的解码检查),但不应用于构建训练数据集。老式的扁平文本路径(把对话预渲染成text列并设置dataset_text_field="text")虽然仍能运行,但会对整个序列(含 user 轮次与模板标记)计算损失——这正是SKILL.md警告的"静默训练全部内容"故障,仅适用于确实想要全序列损失的场景(如对原始文本做 CPT 式持续预训练),绝不适用于对话式 SFT。

ShareGPT → role/content 转换

老数据集常以 ShareGPT 的conversations形态(from/value键、human/gpt角色)存在,而当前 TRL 期望messagesrole/content形态。转换要在模板化之前完成,而不是过程中

ROLE_MAP = {"human": "user", "gpt": "assistant", "system": "system"} def sharegpt_to_messages(example): messages = [ {"role": ROLE_MAP[turn["from"]], "content": turn["value"]} for turn in example["conversations"] ] return {"messages": messages} dataset = dataset.map(sharegpt_to_messages, remove_columns=["conversations"])

转换完成后(并抽查若干行),才轮到"拼接前应用模板"的规则生效。仍以from/value形态进入打包或模板化的 ShareGPT 数据集,会生成畸形轮次,而模板调用不会报错。

序列打包:省算力但改变批次语义

不做打包时,40–70% 的计算被浪费在 padding 上——变长示例按固定序列长度批处理时,每个示例长度与批次最大值之间的空隙被白白浪费。打包把多个示例拼接进一条序列(直到最大长度),消掉大部分浪费。

但打包带来两个必须正视的后果:

  1. 打包改变批次语义。一条打包序列可能包含多条原始示例,因此"每 epoch 步数"以及任何按示例数量锚定的 LR 调度都会在打包开启后偏移——必须按打包后序列数量重算调度里程碑
  2. 强制要求:在扩展到完整训练前,解码并人工检查 5–10 条打包序列。确认示例边界落在预期位置、每个子示例的模板标记完好、每条打包序列内的损失掩码仍然只对 assistant。这一步不可跳过——打包 bug 是静默的(损失曲线看起来正常),只会在数小时后的评估质量中浮出水面。

检查代码:

for seq in packed_dataset.select(range(10)): print(tokenizer.decode(seq["input_ids"]))

/finetune的 Phase 2 流程中,这一步被明确为"强制而非抽查":训练工程师必须解码并人工检查 5–10 条打包序列,并把解码样本本身附加到验证报告中(见 finetune.md),而不是只写一行 pass/fail。

合成数据规则:防坍缩、生成方法与接受率预算

SKILL.md的合成数据规则是数据规模扩大的防线,四条规则层层递进:

  1. 保持 ≥25% 真实数据作为防坍缩底线。在越来越多模型生成数据上训练、却没有真实数据下限,会在连续几代中驱动可测的质量坍缩——25% 真实数据是守住这条线的最低值。关键定义:通用域 replay 行计入这条底线——这里的"真实"指"不是为这个任务、由这个学生模型生成的",而不是"人类撰写的"。一个全合成构造的数据集可以仅靠 replay 就满足 ≥25% 底线(见 references/synthetic-data.md 的 Replay-Mix Construction 配方);必须在数据集卡片中说明哪些行算作"真实",而不是让底线在结构上无法满足。
  2. Magpie 和 rejection sampling 是主力方法。Magpie 直接从模型自身的模板先验中抽取提示词;rejection sampling 为每个提示词生成多个候选、只保留通过过滤器的那些。两者都优于朴素的一次生成。
  3. 定向、学生感知的生成比静态生成高 1.3–2 倍样本效率——瞄准学生模型的实际失败模式,用更少的过滤样本就能达到质量线。
  4. 过滤后的典型接受率在 10–30%。据此规划生成量——以 10,000 行目标、15% 接受率计算,需要约 65,000+ 条原始生成。

生成方法排序与过滤漏斗

references/synthetic-data.md 给出了从弱到强的生成方法排序(按同预算下的样本效率与下游质量),每一级都包含前一级——rejection-sampling 管线通常在其下用 Magpie 或 persona 条件提示词生成候选:

  1. Self-Instruct——用模型改写和扩展少量种子集引导新提示词。最便宜也最弱:提示词多样性快速触顶,质量紧贴种子集。
  2. Evol-Instruct——跨代迭代改写提示词以增加复杂度(加约束、加深推理、拓宽范围)。难度覆盖优于 Self-Instruct,但仍依赖种子。
  3. Magpie——无需种子提示词,直接从目标模型自身聊天模板先验的 user 轮位置采样提取提示词。完全消除种子集偏差,这是它成为主力而非小众技巧的原因。
  4. Persona-conditioned generation——以采样的人物/角色描述为条件生成提示词,拓宽无条件单策略生成之外的风格与主题覆盖。
  5. Rejection sampling / verifier-filtered——每个提示词生成多个候选补全,只保留过滤器/验证器/裁判接受的那些。它是补全侧的过滤器,本身不是提示词生成方法,可与上面任意方法组合。

定向、学生感知的生成叠加在任意方法之上:把提示词或人物选择引向当前学生模型的实际失败模式(而非均匀采样),这正是SKILL.md所引 1.3–2 倍样本效率的来源。它需要一个学生模型上的评估信号来获知其失败模式;没有该信号,生成就退化为非定向/静态的。

过滤漏斗按成本从低到高排序,廉价阶段应先用它削减体量,昂贵阶段最后才在剩余小集合上运行(见 references/synthetic-data.md):

  1. 精确去重——规范化(合并空白/大小写)后做哈希精确匹配。最廉价,最先跑,在后续阶段前清除生成循环重复。
  2. 语义去重(约 0.92 相似度阈值)——嵌入每个候选,丢弃与已保留行最近邻余弦相似度超过约 0.92 的行。捕获精确去重漏掉的改写级重复。
  3. 长度过滤——丢弃低于最小或高于最大 token 长度的候选:过短回答通常是退化的,过长通常是啰嗦或跑题的。
  4. 语言 ID 过滤——丢弃未通过目标语言检查的候选:生成偶尔会漂移语言,尤其是多语言基座模型在提示词描述不足时。
  5. 基于分数的 top-30% 过滤——对剩余候选打分(奖励模型、启发式或自洽性分数),保留约前 30%——这是最昂贵阶段前的粗略质量切分。
  6. 裁判 ≥ 阈值——把最昂贵的检查放在最后、最小的集合上:LLM 裁判或人类等效质量检查对照固定阈值。此处失败的行无论上游得分如何都丢弃。

SKILL.md10–30% 典型接受率是漏斗端到端的整体产出率(六阶段全通过),不是任何单一阶段的通过率——必须按全漏斗产出率预算原始生成量。

教师→学生蒸馏模式与 Replay-Mix 构造

蒸馏不是特殊格式,而是一条 provenance 标签(references/synthetic-data.md):先生成教师轨迹(TEACHER对目标任务提示词分布采样补全,含推理轨迹)、用过滤漏斗验证(蒸馏集也是合成数据集,仍需 ≥25% 真实数据底线与同样的去重质量阶段)、再用标准 SFT 格式与模板规则训练学生。TEACHER身份与生成配置(采样温度、用于引出轨迹的提示词模板)必须记录在数据集卡片的 provenance 字段——"distilled fromTEACHER"是/finetune与下游审计都期望在那里看到的事实。

Replay-Mix 构造(checkpoint-promotion灾难性遗忘升级阶梯的实现配方)有五个按出现顺序排列的决策:

  1. 通用域来源选择——选真正通用域的来源,两个要避免的失败模式:不要"教给闸门"(replay 源与漂移套件基准同分布会污染漂移分数测量,若必须使用需按checkpoint-promotion的指令复用披露规则披露,且存在更宽的来源时以更宽来源为更可辩护的默认);把来源匹配到遗忘特征(错误分析显示特定能力丢失时,针对该能力的 replay 源恢复更快,但会收窄"通用域"声明——都需在卡片中说明)。
  2. 提示词形态——自然指令、漂移测试台的确切措辞、或裸输入无指令包装,三种形态各有权衡,按遗忘特征而非默认选择,并无论如何都在卡片中披露。
  3. 答案重格式化——replay 参考答案是否向目标任务输出约定重格式化(如把数学数据集的#### N终结符改写为目标任务的提取约定),记录确切变换或"无——保留源格式"。
  4. 验证集处理——验证集只含任务行(eval_loss跨仅 replay 分数不同的运行直接可比,但训练循环对 replay 拟合零可见性)或验证集也含 replay 行(循环内可见 replay 拟合,但eval_loss不再与先前任务-only 验证集运行可对苹果比)。两者皆非普适正确,必须在卡片中说明选择与原因。
  5. 不相交性验证——训练前必须验证 replay 行与漂移套件或 goldens 集不重叠:分裂级分离 + 精确匹配文本过滤(对照eval/goldens.jsonl规范化精确匹配,命中即丢弃),并在卡片中记录发现的重复数(期望 0)。

还有一个硬规则:后续运行改变 replay 分数时,用"交换"而非"添加"——replay 行进入时把目标任务行移出训练集,使总行/步数在旧与新运行之间保持恒定。添加行会同时改变 replay 分数与总优化步数,使后续漂移分数变化无法归因。行数不是 token 数——1:1 交换保持行数恒定,但 replay 行与目标任务行长度常不同,交换仍可能移动总训练 token(进而影响固定批次大小与打包方案下的max_steps);应在新旧运行之间保持总训练 token 或直接保持max_steps恒定,并在卡片中记录每轮的打包 token 数。

全合成数据集与 ≥25% 真实底线

当训练集按构造 100% 合成(全新任务、根本无真实数据池可抽取,而非在真实基座上大量合成增强)时,底线在定义上无法满足,除非混合中的某些东西算作"真实"。解决方案:通用域 replay 行计入 ≥25% 底线——"真实"在此规则中意为"不是为这个特定任务、从这个特定学生模型生成的",从既有通用指令数据集抽取的 replay 行满足该定义。按上述五决策构建 replay 混合后,把 replay 行作为"真实"份额计算卡片所需的合成/真实比例,并在卡片中明确说明这是如何满足比例的,避免后续审计把全合成目标任务数据误读为悄悄跳过了防坍缩守卫。

数据集卡片:六字段闸门,而非事后总结

每份进入训练的数据集都必须有一张卡片——这是/finetune在启动前检查的必需 Phase 2 交付物。卡片不是自由格式文档,必须携带以下六字段:

  • Provenance(来源)——每行来自哪里(真实来源、合成方法或两者),可追溯到trace-to-training-data的输出。
  • Counts(数量)——总行数,以及若划分了 train/eval/held-out 各 split 的行数。
  • Synthetic/real ratio(合成/真实比例)——实测比例,对照上面 ≥25% 真实底线检查。
  • Dedup method(去重方法)——精确匹配、语义(嵌入阈值)或两者;参见references/synthetic-data.md的过滤漏斗。
  • Template used(所用模板)——确切的聊天模板字符串/标识符,保持贯穿推理与评估一致——这正是把一次eval-harness-first运行与 checkpoint 关联起来的纽带。
  • Packing config(打包配置)——是否使用打包、最大序列长度,以及上面 5–10 序列人工检查确实已完成的确认。

缺任一字段的数据集就不算为/finetune就绪——卡片是闸门,不是事后补写的摘要

Phase 2 退出清单:移交给 /finetune 前的六项确认

在移交给/finetune之前,逐项确认:

  1. 格式与目标方法匹配(上文格式表)。
  2. 模板在拼接之前应用。
  3. 损失只掩码到 assistant 轮次。
  4. 5–10 条打包序列已解码并阅读。
  5. 最终混合中 ≥25% 真实数据。
  6. 数据集卡片完整——六字段齐全。

对照/finetune的 Phase 2 闸门描述(finetune.md):数据集卡片与验证报告(若用了打包须含解码样本)必须按 Phase 2 Exit Checklist 完整,Phase 3 才能开始;缺失即停在该闸门,而不是跳过或即兴推进。

技能全景与参考索引

dataset-curation处于微调技能网的枢纽位置,周边协作关系(见 SKILL.md 末尾的 References 与 Related skills)如下:

  • 上游finetuning-method-selection把路由决策送进本技能(方法选择与数据形态判断);trace-to-training-data是分级轨迹数据集(graded-trajectory datasets)的 provenance 来源。
  • 下游消费方lora-qlora-recipesvision-sftpreference-optimization消费本技能产出的数据集;eval-harness-first对最终 checkpoint 打分,其运行通过数据集卡片的 Template used 字段与 checkpoint 关联。
  • 参考文档
    • references/formats-and-templates.md——每种格式的 JSONL 示例、当前 TRL 掩码代码、ShareGPT 转换说明;
    • references/synthetic-data.md——生成方法排序、过滤漏斗、replay-mix 构造、教师→学生蒸馏模式。

一个贯穿全文的提醒:SKILL.md与参考文档中的所有代码示例都使用BASE_MODELTEACHERSTUDENT占位符,仓库不推荐具体基座模型——实际 checkpoint 选择参见finetuning-method-selectionreferences/model-catalog.md。从格式选择、模板先行、打包检查、合成数据防坍缩到六字段卡片,每一步都有明确的验证动作与失败模式对照,这正是这套数据集整理方法论能在真实微调运行中落地、而不是停留在文档层面的原因。

【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询