Contents
For a week the team spins LoRA on a local checkpoint. The “dataset” is six hundred chat exports: mismatched system prompts, answers with no shared template, not a single explicit refusal, no “obsolete policy” slice. On a holdout carved from the same chat, the metric rises. In the pilot, legal catches a confident answer from a revoked edition; an operator hears a tone that must never ship.
The failure is almost never the optimizer. It is like teaching handwriting from a pile of random scraps instead of a copybook: somewhere a model line “write it like this,” somewhere another person’s hand, and the exam later is graded from the same notebook. The supervised fine-tuning (SFT) corpus was assembled as a folder of examples, not as a book of exercises with a contract, coverage, and a gate before the lesson.
Below is how to design that corpus: what belongs in an instruction→answer pair, where examples come from, how not to mix homework with the exam, and when synthetic data helps or hurts. It continues the dataset engineering overview (gauge and inspection there) and complements when fine-tuning is actually needed, without duplicating the Qwen classification case or how LLMs are trained.
Key takeaways
SFT teaches behavior on input→desired-output pairs. It is not raw-web pretraining and not “answer A beats B.” Mixing families yields a pretty loss and odd production behavior.
Pair contract first, volume second. Answer format, language, when to refuse, when to escalate — before labeling and before synthesis.
Coverage beats size. A thousand identical polite shorts lose to three hundred stratified exercises with refusals and real user wording.
Synthetic data is a photocopy of a draft, not the teacher’s signature. Domain facts and tone still need a human with a rubric.
Before training — a static gate: schema, dedup, no overlap with eval, refusal share, chat template matching production.
Eval does not live in the same notebook as the exercises. Otherwise you tune answers to the report. Eval framing: evaluate LLMs before production.
This is a copybook, not four foreign notebooks
Projects often hold four data families. For SFT, do not confuse what teaches with what measures — or you remix the gauge from the series overview with the batch again.
| Family | Teaches / measures | Typical unit | Mix-up cost |
|---|---|---|---|
| SFT corpus | How to answer (format, tone, pattern) | instruction → answer | Train on eval gold without audit |
| Preference data | Which of two plausible answers | chosen / rejected | Style without facts |
| Golden set | Measure behavior | input + acceptance | Prompt overfitting to visible cases |
| Mining buffer | Raw production failures | unlabeled traces | Scoring unlabeled cases |
SFT is the copybook: given this input, we want one output (or a refusal). Preferences compare two essays. The CI golden is the exam key. The buffer is desk drafts still unscored.
The corpus may be wider and noisier than golden: the goal is to learn a pattern, not lock a regression gate. If a record cannot be stated as “on this input we want that output,” it is not yet an SFT exercise.
Rules for the line before the stack of pages
Before labeling, put the pair contract in one place (meta.yaml or a short RFC) — like the model letter at the top of a copybook:
| Element | Question | Policy-assistant example |
|---|---|---|
| Input | What does the model see? | User question; optional retrieved chunks |
| Output | Format? | Short answer + clause cite; or JSON |
| Refusal | When not to answer? | No source; outside ACL; obsolete version |
| Escalation | When to a human? | High risk; two documents conflict |
| Language | ru / en / mixed? | Answer in the question’s language |
| Tone | Formal / operator? | No slang; no confidence without a source |
| Source of truth | What is fact? | Current DMS edition — not chat |
Without that, two experts write two “correct” answers of different length, and the model learns the average of noise. If search plus a hard template already closes the contract, check when fine-tuning is justified first. SFT earns its keep when stable behavior (format, refusal, tone, jargon) will not hold on prompt and retrieval alone.
One cell, one set of fields
A minimal instruction-tuning record is not a wall of text — it is fields that survive checkpoint and library changes:
{
"id": "sft-reg-0142",
"messages": [
{"role": "system", "content": "…one system-prompt version…"},
{"role": "user", "content": "May PPE be stored without an issue log?"},
{"role": "assistant", "content": "Per policy v3.2 §4.1 — no. …"}
],
"meta": {
"domain": "ot_pb",
"intent": "policy_qa",
"doc_version": "3.2",
"language": "en",
"refusal": false,
"source": "editor",
"difficulty": "medium"
}
}
Four rules save weeks:
- One system-prompt version per corpus manifest (or an explicit
system_version). Five different systems in one JSONL teach policy conflict. - Stable
idacross corpus versions so an answer edit is not a silent new case. - Slice metadata: domain, intent, document version, language, refusal, source. Without them you cannot say which slice failed.
- Chat template matches production. If production has no
system, do not train on a long system that will never be sent.
Classification may use a simpler input / label shape; the principle stays: schema + metadata + manifest version.
Where the lines in the book come from
Four sources, each with its risk.
| Source | Upside | Risk | How to use |
|---|---|---|---|
| Golden editors | Domain facts and tone | Costly, slow | Coverage core and all high-risk refusals |
| Production logs | Real wording | PII, ACL, noise | After filter and review; never treat model output as truth |
| Synthetic (LLM) | Volume and variants | Hallucinations, bland style | Draft → mandatory review; quota “synthetic ≤ N%” |
| Transcription / rewrite | Org tone | Narrow coverage | Good for format; bad as the only intent source |
A mix that works in pilots: 30–40% core written or approved by experts; periphery grown with synthetic paraphrases by intent template; tail from the failure buffer after review. Photocopies without quota and rubric fill the book with confident average — the model turns polite and empty.
“Model generated a pair” ≠ “pair verified.” In high-cost domains, final status needs a human. Synthetic data does not sign the manifest.
Not line count — a map of exercises
“How many examples?” without a coverage map is empty. Working ranges (not dogma):
| Task type | Working start | Look before volume |
|---|---|---|
| Classification / routing | 1k–20k labels | Class balance, confusable classes |
| Instruction / dialogue SFT | 500–5k pairs | Intents, refusals, length, language |
| Structured output (JSON) | 300–3k | Schema adherence, rare fields |
| Domain code / SQL | 500–8k | Dialects, DB schemas, dangerous queries |
“More” helps only when intent and condition coverage grow — not paraphrases of one line. Map intents × conditions (source present / absent; current / obsolete version; one doc / conflict). An empty cell beats a hundred similar “success” answers.
If one editor wrote every user line in literary prose, the model fails on conversational production. Mix fragments, typos (if they exist in traffic), and formal mail — in traffic shares, not annotator taste.
Narrow classification on a small model sometimes needs only hundreds of examples — see the Qwen 0.6B case. Open policy dialogue without refusals will not be saved by ten thousand pairs.
Exercises where the right answer is “do not write”
A corpus without refusals teaches the model to always answer. In an enterprise assistant that is a straight road to invented clauses.
Minimum “negative” skills in the copybook:
- Refuse without a source — “not in the provided chunks; I will not invent.”
- Refuse on ACL — no rights; do not paraphrase from “general knowledge.”
- Refuse on obsolete version — document withdrawn.
- Escalate — two norms conflict; hand off by template.
- Out-of-scope refuse — weather, jokes, if the product forbids them.
Such cases often take 15–30% at pilot start — otherwise the positive class crushes behavior. Presence of every refusal type from the contract matters more than the exact percent.
“Similar but wrong” answers usually do not belong as assistant — that is preference / DPO territory. For SFT, prefer a strictly correct output or a record whose correct output is a refusal. Choosing between two phrasings needs a separate family, or one notebook pulls the model both ways.
Do not open the lesson until the notebook passes inspection
Training does not start from “a folder on disk.” Gate first — like checking the copybook before the exam:
flowchart TB
sources[Sources: editor / prod / synthetic] --> normalize[Normalize schema and template]
normalize --> lint[Static checks]
lint --> split[Train / dev / holdout]
split --> trainJob[SFT job]
split --> evalGate[Eval on golden]
evalGate --> release{Regression gate}
release -->|pass| ship[Ship adapter]
release -->|fail| buffer[Corpus fix buffer]
buffer --> sources
What catches pain before GPU:
- schema: required fields, types, allowed
role; - one system per manifest (or explicit versions);
- dedup on text and near-duplicates;
- zero overlap with eval golden;
- refusal share in a corridor;
- length, empty
content, giant log pastes; - PII and secrets by policy;
- language label matches audited text.
The gate’s output is a manifest: version, hash, slices, approver, rubric link. Without it, “model A vs B” also compares different notebooks.
Homework must not match the exam
A common trap: take the last 10% of the file as test. If the file is sorted by time or author, the test does not look like production. Worse: edit train answers while peeking at the same phrasings that go into the customer report.
Practical rules:
- Holdout — tens to hundreds of cases closed during prompt and corpus iteration. “Ready for pilot” reports only from holdout or a separate golden.
- Visible dev — for debugging; do not sell its metrics to the business as final.
- Eval golden versioned apart from the train manifest. Cross-links are fine (“train v0.4 scored on gold v0.3”); embedding golden inside train JSONL “for convenience” is not.
- Paraphrase is leakage too. “May PPE be stored without an issue log?” and “Is an issue log mandatory for PPE?” must not split across train and holdout without a policy. Search near-duplicates.
RAG eval goldens are built differently — golden sets for RAG. RAG checks retrieval and grounding; SFT teaches phrasing and answer policy. Shared questions across loops are leakage candidates.
Enterprise example: a policy assistant
An internal assistant answers on current policies. Retrieval already returns chunks; answers still drift in format and invent clauses missing from the chunks.
Contract: answer only from provided chunks; require doc_id and version; otherwise refuse; formal tone.
Corpus v0.2 (example mix):
| Slice | Share | Who approves |
|---|---|---|
| Success with citation | 55% | Editor + spot audit |
| Refuse: not in chunks | 15% | Editor |
| Refuse: obsolete document | 10% | Editor |
| Two norms conflict → escalate | 10% | Counsel / compliance |
| Out of product scope | 5% | Editor |
| Short conversational ask | 5% | Logs after filter |
Synthetic only for paraphrases of success and “not in chunks,” 25% quota, mandatory review. After the pilot, “confident answer on empty retrieval” failures became refusals in v0.3 — not new successful fantasies.
Adapter release metric: not average “looks like golden,” but contract-violation rate on holdout below a threshold.
Industrial example: operator instructions
A shop-floor kiosk or tablet: the model helps find the next instruction step and allowed tolerances. Errors cost more than an office chat.
Copybook differences: short lines, speech-recognition noise, mixed language (local + equipment codes); hard refuse on “how do I bypass the interlock” and off-clearance asks; metadata — line, machine, tech-card version, clearance level.
Here 800–1,500 approved pairs with full refusal and line coverage beat five thousand synthetic polite dialogues. Same logic as the handwritten-digit OCR breakdown: resemblance to operations first, scale second.
Nearby reading
A narrow “classify → label” experiment shows a small model with clean labels can beat a large dirty checkpoint. Do not copy that win onto open dialogue one-to-one: the unit is answer policy, and “almost right” text costs more.
| Question | Material |
|---|---|
| Is fine-tuning needed? | When fine-tuning is needed |
| How data families work | Dataset engineering |
| How to measure before prod | Evaluate LLMs before production |
| RAG-only golden | RAG golden dataset |
| Classification case | Fine-tuning Qwen 0.6B |
This piece answers: how to design the corpus once “we fine-tune” is decided.
Where teams ruin the copybook
Chat dump without a schema. Many systems, no id — zero reproducibility.
Zero refusals. The model learns to always be helpful; production gets confident hallucinations.
90% synthetic without review. Pretty loss curves, empty pilot.
Train on the eval golden. Metrics cheer until the first unfamiliar ask.
One author for every user line. Gap to employee or operator language.
SFT and preferences in one file. The model cannot tell “one correct answer” from “what people like more.”
No manifest. You cannot roll back the corpus or explain a regression.
Ignoring ACL and PII in logs. Legal and security debt in the same JSONL.
What to try today
- Write a one-page pair contract: input, output, refuse, escalate, tone.
- Draft a coverage map of intents × conditions and mark empty cells — that is the labeling queue, not “another LoRA.”
- Add at least five refusals of each type from the contract.
- Run the static gate before the first training job.
- Name a manifest owner — without whose sign-off the file never enters training.
Finish the copybook before spinning the adapter again. Otherwise the next metric bump is just copying from the same notebook.
FAQ
How many SFT examples do we need?
Enough to close the coverage map and refusal corridor — not “whatever the blog said.” Narrow classification often needs hundreds to a couple thousand clean labels; policy dialogue usually needs hundreds to a few thousand stratified pairs. Seven hundred approved beat seven thousand synthetic without an editor.
Can the whole corpus be synthetic?
As a draft and for paraphrases — yes, with quota and review. As the only source of truth in a high-cost domain — no. Synthetic accelerates; an expert signs.
Does every record need a system prompt?
It needs consistency with production. If production system is fixed, keep one version per manifest. Five conflicting systems teach the model to ignore policy.
How does an SFT corpus differ from a CI golden?
A CI golden is small, stable, hard-rubric — you measure with it. An SFT corpus teaches and may be wider. Scoring a release only on a random train subset is a methodology error.
When move from SFT to preference data?
When format and facts mostly hold, but you must reliably choose between two acceptable answers. That is a separate family; do not mix chosen/rejected with a single assistant without a policy.
How do we keep PII from logs out of the corpus?
Filter before labeling, mask by policy, ban raw traces in git without a scanner, spot-audit. An unreviewed production row is not “fast SFT” — it is training leakage.
Next in the series
- Dataset engineering overview — families and lifecycle.
- JSONL, shards, and the path to the GPU — physical layout.
- Golden editors — rubric and adjudication (
golden-editors-annotation-workflow-2026). - Train / eval / holdout and leakage (
dataset-splits-leakage-2026). - Preference data: DPO and pairs (
preference-dataset-rlhf-2026). - Synthetic and hybrid pipelines (
synthetic-human-dataset-pipeline-2026).



Comments