From af26b2e68a2b5e20d40ab027ed253d505cc0b1c6 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Fri, 2 May 2025 15:29:29 -0400 Subject: [PATCH 01/13] propagate cli stuff to serve command --- atroposlib/envs/base.py | 256 ++++++++++++++++++++++++++++++++-------- 1 file changed, 204 insertions(+), 52 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 6c4d2bc4..65a41581 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -939,30 +939,138 @@ class BaseEnv(ABC): type: The CliServeConfig class for serving commands. """ - env_config, server_configs = cls.config_init() + # Get the default configurations defined by the specific environment class + default_env_config, default_server_configs = cls.config_init() + + # Determine a default OpenaiConfig instance for merging purposes, + # even if the actual default is ServerBaseline or a list. + # This allows overriding with OpenAI settings via CLI/YAML consistently. + default_openai_config = OpenaiConfig() # Base default + if isinstance(default_server_configs, OpenaiConfig): + default_openai_config = default_server_configs + elif isinstance(default_server_configs, list) and default_server_configs: + # If the default is a list, use the first item if it's OpenaiConfig + if isinstance(default_server_configs[0], OpenaiConfig): + default_openai_config = default_server_configs[0] + + # Define namespace prefixes for CLI arguments and YAML keys env_full_prefix = f"{ENV_NAMESPACE}{NAMESPACE_SEP}" openai_full_prefix = f"{OPENAI_NAMESPACE}{NAMESPACE_SEP}" + # Define the CLI configuration class dynamically class CliServeConfig( - get_prefixed_pydantic_model(type(env_config), env_full_prefix), - get_prefixed_pydantic_model(OpenaiConfig, openai_full_prefix), - ServerManagerConfig, + get_prefixed_pydantic_model(type(default_env_config), env_full_prefix), + get_prefixed_pydantic_model( + OpenaiConfig, openai_full_prefix + ), # Use OpenaiConfig for CLI args + ServerManagerConfig, # ServerManager args are not namespaced by default Cmd, ): """ Configuration for the serve command. - This combines BaseEnvConfig and OpenaiConfig into a single command. + Supports overrides via YAML config file and CLI arguments. + Order of precedence: CLI > YAML > Class Defaults. """ + config: str | None = Field( + default=None, + description="Path to .yaml config file. CLI args override this.", + ) + def run(self) -> None: """The logic to execute for the 'serve' command.""" - # Convert this config into the formats needed by BaseEnv + # Set default wandb name if not provided and class has a name + # Note: This modifies the 'self' instance based on CLI args before full parsing. wandb_name_attr = f"{ENV_NAMESPACE}{NAMESPACE_SEP}wandb_name" - if getattr(self, wandb_name_attr) is None and cls.name is not None: + if ( + getattr(self, wandb_name_attr, None) is None + and cls.name is not None + ): setattr(self, wandb_name_attr, cls.name) - model_dumped = self.model_dump(exclude_unset=True) - server_manager_config = ServerManagerConfig(**model_dumped) - # Create the environment instance + + # Load configuration from YAML file if specified + if self.config is not None: + with open(self.config, "r") as f: + yaml_config = yaml.safe_load(f) + print(f"Loaded config from {self.config}") + else: + yaml_config = {} + + # Get CLI flags passed with double dashes (e.g., --env--foo bar) + cli_passed_flags = get_double_dash_flags() + + # --- Configuration Merging --- + # Priority: CLI > YAML > Class Defaults + + # 1. Environment Configuration + env_config_dict = merge_dicts( + default_env_config.model_dump(), # Class Defaults + yaml_config.get(ENV_NAMESPACE, {}), # YAML config + extract_namespace(cli_passed_flags, env_full_prefix), # CLI args + ) + + # 2. OpenAI Configuration (used for potential overrides) + openai_config_dict = merge_dicts( + default_openai_config.model_dump(), # Default OpenaiConfig (or from class init) + yaml_config.get(OPENAI_NAMESPACE, {}), # YAML config + extract_namespace(cli_passed_flags, openai_full_prefix), # CLI args + ) + + # 3. Server Manager Configuration (slurm, testing - not namespaced) + # Extract only relevant CLI flags for ServerManager + server_manager_cli_passed_flags = {} + if "slurm" in cli_passed_flags: + server_manager_cli_passed_flags["slurm"] = cli_passed_flags["slurm"] + if "testing" in cli_passed_flags: + server_manager_cli_passed_flags["testing"] = cli_passed_flags[ + "testing" + ] + + server_manager_config_dict = merge_dicts( + ServerManagerConfig().model_dump(), # Base defaults for ServerManager + yaml_config.get(SERVER_MANAGER_NAMESPACE, {}), # YAML config + server_manager_cli_passed_flags, # CLI args + ) + + # --- Instantiate Final Config Objects --- + # Create instances from the merged dictionaries using the original default types where appropriate + + # Instantiate the final environment config using its original type + env_config = type(default_env_config)(**env_config_dict) + + # Instantiate the final server manager config + server_manager_config = ServerManagerConfig( + **server_manager_config_dict + ) + + # Determine the final server_configs based on the original default type from cls.config_init() + # This allows handling ServerBaseline, single OpenaiConfig, or list[OpenaiConfig] + server_configs = ( + default_server_configs # Start with the original default + ) + if isinstance(default_server_configs, OpenaiConfig): + # If default was single OpenaiConfig, update it with merged values + server_configs = OpenaiConfig(**openai_config_dict) + elif isinstance(default_server_configs, list): + # If default was list (presumably of OpenaiConfig), update the first or create one + # This assumes the primary server config is the one overridden via CLI/YAML + if default_server_configs and isinstance( + default_server_configs[0], OpenaiConfig + ): + # Update the first element, keep others as they were + server_configs = [ + OpenaiConfig(**openai_config_dict) + ] + default_server_configs[1:] + else: + # If list was empty or didn't contain OpenaiConfig, create a new list with the merged config + server_configs = [OpenaiConfig(**openai_config_dict)] + # If default_server_configs was ServerBaseline, server_configs remains ServerBaseline, + # effectively ignoring the openai_config_dict unless the user explicitly provides + # OpenaiConfig settings via CLI/YAML, which would be captured but not used here unless + # the environment class's config_init returned an OpenaiConfig or list. + + # --- Create and Run Environment --- + # Create the environment instance using the final, instantiated config objects env = cls( config=env_config, server_configs=server_configs, @@ -970,7 +1078,7 @@ class BaseEnv(ABC): testing=server_manager_config.testing, ) - # Run the environment + # Run the environment's main asynchronous manager function asyncio.run(env.env_manager()) return CliServeConfig @@ -984,51 +1092,76 @@ class BaseEnv(ABC): type: The CliProcessConfig class for processing commands. """ + # Define specific default configurations for the 'process' mode PROCESS_MODE_ENV_DEFAULT_CONFIG = BaseEnvConfig( group_size=8, total_steps=2, ensure_scores_are_not_same=False, include_messages=True, + # Ensure a default path for process mode if not set by class/cli/yaml + data_path_to_save_groups="output_groups.jsonl", + use_wandb=False, # Typically disable wandb for simple processing ) PROCESS_MODE_OPENAI_DEFAULT_CONFIG = OpenaiConfig( - model_name="gpt-4.1-nano", + model_name="gpt-4.1-nano", # A reasonable default for processing base_url=None, api_key=None, ) PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG = ServerManagerConfig( - slurm=False, + slurm=False, # Usually run locally testing=False, ) - default_env_config, default_openai_config = cls.config_init() + # Get the base default configurations from the specific environment class + default_env_config, default_server_configs = cls.config_init() - if isinstance(default_openai_config, list): - default_openai_config = default_openai_config[0] + # Ensure default_openai_config is a single instance for default merging logic. + # Process mode specifically uses OpenaiConfig, so we establish a base default. + if isinstance(default_server_configs, list): + # Use the first if available and is OpenaiConfig, otherwise use a base OpenaiConfig + default_openai_config = ( + default_server_configs[0] + if default_server_configs + and isinstance(default_server_configs[0], OpenaiConfig) + else OpenaiConfig() + ) + elif isinstance(default_server_configs, OpenaiConfig): + default_openai_config = default_server_configs + else: + # If config_init returned ServerBaseline or something else, use a base OpenaiConfig for defaults + default_openai_config = OpenaiConfig() + # Define namespace prefixes env_full_prefix = f"{ENV_NAMESPACE}{NAMESPACE_SEP}" openai_full_prefix = f"{OPENAI_NAMESPACE}{NAMESPACE_SEP}" + # Create Pydantic model classes with the 'process' mode defaults applied. + # These adjusted classes will be used for final instantiation. env_config_cls_new_defaults = adjust_model_defaults( type(default_env_config), PROCESS_MODE_ENV_DEFAULT_CONFIG ) openai_config_cls_new_defaults = adjust_model_defaults( - OpenaiConfig, PROCESS_MODE_OPENAI_DEFAULT_CONFIG + OpenaiConfig, + PROCESS_MODE_OPENAI_DEFAULT_CONFIG, # Process always uses OpenaiConfig type ) server_manager_config_cls_new_defaults = adjust_model_defaults( ServerManagerConfig, PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG, ) + # Define the CLI configuration class dynamically class CliProcessConfig( get_prefixed_pydantic_model(env_config_cls_new_defaults, env_full_prefix), get_prefixed_pydantic_model( openai_config_cls_new_defaults, openai_full_prefix ), - server_manager_config_cls_new_defaults, + server_manager_config_cls_new_defaults, # Uses adjusted defaults Cmd, ): """ Configuration for the process command. + Supports overrides via YAML config file and CLI arguments. + Order of precedence: CLI > YAML > Class Defaults > Process Mode Defaults. """ config: str | None = Field( @@ -1038,42 +1171,46 @@ class BaseEnv(ABC): def run(self) -> None: """The logic to execute for the 'process' command.""" - # Setup environment configuration + # Set default wandb name if not provided and class has a name wandb_name_attr = f"{ENV_NAMESPACE}{NAMESPACE_SEP}wandb_name" - if getattr(self, wandb_name_attr) is None and cls.name is not None: + if ( + getattr(self, wandb_name_attr, None) is None + and cls.name is not None + ): setattr(self, wandb_name_attr, cls.name) + # Load configuration from YAML file if specified if self.config is not None: with open(self.config, "r") as f: - config = yaml.safe_load(f) + yaml_config = yaml.safe_load(f) print(f"Loaded config from {self.config}") else: - config = {} + yaml_config = {} + # Get CLI flags passed with double dashes cli_passed_flags = get_double_dash_flags() - # cli args overrides config file which overrides class defaults which overrides process mode defaults - env_config = env_config_cls_new_defaults( - **merge_dicts( - default_env_config.model_dump(), - PROCESS_MODE_ENV_DEFAULT_CONFIG.model_dump(), - config.get(ENV_NAMESPACE, {}), - extract_namespace( - cli_passed_flags, env_full_prefix - ), # only extract namespace for cli-passed args - ) - ) - openai_config = openai_config_cls_new_defaults( - **merge_dicts( - default_openai_config.model_dump(), - PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), - config.get(OPENAI_NAMESPACE, {}), - extract_namespace( - cli_passed_flags, openai_full_prefix - ), # only extract namespace for cli-passed args - ) + # --- Configuration Merging --- + # Priority: CLI > YAML > Class Defaults > Process Mode Defaults + + # 1. Environment Configuration + env_config_dict = merge_dicts( + default_env_config.model_dump(), # Class Defaults + PROCESS_MODE_ENV_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults + yaml_config.get(ENV_NAMESPACE, {}), # YAML config + extract_namespace(cli_passed_flags, env_full_prefix), # CLI args ) + # 2. OpenAI Configuration + openai_config_dict = merge_dicts( + default_openai_config.model_dump(), # Class Defaults (adjusted to be OpenaiConfig) + PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults + yaml_config.get(OPENAI_NAMESPACE, {}), # YAML config + extract_namespace(cli_passed_flags, openai_full_prefix), # CLI args + ) + + # 3. Server Manager Configuration + # Extract only relevant CLI flags server_manager_cli_passed_flags = {} if "slurm" in cli_passed_flags: server_manager_cli_passed_flags["slurm"] = cli_passed_flags["slurm"] @@ -1082,36 +1219,51 @@ class BaseEnv(ABC): "testing" ] - server_manager_config = server_manager_config_cls_new_defaults( - **merge_dicts( - ServerManagerConfig().model_dump(), - PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG.model_dump(), - config.get(SERVER_MANAGER_NAMESPACE, {}), - server_manager_cli_passed_flags, - ) + server_manager_config_dict = merge_dicts( + ServerManagerConfig().model_dump(), # Base defaults + PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults + yaml_config.get(SERVER_MANAGER_NAMESPACE, {}), # YAML config + server_manager_cli_passed_flags, # CLI args ) + # --- Instantiate Final Config Objects --- + # Use the classes with adjusted defaults for instantiation + + env_config = env_config_cls_new_defaults(**env_config_dict) + openai_config = openai_config_cls_new_defaults(**openai_config_dict) + server_manager_config = server_manager_config_cls_new_defaults( + **server_manager_config_dict + ) + + # --- Create and Run Environment --- # Create the environment instance env = cls( config=env_config, + # Process mode always uses a single OpenAI config, passed as a list server_configs=[openai_config], slurm=server_manager_config.slurm, testing=server_manager_config.testing, ) - # Set the process mode parameters + # Set specific parameters for process mode on the environment instance env.process_mode = True env.n_groups_to_process = env_config.total_steps env.group_size_to_process = env_config.group_size + # Validate that an output path is set (should have a default from PROCESS_MODE_ENV_DEFAULT_CONFIG) + if env_config.data_path_to_save_groups is None: + # This check might be redundant if the default is always set, but good practice. + raise ValueError( + "data_path_to_save_groups must be set for process mode" + ) + print( f"Processing {env_config.total_steps} groups of " f"{env_config.group_size} responses and " f"writing to {env_config.data_path_to_save_groups}" ) + # Run the environment's asynchronous process manager function asyncio.run(env.process_manager()) - # Actual implementation would go here - return CliProcessConfig From fe616ec7fa281343b117164f6df0bf4af3ba06bd Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 05:28:40 -0400 Subject: [PATCH 02/13] add exceptions --- atroposlib/envs/base.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 65a41581..c8aaf53a 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -684,7 +684,19 @@ class BaseEnv(ABC): f"{self.config.rollout_server_url}/status-env", json={"env_id": self.env_id}, ) as resp: - self.status_dict = await resp.json() + try: + # Raise an exception for bad status codes (4xx or 5xx) + resp.raise_for_status() + # Attempt to parse the response as JSON + self.status_dict = await resp.json() + except Exception as e: + # Handle HTTP errors (raised by raise_for_status) + error_text = await resp.text() # Read the response text for logging + logger.error( + f"Error fetching status from rollout server. Status: {e.status}, Message: {e.message}. Response: {error_text}" # noqa: E501 + ) + # Re-raise the exception to allow the @retry decorator to handle it + raise new_weight = self.status_dict["env_weight"] max_num_workers = self.config.max_num_workers if max_num_workers == -1: From 4348dd2ec1709d647aaca43012e86a3aba934cfe Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 14:18:50 -0700 Subject: [PATCH 03/13] hide complicated openai config override behavior somewhere else --- atroposlib/envs/base.py | 107 +++++++++++------- .../envs/server_handling/openai_server.py | 79 +++++++++++++ environments/configs/example.yaml | 21 ++++ 3 files changed, 166 insertions(+), 41 deletions(-) create mode 100644 environments/configs/example.yaml diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index c8aaf53a..2c2c8612 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -20,15 +20,12 @@ import wandb import yaml from pydantic import BaseModel, Field from pydantic_cli import Cmd, FailedExecutionException, run_and_exit +from rich import print as rprint from tenacity import retry, stop_after_attempt, wait_random_exponential from transformers import AutoTokenizer -from atroposlib.envs.constants import ( - ENV_NAMESPACE, - NAMESPACE_SEP, - OPENAI_NAMESPACE, - SERVER_MANAGER_NAMESPACE, -) +from atroposlib.envs.constants import ENV_NAMESPACE, NAMESPACE_SEP, OPENAI_NAMESPACE +from atroposlib.envs.server_handling.openai_server import resolve_openai_configs from atroposlib.frontend.jsonl2html import generate_html from atroposlib.type_definitions import UUID from atroposlib.utils.cli import ( @@ -1022,11 +1019,29 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration (used for potential overrides) - openai_config_dict = merge_dicts( - default_openai_config.model_dump(), # Default OpenaiConfig (or from class init) - yaml_config.get(OPENAI_NAMESPACE, {}), # YAML config - extract_namespace(cli_passed_flags, openai_full_prefix), # CLI args - ) + yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) + if ( + isinstance(default_openai_config, list) + and len(default_openai_config) == 1 + ): + # can't use the same var name because it shadows the class variable and we get an error + default_openai_config_ = default_openai_config[0] + else: + default_openai_config_ = default_openai_config + if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: + yaml_oai_config = yaml_oai_config[0] + if isinstance(default_openai_config, OpenaiConfig) and isinstance( + yaml_oai_config, dict + ): + openai_config_dict = merge_dicts( + default_openai_config_.model_dump(), # Default OpenaiConfig (or from class init) + yaml_oai_config, + extract_namespace( + cli_passed_flags, openai_full_prefix + ), # CLI args + ) + else: + openai_config_dict = {} # 3. Server Manager Configuration (slurm, testing - not namespaced) # Extract only relevant CLI flags for ServerManager @@ -1038,9 +1053,15 @@ class BaseEnv(ABC): "testing" ] + server_manager_yaml_dict = {} + if "slurm" in yaml_config: + server_manager_yaml_dict["slurm"] = yaml_config["slurm"] + if "testing" in yaml_config: + server_manager_yaml_dict["testing"] = yaml_config["testing"] + server_manager_config_dict = merge_dicts( ServerManagerConfig().model_dump(), # Base defaults for ServerManager - yaml_config.get(SERVER_MANAGER_NAMESPACE, {}), # YAML config + server_manager_yaml_dict, # YAML config server_manager_cli_passed_flags, # CLI args ) @@ -1055,40 +1076,26 @@ class BaseEnv(ABC): **server_manager_config_dict ) - # Determine the final server_configs based on the original default type from cls.config_init() - # This allows handling ServerBaseline, single OpenaiConfig, or list[OpenaiConfig] - server_configs = ( - default_server_configs # Start with the original default + # Determine the final server_configs, handling single, multiple servers, and overrides. + + openai_configs = resolve_openai_configs( + default_server_configs=default_server_configs, + openai_config_dict=openai_config_dict, + yaml_config=yaml_config, + cli_passed_flags=cli_passed_flags, + logger=logger, ) - if isinstance(default_server_configs, OpenaiConfig): - # If default was single OpenaiConfig, update it with merged values - server_configs = OpenaiConfig(**openai_config_dict) - elif isinstance(default_server_configs, list): - # If default was list (presumably of OpenaiConfig), update the first or create one - # This assumes the primary server config is the one overridden via CLI/YAML - if default_server_configs and isinstance( - default_server_configs[0], OpenaiConfig - ): - # Update the first element, keep others as they were - server_configs = [ - OpenaiConfig(**openai_config_dict) - ] + default_server_configs[1:] - else: - # If list was empty or didn't contain OpenaiConfig, create a new list with the merged config - server_configs = [OpenaiConfig(**openai_config_dict)] - # If default_server_configs was ServerBaseline, server_configs remains ServerBaseline, - # effectively ignoring the openai_config_dict unless the user explicitly provides - # OpenaiConfig settings via CLI/YAML, which would be captured but not used here unless - # the environment class's config_init returned an OpenaiConfig or list. # --- Create and Run Environment --- # Create the environment instance using the final, instantiated config objects env = cls( config=env_config, - server_configs=server_configs, + server_configs=openai_configs, slurm=server_manager_config.slurm, testing=server_manager_config.testing, ) + rprint(env_config) + rprint(openai_configs) # Run the environment's main asynchronous manager function asyncio.run(env.env_manager()) @@ -1231,10 +1238,16 @@ class BaseEnv(ABC): "testing" ] + server_manager_yaml_dict = {} + if "slurm" in yaml_config: + server_manager_yaml_dict["slurm"] = yaml_config["slurm"] + if "testing" in yaml_config: + server_manager_yaml_dict["testing"] = yaml_config["testing"] + server_manager_config_dict = merge_dicts( ServerManagerConfig().model_dump(), # Base defaults PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults - yaml_config.get(SERVER_MANAGER_NAMESPACE, {}), # YAML config + server_manager_yaml_dict, server_manager_cli_passed_flags, # CLI args ) @@ -1242,17 +1255,29 @@ class BaseEnv(ABC): # Use the classes with adjusted defaults for instantiation env_config = env_config_cls_new_defaults(**env_config_dict) - openai_config = openai_config_cls_new_defaults(**openai_config_dict) server_manager_config = server_manager_config_cls_new_defaults( **server_manager_config_dict ) + # Determine the final server_configs, handling single, multiple servers, and overrides. + + openai_configs = resolve_openai_configs( + default_server_configs=default_server_configs, + openai_config_dict=openai_config_dict, + yaml_config=yaml_config, + cli_passed_flags=cli_passed_flags, + logger=logger, + ) + + rprint(env_config) + rprint(openai_configs) + # --- Create and Run Environment --- # Create the environment instance env = cls( config=env_config, - # Process mode always uses a single OpenAI config, passed as a list - server_configs=[openai_config], + # Use the resolved configs (single or list) + server_configs=openai_configs, slurm=server_manager_config.slurm, testing=server_manager_config.testing, ) diff --git a/atroposlib/envs/server_handling/openai_server.py b/atroposlib/envs/server_handling/openai_server.py index 4a3562cb..f161869e 100644 --- a/atroposlib/envs/server_handling/openai_server.py +++ b/atroposlib/envs/server_handling/openai_server.py @@ -10,8 +10,11 @@ import openai from openai.types.chat.chat_completion import ChatCompletion from openai.types.completion import Completion from pydantic import BaseModel, Field +from pydantic_cli import FailedExecutionException from tenacity import retry, stop_after_attempt, wait_random_exponential +from atroposlib.envs.constants import NAMESPACE_SEP, OPENAI_NAMESPACE + class OpenaiConfig(BaseModel): """ @@ -294,3 +297,79 @@ class OpenAIServer: self.eval_request_timings.append(stat_dict["end"] - stat_dict["start"]) self.eval_attempts_list.append(stat_dict["attempts"]) return ret_data + + +def resolve_openai_configs( + default_server_configs, + openai_config_dict, + yaml_config, + cli_passed_flags, + logger, +): + """ + Helper to resolve the final server_configs, handling single, multiple servers, and overrides. + """ + from atroposlib.envs.server_handling.server_manager import ServerBaseline + + openai_full_prefix = f"{OPENAI_NAMESPACE}{NAMESPACE_SEP}" + openai_yaml_config = yaml_config.get(OPENAI_NAMESPACE, None) + openai_cli_config = { + k: v for k, v in cli_passed_flags.items() if k.startswith(openai_full_prefix) + } + + is_multi_server_yaml = ( + isinstance(openai_yaml_config, list) and len(openai_yaml_config) >= 2 + ) + is_multi_server_default = ( + (not is_multi_server_yaml) + and isinstance(default_server_configs, list) + and len(default_server_configs) >= 2 + ) + + if (is_multi_server_yaml or is_multi_server_default) and openai_cli_config: + raise FailedExecutionException( + f"CLI overrides for OpenAI settings (--{openai_full_prefix}*) are not supported " + f"when multiple servers are defined (either via YAML list under '{OPENAI_NAMESPACE}' " + "or a default list with length >= 2)." + ) + + if is_multi_server_yaml: + logger.info( + f"Using multi-server configuration defined in YAML under '{OPENAI_NAMESPACE}'." + ) + try: + server_configs = [OpenaiConfig(**cfg) for cfg in openai_yaml_config] + except Exception as e: + raise FailedExecutionException( + f"Error parsing multi-server OpenAI configuration from YAML under '{OPENAI_NAMESPACE}': {e}" + ) from e + elif isinstance(default_server_configs, ServerBaseline): + logger.info("Using ServerBaseline configuration.") + server_configs = default_server_configs + elif is_multi_server_default: + logger.info("Using default multi-server configuration (length >= 2).") + server_configs = default_server_configs + else: + logger.info( + "Using single OpenAI server configuration based on merged settings (default/YAML/CLI)." + ) + try: + final_openai_config = OpenaiConfig(**openai_config_dict) + except Exception as e: + raise FailedExecutionException( + f"Error creating final OpenAI configuration from merged settings: {e}\n" + f"Merged Dict: {openai_config_dict}" + ) from e + + if isinstance(default_server_configs, OpenaiConfig): + server_configs = final_openai_config + elif isinstance(default_server_configs, list): + server_configs = [final_openai_config] + else: + logger.warning( + f"Unexpected type for default_server_configs: {type(default_server_configs)}. " + f"Proceeding with single OpenAI server configuration based on merged settings." + ) + server_configs = [final_openai_config] + + return server_configs diff --git a/environments/configs/example.yaml b/environments/configs/example.yaml new file mode 100644 index 00000000..680458cf --- /dev/null +++ b/environments/configs/example.yaml @@ -0,0 +1,21 @@ +# Environment configuration +env: + group_size: 4 + max_batches_offpolicy: 3 + tokenizer_name: "Qwen/Qwen2.5-1.5B-Instruct" + use_wandb: true + rollout_server_url: "http://localhost:8000" + wandb_name: "example_env" + ensure_scores_are_not_same: true + data_path_to_save_groups: null + include_messages: true # if data_path_to_save_groups is set this will add the messages to the saved .jsonl + +# OpenAI server configurations +openai: + - model_name: "Qwen/Qwen2.5-1.5B-Instruct" + base_url: "http://localhost:9001/v1" + api_key: "x" + weight: 1.0 + +slurm: false +testing: false From d1106f3b114ab2cfe52a4556171535422547141c Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 15:42:06 -0700 Subject: [PATCH 04/13] add rich dep --- README.md | 12 +++++++++--- pyproject.toml | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6fdaca77..ea70cae6 100644 --- a/README.md +++ b/README.md @@ -167,9 +167,15 @@ pre-commit install You should edit the config_init section of the environment file you want ([For example, in GSM8K Environment](https://github.com/NousResearch/atropos/blob/main/environments/gsm8k_server.py#L53)) to point to a running VLLM or SGLang inference server as well as any other configuration changes you'd like to make, such as the group size, then: ```bash - # Start the API server and run the GSM8K environment - run-api & python environments/gsm8k_server.py serve \ - --slurm false + # Start the API server + run-api + ``` + In a separate terminal, start the GSM8K environment microservice + ```bash + python environments/gsm8k_server.py serve --openai.model_name Qwen/Qwen2.5-1.5B-Instruct --slurm false + # alternatively + # python environments/gsm8k_server.py serve --config configs/example.yaml + # python environments/gsm8k_server.py serve --config configs/example.yaml --env.group_size 8 # cli args override config settings ``` 3. **Query the the API (Optional)** diff --git a/pyproject.toml b/pyproject.toml index 50ad2c59..fb7eccea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ dependencies = [ "math-verify==0.7.0", "jinja2", "nltk", + "rich", "polars", "aiofiles", "jsonlines", From aa23f108578046b260d8a23a41a81ebec35eb939 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 15:52:13 -0700 Subject: [PATCH 05/13] remove try/except because handled in separate pr --- atroposlib/envs/base.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 2c2c8612..53160168 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -681,19 +681,7 @@ class BaseEnv(ABC): f"{self.config.rollout_server_url}/status-env", json={"env_id": self.env_id}, ) as resp: - try: - # Raise an exception for bad status codes (4xx or 5xx) - resp.raise_for_status() - # Attempt to parse the response as JSON - self.status_dict = await resp.json() - except Exception as e: - # Handle HTTP errors (raised by raise_for_status) - error_text = await resp.text() # Read the response text for logging - logger.error( - f"Error fetching status from rollout server. Status: {e.status}, Message: {e.message}. Response: {error_text}" # noqa: E501 - ) - # Re-raise the exception to allow the @retry decorator to handle it - raise + self.status_dict = await resp.json() new_weight = self.status_dict["env_weight"] max_num_workers = self.config.max_num_workers if max_num_workers == -1: From a4d8d7e875b28756e0f86d36fc63354399744ab2 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 15:58:17 -0700 Subject: [PATCH 06/13] remove spurious comments --- atroposlib/envs/base.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 53160168..fe660bac 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -1085,7 +1085,7 @@ class BaseEnv(ABC): rprint(env_config) rprint(openai_configs) - # Run the environment's main asynchronous manager function + # Run the environment asyncio.run(env.env_manager()) return CliServeConfig @@ -1105,17 +1105,16 @@ class BaseEnv(ABC): total_steps=2, ensure_scores_are_not_same=False, include_messages=True, - # Ensure a default path for process mode if not set by class/cli/yaml - data_path_to_save_groups="output_groups.jsonl", - use_wandb=False, # Typically disable wandb for simple processing + data_path_to_save_groups="data/{cls.name or 'groups'}.jsonl", + use_wandb=True, ) PROCESS_MODE_OPENAI_DEFAULT_CONFIG = OpenaiConfig( - model_name="gpt-4.1-nano", # A reasonable default for processing + model_name="gpt-4.1-nano", base_url=None, api_key=None, ) PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG = ServerManagerConfig( - slurm=False, # Usually run locally + slurm=False, testing=False, ) @@ -1149,26 +1148,25 @@ class BaseEnv(ABC): ) openai_config_cls_new_defaults = adjust_model_defaults( OpenaiConfig, - PROCESS_MODE_OPENAI_DEFAULT_CONFIG, # Process always uses OpenaiConfig type + PROCESS_MODE_OPENAI_DEFAULT_CONFIG, ) server_manager_config_cls_new_defaults = adjust_model_defaults( ServerManagerConfig, PROCESS_MODE_SERVER_MANAGER_DEFAULT_CONFIG, ) - # Define the CLI configuration class dynamically class CliProcessConfig( get_prefixed_pydantic_model(env_config_cls_new_defaults, env_full_prefix), get_prefixed_pydantic_model( openai_config_cls_new_defaults, openai_full_prefix ), - server_manager_config_cls_new_defaults, # Uses adjusted defaults + server_manager_config_cls_new_defaults, Cmd, ): """ Configuration for the process command. Supports overrides via YAML config file and CLI arguments. - Order of precedence: CLI > YAML > Class Defaults > Process Mode Defaults. + Order of precedence: CLI > YAML > Process Mode Defaults > `config_init` defaults. """ config: str | None = Field( @@ -1198,7 +1196,7 @@ class BaseEnv(ABC): cli_passed_flags = get_double_dash_flags() # --- Configuration Merging --- - # Priority: CLI > YAML > Class Defaults > Process Mode Defaults + # Priority: CLI > YAML > Process Mode Defaults > `config_init` defaults # 1. Environment Configuration env_config_dict = merge_dicts( @@ -1264,7 +1262,6 @@ class BaseEnv(ABC): # Create the environment instance env = cls( config=env_config, - # Use the resolved configs (single or list) server_configs=openai_configs, slurm=server_manager_config.slurm, testing=server_manager_config.testing, From ae24b022c3acfc5b0b18633320556068a7cdc9b8 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 16:24:35 -0700 Subject: [PATCH 07/13] fix bug where None would be parsed as a str instead of special value --- atroposlib/envs/base.py | 55 ++++++++++++++++++++++------------------- atroposlib/utils/cli.py | 29 +++++++++++++++++----- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index fe660bac..f856db45 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -1018,7 +1018,7 @@ class BaseEnv(ABC): default_openai_config_ = default_openai_config if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: yaml_oai_config = yaml_oai_config[0] - if isinstance(default_openai_config, OpenaiConfig) and isinstance( + if isinstance(default_openai_config_, OpenaiConfig) and isinstance( yaml_oai_config, dict ): openai_config_dict = merge_dicts( @@ -1119,23 +1119,10 @@ class BaseEnv(ABC): ) # Get the base default configurations from the specific environment class - default_env_config, default_server_configs = cls.config_init() - - # Ensure default_openai_config is a single instance for default merging logic. - # Process mode specifically uses OpenaiConfig, so we establish a base default. - if isinstance(default_server_configs, list): - # Use the first if available and is OpenaiConfig, otherwise use a base OpenaiConfig - default_openai_config = ( - default_server_configs[0] - if default_server_configs - and isinstance(default_server_configs[0], OpenaiConfig) - else OpenaiConfig() - ) - elif isinstance(default_server_configs, OpenaiConfig): - default_openai_config = default_server_configs - else: - # If config_init returned ServerBaseline or something else, use a base OpenaiConfig for defaults - default_openai_config = OpenaiConfig() + ( + default_env_config, + default_openai_config, + ) = cls.config_init() # Define namespace prefixes env_full_prefix = f"{ENV_NAMESPACE}{NAMESPACE_SEP}" @@ -1207,12 +1194,30 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration - openai_config_dict = merge_dicts( - default_openai_config.model_dump(), # Class Defaults (adjusted to be OpenaiConfig) - PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults - yaml_config.get(OPENAI_NAMESPACE, {}), # YAML config - extract_namespace(cli_passed_flags, openai_full_prefix), # CLI args - ) + if ( + isinstance(default_openai_config, list) + and len(default_openai_config) == 1 + ): + # can't use the same var name because it shadows the class variable and we get an error + default_openai_config_ = default_openai_config[0] + else: + default_openai_config_ = default_openai_config + yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) + if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: + yaml_oai_config = yaml_oai_config[0] + if isinstance(default_openai_config_, OpenaiConfig) and isinstance( + yaml_oai_config, dict + ): + openai_config_dict = merge_dicts( + default_openai_config_.model_dump(), # Default OpenaiConfig (or from class init) + PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults + yaml_oai_config, + extract_namespace( + cli_passed_flags, openai_full_prefix + ), # CLI args + ) + else: + openai_config_dict = {} # 3. Server Manager Configuration # Extract only relevant CLI flags @@ -1248,7 +1253,7 @@ class BaseEnv(ABC): # Determine the final server_configs, handling single, multiple servers, and overrides. openai_configs = resolve_openai_configs( - default_server_configs=default_server_configs, + default_server_configs=default_openai_config, openai_config_dict=openai_config_dict, yaml_config=yaml_config, cli_passed_flags=cli_passed_flags, diff --git a/atroposlib/utils/cli.py b/atroposlib/utils/cli.py index a20b6d6d..1ca6082f 100644 --- a/atroposlib/utils/cli.py +++ b/atroposlib/utils/cli.py @@ -156,24 +156,41 @@ def get_double_dash_flags() -> Dict[str, Any]: # Remove '--' prefix key_part = arg[2:] + key = "" + value_str = ( + None # Variable to hold the string value before potential conversion + ) # Check for '--key=value' format if "=" in key_part: - key, value = key_part.split("=", 1) - if key: # Ensure key is not empty (e.g. --=value) - flags_dict[key] = value + key, value_str = key_part.split("=", 1) + if not key: # Ensure key is not empty (e.g. --=value) + i += 1 + continue # Skip if key is empty + + # Process value: Convert "None" string to None object + if value_str == "None": + flags_dict[key] = None + else: + flags_dict[key] = value_str i += 1 # Check if next argument exists and is a value (doesn't start with '-') elif i + 1 < len(args) and not args[i + 1].startswith("-"): key = key_part - value = args[i + 1] - flags_dict[key] = value + value_str = args[i + 1] + + # Process value: Convert "None" string to None object + if value_str == "None": + flags_dict[key] = None + else: + flags_dict[key] = value_str # Skip the next argument since we've consumed it as a value i += 2 # Otherwise, treat as a boolean flag else: key = key_part - flags_dict[key] = True + if key: # Ensure key is not empty (e.g. just '--') + flags_dict[key] = True i += 1 return flags_dict From 1d35b9d6265add5ab33775d89103b7a6ab24e252 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Sat, 3 May 2025 16:26:35 -0700 Subject: [PATCH 08/13] remove comment --- atroposlib/envs/base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index f856db45..0d3fe8f9 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -1212,9 +1212,7 @@ class BaseEnv(ABC): default_openai_config_.model_dump(), # Default OpenaiConfig (or from class init) PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults yaml_oai_config, - extract_namespace( - cli_passed_flags, openai_full_prefix - ), # CLI args + extract_namespace(cli_passed_flags, openai_full_prefix), ) else: openai_config_dict = {} From 38575d7029f92a2340fc89c1e003bfd38d1616cb Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Tue, 6 May 2025 22:29:34 -0400 Subject: [PATCH 09/13] not supported warning for server baseline --- README.md | 4 ++-- atroposlib/envs/base.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea70cae6..63c4a726 100644 --- a/README.md +++ b/README.md @@ -174,8 +174,8 @@ pre-commit install ```bash python environments/gsm8k_server.py serve --openai.model_name Qwen/Qwen2.5-1.5B-Instruct --slurm false # alternatively - # python environments/gsm8k_server.py serve --config configs/example.yaml - # python environments/gsm8k_server.py serve --config configs/example.yaml --env.group_size 8 # cli args override config settings + # python environments/gsm8k_server.py serve --config environments/configs/example.yaml + # python environments/gsm8k_server.py serve --config environments/configs/example.yaml --env.group_size 8 # cli args override corresponding config settings ``` 3. **Query the the API (Optional)** diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 0d3fe8f9..6e51ed73 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -996,6 +996,13 @@ class BaseEnv(ABC): # Get CLI flags passed with double dashes (e.g., --env--foo bar) cli_passed_flags = get_double_dash_flags() + if cli_passed_flags and isinstance( + default_server_configs, ServerBaseline + ): + raise ValueError( + "ServerBaseline currently does not support CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 + ) + # --- Configuration Merging --- # Priority: CLI > YAML > Class Defaults @@ -1182,6 +1189,13 @@ class BaseEnv(ABC): # Get CLI flags passed with double dashes cli_passed_flags = get_double_dash_flags() + if cli_passed_flags and isinstance( + default_openai_config, ServerBaseline + ): + raise ValueError( + "ServerBaseline currently does not support CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 + ) + # --- Configuration Merging --- # Priority: CLI > YAML > Process Mode Defaults > `config_init` defaults From ec6b86bb5d6142cb504cc0f80ab2cbafc940c6f2 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Wed, 7 May 2025 14:51:51 -0400 Subject: [PATCH 10/13] unbreak ServerBaseline --- atroposlib/envs/base.py | 54 ++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 6e51ed73..bdab19bf 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -939,17 +939,6 @@ class BaseEnv(ABC): # Get the default configurations defined by the specific environment class default_env_config, default_server_configs = cls.config_init() - # Determine a default OpenaiConfig instance for merging purposes, - # even if the actual default is ServerBaseline or a list. - # This allows overriding with OpenAI settings via CLI/YAML consistently. - default_openai_config = OpenaiConfig() # Base default - if isinstance(default_server_configs, OpenaiConfig): - default_openai_config = default_server_configs - elif isinstance(default_server_configs, list) and default_server_configs: - # If the default is a list, use the first item if it's OpenaiConfig - if isinstance(default_server_configs[0], OpenaiConfig): - default_openai_config = default_server_configs[0] - # Define namespace prefixes for CLI arguments and YAML keys env_full_prefix = f"{ENV_NAMESPACE}{NAMESPACE_SEP}" openai_full_prefix = f"{OPENAI_NAMESPACE}{NAMESPACE_SEP}" @@ -996,13 +985,6 @@ class BaseEnv(ABC): # Get CLI flags passed with double dashes (e.g., --env--foo bar) cli_passed_flags = get_double_dash_flags() - if cli_passed_flags and isinstance( - default_server_configs, ServerBaseline - ): - raise ValueError( - "ServerBaseline currently does not support CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 - ) - # --- Configuration Merging --- # Priority: CLI > YAML > Class Defaults @@ -1014,15 +996,22 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration (used for potential overrides) + oai_cli_passed_args = ( + extract_namespace(cli_passed_flags, openai_full_prefix), + ) # CLI args yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) + if oai_cli_passed_args or yaml_oai_config: + raise ValueError( + "ServerBaseline is not compatible with OpenAI-namespaced CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 + ) if ( - isinstance(default_openai_config, list) - and len(default_openai_config) == 1 + isinstance(default_server_configs, list) + and len(default_server_configs) == 1 ): # can't use the same var name because it shadows the class variable and we get an error - default_openai_config_ = default_openai_config[0] + default_openai_config_ = default_server_configs[0] else: - default_openai_config_ = default_openai_config + default_openai_config_ = default_server_configs if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: yaml_oai_config = yaml_oai_config[0] if isinstance(default_openai_config_, OpenaiConfig) and isinstance( @@ -1031,9 +1020,7 @@ class BaseEnv(ABC): openai_config_dict = merge_dicts( default_openai_config_.model_dump(), # Default OpenaiConfig (or from class init) yaml_oai_config, - extract_namespace( - cli_passed_flags, openai_full_prefix - ), # CLI args + oai_cli_passed_args, ) else: openai_config_dict = {} @@ -1189,13 +1176,6 @@ class BaseEnv(ABC): # Get CLI flags passed with double dashes cli_passed_flags = get_double_dash_flags() - if cli_passed_flags and isinstance( - default_openai_config, ServerBaseline - ): - raise ValueError( - "ServerBaseline currently does not support CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 - ) - # --- Configuration Merging --- # Priority: CLI > YAML > Process Mode Defaults > `config_init` defaults @@ -1208,6 +1188,15 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration + oai_cli_passed_args = ( + extract_namespace(cli_passed_flags, openai_full_prefix), + ) # CLI args + yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) + if oai_cli_passed_args or yaml_oai_config: + raise ValueError( + "ServerBaseline is not compatible with OpenAI-namespaced CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 + ) + if ( isinstance(default_openai_config, list) and len(default_openai_config) == 1 @@ -1216,7 +1205,6 @@ class BaseEnv(ABC): default_openai_config_ = default_openai_config[0] else: default_openai_config_ = default_openai_config - yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: yaml_oai_config = yaml_oai_config[0] if isinstance(default_openai_config_, OpenaiConfig) and isinstance( From 0373005175e113d21a7340c884a59c9e80d983cc Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Wed, 7 May 2025 15:09:34 -0400 Subject: [PATCH 11/13] forgot to condition on is ServerBaseline instance --- atroposlib/envs/base.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index bdab19bf..7b4eab14 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -1000,7 +1000,9 @@ class BaseEnv(ABC): extract_namespace(cli_passed_flags, openai_full_prefix), ) # CLI args yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) - if oai_cli_passed_args or yaml_oai_config: + if isinstance(default_server_configs, ServerBaseline) and ( + oai_cli_passed_args or yaml_oai_config + ): raise ValueError( "ServerBaseline is not compatible with OpenAI-namespaced CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 ) @@ -1115,7 +1117,7 @@ class BaseEnv(ABC): # Get the base default configurations from the specific environment class ( default_env_config, - default_openai_config, + default_server_configs, ) = cls.config_init() # Define namespace prefixes @@ -1192,19 +1194,21 @@ class BaseEnv(ABC): extract_namespace(cli_passed_flags, openai_full_prefix), ) # CLI args yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) - if oai_cli_passed_args or yaml_oai_config: + if isinstance(default_server_configs, ServerBaseline) and ( + oai_cli_passed_args or yaml_oai_config + ): raise ValueError( "ServerBaseline is not compatible with OpenAI-namespaced CLI arguments. Please edit `config_init` directly or use OpenaiConfig." # noqa: E501 ) if ( - isinstance(default_openai_config, list) - and len(default_openai_config) == 1 + isinstance(default_server_configs, list) + and len(default_server_configs) == 1 ): # can't use the same var name because it shadows the class variable and we get an error - default_openai_config_ = default_openai_config[0] + default_openai_config_ = default_server_configs[0] else: - default_openai_config_ = default_openai_config + default_openai_config_ = default_server_configs if isinstance(yaml_oai_config, list) and len(yaml_oai_config) == 1: yaml_oai_config = yaml_oai_config[0] if isinstance(default_openai_config_, OpenaiConfig) and isinstance( @@ -1253,7 +1257,7 @@ class BaseEnv(ABC): # Determine the final server_configs, handling single, multiple servers, and overrides. openai_configs = resolve_openai_configs( - default_server_configs=default_openai_config, + default_server_configs=default_server_configs, openai_config_dict=openai_config_dict, yaml_config=yaml_config, cli_passed_flags=cli_passed_flags, From cdf5a9baa9aa9181dea14718b2455bd759d48a19 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Wed, 7 May 2025 15:22:01 -0400 Subject: [PATCH 12/13] remove , --- atroposlib/envs/base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 7b4eab14..3b7f8c3c 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -996,8 +996,8 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration (used for potential overrides) - oai_cli_passed_args = ( - extract_namespace(cli_passed_flags, openai_full_prefix), + oai_cli_passed_args = extract_namespace( + cli_passed_flags, openai_full_prefix ) # CLI args yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) if isinstance(default_server_configs, ServerBaseline) and ( @@ -1190,8 +1190,8 @@ class BaseEnv(ABC): ) # 2. OpenAI Configuration - oai_cli_passed_args = ( - extract_namespace(cli_passed_flags, openai_full_prefix), + oai_cli_passed_args = extract_namespace( + cli_passed_flags, openai_full_prefix ) # CLI args yaml_oai_config = yaml_config.get(OPENAI_NAMESPACE, {}) if isinstance(default_server_configs, ServerBaseline) and ( @@ -1218,7 +1218,7 @@ class BaseEnv(ABC): default_openai_config_.model_dump(), # Default OpenaiConfig (or from class init) PROCESS_MODE_OPENAI_DEFAULT_CONFIG.model_dump(), # Process Mode Defaults yaml_oai_config, - extract_namespace(cli_passed_flags, openai_full_prefix), + oai_cli_passed_args, ) else: openai_config_dict = {} From 9415cadc53ffbd56e145fe793b7ee65a92e53e71 Mon Sep 17 00:00:00 2001 From: hjc-puro Date: Thu, 8 May 2025 06:54:43 -0700 Subject: [PATCH 13/13] fix cls name --- atroposlib/envs/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atroposlib/envs/base.py b/atroposlib/envs/base.py index 3b7f8c3c..cdc4a27b 100644 --- a/atroposlib/envs/base.py +++ b/atroposlib/envs/base.py @@ -1101,7 +1101,7 @@ class BaseEnv(ABC): total_steps=2, ensure_scores_are_not_same=False, include_messages=True, - data_path_to_save_groups="data/{cls.name or 'groups'}.jsonl", + data_path_to_save_groups=f"data/{cls.name or 'groups'}.jsonl", use_wandb=True, ) PROCESS_MODE_OPENAI_DEFAULT_CONFIG = OpenaiConfig(