Audit an OpenMed NER or de-identification model for performance disparities across demographic subgroups (sex, age band, race/ethnicity when available) using openmed.eval.fairness_report. Use when the user wants per-subgroup recall and leakage, wants to check whether de-identification under-protects a group, wants to surface a documentation gap where subgroup data is missing, or needs equalized-odds-style disparity numbers for a clinical model. Trigger on "fairness", "subgroup", "bias audit", "disparity", "equalized odds", "under-protected group", "per-group recall", or "STANDING Together" for an OpenMed model.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
An aggregate pass can hide a group the model fails. For de-identification that
failure has a name: under-protection — PHI that leaks more often for one
demographic group than another. openmed.eval.fairness_report slices leakage and
recall by gold-span group so disparities surface before deployment, not after a
breach.
For each surrogate group fairness_report returns:
max - min leakage across groups (the gap to close).Group membership comes from a group tag in each gold span's metadata (keys
group, demographic_group, or surrogate_group); ungrouped spans fall into
unspecified.
from openmed.eval import fairness_report
# Gold fixtures must tag spans with a surrogate group, e.g.
# {"start": 4, "end": 12, "label": "PERSON", "metadata": {"group": "female"}}
fair = fairness_report(
"OpenMed/Privacy-PII-Detection",
"golden", # named suite, or pass a list of fixtures
device="cpu",
)
print("leakage disparity:", fair.leakage_disparity)
print("worst group :", fair.worst_group, fair.worst_group_leakage)
for group, m in sorted(fair.per_group.items()):
print(f" {group:14s} recall={m.recall:.3f} leakage={m.leakage_rate:.4f}")
# Under-protection alarm: any group leaking more than the rest.
LEAKAGE_GAP_LIMIT = 0.0 # leakage-first: ideally zero leakage everywhere
assert fair.leakage_disparity <= LEAKAGE_GAP_LIMIT or fair.worst_group_leakage == 0FairnessReport.to_dict() is JSON-ready and PHI-free — drop it straight into a
model card.
group to each PHI span's
metadata (sex, age band, race/ethnicity surrogate). Use synthetic surrogates,
not real protected attributes (see building-gold-corpus).fairness_report on the model + suite.leakage_disparity) and locate worst_group.
Equalized-odds framing: equal true-positive (recall) and equal leakage
across groups.building-gold-corpus: supplies group-tagged synthetic fixtures.evaluating-with-leakage-gates: an aggregate RELEASABLE decision
should be paired with this audit — overall pass, subgroup fail is exactly the
trap this catches.authoring-model-cards: FairnessReport.to_dict() fills the
quantitative-analysis / subgroup section.benchmarking-clinical-ner: same run, different slice (label vs
group).unspecified is not a real group. A pile of spans in unspecified means
your gold isn't tagged; fix the corpus before trusting the disparity.span_count,
total_chars) alongside rates; a 1-of-2 leak isn't a 50% population rate.openmed/eval/fairness.py
(fairness_report, FairnessReport, FairnessGroupMetrics).maziyarpanahi/openmed
00e9efd
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.