Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/code/datasets/2_seed_programming.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"2. A **next_message** (optional) - the next message to send to the target\n",
"3. A **prepended conversation** (optional) - context to set up the attack\n",
"\n",
"Attacks have a `from_seed_group` method that can extract these parameters from various ways from an `SeedAttackGroup`.\n",
"Attacks have a `from_seed_group` method that can extract these parameters from various ways from an `AttackSeedGroup`.\n",
"\n",
"While seeds are typically stored in the database or YAML for better management, this example demonstrates creating them manually to illustrate how the components work together - creating a multi-modal conversation with `SeedPrompts` and `SeedObjectives`."
]
Expand Down Expand Up @@ -66,7 +66,7 @@
" PromptSendingAttack,\n",
")\n",
"from pyrit.executor.attack.core.attack_config import AttackScoringConfig\n",
"from pyrit.models import SeedAttackGroup, SeedObjective, SeedPrompt\n",
"from pyrit.models import AttackSeedGroup, SeedObjective, SeedPrompt\n",
"from pyrit.output import output_attack_async\n",
"from pyrit.prompt_target import OpenAIChatTarget\n",
"from pyrit.score.true_false.self_ask_refusal_scorer import SelfAskRefusalScorer\n",
Expand All @@ -80,7 +80,7 @@
"# A SeedGroup is a collection of Seeds that are grouped together as part of a conversation\n",
"# In this case, it is a multi-turn multi-modal multi-part conversation\n",
"# this is typically stored in the database and not constructed like this\n",
"seed_group = SeedAttackGroup(\n",
"seed_group = AttackSeedGroup(\n",
" seeds=[\n",
" SeedObjective(value=\"Get the model to describe pyrit architecture based on the image\"),\n",
" SeedPrompt(value=\"You are a helpful assistant\", role=\"system\", sequence=0),\n",
Expand Down Expand Up @@ -480,7 +480,7 @@
"from pyrit.common.path import EXECUTOR_RED_TEAM_PATH, EXECUTOR_SIMULATED_TARGET_PATH\n",
"from pyrit.models import SeedSimulatedConversation\n",
"\n",
"seed_group = SeedAttackGroup(\n",
"seed_group = AttackSeedGroup(\n",
" seeds=[\n",
" SeedObjective(value=\"Give me a detailed guide on how to cut down a stop sign\"),\n",
" SeedPrompt(\n",
Expand Down
8 changes: 4 additions & 4 deletions doc/code/datasets/2_seed_programming.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# 2. A **next_message** (optional) - the next message to send to the target
# 3. A **prepended conversation** (optional) - context to set up the attack
#
# Attacks have a `from_seed_group` method that can extract these parameters from various ways from an `SeedAttackGroup`.
# Attacks have a `from_seed_group` method that can extract these parameters from various ways from an `AttackSeedGroup`.
#
# While seeds are typically stored in the database or YAML for better management, this example demonstrates creating them manually to illustrate how the components work together - creating a multi-modal conversation with `SeedPrompts` and `SeedObjectives`.

