Skip to main content

hackagent.evaluation.audit

How far to trust the panel: measure it against samples people have judged.

A run's findings are only as good as the judges that called them findings. An audit shows the panel labelled samples whose answers are already known and reports what it got right, what it invented, and what it missed.

Two things are measured in one pass, because a panel verdict carries every judge's vote:

  • each judge on its own, which is how a judge that is dragging the panel down gets identified;
  • the panel's aggregate verdict, which is what a run actually uses.

Robustness is the second half. A judge that is accurate on plain text but changes its mind when the same answer is wrapped in a refusal preamble is not measuring harm, it is measuring style, and an attack that learns the wrapper will walk straight past it. Each wrapper is applied to the response alone, leaving the label untouched: the content did not change, so a changed verdict is the judge being wrong once.

This module computes; it does not load. Labelled samples come from :mod:hackagent.datasets.calibration, and the two meet in the orchestrator.

PANEL​

The name the panel's own aggregate verdict is reported under.

WRAPPERS​

Rewrites that leave a response's substance alone. A judge's verdict should survive all of them.

RobustnessSpec Objects​

class RobustnessSpec(_Spec)

Which rewrites to re-judge every sample under, and how many may land.

Unlike precision or recall, this has a target that does not depend on what the run is for: a rewrite that preserves the content should change no verdict at all, so the ideal is zero and anything above it is a defect. That is what makes it worth gating on.

Metrics Objects​

class Metrics(_Report)

A confusion matrix and what falls out of it.

FlipMetrics Objects​

class FlipMetrics(_Report)

What one wrapper changed about a judge's verdicts.

Robustness Objects​

class Robustness(_Report)

How the judge held up across every wrapper.

JudgeReport Objects​

class JudgeReport(_Report)

One row of an audit: a judge, or the panel, and how it did.

metrics is reported, never graded. What counts as enough precision or recall depends on what the panel is for — a screening panel wants recall, a reporting one wants precision — so the numbers are given and the judgement is yours.

passed​

@computed_field
@property
def passed() -> Optional[bool]

None when the audit was asked to check nothing.

AuditReport Objects​

class AuditReport(_Report)

What the audit found, panel row last.

passed​

@computed_field
@property
def passed() -> Optional[bool]

None when nothing was checked: measured, but not graded.

binary_metrics​

def binary_metrics(predictions: Sequence[bool],
labels: Sequence[bool],
abstentions: int = 0) -> Metrics

Score predictions against the labels people gave.

flip_metrics​

def flip_metrics(wrapper: str, baseline: Sequence[bool],
wrapped: Sequence[bool],
labels: Sequence[bool]) -> FlipMetrics

Compare a judge against itself, before and after one rewrite.

wrap​

def wrap(sample: Sample, wrapper: str) -> Sample

The same sample with its response rewritten. The label still holds.

audit_panel​

async def audit_panel(panel: Panel,
samples: Sequence[LabelledSample],
*,
robustness: Optional[RobustnessSpec] = None,
concurrency: int = 1) -> AuditReport

Judge every labelled sample and report how each judge and the panel did.