"""汇总 S4 一次运行:按银标准类型(★ / 斜体下划线)算总召回,列出漏掉的句子。""" import json, sys, pathlib OUT = pathlib.Path(__file__).parent / "out" tag = sys.argv[1] summary = json.loads((OUT / f"run-{tag}" / "summary.json").read_text()) agg = {"star": [0, 0, 0], "iu": [0, 0, 0]} # 严格命中、相邻命中、总数 missed = [] for sid in summary["docs"]: sents = json.loads((OUT / f"{sid}-input.json").read_text()) order = {s["id"]: i for i, s in enumerate(sents)} res = json.loads((OUT / f"run-{tag}" / f"{sid}.json").read_text()) cited = {e["sid"] for r in res for it in r["accepted"] for e in it["evidence"]} near = {sents[j]["id"] for c in cited for j in (order[c] - 1, order[c], order[c] + 1) if 0 <= j < len(sents)} for s in sents: if s["silver"]: a = agg[s["silver"]]; a[2] += 1; a[0] += s["id"] in cited; a[1] += s["id"] in near if s["id"] not in near: missed.append((sid, s["silver"], s["id"], s["text"][:60])) for k, (st, nb, n) in agg.items(): print(f"{k}: strict {st}/{n} = {st/n:.1%}, neighbor {nb}/{n} = {nb/n:.1%}") acc = sum(d["eval"]["accepted_items"] for d in summary["docs"].values()) ok = sum(round(d["eval"]["precision_incl_explicit_invalid"] * d["eval"]["accepted_items"]) for d in summary["docs"].values()) pend = sum(d["eval"]["pending_items"] for d in summary["docs"].values()) evt = sum(d["eval"]["evidence_total"] for d in summary["docs"].values()); evp = sum(d["eval"]["evidence_pass"] for d in summary["docs"].values()) print(f"accepted {acc}, on-silver-or-explicit-invalid {ok} = {ok/acc:.1%}, pending {pend}, evidence pass {evp}/{evt} = {evp/evt:.1%}") print("total usage", summary["total_usage"]) for m in missed: print(" MISSED", m)