1
Fork 0

fix: mypy complaints

This commit is contained in:
Tibo De Peuter 2026-04-08 23:37:01 +02:00
parent f6dc9c8e7f
commit 75c6d5bacd
Signed by: tdpeuter
SSH key fingerprint: SHA256:u/h/LVoqKF1Iz02uOyxe6hcjmoZASCGV2HM0TG9ZMoU
7 changed files with 26 additions and 23 deletions

View file

@ -10,7 +10,7 @@ from brittle_star_project.dataclasses import PPOArgs
from brittle_star_project.trainers.PPOTrainer import PPOTrainer from brittle_star_project.trainers.PPOTrainer import PPOTrainer
from brittle_star_project.environment.BrittleStarJaxEnvWrapper import BrittleStarJaxEnvWrapper from brittle_star_project.environment.BrittleStarJaxEnvWrapper import BrittleStarJaxEnvWrapper
from experiment_logger.unified_logger import get_logger from experiment_logger import UnifiedLogger
from experiment_logger.config_utils import merge_config_with_cli, print_config from experiment_logger.config_utils import merge_config_with_cli, print_config
@ -37,7 +37,7 @@ def get_git_hash() -> str:
return ( return (
subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode("ascii").strip() subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode("ascii").strip()
) )
except subprocess.CalledProcessError | UnicodeDecodeError: except (subprocess.CalledProcessError, UnicodeDecodeError):
return "none" return "none"
@ -59,8 +59,8 @@ if __name__ == "__main__":
os.makedirs(run_dir, exist_ok=True) os.makedirs(run_dir, exist_ok=True)
# Initialize Global Logger # Initialize Global Logger
logger = get_logger() logger = UnifiedLogger(
logger.init( config=vars(args),
project_name=args.wandb_project_name, # or default PPO-Modularity if missing project_name=args.wandb_project_name, # or default PPO-Modularity if missing
run_name=run_name, run_name=run_name,
base_dir=os.path.dirname(run_dir), base_dir=os.path.dirname(run_dir),

View file

@ -22,9 +22,6 @@ class PPOArgs:
# the directory to save the experiment results # the directory to save the experiment results
run_dir: str | None = None run_dir: str | None = None
# how often to save checkpoints (0 to disable)
checkpoint_frequency: int = 0
# seed of the experiment # seed of the experiment
seed: int = 1 seed: int = 1

View file

@ -36,6 +36,9 @@ def simulate_policy(
import mujoco.viewer import mujoco.viewer
if state is None:
raise ValueError("A valid environment state must be provided.")
model = state.mj_model model = state.mj_model
data = state.mj_data data = state.mj_data

View file

@ -312,14 +312,14 @@ class PPOTrainer:
def _init_episode_stats(self) -> EpisodeStatistics: def _init_episode_stats(self) -> EpisodeStatistics:
self.logger.info("[EPISODE STATS]: Initializing episode stats...") self.logger.info("[EPISODE STATS]: Initializing episode stats...")
return EpisodeStatistics( return EpisodeStatistics( # type: ignore[call-arg]
episode_returns=jnp.zeros(self.args.num_envs, dtype=jnp.float32), episode_returns=jnp.zeros(self.args.num_envs, dtype=jnp.float32),
episode_lengths=jnp.zeros(self.args.num_envs, dtype=jnp.int32), episode_lengths=jnp.zeros(self.args.num_envs, dtype=jnp.int32),
returned_episode_returns=jnp.zeros(self.args.num_envs, jnp.float32), returned_episode_returns=jnp.zeros(self.args.num_envs, jnp.float32),
returned_episode_lengths=jnp.zeros(self.args.num_envs, dtype=jnp.int32), returned_episode_lengths=jnp.zeros(self.args.num_envs, dtype=jnp.int32),
) )
def _rollout(self, env_state, next_obs, next_done) -> tuple[Storage, ...]: def _rollout(self, env_state, next_obs, next_done) -> tuple[Any, ...]:
return self._rollout_jit( return self._rollout_jit(
self.agent_state, self.agent_state,
self.episode_stats, self.episode_stats,

View file

@ -9,17 +9,20 @@ This library is designed to be a standalone package that decouples the logging l
The recommended way to use the logger is through the `get_logger()` singleton: The recommended way to use the logger is through the `get_logger()` singleton:
```python ```python
from experiment_logger import get_logger from experiment_logger import UnifiedLogger, get_logger
logger = get_logger()
# Initialize at the start of your script (e.g., in train.py) # Initialize at the start of your script (e.g., in train.py)
logger.init( logger = UnifiedLogger(
project_name="MyProject",
run_name="my_experiment_run", run_name="my_experiment_run",
config={"learning_rate": 3e-4},
project_name="MyProject",
base_dir="runs", base_dir="runs",
use_wandb=True use_wandb=True
) )
# In other files, retrieve the initialized singleton:
# logger = get_logger()
# Log metrics (Scalar values, numpy scalars, or JAX types) # Log metrics (Scalar values, numpy scalars, or JAX types)
logger.log({"loss": 0.5, "accuracy": 0.98}, step=100) logger.log({"loss": 0.5, "accuracy": 0.98}, step=100)

View file

@ -44,10 +44,10 @@ def dataclass_from_dict(cls: Type[T], config_dict: Dict[str, Any]) -> T:
raise ValueError(f"{cls} is not a dataclass") raise ValueError(f"{cls} is not a dataclass")
# Get field names and types # Get field names and types
field_map = {f.name: f for f in fields(cls)} field_map = {f.name: f for f in fields(cls)} # type: ignore
# Filter config to only include valid fields # Filter config to only include valid fields
filtered_config = {} filtered_config: Dict[str, Any] = {}
for key, value in config_dict.items(): for key, value in config_dict.items():
if key in field_map: if key in field_map:
field = field_map[key] field = field_map[key]
@ -64,7 +64,7 @@ def dataclass_from_dict(cls: Type[T], config_dict: Dict[str, Any]) -> T:
if field.type is bool and isinstance(value, str): if field.type is bool and isinstance(value, str):
filtered_config[key] = value.lower() in ("true", "1", "yes", "on") filtered_config[key] = value.lower() in ("true", "1", "yes", "on")
else: else:
filtered_config[key] = field.type(value) if value is not None else None filtered_config[key] = field.type(value) if value is not None else None # type: ignore
except (ValueError, TypeError) as e: except (ValueError, TypeError) as e:
log.warning(f"Could not convert {key}={value} to {field.type}: {e}") log.warning(f"Could not convert {key}={value} to {field.type}: {e}")
filtered_config[key] = value filtered_config[key] = value
@ -74,7 +74,7 @@ def dataclass_from_dict(cls: Type[T], config_dict: Dict[str, Any]) -> T:
return cls(**filtered_config) return cls(**filtered_config)
def merge_config_with_cli(config_class: Type[T], config_file: str = None) -> T: def merge_config_with_cli(config_class: Type[T], config_file: str | None = None) -> T:
"""Merge YAML config with CLI arguments, with CLI taking precedence. """Merge YAML config with CLI arguments, with CLI taking precedence.
Args: Args:
@ -107,16 +107,16 @@ def merge_config_with_cli(config_class: Type[T], config_file: str = None) -> T:
# Create default instance to know what the defaults are # Create default instance to know what the defaults are
default_instance = config_class() default_instance = config_class()
default_dict = {f.name: getattr(default_instance, f.name) for f in fields(config_class)} default_dict = {f.name: getattr(default_instance, f.name) for f in fields(config_class)} # type: ignore
# Parse CLI args # Parse CLI args
cli_instance = tyro.cli(config_class) cli_instance = tyro.cli(config_class)
cli_dict = {f.name: getattr(cli_instance, f.name) for f in fields(config_class)} cli_dict = {f.name: getattr(cli_instance, f.name) for f in fields(config_class)} # type: ignore
# Merge configs: YAML as base, CLI overrides non-default values # Merge configs: YAML as base, CLI overrides non-default values
final_config = {} final_config = {}
for field in fields(config_class): for field in fields(config_class): # type: ignore
field_name = field.name field_name = field.name
default_value = default_dict[field_name] default_value = default_dict[field_name]
yaml_value = yaml_config.get(field_name, default_value) yaml_value = yaml_config.get(field_name, default_value)

View file

@ -224,7 +224,7 @@ class UnifiedLogger:
self._log_to_stdout(metrics_with_metadata) self._log_to_stdout(metrics_with_metadata)
# Log to WandB # Log to WandB
if self.wandb_available: if self.wandb_run is not None:
try: try:
self.wandb_run.log(metrics, step=step, commit=commit) self.wandb_run.log(metrics, step=step, commit=commit)
except Exception as e: except Exception as e:
@ -306,7 +306,7 @@ class UnifiedLogger:
self.info(f"Checkpoint saved: {checkpoint_path}") self.info(f"Checkpoint saved: {checkpoint_path}")
# Log to WandB as artifact # Log to WandB as artifact
if self.wandb_available: if self.wandb_run is not None:
try: try:
import wandb import wandb
@ -342,7 +342,7 @@ class UnifiedLogger:
self.info(f"Final model saved: {final_model_path}") self.info(f"Final model saved: {final_model_path}")
# Log to WandB # Log to WandB
if self.wandb_available: if self.wandb_run is not None:
try: try:
import wandb import wandb