"""完整静态、Fast 与 Deep 技能编译流水线。""" from __future__ import annotations from pathlib import Path import shutil import sys from typing import Any from scripts.dynamic_compile.deep.pipeline import DeepLoop from scripts.dynamic_compile.fast.pipeline import run_pipeline as run_fast_pipeline from scripts.static_compile.compiler.compiler import compile_input from scripts.static_compile.profile_generation.pipeline import ensure_profile from .evaluation import ( MAX_PARALLEL, complete_deep_skill, deep_final_rollouts, evaluate, ) from .manifest import RunManifest, read_json_object from .paths import requested_run_root, single_skill_source, task_directory ORIGINAL_ROLLOUTS = 6 STATIC_ROLLOUTS = 6 FAST_ROLLOUTS = 3 FINAL_ROLLOUTS = 3 def _complete_static_skill(output: Path) -> tuple[Path, str] | None: complete: list[tuple[Path, str]] = [] if not output.is_dir(): return None for report_path in output.rglob("rewrite-report.json"): skill = report_path.parent report = read_json_object(report_path) if report is None or not (skill / "SKILL.md").is_file(): continue status = str(report.get("status", "failed")) if status not in {"failed", "rolled_back"}: complete.append((skill, status)) return complete[0] if len(complete) == 1 else None def run_pipeline( *, harness: str, model: str, external_model: str, task: str, run_dir: str | Path | None = None, ) -> Path: task_dir = task_directory(task) source_skills = single_skill_source(task_dir) task_name = task_dir.name run_root = requested_run_root(run_dir) if ( run_root.is_dir() and any(run_root.iterdir()) and not (run_root / "manifest.json").is_file() ): raise ValueError( f"non-empty run directory has no manifest and cannot be resumed: {run_root}" ) run_root.mkdir(parents=True, exist_ok=True) manifest = RunManifest( run_root / "manifest.json", harness=harness, model=model, external_model=external_model, task_dir=task_dir, ) artifacts = run_root / "artifacts" trace_task_root = run_root / "traces" / task_name original_traces = trace_task_root / "ori_skill" static_root = artifacts / "static" static_traces = trace_task_root / "model_skill" fast_score = artifacts / "fast" / "score" fast_output = artifacts / "fast" / "optimization" fast_traces = trace_task_root / "fast_skill" deep_output = artifacts / "deep" final_traces = trace_task_root / "final_skill" print(f"[compile-pipeline] run directory: {run_root}", file=sys.stderr, flush=True) try: manifest.stage("original_evaluation", "running", output=str(original_traces)) evaluate( harness=harness, model=model, task_dir=task_dir, skill_source=source_skills, output=original_traces, repeat=ORIGINAL_ROLLOUTS, ) manifest.stage( "original_evaluation", "complete", output=str(original_traces), rollouts=ORIGINAL_ROLLOUTS, max_parallel=MAX_PARALLEL, ) manifest.stage("profile", "running") profile_path, generated = ensure_profile(model) manifest.stage("profile", "complete", path=str(profile_path), generated=generated) cached_static = _complete_static_skill(static_root) if cached_static is not None: static_skill, static_status = cached_static print( f"[compile-pipeline] static compilation complete: {static_skill}; skipping", file=sys.stderr, flush=True, ) else: manifest.stage("static_compile", "running") static_results = compile_input( source_skills, profile_path, static_root, mode="hybrid", annotator_model=external_model, force=static_root.exists(), ) if len(static_results) != 1 or static_results[0].output_dir is None: raise RuntimeError("static compilation did not produce exactly one Skill package") static_status = str(static_results[0].report.get("status", "failed")) if static_status in {"failed", "rolled_back"}: raise RuntimeError(f"static compilation ended with status {static_status}") static_skill = static_results[0].output_dir manifest.stage( "static_compile", "complete", skill=str(static_skill), compile_status=static_status, ) manifest.stage("static_evaluation", "running", output=str(static_traces)) evaluate( harness=harness, model=model, task_dir=task_dir, skill_source=static_skill, output=static_traces, repeat=STATIC_ROLLOUTS, ) manifest.stage( "static_evaluation", "complete", output=str(static_traces), rollouts=STATIC_ROLLOUTS, max_parallel=MAX_PARALLEL, ) manifest.stage("fast_compile", "running") fast_skill = run_fast_pipeline( static_traces, static_skill, score_output=fast_score, output=fast_output, model=external_model, max_parallel=MAX_PARALLEL, ) manifest.stage("fast_compile", "complete", skill=str(fast_skill)) manifest.stage("fast_evaluation", "running", output=str(fast_traces)) evaluate( harness=harness, model=model, task_dir=task_dir, skill_source=fast_skill, output=fast_traces, repeat=FAST_ROLLOUTS, ) manifest.stage( "fast_evaluation", "complete", output=str(fast_traces), rollouts=FAST_ROLLOUTS, max_parallel=MAX_PARALLEL, ) final_skill = complete_deep_skill(deep_output) if final_skill is not None: print( f"[compile-pipeline] deep compilation complete: {final_skill}; skipping", file=sys.stderr, flush=True, ) else: manifest.stage("deep_compile", "running", output=str(deep_output)) deep_loop = ( DeepLoop(deep_output) if (deep_output / "run.json").is_file() else DeepLoop.create(fast_skill, fast_traces, deep_output, model=external_model) ) final_skill = deep_loop.drive() if complete_deep_skill(deep_output) is None: raise RuntimeError( f"deep compilation did not produce complete artifacts under {deep_output}" ) manifest.stage("deep_compile", "complete", skill=str(final_skill)) reusable_rollouts = deep_final_rollouts( deep_output, final_skill, FINAL_ROLLOUTS, ) if reusable_rollouts is not None: print( f"[compile-pipeline] copying Deep final rollouts to: {final_traces}", file=sys.stderr, flush=True, ) shutil.copytree(reusable_rollouts, final_traces, dirs_exist_ok=True) final_evaluation_output = final_traces manifest.stage("final_evaluation", "running", output=str(final_evaluation_output)) evaluate( harness=harness, model=model, task_dir=task_dir, skill_source=final_skill, output=final_evaluation_output, repeat=FINAL_ROLLOUTS, ) manifest.stage( "final_evaluation", "complete", output=str(final_evaluation_output), rollouts=FINAL_ROLLOUTS, max_parallel=MAX_PARALLEL, reused_deep_rollouts=reusable_rollouts is not None, ) manifest.complete(final_skill) return final_skill except Exception as exc: manifest.fail(exc) raise