Synthetic Data and Distillation
Distillation copies a frozen teacher's behavior into a smaller student — either by matching its output distribution (logit KD) or by training on the strings it samples (synthetic-data SFT).
A frontier model costs a ridiculous amount of money to train. Tens of millions of dollars in GPUs, months of engineering, terabytes of carefully filtered text. Once it's finished, you have this giant artifact that can do extraordinary things, and also a very natural question: can I get most of that behavior out of a model 10× smaller?
That question has two families of answers, and they get mixed up all the time because the pipelines look similar from the outside. One is distillation, which means training a small model to match a big model's output distribution. The other is synthetic data, which means using a strong model to manufacture training examples for a weaker one. They share a lot of machinery and often get combined, but the mechanism by which the student gets better is different in each case. This post separates them, builds the intuition for each, and then looks at what happens when the thing eating its own outputs is a whole ecosystem.
Prerequisites
This post assumes you've read:
- Pretraining the Base Model for where the "base model" comes from.
- Supervised Fine-Tuning for what SFT is and why the (prompt, response) format matters.
- Cross-Entropy and Loss for what KL divergence is doing underneath.
The problem
Say you have a 70B-parameter model that behaves the way you want — follows instructions, writes clean code, gives reasonable answers about biology. You'd love to deploy it everywhere, but inference on a 70B model is expensive: big GPU, lots of memory bandwidth, slow tokens per second. Every prompt you serve is a tax on your infrastructure. Meanwhile a 7B-parameter model runs on a single consumer GPU, generates tokens fast, and if it could imitate the 70B's behavior closely enough, it would be good enough for most of what you care about.
The question is how to get the 7B to act like the 70B. You can't just copy weights, because the architectures have different shapes. Training the 7B from scratch on the same data won't work either; that's the whole reason the 70B is better in the first place. What you need is a way to let the 70B teach the 7B directly.
Here's the setup:
- The big model. Call it the teacher. It's frozen. Nobody's updating its weights.
- The small model. Call it the student. It has its own weights, its own loss, and we're going to train it.
- Some way of copying "what the teacher knows" into the student's weights.
The rest of the post is about the different ways people have tried to close that loop.
Soft labels: what the teacher actually knows
The first insight, the one that made Hinton et al.'s 2015 paper a classic, is that a trained model's output distribution contains way more information than its top prediction alone. If you ask the teacher "what comes after the cat sat on the?" and it says mat with probability 0.42, rug at 0.24, floor at 0.14, couch at 0.09, and a long tail after that, those probabilities are a quiet confession about what the model has learned. The teacher thinks rug is almost as likely as mat, but much more likely than couch. That relative ordering encodes the teacher's sense of what makes sense in context.
Hinton called this "dark knowledge." The one-hot "correct" label says mat and nothing else. The full distribution says mat, and here's the entire shadow of things that could have been said, and here's how they rank. If you train the student to match the full distribution, you transmit all of that, not just the argmax.
So.
The distillation loss works on that right-hand distribution. Given the teacher's probabilities over the vocabulary and the student's , you minimize the KL divergence between them:
The is a temperature applied to the softmax before you compute the KL. Higher flattens both distributions, which drags the student's attention away from the single mode and onto the relative ordering of secondary options. The out front is the rescaling factor Hinton derives so that the gradient magnitudes don't fall off as you warm up.
In practice you usually train the student on a weighted combination of the distillation loss and the normal cross-entropy on the ground-truth label, if you have one. Something like:
But the critical piece is the KD term. That's what makes distillation different from just copying the teacher's top pick.
Two flavors of "use the teacher"
Once you understand soft labels, there are two recognizable paths people actually take. The vocabulary gets loose here, so let me pin it down.
Logit distillation. You run the teacher and the student on the same input, grab both of their output distributions, and optimize the KL between them. This is the closest thing to "classical" knowledge distillation. Gemma 2 notably did a version of this for its 2B and 9B models at pretraining scale. It requires the teacher's logits, which means you need access to the model — it's easiest inside one lab, harder to do against a closed API.
Synthetic-data SFT. You sample text from the teacher, keep the tokens as ground-truth targets, and fine-tune the student with ordinary cross-entropy on those tokens. No logits needed, just the sampled strings. Alpaca, Self-Instruct, Orca, and most of what people informally call "distilling GPT-4" are this flavor. The student isn't matching a distribution; it's matching the teacher's samples and hoping that the teacher's distribution shows up in the aggregate.
Both of these get called "distillation" in the wild. Both work. They have different properties: logit distillation is a stronger signal per example, while synthetic-data SFT is easier to set up and composes naturally with RLHF or DPO downstream. Most of what you read about in production uses some mix.
The Alpaca-style pipeline
The synthetic-data-as-SFT route is worth walking through because the scale involved is genuinely surprising. In 2023, the Stanford Alpaca team started with 175 human-written seed tasks, asked text-davinci-003 to generate variations, filtered the results, and ended up with 52,000 instruction-response pairs. They fine-tuned a Llama 7B on that set for under $600 of compute. The resulting model was, for casual instruction-following, within spitting distance of text-davinci-003's actual behavior. A lot of the early open-weights instruct models are descendants of that exact recipe.
The pipeline is roughly:
- Start with a small, hand-written set of diverse tasks (the "seed" pool).
- Prompt the teacher to produce new tasks in the same style, either from the seeds directly or via templated few-shot prompts.
- For each generated instruction, prompt the teacher again to produce a response.
- Filter. Deduplication (e.g., ROUGE-L similarity cutoff), length constraints, cheap safety filters, sometimes LLM-as-judge scoring.
- Feed the surviving rows into an SFT loop against the student.
The filter stage tends to get glossed over. In the Self-Instruct paper, less than half of the raw generations survive filtering. The pipeline's real output is not "many tokens from GPT-4"; it's "many tokens from GPT-4 that look like the kind of task you wanted to teach the student." The quality bar is what moves the needle, not the raw volume.
Now.
Why does it work at all?
Here's the intuition I carry around. The student is a function with billions of parameters and a specific inductive bias (the transformer architecture, pretrained on text). The teacher is a much bigger function with the same bias, trained longer. The student has enough capacity to represent most of what the teacher knows about any narrow behavior like writing polite refusals, formatting markdown lists, or answering MMLU-style multiple choice. But the student's base model doesn't know which behaviors to put on top.
Distillation, in either flavor, shows the student the teacher's behavior on a huge number of inputs. The student's weights adjust to imitate that behavior. Where the teacher is strong, the student inherits the strength. Where the teacher is weak or just wrong, the student inherits the weakness. This is a pointed copy of the parts of the teacher's behavior you expose the student to. It is not a general uplift.
This has a useful consequence. The student can exceed the teacher on narrow axes, but very rarely on everything. Orca's 13B model beat GPT-3.5 on several reasoning benchmarks because the Orca team specifically distilled GPT-4's reasoning traces, not just its final answers. Phi-3 mini does unreasonably well on MMLU because the Phi team specifically curated synthetic "textbook-like" content. Neither of those small models is uniformly better than a frontier model. They're better on the slice they were distilled toward.
And the other side of that coin: the student can inherit the teacher's blind spots, too. If the teacher has a bad habit (confabulating citations, refusing benign prompts, preferring a certain rhetorical style), the student will come out with the same habit baked in. There's no filter for "only learn the good parts" short of the explicit one you build during data curation.
Model collapse: the thing nobody wants
There's a failure mode that took a few years to articulate cleanly. If you train a model on synthetic data sampled from another model, and then later train a third model on data sampled from the second, and so on, the distribution of the outputs gets narrower and narrower. The tails fall off. Rare modes disappear. Eventually the whole thing collapses onto a handful of bland generations.
The Shumailov et al. "Curse of Recursion" paper made this formal. Their argument is basically: sampling from a distribution is a lossy estimate of that distribution, and if you train the next generation on a finite sample, you underweight everything that wasn't well represented. Run this loop a few times and the dropout compounds. The model's output support shrinks until it barely covers the real support at all.
Why should you care? Two reasons.
First, iterative self-distillation as a training recipe is tempting and dangerous. If you let a team keep training smaller and smaller checkpoints on the previous one's outputs without injecting fresh real data, you walk right into collapse. The pattern is: model v1 is good, v2 is almost as good but slightly bland, v3 is noticeably narrower, v4 is unusable, and no single step in that chain looks alarming. Budget a minimum fraction of real, non-synthetic data at every generation and resist the efficiency argument that "we can just keep looping the teacher."
Second, even if you personally never do that loop, the open web is doing it for you. A significant fraction of text on the internet after 2023 is model-generated. If you scrape aggressively and train a new base model on post-2023 crawl data, you are implicitly doing one round of "train on the previous generation's outputs." The collapse math says this gets worse over time unless the field develops durable ways to mark and filter synthetic text. That's an open problem as of early 2026.
Worked example
Let me put some numbers on it. Say you want to distill a 70B-parameter chat model into a 7B base model, the pattern people have actually done for Llama, Mistral, Qwen, and so on.
You have a few knobs:
- Data budget. 50k rows is the Alpaca scale and it produces a coherent instruction-follower. 500k to 5M rows is the Orca / Nectar scale and it produces noticeably better reasoning. Beyond that you run into diminishing returns and filtering becomes the bottleneck.
- Teacher diversity. One teacher gives you a consistent style but also consistent blind spots. Several teachers combined (GPT-4, Claude, Gemini) widen the coverage at the cost of some stylistic incoherence.
- KD weight . If you have the teacher's logits, you can blend real-label cross-entropy with KL against the teacher at . No single number wins across tasks; you tune this per domain.
- Temperature . Standard Hinton starts at 2–4 and anneals down. Above 6 you dilute the signal so much it hurts; below 1.5 you lose most of the dark knowledge.
Compared to direct SFT with human-written data, the synthetic route gets you to a "usable instruction-follower" about 10× cheaper, because the teacher's time is free once you pay for the API tokens. Compared to training the 7B from scratch for equivalent behavior, it's something like 1000× cheaper, because you're not burning pretraining FLOPs.
The catch, again: this buys you imitation of the teacher on the slice the data covers. It does not raise the student's ceiling above the teacher's. Distillation is a fast-follow lever, not a frontier lever. If you want to push the frontier with a small model, you need something else.
Implementation sketch
Here's the minimum viable version of both flavors. One PyTorch loss function for logit distillation, one tiny wrapper for generating synthetic data. Real pipelines add batching, caching, retry logic, safety filters, and a bunch of other scaffolding, but the core loop is this small.
import torch
import torch.nn.functional as F
# --- Logit distillation loss (Hinton et al.) ---
def kd_loss(
student_logits: torch.Tensor, # (batch, seq, vocab)
teacher_logits: torch.Tensor, # (batch, seq, vocab)
labels: torch.Tensor, # (batch, seq) — ground-truth ids
tau: float = 2.0,
alpha: float = 0.5,
ignore_index: int = -100,
) -> torch.Tensor:
"""
Combined cross-entropy (hard label) + KD (soft label) loss.
When labels == ignore_index at a position, skip that position in the
hard loss. The KD term uses every valid position.
"""
# Hard-label CE on real tokens
ce = F.cross_entropy(
student_logits.reshape(-1, student_logits.size(-1)),
labels.reshape(-1),
ignore_index=ignore_index,
)
# Soft-label KL at temperature tau
s = F.log_softmax(student_logits / tau, dim=-1)
t = F.softmax(teacher_logits / tau, dim=-1)
kd = F.kl_div(s, t, reduction="batchmean") * (tau ** 2)
return alpha * ce + (1.0 - alpha) * kd
# --- Synthetic data generation (Alpaca / Self-Instruct flavor) ---
def generate_synthetic_row(teacher, seed_tasks: list[str]) -> dict | None:
"""
One round of "ask the teacher for a new task similar to these seeds,
then ask the teacher to answer it."
Returns None when the row fails filters (dedup, length, safety).
"""
few_shot = "\n\n".join(
f"Task: {t}" for t in random.sample(seed_tasks, k=3)
)
instruction = teacher(
f"Generate one new instruction in the same style:\n{few_shot}\nTask:"
).strip()
if len(instruction) < 8 or len(instruction) > 400:
return None
if rouge_l_against_seeds(instruction, seed_tasks) > 0.7:
return None # too similar to an existing seed
response = teacher(
f"Follow this instruction exactly:\n{instruction}\n\nResponse:"
).strip()
if len(response) < 4:
return None
return {"instruction": instruction, "response": response}The kd_loss is about ten lines of real logic, which is about how big the conceptual content is. And the generator function has three filters for every one generation call, which is the right ratio. Synthetic data pipelines that skip the filters produce data that hurts more than it helps.
Misconceptions
"Distillation makes the small model as good as the big model." No. Distillation makes the small model a better imitator of the big model on the domains where you trained it. If the teacher is 80% accurate on a task and you distill cleanly, the student will land somewhere between "the small model's baseline" and 80%. The student's ceiling is bounded by the teacher. Carefully chosen data can make the gap surprisingly small; nothing makes it negative in general. When you see a headline claiming a small model "beats" a bigger one, it's almost always on a narrow benchmark that was explicitly targeted in the training mix.
"Synthetic data is free." Sure, the marginal cost per token is low, but every synthetic dataset was produced by running a teacher model at some cost. More importantly, the quality of the data is bounded by the quality of the teacher plus your filter. If your teacher is wrong about a topic, your synthetic data is wrong about that topic, and your student will be confidently wrong after training. The cost shows up as quality debt, not as a dollar line item.
"If the teacher is aligned, the student will be too." Alignment transfers weakly, at best. A teacher that politely refuses harmful prompts can produce training data that looks aligned on the surface. But if you fine-tune a base model on that data you haven't installed the underlying preferences. You've installed a surface imitation of refusals for the specific triggers that showed up in the training set. Safety work on the student model is a separate effort, usually involving RLHF or DPO on top of the distilled SFT stage. Don't skip it.
What's next
The next post covers LoRA and parameter-efficient fine-tuning, where instead of distilling a whole new model we bolt small trainable modules onto a frozen base. The cheapest way to teach an existing model a new trick without retraining it.
Additional reading (and watching)
-
Hinton, G., Vinyals, O., & Dean, J. (2015). Distilling the Knowledge in a Neural Network. arXiv:1503.02531. The original knowledge-distillation paper. Introduces the temperature-scaled KL loss and the "dark knowledge" framing.
-
Gemma Team. (2024). Gemma 2: Improving Open Language Models at a Practical Size. arXiv:2408.00118. Describes logit-level distillation from a larger teacher during pretraining for the 9B and 27B models.
-
Taori, R., et al. (2023). Alpaca: A Strong, Replicable Instruction-Following Model. Stanford CRFM. The seed project that popularized GPT-3.5 → 7B synthetic SFT.
-
Wang, Y., et al. (2023). Self-Instruct: Aligning Language Models with Self-Generated Instructions. ACL 2023. The canonical pipeline for bootstrapping instruction data from a small seed pool.
-
Mukherjee, S., et al. (2023). Orca: Progressive Learning from Complex Explanation Traces of GPT-4. arXiv:2306.02707. Distilling GPT-4 reasoning traces into a 13B student.
-
Abdin, M., et al. (2024). Phi-3 Technical Report: A Highly Capable Language Model Locally on Your Phone. arXiv:2404.14219. The most recent public Phi report describing the synthetic-textbook data recipe.
-
Shumailov, I., et al. (2023). The Curse of Recursion: Training on Generated Data Makes Models Forget. arXiv:2305.17493. The formal treatment of model collapse under iterative self-training.
-
Dohmatob, E., et al. (2024). A Tale of Tails: Model Collapse as a Change of Scaling Laws. ICML 2024. Shows how model collapse interacts with pretraining scaling laws when synthetic data contaminates the mix.
-
Gunasekar, S., et al. (2023). Textbooks Are All You Need. arXiv:2306.11644. The original Phi-1 paper introducing the synthetic-textbook pretraining idea.
-
Zhang, H., Da, J., Lee, D., et al. (2024). A Careful Examination of Large Language Model Performance on Grade School Arithmetic. arXiv:2405.00332. Discussion of benchmark contamination issues, including the Phi family's reported scores.
-
DeepSeek-AI. (2025). DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arXiv:2501.12948. Includes six distilled smaller models trained on ~800k reasoning traces from the full R1.
-
Long, L., et al. (2024). On LLMs-Driven Synthetic Data Generation, Curation, and Evaluation: A Survey. arXiv:2406.15126. Helpful survey of the current synthetic-data landscape across SFT, distillation, and evaluation uses.