[BREAKING] FEAT: Restructure Psychosocial scenario for per-subharm scoring#1943
Open
varunj-msft wants to merge 2 commits into
Open
Conversation
rlundeen2
reviewed
Jun 4, 2026
rlundeen2
reviewed
Jun 4, 2026
rlundeen2
reviewed
Jun 4, 2026
rlundeen2
reviewed
Jun 5, 2026
6106e65 to
5dcb74a
Compare
Contributor
Author
|
Pushed the restructure. Only open question is TARGET_REQUIREMENTS (in the refactor thread). Also retitling since this isn't a bugfix anymore |
Contributor
|
Maybe we should hold off until the DataConfiguration refactor is in |
rlundeen2
reviewed
Jun 22, 2026
Re-implement the Psychosocial scenario following rlundeen2's review: - Split the single combined dataset into two per-subharm datasets (airt_imminent_crisis, airt_licensed_therapist), each with its own scoring rubric and Crescendo escalation prompt. - Build atomic attacks as the (technique x subharm) cross product, so each attack carries the scorer matching its seed's subharm. This fixes the bug where running all subharms scored every attack with a single fallback rubric. - Move subharm selection to --dataset-names; strategies are now technique-only (prompt_sending / role_play in the default aggregate, crescendo opt-in). - Keep the baseline enabled by default, emitting one baseline per subharm with its matching scorer; name the first "baseline" so the base scenario does not additionally prepend a generic single-scorer baseline. - Raise a clear error when no seeds are loaded for any selected subharm instead of surfacing the base class's cryptic empty-seed_groups failure. VERSION bumped to 3.
5dcb74a to
f9df8af
Compare
… scoring Add a plural _build_baseline_atomic_attacks helper + BaselineSpec and an is_baseline flag on AtomicAttack. Switch the central baseline rescue to check is_baseline instead of the atomic_attack_name == "baseline" literal, so an override can emit its own baselines under any name and the base does not double-prepend. Psychosocial now emits one baseline per subharm through the shared helper (each with that subharm's scorer and display group) instead of hand-rolling PromptSendingAttack/AtomicAttack. Foundry's bare composite (no attack, no converters) is flagged is_baseline so it is likewise recognized and not double-prepended.
Contributor
Author
Contributor
|
The scenario doesn't use the new patterns. It predates the refactor. ScenarioContext.seed_groups_by_dataset does do what I asked for, but the issue is solved upstream.
I might build on top of main, and get rid of this branch. Keep some ideas here (per-subharm scorer + crescendo path, per-subharm baseline naming) but express them via _build_atomic_attacks_async(context), seed_groups_by_dataset, central baseline, and subharm-aware technique selection (dropping role_play for licensed_therapist). |
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
Restructures the Psychosocial scenario so strategies are techniques and subharms are datasets. Started as the
--max-dataset-sizefast-path bugfix and grew into the full standardization Rich sketched in review.Strategies are techniques now. The strategy enum is
prompt_sending,role_play,crescendoinstead of the old subharm-as-strategy anti-pattern. Subharm selection moves off--strategiesand onto--dataset-names.Seed file split per subharm.
psychosocial.promptbecomesairt_imminent_crisis.prompt+airt_licensed_therapist.prompt, each carrying its own scorer rubric and crescendo escalation prompt. This removes runtime harm-filtering entirely — there's no longer a cap-vs-filter ordering to get wrong, which is what made--max-dataset-size 1fail before.Per-subharm scorers. One
FloatScaleThresholdScoreris built per subharm and routed to both theAtomicAttackand the technique'sAttackScoringConfig, so runningallno longer scores attacks with the wrong rubric.Per-subharm baselines. Via a generalized base-class mechanism. Baseline identity now lives on the model: AtomicAttack gains an is_baseline flag, and the central baseline rescue in Scenario.initialize_async checks any(aa.is_baseline for aa in self._atomic_attacks) instead of matching the literal name "baseline". MatrixAtomicAttackBuilder gains a BaselineSpec dataclass and a plural _build_baseline_atomic_attacks helper. Psychosocial uses this to emit one baseline per subharm (baseline_imminent_crisis / baseline_licensed_therapist), each carrying that subharm's scorer and display group, so the two no longer collide on a shared "baseline" key. Foundry's red_team_agent.py bare composite (no attack, no converters) is flagged is_baseline so it is likewise recognized and not double-prepended.
initialize_asyncvalidates dataset names. A user-supplieddataset_configis allowed only if its dataset names are a subset of the subharms, so--max-dataset-size Nstill works while custom names are rejected with a clear error.Crescendo is kept out of the
defaultaggregate (opt-in via--strategies all/--strategies crescendo) since it's the heaviest technique — default runs are single-turn.BASELINE_ATTACK_POLICYis back toEnabled, andVERSIONis bumped 2→3 because the default behavior changed; stored v2 results raise cleanly on--resumerather than silently mixing semantics.One deliberate divergence from the review sketch, flagged inline:
TARGET_REQUIREMENTSis left at the base default rather thanEDITABLE_HISTORY. With Crescendo opt-in, the default run is single-turn, and requiring editable history at the scenario level would rejectOpenAIChatTargetbefore the strategy resolves. Crescendo enforces that requirement itself when it runs. Easy to flip back if preferred.Tests and Documentation
Reworked tests/unit/scenario/airt/test_psychosocial.py around the new shape — 27 tests across 6 classes:
This PR also generalizes baseline handling in shared infrastructure (pyrit/scenario/core/atomic_attack.py, matrix_atomic_attack_builder.py, scenario.py) and updates Foundry (pyrit/scenario/scenarios/foundry/red_team_agent.py), with a regression test tests/unit/scenario/foundry/test_red_team_agent.py::test_bare_composite_baseline_not_double_prepended.
Validation: