77import json
88import sys
99import tempfile
10+ from datetime import datetime
11+ from datetime import timezone
1012from pathlib import Path
1113from typing import Any
1214
@@ -55,6 +57,7 @@ def run_pipeline(
5557 update_source : bool = False ,
5658 gate_config_path : str | Path | None = None ,
5759 target_prompts : list [str ] | None = None ,
60+ run_id : str | None = None ,
5861) -> OptimizationReport :
5962 """Run baseline eval, fake optimization, validation gate, and reports."""
6063
@@ -101,6 +104,8 @@ def run_pipeline(
101104 gate_config = wrapper_gate_config ,
102105 gate_config_path = gate_config_path ,
103106 target_prompt_paths = target_prompt_paths ,
107+ sdk_call_agent = sdk_call_agent ,
108+ run_id = run_id ,
104109 )
105110 write_reports (report , output_dir )
106111 return report
@@ -334,6 +339,8 @@ def _build_sdk_report(
334339 gate_config : dict [str , float ],
335340 gate_config_path : str | Path | None ,
336341 target_prompt_paths : dict [str , str | Path ],
342+ sdk_call_agent : str | None ,
343+ run_id : str | None ,
337344) -> OptimizationReport :
338345 input_hashes = _input_hashes (
339346 train_path = train_path ,
@@ -351,6 +358,14 @@ def _build_sdk_report(
351358 )
352359 total_llm_cost = _summary_float (sdk_summary , "total_llm_cost" , 0.0 )
353360 duration_seconds = _summary_float (sdk_summary , "duration_seconds" , 0.0 )
361+ effective_run_id = run_id or _default_sdk_run_id (sdk_summary )
362+ target_prompt_hashes = {
363+ name : sha256_file (path )
364+ for name , path in target_prompt_paths .items ()
365+ }
366+ input_hashes ["target_prompts" ] = target_prompt_hashes
367+ if gate_config_path :
368+ input_hashes ["gate_config" ] = sha256_file (gate_config_path )
354369 availability = {
355370 "aggregate_validation_result" : True ,
356371 "full_train_eval_result" : False ,
@@ -401,10 +416,6 @@ def _build_sdk_report(
401416 for candidate in candidates
402417 }
403418 field_prompt_hashes = _candidate_prompt_hashes_by_field (candidates , sdk_summary )
404- target_prompt_hashes = {
405- name : sha256_file (path )
406- for name , path in target_prompt_paths .items ()
407- }
408419 audit = {
409420 "seed" : None ,
410421 "duration_seconds" : duration_seconds ,
@@ -450,10 +461,12 @@ def _build_sdk_report(
450461 update_source = update_source ,
451462 gate_config_path = gate_config_path ,
452463 target_prompt_paths = target_prompt_paths ,
464+ sdk_call_agent = sdk_call_agent ,
465+ run_id = effective_run_id ,
453466 ),
454467 }
455468 run = {
456- "run_id" : "eval_optimize_loop_sdk" ,
469+ "run_id" : effective_run_id ,
457470 "mode" : "sdk" ,
458471 "fake_model" : False ,
459472 "fake_judge" : False ,
@@ -507,18 +520,21 @@ def _sdk_reproducibility_command(
507520 update_source : bool ,
508521 gate_config_path : str | Path | None ,
509522 target_prompt_paths : dict [str , str | Path ],
523+ sdk_call_agent : str | None ,
524+ run_id : str ,
510525) -> str :
511526 command = (
512527 "python examples/optimization/eval_optimize_loop/run_pipeline.py "
513528 f"--mode sdk --train { train_path } --val { val_path } "
514529 f"--optimizer-config { optimizer_config_path } --prompt { prompt_path } "
515- f"--output-dir { output_dir } --sdk-call-agent module:function "
530+ f"--output-dir { output_dir } --sdk-call-agent { sdk_call_agent or '' } "
516531 )
517532 for name , path in target_prompt_paths .items ():
518533 if not (name == "system_prompt" and Path (path ) == Path (prompt_path ) and len (target_prompt_paths ) == 1 ):
519534 command += f" --target-prompt { name } ={ path } "
520535 if gate_config_path :
521536 command += f" --gate-config { gate_config_path } "
537+ command += f" --run-id { run_id } "
522538 if update_source :
523539 command += " --update-source"
524540 return command
@@ -624,6 +640,21 @@ def _summary_float(summary: dict[str, Any], key: str, default: float) -> float:
624640 return default
625641
626642
643+ def _default_sdk_run_id (sdk_summary : dict [str , Any ]) -> str :
644+ started_at = sdk_summary .get ("started_at" )
645+ if isinstance (started_at , str ) and started_at .strip ():
646+ source = started_at .strip ()
647+ else :
648+ source = datetime .now (timezone .utc ).isoformat (timespec = "seconds" )
649+ safe = []
650+ for char in source :
651+ if char .isalnum () or char in {"-" , "_" }:
652+ safe .append (char )
653+ else :
654+ safe .append ("-" )
655+ return "eval_optimize_loop_sdk_" + "" .join (safe ).strip ("-" )
656+
657+
627658def _parse_target_prompt_paths (
628659 target_prompts : list [str ] | None ,
629660 * ,
@@ -681,6 +712,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
681712 action = "append" ,
682713 help = "SDK target prompt path in name=path format. May be repeated. Defaults to system_prompt=--prompt." ,
683714 )
715+ parser .add_argument ("--run-id" , help = "Optional report/audit run id. Fake mode keeps its deterministic default." )
684716 return parser .parse_args (argv )
685717
686718
@@ -734,6 +766,7 @@ def main(argv: list[str] | None = None) -> OptimizationReport:
734766 update_source = args .update_source ,
735767 gate_config_path = args .gate_config ,
736768 target_prompts = args .target_prompt ,
769+ run_id = args .run_id ,
737770 )
738771 output_dir = Path (args .output_dir )
739772 print (f"Wrote { output_dir / 'optimization_report.json' } " )
0 commit comments