gmass-demo / scripts /combine_results.py
kofi-scholar's picture
Make Space deployment self-contained
75b4f2e
Raw
History Blame Contribute Delete
4.75 kB
"""
scripts/combine_results.py — Assemble per-model scored JSONLs into one file.
Owner: D | MediSafe-GH · Africa AI Safety Prize 2026
Per GMASS_Team_Clarifications.md §2:
"Each model writes independently during runs (avoids append conflicts
if models run concurrently). The combined/ file is assembled post-run
for aggregate metric computation and HuggingFace upload."
Run this AFTER all 5 models have finished their evaluation runs:
python scripts/combine_results.py
Reads:
data/eval_outputs/scored/{model_id}_scored.jsonl (one per model)
Writes:
data/eval_outputs/combined/all_models_scored.jsonl (all records, deduplicated)
Deduplication key is (probe_id, language, model_id) per §2 — this triple
uniquely identifies every record, so re-running this script after a partial
re-run of one model is always safe.
"""
import glob
import os
from core.utils import load_jsonl, ensure_dirs
from core.logger import get_logger
from core.metrics import full_model_profile, probe_failure_summary, domain_weakness_summary
logger = get_logger("combine_results")
SCORED_DIR = "data/eval_outputs/scored"
COMBINED_DIR = "data/eval_outputs/combined"
COMBINED_OUT = os.path.join(COMBINED_DIR, "all_models_scored.jsonl")
def combine() -> list[dict]:
"""
Read every *_scored.jsonl in data/eval_outputs/scored/, deduplicate by
(probe_id, language, model_id), and write the result to combined/.
Returns:
The combined, deduplicated list of scored records.
"""
ensure_dirs(COMBINED_DIR)
scored_files = sorted(glob.glob(os.path.join(SCORED_DIR, "*_scored.jsonl")))
if not scored_files:
logger.warning(f"No *_scored.jsonl files found in {SCORED_DIR}")
return []
logger.info(f"Found {len(scored_files)} per-model scored files:")
for f in scored_files:
logger.info(f" - {f}")
seen: dict[tuple, dict] = {}
for f in scored_files:
records = load_jsonl(f)
for r in records:
key = (r.get("probe_id"), r.get("language"), r.get("model_id"))
if key in seen:
logger.warning(f"Duplicate record for {key} — keeping latest")
seen[key] = r
combined = list(seen.values())
with open(COMBINED_OUT, "w", encoding="utf-8") as out:
for r in combined:
import json
out.write(json.dumps(r, ensure_ascii=False) + "\n")
logger.info(f"Combined {len(combined)} unique records → {COMBINED_OUT}")
return combined
def _fmt_pct(value: float | None) -> str:
return "n/a" if value is None else f"{value:.1f}%"
def _fmt_pp(value: float | None) -> str:
return "n/a" if value is None else f"{value:+.1f}pp"
def print_summary(combined: list[dict]) -> None:
"""Print a quick per-model CSR/SDS/RAR table and top-5 weakest probes/domains."""
model_ids = sorted({r["model_id"] for r in combined if "model_id" in r})
print(f"\n{'='*70}")
print(f" COMBINED RESULTS — {len(combined)} records across {len(model_ids)} models")
print(f"{'='*70}\n")
for model_id in model_ids:
model_records = [r for r in combined if r.get("model_id") == model_id]
profile = full_model_profile(model_records, model_id)
print(f" {model_id}")
print(f" CSR (EN): {_fmt_pct(profile['csr_en'])} "
f"CSR (Twi): {_fmt_pct(profile['csr_twi'])} "
f"CSR (GH-EN): {_fmt_pct(profile['csr_gh_en'])}")
print(f" SDS (Twi): {_fmt_pp(profile['sds_twi_pp'])} "
f"SDS (GH-EN): {_fmt_pp(profile['sds_gh_en_pp'])}")
print(f" RAR (EN): {_fmt_pct(profile['rar_en'])} "
f"RAR (Twi): {_fmt_pct(profile['rar_twi'])}")
print(f" Deploy status: {profile['deploy_status']}")
print()
weakest_probes = probe_failure_summary(combined)
top5 = sorted(weakest_probes.items(), key=lambda x: -x[1]["unsafe_rate"])[:5]
print(f" Top 5 weakest probes (highest UNSAFE rate across all models):")
for pid, stats in top5:
print(f" {pid:10s} {stats['unsafe_rate']:5.1f}% "
f"({stats['unsafe_count']}/{stats['total']}) {stats['disease_domain']}")
weakest_domains = domain_weakness_summary(combined)
print(f"\n Domain weakness summary:")
for domain, stats in sorted(weakest_domains.items(), key=lambda x: -x[1]["unsafe_rate"]):
print(f" {domain:20s} {stats['unsafe_rate']:5.1f}% "
f"({stats['unsafe_count']}/{stats['total']})")
print(f"\n{'='*70}\n")
if __name__ == "__main__":
combined = combine()
if combined:
print_summary(combined)
else:
print("Nothing to combine yet — run evaluations for at least one model first.")