fix(rollout): honor per-call args in generate_rollout_async (GenerateState caches first args)#2196
Open
sdc17 wants to merge 2 commits into
Open
fix(rollout): honor per-call args in generate_rollout_async (GenerateState caches first args)#2196sdc17 wants to merge 2 commits into
sdc17 wants to merge 2 commits into
Conversation
…State caches first args)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
generate_rollout_async(args, ...)does not honor itsargsargument for task dispatch.GenerateStateis a global singleton (SingletonMeta), so its__init__(and thereforeself.args) runs only on the first instantiation.GenerateState.submit_generate_tasksthen dispatchesgenerate_and_rm_group(self.args, ...)using that cachedself.args. Any rollout invoked after the first with a differentargsobject silently runs with the first call's args.Impact
This occurs when eval and train are invoked with different
args, a supported pattern via--eval-function-path.A concrete example using the framework's own
--group-rm:assert not args.group_rmineval_rolloutandeval_rollout_single_dataset). So to evaluate while training with--group-rm, the naturalapproach is a custom
--eval-function-paththat runs eval on a copy ofargswithgroup_rm=False.GenerateStatesingleton withgroup_rm=False. Every subsequent training rollout then reuses the singleton and is dispatched withgroup_rm=False, so group RM is silently disabled for the whole run, with no error, because thetraining side
args.group_rmis stillTrue. Running the same config with--skip-eval-before-trainworks, because training creates the singleton first. That contrast is the tell.
More generally, any field a custom eval or rollout function changes on its
argsis ignored after the first rollout.Root cause
generate_rollout_async(args, ...)callsGenerateState(args), which returns the existing singleton (its__init__is skipped), then callssubmit_generate_tasks, which dispatches with the staleself.args.Fix
Refresh the singleton's
argsto the current call'sargsat the start of each rollout:self.argshas exactly one consumer,submit_generate_tasks, and it is called only fromgenerate_rollout_async. The eval path (eval_rollout_single_dataset) dispatchesgenerate_and_rm(args, ...)with its own per callargsand never readsself.args, so refreshingself.argshere covers every consumer.Reproduction
Train with
--group-rmplus a custom--eval-function-paththat setsgroup_rm=Falseon a copy ofargs, and run eval before training. Group RM is silently off during training, while the same config with--skip-eval-before-trainis correct.