Multimodal input · guardrails · LoRA distillation
Pacing plans that are checked before you see them
Photograph a race course map and state a goal time. Local OCR and Claude read the map into a course profile, retrieval adds pacing research, and Claude writes a km-by-km plan. Six checks in plain Python (coverage, split sum, hill plausibility, fade, heat, citations) must pass before the plan is shown; failures go back to the model as sentences. A LoRA fine-tune of Qwen2.5-3B, trained on a laptop, tries to do the same job locally.
- km 0 to 16Downhill, gentle. Splits may run faster than mean pace.
- km 16 to 26Flat. Splits within 12% of mean pace.
- km 26 to 34Uphill, steep, "Newton hills". Splits may run up to 20% slower.
- km 34 to 42.2Downhill, moderate.
One of six hand-built course fixtures in assets/example_courses/, with the plausibility allowance verifier.py applies to each segment.
70 held-out scenarios
Fine-tuning taught the student the format: parse success went from 55.7% to 95.7%, and it fails coverage, plausibility and heat on under 5% of plans. Where it falls down is arithmetic: 82.9% of its plans miss the goal by more than 90 seconds, and 91.4% report a fade that doesn't match their own splits. (Test set split by scenario id; all three systems ran zero-shot with no retries on the same prompt.)
The six checks
- CoverageOne split per km, plus the partial last km.
- SumSplits total the goal within 90 seconds.
- PlausibilityEach split within its segment's allowance.
- Fade0 to 8% slower in the second half, or a flagged negative split citing the 2.5% base rate.
- HeatAt 18°C and up, an adjustment band derived from my Boston heat-tax finding.
- CitationsAt least one, and only ids retrieved for that prompt.
Training took four attempts
1,458 verifier-passed teacher plans (96.0% of 1,519 attempts) trained an MLX LoRA adapter on a 16 GB Mac. Along the way: a sequence length 2.7 times too short, a memory overflow that printed "loss 0.000" instead of crashing, and three divergences, the last despite a custom gradient-clipping loop. The published adapter is the best checkpoint, about 400 clean iterations at validation loss 0.226.
The full writeup has the per-check table, the training incidents and the limitations.