Conversation
Signed-off-by: Brian Yu <bxyu@nvidia.com>
📝 WalkthroughWalkthroughThis PR introduces Penguin-based asynchronous rollout capability integrated with Ray and vLLM, extending the GRPO training pipeline. Changes include Penguin environment initialization with Ray integration, new async rollout functions, vLLM server configuration updates, and corresponding test coverage. Changes
Sequence Diagram(s)sequenceDiagram
participant GRPO as GRPO Training
participant Penguin as Penguin Rollout<br/>(Ray-enabled)
participant AsyncRL as Async RL Rollout
participant vLLM as vLLM Engine
rect rgb(200, 240, 255)
Note over GRPO,vLLM: New Penguin-prioritized flow
end
GRPO->>GRPO: _should_use_penguin(config)?
alt Penguin enabled
GRPO->>Penguin: run_async_penguin_rollout()
Penguin->>Penguin: Validate Ray initialized<br/>Fetch GCS address
Penguin->>vLLM: Per-row generation via HTTP
vLLM-->>Penguin: Token responses
Penguin->>Penguin: Compute per-sample metrics<br/>(turns, rewards, etc.)
Penguin-->>GRPO: AsyncPenguinRolloutResult<br/>(input_ids, final_batch, metrics)
GRPO->>GRPO: Merge Penguin results<br/>into batch
end
rect rgb(240, 220, 255)
Note over GRPO,vLLM: Fallback to existing async path
end
alt Async vLLM enabled (fallback)
GRPO->>AsyncRL: Existing async rollout
AsyncRL->>vLLM: Batch generation
vLLM-->>AsyncRL: Results
AsyncRL-->>GRPO: Batch
else Standard multi-turn
GRPO->>GRPO: Multi-turn rollout
end
GRPO->>GRPO: Update metrics & continue training
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
nemo_rl/utils/logger.py (1)
133-137: Consider logging a warning for skipped metrics.While filtering non-primitive types is correct for TensorBoard compatibility, silently skipping metrics with
continuecould make debugging difficult if users expect certain metrics to appear. Consider logging a debug or warning message when metrics are skipped.Apply this diff to add visibility:
# Penguin will add additional metrics like wandb histograms. However, some people will log to Tensorboard instead which may not be compatible # This logic catches non-compatible objects being logged. if not isinstance(value, (int, float, bool, str)): + logging.getLogger(__name__).debug( + f"Skipping non-primitive metric '{name}' of type {type(value).__name__} for TensorBoard" + ) continue
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
.gitignore(1 hunks)3rdparty/Penguin-workspace/setup.py(2 hunks)nemo_rl/algorithms/grpo.py(5 hunks)nemo_rl/environments/penguin.py(1 hunks)nemo_rl/experience/rollouts.py(3 hunks)nemo_rl/models/generation/vllm/vllm_worker.py(1 hunks)nemo_rl/models/generation/vllm/vllm_worker_async.py(5 hunks)nemo_rl/utils/logger.py(1 hunks)tests/unit/environments/test_penguin.py(1 hunks)tests/unit/experience/test_rollouts.py(3 hunks)tests/unit/models/generation/test_vllm_generation.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (CODING_GUIDELINES.md)
**/*.py: Follow the Google Python Style Guide for all Python code
Target Python 3.12+ for all Python code in NeMo-RL
Indent Python code with 4 spaces; do not use tabs
Python filenames should be snake_case (e.g., some_file.py)
Class names should be PascalCase
Function and method names should be snake_case
Local variable names should be snake_case; if starting with a number, prefix with k (e.g., k_99th_percentile)
Global variables should be UPPER_SNAKE_CASE and prefixed with G_ (e.g., G_MY_GLOBAL)
Constants should be UPPER_SNAKE_CASE
Avoid shadowing variables declared in an outer scope
Initialize all externally visible members of a class in the constructor
For public interfaces used outside a file, prefer docstrings over comments
Use comments mainly for code within a function or interfaces local to a file
Commented-out code must include a nearby comment explaining usage and why it is commented out; otherwise remove before merging
Use Google-style docstrings for classes and functions (Sphinx-parseable)
Avoid using reflection when functionality can be easily achieved without it
Limit except clauses to the smallest specific set of exceptions possible
For duck-typing via try/except, keep the try body minimal and use else for main logic
Add the NVIDIA copyright header (with current year) at the top of all Python files, excluding tests/ and test-only scripts
Files:
tests/unit/models/generation/test_vllm_generation.pytests/unit/environments/test_penguin.pynemo_rl/models/generation/vllm/vllm_worker.pynemo_rl/utils/logger.pynemo_rl/environments/penguin.pynemo_rl/algorithms/grpo.pynemo_rl/models/generation/vllm/vllm_worker_async.py3rdparty/Penguin-workspace/setup.pynemo_rl/experience/rollouts.pytests/unit/experience/test_rollouts.py
nemo_rl/**/*.py
📄 CodeRabbit inference engine (CODING_GUIDELINES.md)
nemo_rl/**/*.py: Do not set non-None configuration defaults in code; YAML is the single source of truth for defaults
Access required config attributes directly (e.g., policy_cfg["precision"]) and assume presence; do not introduce hidden defaults
Express configuration optionality via TypedDict using typing.NotRequired
When adding a new config key to a TypedDict subclass, document the key’s purpose, valid values/types, and recommended default in code
For any class or function decorated with @ray.remote, add '# pragma: no cover' on the class/def line (and on remote functions)
Files:
nemo_rl/models/generation/vllm/vllm_worker.pynemo_rl/utils/logger.pynemo_rl/environments/penguin.pynemo_rl/algorithms/grpo.pynemo_rl/models/generation/vllm/vllm_worker_async.pynemo_rl/experience/rollouts.py
🧠 Learnings (4)
📚 Learning: 2025-09-10T05:34:35.406Z
Learnt from: bxyu-nvidia
Repo: NVIDIA-NeMo/RL PR: 1110
File: nemo_rl/models/generation/vllm/vllm_worker_async.py:346-359
Timestamp: 2025-09-10T05:34:35.406Z
Learning: In nemo_rl/models/generation/vllm/vllm_worker_async.py, the HTTP server intentionally uses different path structures: `/v1/chat/completions` is under the `/v1` prefix while `/tokenize` is at the root level without the `/v1` prefix. This is the intended design.
Applied to files:
tests/unit/models/generation/test_vllm_generation.pynemo_rl/models/generation/vllm/vllm_worker_async.py
📚 Learning: 2025-09-10T05:35:59.840Z
Learnt from: bxyu-nvidia
Repo: NVIDIA-NeMo/RL PR: 1110
File: nemo_rl/models/generation/vllm/vllm_worker_async.py:363-369
Timestamp: 2025-09-10T05:35:59.840Z
Learning: In nemo_rl/models/generation/vllm/vllm_worker_async.py, the HTTP server should explicitly bind to "0.0.0.0" (all interfaces) rather than a specific interface, as confirmed by bxyu-nvidia. This is an intentional design decision for the vLLM HTTP server functionality.
Applied to files:
tests/unit/models/generation/test_vllm_generation.pynemo_rl/models/generation/vllm/vllm_worker_async.py
📚 Learning: 2025-09-20T14:58:45.492Z
Learnt from: CR
Repo: NVIDIA-NeMo/RL PR: 0
File: CODING_GUIDELINES.md:0-0
Timestamp: 2025-09-20T14:58:45.492Z
Learning: Applies to examples/configs/recipes/**/*.yaml : Recipe YAMLs under examples/configs/recipes/** are runnable snapshots and may omit documentation
Applied to files:
.gitignore
📚 Learning: 2025-09-10T05:29:34.349Z
Learnt from: bxyu-nvidia
Repo: NVIDIA-NeMo/RL PR: 1110
File: nemo_rl/models/generation/vllm/vllm_worker_async.py:98-105
Timestamp: 2025-09-10T05:29:34.349Z
Learning: In the _maybe_correct_merged_tokens function in nemo_rl/models/generation/vllm/vllm_worker_async.py, the loop condition `len(candidate_token_ids) < len(actual_token_ids) - 1` is intentionally designed to prevent accessing the final token in actual_token_ids, likely to handle specific tokenization edge cases in the vLLM HTTP server integration.
Applied to files:
nemo_rl/models/generation/vllm/vllm_worker_async.py
🧬 Code graph analysis (3)
nemo_rl/algorithms/grpo.py (1)
nemo_rl/experience/rollouts.py (1)
run_async_penguin_rollout(965-1155)
nemo_rl/experience/rollouts.py (5)
nemo_rl/models/generation/interfaces.py (2)
GenerationConfig(118-131)GenerationInterface(215-249)nemo_rl/distributed/batched_data_dict.py (1)
BatchedDataDict(75-860)nemo_rl/data/interfaces.py (1)
DatumSpec(32-40)nemo_rl/environments/penguin.py (1)
run_rollouts(107-115)nemo_rl/data/llm_message_utils.py (1)
batched_message_log_to_flat_message(233-390)
tests/unit/experience/test_rollouts.py (5)
nemo_rl/data/collate_fn.py (1)
rl_collate_fn(29-73)nemo_rl/data/interfaces.py (1)
DatumSpec(32-40)nemo_rl/environments/penguin.py (1)
penguin_example_to_nemo_rl_datum_spec(199-212)nemo_rl/experience/rollouts.py (2)
run_async_multi_turn_rollout(779-934)run_async_penguin_rollout(965-1155)nemo_rl/distributed/batched_data_dict.py (2)
BatchedDataDict(75-860)get_dict(858-860)
🪛 Ruff (0.14.2)
nemo_rl/experience/rollouts.py
1077-1077: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
tests/unit/experience/test_rollouts.py
46-46: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
47-47: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
48-48: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
49-49: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
50-50: Unused noqa directive (non-enabled: F401)
Remove unused noqa directive
(RUF100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Post automodel integration comment / Comment on PR
- GitHub Check: Post submodule check comment / Comment on PR
🔇 Additional comments (11)
.gitignore (1)
44-44: LGTM! Standard cache ignore pattern.Adding
.cache/to the gitignore is appropriate for excluding runtime cache artifacts.nemo_rl/models/generation/vllm/vllm_worker.py (1)
308-308: LGTM! Correct vLLM server model name configuration.Adding
served_model_nameto the LLM initialization aligns with vLLM's OpenAI-compatible API server requirements for model identification.tests/unit/models/generation/test_vllm_generation.py (1)
1115-1115: LGTM! Aligns test with OpenAI API specification.Adding the
modelfield to the HTTP request body correctly reflects the OpenAI chat completions API requirements and aligns with the vLLM server changes.3rdparty/Penguin-workspace/setup.py (2)
43-43: LGTM! Ray dependency added for Penguin integration.Adding
ray[default]to CACHED_DEPENDENCIES correctly supports the Ray-based Penguin rollout integration introduced in this PR.
28-28: The constraint currently allows the latest version; consider loosening for maintainability.The constraint
openai<=2.6.1is not actually restrictive at present, as v2.6.1 is the latest release and no breaking changes were introduced after 2.6.1. However, this hard cap may become problematic for future patch or minor releases. Consider usingopenai>=2.6.0,<3.0.0to allow patch updates and prevent maintenance burden as new releases occur.nemo_rl/models/generation/vllm/vllm_worker_async.py (4)
181-184: LGTM! Dual model path registration.Adding both
served_model_nameandmodelas BaseModelPath entries allows the vLLM OpenAI server to route requests using either identifier, improving flexibility for client integrations.
292-292: LGTM! Improved variable naming for clarity.Using
actual_corresponding_token_idsinstead oftemplate_prefix_token_idsbetter reflects that this variable contains the actual tokenized result from preprocessing the messages up to the last assistant turn, making the token replacement logic more understandable.
455-465: LGTM! Appropriate log noise reduction.Adding a filter to suppress HTTP 200 OK messages from
uvicorn.accesslogs helps reduce noise and makes error messages more visible during debugging and operation.
379-382: Incorrect review comment - no custom override was removed.The search across the codebase found no
create_tokenizemethod definition anywhere. TheNeMoRLOpenAIServingTokenizationclass with apassbody is the correct design: it acts as a bridge combiningNeMoRLOpenAIServingMixin(which provides_preprocess_chatcustomizations via MRO) with vLLM'sOpenAIServingTokenization(which provides the inheritedcreate_tokenizemethod). The tokenization behavior is preserved and resolves correctly to the vLLM parent implementation.Likely an incorrect or invalid review comment.
tests/unit/environments/test_penguin.py (1)
106-106: LGTM! Enables reasoning parser for Penguin tests.Adding
uses_reasoning_parser: trueto the test configuration correctly enables the reasoning parser feature for the Qwen model, aligning with the Penguin integration's reasoning capabilities.nemo_rl/environments/penguin.py (1)
66-74: LGTM! Proper Ray cluster integration.The Ray initialization checks and GCS address retrieval correctly ensure that Penguin can connect to the Ray cluster. The assertions provide clear runtime validation, and storing the address in the global config enables Penguin components to access the Ray cluster head node.
Signed-off-by: Brian Yu <bxyu@nvidia.com>
…NeMo/RL into bxyu/integrate-penguin-env-logic
Signed-off-by: Brian Yu <bxyu@nvidia.com>
…NeMo/RL into bxyu/integrate-penguin-env-logic
Signed-off-by: Brian Yu <bxyu@nvidia.com>
Signed-off-by: Brian Yu <bxyu@nvidia.com> Co-authored-by: Parth Chadha <pchadha@nvidia.com>
Signed-off-by: Brian Yu <bxyu@nvidia.com> Co-authored-by: Parth Chadha <pchadha@nvidia.com>
Signed-off-by: Brian Yu <bxyu@nvidia.com> Co-authored-by: Parth Chadha <pchadha@nvidia.com> Signed-off-by: yuanhangs <yuanhangs@nvidia.com>
What does this PR do ?
Add a one line overview of what this PR aims to accomplish.
Issues
List issues that this PR closes (syntax):
Usage
# Add a code snippet demonstrating how to use thisBefore your PR is "Ready for review"
Pre checks:
Additional Information
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Dependencies
Tests