from __future__ import annotations import subprocess import sys from pathlib import Path from dovla_cil.data.datasets import CILDataset from dovla_cil.experiments.baselines import ( BaselineConfig, loss_weights_for_baseline, prepare_dataset_for_baseline, ) from dovla_cil.generation.pipeline import generate_cil_dataset from dovla_cil.tasks.library import built_in_toy_tasks from dovla_cil.utils.io import read_json def _make_dataset(tmp_path: Path) -> Path: dataset_dir = tmp_path / "cil" generate_cil_dataset( backend="toy", tasks=built_in_toy_tasks()[:2], out_dir=dataset_dir, num_states_per_task=1, k=4, seed=9, shard_size=8, inline_observations=True, ) return dataset_dir def test_expert_only_dataset_has_one_record_per_group(tmp_path: Path) -> None: dataset_dir = _make_dataset(tmp_path) prepared = prepare_dataset_for_baseline( dataset_dir, "expert_only_bc", tmp_path / "expert_only" ) dataset = CILDataset(prepared) assert len(dataset.records) == len(dataset.group_ids) assert all(len(dataset.get_group(group_id)) == 1 for group_id in dataset.group_ids) def test_random_negatives_mode_can_generate(tmp_path: Path) -> None: dataset_dir = _make_dataset(tmp_path) prepared = prepare_dataset_for_baseline( dataset_dir, "random_negatives", tmp_path / "random_negatives" ) dataset = CILDataset(prepared) assert any(record.candidate_type == "random_negative" for record in dataset.records) assert (prepared / "baseline_metadata.json").exists() def test_world_model_auxiliary_sets_loss_weights() -> None: weights = loss_weights_for_baseline("world_model_auxiliary") assert weights.weight("effect") == 1.0 assert weights.weight("progress") == 1.0 assert weights.weight("rank") == 0.0 assert weights.weight("regret") == 0.0 def test_cross_state_baseline_is_measured_not_placeholder(tmp_path: Path) -> None: dataset_dir = _make_dataset(tmp_path) prepared = prepare_dataset_for_baseline( dataset_dir, "cross_state_negatives", tmp_path / "cross_state" ) metadata = read_json(prepared / "baseline_metadata.json") assert metadata["approximate"] is False def test_baseline_config_model_dump(tmp_path: Path) -> None: config = BaselineConfig( baseline="expert_only_bc", dataset=tmp_path / "dataset", out=tmp_path / "out", ) payload = config.model_dump() assert payload["baseline"] == "expert_only_bc" def test_baseline_cli_smoke_runs(tmp_path: Path) -> None: dataset_dir = _make_dataset(tmp_path) out_dir = tmp_path / "run" subprocess.run( [ sys.executable, "scripts/run_baseline.py", "--baseline", "expert_only_bc", "--dataset", str(dataset_dir), "--out", str(out_dir), "--epochs", "1", "--batch-groups", "1", "--records-per-group", "1", "--hidden-dim", "32", "--eval-num-tasks", "2", "--eval-k", "4", ], check=True, capture_output=True, text=True, ) assert (out_dir / "train" / "best.pt").exists() metrics = read_json(out_dir / "metrics.json") assert metrics["baseline"] == "expert_only_bc" assert "pairwise_ranking_accuracy" in metrics["eval"]