L3 · 06 · Fine-tuning, LoRA & Distillation

Fine-tuning changes the model itself by continuing its training on your data. It's powerful and usually the last thing you should reach for — after prompting, structured output and RAG. This page covers when it's justified, the data it needs, parameter-efficient methods (LoRA/QLoRA), distillation, and how to tell if it worked.

Level 355 minTracks 3, 13Last verified 2026-10

By the end of this page you can

The decision order (fine-tune last)

1. Prompting+ few-shot 2. Structured output+ RAG 3. Tool use /agents 4. Fine-tuning(last resort)
Your problemRight fixNOT fine-tuning
Model doesn't know your data (policies, SKUs, internal docs)RAG — inject it at query timeFacts change; a frozen model goes stale
Output format is wrongStructured output / JSON schemaSchema enforcement is cheaper and exact
Task is just hardBetter prompt + stronger modelFine-tuning can't add capability data can't teach
Consistent style/format/behaviour across thousands of callsFine-tuning — finally justified—
Small model must match big model on a narrow task (cost/latency)Distillation—
Domain jargon the base model butchersFine-tuning (or RAG first)—
Rule of thumb If you can write it as instructions or retrieve it as context, don't fine-tune. Fine-tune for behaviour and form (style, format, task pattern, domain tone), not for knowledge — knowledge goes stale and belongs in retrieval.

The data is the hard part

Fine-tuning learns whatever you show it — including your mistakes. Supervised fine-tuning (SFT) uses input → desired output pairs:

{"messages": [{"role": "system", "content": "You are a store assistant. Reply with a JSON action."}, {"role": "user", "content": "any earbuds at riverside?"}, {"role": "assistant", "content": "{\"action\": \"check_inventory\", \"sku\": \"EARBUDS-AIR2\", \"store\": \"riverside\"}"}]}
{"messages": [{"role": "system", "content": "You are a store assistant. Reply with a JSON action."}, {"role": "user", "content": "I want to return opened headphones bought 10 days ago"}, {"role": "assistant", "content": "{\"action\": \"check_return_policy\", \"category\": \"opened_electronics\"}"}]}

LoRA and QLoRA: fine-tune without a server farm

Full fine-tuning updates all billions of parameters — expensive and risks "catastrophic forgetting" of general ability. LoRA (Low-Rank Adaptation) freezes the base model and trains only small adapter matrices injected into each layer:

Base modelfrozen weights + LoRA adapterstiny, trainable Specialised model~1% params trained
Starting hyperparametersSensible start
LoRA rank (r)8–16 (higher = more capacity, more overfitting risk)
Learning rate1e-4 – 2e-4 for LoRA
Epochs1–3; more memorises, not learns
Batch size / seq lenAs large as memory allows / covers your examples
# On Apple silicon, MLX runs LoRA locally:
mlx_lm.lora --model mlx-community/<model>-4bit --train --data ./sft_data
# Produces adapter files (not a full model copy) — merge or load alongside the base.

Distillation: big model teaches small model

Use a frontier model to generate high-quality answers, then fine-tune a small model to imitate them. You get near-big-model quality on a narrow task at small-model cost and latency. The catch: check the teacher model's licence — many providers restrict using outputs to train competing models.

Evaluate honestly

Try it (90 min)
  1. Write 50 SFT examples teaching a strict JSON-action format for the Store Assistant.
  2. Hold out 10 as a test set. Check they cover intents, refusals and missing data.
  3. Run LoRA on a small local model (MLX on Mac, or a hosted fine-tune service). Evaluate on the test set.
  4. Compare: fine-tuned small model vs. few-shot prompted base model. Which wins on format compliance? On cost?

Key takeaways