Home / Guides / Building a Fine-Tuning Dataset That Actually Teaches Something
By Peter Peeters Published 29 Oct 2026 Verified Oct 2026 3 min read

Building a Fine-Tuning Dataset That Actually Teaches Something

JSONL formats by method, how many examples you really need, deduplication, synthetic data and the split that makes your evaluation mean something.

Most fine-tuning projects that disappoint do not have a training problem. They have a dataset problem: examples that contradict each other, a format the model was never shown at inference time, or a test set drawn from the same distribution so the metrics look excellent and the product does not improve.

This is the part worth slowing down for.

Format follows the objective

Instruction / chat tuning. One example is one conversation. Use the model’s own chat template — not a generic one.

{"messages": [
  {"role": "system", "content": "You extract invoice fields as JSON."},
  {"role": "user", "content": "Invoice 4471 from Acme, due 2026-11-30, total 1284.50 EUR"},
  {"role": "assistant", "content": "{\"id\": \"4471\", \"vendor\": \"Acme\", \"due\": \"2026-11-30\", \"total\": 1284.50, \"currency\": \"EUR\"}"}
]}

Completion only. If you are training raw continuation rather than chat, {"prompt": "...", "completion": "..."} with loss masked to the completion. Training on the prompt teaches the model to reproduce inputs, which is rarely what you want.

Preference pairs (DPO). {"prompt": "...", "chosen": "...", "rejected": "..."} — and the rejected answer should be a plausible wrong answer, not garbage. A model trained against obviously bad outputs learns almost nothing.

The single most common format bug: training with one template and inferring with another. A Llama model trained on Mistral’s template learns the wrong control tokens and produces broken output that looks like a capability problem.

How many examples

ExamplesWhat to expect
< 100Few-shot prompting is probably better. Fine-tuning will overfit
300–1,000Enough for a narrow format or extraction task
1,000–5,000The useful band for most behaviour changes
5,000–20,000Diminishing returns unless the task is genuinely broad
> 20,000Ask whether a better base model or better retrieval solves it cheaper

These are honest ranges, not rules. A hundred perfectly consistent examples beat a thousand sloppy ones, and a task with high output diversity needs more coverage than one with a fixed schema.

Quality checks before you train

Contradictions. Two examples with the same input and different correct outputs teach the model to hedge. Deduplicate on normalised input, then check that surviving duplicates agree.

Length distribution. If your target outputs are always 40 tokens, the model learns to stop at 40 tokens. That is fine if true, disastrous if your real traffic has long outputs.

Template leakage. Grep for the system prompt, the dataset’s own field names, or annotation artefacts in the assistant turns. Models happily learn to emit them.

Truncation. Count how many examples exceed your max sequence length. Silent truncation cuts the answer off mid-sentence and trains the model to stop early.

The split that makes evaluation mean something

A random 90/10 split is the default and it is usually wrong, because the interesting failure is generalisation to a different slice of the task.

Split by the thing you care about:

  • If you have five output categories, stratify so each appears in the test set with enough examples to measure.
  • If your data comes from multiple sources, hold out an entire source. This is the honest test of whether the model learned the task or the source’s quirks.
  • Keep a small “hard” set of cases the base model currently fails. That is where improvement is visible.

A test set of 200 examples gives you a metric with roughly ±5% noise at 90% accuracy. Reporting a 2-point improvement on 200 examples is reporting noise.

Synthetic data

Generating examples with a stronger model is legitimate and now standard. Three rules keep it from poisoning the dataset:

  1. Verify the outputs — programmatically where possible (does the JSON parse? does the number match?), by sampling where not.
  2. Mix, do not replace. Synthetic-only datasets inherit the generator’s stylistic tics. A 50/50 or 70/30 mix with real data behaves better.
  3. Diversify the prompts, not just the answers. Twenty thousand variations of one prompt template teaches one template.

What to do this week

Pull 300 real examples from logs or tickets. Put them in the right template. Deduplicate. Hold out a stratified 15%. Run a QLoRA fine-tune on the rest — a few dollars on a rented card. Compare against the base model with a good prompt on the held-out set.

That single loop tells you more than another month of planning, and it costs less than the coffee budget for the meeting where you plan it. The config generator will size the run to your GPU; the fine-tuning guide covers the rest.