Initial commit
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
"""完整静态、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
|
||||
Reference in New Issue
Block a user