feat: per-attack-family ASR diagnostics in evaluation output - #6
feat: per-attack-family ASR diagnostics in evaluation output#6perezpefaur wants to merge 3 commits into
Conversation
Every baseline, candidate, and evaluate run now prints a per-attack-family ASR breakdown (ranked leakiest-first) alongside the aggregate ASR, so each iteration becomes a targeted, one-family-at-a-time worklist instead of a single opaque number. Families are derived from the existing harness attack taxonomy and counts are pooled across repeated passes, so the frozen evaluation surface (eval_suite.jsonl, judge_prompt.md) is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
|
I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
|
recheck |
|
Hi @perezpefaur — thanks for the contribution! The only thing pending before we can review/merge is the CLA. Please post the following comment on this PR to sign it:
Once signed, the CLA Assistant check will turn green automatically. 🙌 |
|
Hi @perezpefaur — thanks again for this contribution. The change itself looks good and all CI checks are green (lint, tests on Python 3.10/3.11/3.12, CodeQL, no-runtime-deps). The only thing blocking the merge is the CLA: it hasn't been signed yet, so the To unblock, please post a new comment on this PR with exactly this text:
Once the CLA Assistant re-runs and turns green, we'll merge right away. Thanks! |
|
Friendly ping @perezpefaur 👋 — this PR is good to go and fully green; we're just waiting on your CLA signature to merge. Please drop a comment with:
Thanks! |
|
Hi @perezpefaur, and thank you for this contribution! 🙏 We reviewed the change in depth and the substance is approved — this is a genuinely useful addition. The per-attack-family ASR breakdown turns "lower the ASR" into a concrete, one-family-at-a-time worklist, it reuses the harness's existing attack taxonomy instead of inventing new heuristics, it stays fully backward-compatible ( Two things are needed before we can merge (neither is about code quality):
Once the rebase is done and the CLA check turns green, we'll re-run CI and merge. Thanks again for the clean, well-tested contribution! |
Description
The research loop optimizes a single number — aggregate
ASR— but the documentedworkflow is to lower it one attack family at a time (see the README "Typical
Iteration Pattern"). Today the harness gives no family-level signal, so after each
run you cannot tell which family is still leaking and therefore what to edit in
policy.mdnext. You're effectively flying blind between iterations.This PR adds a per-attack-family ASR breakdown to every
baseline,candidate,and
evaluaterun, printed right after the aggregate metrics and rankedleakiest-first:
This turns "lower the ASR" into a concrete, targeted worklist: the top line is
usually the best next target for a policy edit.
How it works
(
ATTACK_FAMILIESinmodel_adapter.py) viaclassify_prompt_family, so there isa single source of truth and no new heuristics. It is a diagnostic lens, not ground
truth; prompts that match no family are bucketed as
unclassified.EvaluationSummary/RepeatedEvaluationSummarygain an optional, backward-compatiblefamily_statsfield (defaults to()), and counts are pooled across repeatedpasses (
n = cases × repeats).autoguardrails/README.md.Related issue
N/A
Type of change
Research contract
eval_suite.jsonl,judge_prompt.md)Families are derived from the prompts at runtime using the taxonomy already shipped in
the fixed harness, so no scoring inputs change and existing
results.tsvnumbers remaincomparable. The
results.tsvschema is intentionally left untouched.Checklist
ruff check .andblack --check .passmypy autoguardrailspassespython -m pytestpasses (32 tests, coverage 91%)Test plan
asr=0.0, uncovered stay at1.0), counts pool across repeats, ordering isdeterministic, the
FamilyStat.asrzero-division branch is covered, and the CLIranks leaky families above covered ones.
Made with Cursor