PR #62 added fp8_recipe support but only wired sft.py directly.
The other 10 trainers (dpo, pretrain, grpo, kto, orpo, simpo, ipo,
ppo, reward_model, embedding) all route through apply_v028_speed_memory,
which was calling apply_fp8_training(model) without recipe -- meaning
user-set fp8_recipe='rowwise' was a silent no-op on every non-SFT task.
- v028_features.apply_v028_speed_memory: read tcfg.fp8_recipe and pass
through to apply_fp8_training; surface the picked recipe in the
green status line so the run record reflects the actual dispatch
- sft.py: drop the defensive getattr (fp8_recipe is a Pydantic field
with a default, not optional) -- use tcfg.fp8_recipe directly
- tests: add TestFP8RecipeViaV028Features (4 tests) verifying the
recipe propagates through apply_v028_speed_memory for tensorwise /
rowwise / rowwise_with_gw_hp, plus the int8-QAT path is unaffected
Add fp8_recipe config field to TrainingConfig with three torchao-backed
scaling recipes: tensorwise (default, v0.28.0 behavior), rowwise (more
accurate via CUTLASS), and rowwise_with_gw_hp (most accurate, grad_weight
in high precision). Dispatches via Float8LinearConfig.from_recipe_name().
- schema.py: add fp8_recipe Literal field with validator requiring
quantization_aware='fp8' for non-default recipes
- fp8.py: update apply_fp8_training() to accept recipe parameter
- sft.py: pass tcfg.fp8_recipe to apply_fp8_training()
- README.md: document recipe options with comparison table
- tests: 24 tests covering schema, dispatch, validation, backward compat