File size: 1,965 Bytes
a39757f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""Evaluate OCR outputs against a JSONL ground-truth manifest.

Manifest rows: {"id": str, "expected_text": str, "actual_text": str,
                "expected_fields": {..}, "actual_fields": {..}}
Use `--outputs` to score an already-generated JSONL file. Without outputs,
the manifest itself must include actual_text/actual_fields from a prior run.
"""

import argparse
import json
from pathlib import Path

from app.services.ocr.metrics import aggregate_text_metrics, field_metrics, text_metrics


def evaluate(rows):
    results = []
    field_scores = []
    for row in rows:
        text = text_metrics(row.get("expected_text", ""), row.get("actual_text", ""))
        expected_fields = row.get("expected_fields", {})
        actual_fields = row.get("actual_fields", {})
        fields = field_metrics(expected_fields, actual_fields) if expected_fields else None
        results.append({"id": row.get("id"), "text": text, "fields": fields})
        if fields is not None:
            field_scores.append(fields)
    return {
        "samples": len(rows),
        "text": aggregate_text_metrics(rows),
        "field_accuracy": (
            sum(s["correct"] for s in field_scores) / max(sum(s["total"] for s in field_scores), 1)
            if field_scores else None
        ),
        "field_count": sum(s["total"] for s in field_scores),
        "records": results,
    }


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("manifest", type=Path)
    parser.add_argument("--output", type=Path, help="Write report JSON to this path")
    args = parser.parse_args()
    rows = [json.loads(line) for line in args.manifest.read_text(encoding="utf-8").splitlines() if line.strip()]
    report = evaluate(rows)
    rendered = json.dumps(report, ensure_ascii=False, indent=2)
    if args.output:
        args.output.write_text(rendered + "\n", encoding="utf-8")
    print(rendered)


if __name__ == "__main__":
    main()