File size: 2,909 Bytes
b2f5c42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
"""Evaluate rule routing vs lightweight ML routing."""

from __future__ import annotations

import argparse
import csv
import json
from pathlib import Path
import sys

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))

from pipeline.ml_router import DEFAULT_MODEL_DIR, MLRouter  # noqa: E402
from pipeline.v2_schema import SafetyTier, classify_route  # noqa: E402


DEFAULT_DATASET = ROOT / "eval" / "empathrag_core_supervised.csv"


def read_rows(path: Path) -> list[dict]:
    with path.open("r", encoding="utf-8-sig", newline="") as handle:
        return list(csv.DictReader(handle))


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--dataset", type=Path, default=DEFAULT_DATASET)
    parser.add_argument("--model-dir", type=Path, default=ROOT / DEFAULT_MODEL_DIR)
    parser.add_argument("--split", default="test")
    parser.add_argument("--output", type=Path, default=ROOT / "eval" / "router_eval_results.json")
    args = parser.parse_args()

    rows = [row for row in read_rows(args.dataset) if row.get("split") == args.split]
    router = MLRouter(args.model_dir)
    cases = []
    rule_route_correct = 0
    ml_route_correct = 0
    ml_tier_correct = 0

    for row in rows:
        expected_route = row["route_label"]
        expected_tier = row["safety_tier"]
        rule_route = classify_route(row["query_text"], SafetyTier(expected_tier), row.get("audience_mode") or "student").route.value
        pred = router.predict(row["query_text"], rule_route, expected_tier)
        rule_route_correct += int(rule_route == expected_route)
        ml_route_correct += int(pred.route_label == expected_route)
        ml_tier_correct += int(pred.safety_tier == expected_tier)
        cases.append(
            {
                "query_id": row["query_id"],
                "query_text": row["query_text"],
                "expected_route": expected_route,
                "rule_route": rule_route,
                "ml_route": pred.route_label,
                "expected_tier": expected_tier,
                "ml_tier": pred.safety_tier,
                "route_confidence": pred.route_confidence,
                "tier_confidence": pred.tier_confidence,
                "used_ml": pred.used_ml,
                "reason": pred.reason,
            }
        )

    total = len(rows)
    result = {
        "summary": {
            "rows": total,
            "model_available": router.available,
            "rule_route_accuracy": rule_route_correct / total if total else None,
            "ml_route_accuracy": ml_route_correct / total if total else None,
            "ml_tier_accuracy": ml_tier_correct / total if total else None,
        },
        "cases": cases,
    }
    args.output.write_text(json.dumps(result, indent=2), encoding="utf-8")
    print(json.dumps(result["summary"], indent=2))


if __name__ == "__main__":
    main()