Skip to content

Commit 97394aa

Browse files
committed
fix(examples): make optimization audit reproducible
1 parent 35a99bf commit 97394aa

7 files changed

Lines changed: 1445 additions & 154 deletions

File tree

examples/optimization/eval_optimize_loop/eval_loop/pipeline.py

Lines changed: 43 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
from .gate import AcceptanceGate
3030
from .loader import read_json
3131
from .loader import stable_config_hash
32+
from .report import RunArtifactPaths
3233
from .report import build_report
3334
from .report import compute_case_deltas
3435
from .report import finalize_run_artifacts
3536
from .report import persist_writeback_journal
3637
from .report import persist_writeback_outcome
3738
from .report import prepare_run_artifacts
39+
from .report import reserve_run_artifacts
40+
from .report import validate_unique_round_ids
3841
from .schemas import CandidatePrompt
3942
from .schemas import CostSummary
4043
from .schemas import EvalResult
@@ -119,7 +122,8 @@ async def execute_pipeline(
119122
{"train": request.train_path, "validation": request.validation_path},
120123
context="train and validation evalset paths",
121124
)
122-
run_root = _claim_run_directory(request.output_dir, run_id=run_id)
125+
artifact_paths = reserve_run_artifacts(request.output_dir, run_id=run_id)
126+
run_root = artifact_paths.temp_run_dir
123127

