askmydocs / scripts /update_baseline.py
Prabu17's picture
Upload folder using huggingface_hub
f8b48da verified
Raw History Blame Contribute Delete
4.54 kB
"""
Update the stored evaluation baseline with the latest experiment results.
This script should be run MANUALLY after a successful evaluation run
when you want to record the current implementation's performance as the
new golden baseline for regression detection.
Run:
python scripts/update_baseline.py
python scripts/update_baseline.py --experiment hybrid --output evals/baselines/baseline.json
Exit codes:
0 — baseline updated successfully
1 — no results found or error
"""
from __future__ import annotations
import argparse
import json
import sys
from datetime import UTC, datetime
from pathlib import Path
from app.evaluation.regression import save_baseline
from app.evaluation.runner import run_evaluation
ROOT = Path(__file__).resolve().parent.parent
DEFAULT_OUTPUT = ROOT / "evals" / "baselines" / "baseline.json"
RESULTS_DIR = ROOT / "evals" / "results"
def _latest_result(experiment: str) -> Path | None:
results_exp_dir = RESULTS_DIR / experiment
if not results_exp_dir.exists():
return None
files = sorted(results_exp_dir.glob("*.json"), key=lambda p: p.stat().st_mtime)
return files[-1] if files else None
def main() -> int:
parser = argparse.ArgumentParser(
description="Update the stored evaluation baseline.",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--experiment",
"-e",
choices=["vector", "bm25", "hybrid", "final"],
default="final",
help="Which experiment result to promote to baseline",
)
parser.add_argument(
"--output",
"-o",
type=str,
default=str(DEFAULT_OUTPUT),
help="Where to write the baseline JSON",
)
parser.add_argument(
"--from-run",
action="store_true",
help="Run evaluation first and use those results (slow), "
"otherwise use the latest stored results",
)
parser.add_argument(
"--check",
action="store_true",
help="Load the baseline and print a summary without updating anything. "
"Exits 0 if the baseline exists, 1 if it is missing.",
)
args = parser.parse_args()
# --check: validate baseline exists and print a summary without updating
if args.check:
baseline_path = Path(args.output)
if not baseline_path.exists():
print(f"Baseline not found: {baseline_path}", file=sys.stderr)
return 1
data = json.loads(baseline_path.read_text(encoding="utf-8"))
print(f"Baseline exists: {baseline_path}")
print(f" Experiment : {data.get('experiment_name', 'unknown')}")
print(f" Questions : {data.get('question_count', '?')}")
agg_ret = data.get("aggregate_retrieval", {})
print(f" Recall@10 : {agg_ret.get('recall_at_k', 'N/A')}")
print(f" Hit Rate : {agg_ret.get('hit_rate', 'N/A')}")
agg_cit = data.get("aggregate_citation", {})
print(f" Citation : {agg_cit.get('citation_correctness', 'N/A')}")
return 0
# Find the results to promote
if args.from_run:
print(f"Running evaluation experiment={args.experiment} (mock mode) ...")
results = run_evaluation(experiment=args.experiment, mock=True)
output_path = Path(args.output)
save_baseline(results, output_path)
print(f"Baseline updated from fresh run: {output_path}")
return 0
result_path = _latest_result(args.experiment)
if result_path is None:
print(
f"No results found for experiment={args.experiment} in {RESULTS_DIR}",
file=sys.stderr,
)
print("Run 'make eval' first, or use --from-run to evaluate now.", file=sys.stderr)
return 1
data = json.loads(result_path.read_text(encoding="utf-8"))
output_path = Path(args.output)
output_path.parent.mkdir(parents=True, exist_ok=True)
data["_saved_at"] = datetime.now(UTC).isoformat() # UTC is already imported
data["_source_file"] = str(result_path)
output_path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"Baseline updated: {output_path}")
print(f" Source: {result_path.name}")
print(f" Experiment: {data.get('experiment_name')}")
print(f" Questions: {data.get('question_count')}")
return 0
if __name__ == "__main__":
sys.exit(main())