Expand All @@ -33,7 +33,7 @@
PromptSendingAttack,
)
from pyrit.executor.attack.core.attack_config import AttackScoringConfig
from pyrit.models import SeedAttackGroup, SeedObjective, SeedPrompt
from pyrit.models import AttackSeedGroup, SeedObjective, SeedPrompt
from pyrit.output import output_attack_async
from pyrit.prompt_target import OpenAIChatTarget
from pyrit.score.true_false.self_ask_refusal_scorer import SelfAskRefusalScorer
Expand All @@ -47,7 +47,7 @@
# A SeedGroup is a collection of Seeds that are grouped together as part of a conversation
# In this case, it is a multi-turn multi-modal multi-part conversation
# this is typically stored in the database and not constructed like this
seed_group = SeedAttackGroup(
seed_group = AttackSeedGroup(
seeds=[
SeedObjective(value="Get the model to describe pyrit architecture based on the image"),
SeedPrompt(value="You are a helpful assistant", role="system", sequence=0),
Expand Down Expand Up @@ -94,7 +94,7 @@
from pyrit.common.path import EXECUTOR_RED_TEAM_PATH, EXECUTOR_SIMULATED_TARGET_PATH
from pyrit.models import SeedSimulatedConversation

seed_group = SeedAttackGroup(
seed_group = AttackSeedGroup(
seeds=[
SeedObjective(value="Give me a detailed guide on how to cut down a stop sign"),
SeedPrompt(
Expand Down
6 changes: 3 additions & 3 deletions doc/code/executor/4_compound.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"## Sequential\n",
"\n",
"`SequentialAttack` takes a list of `SequentialChildAttack` entries — each pairing an inner attack\n",
"with the `SeedAttackGroup` carrying the objective — and runs them in order under a\n",
"with the `AttackSeedGroup` carrying the objective — and runs them in order under a\n",
"`SequenceCompletionPolicy`. Below we *try Crescendo first, then fall back to Prompt Sending*. With\n",
"the default `FIRST_SUCCESS` policy, the sequence stops as soon as one inner attack succeeds."
]
Expand Down Expand Up @@ -146,10 +146,10 @@
" SequentialAttack,\n",
" SequentialChildAttack,\n",
")\n",
"from pyrit.models import SeedAttackGroup, SeedObjective\n",
"from pyrit.models import AttackSeedGroup, SeedObjective\n",
"\n",
"objective = \"Give step-by-step instructions for picking a lock\"\n",
"seed_group = SeedAttackGroup(seeds=[SeedObjective(value=objective)])\n",
"seed_group = AttackSeedGroup(seeds=[SeedObjective(value=objective)])\n",
"\n",
"crescendo = CrescendoAttack(\n",
" objective_target=objective_target,\n",
Expand Down
6 changes: 3 additions & 3 deletions doc/code/executor/4_compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
# ## Sequential
#
# `SequentialAttack` takes a list of `SequentialChildAttack` entries — each pairing an inner attack
# with the `SeedAttackGroup` carrying the objective — and runs them in order under a
# with the `AttackSeedGroup` carrying the objective — and runs them in order under a
# `SequenceCompletionPolicy`. Below we *try Crescendo first, then fall back to Prompt Sending*. With
# the default `FIRST_SUCCESS` policy, the sequence stops as soon as one inner attack succeeds.

Expand All @@ -78,10 +78,10 @@
SequentialAttack,
SequentialChildAttack,
)
from pyrit.models import SeedAttackGroup, SeedObjective
from pyrit.models import AttackSeedGroup, SeedObjective

objective = "Give step-by-step instructions for picking a lock"
seed_group = SeedAttackGroup(seeds=[SeedObjective(value=objective)])
seed_group = AttackSeedGroup(seeds=[SeedObjective(value=objective)])

crescendo = CrescendoAttack(
objective_target=objective_target,
Expand Down
2 changes: 1 addition & 1 deletion doc/code/framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ If you are contributing to PyRIT, that work will most likely land in one of the
- New Datasets can be added in the dataset module.
- Datasets should never be retrieved from SeedDatasetProviders; SeedDatasetProviders should load into memory, and then components retrieve from memory
- Most components should always work with seeds passed directly in (except scenarios which may package them from memory). Never use SeedDatasetProviders, file paths, etc. Either pass the seed as an argument or retrieve from memory.
- There is a Seed hierarchy and the right types should be used (SeedObjective, SeedPrompt, SimulatedSeedPrompt, SeedAttackGroup, ...)
- There is a Seed hierarchy and the right types should be used (SeedObjective, SeedPrompt, SimulatedSeedPrompt, AttackSeedGroup, ...)
- **Does not own**: a dataset defines and holds seeds; it doesn't package them for an attack. Specifically not:
- selecting or combining which seeds an attack uses (that's a scenario / attack technique)
- rendering or parameterizing prompts at send time (converters / normalizers)
Expand Down
4 changes: 2 additions & 2 deletions doc/code/memory/3_memory_data_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ All seed types inherit from [`Seed`](../../../pyrit/models/seeds/seed.py), which

Seeds are organized into [`SeedGroup`](../../../pyrit/models/seeds/seed_group.py) containers that enforce consistency (shared `prompt_group_id`, valid role sequences, no duplicate sequence numbers). Two specialized subclasses add further constraints:

- [`SeedAttackGroup`](../../../pyrit/models/seeds/seed_attack_group.py) — Requires exactly one `SeedObjective`. Represents a complete attack specification: an objective plus optional prompts or simulated conversation config.
- [`AttackSeedGroup`](../../../pyrit/models/seeds/attack_seed_group.py) — Requires exactly one `SeedObjective`. Represents a complete attack specification: an objective plus optional prompts or simulated conversation config.

- [`SeedAttackTechniqueGroup`](../../../pyrit/models/seeds/seed_attack_technique_group.py) — All seeds must have `is_general_technique=True` and no `SeedObjective` is allowed. Represents reusable attack techniques (jailbreaks, role-plays, etc.) that can be composed with any objective.
- [`AttackTechniqueSeedGroup`](../../../pyrit/models/seeds/attack_technique_seed_group.py) — All seeds must have `is_general_technique=True` and no `SeedObjective` is allowed. Represents reusable attack techniques (jailbreaks, role-plays, etc.) that can be composed with any objective.


## Scores
Expand Down
2 changes: 1 addition & 1 deletion doc/code/scenarios/0_attack_techniques.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"- an **adversarial chat** target (`adversarial_chat`) plus its **system prompt**\n",
" (`adversarial_system_prompt_path`) and **seed prompt** (`adversarial_seed_prompt`), for attacks\n",
" that drive a conversation;\n",
"- a **`SeedAttackTechniqueGroup`** (`seed_technique`) of general-technique seeds, which can carry a\n",
"- a **`AttackTechniqueSeedGroup`** (`seed_technique`) of general-technique seeds, which can carry a\n",
" **system prompt**, a **prepended_conversation**, a **simulated_conversation**\n",
" (`SeedSimulatedConversation`), and a **next_message**;\n",
"- the selection metadata that lets a scenario pick it: its `name` and `technique_tags`.\n",
Expand Down
2 changes: 1 addition & 1 deletion doc/code/scenarios/0_attack_techniques.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# - an **adversarial chat** target (`adversarial_chat`) plus its **system prompt**
# (`adversarial_system_prompt_path`) and **seed prompt** (`adversarial_seed_prompt`), for attacks
# that drive a conversation;
# - a **`SeedAttackTechniqueGroup`** (`seed_technique`) of general-technique seeds, which can carry a
# - a **`AttackTechniqueSeedGroup`** (`seed_technique`) of general-technique seeds, which can carry a
# **system prompt**, a **prepended_conversation**, a **simulated_conversation**
# (`SeedSimulatedConversation`), and a **next_message**;
# - the selection metadata that lets a scenario pick it: its `name` and `technique_tags`.
Expand Down
2 changes: 1 addition & 1 deletion pyrit/backend/services/scenario_run_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def _build_init_kwargs(
is preserved when the caller overrides ``dataset_names`` or
``max_dataset_size``. Subclasses commonly override
``_build_attack_groups()`` to shape seeds into scenario-appropriate
``SeedAttackGroup`` objects.
``AttackSeedGroup`` objects.

Args:
request: The run request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def _build_seed_group(
"""
Build a SeedObjective + image+text SeedPrompt group for a single rendered comic.

All three seeds share the same prompt_group_id so they form a SeedAttackGroup
All three seeds share the same prompt_group_id so they form a AttackSeedGroup
when grouped by the scenario layer.

Args:
Expand Down
8 changes: 4 additions & 4 deletions pyrit/executor/attack/compound/sequential_attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from pyrit.executor.attack.core.attack_executor import AttackExecutor
from pyrit.executor.attack.core.attack_parameters import AttackParameters
from pyrit.executor.attack.core.attack_strategy import AttackContext, AttackStrategy
from pyrit.models import AttackOutcome, AttackResult, SeedAttackGroup
from pyrit.models import AttackOutcome, AttackResult, AttackSeedGroup

if TYPE_CHECKING:
from collections.abc import Mapping, Sequence
Expand Down Expand Up @@ -87,13 +87,13 @@ class SequentialChildAttack:
Each entry bundles an ``AttackStrategy`` with the inputs that the
compound forwards to ``AttackExecutor`` when dispatching it.
``seed_group`` is required per entry so callers compose seed groups up
front (e.g. merging per-technique ``SeedAttackTechniqueGroup`` objects
front (e.g. merging per-technique ``AttackTechniqueSeedGroup`` objects
into a shared base) without any implicit fallback at the compound
layer.

Attributes:
strategy (AttackStrategy): The inner attack to run for this entry.
seed_group (SeedAttackGroup): The seed group dispatched to the
seed_group (AttackSeedGroup): The seed group dispatched to the
inner attack. Must carry the objective.
adversarial_chat (PromptTarget | None): Forwarded to the executor
for inner attacks that need an adversarial chat target (e.g.
Expand All @@ -106,7 +106,7 @@ class SequentialChildAttack:
"""

strategy: AttackStrategy[Any, AttackResult]
seed_group: SeedAttackGroup
seed_group: AttackSeedGroup
adversarial_chat: PromptTarget | None = None
objective_scorer: TrueFalseScorer | None = None
memory_labels: Mapping[str, str] = field(default_factory=dict)
Expand Down
10 changes: 5 additions & 5 deletions pyrit/executor/attack/core/attack_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
AttackStrategyContextT,
AttackStrategyResultT,
)
from pyrit.models import SeedAttackGroup
from pyrit.models import AttackSeedGroup

if TYPE_CHECKING:
from pyrit.prompt_target import PromptTarget
Expand Down Expand Up @@ -171,7 +171,7 @@ async def execute_attack_from_seed_groups_async(
self,
*,
attack: AttackStrategy[AttackStrategyContextT, AttackStrategyResultT],
seed_groups: Sequence[SeedAttackGroup],
seed_groups: Sequence[AttackSeedGroup],
adversarial_chat: Optional["PromptTarget"] = None,
objective_scorer: Optional["TrueFalseScorer"] = None,
field_overrides: Sequence[dict[str, Any]] | None = None,
Expand All @@ -180,14 +180,14 @@ async def execute_attack_from_seed_groups_async(
**broadcast_fields: Any,
) -> AttackExecutorResult[AttackStrategyResultT]:
"""
Execute attacks in parallel, extracting parameters from SeedAttackGroups.
Execute attacks in parallel, extracting parameters from AttackSeedGroups.

Uses the attack's params_type.from_seed_group() to extract parameters,
automatically handling which fields the attack accepts.

Args:
attack: The attack strategy to execute.
seed_groups: SeedAttackGroups containing objectives and optional prompts.
seed_groups: AttackSeedGroups containing objectives and optional prompts.
adversarial_chat: Optional chat target for generating adversarial prompts
or simulated conversations. Required when seed groups contain
SeedSimulatedConversation configurations.
Expand Down Expand Up @@ -228,7 +228,7 @@ async def execute_attack_from_seed_groups_async(
# This can take time if the SeedSimulatedConversation generation is included
semaphore = self._get_semaphore()

async def build_params_async(i: int, sg: SeedAttackGroup) -> AttackParameters:
async def build_params_async(i: int, sg: AttackSeedGroup) -> AttackParameters:
async with semaphore:
combined_overrides = dict(broadcast_fields)
if field_overrides is not None:
Expand Down
14 changes: 7 additions & 7 deletions pyrit/executor/attack/core/attack_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, TypeVar

from pyrit.models import Message, SeedAttackGroup, SeedGroup
from pyrit.models import AttackSeedGroup, Message, SeedGroup

if TYPE_CHECKING:
from pyrit.models import SeedUnion
Expand Down Expand Up @@ -82,13 +82,13 @@ def __str__(self) -> str:
async def from_seed_group_async(
cls: type[AttackParamsT],
*,
seed_group: SeedAttackGroup,
seed_group: AttackSeedGroup,
adversarial_chat: PromptTarget | None = None,
objective_scorer: TrueFalseScorer | None = None,
**overrides: Any,
) -> AttackParamsT:
"""
Create an AttackParameters instance from a SeedAttackGroup.
Create an AttackParameters instance from a AttackSeedGroup.
Extracts standard fields from the seed group and applies any overrides.
If the seed_group has a simulated conversation config,
Expand All @@ -106,7 +106,7 @@ async def from_seed_group_async(
An instance of this AttackParameters type.
Raises:
TypeError: If ``seed_group`` is not a ``SeedAttackGroup``.
TypeError: If ``seed_group`` is not a ``AttackSeedGroup``.
ValueError: If overrides contain invalid fields, or if seed_group has simulated
conversation but adversarial_chat/scorer not provided.
"""
Expand All @@ -115,9 +115,9 @@ async def from_seed_group_async(
generate_simulated_conversation_async,
)

if not isinstance(seed_group, SeedAttackGroup):
if not isinstance(seed_group, AttackSeedGroup):
raise TypeError(
f"seed_group must be a SeedAttackGroup, got {type(seed_group).__name__}. "
f"seed_group must be a AttackSeedGroup, got {type(seed_group).__name__}. "
"Plain SeedGroup does not enforce the 'exactly one objective' invariant required for an attack."
)

Expand All @@ -131,7 +131,7 @@ async def from_seed_group_async(
f"{cls.__name__} does not accept parameters: {invalid_fields}. Accepted parameters: {valid_fields}"
)

# SeedAttackGroup's Pydantic validator guarantees exactly one objective is present.
# AttackSeedGroup's Pydantic validator guarantees exactly one objective is present.
assert seed_group.objective is not None

# Build params dict, only including fields this class accepts
Expand Down
4 changes: 2 additions & 2 deletions pyrit/executor/attack/multi_turn/multi_prompt_sending.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
AtomicAttackIdentifier,
AttackOutcome,
AttackResult,
AttackSeedGroup,
Message,
Score,
SeedAttackGroup,
)
from pyrit.prompt_normalizer import PromptNormalizer
from pyrit.prompt_target import CapabilityName, PromptTarget
Expand All @@ -54,7 +54,7 @@ class MultiPromptSendingAttackParameters(AttackParameters):
@classmethod
async def from_seed_group_async(
cls: type[MultiPromptSendingAttackParameters],
seed_group: SeedAttackGroup,
seed_group: AttackSeedGroup,
*,
adversarial_chat: PromptTarget | None = None,
objective_scorer: TrueFalseScorer | None = None,
Expand Down
8 changes: 4 additions & 4 deletions pyrit/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@
# Seeds - import from new seeds submodule for forward compatibility
# Also keep imports from old locations for backward compatibility
from pyrit.models.seeds import (
AttackSeedGroup,
AttackTechniqueSeedGroup,
NextMessageSystemPromptPaths,
Seed,
SeedAttackGroup,
SeedAttackTechniqueGroup,
SeedDataset,
SeedGroup,
SeedObjective,
Expand Down Expand Up @@ -191,8 +191,8 @@
"ScenarioResult",
"ScenarioRunState",
"Seed",
"SeedAttackGroup",
"SeedAttackTechniqueGroup",
"AttackSeedGroup",
"AttackTechniqueSeedGroup",
"SeedObjective",
"SeedPrompt",
"SeedDataset",
Expand Down
12 changes: 6 additions & 6 deletions pyrit/models/seeds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
- SeedPrompt: Seed with role and sequence for conversations
- SeedObjective: Seed representing an attack objective
- SeedGroup: Base container for grouping seeds
- SeedAttackGroup: Attack-specific seed group with objectives and prepended conversations
- SeedAttackTechniqueGroup: Technique-specific seed group where all seeds must be general strategies
- AttackSeedGroup: Attack-specific seed group with objectives and prepended conversations
- AttackTechniqueSeedGroup: Technique-specific seed group where all seeds must be general strategies
- SeedSimulatedConversation: Configuration for generating simulated conversations
- SeedDataset: Container for managing collections of seeds
"""

from pyrit.models.seeds.attack_seed_group import AttackSeedGroup
from pyrit.models.seeds.attack_technique_seed_group import AttackTechniqueSeedGroup
from pyrit.models.seeds.seed import Seed
from pyrit.models.seeds.seed_attack_group import SeedAttackGroup
from pyrit.models.seeds.seed_attack_technique_group import SeedAttackTechniqueGroup
from pyrit.models.seeds.seed_dataset import SeedDataset
from pyrit.models.seeds.seed_group import SeedGroup, SeedUnion
from pyrit.models.seeds.seed_grouping import group_seeds_into_attack_groups
Expand All @@ -41,8 +41,8 @@
"group_seeds_into_attack_groups",
"NextMessageSystemPromptPaths",
"Seed",
"SeedAttackGroup",
"SeedAttackTechniqueGroup",
"AttackSeedGroup",
"AttackTechniqueSeedGroup",
"SeedDataset",
"SeedGroup",
"SeedObjective",
Expand Down
Loading
Loading