Evaluation¶
eval.py loads every stage's checkpoint that exists on disk and puts them
side by side on the same prompts — so you can see what pretraining, SFT,
LoRA, and DPO each changed. It needs no training state, so it runs standalone any
time after the stages you want to compare have finished. Missing checkpoints
(LoRA is optional) are skipped with a note.
Summary
Script: eval.py ·
Loads: ckpt_base.pt, ckpt_sft.pt, ckpt_lora.pt, ckpt_dpo.pt (whichever exist) ·
Run: python eval.py
The four probes¶
1. Instruction following on a hard prompt¶
A prompt with unusual, checkable words (spoon, bird, brave). For each stage the
script reports the required-words coverage, sentiment, and whether the
model stopped on its own (emitted <|endoftext|> before the token cap).
Pretraining typically ignores the instruction; SFT and LoRA follow it and stop.
2. A sad instruction¶
"Summary: A dog loses his toy and cries." This is where the DPO model shows
its bias: SFT obeys the sad summary, while a DPO model trained with the sentiment
reward drags the story back toward a happier tone — visible in the sentiment
score.
3. Mean reward over a fixed pool¶
One number per stage: the mean programmatic reward over 64 fixed eval prompts
(the same pool and seed as dpo.py). This is the single trend line that should
climb from pretrain → sft → dpo when DPO is working.
4. Next-word probability probe¶
No sampling noise — a direct look at the distribution. After
"The dog felt very", the script prints P(happy), P(sad), P(scared),
P(excited) for each stage, so you can watch the preference-tuned model shift
probability mass toward positive continuations.
Reproducibility
The eval pool is drawn with the same seed (np.random.default_rng(0)) as the
DPO stage, so the reward numbers here line up with what you saw during
training.
📄 Source: eval.py