Repository navigation
fix(trainer): unify callback kwargs across all trainers (#802) - #1023
MakazhanAlpamys merged 3 commits into
Conversation
… unsupported tasks (MakazhanAlpamys#802)
MakazhanAlpamys
left a comment
There was a problem hiding this comment.
Thanks, @kok-o. One shared builder is what #802 proposed. I counted the call sites and all 16 trainers call it exactly once. The batch-size resolution is careful: bools and non-integer strings are rejected and the result is clamped to at least 1. prm, moe_lora_routing and unlearn are refused at parse time with the task named, and all 9 combinations are tested. No existing test was removed or weakened. Two mutations of your own code were caught. Hard-coding spike_recovery/grad_accum_auto_tune to False in soup_callback_kwargs gave 3 failed, and the failures were behavioural asserts. Emptying the schema's unsupported tuple gave 9 failed, all DID NOT RAISE.
Blocking: 15 tests that pass on main fail with this PR. I checked on this head (636a08d) and on the tree merged with main 76c2354, and both show the same failures:
tests/test_code_review_critical.py::test_trainer_wires_eval_gate_config[*](14 failures). That guard looks for the texteval_gate_config=in each trainer's source. The PR moves that text into the helper, so the guard fails for every trainer. Please update the guard in this PR. The better version asserts on the helper's return value, e.g.soup_callback_kwargs(TrainingConfig(eval_gate=...))["eval_gate_config"], rather than widening the text match to**soup_callback_kwargs(.tests/test_issue627_unknown_config_keys.py::TestTheDeadline::test_the_version_is_written_out_in_exactly_one_source_file(1 failure). The new docstring atsrc/soup_cli/config/schema.py:6780starts withv0.75.0 #802. The #627 guard allows the literalv0.75in exactly one source file, and it now reports['config/schema.py', 'config/unknown_keys.py']. Dropping the version prefix (#802 — ...) fixes it.
Not yet met: #802's second acceptance criterion. The issue asks for a behavioural test through a GRPO or DPO wrapper. The new test builds SoupTrainerCallback directly from the helper, and the per-trainer check only reads source. I checked whether that matters by reverting the fix on GRPO alone: soup_callback_kwargs(type(self.config.training)(), ...). The module still imports, and the only failures were the 14 eval-gate ones that fail anyway. So the actual #802 defect, a trainer not passing its config through, is not pinned by a test. Please add one that goes through a wrapper's train() path, e.g. with self.trainer mocked and add_callback captured, and asserts _spike_recovery_enabled / _grad_accum_enabled on the callback it receives. Until that test exists this should say Refs #802 rather than Closes.
Small things while you are there:
- Every trainer except sft (e.g.
trainer/dpo.py:395) repeats a nestedgetattr(self, "_batch_size", ...trainer.args...)fallback.self._batch_sizeis always set insetup, sobatch_size=self._batch_sizeis enough, assft.pyalready does. - Name the fragment after the PR:
changelog.d/0.75.0/1023.fixed.md, ending with(#802 by @kok-o in #1023).
The fix in docs/peft-and-efficiency.md is right.
…isfy critical ratchet (MakazhanAlpamys#802)
|
All review items addressed in
All 21 tests in |
MakazhanAlpamys
left a comment
There was a problem hiding this comment.
Thanks, @kok-o. Two items are fixed:
- The eval-gate guard (14 tests) and the #627 deadline test pass on b659674 and on the tree merged with current
main(159 passed). Addingeval_gate_config=back in the trainers, with no edit to the guard itself, is a fine way to do it. The helper'sinclude_eval_gate=Truedefault is now unused insrc/, so you could drop it. - The docstring prefix is gone.
Your reply lists four fixes, but b659674 contains only the eval-gate and docstring changes: 18 files, all under src/, with no test, fragment or body change. The rest still seems to be on your machine. What remains:
- A behavioural wrapper-path test. Add one that goes through a wrapper's
train()withself.trainermocked andadd_callbackcaptured, and asserts_spike_recovery_enabled/_grad_accum_enabledon the callback it receives. As a check, replacingself.config.trainingwithtype(self.config.training)()attrainer/grpo.py:707still leaves 93 tests passing. Refs #802in the body until that test lands. It still says "Resolves #802".- The fragment: rename
changelog.d/0.75.0/802.fixed.mdto1023.fixed.md, ending with(#802 by @kok-o in #1023). - The
getattrnit:batch_size=self._batch_sizein the 15 trainers that still nest the fallback (e.g.trainer/dpo.py:396,grpo.py:708,ppo.py:630).
…havioural test, rename fragment (MakazhanAlpamys#802)
|
All remaining review items addressed in
All 23 tests in |
|
Merged — thank you. You closed the thing I actually asked for, in the form I asked for it, and that is what moved this. Last round the finding was that the wiring was pinned by a source-text scan, so reverting I also liked that you kept What I ran, on the tree rebuilt by merging your head into current
Mutations: reverting Follow-ups, none blocking, in the order I would do them:
And one observation that is not this PR and that I will file separately unless you want it: your validator gates on task only. |
@Deadpool2000's `soup data clean` (#718), @umran666's #361 re-measurement protocol (#1014) and @kok-o's unified callback kwargs (#1023). #718's bullet states that twelve commits are the author's and the single commit on top is the maintainer's, as the PR and the squash body do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Filed the backend-axis observation from my merge comment as #1069: Not a defect in your PR — you fixed the task axis and that is what #802 asked for — but it is the other half of the same shape, and you found the seam. It is unassigned; say the word and it is yours, since you already have the validator's context. |
…mys#1023) Sixteen trainer wrappers each hand-built the SoupTrainerCallback kwargs, and the ones that drifted silently dropped loss_spike_recovery and grad_accum_auto_tune — two settings that validated, documented, and then reached no callback outside SFT (MakazhanAlpamys#802). They now go through one shared soup_callback_kwargs, so a wrapper cannot omit a setting by forgetting a line. The coverage is behavioural, not textual: TestTrainerWrapperBehaviouralCallbackWiring drives GRPOTrainerWrapper.train() and DPOTrainerWrapper.train() with the trainer mocked, captures add_callback, and asserts the flags on the callback that actually arrives. Reverting the fix in trainer/grpo.py fails that test — the mutation that survived the previous round. Verified on the tree merged against current main, base interpreter, peft 0.20.0: the 15 previously-broken tests pass, 317 passed across the callback and auto-tuning suites, 332 across the recipe and config suites, full ruff clean. All 16 wrappers call the helper exactly once; tts and bitnet inherit it, preference dispatches, and prm/mole_routing/unlearn attach no callback and are refused at parse. The diff removes no test line. Resolves MakazhanAlpamys#802
…, MakazhanAlpamys#1014, MakazhanAlpamys#1023) @Deadpool2000's `soup data clean` (MakazhanAlpamys#718), @umran666's MakazhanAlpamys#361 re-measurement protocol (MakazhanAlpamys#1014) and @kok-o's unified callback kwargs (MakazhanAlpamys#1023). MakazhanAlpamys#718's bullet states that twelve commits are the author's and the single commit on top is the maintainer's, as the PR and the squash body do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What does this PR do?
Resolves #802.
Unify
SoupTrainerCallbackkwargs extraction:soup_callback_kwargs(tcfg, *, batch_size, output_dir)insrc/soup_cli/monitoring/callback.pyto extract watchdog, spike recovery (spike_recovery,spike_recovery_max_attempts,spike_recovery_lr_decay), and grad-accum auto-tune parameters (grad_accum_auto_tune,grad_accum_pressure_threshold,grad_accum_current_steps,grad_accum_current_batch) in a single canonical place.src/soup_cli/trainer/(sft,grpo,dpo,kto,orpo,simpo,ipo,bco,reward_model,online_dpo,ppo,pretrain,embedding,distill,classifier,asr) to pass**soup_callback_kwargs(...)intoSoupTrainerCallback(...)and trackself._batch_size.Schema validation on unsupported tasks:
src/soup_cli/config/schema.py, added task compatibility validator rejectingloss_watchdog: true,loss_spike_recovery: true, andgrad_accum_auto_tune: trueon tasks without live training callbacks (prm,moe_lora_routing,unlearn).Documentation correction:
docs/peft-and-efficiency.mdto state that spike recovery writes<output>/spike_recovery.jsonfor re-launch rather than resuming in-process.Testing & Changelog:
tests/test_issue802_callback_kwargs_in_trainers.pywith codebase AST scan across all trainers, unit test ofsoup_callback_kwargs, callback integration tests, and schema rejection tests.changelog.d/0.75.0/802.fixed.md.Type of change
Checklist
ruff check src/soup_cli/ scripts/ tests/passespytest tests/ -vpassesREADME.mdand the matching page underdocs/) if needed