Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/prime_rl/orchestrator/eval_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,4 @@ async def evaluate_env(
eval_metrics.update({"progress/ckpt_step": ckpt_step, "step": step})
monitor = get_monitor()
monitor.log(eval_metrics, step=step)
monitor.log_eval_samples(outputs, env_name=env_name, step=step)
7 changes: 7 additions & 0 deletions src/prime_rl/utils/monitor/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ def log(self, metrics: dict[str, Any], step: int) -> None:
def log_samples(self, rollouts: list[vf.RolloutOutput], step: int) -> None:
pass

@abstractmethod
def log_eval_samples(self, rollouts: list[vf.RolloutOutput], env_name: str, step: int) -> None:
pass

@abstractmethod
def log_final_samples(self) -> None:
pass
Expand Down Expand Up @@ -48,6 +52,9 @@ def log(self, metrics: dict[str, Any], step: int) -> None:
def log_samples(self, rollouts: list[vf.RolloutOutput], step: int) -> None:
pass

def log_eval_samples(self, rollouts: list[vf.RolloutOutput], env_name: str, step: int) -> None:
pass

def log_final_samples(self) -> None:
pass

Expand Down
7 changes: 7 additions & 0 deletions src/prime_rl/utils/monitor/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ def log_samples(self, rollouts: list[vf.RolloutOutput], step: int) -> None:
except Exception as e:
self.logger.warning(f"Failed to log samples to {monitor.__class__.__name__}: {e}")

def log_eval_samples(self, rollouts: list[vf.RolloutOutput], env_name: str, step: int) -> None:
for monitor in self.monitors:
try:
monitor.log_eval_samples(rollouts=rollouts, env_name=env_name, step=step)
except Exception as e:
self.logger.warning(f"Failed to log eval samples to {monitor.__class__.__name__}: {e}")

def log_final_samples(self) -> None:
for monitor in self.monitors:
try:
Expand Down
3 changes: 3 additions & 0 deletions src/prime_rl/utils/monitor/prime.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,9 @@ async def _confirm_samples_upload(self, step: int, s3_key: str, max_retries: int
await asyncio.sleep(delay)
return False

def log_eval_samples(self, rollouts: list[vf.RolloutOutput], env_name: str, step: int) -> None:
pass

def log_final_samples(self) -> None:
"""Log final samples (no-op - samples are logged per-step only)."""
pass
Expand Down
33 changes: 33 additions & 0 deletions src/prime_rl/utils/monitor/wandb.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ def init_wandb(max_retries: int):
)
self.tokenizer = tokenizer
self.samples = []
self.eval_samples_cols = ["step", "env", "task", "example_id", "completion", "reward"]
self.eval_samples_table = wandb.Table(
columns=self.eval_samples_cols,
log_mode="INCREMENTAL",
)

def _maybe_overwrite_wandb_command(self) -> None:
"""Overwrites sys.argv with the start command if it is set in the environment variables."""
Expand Down Expand Up @@ -165,6 +170,34 @@ def log_samples(self, rollouts: list[vf.RolloutOutput], step: int) -> None:
self.last_log_samples_step = step
self.logger.debug(f"Logged samples at step {step} to W&B table in {time.perf_counter() - start_time:.2f}s")

def log_eval_samples(self, rollouts: list[vf.RolloutOutput], env_name: str, step: int) -> None:
"""Logs eval rollouts to a separate W&B table."""
if not self.is_master:
return
if (
not self.config
or not isinstance(self.config, WandbWithExtrasConfig)
or not self.config.log_extras
or not self.config.log_extras.samples
):
return

for rollout in rollouts:
completion = rollout.get("completion", "")
if not completion:
continue
sample = {
"step": step,
"env": env_name,
"task": rollout.get("task"),
"example_id": rollout["example_id"],
"completion": completion,
"reward": rollout["reward"],
}
self.eval_samples_table.add_data(*sample.values())

wandb.log({"eval/samples": self.eval_samples_table, "step": step})

def log_final_samples(self) -> None:
"""Log final samples to W&B table."""
if not self.is_master:
Expand Down
Loading