124128
input_snapshots = _snapshot_pipeline_inputs(request, run_id=run_id)
125129
try:
@@ -130,6 +134,7 @@ async def execute_pipeline(
130134
started=started,
131135
run_id=run_id,
132136
run_root=run_root,
137+
artifact_paths=artifact_paths,
133138
input_snapshots=input_snapshots,
134139
)
135140
except BaseException as primary_error:
@@ -172,6 +177,7 @@ async def _execute_with_snapshots(
172177
started: float,
173178
run_id: str,
174179
run_root: Path,
180+
artifact_paths: RunArtifactPaths,
175181
input_snapshots: _InputSnapshots,
176182
) -> OptimizationReport:
177183
prompt_snapshot = snapshot_prompt_files(request.target_prompt_paths)
@@ -483,6 +489,7 @@ async def _execute_with_snapshots(
483489
gate_decisions=gate_decisions,
484490
selected_candidate=selected_candidate,
485491
audit=audit,
492+
baseline_prompts=dict(baseline_prompts),
486493
rounds=optimization.rounds,
487494
cost_summary=cost_summary,
488495
writeback=provisional_writeback,
@@ -492,7 +499,7 @@ async def _execute_with_snapshots(
492499
prompt_snapshot,
493500
context="immediately before preparing run artifacts",
494501
)
495-
artifact_paths = prepare_run_artifacts(report, request.output_dir)
502+
prepare_run_artifacts(report, artifact_paths)
496503
if selected_candidate is None or not request.update_source:
497504
terminal_journal = _terminal_journal(
498505
writeback_journal,
@@ -509,22 +516,17 @@ async def _execute_with_snapshots(
509516
request=request,
510517
)
511518
persist_writeback_outcome(final_report, artifact_paths)
512-
_verify_terminal_writeback_integrity(
513-
prompt_snapshot,
514-
expected_hashes=prompt_snapshot.hashes(),
515-
context="immediately before finalizing no-write run",
516-
artifact_paths=artifact_paths,
517-
journal=terminal_journal,
518-
request=request,
519-
)
520-
finalize_run_artifacts(final_report, artifact_paths)
521-
_verify_terminal_writeback_integrity(
522-
prompt_snapshot,
523-
expected_hashes=prompt_snapshot.hashes(),
524-
context="immediately before returning no-write run",
525-
artifact_paths=artifact_paths,
526-
journal=terminal_journal,
527-
request=request,
519+
finalize_run_artifacts(
520+
final_report,
521+
artifact_paths,
522+
before_publish=lambda: _verify_terminal_writeback_integrity(
523+
prompt_snapshot,
524+
expected_hashes=prompt_snapshot.hashes(),
525+
context="immediately before publishing no-write run",
526+
artifact_paths=artifact_paths,
527+
journal=terminal_journal,
528+
request=request,
529+
),
528530
)
529531
return final_report
530532

@@ -553,22 +555,17 @@ async def _execute_with_snapshots(
553555
request=request,
554556
)
555557
persist_writeback_outcome(final_report, artifact_paths)
556-
_verify_terminal_writeback_integrity(
557-
prompt_snapshot,
558-
expected_hashes=prompt_snapshot.hashes(),
559-
context="immediately before finalizing input-drift run",
560-
artifact_paths=artifact_paths,
561-
journal=final_journal,
562-
request=request,
563-
)
564-
finalize_run_artifacts(final_report, artifact_paths)
565-
_verify_terminal_writeback_integrity(
566-
prompt_snapshot,
567-
expected_hashes=prompt_snapshot.hashes(),
568-
context="immediately before returning input-drift run",
569-
artifact_paths=artifact_paths,
570-
journal=final_journal,
571-
request=request,
558+
finalize_run_artifacts(
559+
final_report,
560+
artifact_paths,
561+
before_publish=lambda: _verify_terminal_writeback_integrity(
562+
prompt_snapshot,
563+
expected_hashes=prompt_snapshot.hashes(),
564+
context="immediately before publishing input-drift run",
565+
artifact_paths=artifact_paths,
566+
journal=final_journal,
567+
request=request,
568+
),
572569
)
573570
return final_report
574571

@@ -637,22 +634,17 @@ async def _execute_with_snapshots(
637634
request=request,
638635
)
639636
persist_writeback_outcome(final_report, artifact_paths)
640-
_verify_terminal_writeback_integrity(
641-
prompt_snapshot,
642-
expected_hashes=terminal_prompt_hashes,
643-
context="immediately before finalizing writeback run",
644-
artifact_paths=artifact_paths,
645-
journal=final_journal,
646-
request=request,
647-
)
648-
finalize_run_artifacts(final_report, artifact_paths)
649-
_verify_terminal_writeback_integrity(
650-
prompt_snapshot,
651-
expected_hashes=terminal_prompt_hashes,
652-
context="immediately before returning writeback run",
653-
artifact_paths=artifact_paths,
654-
journal=final_journal,
655-
request=request,
637+
finalize_run_artifacts(
638+
final_report,
639+
artifact_paths,
640+
before_publish=lambda: _verify_terminal_writeback_integrity(
641+
prompt_snapshot,
642+
expected_hashes=terminal_prompt_hashes,
643+
context="immediately before publishing writeback run",
644+
artifact_paths=artifact_paths,
645+
journal=final_journal,
646+
request=request,
647+
),
656648
)
657649
return final_report
658650

@@ -711,17 +703,6 @@ def _snapshot_pipeline_inputs(request: PipelineRequest, *, run_id: str) -> _Inpu
711703
return _InputSnapshots(snapshots)
712704

713705

714-
def _claim_run_directory(output_dir: str | Path, *, run_id: str) -> Path:
715-
runs_root = Path(output_dir) / "runs"
716-
runs_root.mkdir(parents=True, exist_ok=True)
717-
run_root = runs_root / run_id
718-
try:
719-
run_root.mkdir()
720-
except FileExistsError as error:
721-
raise ValueError(f"run_id {run_id!r} already exists in {runs_root}") from error
722-
return run_root
723-
724-
725706
def _verify_snapshot_integrity(
726707
snapshots: _InputSnapshots,
727708
*requested_roles: str,
@@ -1335,6 +1316,7 @@ def _validate_optimization_result(result: OptimizationResult) -> None:
13351316
round_record.cost,
13361317
context=f"optimization round {round_record.round_id} cost",
13371318
)
1319+
validate_unique_round_ids(result.rounds)
13381320
if not isinstance(result.raw_summary, dict):
13391321
raise ValueError("optimization raw_summary must be an object")
13401322
_validate_nested_numbers(result.raw_summary, context="optimization raw_summary")

0 commit comments

Comments
 (0)