The most impactful thing you can do for fine-tuning quality is improve your data.
A 500-example dataset of expert-curated pairs will outperform 50,000 noisy scraped examples.
The pipeline supports five input formats (auto-detected from JSONL structure):
{"instruction": "Explain recursion.", "input": "", "output": "Recursion is..."}{"messages": [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]}{"conversations": [{"from": "human", "value": "..."}, {"from": "gpt", "value": "..."}]}{"question": "What is LoRA?", "answer": "LoRA is..."}Before you start training, check every item:
The DatasetPreparer computes a quality score (0.0–1.0) for each record using:
| Signal | Weight | What It Measures |
|---|---|---|
| Response/instruction length ratio | 30% | Good responses are at least as long as the question |
| Lexical diversity | 25% | Unique words / total words — catches repetitive text |
| Boilerplate detection | 25% | Penalizes "as an AI model" refusals and lorem ipsum |
| Instruction actionability | 20% | Questions (?) and imperative verbs score higher |
Records below min_quality_score (default: 0.3) are dropped.
| Task Type | Minimum Examples | Sweet Spot | Diminishing Returns |
|---|---|---|---|
| Classification | 100 | 500-1000 | 5000+ |
| Q&A (factual) | 200 | 1000-3000 | 10000+ |
| Code generation | 500 | 2000-5000 | 20000+ |
| Creative writing | 300 | 1000-3000 | 10000+ |
| Instruction following | 500 | 2000-5000 | 15000+ |
The default 90/10 split works for most cases. Adjust based on dataset size:
Always use a fixed random seed for reproducible splits.
# Basic usage
python scripts/prepare_dataset.py data/sample_instructions.jsonl
# Multiple files with custom settings
python scripts/prepare_dataset.py data/*.jsonl \
--output-dir data/prepared \
--val-ratio 0.15 \
--min-quality 0.4 \
--seed 42
# Verbose mode for debugging
python scripts/prepare_dataset.py data/raw.jsonl -vOutput structure:
data/prepared/
├── train.jsonl # Training examples
├── val.jsonl # Validation examples
└── preparation_stats.json # Statistics from the preparation run
These four parameters determine 80% of your training outcome:
1. Learning Rate — Most impactful single parameter
2. Dataset Quality — Garbage in, garbage out
3. Number of Epochs — Too few = underfit, too many = overfit
4. LoRA Rank — Capacity vs. efficiency tradeoff
Everything else is refinement on top of these.
| Scenario | Range | Starting Point |
|---|---|---|
| LoRA fine-tuning | 1e-4 to 3e-4 | 2e-4 |
| QLoRA fine-tuning | 1e-4 to 2e-4 | 1.5e-4 |
| Full fine-tuning | 1e-5 to 5e-5 | 2e-5 |
| Continued pre-training | 5e-6 to 2e-5 | 1e-5 |
Cosine (default): Smooth decay from peak to near-zero. Works well across different training durations. Use this unless you have a specific reason not to.
Linear: Constant decrease. Simpler but slightly worse in practice for most tasks.
Constant with warmup: Good for very short training runs where you don't want the LR to decay at all.
Warmup prevents the first few steps (with random adapter weights) from causing large, damaging gradient updates.
Is your dataset > 10,000 examples?
├── Yes → Start with 1-2 epochs
│ Monitor val loss; stop when it starts rising
└── No
├── 1000-10000 examples → 2-3 epochs
├── 500-1000 examples → 3-5 epochs
└── < 500 examples → 5-10 epochs
(but watch for overfitting!)
Effective batch size = per_device_batch × gradient_accumulation × num_gpus
| Effective Batch | Behavior |
|---|---|
| 4-8 | More noise, can generalize better with small data |
| 16-32 | Sweet spot for most fine-tuning tasks |
| 64-128 | Smoother gradients, needs higher LR proportionally |
If VRAM-limited, reduce per_device_batch_size and increase gradient_accumulation_steps. The training dynamics are nearly identical.
If you have the compute budget, sweep these combinations:
Learning Rate: [1e-4, 2e-4, 3e-4]
LoRA Rank: [8, 16, 32]
Epochs: [1, 2, 3]
That's 27 experiments. Most can be shortened to 1/4 of the data and 1 epoch to identify the best LR and rank, then do a full run with the winner.
| Metric | Healthy Range | Red Flag |
|---|---|---|
| Train loss | Steadily decreasing | Flat, oscillating, or NaN |
| Eval loss | Decreasing, slightly above train | Rising while train drops |
| Gradient norm | 0.1 - 10.0 | > 100 (explosion) or < 0.001 (vanishing) |
| Learning rate | Following schedule | N/A |
Set early_stopping_patience to 3-5 evaluation rounds. If eval loss hasn't improved for that many consecutive evaluations, training stops automatically.
This prevents wasting compute on overfitting epochs and is especially important for small datasets.
| Parameter | Default | Q&A | Code Gen | Summarization | Classification |
|---|---|---|---|---|---|
| LR | 2e-4 | 2e-4 | 1.5e-4 | 2e-4 | 3e-4 |
| Rank | 16 | 16 | 32 | 16 | 8 |
| Alpha | 32 | 32 | 64 | 32 | 16 |
| Dropout | 0.05 | 0.05 | 0.05 | 0.05 | 0.1 |
| Epochs | 3 | 2-3 | 3-5 | 2-3 | 3-5 |
| Max Seq Len | 2048 | 2048 | 4096 | 2048 | 512 |
Get the full Fine-Tuning Pipeline and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.