-
Notifications
You must be signed in to change notification settings - Fork 929
[RL] - MessageEnv, Rollout types, Rubric, Renderer #3453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6913120
7c7c9f7
8e4fc60
dc690a1
40ef4c5
767022f
50b5572
86ed252
31dcd8b
7dad6f5
d440e46
1523db5
312c292
14aaeca
6292f1d
e9af27a
85880db
9243ba1
701b4d1
11003ba
5044e86
2dcd0f9
7a72a41
0cf8460
df376bb
d3ba2df
de7c887
c2efd2b
8b597ba
79c3903
621e3cf
3c69ae6
c77d47f
75e69d4
80104f5
4bf9b33
9d91d4c
d33903e
89f8f85
04c47c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -230,11 +230,11 @@ def _pack_episodes(self, episodes: list[Episode]) -> Iterator[dict]: | |
| def _iterate_samples() -> Iterator[dict]: | ||
| for ep in episodes: | ||
| prompt_len = len(ep.prompt_token_ids) | ||
| response_len = len(ep.token_ids) | ||
| raw_ids = ep.prompt_token_ids + ep.token_ids | ||
| gen_lp = [0.0] * prompt_len + ep.token_logprobs | ||
| loss_mask = [False] * prompt_len + [True] * response_len | ||
| advantages = [0.0] * prompt_len + [ep.advantage] * response_len | ||
| completion_len = len(ep.completion_token_ids) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is "completion" more established than "response"? My nit is "completion" doesn't correspond to "prompt" better than "response".
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both are common in vllm. Completion is a class.
When I hear "completion", i know its talking about the InferenceEngine output. There is no ambiguity. I know its not tool results or env outputs or something else. It is about generated tokens. Response should work well as well. It is what we used in Forge, but there is more room for ambiguity IMO.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sounds ok for now |
||
| raw_ids = ep.prompt_token_ids + ep.completion_token_ids | ||
| gen_lp = [0.0] * prompt_len + ep.completion_logprobs | ||
| loss_mask = [False] * prompt_len + [True] * completion_len | ||
| advantages = [0.0] * prompt_len + [ep.advantage] * completion_len | ||
| sample = { | ||
| "input_ids": raw_ids[:-1], | ||
| "labels": raw_ids[1:], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,9 +26,10 @@ | |
| from torchtitan.experiments.rl.actors.generator import SamplingConfig, VLLMGenerator | ||
| from torchtitan.experiments.rl.actors.trainer import PolicyTrainer | ||
| from torchtitan.experiments.rl.batcher import BatchConfig, Batcher | ||
| from torchtitan.experiments.rl.examples.sum_digits import SumDigitsRollouter | ||
| from torchtitan.experiments.rl.grpo import GRPOLoss, RLTrainer | ||
| from torchtitan.experiments.rl.observability.metrics import MetricsProcessor | ||
| from torchtitan.experiments.rl.sum_digits import SumDigitsEnv | ||
| from torchtitan.experiments.rl.renderer import RendererConfig | ||
| from torchtitan.models.common.attention import FlexAttention | ||
| from torchtitan.models.qwen3 import model_registry | ||
| from torchtitan.protocols.model import ModelConfigConverter | ||
|
|
@@ -74,13 +75,12 @@ def rl_grpo_qwen3_0_6b_varlen() -> RLTrainer.Config: | |
| model_spec=model_registry("0.6B", attn_backend="varlen"), | ||
| hf_assets_path="torchtitan/experiments/rl/example_checkpoint/Qwen3-0.6B", | ||
| num_steps=10, | ||
| num_prompts_per_step=5, | ||
| num_groups_per_rollout_batch=5, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel this should be in Rollouter config.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldnt that break the symmetry with trainer? i.e. the controller is the know that knows batchsize, microbatchsize, max_seq_len to pack to, etc. It sounds to me that the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh sorry this was a comment during early review that I wanted to delete later as I read more. But I forgot |
||
| num_validation_samples=20, | ||
| compile=CompileConfig(enable=True, backend="aot_eager"), | ||
| env=SumDigitsEnv.Config(seed=42, correctness_reward=1.0, format_reward=0.3), | ||
| validation_env=SumDigitsEnv.Config( | ||
| seed=99, correctness_reward=1.0, format_reward=0.3 | ||
| ), | ||
| rollouter=SumDigitsRollouter.Config(), | ||
| group_size=group_size, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. similar |
||
| renderer=RendererConfig(name="qwen3", enable_thinking=True), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why render related to a model name? Is it because it will use tokenizer path? Currently
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| metrics=MetricsProcessor.Config(enable_wandb=True), | ||
| batcher=Batcher.Config( | ||
| batch=BatchConfig(local_batch_size=2, global_batch_size=8, seq_len=2048), | ||
|
|
@@ -115,37 +115,34 @@ def rl_grpo_qwen3_0_6b_varlen() -> RLTrainer.Config: | |
| ), | ||
| checkpoint=CheckpointManager.Config(enable=False), | ||
| sampling=SamplingConfig( | ||
| n=group_size, | ||
| temperature=0.8, | ||
| top_p=0.95, | ||
| max_tokens=100, | ||
| max_tokens=700, | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
|
|
||
| def rl_grpo_qwen3_0_6b_flex() -> RLTrainer.Config: | ||
| """GRPO training config for Qwen3-0.6B with flex attention (4 GPUs: 2 gen + 2 train).""" | ||
| spec = model_registry("0.6B", attn_backend="flex") | ||
| group_size = 8 | ||
| return RLTrainer.Config( | ||
| model_spec=spec, | ||
| model_spec=model_registry("0.6B", attn_backend="flex"), | ||
| hf_assets_path="torchtitan/experiments/rl/example_checkpoint/Qwen3-0.6B", | ||
| num_steps=10, | ||
| num_prompts_per_step=5, | ||
| num_groups_per_rollout_batch=5, | ||
| num_validation_samples=20, | ||
| # TODO: add aot_eager compiling overall, today it doesn't work because | ||
| # we are missing mechanism to scoop Flex region to plug in inductor backend support | ||
| env=SumDigitsEnv.Config(seed=42, correctness_reward=1.0, format_reward=0.3), | ||
| validation_env=SumDigitsEnv.Config( | ||
| seed=99, correctness_reward=1.0, format_reward=0.3 | ||
| ), | ||
| rollouter=SumDigitsRollouter.Config(), | ||
| group_size=group_size, | ||
| renderer=RendererConfig(name="qwen3", enable_thinking=True), | ||
| metrics=MetricsProcessor.Config(enable_wandb=True), | ||
| batcher=Batcher.Config( | ||
| batch=BatchConfig(local_batch_size=2, global_batch_size=8, seq_len=2048), | ||
| ), | ||
| trainer=PolicyTrainer.Config( | ||
| optimizer=OptimizersContainer.Config(lr=2e-6), | ||
| optimizer=default_adamw(lr=2e-6), | ||
| lr_scheduler=LRSchedulersContainer.Config( | ||
| warmup_steps=2, | ||
| decay_type="linear", | ||
|
|
@@ -174,7 +171,6 @@ def rl_grpo_qwen3_0_6b_flex() -> RLTrainer.Config: | |
| ), | ||
| checkpoint=CheckpointManager.Config(enable=False), | ||
| sampling=SamplingConfig( | ||
| n=group_size, | ||
| temperature=0.8, | ||
| top_p=0.95, | ||
| max_tokens=100, | ||
|
|
@@ -217,13 +213,12 @@ def rl_grpo_qwen3_1_7b() -> RLTrainer.Config: | |
| model_spec=model_registry("1.7B", attn_backend="varlen"), | ||
| hf_assets_path="torchtitan/experiments/rl/example_checkpoint/Qwen3-1.7B", | ||
| num_steps=10, | ||
| num_prompts_per_step=5, | ||
| num_groups_per_rollout_batch=5, | ||
| num_validation_samples=20, | ||
| compile=CompileConfig(enable=True, backend="aot_eager"), | ||
| env=SumDigitsEnv.Config(seed=42, correctness_reward=1.0, format_reward=0.3), | ||
| validation_env=SumDigitsEnv.Config( | ||
| seed=99, correctness_reward=1.0, format_reward=0.3 | ||
| ), | ||
| rollouter=SumDigitsRollouter.Config(), | ||
| group_size=group_size, | ||
| renderer=RendererConfig(name="qwen3", enable_thinking=True), | ||
| metrics=MetricsProcessor.Config(enable_wandb=True), | ||
| batcher=Batcher.Config( | ||
| batch=BatchConfig(local_batch_size=2, global_batch_size=8, seq_len=2048), | ||
|
|
@@ -259,10 +254,9 @@ def rl_grpo_qwen3_1_7b() -> RLTrainer.Config: | |
| ), | ||
| checkpoint=CheckpointManager.Config(enable=False), | ||
| sampling=SamplingConfig( | ||
| n=group_size, | ||
| temperature=0.8, | ||
| top_p=0.95, | ||
| max_tokens=100, | ||
| max_tokens=700, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will need to change batcher max_seq_length accordingly, otherwise all the samples will be dropped because they are longer than |
||
| ), | ||
| ), | ||
| ) | ||
|
|
@@ -275,13 +269,12 @@ def rl_grpo_qwen3_14b() -> RLTrainer.Config: | |
| model_spec=model_registry("14B", attn_backend="varlen"), | ||
| hf_assets_path="torchtitan/experiments/rl/example_checkpoint/Qwen3-14B", | ||
| num_steps=10, | ||
| num_prompts_per_step=5, | ||
| num_groups_per_rollout_batch=5, | ||
| num_validation_samples=20, | ||
| compile=CompileConfig(enable=True, backend="aot_eager"), | ||
| env=SumDigitsEnv.Config(seed=42, correctness_reward=1.0, format_reward=0.3), | ||
| validation_env=SumDigitsEnv.Config( | ||
| seed=99, correctness_reward=1.0, format_reward=0.3 | ||
| ), | ||
| rollouter=SumDigitsRollouter.Config(), | ||
| group_size=group_size, | ||
| renderer=RendererConfig(name="qwen3", enable_thinking=True), | ||
| metrics=MetricsProcessor.Config(enable_wandb=True), | ||
| batcher=Batcher.Config( | ||
| batch=BatchConfig(local_batch_size=2, global_batch_size=8, seq_len=2048), | ||
|
|
@@ -316,17 +309,16 @@ def rl_grpo_qwen3_14b() -> RLTrainer.Config: | |
| ), | ||
| checkpoint=CheckpointManager.Config(enable=False), | ||
| sampling=SamplingConfig( | ||
| n=group_size, | ||
| temperature=0.8, | ||
| top_p=0.95, | ||
| max_tokens=100, | ||
| max_tokens=700, | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
|
|
||
| def rl_grpo_qwen3_0_6b_batch_invariant() -> RLTrainer.Config: | ||
| """On-policy GRPO config for Qwen3-0.6B under same parallelism (4 GPUs: 2 gen + 2 train). | ||
| """On-policy GRPO config for Qwen3-0.6B (4 GPUs: 2 gen + 2 train). | ||
|
|
||
| Enables deterministic + batch-invariant mode for true on-policy RL training. | ||
| """ | ||
|
|
@@ -336,13 +328,12 @@ def rl_grpo_qwen3_0_6b_batch_invariant() -> RLTrainer.Config: | |
| model_spec=model_registry("0.6B", attn_backend="varlen"), | ||
| hf_assets_path="torchtitan/experiments/rl/example_checkpoint/Qwen3-0.6B", | ||
| num_steps=10, | ||
| num_prompts_per_step=5, | ||
| num_groups_per_rollout_batch=5, | ||
| num_validation_samples=20, | ||
| compile=CompileConfig(enable=True, backend="aot_eager"), | ||
| env=SumDigitsEnv.Config(seed=42, correctness_reward=1.0, format_reward=0.3), | ||
| validation_env=SumDigitsEnv.Config( | ||
| seed=99, correctness_reward=1.0, format_reward=0.3 | ||
| ), | ||
| rollouter=SumDigitsRollouter.Config(), | ||
| group_size=group_size, | ||
| renderer=RendererConfig(name="qwen3", enable_thinking=True), | ||
| metrics=MetricsProcessor.Config(enable_wandb=True), | ||
| batcher=Batcher.Config( | ||
| batch=BatchConfig(local_batch_size=2, global_batch_size=8, seq_len=2048), | ||
|
|
@@ -381,10 +372,9 @@ def rl_grpo_qwen3_0_6b_batch_invariant() -> RLTrainer.Config: | |
| ), | ||
| checkpoint=CheckpointManager.Config(enable=False), | ||
| sampling=SamplingConfig( | ||
| n=group_size, | ||
| temperature=0.8, | ||
| top_p=0.95, | ||
| max_tokens=100, | ||
| max_tokens=700, | ||
| ), | ||
| debug=batch_invariant_config, | ||
| ), | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general I would prefer full spelling over shorthand. Could we do
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to signal somehow that those are "base" envs, not something like a SumDigitsEnvs, thats why i put
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. If we follow strictly the sft counterpart, for classes / interfaces you would expect users to implement, it probably should be
Meanwhile, |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Copyright (c) Meta Platforms, Inc. and affiliates. | ||
| # All rights reserved. | ||
| # | ||
| # This source code is licensed under the BSD-style license found in the | ||
| # LICENSE file in the root directory of this source tree. | ||
|
|
||
| from torchtitan.experiments.rl.environment.message import ( | ||
| MessageEnv, | ||
| MessageEnvInitOutput, | ||
| MessageEnvStepOutput, | ||
| ) | ||
| from torchtitan.experiments.rl.environment.token import TokenEnv, TokenEnvOutput | ||
|
|
||
| __all__ = [ | ||
| "MessageEnv", | ||
| "MessageEnvInitOutput", | ||
| "MessageEnvStepOutput", | ||
| "TokenEnv", | ||
| "TokenEnvOutput", | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would this be used for sft as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to depend on renders lastest main?