Skip to content
Open
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