Best for
- Use when converting raw data into training format, applying chat templates, configuring sequence packing, generating synthetic training data, or writing a dataset card before a run.
wshobson/agents/plugins/llm-finetuning/skills/dataset-curation/SKILL.md
Prepare, format, and validate datasets for supervised fine-tuning and preference training. Use when converting raw data into training format, applying chat templates, configuring sequence packing, generating synthetic training data, or writing a dataset card before a run.
Decision brief
This skill assumes finetuning-method-selection already routed here — the next step is preparing data, not choosing a method. What follows: format selection by target method, the template/packing mechanics behind the most common silent training failures, rules for mixing in synth…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/wshobson/agents --skill "plugins/llm-finetuning/skills/dataset-curation"Inspect the Agent Skill "dataset-curation" from https://github.com/wshobson/agents/blob/c4b82b0ad771190355eb8e204b1329732a18449a/plugins/llm-finetuning/skills/dataset-curation/SKILL.md at commit c4b82b0ad771190355eb8e204b1329732a18449a. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Before handing off to /finetune, confirm:
1,000+ rows is the recommended floor for SFT,
Apply the target model's chat template before any concatenation or packing, never after — packing raw text and templating the packed blob afterward corrupts turn boundaries, landing role markers in the wrong place relative to each example.
Without packing, 40–70% of compute is spent on padding — variable-length examples batched at a fixed sequence length waste the gap between each example's length and the batch's max. Packing concatenates multiple examples into one sequence up to the max length, cutting most of th…
Keep ≥25% real data as a collapse guard.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 72/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 38,313 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
This skill assumes finetuning-method-selection
already routed here — the next step is preparing
data, not choosing a method. What follows: format
selection by target method, the template/packing
mechanics behind the most common silent training
failures, rules for mixing in synthetic data
without collapse, and the dataset card that closes
out Phase 2 before a run starts.
Input: raw examples (demonstrations, preference
judgments, or task prompts) plus a routing decision
from finetuning-method-selection.
Output format: a formatted, packed, validated
JSONL dataset plus a completed dataset card — the
Phase 2 artifact /finetune checks before launching
training.
| Method | Shape | Rows |
|---|---|---|
| SFT, single-turn | Instruct (instruction/response or prompt/completion) | ~1,000+ floor |
| SFT, multi-turn | Conversation / ChatML messages list | ~1,000+ floor |
| DPO / ORPO | Preference pair (prompt, chosen, rejected) | Method-dependent, see preference-optimization |
| KTO | Unpaired (prompt, completion, label) | Method-dependent, see preference-optimization |
| GRPO / RLVR | Prompt-only (prompt + verifier metadata) | Method-dependent, see grpo-rlvr-training |
~1,000+ rows is the recommended floor for SFT, not a target. Below it, a handful of low-quality or duplicate examples can dominate the gradient; above it, quality over quantity — a smaller verified, deduplicated set beats a larger noisy one.
The ChatML shape, for orientation; the other four
formats plus a ShareGPT conversion note live in
references/formats-and-templates.md:
{"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]}
Apply the target model's chat template before any concatenation or packing, never after — packing raw text and templating the packed blob afterward corrupts turn boundaries, landing role markers in the wrong place relative to each example.
Train on assistant responses only. Mask the
loss (-100 in the labels tensor) over system/user
turns and the template's own role markers — only
assistant-turn content tokens contribute to loss.
Template/tokenizer mismatches are a top silent failure mode. A model trained against one chat template but served or evaluated with a different one degrades without erroring. Verify the same template string used in training is applied at inference and eval time.
Keep the dataset in messages shape and let
the trainer template and mask it
(assistant_only_loss=True in current TRL) —
pre-rendering to a flat text field destroys the
turn boundaries masking needs. Full code sketch:
references/formats-and-templates.md. Sanity-check
before training — decode only unmasked positions;
expect only assistant text:
keep = batch["labels"][0] != -100
print(tokenizer.decode(batch["input_ids"][0][keep]))
Without packing, 40–70% of compute is spent on padding — variable-length examples batched at a fixed sequence length waste the gap between each example's length and the batch's max. Packing concatenates multiple examples into one sequence up to the max length, cutting most of that waste.
Packing changes batch semantics. A packed sequence can contain several original examples, so "steps per epoch" and any LR schedule keyed to example count shift once packing is on — recompute schedule milestones against packed-sequence count.
MANDATORY: decode and manually inspect 5–10 packed sequences before scaling to a full run. Confirm example boundaries land where expected, template markers are intact per sub-example, and the loss mask is still assistant-only within each packed sequence. Not optional — packing bugs are silent (the loss curve looks normal) and only surface in eval quality, hours later:
for seq in packed_dataset.select(range(10)):
print(tokenizer.decode(seq["input_ids"]))
references/synthetic-data.md's
Replay-Mix Construction recipe);
state which rows count as "real"
in the dataset card rather than
leaving the floor structurally
unmeetable.references/synthetic-data.md.Every dataset that reaches training gets a card —
the required Phase 2 artifact /finetune checks
before launching. The card is not free-form
documentation; it MUST carry these fields:
trace-to-training-data output.references/synthetic-data.md.eval-harness-first run back to the checkpoint.A dataset missing any of these six fields isn't
ready for /finetune — the card is a gate, not a
summary written after the fact.
Before handing off to /finetune, confirm:
references/formats-and-templates.md — JSONL
examples per format, current-TRL masking code,
and the ShareGPT conversion note.references/synthetic-data.md — generation-method
ranking, filter funnel, replay-mix construction,
and teacher→student distillation pattern.Related skills: finetuning-method-selection routes
here; lora-qlora-recipes, vision-sft, and
preference-optimization consume the datasets this
skill produces; trace-to-training-data is the
provenance source for graded-trajectory datasets;
eval-harness-first grades the resulting checkpoint.