Skip to content

Commit 5891e14

Browse files
committed
ud
1 parent 77c2f1c commit 5891e14

7 files changed

Lines changed: 69 additions & 16 deletions

File tree

comlrl/trainers/actor_critic/ac_base.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,18 +368,22 @@ def evaluate(self) -> Dict[str, float]:
368368
turn_groups: Dict[int, List[Any]] = {}
369369
seen = 0
370370

371-
with torch.no_grad():
372-
for batch in dataloader:
373-
for item in batch:
374-
rollouts = self._collect_rollouts(item)
375-
for sample in rollouts:
376-
t_idx = int(sample.metadata.get("turn_idx", 0))
377-
turn_groups.setdefault(t_idx, []).append(sample)
378-
seen += 1
371+
self._in_eval = True
372+
try:
373+
with torch.no_grad():
374+
for batch in dataloader:
375+
for item in batch:
376+
rollouts = self._collect_rollouts(item)
377+
for sample in rollouts:
378+
t_idx = int(sample.metadata.get("turn_idx", 0))
379+
turn_groups.setdefault(t_idx, []).append(sample)
380+
seen += 1
381+
if seen >= num_samples:
382+
break
379383
if seen >= num_samples:
380384
break
381-
if seen >= num_samples:
382-
break
385+
finally:
386+
self._in_eval = False
383387

384388
eval_log: Dict[str, float] = {}
385389
for turn_idx, samples in sorted(turn_groups.items()):

comlrl/trainers/actor_critic/iac.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,9 @@ def _generate_rollout(
465465
"do_sample": True,
466466
"temperature": self.args.temperature,
467467
"top_p": self.args.top_p,
468-
"num_return_sequences": num_ret,
468+
"num_return_sequences": (
469+
1 if bool(getattr(self, "_in_eval", False)) else num_ret
470+
),
469471
"num_beams": 1,
470472
}
471473
if self.args.top_k is not None:
@@ -558,7 +560,11 @@ def _collect_rollouts(self, item: Dict[str, Any]) -> List[RolloutSample]:
558560
if num_turns > 1:
559561
return self._collect_rollouts_multi_turn(item, num_turns)
560562

561-
num_ret = int(getattr(self.args, "num_generations", 1))
563+
num_ret = (
564+
1
565+
if bool(getattr(self, "_in_eval", False))
566+
else int(getattr(self.args, "num_generations", 1))
567+
)
562568
turn_prompts = [
563569
self._resolve_turn_prompt(item, agent_idx)
564570
for agent_idx in range(self.args.num_agents)

comlrl/trainers/actor_critic/maac.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,11 @@ def _generate(self, agent_model, prompt: str, agent_idx: int) -> Dict[str, Any]:
435435
prompt_attention_mask = encoded_prompt["attention_mask"]
436436
prompt_len = prompt_input_ids.size(1)
437437

438-
num_ret = int(self.args.num_generations)
438+
num_ret = (
439+
1
440+
if bool(getattr(self, "_in_eval", False))
441+
else int(self.args.num_generations)
442+
)
439443
generation_kwargs: Dict[str, Any] = {
440444
"input_ids": prompt_input_ids,
441445
"attention_mask": prompt_attention_mask,

comlrl/trainers/reinforce/magrpo.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,18 +495,21 @@ def get_eval_dataloader(self) -> Optional[DataLoader]:
495495
num_workers=0,
496496
)
497497

498-
def evaluate(self, num_eval_samples: int = 4) -> Dict[str, float]:
498+
def evaluate(self, num_eval_samples: Optional[int] = None) -> Dict[str, float]:
499499
"""
500500
Unified evaluation that supports both single-turn and multi-turn.
501501
502502
Args:
503-
num_eval_samples: Number of samples to evaluate
503+
num_eval_samples: Number of samples to evaluate. Defaults to args.eval_num_samples.
504504
505505
Returns:
506506
Dictionary containing evaluation metrics
507507
"""
508508
if self.eval_dataset is None:
509509
return {}
510+
if num_eval_samples is None:
511+
num_eval_samples = int(getattr(self.args, "eval_num_samples", 4))
512+
num_eval_samples = int(num_eval_samples)
510513

511514
# Storage for completions across turns for all agents
512515
all_agent_completions_turns = [[] for _ in range(self.num_agents)]

docs/content/docs/dev/changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ weight: 3
1010
- Remove the redundant sampling hyperparameters in algorithms.
1111
- Allow multi-gpu training with MP.
1212

13-
## Version 1.3.6
13+
## Latest Changes
1414

1515
- Fixed critical bug of loading heterogeneous models and reform the model loading logics.
1616
- Polish the docs.

docs/content/docs/user-guide/training-parallelization.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ CUDA_VISIBLE_DEVICES=0,1,2,3 python train_iac.py
3232
iac.agent_devices='["cuda:0","cuda:1"]'
3333
iac.critic_devices='["cuda:2","cuda:3"]'
3434
```
35+
36+
{{% hint note %}}
37+
Note that when `parallel_training=mp`, even if the same models with same sampling are used on the same seed, the training is not deterministic due to the non-deterministic GPU scheduling and aggregation on CPU.
38+
{{% /hint %}}

tests/test_distributed_metrics.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,35 @@ def _fake_log(metrics, step): # noqa: ARG001
5757
trainer._log_metrics({"loss": 1.0})
5858
trainer._log_metrics({"reward": 2.0})
5959
assert called["log"] == [{"loss": 1.0}, {"reward": 2.0}]
60+
61+
62+
def test_evaluate_calls_collect_rollouts_with_eval_flag():
63+
class _EvalDummyTrainer(ActorCriticTrainerBase):
64+
def __init__(self):
65+
self.eval_dataset = [{"id": 0}, {"id": 1}]
66+
self.args = SimpleNamespace(eval_batch_size=1, eval_num_samples=1)
67+
self.wandb_initialized = False
68+
self.env_step = 0
69+
self.dist_env = _ctx()
70+
self.verbose = False
71+
self._collect_calls = 0
72+
self.eval_flags = []
73+
74+
def _collect_rollouts(self, item): # noqa: ARG002
75+
self._collect_calls += 1
76+
self.eval_flags.append(bool(getattr(self, "_in_eval", False)))
77+
return [
78+
SimpleNamespace(
79+
metadata={},
80+
reward=torch.tensor([1.0]),
81+
returns=torch.tensor([1.5]),
82+
old_value=torch.tensor([0.5]),
83+
)
84+
]
85+
86+
trainer = _EvalDummyTrainer()
87+
metrics = trainer.evaluate()
88+
assert trainer._collect_calls == 1
89+
assert trainer.eval_flags == [True]
90+
assert trainer._in_eval is False
91+
assert "eval/turn_1/reward_mean" in metrics

0 commit comments

Comments
 (0)