| |
| """ |
| Score OCR predictions against a ground-truth annotation file. |
| |
| This gives us a stable benchmark before wiring OCR into production indexing. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import sys |
| from pathlib import Path |
|
|
|
|
| ROOT_DIR = Path(__file__).resolve().parents[1] |
| BACKEND_DIR = ROOT_DIR / "backend" |
| if str(BACKEND_DIR) not in sys.path: |
| sys.path.insert(0, str(BACKEND_DIR)) |
|
|
| from ocr_ground_truth import build_benchmark_report, load_ground_truth, load_predictions |
|
|
|
|
| def build_parser() -> argparse.ArgumentParser: |
| parser = argparse.ArgumentParser(description="Score OCR predictions against Search-UI ground truth.") |
| parser.add_argument("--ground-truth", required=True, type=Path, help="Ground-truth JSON file") |
| parser.add_argument("--predictions", required=True, type=Path, help="Predictions JSON file") |
| parser.add_argument( |
| "--report", |
| type=Path, |
| default=ROOT_DIR / "docs" / "reports" / "ocr-benchmark-report.json", |
| help="Where to write the report JSON", |
| ) |
| return parser |
|
|
|
|
| def main() -> int: |
| args = build_parser().parse_args() |
| annotations = load_ground_truth(args.ground_truth) |
| predictions = load_predictions(args.predictions) |
| report = build_benchmark_report(annotations, predictions) |
|
|
| args.report.parent.mkdir(parents=True, exist_ok=True) |
| args.report.write_text(json.dumps(report, indent=2, ensure_ascii=False), encoding="utf-8") |
|
|
| summary = report["summary"] |
| print( |
| "OCR benchmark:" |
| f" segments={summary['segments']}" |
| f" exact_match_rate={summary['exact_match_rate']}" |
| f" avg_similarity={summary['average_normalized_edit_similarity']}" |
| f" junk_rate={summary['junk_prediction_rate']}" |
| f" missing_rate={summary['missing_prediction_rate']}" |
| ) |
| print(f"Report: {args.report}") |
| return 0 |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|