"""Build the combined behavioral and format Profile for one model.""" from __future__ import annotations import json from pathlib import Path import subprocess import sys from ..paths import ( FINAL_PROFILE_ROOT, MODEL_PREFERENCE_PROFILE_ROOT, PROJECT_ROOT, model_profile_path, ) MODEL_PROFILE_MODULE = ( "scripts.static_compile.profile_generation.model_preference.run_profile" ) FORMAT_PROFILE_MODULE = ( "scripts.static_compile.profile_generation.format_preference.run_format_preference" ) def run_stage(label: str, command: list[str]) -> None: print(f"\n{'=' * 72}\n{label}\n{'=' * 72}", flush=True) subprocess.run(command, check=True, cwd=PROJECT_ROOT) def profile_paths(model_identifier: str) -> tuple[Path, Path]: """Return the behavioral source Profile and final combined Profile paths.""" upstream = model_profile_path(MODEL_PREFERENCE_PROFILE_ROOT, model_identifier) final = model_profile_path(FINAL_PROFILE_ROOT, model_identifier) return upstream, final def profile_is_reusable(profile_path: Path, model_identifier: str) -> bool: """Return whether a complete combined Profile matches the requested model.""" try: profile = json.loads(profile_path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return False model = profile.get("model") return bool( isinstance(model, dict) and model.get("id") == model_identifier.strip("/") and model.get("profile_status") == "complete" and isinstance(profile.get("behavioral_profile"), dict) and isinstance(profile.get("format_preference"), dict) ) def generate_profile( model_identifier: str, *, refresh_model_preference: bool = False, ) -> Path: """Run behavioral profiling followed by format profiling.""" model_id = model_identifier.strip("/") upstream_profile_path, final_profile_path = profile_paths(model_id) model_command = [sys.executable, "-m", MODEL_PROFILE_MODULE, model_id] if refresh_model_preference: model_command.append("--refresh") run_stage( "1/2 Model-preference profiling: collecting and evaluating behavior", model_command, ) run_stage( "2/2 Format-preference profiling: measuring output-format sensitivity", [ sys.executable, "-m", FORMAT_PROFILE_MODULE, "--model", model_id, "--profile_path", str(final_profile_path), "--base_profile_path", str(upstream_profile_path), ], ) if not profile_is_reusable(final_profile_path, model_id): raise RuntimeError( "profile generation did not produce a complete combined Profile at " f"{final_profile_path}" ) return final_profile_path def ensure_profile(model_identifier: str, *, refresh: bool = False) -> tuple[Path, bool]: """Reuse the final Profile when present, otherwise generate it.""" _, final_profile_path = profile_paths(model_identifier) if profile_is_reusable(final_profile_path, model_identifier) and not refresh: return final_profile_path, False return ( generate_profile( model_identifier, refresh_model_preference=refresh, ), True, )