Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
b024795
Step 0: DELETE EVERYTHING EVAL RELATED - SORRY
WaelDLZ Jul 6, 2026
12c9e68
Step 0:adapt eh code so it still passes tests
WaelDLZ Jul 6, 2026
c61cf91
Step 0: also delete the docs
WaelDLZ Jul 6, 2026
fc22792
Step 1: Restore multiprocessed eval
WaelDLZ Jul 9, 2026
ee1b1cd
Step 2: Per-episode logging (for evals with early reset, for example …
WaelDLZ Jul 15, 2026
48b8c77
a tiny refacto of pufferl.py
WaelDLZ Jul 15, 2026
5df58db
Step 3: seeding and reusability
WaelDLZ Jul 15, 2026
485e989
replay scenarios based on condition
WaelDLZ Jul 15, 2026
dd993de
Step 3: Seeding + Replay
WaelDLZ Jul 16, 2026
fa0b0b7
Remove Episode Summary: There was something better to do --> adapt ve…
WaelDLZ Jul 16, 2026
9b688ec
Force same num_agents_per_batch for seed replay on GPU
WaelDLZ Jul 16, 2026
8f5389f
Pad replay inference to preserve agents per batch
Jul 20, 2026
3232cdf
Capture eval episodes as standard zlib replays
Jul 20, 2026
3269859
Render saved eval replays as HTML
Jul 20, 2026
f4a3ed5
Add scenario progress tracking to eval rollout function
Jul 20, 2026
db2c7e0
Update README and config for eval replays; add observation rendering …
Jul 21, 2026
ec69615
Refactor replay capture logic and remove unused schema validation in …
Jul 21, 2026
f19c116
STEP 5
Jul 21, 2026
a6fef93
Increase number of evaluation agents to 512 and optimize replay writi…
Jul 21, 2026
2d4c799
Less Workers for OBS rendering. Refacto
Jul 22, 2026
4f00c7a
Add validation for training evaluation configuration and implement tr…
Jul 22, 2026
26b120e
Merge remote-tracking branch 'emergelab/3.0' into vb/better_eval
Jul 22, 2026
9477e5c
Refactor and enhance evaluation scripts
Jul 22, 2026
cdb190a
Enhance evaluation configuration and simplify replay validation logic
Jul 22, 2026
7f43e93
Add goal configuration parameters to benchmark evaluation
Jul 22, 2026
985a95f
Optim : Add CSV render only, compile policy
Jul 23, 2026
d0bde82
Enhance benchmark evaluation and visualization logic
Jul 23, 2026
86a4e02
Reduce pr diff
Jul 23, 2026
b684609
Refactor evaluation configurations and update YAML files for clarity …
Jul 23, 2026
1da087d
Reduce PR diff2
Jul 23, 2026
77ba3c2
Refactor evaluation worker functions for clarity and consistency
Jul 23, 2026
38b863b
Add max_agents_per_env configuration and adjust agent count logic in …
Jul 23, 2026
47d2cd0
Update evaluation configurations and add worker cap for SDC replay su…
Jul 24, 2026
78fab61
Enhance evaluation process by adding scenario rendering and updating …
Jul 24, 2026
22783fa
Restore boundary-direction canonicalization in observation processing…
Jul 24, 2026
28b9fd0
Refactor random number generation in Drive functions to use rng_state…
Jul 24, 2026
37273f9
Changes from Valentin's comments
Jul 24, 2026
f92e951
Merge commit '7126974689ae4a38cf1b786be53e6064b218aabc' into vb/bette…
Jul 24, 2026
03a8fa6
Add smoke test for HTML generation in replay validation
Jul 24, 2026
0b0855a
Cleaning 1: rename suites/datasets to benchmark (benchmark=carla_fast…
WaelDLZ Jul 27, 2026
6c15a6e
Clean step 2: Some more renaming, but maybe will change when I attack…
WaelDLZ Jul 27, 2026
cd75b62
Fuse the two yaml in one named benchmark.yaml, update the docs. Resto…
WaelDLZ Jul 27, 2026
48bd185
Cleaning: improve folder naming, remove duplicate fallbacks
WaelDLZ Jul 27, 2026
3291def
make clear which num agents is used !
WaelDLZ Jul 27, 2026
6b6322a
Update docs
WaelDLZ Jul 27, 2026
0f39b4b
Rather use timestamps to name the evals
WaelDLZ Jul 28, 2026
d9ea48c
Refactor vec_reset to require only one argument and remove seed handling
Jul 28, 2026
8f4c12e
Enhance evaluation to support recurrent policies and update tests for…
Jul 28, 2026
cbc29cb
Fix timestamped evaluation output test
Jul 28, 2026
5720e70
Name the thing "render_filter" instead of "failure_metrics"
WaelDLZ Jul 28, 2026
921a094
Restore map_dir
WaelDLZ Jul 28, 2026
2bee767
Remove obsolete timestep get in binding.c
WaelDLZ Jul 28, 2026
6d153d1
Revert useless change in render.h
WaelDLZ Jul 28, 2026
b415408
Clean drive.py
WaelDLZ Jul 28, 2026
632ec42
Clean drive.py - 2: rename replay_buffer to replay_captures, remove s…
WaelDLZ Jul 28, 2026
a2690cb
Move benchmark to ocean drive (like in Miami lol)
WaelDLZ Jul 28, 2026
3d30abb
clean benchmark.py: remove useless pandas fillna and deepcopies
WaelDLZ Jul 28, 2026
ee8f7b5
clean benchmark.py: remove useless RENDER_FILTER_COLUMNS
WaelDLZ Jul 28, 2026
051a695
clean eval_replay.py: move to Ocean drive, delete 2-lines helper, and…
WaelDLZ Jul 28, 2026
dd90a06
clean eval_replay.py: remove safe_part
WaelDLZ Jul 28, 2026
c236558
clean eval_replay.py: clearer variable names
WaelDLZ Jul 28, 2026
6bdbf46
clean pufferl.py: Compile the policy only once, compute the summary o…
WaelDLZ Jul 29, 2026
96291dd
clean pufferl.py: warning (no error) if not enough episodes or too mu…
WaelDLZ Jul 29, 2026
6170d6e
Merge commit '43f4a5db4e31f63949cdf1957e2a6f045a50e78c' into vb/bette…
Jul 29, 2026
36a2596
update render filter options, remove num_goals from benchmark.yaml
Jul 29, 2026
f5efe6f
feat: Enhance gallery index with failure filters and expert agent vis…
Jul 28, 2026
104aa44
Cleaned up Viz.Py
Jul 29, 2026
3b2d5ae
fix: max_agents_per_env for multiple benchmarks
Jul 29, 2026
8e3fb5e
Merge remote-tracking branch 'emergelab/3.0' into vb/better_eval
Jul 29, 2026
ee84b34
Wip tests
Jul 29, 2026
fa80ab3
Add drive eval golden
Jul 29, 2026
fb923fd
WIP Goldens eval
Jul 29, 2026
53506e5
clean eval tests: Remove all tests
WaelDLZ Jul 29, 2026
1bc5288
Proper eval tests on the 4 most important features
WaelDLZ Jul 29, 2026
36b8100
clean eval tests: make the test CI-compatible by reducing to two work…
WaelDLZ Jul 29, 2026
5c9cd62
Refactor evaluation logic: modularize replay rendering and benchmark …
Jul 30, 2026
d4e638c
Change folder position
Jul 30, 2026
cad5f85
Refactor imports in evaluation modules to use the new evaluation_util…
Jul 30, 2026
ccae7cb
Merge commit '4624078f20a6ff5236f75a215b8e367de1d82a30' into vb/bette…
Jul 30, 2026
8492577
Fix typo in lane index assignment in compute_metrics function
Jul 30, 2026
8eeecf6
Update golden JSON files with corrected evaluation metrics and reward…
Jul 30, 2026
90e9b59
Refactor evaluation documentation for clarity and conciseness
Jul 30, 2026
cb541e0
Update evaluation configuration for clarity and functionality
Jul 31, 2026
175f66d
update folder for map_dir wod-motion_val
Jul 31, 2026
e4f1c94
rename all to all_infractions
Jul 31, 2026
4671bc7
Add max_agents_per_env configuration and improve evaluation handling
Jul 31, 2026
24559ce
Remove scripts/eval dead code
WaelDLZ Aug 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 4 additions & 34 deletions .github/workflows/ci.yml
Comment thread
WaelDLZ marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ jobs:
- name: Unit tests
run: python -m pytest -v tests/unit_tests

- name: Evaluation integration tests
run: python -m pytest -v tests/eval
timeout-minutes: 15

c-drive-tests:
name: C Drive Tests
runs-on: ubuntu-latest
Expand Down Expand Up @@ -121,40 +125,6 @@ jobs:
run: docker run --rm pufferdrive-smoke
timeout-minutes: 30

smoke-replay:
name: Smoke Replay HTML
runs-on: ubuntu-latest
env:
PUFFER_CPU: 1
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Free up disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo apt-get clean
sudo rm -rf ~/.cache/pip /tmp/* /var/tmp/*

- name: Install pufferlib
env:
TMPDIR: ${{ runner.temp }}/build
PIP_NO_CACHE_DIR: 1
run: |
sudo apt-get update && sudo apt-get install -y build-essential cmake
python -m pip install -U pip pytest
pip install -e . --no-cache-dir
python setup.py build_ext --inplace --force

- name: Replay HTML test
run: python -m pytest -v tests/smoke_tests/test_validation_replay_html.py
timeout-minutes: 20

Comment on lines -124 to -157

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand deleting this, but why not have a replacement test for the htmls?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted a lot of tests to focus only on testing the 4 most important mechanisms of the PR:

  • multiprocessed eval dispatches map correctly and gather the correct number of scenarios
  • Seeding gets you exactly the same numbers for all metrics
  • Running a mid-training eval doesn't affect training
  • Capturing replays work (complex interaction between C and Python)

My idea was to focus on the most complex mechanisms that rely on both C and Python code, and could be broken by a coming PR that touches drive.h or binding.c, and thus avoid having 2k lines of tests for things that are "less complex"

But I'm very open to advice on it, if you think we should have tests for every mechanism because it's the best way to make the codebase robust for the future, we'll add them !

perf-tests:
name: Smoke Performance Test
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ global-include *.h
global-include *.cpp
global-include *.cu
global-include *.py
recursive-include pufferlib/config *.ini *.yaml
recursive-include pufferlib/resources *
recursive-exclude experiments *
recursive-exclude wandb *
Expand Down
20 changes: 10 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ EXT_SUFFIX := $(shell $(PYTHON) -c "import sysconfig; print(sysconfig.get_config
BINDING := pufferlib/ocean/drive/binding$(EXT_SUFFIX)
DRIVE_SOURCES := $(wildcard pufferlib/ocean/drive/*.c) $(wildcard pufferlib/ocean/drive/*.h) setup.py

.PHONY: help test rebuild ensure-test-deps test-unit test-c test-smoke test-notebooks test-docker-smoke
.PHONY: help test rebuild ensure-test-deps test-unit test-eval test-c test-notebooks test-docker-smoke

help:
@echo "PufferDrive test targets:"
@echo ""
@echo " make test Run the local suites (unit + C + smoke + notebooks),"
@echo " make test Run the local suites (unit + eval + C + notebooks),"
@echo " fail-fast. Rebuilds the C extension first if any"
@echo " .c/.h changed; installs test deps if missing."
@echo " make rebuild Force-rebuild the C extension unconditionally"
@echo ""
@echo " make test-unit Python unit tests (tests/unit_tests)"
@echo " make test-eval Evaluation integration tests (tests/eval)"
@echo " make test-c C sim tests (tests/drive: dynamics, geometry, IDM, ...)"
@echo " make test-smoke Replay-HTML smoke test"
@echo " make test-notebooks Execute every checked-in notebook end-to-end"
@echo ""
@echo " make test-docker-smoke Full smoke suite in Docker (train/rollout/eval goldens)"
@echo " make test-docker-smoke Full smoke suite in Docker (train/rollout goldens)"

$(BINDING): $(DRIVE_SOURCES)
$(PYTHON) setup.py build_ext --inplace --force

# Local suites, fast-failing first: Python unit tests, C sim tests,
# replay-HTML smoke test, then the notebook executions (slowest). The
# Local suites, fast-failing first: Python unit tests, eval integration, C sim tests,
# then the notebook executions (slowest). The
# Docker smoke suite stays opt-in — it needs a Docker daemon.
test: test-unit test-c test-smoke test-notebooks
test: test-unit test-eval test-c test-notebooks

rebuild:
$(PYTHON) setup.py build_ext --inplace --force
Expand All @@ -46,12 +46,12 @@ ensure-test-deps:
test-unit: $(BINDING)
$(PYTHON) -m pytest -v tests/unit_tests

test-eval: $(BINDING)
$(PYTHON) -m pytest -v tests/eval

test-c:
$(MAKE) -C tests/drive test

test-smoke: $(BINDING)
$(PYTHON) -m pytest -v tests/smoke_tests/test_validation_replay_html.py

test-notebooks: $(BINDING) ensure-test-deps
$(PYTHON) -m pytest -v tests/notebooks

Expand Down
79 changes: 27 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,67 +131,42 @@ torchrun --standalone --nnodes=1 --nproc-per-node=6 -m pufferlib.pufferl train p

## Eval

All evaluation runs through the unified `Evaluator`/`EvalManager` pipeline.
`eval.<name>` sections in `puffer_drive.yaml` define each evaluator; the same
ones run inline during training and standalone here.

The default device is CUDA; on a machine without it (e.g. a Mac) add `train.device=cpu`.
The eval command loads one or more named benchmarks from the benchmark YAML and
writes per-episode metrics for each benchmark. Benchmark selection is mandatory;
eval does not choose one implicitly. The default device is CUDA; on a machine
without it add `train.device=cpu`.

```bash
# Run a named evaluator on a checkpoint (config from eval.<name>)
puffer eval puffer_drive --evaluator validation_gigaflow \
load_model_path=experiments/puffer_drive_xxxx/models/model_puffer_drive_000500.pt

# Ad-hoc: pick by simulation + override scale from the CLI
puffer eval puffer_drive --eval_simulation replay \
load_model_path=experiments/puffer_drive_xxxx/models/model_puffer_drive_000500.pt \
--num_scenarios 250 --render 1

# Render the agent's observations (interactive HTML)
puffer eval puffer_drive --eval_simulation gigaflow \
# Run the CARLA YAML benchmark and render every evaluated scenario
puffer eval puffer_drive carla \
load_model_path=experiments/puffer_drive_xxxx/models/model_puffer_drive_000500.pt \
--num_scenarios 10 --render 1 --render-backend obs_html
eval.render_scenarios=true \
eval.capture_observations=false
```

(`--evaluator`, `--eval_simulation`, `--num_scenarios`, `--render`, and
`--render-backend` are per-invocation eval flags consumed before config
loading; everything else uses Hydra `key=value` overrides.)

**For the full guide see [`docs/evaluation.md`](docs/evaluation.md).**

## Failure mining

Roll a trained policy out against a scenario suite, capture per-episode compact replays for episodes whose `episode_return` falls below a threshold, render each one as an interactive HTML page, and produce a sortable cross-episode index. Useful for triaging what a policy fails at after a long training run.
Scenario renders are captured during the benchmark pass and written as
interactive HTML with retained `.replay.zlib` files. To render only episodes
where `offroad_rate > 0` instead:

```bash
puffer mine_failures puffer_drive \
load_model_path=experiments/puffer_drive_xxxx/models/model_puffer_drive_000123.pt \
mine.output_dir=./failure_mining/puffer_drive_xxxx \
mine.num_episodes=200 \
mine.score_threshold=-10.0
```

Config keys (under `mine:` in `puffer_drive.yaml` or `mine.<key>=<value>` on the CLI):

| Key | Default | Notes |
|---|---|---|
| `output_dir` | `./failure_mining/<env_name>` | Where replays, CSV, and HTML output go |
| `num_episodes` | `100` | Total episodes to roll out |
| `score_threshold` | `-inf` | `episode_return < threshold` → flagged as failure; replay written to disk. With `-inf`, no failures are flagged and no replays are persisted. |
| `render` | `True` | Render each captured replay to HTML + write `index.html` via `mining_viz` |

`env.*` overrides apply (e.g. `env.simulation_mode=gigaflow` to mine on procedural scenarios). Single vec env, sequential rollout — no per-worker map pinning yet. On a machine without CUDA add `train.device=cpu vec.backend=Serial` (the default vec config assumes cluster core counts).

**Output structure** (under `output_dir`):

```
episodes.csv # one row per episode, all summary metrics
replays/episode_NNNNNN.replay.zlib # only for failures (above-threshold episodes are not persisted)
renders/episode_NNNNNN.html # one viewer page per failure
renders/index.html # sortable index of all episodes
puffer eval puffer_drive carla \
load_model_path=experiments/puffer_drive_xxxx/models/model_puffer_drive_000500.pt \
eval.render_filter=offroad_rate \
eval.max_rendered_failures=10 \
eval.capture_observations=false
```

Open `renders/index.html` in a browser to triage. The index page filters by "failures only" / "replays only" and sorts by any metric column. Each row links to the per-episode viewer with the scene's full 2D animation.
Use `eval.num_agents`, not `env.num_agents`, to configure evaluation capacity.
Evaluation outputs are written under
`eval/<benchmark>[_<output_name>]/<timestamp>/`. The benchmark seed and effective
worker count are saved in the
resolved configuration: repeated runs with both unchanged produce the same
map/seed rows. Filtered renders replay the exact map and seed recorded by the
metrics pass. Set `eval.failure_replay_csv=<path/to/episode_metrics.csv>` with a
non-null `eval.render_filter` to skip the standard benchmark pass and filter an
existing report directly. See [docs/evaluation.md](docs/evaluation.md) for the
benchmark schema, filtered replay and all-scenario rendering flows, outputs, and
training integration.

## Nightly runs and the regression report

Expand Down
Loading
Loading