FEAT: add ViolenceClassifierScorer, a CPU violence classifier with an abstain band - #2626
Open
WatchTree-19 wants to merge 1 commit into
Open
WatchTree-19 wants to merge 1 commit into
WatchTree-19 wants to merge 1 commit into
Conversation
… abstain band Scores the violence harm category with a frozen bge-small-en-v1.5 encoder and a small MLP head trained from PyRIT's own human-labeled violence datasets, instead of an LLM judge. The head trains on first use from the in-package CSVs, whose bytes are hash-pinned so a changed dataset fails loudly rather than scoring with an unvalidated model. Probabilities are temperature-calibrated on out-of-fold predictions; scores inside the abstain band are returned as UNDETERMINED so callers can route the uncertain tail to an LLM judge. Out-of-fold cross-validation on the training rows: AUC 0.83-0.86 across seeds, ECE about 0.04 after calibration, and with the default band about 0.70 coverage at 0.87 accuracy versus 0.76 at full coverage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MFydrdwX6iPvUuGiqKDybJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a scorer for the violence harm category that runs a small CPU classifier instead of an LLM judge, following the direction discussed with Roman Lutz (@romanlutz): traditional ML scoring with the classifier carrying the bulk and an LLM judge taking the uncertain tail.
The scorer embeds the objective/response pair with a frozen bge-small-en-v1.5 encoder (pinned revision, same pattern as RobloxPiiScorer) and applies a single-hidden-layer MLP trained from PyRIT's own human-labeled violence datasets in
pyrit/datasets/scorer_evals/harm. The head trains on first use in seconds, so no model binary ships in the PR and the whole model reproduces from the repository. The dataset bytes are SHA-256 pinned: if the gold set changes, the scorer refuses to train rather than silently returning numbers validated against different data.Probabilities are temperature-calibrated on out-of-fold predictions. Scores inside the abstain band (default 0.3 to 0.7) are returned with
ScoreStatus.UNDETERMINEDso callers can route them to an LLM judge. Out-of-fold cross-validation on the training rows: AUC 0.83 to 0.86 across seeds, ECE about 0.04 after calibration, and with the default band about 0.70 coverage at 0.87 accuracy versus 0.76 at full coverage. ThroughHarmScorerEvaluatorout of sample (trained on the multi-score rows only, evaluated on the disjoint violence.csv), MAE is 0.235 against 0.244 for AzureContentFilterScorer on the same 96 rows; the gpt-4o Likert judge is at 0.161, partly because this scorer outputs probability of harmful rather than a severity estimate.On operating points: the score is a calibrated probability, so callers can tune for their own FNR/FPR preference with FloatScaleThresholdScorer or the abstain band. From out-of-fold cross-validation: threshold 0.50 gives FNR 0.27 at FPR 0.21, 0.30 gives 0.11 at 0.36, 0.20 gives 0.05 at 0.53. For a low-false-negative configuration, lowering the abstain band's bottom edge (e.g. 0.15 to 0.7) sends borderline responses to the judge rather than marking them safe.
The scorer is restricted to violence deliberately. On these same gold sets, small classifiers are near chance for several other harm categories, so a general head would return confident numbers it cannot support. Extending to other categories, and a composite scorer that automatically routes abstentions to a judge, are natural follow-ups where the data supports them.
No new dependencies; torch and transformers come from the existing
huggingfaceextra.Tests and Documentation
15 unit tests: score construction, abstain behaviour, determinism of the train step, the dataset-hash guard (including that it passes when re-pinned, so the guard is shown to discriminate), and validator config. A section is added to
doc/code/scoring/2_float_scale_scorers.pyand the paired notebook (cells added without outputs; happy to regenerate if preferred).Written with AI assistance.