Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
20 changes: 10 additions & 10 deletions doc/code/converters/6_selectively_converting.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
"source": [
"# Convert words at specific positions (e.g., words 3, 4, and 5)\n",
"converter = SelectiveTextConverter(\n",
" converter=Base64Converter(),\n",
" sub_converter=Base64Converter(),\n",
" selection_strategy=WordIndexSelectionStrategy(indices=[3, 4, 5]),\n",
")\n",
"\n",
Expand Down Expand Up @@ -293,7 +293,7 @@
"source": [
"# Convert all numbers in the prompt\n",
"converter = SelectiveTextConverter(\n",
" converter=Base64Converter(),\n",
" sub_converter=Base64Converter(),\n",
" selection_strategy=WordRegexSelectionStrategy(pattern=r\"\\d+\"),\n",
")\n",
"\n",
Expand Down Expand Up @@ -373,7 +373,7 @@
"source": [
"# Convert the second half of the prompt\n",
"converter = SelectiveTextConverter(\n",
" converter=ROT13Converter(),\n",
" sub_converter=ROT13Converter(),\n",
" selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),\n",
")\n",
"\n",
Expand Down Expand Up @@ -452,7 +452,7 @@
],
"source": [
"converter = SelectiveTextConverter(\n",
" converter=Base64Converter(),\n",
" sub_converter=Base64Converter(),\n",
" selection_strategy=WordProportionSelectionStrategy(proportion=0.3, seed=42),\n",
")\n",
"\n",
Expand Down Expand Up @@ -530,7 +530,7 @@
"source": [
"# Convert specific sensitive words\n",
"converter = SelectiveTextConverter(\n",
" converter=Base64Converter(),\n",
" sub_converter=Base64Converter(),\n",
" selection_strategy=WordKeywordSelectionStrategy(keywords=[\"password\", \"secret\", \"confidential\"]),\n",
")\n",
"\n",
Expand Down Expand Up @@ -610,13 +610,13 @@
"source": [
"# First convert the first half to russian\n",
"first_converter = SelectiveTextConverter(\n",
" converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"russian\"),\n",
" sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"russian\"),\n",
" selection_strategy=WordPositionSelectionStrategy(start_proportion=0.0, end_proportion=0.5),\n",
")\n",
"\n",
"# Then converts the second half to spanish\n",
"second_converter = SelectiveTextConverter(\n",
" converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"spanish\"),\n",
" sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"spanish\"),\n",
" selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),\n",
")\n",
"\n",
Expand Down Expand Up @@ -699,20 +699,20 @@
],
"source": [
"first_converter = SelectiveTextConverter(\n",
" converter=ToneConverter(converter_target=OpenAIChatTarget(), tone=\"angry\"),\n",
" sub_converter=ToneConverter(converter_target=OpenAIChatTarget(), tone=\"angry\"),\n",
" selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),\n",
" preserve_tokens=True,\n",
")\n",
"\n",
"# Second converter auto-detects tokens from first converter\n",
"second_converter = SelectiveTextConverter(\n",
" converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"spanish\"),\n",
" sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language=\"spanish\"),\n",
" selection_strategy=TokenSelectionStrategy(), # Detects tokens from first converter\n",
" preserve_tokens=True,\n",
")\n",
"\n",
"third_converter = SelectiveTextConverter(\n",
" converter=EmojiConverter(),\n",
" sub_converter=EmojiConverter(),\n",
" selection_strategy=TokenSelectionStrategy(), # Detects tokens from second converter\n",
" preserve_tokens=False,\n",
")\n",
Expand Down
20 changes: 10 additions & 10 deletions doc/code/converters/6_selectively_converting.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
# %%
# Convert words at specific positions (e.g., words 3, 4, and 5)
converter = SelectiveTextConverter(
converter=Base64Converter(),
sub_converter=Base64Converter(),
selection_strategy=WordIndexSelectionStrategy(indices=[3, 4, 5]),
)

Expand All @@ -101,7 +101,7 @@
# %%
# Convert all numbers in the prompt
converter = SelectiveTextConverter(
converter=Base64Converter(),
sub_converter=Base64Converter(),
selection_strategy=WordRegexSelectionStrategy(pattern=r"\d+"),
)

Expand All @@ -126,7 +126,7 @@
# %%
# Convert the second half of the prompt
converter = SelectiveTextConverter(
converter=ROT13Converter(),
sub_converter=ROT13Converter(),
selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),
)

Expand All @@ -150,7 +150,7 @@

# %%
converter = SelectiveTextConverter(
converter=Base64Converter(),
sub_converter=Base64Converter(),
selection_strategy=WordProportionSelectionStrategy(proportion=0.3, seed=42),
)

Expand All @@ -173,7 +173,7 @@
# %%
# Convert specific sensitive words
converter = SelectiveTextConverter(
converter=Base64Converter(),
sub_converter=Base64Converter(),
selection_strategy=WordKeywordSelectionStrategy(keywords=["password", "secret", "confidential"]),
)

Expand All @@ -198,13 +198,13 @@
# %%
# First convert the first half to russian
first_converter = SelectiveTextConverter(
converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="russian"),
sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="russian"),
selection_strategy=WordPositionSelectionStrategy(start_proportion=0.0, end_proportion=0.5),
)

# Then converts the second half to spanish
second_converter = SelectiveTextConverter(
converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="spanish"),
sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="spanish"),
selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),
)

Expand All @@ -229,20 +229,20 @@
# %%

first_converter = SelectiveTextConverter(
converter=ToneConverter(converter_target=OpenAIChatTarget(), tone="angry"),
sub_converter=ToneConverter(converter_target=OpenAIChatTarget(), tone="angry"),
selection_strategy=WordPositionSelectionStrategy(start_proportion=0.5, end_proportion=1.0),
preserve_tokens=True,
)

# Second converter auto-detects tokens from first converter
second_converter = SelectiveTextConverter(
converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="spanish"),
sub_converter=TranslationConverter(converter_target=OpenAIChatTarget(), language="spanish"),
selection_strategy=TokenSelectionStrategy(), # Detects tokens from first converter
preserve_tokens=True,
)

third_converter = SelectiveTextConverter(
converter=EmojiConverter(),
sub_converter=EmojiConverter(),
selection_strategy=TokenSelectionStrategy(), # Detects tokens from second converter
preserve_tokens=False,
)
Expand Down
55 changes: 43 additions & 12 deletions doc/code/scenarios/2_custom_scenario_parameters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@
"id": "1",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"./AppData/Local/miniconda3/Lib/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.5.0) or chardet (7.4.3)/charset_normalizer (3.3.2) doesn't match a supported version!\n",
" warnings.warn(\n"
]
},
{
"name": "stdout",
"output_type": "stream",
Expand All @@ -63,7 +71,7 @@
"output_type": "stream",
"text": [
"[pyrit:alembic] No new upgrade operations detected.\n",
"Parameter(name='max_turns', description='Maximum conversation turns for the persuasive_rta strategy.', default=5, param_type=<class 'int'>, choices=None)\n"
"Parameter(name='max_turns', description='Maximum conversation turns for the persuasive_rta strategy.', default=5, param_type=<class 'int'>, destination=<ParameterDestination.CONSTRUCTOR: 'constructor'>)\n"
]
}
],
Expand Down Expand Up @@ -93,8 +101,9 @@
"- **name**: dict key in `self.params`, converted to `--kebab-case` for the CLI\n",
"- **description**: shown in `--list-scenarios` and `--help`\n",
"- **default**: value used when not supplied; deep-copied per run\n",
"- **param_type**: `str`, `int`, `float`, `bool`, `list[str]`, or `None` (raw passthrough)\n",
"- **choices**: optional tuple of allowed values (not supported with `list` types)\n",
"- **param_type**: `str`, `int`, `float`, `bool`, a `Literal[...]`/`Enum` (a\n",
" constrained scalar that carries its own allowed set), a `list[...]` of any of\n",
" those, or `None` (raw passthrough)\n",
"\n",
"A more complete declaration list might look like:"
]
Expand All @@ -109,29 +118,30 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Parameter(name='objective', description='Goal the attack pursues', default=None, param_type=<class 'str'>, choices=None)\n",
"Parameter(name='max_turns', description='Conversation cap', default=5, param_type=<class 'int'>, choices=None)\n",
"Parameter(name='mode', description='Speed mode', default='fast', param_type=<class 'str'>, choices=('fast', 'slow'))\n",
"Parameter(name='tags', description='Tag list', default=['default'], param_type=list[str], choices=None)\n"
"Parameter(name='objective', description='Goal the attack pursues', default=None, param_type=<class 'str'>, destination=<ParameterDestination.CONSTRUCTOR: 'constructor'>)\n",
"Parameter(name='max_turns', description='Conversation cap', default=5, param_type=<class 'int'>, destination=<ParameterDestination.CONSTRUCTOR: 'constructor'>)\n",
"Parameter(name='mode', description='Speed mode', default='fast', param_type=typing.Literal['fast', 'slow'], destination=<ParameterDestination.CONSTRUCTOR: 'constructor'>)\n",
"Parameter(name='tags', description='Tag list', default=['default'], param_type=list[str], destination=<ParameterDestination.CONSTRUCTOR: 'constructor'>)\n"
]
}
],
"source": [
"from pyrit.common import Parameter\n",
"from typing import Literal\n",
"\n",
"from pyrit.models import Parameter\n",
"\n",
"# What a scenario author would return from supported_parameters():\n",
"example_declarations = [\n",
" # Scalar with no default — author must guard against None at run time\n",
" Parameter(name=\"objective\", description=\"Goal the attack pursues\", param_type=str),\n",
" # Scalar with default\n",
" Parameter(name=\"max_turns\", description=\"Conversation cap\", default=5, param_type=int),\n",
" # Choices: behaves like an enum\n",
" # Constrained scalar: a Literal behaves like an enum (the type *is* the allowed set)\n",
" Parameter(\n",
" name=\"mode\",\n",
" description=\"Speed mode\",\n",
" default=\"fast\",\n",
" param_type=str,\n",
" choices=(\"fast\", \"slow\"),\n",
" param_type=Literal[\"fast\", \"slow\"],\n",
" ),\n",
" # List parameter\n",
" Parameter(name=\"tags\", description=\"Tag list\", default=[\"default\"], param_type=list[str]),\n",
Expand Down Expand Up @@ -257,6 +267,27 @@
"id": "8",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"TargetRegistry entry 'objective_scorer_chat' not found. Falling back to default OpenAIChatTarget.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Using fallback default objective scorer: TrueFalseInverterScorer with chat target: OpenAIChatTarget\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"TextAdaptive: _EXCLUDED_TECHNIQUES entries ['prompt_sending'] are not in the current scenario-techniques catalog ['context_compliance', 'crescendo_history_lecture', 'crescendo_journalist_interview', 'crescendo_movie_director', 'crescendo_simulated', 'many_shot', 'pair', 'red_teaming', 'role_play', 'tap', 'violent_durian']; the exclusion is a no-op for those entries. Remove stale entries or update the catalog.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
Expand Down Expand Up @@ -496,7 +527,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.13"
"version": "3.13.5"
}
},
"nbformat": 4,
Expand Down
14 changes: 8 additions & 6 deletions doc/code/scenarios/2_custom_scenario_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,27 +67,29 @@
# - **name**: dict key in `self.params`, converted to `--kebab-case` for the CLI
# - **description**: shown in `--list-scenarios` and `--help`
# - **default**: value used when not supplied; deep-copied per run
# - **param_type**: `str`, `int`, `float`, `bool`, `list[str]`, or `None` (raw passthrough)
# - **choices**: optional tuple of allowed values (not supported with `list` types)
# - **param_type**: `str`, `int`, `float`, `bool`, a `Literal[...]`/`Enum` (a
# constrained scalar that carries its own allowed set), a `list[...]` of any of
# those, or `None` (raw passthrough)
#
# A more complete declaration list might look like:

# %%
from pyrit.common import Parameter
from typing import Literal

from pyrit.models import Parameter

# What a scenario author would return from supported_parameters():
example_declarations = [
# Scalar with no default — author must guard against None at run time
Parameter(name="objective", description="Goal the attack pursues", param_type=str),
# Scalar with default
Parameter(name="max_turns", description="Conversation cap", default=5, param_type=int),
# Choices: behaves like an enum
# Constrained scalar: a Literal behaves like an enum (the type *is* the allowed set)
Parameter(
name="mode",
description="Speed mode",
default="fast",
param_type=str,
choices=("fast", "slow"),
param_type=Literal["fast", "slow"],
),
# List parameter
Parameter(name="tags", description="Tag list", default=["default"], param_type=list[str]),
Expand Down
Loading
Loading