Original source
---
id: llm-pipeline-capstone
title: End-to-End LLM and Fine-Tuning Pipeline
code: EE
subtitle: Plan, run and gate a hashed stage DAG. Head swap, SFT loss mask and DPO loss from the capstones, with defaults.
hue: 215
sources: phases/10-llms-from-scratch/13-building-complete-llm-pipeline, phases/19-capstone-projects/07-end-to-end-fine-tuning-pipeline, phases/19-capstone-projects/38-classifier-finetuning, phases/19-capstone-projects/39-instruction-tuning-sft, phases/19-capstone-projects/40-dpo-from-scratch
source_hash: 2d1fd91ad69bc1db
---
## Commands
type: command-table
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/10-llms-from-scratch/13-building-complete-llm-pipeline/code/main.py, phases/19-capstone-projects/07-end-to-end-fine-tuning-pipeline/docs/en.md, phases/19-capstone-projects/07-end-to-end-fine-tuning-pipeline/code/main.py, phases/19-capstone-projects/38-classifier-finetuning/code/main.py, phases/19-capstone-projects/39-instruction-tuning-sft/code/main.py, phases/19-capstone-projects/40-dpo-from-scratch/code/main.py
| Command | What it does |
|---|---|
| `python code/main.py plan` | Validates the manifest, prints DAG and gates |
| `python code/main.py run` | Runs stages, prints the manifest JSON |
| `python code/main.py gate` | Applies eval gates. Prints `SHIP` or `HOLD` |
| `python code/main.py` | Demo: plan, run, a passing and a failing gate |
| `./pipeline.sh config/llama3.3-8b-domainX.yaml` | Capstone 07: data to model card |
| `run_demo()` | Capstones 38 to 40. Exits zero on success |
## Twelve-stage DAG
type: architecture
span: 2
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/10-llms-from-scratch/13-building-complete-llm-pipeline/code/main.py
```arch
node | tok | 1,1 | 01-02 Tokenizer | vocab, merges | store
node | data | 2,1 | 03 Dataset | sharded | store
node | base | 3,1 | 04-05 Checkpoint | pre-train, scale | gpu
node | sft | 4,1 | 06 SFT model | checkpoint + recipe | gpu
node | ppo | 4,2 | 07 Reward + PPO | policy | gpu
node | dpo | 3,2 | 08 DPO | policy | gpu
node | cai | 2,2 | 09 CAI / GRPO | refined policy | gpu
node | eval | 1,2 | 10 Eval report | scores, diffs | process
node | quant | 2,3 | 11 Quantized | weights + delta | store
node | srv | 3,3 | 12 Server spec | endpoint | process
node | gate | 1,3 | Ship gate | SHIP or HOLD | client
edge | tok | data |
edge | data | base |
edge | base | sft |
edge | sft | ppo |
edge | sft | dpo |
edge | ppo | cai |
edge | dpo | cai |
edge | cai | eval |
edge | cai | quant |
edge | quant | srv |
edge | eval | gate |
edge | srv | gate |
```
## What the orchestrator does
type: flow
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/10-llms-from-scratch/13-building-complete-llm-pipeline/code/main.py
1. **Orchestrator**: resolves the DAG from the manifest.
2. **Orchestrator**: skips a stage if its output already exists at the correct hash.
3. **Stage**: runs. The orchestrator measures wall clock and cost.
4. **Orchestrator**: checks the output hash against the next stage input hash.
5. **CostTracker**: halts with `halted_over_budget` when total cost passes the budget.
6. **On failure**: writes a partial manifest and exits nonzero.
## Manifest and gates
type: annotated-code
lang: yaml
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md
```yaml
pipeline_version: 1.2.3
seed: 42
git_commit: a1b2c3d4
stages:
01_tokenizer:
input_hash: sha256:... # output hash of the stage before
output_hash: sha256:... # input hash of the next stage
gates:
mmlu: >= baseline + 0.5 # no regression
humaneval: >= baseline + 1.0
safety_refusal_rate: <= 0.05
kl_from_reference: <= 25.0 # KL budget gate
cost_total_usd: <= 50000
```
## Gate defaults in main.py
type: defaults
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/code/main.py
| Setting | Default | Note |
|---|---|---|
| `mmlu` | 65.0 | op `>=` |
| `humaneval` | 40.0 | op `>=` |
| `truthfulqa` | 50.0 | op `>=` |
| `safety_refusal_rate` | 0.05 | op `<=` |
| `kl_from_reference` | 25.0 | op `<=` |
| `cost_total_usd` | 50000.0 | op `<=` |
| `budget_usd` | 50000.0 | Run halts above it |
| `seed` | 42 | In `Manifest` |
## The three capstones side by side
type: comparison
span: 2
from: phases/19-capstone-projects/38-classifier-finetuning, phases/19-capstone-projects/39-instruction-tuning-sft, phases/19-capstone-projects/40-dpo-from-scratch
| Factor | 38 Classifier head swap | 39 Instruction SFT | 40 DPO |
|---|---|---|---|
| Builds | Body + mean pool + 2-class head | `TinyGPT` trained on response tokens | Policy against a frozen reference |
| Data | 800 SMS, 640 train, 160 test | 200 pairs, 160 train, 40 test | 12 (prompt, chosen, rejected) triples |
| Model | hidden 64, 4 heads, 2 blocks, max 32 | hidden 96, 2 blocks | hidden 64, 2 blocks |
| Train | 20 epochs head-only, 20 full | 20 epochs, lr 5e-4 | 30 epochs, beta 0.2, lr 1e-3 |
| Metric | Precision, recall, F1, confusion | Exact-match per category | Chosen minus rejected margin |
| Check | Head-only and full both report | Exact-match rises over epochs | Loss falls, margin grows |
## Key calls in the capstones
type: task-table
span: 2
from: phases/19-capstone-projects/38-classifier-finetuning/code/main.py, phases/19-capstone-projects/39-instruction-tuning-sft/code/main.py, phases/19-capstone-projects/40-dpo-from-scratch/code/main.py
| Task | Code |
|---|---|
| Freeze the body for head-only training | `freeze_body(model)` |
| Pool hidden states with the mask | `mean_pool(h, mask)` |
| Pad a batch and mask labels with -100 | `sft_collate(batch)` |
| Causal loss on response tokens | `shifted_loss(logits, labels)` |
| Score a completion under a model | `sequence_log_prob(...)` |
| DPO loss and implicit reward margin | `dpo_loss(lp_w_pol, lp_l_pol, lp_w_ref, lp_l_ref, beta=cfg.beta)` |
| Start the policy from the reference | `policy.load_state_dict(reference.state_dict())` |
## DPO loss
type: annotated-code
lang: python
from: phases/19-capstone-projects/40-dpo-from-scratch/code/main.py
```python
diff_w = logp_w_pol - logp_w_ref # chosen log-ratio
diff_l = logp_l_pol - logp_l_ref # rejected log-ratio
margin = diff_w - diff_l # implicit reward difference
z = beta * margin
loss = -F.logsigmoid(z) # numerically stable
for p in reference.parameters():
p.requires_grad = False # reference never trains
reference.eval()
```
## Capstone 07 log lines
type: command-table
from: phases/19-capstone-projects/07-end-to-end-fine-tuning-pipeline/docs/en.md
| Command | What it does |
|---|---|
| `280k accepted (seed=7)` | Data stage rows kept |
| `val loss 1.42 -> 1.03` | SFT, 3 epochs on 8xH100 |
| `1 epoch, beta=0.08, 4xH100` | DPO run |
| `GPTQ-INT4 4.6 GB, AWQ-INT4 4.8 GB` | Quant sizes |
| `EAGLE-3 acceptance 0.74` | Speculative decoding check |
| `p99 126ms @ bs=8` | Tail latency at batch 8 |
| `MMLU-Pro +3.2, MT-Bench-v2 +0.41` | Eval gain over base |
## Troubleshooting
type: troubleshooting
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/10-llms-from-scratch/13-building-complete-llm-pipeline/code/main.py, phases/19-capstone-projects/39-instruction-tuning-sft/docs/en.md, phases/19-capstone-projects/38-classifier-finetuning/docs/en.md, phases/19-capstone-projects/40-dpo-from-scratch/docs/en.md, phases/19-capstone-projects/07-end-to-end-fine-tuning-pipeline/docs/en.md
| Symptom | Cause | Fix |
|---|---|---|
| `HOLD: missing metric <metric>` | Eval report has no value | Add the metric to the eval stage |
| `input hash missing for stage` | Upstream artifact not in store | Re-run the upstream stage |
| `halted_over_budget` | Total cost above `budget_usd` | Fix the cost estimate at plan time |
| DPO model sent through the SFT path | Untyped artifacts | Typed artifacts and stage signatures |
| Model learns to predict the instruction | No loss mask | `-100` on instruction, pad, boundary |
| Full fine-tuning overfits 800 examples | Small data washes out the body | Train the head only |
| MMLU-Pro accuracy jumps | Contamination in training data | MinHash check, reject any overlap |
| DPO prefers short completions | Length bias | Divide log-prob by completion length |
## Rollback and tips
type: tips
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/19-capstone-projects/40-dpo-from-scratch/docs/en.md
- Run `plan` first every time. It is free. `run` is expensive.
- Cheap to re-run: tokenizer, eval, quantization, inference server.
- Medium: SFT, DPO, CAI. Keep the base model.
- Expensive: pre-training. Use the last good checkpoint.
- A failure at stage 06 invalidates 06 to 12. At stage 11, only 11 and 12.
- Address artifacts by hash. A filename like `latest.pt` is a foot-gun.
- Pre-training FLOPs: 6 x params x tokens.
## Q&A
type: qa
from: phases/10-llms-from-scratch/13-building-complete-llm-pipeline/docs/en.md, phases/19-capstone-projects/40-dpo-from-scratch/docs/en.md, phases/19-capstone-projects/39-instruction-tuning-sft/docs/en.md
- **Which two gates catch most disasters?** A regression gate and a KL budget gate.
- **Reproducible or deterministic?** Reproducible. Floats differ at the 1e-5 level.
- **Why does log Z(x) drop out of DPO?** It is the same for chosen and rejected.
- **Why greedy for exact-match?** Temperature makes the metric stochastic.