Skip to content

Commit 77a738b

Browse files
romanlutzCopilothannahwestra25
authored
DOC: initializer-rename doc updates and notebook/test fixes (post #2157) (#2187)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: hannahwestra25 <hannahwestra@microsoft.com>
1 parent 5531da0 commit 77a738b

11 files changed

Lines changed: 235 additions & 252 deletions

File tree

doc/code/setup/1_configuration.ipynb

Lines changed: 148 additions & 139 deletions
Large diffs are not rendered by default.

doc/code/setup/1_configuration.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,6 @@
99
# jupytext_version: 1.19.4
1010
# ---
1111

12-
# %%
13-
from pyrit.output import output_attack_async
14-
15-
# ---
16-
# jupyter:
17-
# jupytext:
18-
# text_representation:
19-
# extension: .py
20-
# format_name: percent
21-
# format_version: '1.3'
22-
# jupytext_version: 1.19.1
23-
# ---
2412
# %% [markdown]
2513
# # Configuration
2614
#
@@ -148,6 +136,7 @@
148136
AttackScoringConfig,
149137
PromptSendingAttack,
150138
)
139+
from pyrit.output import output_attack_async
151140
from pyrit.prompt_normalizer.converter_configuration import (
152141
ConverterConfiguration,
153142
)

doc/code/targets/use_huggingface_chat_target.ipynb

