From 18316030fceecfd7c7fab7bced7174126167ccf9 Mon Sep 17 00:00:00 2001 From: Eugene Vinitsky Date: Fri, 24 Jul 2026 10:57:45 -0400 Subject: [PATCH] Remove drive.ini and default.ini; puffer_drive.yaml is the config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the Hydra switch, load_config composes puffer_drive.yaml — the ini files were dead config that still looked authoritative: editing them changed nothing at runtime, and their values silently diverged from the yaml. Delete both, along with the MANIFEST.in include that packaged them and the unused --config argument in metrics_sanity_check.py (load_config never read it). Comments, docstrings, error strings, and docs now point at puffer_drive.yaml; docs/evaluation.md's config-schema example is written in the yaml layout instead of ini sections. Co-Authored-By: Claude Fable 5 --- MANIFEST.in | 1 - README.md | 10 +- data_utils/fetch_data.py | 4 +- docs/data_storage.md | 2 +- docs/evaluation.md | 48 +- pufferlib/config/default.ini | 213 ------- pufferlib/config/ocean/drive.ini | 538 ------------------ pufferlib/config/puffer_drive.yaml | 7 +- .../ocean/benchmark/evaluators/__init__.py | 2 +- pufferlib/ocean/benchmark/evaluators/base.py | 2 +- .../ocean/benchmark/metrics_sanity_check.py | 1 - pufferlib/pufferl.py | 14 +- .../single_agent_speed_run.yaml | 2 +- scripts/cluster_configs/train_base.yaml | 2 +- 14 files changed, 48 insertions(+), 798 deletions(-) delete mode 100644 pufferlib/config/default.ini delete mode 100644 pufferlib/config/ocean/drive.ini diff --git a/MANIFEST.in b/MANIFEST.in index 7f6f85babc..8bc498003f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,7 +4,6 @@ global-include *.h global-include *.cpp global-include *.cu global-include *.py -recursive-include pufferlib/config *.ini recursive-include pufferlib/resources * recursive-exclude experiments * recursive-exclude wandb * diff --git a/README.md b/README.md index c4b3cdef02..f12ccfc735 100644 --- a/README.md +++ b/README.md @@ -231,9 +231,9 @@ To add a metric to the report: add its key to `TREND_METRICS` / `FINALS_METRICS` / `CURVE_METRICS` in `scripts/nightly_report.py`, then run `update` followed by `report`. -## Key Configuration (`pufferlib/config/ocean/drive.ini`) +## Key Configuration (`pufferlib/config/puffer_drive.yaml`) -### `[env]` — Simulation +### `env` — Simulation | Parameter | Default | Notes | |-----------|---------|-------| @@ -250,7 +250,7 @@ To add a metric to the report: add its key to `TREND_METRICS` / | `reward_conditioning` | `False` | Condition policy on reward weights | | `reward_randomization` | `False` | Randomize reward weights each episode | -### `[env]` — Reward Shaping +### `env` — Reward Shaping | Parameter | Default | Effect | |-----------|---------|--------| @@ -263,7 +263,7 @@ To add a metric to the report: add its key to `TREND_METRICS` / | `reward_stop_line` | `1.0` | Stop line penalty | | `reward_overspeed` | `0.05` | Speeding penalty | -### `[train]` — PPO +### `train` — PPO | Parameter | Default | Notes | |-----------|---------|-------| @@ -277,7 +277,7 @@ To add a metric to the report: add its key to `TREND_METRICS` / | `vtrace_rho_clip` / `vtrace_c_clip` | `1` | V-trace IS ratio clipping | | `adv_sampling_prio_alpha` / `adv_sampling_prio_beta0` | `0.85` | Priority sampling exponents | -### `[policy]` — Network +### `policy` — Network | Parameter | Default | Notes | |-----------|---------|-------| diff --git a/data_utils/fetch_data.py b/data_utils/fetch_data.py index 0ec285b1ef..f009911a4b 100644 --- a/data_utils/fetch_data.py +++ b/data_utils/fetch_data.py @@ -1,7 +1,7 @@ """Fetch shared PufferDrive datasets from S3. Datasets are declared in data_utils/datasets.yaml and sync into -/data// (gitignored), where the drive.ini defaults expect them. +/data// (gitignored), where the default config expects them. Fetching elsewhere (--data-root) means pointing env.map_dir there too. python data_utils/fetch_data.py # the default ~10 GB mini sets @@ -95,7 +95,7 @@ def main(): parser.add_argument( "--data-root", default=DEFAULT_DATA_ROOT, - help="destination root (default: /data, where the drive.ini defaults expect it)", + help="destination root (default: /data, where the default config expects it)", ) parser.add_argument("--dry-run", action="store_true", help="show what would be downloaded without writing") args = parser.parse_args() diff --git a/docs/data_storage.md b/docs/data_storage.md index 94aff77561..431b101ba9 100644 --- a/docs/data_storage.md +++ b/docs/data_storage.md @@ -6,7 +6,7 @@ lab's S3 buckets and pulled onto a machine for training and evaluation. ## Fetching data Datasets are registered in `data_utils/datasets.yaml` and land under -`/data/` (gitignored), where the `drive.ini` defaults expect them. +`/data/` (gitignored), where the default config expects them. Fetching elsewhere (`--data-root`) means pointing `env.map_dir` there too. ```bash diff --git a/docs/evaluation.md b/docs/evaluation.md index f02c7491b2..6cceff5a8d 100644 --- a/docs/evaluation.md +++ b/docs/evaluation.md @@ -8,10 +8,10 @@ training and standalone from the CLI — there is no second eval path. ## Concepts -- **Evaluator** — one evaluation, defined by an `[eval.]` section in - `pufferlib/config/ocean/drive.ini`. It owns an env config, a rollout, a set +- **Evaluator** — one evaluation, defined by an `eval.` section in + `pufferlib/config/puffer_drive.yaml`. It owns an env config, a rollout, a set of metrics, and optional rendering. -- **EvalManager** — discovers every `[eval.]` section, instantiates the +- **EvalManager** — discovers every `eval.` section, instantiates the evaluators, and runs the ones whose `interval` is due (inline) or that you name (standalone). One evaluator failing doesn't stop the rest. - **Evaluator types** (the `type` field): `multi_scenario` (sweep a scenario @@ -20,20 +20,24 @@ training and standalone from the CLI — there is no second eval path. ## Config schema -```ini -[eval.] -type = "multi_scenario" ; registered evaluator class (omit for a template) -enabled = true ; skip when false -interval = 250 ; run every N epochs inline (0 disables inline) -mode = "inline" ; "inline" (block training) | "subprocess" -inherits = "" ; optional: pull defaults from another section -clean = true ; zero perturbations/dropout + enforce red lights -render = true ; capture renders during the rollout -render_views = ["sim_state","bev"]; camera views for the egl backend -render_backend = "egl" ; egl | triage_html | obs_html (see Render backends) -env. = ; any [env] override (dotted) -eval. = ; evaluator-specific knob (see below) -vec. = ; any [vec] override +```yaml +eval: + : + type: multi_scenario # registered evaluator class (omit for a template) + enabled: 'true' # skip when false + interval: 250 # run every N epochs inline (0 disables inline) + mode: inline # inline (block training) | subprocess + inherits: # optional: pull defaults from another section + clean: 'true' # zero perturbations/dropout + enforce red lights + render: 'true' # capture renders during the rollout + render_views: [sim_state, bev] # camera views for the egl backend + render_backend: egl # egl | triage_html | obs_html (see Render backends) + env: # any env override + : + eval: # evaluator-specific knobs (see below) + : + vec: # any vec override + : ``` A section **without** a `type` is a *template*: it is never instantiated, only @@ -70,23 +74,23 @@ puffer eval puffer_drive --evaluator validation_gigaflow \ --load-model-path experiments/puffer_drive_xxxx/models/model_000500.pt ``` -Runs that one evaluator with its `[eval.validation_gigaflow]` config. The +Runs that one evaluator with its `eval.validation_gigaflow` config. The checkpoint's network architecture is read from the sibling `config.yaml` (next to `models/`), so a checkpoint loads even if its policy/rnn dims differ from -`drive.ini`. With no `--load-model-path`, a fresh (random) policy is used — +`puffer_drive.yaml`. With no `--load-model-path`, a fresh (random) policy is used — useful for smoke-testing the eval path itself. ### Standalone, ad-hoc Same as by-name, except instead of naming an evaluator you select one of the two built-in `validation_*` evaluators by simulation and override its config from the -CLI — no `drive.ini` edit needed: +CLI — no config edit needed: - `--eval_simulation gigaflow` → runs the `validation_gigaflow` section - `--eval_simulation replay` → runs the `validation_replay` section The flags below override that evaluator's config for this run, and each applies -**only when passed** — omit one and the evaluator's own `[eval.*]` value stands: +**only when passed** — omit one and the evaluator's own `eval.*` value stands: ```bash puffer eval puffer_drive --eval_simulation gigaflow \ @@ -162,7 +166,7 @@ weights and clean-eval knobs from the `validation_defaults` template. `evaluators/__init__.py`. Most subclasses only override `env_overrides`, `_should_stop`, and optionally `_render_env_overrides`; the base `rollout` handles the step loop, metric aggregation, CSV, and coverage. -2. Add an `[eval.]` section with `type = ""`. +2. Add an `eval.` section with `type: `. ## Scripts diff --git a/pufferlib/config/default.ini b/pufferlib/config/default.ini deleted file mode 100644 index 4cd37d10a4..0000000000 --- a/pufferlib/config/default.ini +++ /dev/null @@ -1,213 +0,0 @@ -[base] -package = None -env_name = None -policy_name = Policy -rnn_name = None -max_suggestion_cost = 3600 - -[vec] -backend = Multiprocessing -num_envs = 2 -num_workers = auto -batch_size = auto -zero_copy = True -seed = 42 - -[env] -[policy] -[rnn] - -[train] -name = pufferai -project = ablations - -seed = 42 -torch_deterministic = False -cpu_offload = False -device = cuda -optimizer = adamw -anneal_lr = True -amp = True -precision = float32 -total_timesteps = 10_000_000 -learning_rate = 0.015 -gamma = 0.995 -gae_lambda = 0.90 -update_epochs = 1 -clip_coef = 0.2 -vf_coef = 2.0 -vf_clip_coef = 0.2 -max_grad_norm = 1.5 -normalize_rewards = True -ent_coef = 0.001 -adam_beta1 = 0.95 -adam_beta2 = 0.999 -adam_eps = 1e-12 - -data_dir = experiments -resume_state_path = None -checkpoint_interval = 200 -batch_size = auto -minibatch_size = 8192 - -# Accumulate gradients above this size -max_minibatch_size = 32768 -bptt_horizon = 64 -compile = False -compile_mode = default -compile_fullgraph = False - -vtrace_rho_clip = 1.0 -vtrace_c_clip = 1.0 - -adv_sampling_prio_alpha = 0.8 -adv_sampling_prio_beta0 = 0.2 - -[sweep] -method = Protein -metric = score -goal = maximize -downsample = 10 - -#[sweep.vec.num_envs] -#distribution = uniform_pow2 -#min = 1 -#max = 16 -#mean = 8 -#scale = auto - -; # TODO: Elim from base -; [sweep.train.total_timesteps] -; distribution = log_normal -; min = 5e7 -; max = 1e10 -; mean = 1e8 -; scale = time - -; [sweep.train.bptt_horizon] -; distribution = uniform_pow2 -; min = 16 -; max = 64 -; mean = 64 -; scale = auto - -; [sweep.train.minibatch_size] -; distribution = uniform_pow2 -; min = 8192 -; max = 65536 -; mean = 32768 -; scale = auto - -; [sweep.train.learning_rate] -; distribution = log_normal -; min = 0.00001 -; mean = 0.01 -; max = 0.1 -; scale = 0.5 - -; [sweep.train.ent_coef] -; distribution = log_normal -; min = 0.00001 -; mean = 0.01 -; max = 0.2 -; scale = auto - -; [sweep.train.gamma] -; distribution = logit_normal -; min = 0.8 -; mean = 0.98 -; max = 0.9999 -; scale = auto - -; [sweep.train.gae_lambda] -; distribution = logit_normal -; min = 0.6 -; mean = 0.95 -; max = 0.995 -; scale = auto - -; [sweep.train.vtrace_rho_clip] -; distribution = uniform -; min = 0.0 -; max = 5.0 -; mean = 1.0 -; scale = auto - -; [sweep.train.vtrace_c_clip] -; distribution = uniform -; min = 0.0 -; max = 5.0 -; mean = 1.0 -; scale = auto - -; #[sweep.train.update_epochs] -; #distribution = int_uniform -; #min = 1 -; #max = 8 -; #mean = 1 -; #scale = 2.0 - -; [sweep.train.clip_coef] -; distribution = uniform -; min = 0.01 -; max = 1.0 -; mean = 0.2 -; scale = auto - -; # Optimal vf clip can be lower than 0.1, -; # but this results in jank unstable runs -; [sweep.train.vf_clip_coef] -; distribution = uniform -; min = 0.1 -; max = 5.0 -; mean = 0.2 -; scale = auto - -; [sweep.train.vf_coef] -; distribution = uniform -; min = 0.0 -; max = 5.0 -; mean = 2.0 -; scale = auto - -; [sweep.train.max_grad_norm] -; distribution = uniform -; min = 0.0 -; mean = 1.0 -; max = 5.0 -; scale = auto - -; [sweep.train.adam_beta1] -; distribution = logit_normal -; min = 0.5 -; mean = 0.9 -; max = 0.999 -; scale = auto - -; [sweep.train.adam_beta2] -; distribution = logit_normal -; min = 0.9 -; mean = 0.999 -; max = 0.99999 -; scale = auto - -; [sweep.train.adam_eps] -; distribution = log_normal -; min = 1e-14 -; mean = 1e-8 -; max = 1e-4 -; scale = auto - -; [sweep.train.adv_sampling_prio_alpha] -; distribution = logit_normal -; min = 0.1 -; mean = 0.85 -; max = 0.99 -; scale = auto - -; [sweep.train.adv_sampling_prio_beta0] -; distribution = logit_normal -; min = 0.1 -; mean = 0.85 -; max = 0.99 -; scale = auto diff --git a/pufferlib/config/ocean/drive.ini b/pufferlib/config/ocean/drive.ini deleted file mode 100644 index 6fa46e4452..0000000000 --- a/pufferlib/config/ocean/drive.ini +++ /dev/null @@ -1,538 +0,0 @@ -[base] -package = ocean -env_name = puffer_drive -policy_name = Drive -; Options: Recurrent, None -rnn_name = None - -[vec] -num_envs = 20 -num_workers = auto -batch_size = auto - -[policy] -; Encoder layer (per-encoder embedding width) -ego_input_size = 64 -partner_input_size = 64 -lane_input_size = 64 -boundary_input_size = 64 -traffic_control_input_size = 64 -context_input_size = 64 -; Encoder activation - options: "relu", "tanh", "gelu" -encoder_activation = "relu" -encoder_layer_norm = True -mask_padded_features = False -; Shared backbone layer -backbone_hidden_size = 512 -backbone_num_layers = 4 -; Backbone activation - options: "relu", "tanh", "gelu" -backbone_activation = "gelu" -backbone_layer_norm = False -; Actor head layer -actor_hidden_size = 512 -actor_num_layers = 0 -; Critic head layer -critic_hidden_size = 512 -critic_num_layers = 0 -; Dual or shared actor-critic backbone -shared_network = True - -[rnn] -input_size = 512 -hidden_size = 512 - -[env] -; --- Simulation --- -; Options: "gigaflow", "replay" -simulation_mode = "gigaflow" -; Total number of agents in the environment -num_agents = 1024 -; GIGAFLOW-specific: minimum/maximum number of agents per environment -min_agents_per_env = 1 -max_agents_per_env = 80 -; Actions type - options: "discrete", "continuous" -action_type = "discrete" -; Dynamics model - options: "classic", "jerk" -dynamics_model = "jerk" -; Time delta between steps in seconds -dt = 0.1 -; Optional nonzero launch speed for gigaflow random spawns -spawn_initial_speed = 0.0 -; Collision behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove -collision_behavior = 1 -; Offroad behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove -offroad_behavior = 1 -; Traffic light behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove -traffic_light_behavior = 1 -; Share static map geometry (roads/grid/lane-graph) across envs using the same map - 0 off, 1 on -use_map_cache = 0 -; Number of steps before reset -scenario_length = 1280 -; Frequency of resampling scenario (in steps), 0 to disable -resample_frequency = 12_800_0000 -; End of episode - options: 0 - scenario_length, 1 - early reset when too many agents are removed -termination_mode = 1 -; Ratio of inactive agents (stopped/removed) that triggers early reset (used when termination_mode = 1) -inactive_agent_threshold = 0.4 -; End the episode as soon as the agent reaches its final goal. Only active in -; control_sdc_only replay mode (single active agent). -terminate_on_goal = 0 -; Determines which step of the trajectory to initialize the agents at upon reset -init_step = 0 -; allows to initiate the C environment at random init points - works in replay mode only: -init_step_spread = False -; sets an upper bound on the random init step -; the sampled init step can be at most this close to the end of the episode; -init_step_min_horizon = 20 -; options: "control_vehicles", "control_agents", "control_tracks_to_predict", "control_sdc_only" -control_mode = "control_vehicles" -; Controller used by agent 0, the canonical SDC/target. -; options: "static", "policy", "replay", "idm" -sdc_controller = "policy" -; Controller used by non-SDC vehicles. -; options: "static", "policy", "replay", "idm" -non_sdc_controller = "policy" -; Controller used by non-vehicle agents. "auto" follows non_sdc_controller unless it is "idm", then it uses "replay". -; options: "auto", "static", "policy", "replay", "idm" -non_vehicle_controller = "auto" -; Options: "created_all_valid", "create_only_controlled" -init_mode = "create_all_valid" -; Enable computation of evaluation-only metrics -compute_eval_metrics = False - -; --- Goal --- -; Goal regeneration policy - options: "finite" (regen full set when all reached), "rolling" (sliding window) -goal_regen_mode = "finite" -; How the goal set is seeded - options: "route" (agent forward route), "map" (uniform free-roam) -goal_source = "route" -; Append normalized lane-graph distance to the current goal lane on each lane obs row -obs_goal_lane_distance = False -; Meters around goal to be considered "reached" -goal_radius = 2.0 -; Maximum speed at final waypoint to count goal reward -goal_speed = 1000.0 -; Number of goals shown in the observation (the goal window size) -num_goals = 3 -; Goal spacing range (m) sampled directly between consecutive goals along the route or after first sampled goal on the map -min_goal_spacing = 20.0 -max_goal_spacing = 60.0 - -; --- Rewards --- -reward_conditioning = False -reward_randomization = False -reward_goal = 1.0 -reward_collision = 1.5 -reward_offroad = 1.5 -reward_stop_line = 1.0 -reward_comfort = 0.05 -reward_lane_align = 0.025 -reward_vel_align = 1.0 -reward_lane_center = 0.0038 -reward_center_bias = 0.0 -reward_velocity = 0.0025 -reward_reverse = 0.005 -reward_timestep = 0.000025 -reward_overspeed = 0.05 -reward_ade = 0.0 - -; --- Map --- -; Path to map used for training -map_dir = "pufferlib/resources/drive/binaries/carla" -; Number of maps to load from map_dir -num_maps = 8 - -; --- Observation slot counts --- -obs_slots_lane_n = 80 -obs_slots_boundary_n = 80 -obs_slots_partners_n = 16 -obs_slots_traffic_controls_n = 4 -; Fraction of segment observation slots to drop (reduces obs size) -obs_dropout_lane = 0.0 -obs_dropout_boundary = 0.0 -; Stride for lane and boundary segments; 1 means use every segment, 2 means use every other segment, etc. -obs_lane_stride = 1 -obs_boundary_stride = 1 -; --- Observation normalization --- -obs_norm_goal_offset_m = 120.0 -obs_norm_xy_offset_m = 120.0 -obs_norm_veh_length_m = 15.0 -obs_norm_veh_width_m = 10.0 -obs_norm_road_seg_length_m = 10.0 -obs_norm_road_seg_width_m = 5.0 -; --- Observation ranges (meters, ego frame) --- -obs_range_road_front_m = 120.0 -obs_range_road_behind_m = 20.0 -obs_range_road_side_m = 30.0 -obs_range_partner_m = 100.0 -obs_range_traffic_control_m = 100.0 - -; --- Robustness features--- -; Erratic agents are selected once per episode; masked out of the PPO rollout buffer. -; Per-episode probability that an agent is blind to other agents for the whole episode -partner_blindness_prob = 0.0 -; Per-step probability that a flagged blind-partner agent zeros out its partner observations -partner_blindness_trigger_prob = 0.0 -; Per-episode probability that an agent is flagged as a phantom braker for the whole episode -phantom_braking_prob = 0.0 -; Per-step probability that a flagged phantom-braker actually initiates a brake window -phantom_braking_trigger_prob = 0.0 -; Duration (in steps) of phantom braking once triggered -phantom_braking_duration = 10 - -[train] -total_timesteps = 10_000_000_000 -checkpoint_interval = 50 -anneal_lr = True -; batch_size = num_workers * num_agents * bptt_horizon -batch_size = auto -minibatch_size = 65_536 -max_minibatch_size = 65_536 -bptt_horizon = 128 -learning_rate = 0.0005 -gae_lambda = 0.95 -gamma = 0.999 -ent_coef = 0.01 -clip_coef = 0.2 -max_grad_norm = 0.5 -vf_clip_coef = None -vf_coef = 0.5 -update_epochs = 2 -normalize_rewards = True -; --- -adam_beta1 = 0.9 -adam_beta2 = 0.999 -adam_eps = 1e-8 -vtrace_c_clip = 1 -vtrace_rho_clip = 1 -adv_sampling_prio_alpha = 0.8499999999999999 -adv_sampling_prio_beta0 = 0.8499999999999999 -adv_filter_ewma_beta = 0.25 -adv_filter_threshold_scale = 0.01 -; Rendering options -render = False -render_interval = 1000 -; If True, show exactly what the agent sees in agent observation -obs_only = True -; Show grid lines -show_grid = False -; Draws lines from ego agent observed ORUs and road elements to show detection range -show_lasers = False -; Display human xy logs in the background -show_human_logs = True -; Options: List[str to path], str to path (e.g., "resources/drive/training/binaries/map_001.bin"), None -render_map = none - -; =========================================================================== -; Evaluation suites -; -; Each [eval.] section is one Evaluator instance. EvalManager discovers -; them via auto-discovery (any section under [eval] with a `type` field). -; Sections without a `type` field are templates — referenced from other -; sections via `inherits = ""`. -; -; Field reference: -; type — registered evaluator class (multi_scenario, behavior_class, -; human_replay, wosac) -; enabled — true|false -; interval — epochs between runs (0 disables) -; mode — "inline" (block training) | "subprocess" (spawn process) -; inherits — pull defaults from another section, recursively -; clean — true → zero perturbations + dropout + enforce red lights -; render — true → capture mp4(s) during rollout -; render_views — list of camera views: sim_state, bev, topdown_sim, bev_all -; env. — any [env] override (dotted key) -; eval. — evaluator-specific knob (e.g. num_scenarios) -; vec. — any [vec] override -; =========================================================================== - -[mine] -; Failure-mining workflow. `puffer mine_failures puffer_drive ...` -; rolls a trained policy out N times and writes compact-replay HTML -; for episodes whose episode_return is strictly below score_threshold. -output_dir = "" -num_episodes = 100 -score_threshold = -inf -render = true - -; --------------------------------------------------------------------------- -; Multi-scenario validation eval. validation_defaults holds the shared -; clean-eval env + fixed eval reward weights; the replay / gigaflow sections -; add their sim-specific map set and agent layout. Each sweeps 250 scenarios, -; ignores traffic lights, and disables reward randomization so metrics are -; comparable across checkpoints. Both write a per-episode CSV and a coverage -; report (episode_metrics/). -; --------------------------------------------------------------------------- - -[eval.validation_defaults] -enabled = true -interval = 250 -mode = "inline" -clean = true -env.eval_mode = 1 -env.collision_behavior = 1 -env.offroad_behavior = 1 -; Explicit 0 wins over the clean macro's red-light enforcement. -env.traffic_light_behavior = 0 -env.reward_randomization = False -env.termination_mode = 0 -env.num_agents = 1024 -env.goal_regen_mode = finite -env.goal_source = route -env.goal_speed = 3.0 -env.reward_collision = 3.0 -env.reward_offroad = 3.0 -env.reward_stop_line = 1.0 -env.reward_goal = 1.0 -env.reward_overspeed = 0.05 -env.reward_comfort = 0.05 -env.reward_velocity = 0.0025 -env.reward_lane_align = 0.025 -env.reward_lane_center = 0.0038 -env.reward_timestep = 0.000025 -env.reward_reverse = 0.005 -env.reward_ade = 0.0 -env.obs_dropout_lane = 0.0 -env.obs_dropout_boundary = 0.0 -env.obs_slots_lane_n = 80 -env.obs_slots_boundary_n = 80 -eval.num_scenarios = 250 -eval.export_episode_csv = true -eval.verify_coverage = true - -[eval.validation_replay] -inherits = "validation_defaults" -type = "multi_scenario" -enabled = false -render = true -render_backend = "triage_html" -env.simulation_mode = "replay" -env.control_mode = "control_sdc_only" -env.map_dir = "data/nuplan_mini_val" -env.num_maps = 250 -env.max_agents_per_env = 64 -env.scenario_length = 200 -env.resample_frequency = 200 -eval.render_num_scenarios = 5 -eval.render_max_steps = 200 - -[eval.validation_gigaflow] -inherits = "validation_defaults" -type = "multi_scenario" -enabled = true -render = true -render_backend = "egl" -render_views = ["sim_state", "bev"] -env.simulation_mode = "gigaflow" -env.map_dir = "pufferlib/resources/drive/binaries/carla" -env.num_maps = 8 -env.num_agents = 1024 -env.min_agents_per_env = 40 -env.max_agents_per_env = 40 -env.scenario_length = 500 -env.resample_frequency = 500 -eval.render_num_scenarios = 8 -eval.render_max_steps = 300 - -[eval.dnf_triage] -inherits = "validation_defaults" -type = "multi_scenario" -enabled = false -render = true -render_backend = "triage_html" -env.simulation_mode = "gigaflow" -env.map_dir = "pufferlib/resources/drive/binaries/carla/opendrive__Town10HD.bin" -env.num_maps = 1 -env.min_agents_per_env = 1 -env.max_agents_per_env = 1 -env.scenario_length = 500 -env.resample_frequency = 500 -eval.num_scenarios = 32 -eval.render_num_scenarios = 16 -eval.render_max_steps = 300 - -; --------------------------------------------------------------------------- -; Optional: WOSAC realism eval. Off by default. -; --------------------------------------------------------------------------- - -[eval.wosac] -type = "wosac" -enabled = false -interval = 500 -mode = "subprocess" -clean = true -render = false -env.control_mode = "control_wosac" -env.init_mode = "create_all_valid" -env.init_step = 10 -env.goal_radius = 2.0 -eval.wosac_num_rollouts = 32 -eval.wosac_num_agents = 256 -eval.wosac_sanity_check = false -eval.wosac_aggregate_results = true - -; [sweep.train.learning_rate] -; distribution = log_normal -; min = 0.0001 -; mean = 0.001 -; max = 0.002 -; scale = auto - -; [sweep.train.ent_coef] -; distribution = log_normal -; min = 0.0005 -; mean = 0.01 -; max = 0.02 -; scale = auto - -; [sweep.train.vf_clip_coef] -; distribution = log_normal -; min = 0.1 -; mean = 0.2 -; max = 3 -; scale = auto - -; [sweep.env.inactive_agent_threshold] -; distribution = log_normal -; min = 0.1 -; mean = 0.4 -; max = 1.0 -; scale = auto - -; [sweep.train.gamma] -; distribution = logit_normal -; min = 0.90 -; mean = 0.99 -; max = 0.9999 -; scale = auto - -; [sweep.train.max_grad_norm] -; distribution = uniform -; min = 0.2 -; mean = 0.5 -; max = 2.0 -; scale = auto - -; [sweep.train.update_epochs] -; distribution = int_uniform -; min = 1 -; mean = 1 -; max = 6 -; scale = auto - -; [sweep.train.vf_coef] -; distribution = uniform -; min = 0.2 -; mean = 0.5 -; max = 3.0 -; scale = auto - -; [sweep.train.vtrace_rho_clip] -; distribution = uniform -; min = 0.0 -; max = 5.0 -; mean = 1.0 -; scale = auto - -; [sweep.train.vtrace_c_clip] -; distribution = uniform -; min = 0.0 -; max = 5.0 -; mean = 1.0 -; scale = auto - -; [sweep.train.clip_coef] -; distribution = uniform -; min = 0.01 -; max = 1.0 -; mean = 0.2 -; scale = auto - -; [sweep.train.gae_lambda] -; distribution = logit_normal -; min = 0.8 -; mean = 0.95 -; max = 0.995 -; scale = auto - -; [sweep.policy.actor_num_layers] -; distribution = int_uniform -; min = 1 -; mean = 1 -; max = 2 -; scale = auto - -; [sweep.policy.critic_num_layers] -; distribution = int_uniform -; min = 1 -; mean = 1 -; max = 2 -; scale = auto - -; [sweep.env.reward_goal] -; distribution = uniform -; min = 0.0 -; mean = 0.5 -; max = 1.0 -; scale = auto - -; [sweep.env.reward_comfort] -; distribution = uniform -; min = 0.0 -; mean = 0.05 -; max = 0.2 -; scale = auto - -; [sweep.env.reward_lane_align] -; distribution = uniform -; min = 0.0 -; mean = 0.025 -; max = 0.2 -; scale = auto - -; [sweep.env.reward_lane_center] -; distribution = uniform -; min = 0.0 -; mean = 0.0038 -; max = 0.2 -; scale = auto - -; [sweep.env.reward_velocity] -; distribution = uniform -; min = 0.0 -; mean = 0.0025 -; max = 0.01 -; scale = auto - -; [sweep.train.adam_beta1] -; distribution = logit_normal -; min = 0.7 -; mean = 0.9 -; max = 0.999 -; scale = auto - -; [sweep.train.adam_beta2] -; distribution = logit_normal -; min = 0.99 -; mean = 0.999 -; max = 0.9999 -; scale = auto - -; [sweep.train.adv_sampling_prio_alpha] -; distribution = logit_normal -; min = 0.7 -; mean = 0.85 -; max = 0.99 -; scale = auto - -; [sweep.train.adv_sampling_prio_beta0] -; distribution = logit_normal -; min = 0.7 -; mean = 0.85 -; max = 0.99 -; scale = auto - -[controlled_exp.train.learning_rate] -values = [0.001, 0.003, 0.01] - -[controlled_exp.train.ent_coef] -values = [0.01, 0.005] diff --git a/pufferlib/config/puffer_drive.yaml b/pufferlib/config/puffer_drive.yaml index 30ae2f8f15..b9d87b18e7 100644 --- a/pufferlib/config/puffer_drive.yaml +++ b/pufferlib/config/puffer_drive.yaml @@ -1,7 +1,6 @@ -# Monolithic config for `puffer puffer_drive` — Hydra migration phase 1. -# Generated by scripts/convert_ini_to_yaml.py from pufferlib/config/ocean/drive.ini -# (merged over pufferlib/config/default.ini). Override at the CLI with -# Hydra syntax: train.learning_rate=1e-4 env.num_agents=512 wandb=true +# Monolithic config for `puffer puffer_drive` — the single source of +# truth for every default. Override at the CLI with Hydra syntax: +# train.learning_rate=1e-4 env.num_agents=512 wandb=true load_model_path: null load_id: null render_mode: auto diff --git a/pufferlib/ocean/benchmark/evaluators/__init__.py b/pufferlib/ocean/benchmark/evaluators/__init__.py index d7594bffc4..3f3d66087a 100644 --- a/pufferlib/ocean/benchmark/evaluators/__init__.py +++ b/pufferlib/ocean/benchmark/evaluators/__init__.py @@ -1,7 +1,7 @@ """Unified evaluator framework for PufferDrive. Each Evaluator subclass owns one rollout pattern. The EvalManager (parent -package) discovers evaluators from `[eval.]` sections in drive.ini +package) discovers evaluators from `eval.` sections in puffer_drive.yaml and dispatches them inline (during training) or as subprocesses. See docs/eval_unification.md for the full design rationale. diff --git a/pufferlib/ocean/benchmark/evaluators/base.py b/pufferlib/ocean/benchmark/evaluators/base.py index de51ece27f..72137636c0 100644 --- a/pufferlib/ocean/benchmark/evaluators/base.py +++ b/pufferlib/ocean/benchmark/evaluators/base.py @@ -55,7 +55,7 @@ def __init__(self, name: str, config: dict, train_config: dict): # `config` = merged per-evaluator config (after inheritance + clean # macro expansion). Has nested `env`, `vec`, plus flat scalar knobs. self.config = config - # `train_config` = the full training config from drive.ini, used as + # `train_config` = the full training config from puffer_drive.yaml, used as # the base layer that `config` overrides on top of. self.train_config = train_config diff --git a/pufferlib/ocean/benchmark/metrics_sanity_check.py b/pufferlib/ocean/benchmark/metrics_sanity_check.py index d0e0e57df8..9a0b451971 100644 --- a/pufferlib/ocean/benchmark/metrics_sanity_check.py +++ b/pufferlib/ocean/benchmark/metrics_sanity_check.py @@ -81,7 +81,6 @@ def format_results_table(results): def main(): parser = argparse.ArgumentParser(description="Validate WOSAC log-likelihood metrics") parser.add_argument("--env", default="puffer_drive") - parser.add_argument("--config", default="config/ocean/drive.ini") args = parser.parse_args() config = load_config(args.env) diff --git a/pufferlib/pufferl.py b/pufferlib/pufferl.py index ce6f144be5..680e291916 100644 --- a/pufferlib/pufferl.py +++ b/pufferlib/pufferl.py @@ -527,7 +527,7 @@ def train(self): print(f"Failed to export model weights: {e}") # All evaluation is now driven by the unified EvalManager. Each - # [eval.] section in drive.ini is one evaluator instance; + # eval. section in puffer_drive.yaml is one evaluator instance; # the manager fires any whose interval divides this epoch. See # docs/eval_unification.md for the design. # Under DDP, only rank 0 runs eval — every rank has identical @@ -1619,7 +1619,7 @@ def _merge_checkpoint_arch(args, model_path): """Adopt a checkpoint's architecture from its sibling config.yaml. A standalone eval may load a checkpoint whose network shape or observation - layout differs from drive.ini. The training run writes config.yaml next to + layout differs from puffer_drive.yaml. The training run writes config.yaml next to models/, so pull from it before the policy/env are built: - policy.*, rnn.*, policy_name, rnn_name (+ derived use_rnn) — the net, else load_state_dict mismatches. @@ -1665,7 +1665,7 @@ def eval( render_backend=None, num_maps=None, ): - """Run a single named evaluator from drive.ini. + """Run a single named evaluator from puffer_drive.yaml. Standalone form: `puffer eval puffer_drive --evaluator `. The evaluator's config (env/vec overrides, render flag, etc.) comes from @@ -1676,7 +1676,7 @@ def eval( flags `--num_scenarios`, `--render`, `--render-backend`, `--num_maps` override the chosen evaluator's config for this run (only when passed), so a checkpoint can be evaluated at an arbitrary scale from the CLI - without editing drive.ini. + without editing puffer_drive.yaml. Subprocess form: `--out ` writes the result dict to a JSON file so the parent EvalManager can read structured metrics back without @@ -1691,7 +1691,7 @@ def eval( # When evaluating a checkpoint, adopt its network architecture from the # training run's sibling config.yaml so the policy is built to match the - # weights regardless of what drive.ini currently says. + # weights regardless of what puffer_drive.yaml currently says. if args.get("load_model_path"): _merge_checkpoint_arch(args, args["load_model_path"]) @@ -1702,7 +1702,7 @@ def eval( if evaluator_name is None: raise pufferlib.APIUsageError( "puffer eval requires --evaluator (or --eval_simulation gigaflow|replay); " - "named [eval.] sections live in drive.ini" + "named eval. sections live in puffer_drive.yaml" ) # Derive a default render output dir from the model path when none is set. @@ -1721,7 +1721,7 @@ def eval( # Ad-hoc CLI overrides applied to the chosen evaluator for this run. # The evaluator reads self.config / self.render at rollout time, so - # mutating them here takes effect without touching drive.ini. + # mutating them here takes effect without touching puffer_drive.yaml. if num_scenarios is not None: target.config.setdefault("eval", {})["num_scenarios"] = int(num_scenarios) if num_maps is not None: diff --git a/scripts/cluster_configs/single_agent_speed_run.yaml b/scripts/cluster_configs/single_agent_speed_run.yaml index 8bbb6dbd75..636b312d52 100644 --- a/scripts/cluster_configs/single_agent_speed_run.yaml +++ b/scripts/cluster_configs/single_agent_speed_run.yaml @@ -2,7 +2,7 @@ # One controlled agent per environment on a single CARLA map (Town10), with many # parallel environments sharing one cached copy of the map geometry. Traffic # lights are fully disabled (no observation, no metric, no reward penalty). Keys -# here override pufferlib/config/ocean/drive.ini; submit_cluster.py converts +# here override pufferlib/config/puffer_drive.yaml; submit_cluster.py converts # underscores in each key to dashes for the CLI. # # Launch (3 seeds via the colon sweep): diff --git a/scripts/cluster_configs/train_base.yaml b/scripts/cluster_configs/train_base.yaml index f27a8fb6b9..1c6f055605 100644 --- a/scripts/cluster_configs/train_base.yaml +++ b/scripts/cluster_configs/train_base.yaml @@ -1,7 +1,7 @@ # Base training configuration for PufferDrive cluster jobs (turbostream). # These args are passed to `puffer train puffer_drive` as --key=value flags. # -# Only keys listed here override the defaults in pufferlib/config/ocean/drive.ini. +# Only keys listed here override the defaults in pufferlib/config/puffer_drive.yaml. # Vec settings (num_envs, num_workers, batch_size), env.map_dir, env.num_maps, # and env.num_agents are all intentionally omitted so runs inherit the ini.