| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import os |
| from typing import Any |
|
|
|
|
| def resolve_config_path(config_path: str) -> str: |
| """Resolve agent loop configuration file path. |
| |
| In multi-node Ray training, relative paths may not resolve correctly |
| because the working directory on remote nodes can differ from the driver node. |
| This function resolves relative paths by checking multiple locations in order: |
| 1. If already absolute, return as-is |
| 2. Try current working directory |
| 3. Try relative to verl package installation (project root) |
| |
| Args: |
| config_path: Configuration file path (relative or absolute) |
| |
| Returns: |
| Absolute path to the configuration file |
| |
| Raises: |
| FileNotFoundError: If the configuration file cannot be found |
| """ |
| |
| if os.path.isabs(config_path): |
| return config_path |
|
|
| |
| cwd = os.path.abspath(os.getcwd()) |
| cwd_path = os.path.abspath(os.path.join(cwd, config_path)) |
| if (cwd_path == cwd or cwd_path.startswith(cwd + os.sep)) and os.path.exists(cwd_path): |
| return cwd_path |
|
|
| |
| try: |
| import verl |
|
|
| verl_package_dir = os.path.abspath(os.path.dirname(verl.__file__)) |
|
|
| |
| project_root = os.path.dirname(verl_package_dir) |
| dev_path = os.path.abspath(os.path.join(project_root, config_path)) |
| if (dev_path == project_root or dev_path.startswith(project_root + os.sep)) and os.path.exists(dev_path): |
| return dev_path |
|
|
| |
| install_path = os.path.abspath(os.path.join(verl_package_dir, config_path)) |
| if (install_path == verl_package_dir or install_path.startswith(verl_package_dir + os.sep)) and os.path.exists( |
| install_path |
| ): |
| return install_path |
| except (ImportError, AttributeError): |
| pass |
|
|
| |
| raise FileNotFoundError( |
| f"Agent loop configuration file not found: {config_path}. Tried current directory and verl project root." |
| ) |
|
|
|
|
| |
| |
| |
| def format_gpt_oss_tool_response_manually(tool_response: str, tool_call_name: str) -> str: |
| """Format tool response for gpt-oss model. |
| Args: |
| tool_response: Tool response string |
| tool_call_name: Name of the tool that was called |
| |
| Returns: |
| Formatted tool response string |
| """ |
| return f"<|start|>functions.{tool_call_name} to=assistant<|channel|>commentary<|message|>{tool_response}<|end|>" |
|
|
|
|
| def add_generation_prompt_for_gpt_oss(message_content: str) -> str: |
| """Add generation prompt for gpt-oss model. |
| Args: |
| message_content: Message content string |
| |
| Returns: |
| Message content string with generation prompt |
| """ |
| return message_content + "<|start|>assistant" |
|
|
|
|
| def build_gpt_oss_tool_response_text(messages: list[dict[str, Any]], tool_call_names: list[str]) -> str: |
| """Build gpt-oss tool response text (manual formatting + generation prompt).""" |
| tool_response_texts: list[str] = [] |
| for i, tool_msg in enumerate(messages): |
| actual_tool_name = tool_call_names[i] |
| formatted = format_gpt_oss_tool_response_manually(tool_msg["content"], actual_tool_name) |
| tool_response_texts.append(formatted) |
| return add_generation_prompt_for_gpt_oss("".join(tool_response_texts)) |
|
|