| """Stage-1 scorer: foundational-authority recall + control no-regression. |
| Runs each gold query through the live deep/fast API and checks whether the tagged seminal |
| authority surfaces in the returned results. Baseline before the citation-graph + agent work. |
| |
| Run on Thor: python3 32_score_foundational.py (hits localhost:8000) |
| """ |
| import json, re, urllib.request, urllib.parse, os |
|
|
| GOLD = os.path.join(os.path.dirname(__file__), "..", "eval", "gold_foundational.json") |
| GOLD = os.path.normpath(GOLD) if os.path.exists(GOLD) else "gold_foundational.json" |
| BASE = "http://127.0.0.1:8000" |
|
|
| EP = os.environ.get("THEMIS_EP", "search_stream") |
| def search(q): |
| url = f"{BASE}/api/{EP}?q=" + urllib.parse.quote(q) |
| results = [] |
| with urllib.request.urlopen(url, timeout=120) as r: |
| for raw in r: |
| line = raw.decode("utf-8", "ignore") |
| if line.startswith("data: "): |
| ev = json.loads(line[6:]) |
| if ev.get("t") == "results": |
| results = ev["results"] |
| return results |
|
|
| def matches(case_name, alts): |
| nm = (case_name or "").lower() |
| return any(all(re.search(r"\b" + re.escape(tok) + r"\b", nm) for tok in alt) for alt in alts) |
|
|
| gold = json.load(open(GOLD)) |
| found_q = [g for g in gold if g["foundational"] and not g["control"]] |
| ctrl_q = [g for g in gold if g["control"]] |
|
|
| h5 = h8 = 0 |
| print("=== FOUNDATIONAL-AUTHORITY RECALL ===") |
| for g in found_q: |
| res = search(g["query"]) |
| names = [r.get("case_name") for r in res] |
| rank = next((i + 1 for i, n in enumerate(names) if matches(n, g["foundational"])), None) |
| in5 = rank is not None and rank <= 5 |
| in8 = rank is not None and rank <= 8 |
| h5 += in5; h8 += in8 |
| tag = "/".join("+".join(a) for a in g["foundational"]) |
| mark = "HIT@5" if in5 else ("HIT@8" if in8 else "MISS ") |
| print(f" {mark} {g['id']:10} foundational[{tag}]" + (f" at #{rank}" if rank else f" (top: {names[0][:38] if names else '-'})")) |
| print(f"\nFoundational Recall@5 (groundable): {h5}/{len(found_q)} = {h5/len(found_q):.2f} [CP-A baseline]") |
| print(f"Foundational Recall@8 (shown): {h8}/{len(found_q)} = {h8/len(found_q):.2f}") |
|
|
| print("\n=== CONTROL (no-regression: lookup must still return the exact case at #1) ===") |
| creg = 0 |
| for g in ctrl_q: |
| res = search(g["query"]) |
| names = [r.get("case_name") for r in res] |
| top1 = matches(names[0], g["foundational"]) if names else False |
| creg += top1 |
| print(f" {'OK ' if top1 else 'REGRESSED'} {g['id']:10} top1={names[0][:42] if names else '-'}") |
| print(f"\nControl held: {creg}/{len(ctrl_q)}") |
|
|