Source code for nemo_rl
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
import sys
from pathlib import Path
"""
This is a work around to ensure whenever NeMo RL is imported, that we
add Megatron-LM to the python path. This is because the only sub-package
that's officially installed is megatron.core. So we add the whole repo into
the path so we can access megatron.{training,legacy,inference,...}
Since users may pip install NeMo RL, this is a convenience so they do not
have to manually run with PYTHONPATH=3rdparty/Megatron-LM-workspace/Megatron-LM.
"""
megatron_path = (
Path(__file__).parent.parent / "3rdparty" / "Megatron-LM-workspace" / "Megatron-LM"
)
if megatron_path.exists() and str(megatron_path) not in sys.path:
sys.path.append(str(megatron_path))
from nemo_rl.package_info import (
__contact_emails__,
__contact_names__,
__description__,
__download_url__,
__homepage__,
__keywords__,
__license__,
__package_name__,
__repository_url__,
__shortversion__,
__version__,
)
os.environ["RAY_USAGE_STATS_ENABLED"] = "0"
[docs]
def _patch_nsight_file():
"""Patch the nsight.py file to fix the context.py_executable assignment.
Until this fix is upstreamed, we will maintain this patch here. This patching
logic is only applied if the user intends to use nsys profiling which they enable with
NRL_NSYS_WORKER_PATTERNS.
If enabled, will effectively apply the following patch in an idempotent manner:
https://github.com/ray-project/ray/compare/master...terrykong:ray:tk/nsight-py-exeutable-fix?expand=1
This hack works b/c the nsight plugin is not called from the main driver process, so
as soon as nemo_rl is imported, the patch is applied and the source of the nsight.py module
is up to date before the nsight.py is actually needed.
"""
# Only apply patch if user intends to use nsys profiling
# Don't rely on nemo_rl.utils.nsys.NRL_NSYS_WORKER_PATTERNS since nemo_rl may not be available
# on the node that imports nemo_rl.
if not os.environ.get("NRL_NSYS_WORKER_PATTERNS"):
return
try:
from ray._private.runtime_env import nsight
file_to_patch = nsight.__file__
# Read the current file content
with open(file_to_patch, "r") as f:
content = f.read()
# The line we want to replace
old_line = 'context.py_executable = " ".join(self.nsight_cmd) + " python"'
new_line = 'context.py_executable = " ".join(self.nsight_cmd) + f" {context.py_executable}"'
# Check if patch has already been applied (idempotent check)
if new_line in content:
# Already patched
logging.info(f"Ray nsight plugin already patched at {file_to_patch}")
return
# Check if the old line exists to patch
if old_line not in content:
# Nothing to patch or file structure has changed
logging.warning(
f"Expected line not found in {file_to_patch} - Ray version may have changed"
)
return
# Apply the patch
patched_content = content.replace(old_line, new_line)
# Write back the patched content
with open(file_to_patch, "w") as f:
f.write(patched_content)
logging.info(f"Successfully patched Ray nsight plugin at {file_to_patch}")
except (ImportError, FileNotFoundError, PermissionError) as e:
# Allow failures gracefully - Ray might not be installed or file might be read-only
pass
# Apply the patch
_patch_nsight_file()