Lines changed: 42 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,6 @@
4141
"id": "1",
4242
"metadata": {},
4343
"outputs": [
44-
{
45-
"name": "stderr",
46-
"output_type": "stream",
47-
"text": [
48-
"./git/copilot-worktrees/PyRIT/romanlutz-cautious-meme/.venv/Lib/site-packages/confusables/__init__.py:46: SyntaxWarning: \"\\*\" is an invalid escape sequence. Such sequences will not work in the future. Did you mean \"\\\\*\"? A raw string is also an option.\n",
49-
" space_regex = \"[\\*_~|`\\-\\.]*\" if include_character_padding else ''\n"
50-
]
51-
},
5244
{
5345
"name": "stdout",
5446
"output_type": "stream",
@@ -69,13 +61,13 @@
6961
"name": "stdout",
7062
"output_type": "stream",
7163
"text": [
72-
"Running model: Qwen/Qwen2-0.5B-Instruct\n"
64+
"Running model: HuggingFaceTB/SmolLM2-135M-Instruct\n"
7365
]
7466
},
7567
{
7668
"data": {
7769
"application/vnd.jupyter.widget-view+json": {
78-
"model_id": "2cb1ed2b5d6c4fa98456d1c217564010",
70+
"model_id": "5ccc9dc2fe35480bbe25f5b8fd6bd50a",
7971
"version_major": 2,
8072
"version_minor": 0
8173
},
@@ -89,12 +81,12 @@
8981
{
9082
"data": {
9183
"application/vnd.jupyter.widget-view+json": {
92-
"model_id": "76523dac8fe04b87921ad444853385c3",
84+
"model_id": "3fc4b0633f704408aa0ca3a28d38bc1e",
9385
"version_major": 2,
9486
"version_minor": 0
9587
},
9688
"text/plain": [
97-
"Fetching 10 files: 0%| | 0/10 [00:00<?, ?it/s]"
89+
"Fetching 25 files: 0%| | 0/25 [00:00<?, ?it/s]"
9890
]
9991
},
10092
"metadata": {},
@@ -103,12 +95,12 @@
10395
{
10496
"data": {
10597
"application/vnd.jupyter.widget-view+json": {
106-
"model_id": "650a316e795b4e84abdc46b06bc79cc1",
98+
"model_id": "73eb775a3c3a419fbc79d3f3ce7d96ef",
10799
"version_major": 2,
108100
"version_minor": 0
109101
},
110102
"text/plain": [
111-
"Loading weights: 0%| | 0/290 [00:00<?, ?it/s]"
103+
"Loading weights: 0%| | 0/272 [00:00<?, ?it/s]"
112104
]
113105
},
114106
"metadata": {},
@@ -118,7 +110,7 @@
118110
"name": "stdout",
119111
"output_type": "stream",
120112
"text": [
121-
"Average response time for Qwen/Qwen2-0.5B-Instruct: 7.43 seconds\n",
113+
"Average response time for HuggingFaceTB/SmolLM2-135M-Instruct: 2.59 seconds\n",
122114
"\n",
123115
"\n",
124116
"\u001b[33m════════════════════════════════════════════════════════════════════════════════════════════════════\u001b[0m\n",
@@ -130,11 +122,11 @@
130122
"\u001b[1m 📋 Basic Information\u001b[0m\n",
131123
"\u001b[36m • Objective: What is 3*3? Give me the solution.\u001b[0m\n",
132124
"\u001b[36m • Attack Type: PromptSendingAttack\u001b[0m\n",
133-
"\u001b[36m • Conversation ID: 3e01b421-e41b-4c47-a51b-ea192f7cdb24\u001b[0m\n",
125+
"\u001b[36m • Conversation ID: 84048a6c-960d-483d-b54d-b19d8e0e3eb1\u001b[0m\n",
134126
"\n",
135127
"\u001b[1m ⚡ Execution Metrics\u001b[0m\n",
136128
"\u001b[32m • Turns Executed: 1\u001b[0m\n",
137-
"\u001b[32m • Execution Time: 12.20s\u001b[0m\n",
129+
"\u001b[32m • Execution Time: 4.61s\u001b[0m\n",
138130
"\n",
139131
"\u001b[1m 🎯 Outcome\u001b[0m\n",
140132
"\u001b[33m • Status: ❓ UNDETERMINED\u001b[0m\n",
@@ -151,14 +143,12 @@
151143
"\u001b[33m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
152144
"\u001b[1m\u001b[33m🔸 ASSISTANT\u001b[0m\n",
153145
"\u001b[33m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
154-
"\u001b[33m The answer to \"What is 3 * 3?\" is 9.\u001b[0m\n",
155-
"\u001b[33m \u001b[0m\n",
156-
"\u001b[33m This is because the product of two numbers, where the first number (\u001b[0m\n",
146+
"\u001b[33m 3*3 = 9\u001b[0m\n",
157147
"\n",
158148
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
159149
"\n",
160150
"\u001b[2m\u001b[37m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
161-
"\u001b[2m\u001b[37m Report generated at: 2026-07-16 05:18:39 UTC \u001b[0m\n",
151+
"\u001b[2m\u001b[37m Report generated at: 2026-07-13 23:25:00 UTC \u001b[0m\n",
162152
"\n",
163153
"\u001b[33m════════════════════════════════════════════════════════════════════════════════════════════════════\u001b[0m\n",
164154
"\u001b[1m\u001b[33m ❓ ATTACK RESULT: UNDETERMINED ❓ \u001b[0m\n",
@@ -169,11 +159,11 @@
169159
"\u001b[1m 📋 Basic Information\u001b[0m\n",
170160
"\u001b[36m • Objective: What is 4*4? Give me the solution.\u001b[0m\n",
171161
"\u001b[36m • Attack Type: PromptSendingAttack\u001b[0m\n",
172-
"\u001b[36m • Conversation ID: 76b845b6-0e72-4a80-a793-09652c4d7405\u001b[0m\n",
162+
"\u001b[36m • Conversation ID: bc388b83-e4d3-441b-80f1-dc8d433bc314\u001b[0m\n",
173163
"\n",
174164
"\u001b[1m ⚡ Execution Metrics\u001b[0m\n",
175165
"\u001b[32m • Turns Executed: 1\u001b[0m\n",
176-
"\u001b[32m • Execution Time: 2.63s\u001b[0m\n",
166+
"\u001b[32m • Execution Time: 557ms\u001b[0m\n",
177167
"\n",
178168
"\u001b[1m 🎯 Outcome\u001b[0m\n",
179169
"\u001b[33m • Status: ❓ UNDETERMINED\u001b[0m\n",
@@ -190,17 +180,13 @@
190180
"\u001b[33m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
191181
"\u001b[1m\u001b[33m🔸 ASSISTANT\u001b[0m\n",
192182
"\u001b[33m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
193-
"\u001b[33m The result of multiplying 4 by itself four times is:\u001b[0m\n",
194-
"\u001b[33m 256.\u001b[0m\n",
195-
"\u001b[33m \u001b[0m\n",
196-
"\u001b[33m Here's why:\u001b[0m\n",
197-
"\u001b[33m First, we multiply 4 and\u001b[0m\n",
183+
"\u001b[33m 4*4 = 16.\u001b[0m\n",
198184
"\n",
199185
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
200186
"\n",
201187
"\u001b[2m\u001b[37m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n",
202-
"\u001b[2m\u001b[37m Report generated at: 2026-07-16 05:18:39 UTC \u001b[0m\n",
203-
"Qwen/Qwen2-0.5B-Instruct: 7.43 seconds\n"
188+
"\u001b[2m\u001b[37m Report generated at: 2026-07-13 23:25:00 UTC \u001b[0m\n",
189+
"HuggingFaceTB/SmolLM2-135M-Instruct: 2.59 seconds\n"
204190
]
205191
}
206192
],
@@ -218,7 +204,7 @@
218204
"await initialize_pyrit_async(memory_db_type=IN_MEMORY) # type: ignore\n",
219205
"\n",
220206
"# models to test\n",
221-
"model_id = \"Qwen/Qwen2-0.5B-Instruct\"\n",
207+
"model_id = \"HuggingFaceTB/SmolLM2-135M-Instruct\"\n",
222208
"\n",
223209
"# List of prompts to send\n",
224210
"prompt_list = [\"What is 3*3? Give me the solution.\", \"What is 4*4? Give me the solution.\"]\n",
@@ -228,51 +214,44 @@
228214
"\n",
229215
"print(f\"Running model: {model_id}\")\n",
230216
"\n",
231-
"try:\n",
232-
" # Initialize HuggingFaceChatTarget with the current model\n",
233-
" target = HuggingFaceChatTarget(model_id=model_id, use_cuda=False, tensor_format=\"pt\", max_new_tokens=30)\n",
234-
"\n",
235-
" # Initialize the attack\n",
236-
" attack = PromptSendingAttack(objective_target=target)\n",
217+
"# Initialize HuggingFaceChatTarget with the current model\n",
218+
"target = HuggingFaceChatTarget(model_id=model_id, use_cuda=False, tensor_format=\"pt\", max_new_tokens=30)\n",
237219
"\n",
238-
" # Record start time\n",
239-
" start_time = time.time()\n",
220+
"# Initialize the attack\n",
221+
"attack = PromptSendingAttack(objective_target=target)\n",
240222
"\n",
241-
" # Send prompts asynchronously\n",
242-
" responses = await AttackExecutor().execute_attack_async( # type: ignore\n",
243-
" attack=attack,\n",
244-
" objectives=prompt_list,\n",
245-
" )\n",
223+
"# Record start time\n",
224+
"start_time = time.time()\n",
246225
"\n",
247-
" # Record end time\n",
248-
" end_time = time.time()\n",
226+
"# Send prompts asynchronously\n",
227+
"responses = await AttackExecutor().execute_attack_async( # type: ignore\n",
228+
" attack=attack,\n",
229+
" objectives=prompt_list,\n",
230+
")\n",
249231
"\n",
250-
" # Calculate total and average response time\n",
251-
" total_time = end_time - start_time\n",
252-
" avg_time = total_time / len(prompt_list)\n",
253-
" model_times[model_id] = avg_time\n",
232+
"# Record end time\n",
233+
"end_time = time.time()\n",
254234
"\n",
255-
" print(f\"Average response time for {model_id}: {avg_time:.2f} seconds\\n\")\n",
235+
"# Calculate total and average response time\n",
236+
"total_time = end_time - start_time\n",
237+
"avg_time = total_time / len(prompt_list)\n",
238+
"model_times[model_id] = avg_time\n",
256239
"\n",
257-
" # Print the conversations\n",
258-
" for result in responses:\n",
259-
" await output_attack_async(result)\n",
240+
"print(f\"Average response time for {model_id}: {avg_time:.2f} seconds\\n\")\n",
260241
"\n",
261-
"except Exception as e:\n",
262-
" print(f\"An error occurred with model {model_id}: {e}\\n\")\n",
263-
" model_times[model_id] = None\n",
242+
"# Print the conversations\n",
243+
"for result in responses:\n",
244+
" await output_attack_async(result)\n",
264245
"\n",
265246
"# Print the model average time\n",
266-
"if model_times[model_id] is not None:\n",
267-
" print(f\"{model_id}: {model_times[model_id]:.2f} seconds\")\n",
268-
"else:\n",
269-
" print(f\"{model_id}: Error occurred, no average time calculated.\")"
247+
"print(f\"{model_id}: {model_times[model_id]:.2f} seconds\")"
270248
]
271249
}
272250
],
273251
"metadata": {
274252
"jupytext": {
275-
"cell_metadata_filter": "-all"
253+
"cell_metadata_filter": "-all",
254+
"main_language": "python"
276255
},
277256
"language_info": {
278257
"codemirror_mode": {
@@ -284,7 +263,7 @@
284263
"name": "python",
285264
"nbconvert_exporter": "python",
286265
"pygments_lexer": "ipython3",
287-
"version": "3.14.4"
266+
"version": "3.12.12"
288267
}
289268
},
290269
"nbformat": 4,

doc/code/targets/use_huggingface_chat_target.py

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
# extension: .py
77
# format_name: percent
88
# format_version: '1.3'
9-
# jupytext_version: 1.19.0
9+
# jupytext_version: 1.19.4
1010
# ---
11+
1112
# %% [markdown]
1213
# # HuggingFace Chat Target - optional
1314
#
@@ -50,7 +51,7 @@
5051
await initialize_pyrit_async(memory_db_type=IN_MEMORY) # type: ignore
5152

5253
# models to test
53-
model_id = "Qwen/Qwen2-0.5B-Instruct"
54+
model_id = "HuggingFaceTB/SmolLM2-135M-Instruct"
5455

5556
# List of prompts to send
5657
prompt_list = ["What is 3*3? Give me the solution.", "What is 4*4? Give me the solution."]
@@ -60,42 +61,34 @@
6061

6162
print(f"Running model: {model_id}")
6263

63-
try:
64-
# Initialize HuggingFaceChatTarget with the current model
65-
target = HuggingFaceChatTarget(model_id=model_id, use_cuda=False, tensor_format="pt", max_new_tokens=30)
66-
67-
# Initialize the attack
68-
attack = PromptSendingAttack(objective_target=target)
64+
# Initialize HuggingFaceChatTarget with the current model
65+
target = HuggingFaceChatTarget(model_id=model_id, use_cuda=False, tensor_format="pt", max_new_tokens=30)
6966

70-
# Record start time
71-
start_time = time.time()
67+
# Initialize the attack
68+
attack = PromptSendingAttack(objective_target=target)
7269

73-
# Send prompts asynchronously
74-
responses = await AttackExecutor().execute_attack_async( # type: ignore
75-
attack=attack,
76-
objectives=prompt_list,
77-
)
70+
# Record start time
71+
start_time = time.time()
7872

79-
# Record end time
80-
end_time = time.time()
73+
# Send prompts asynchronously
74+
responses = await AttackExecutor().execute_attack_async( # type: ignore
75+
attack=attack,
76+
objectives=prompt_list,
77+
)
8178

82-
# Calculate total and average response time
83-
total_time = end_time - start_time
84-
avg_time = total_time / len(prompt_list)
85-
model_times[model_id] = avg_time
79+
# Record end time
80+
end_time = time.time()
8681

87-
print(f"Average response time for {model_id}: {avg_time:.2f} seconds\n")
82+
# Calculate total and average response time
83+
total_time = end_time - start_time
84+
avg_time = total_time / len(prompt_list)
85+
model_times[model_id] = avg_time
8886

89-
# Print the conversations
90-
for result in responses:
91-
await output_attack_async(result)
87+
print(f"Average response time for {model_id}: {avg_time:.2f} seconds\n")
9288

93-
except Exception as e:
94-
print(f"An error occurred with model {model_id}: {e}\n")
95-
model_times[model_id] = None
89+
# Print the conversations
90+
for result in responses:
91+
await output_attack_async(result)
9692

9793
# Print the model average time
98-
if model_times[model_id] is not None:
99-
print(f"{model_id}: {model_times[model_id]:.2f} seconds")
100-
else:
101-
print(f"{model_id}: Error occurred, no average time calculated.")
94+
print(f"{model_id}: {model_times[model_id]:.2f} seconds")

doc/getting_started/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ from pyrit.setup.initializers import ScorerInitializer, TargetInitializer
3737
await initialize_pyrit_async(memory_db_type="InMemory", initializers=[TargetInitializer(), ScorerInitializer()])
3838
```
3939

40-
This gives you an in-memory database and default converter/scorer config — enough to run most notebooks and examples. Replace the endpoint/key/model for your provider (Azure, Ollama, Groq, HuggingFace, etc.).
40+
This gives you an in-memory database with configured targets and scorers registered for selection by name or tag. Replace the endpoint/key/model for your provider (Azure, Ollama, Groq, HuggingFace, etc.).
4141

4242
## For Persistent Setup
4343

doc/getting_started/pyrit_conf.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ Most users should enable the following initializers. These are what the `.pyrit_
117117
**Execution order follows listing order.** Initializers execute in the order they appear in the config. Ensure dependencies are satisfied — for example, list `target` before `scorer` since scorers need targets to be registered first.
118118
```
119119

120+
```{important}
121+
The default initializers were consolidated and renamed as part of the cleanup leading up to the **v1.0.0** release. Configurations created before v1.0.0 may still reference the removed names `simple`, `airt`, `scenario_technique`, or `scenario_objective_list` — replace them with the current initializers listed above.
122+
```
123+
120124
The recommended config:
121125

122126
```yaml

doc/gui/0_gui.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ For `AzureMLChatTarget`, additional fields are available: **Max New Tokens**, **
151151

152152
#### Auto-Populating Targets
153153

154-
Targets can also be auto-populated by adding an initializer (e.g., `airt`) to your `~/.pyrit/.pyrit_conf` file. This reads endpoints from your `.env` and `.env.local` files. See [.pyrit_conf_example](https://github.com/microsoft/PyRIT/blob/main/.pyrit_conf_example) for details.
154+
Targets can also be auto-populated by adding the `target` initializer to your `~/.pyrit/.pyrit_conf` file. This reads endpoints from your `.env` and `.env.local` files. See [.pyrit_conf_example](https://github.com/microsoft/PyRIT/blob/main/.pyrit_conf_example) for details.
155155

156156
---
157157

doc/scanner/1_pyrit_scan.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@
610610
"\n",
611611
"PyRITInitializers are how you can configure the CLI scanner. PyRIT includes several built-in initializers you can use with the `--initializers` flag.\n",
612612
"\n",
613-
"The `--list-initializers` command shows all available initializers. Initializers are referenced by their filename (e.g., `target`, `scorer`, `simple`) regardless of which subdirectory they're in.\n",
613+
"The `--list-initializers` command shows all available initializers. Initializers are referenced by their filename (e.g., `target`, `scorer`) regardless of which subdirectory they're in.\n",
614614
"\n",
615615
"List the available initializers using the --list-initializers flag."
616616
]

doc/scanner/1_pyrit_scan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
#
5959
# PyRITInitializers are how you can configure the CLI scanner. PyRIT includes several built-in initializers you can use with the `--initializers` flag.
6060
#
61-
# The `--list-initializers` command shows all available initializers. Initializers are referenced by their filename (e.g., `target`, `scorer`, `simple`) regardless of which subdirectory they're in.
61+
# The `--list-initializers` command shows all available initializers. Initializers are referenced by their filename (e.g., `target`, `scorer`) regardless of which subdirectory they're in.
6262
#
6363
# List the available initializers using the --list-initializers flag.
6464

pyrit/registry/components/initializer_registry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class InitializerRegistry(ParamBagRegistry["PyRITInitializer", InitializerMetada
6767
``pyrit/setup/initializers`` directory structure via a filesystem scan (so
6868
``_discover`` is overridden rather than supplying ``_base_type`` /
6969
``_discovery_package``). Initializers are identified by their suffix-stripped
70-
snake_case class name (e.g., ``"objective_target"``, ``"simple"``); the
70+
snake_case class name (e.g., ``"objective_target"``, ``"technique"``); the
7171
directory structure is used for organization but not exposed to users.
7272
"""
7373

0 commit comments

Comments
 (0)