Skip to content

Commit 20058f5

Browse files
authored
MAINT: dataset path reorg (microsoft#1210)
1 parent 0f4f25b commit 20058f5

274 files changed

Lines changed: 946 additions & 561 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
applyTo: 'doc/code/**/*.{py,ipynb}'
3+
---
4+
5+
# Documentation File Synchronization
6+
7+
## CRITICAL: .ipynb and .py Files Are Linked
8+
9+
All Jupyter notebooks (.ipynb) in the `doc/` directory have corresponding Python (.py) files that are **tightly synchronized**. These files MUST always match exactly in content. They represent the same documentation in different formats.
10+
11+
**Locations:** `doc/code/**/*.ipynb` and `doc/code/**/*.py`
12+
13+
## Editing Guidelines
14+
15+
### Preferred Approach: Inline Updates to Both Files
16+
For simple, straightforward changes (imports, variable names, paths, small code fixes):
17+
- **UPDATE BOTH FILES INLINE** using search/replace operations
18+
- This is the fastest and most reliable method for minor edits
19+
- Ensures immediate synchronization without execution overhead
20+
- **Exercise extreme caution**: Even small mismatches will break synchronization
21+
- Also acceptable to just edit the .ipynb and regenerate the .py (this is fast)
22+
23+
### Last Resort: Regenerate the ipynb with Jupytext
24+
For complex or extensive changes where inline editing is error-prone:
25+
1. Edit ONLY the .py file
26+
2. Regenerate the .ipynb using: `jupytext --to ipynb --execute doc/path/to/your_notebook.py`
27+
3. **WARNING**: This process takes several minutes to execute
28+
4. Use this ONLY when inline updates are too risky or complex
29+
30+
## Why This Matters
31+
- Out-of-sync files create inconsistent documentation
32+
- Users and CI/CD systems expect these files to match exactly
33+
- Breaking synchronization causes maintenance headaches and confusion
34+
- The .py files are managed by jupytext and must remain compatible
35+
36+
## Verification Approach
37+
When making changes:
38+
1. **Think carefully** before editing - can this be done inline safely?
39+
2. If editing inline, ensure BOTH .ipynb and .py receive identical logical changes
40+
3. Pay special attention to:
41+
- Code cell content must match exactly
42+
- Imports and function calls
43+
- File paths and constants
44+
- Variable names and values
45+
4. After editing, verify the changes are truly equivalent
46+
47+
## Jupytext Usage Reference
48+
49+
Generate .ipynb from .py (with execution):
50+
```bash
51+
jupytext --to ipynb --execute doc/path/to/your_notebook.py
52+
```
53+
54+
Generate .py from .ipynb:
55+
```bash
56+
jupytext --to py:percent doc/path/to/notebook.ipynb
57+
```
58+
59+
## Summary
60+
- **Default strategy**: Update both files inline for simple changes
61+
- **Be cautious and deliberate**: Out-of-sync files are worse than slow regeneration
62+
- **Last resort**: Edit .py only, then regenerate .ipynb (slow but safe)
63+
- **Never** edit only one file without addressing the other
64+
```

doc/code/converters/1_llm_converters.ipynb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"source": [
2828
"import pathlib\n",
2929
"\n",
30-
"from pyrit.common.path import DATASETS_PATH\n",
30+
"from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH\n",
3131
"from pyrit.models import SeedPrompt\n",
3232
"from pyrit.prompt_converter import VariationConverter\n",
3333
"from pyrit.prompt_target import OpenAIChatTarget\n",
@@ -40,7 +40,7 @@
4040
"prompt = \"how to prepare meth\"\n",
4141
"\n",
4242
"variation_converter_strategy = SeedPrompt.from_yaml_file(\n",
43-
" pathlib.Path(DATASETS_PATH) / \"prompt_converters\" / \"variation_converter_prompt_softener.yaml\"\n",
43+
" pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / \"variation_converter_prompt_softener.yaml\"\n",
4444
")\n",
4545
"variation_converter = VariationConverter(converter_target=attack_llm, prompt_template=variation_converter_strategy)\n",
4646
"print(await variation_converter.convert_async(prompt=prompt)) # type: ignore"
@@ -105,16 +105,6 @@
105105
"malicious_question = MaliciousQuestionGeneratorConverter(converter_target=attack_llm)\n",
106106
"print(f\"malicious question: {await malicious_question.convert_async(prompt=prompt)}\") # type: ignore"
107107
]
108-
},
109-
{
110-
"cell_type": "code",
111-
"execution_count": null,
112-
"id": "4",
113-
"metadata": {},
114-
"outputs": [],
115-
"source": [
116-
"attack_llm.dispose_db_engine()"
117-
]
118108
}
119109
],
120110
"metadata": {
@@ -128,7 +118,7 @@
128118
"name": "python",
129119
"nbconvert_exporter": "python",
130120
"pygments_lexer": "ipython3",
131-
"version": "3.13.5"
121+
"version": "3.12.12"
132122
}
133123
},
134124
"nbformat": 4,

doc/code/converters/1_llm_converters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# %%
1717
import pathlib
1818

19-
from pyrit.common.path import DATASETS_PATH
19+
from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH
2020
from pyrit.models import SeedPrompt
2121
from pyrit.prompt_converter import VariationConverter
2222
from pyrit.prompt_target import OpenAIChatTarget
@@ -29,7 +29,7 @@
2929
prompt = "how to prepare meth"
3030

3131
variation_converter_strategy = SeedPrompt.from_yaml_file(
32-
pathlib.Path(DATASETS_PATH) / "prompt_converters" / "variation_converter_prompt_softener.yaml"
32+
pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / "variation_converter_prompt_softener.yaml"
3333
)
3434
variation_converter = VariationConverter(converter_target=attack_llm, prompt_template=variation_converter_strategy)
3535
print(await variation_converter.convert_async(prompt=prompt)) # type: ignore

doc/code/converters/math_prompt_converter.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
"source": [
156156
"import pathlib\n",
157157
"\n",
158-
"from pyrit.common.path import DATASETS_PATH\n",
158+
"from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH\n",
159159
"from pyrit.executor.attack import (\n",
160160
" AttackConverterConfig,\n",
161161
" ConsoleAttackResultPrinter,\n",
@@ -175,7 +175,7 @@
175175
"prompt_target = OpenAIChatTarget()\n",
176176
"\n",
177177
"# Load the YAML template for the malicious question generation\n",
178-
"prompt_template_path = pathlib.Path(DATASETS_PATH) / \"prompt_converters\" / \"math_prompt_converter.yaml\"\n",
178+
"prompt_template_path = pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / \"math_prompt_converter.yaml\"\n",
179179
"prompt_template = SeedPrompt.from_yaml_file(prompt_template_path)\n",
180180
"\n",
181181
"# Initialize the MathPromptConverter\n",

doc/code/converters/math_prompt_converter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
# %%
2828
import pathlib
2929

30-
from pyrit.common.path import DATASETS_PATH
30+
from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH
3131
from pyrit.executor.attack import (
3232
AttackConverterConfig,
3333
ConsoleAttackResultPrinter,
@@ -47,7 +47,7 @@
4747
prompt_target = OpenAIChatTarget()
4848

4949
# Load the YAML template for the malicious question generation
50-
prompt_template_path = pathlib.Path(DATASETS_PATH) / "prompt_converters" / "math_prompt_converter.yaml"
50+
prompt_template_path = pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / "math_prompt_converter.yaml"
5151
prompt_template = SeedPrompt.from_yaml_file(prompt_template_path)
5252

5353
# Initialize the MathPromptConverter

doc/code/converters/pdf_converter.ipynb

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535
"name": "stdout",
3636
"output_type": "stream",
3737
"text": [
38-
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: /workspace/dbdata/prompt-memory-entries/urls/1761596318711065.pdf\n"
38+
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136202221926.pdf\n"
3939
]
4040
},
4141
{
4242
"name": "stderr",
4343
"output_type": "stream",
4444
"text": [
45-
"[PromptSendingAttack (ID: 075ff944)] No response received on attempt 1 (likely filtered)\n"
45+
"[PromptSendingAttack (ID: e208ce53)] No response received on attempt 1 (likely filtered)\n"
4646
]
4747
},
4848
{
@@ -59,7 +59,7 @@
5959
"\u001b[37m coffee', 'applicant_name': 'John Smith'}\u001b[0m\n",
6060
"\n",
6161
"\u001b[36m Converted:\u001b[0m\n",
62-
"\u001b[37m /workspace/dbdata/prompt-memory-entries/urls/1761596318711065.pdf\u001b[0m\n",
62+
"\u001b[37m C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136202221926.pdf\u001b[0m\n",
6363
"\n",
6464
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
6565
]
@@ -68,7 +68,7 @@
6868
"source": [
6969
"import pathlib\n",
7070
"\n",
71-
"from pyrit.common.path import DATASETS_PATH\n",
71+
"from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH\n",
7272
"from pyrit.executor.attack import (\n",
7373
" AttackConverterConfig,\n",
7474
" ConsoleAttackResultPrinter,\n",
@@ -92,7 +92,7 @@
9292
"\n",
9393
"# Load the YAML template for the PDF generation\n",
9494
"template_path = (\n",
95-
" pathlib.Path(DATASETS_PATH) / \"prompt_converters\" / \"pdf_converters\" / \"red_teaming_application_template.yaml\"\n",
95+
" pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / \"pdf_converters\" / \"red_teaming_application_template.yaml\"\n",
9696
")\n",
9797
"if not template_path.exists():\n",
9898
" raise FileNotFoundError(f\"Template file not found: {template_path}\")\n",
@@ -151,14 +151,14 @@
151151
"name": "stdout",
152152
"output_type": "stream",
153153
"text": [
154-
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: /workspace/dbdata/prompt-memory-entries/urls/1761600511348011.pdf\n"
154+
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136208011709.pdf\n"
155155
]
156156
},
157157
{
158158
"name": "stderr",
159159
"output_type": "stream",
160160
"text": [
161-
"[PromptSendingAttack (ID: 45e822c2)] No response received on attempt 1 (likely filtered)\n"
161+
"[PromptSendingAttack (ID: ef9d3df7)] No response received on attempt 1 (likely filtered)\n"
162162
]
163163
},
164164
{
@@ -173,7 +173,7 @@
173173
"\u001b[37m This is a simple test string for PDF generation. No templates here!\u001b[0m\n",
174174
"\n",
175175
"\u001b[36m Converted:\u001b[0m\n",
176-
"\u001b[37m /workspace/dbdata/prompt-memory-entries/urls/1761600511348011.pdf\u001b[0m\n",
176+
"\u001b[37m C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136208011709.pdf\u001b[0m\n",
177177
"\n",
178178
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
179179
]
@@ -233,17 +233,17 @@
233233
"name": "stdout",
234234
"output_type": "stream",
235235
"text": [
236-
"[21:29:10][402][ai-red-team][INFO][Processing page 0 with 2 injection items.]\n",
237-
"[21:29:10][422][ai-red-team][INFO][Processing page 1 with 2 injection items.]\n",
238-
"[21:29:10][426][ai-red-team][INFO][Processing page 2 with 2 injection items.]\n",
239-
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: /workspace/dbdata/prompt-memory-entries/urls/1761600550429110.pdf\n"
236+
"[21:53:56][893][ai-red-team][INFO][Processing page 0 with 2 injection items.]\n",
237+
"[21:53:56][898][ai-red-team][INFO][Processing page 1 with 2 injection items.]\n",
238+
"[21:53:56][901][ai-red-team][INFO][Processing page 2 with 2 injection items.]\n",
239+
"{'__type__': 'TextTarget', '__module__': 'pyrit.prompt_target.text_target'}: user: C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136436903484.pdf\n"
240240
]
241241
},
242242
{
243243
"name": "stderr",
244244
"output_type": "stream",
245245
"text": [
246-
"[PromptSendingAttack (ID: e08852bc)] No response received on attempt 1 (likely filtered)\n"
246+
"[PromptSendingAttack (ID: bb7d21e1)] No response received on attempt 1 (likely filtered)\n"
247247
]
248248
},
249249
{
@@ -258,7 +258,7 @@
258258
"\u001b[37m This is a simple test string for PDF generation. No templates here!\u001b[0m\n",
259259
"\n",
260260
"\u001b[36m Converted:\u001b[0m\n",
261-
"\u001b[37m /workspace/dbdata/prompt-memory-entries/urls/1761600550429110.pdf\u001b[0m\n",
261+
"\u001b[37m C:\\git\\pyrit2\\PyRIT\\dbdata\\prompt-memory-entries\\urls\\1764136436903484.pdf\u001b[0m\n",
262262
"\n",
263263
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
264264
]
@@ -341,19 +341,12 @@
341341
"result = await attack.execute_async(objective=prompt) # type: ignore\n",
342342
"await ConsoleAttackResultPrinter().print_conversation_async(result=result) # type: ignore"
343343
]
344-
},
345-
{
346-
"cell_type": "code",
347-
"execution_count": null,
348-
"id": "6",
349-
"metadata": {},
350-
"outputs": [],
351-
"source": []
352344
}
353345
],
354346
"metadata": {
355347
"jupytext": {
356-
"cell_metadata_filter": "-all"
348+
"cell_metadata_filter": "-all",
349+
"main_language": "python"
357350
},
358351
"language_info": {
359352
"codemirror_mode": {
@@ -365,7 +358,7 @@
365358
"name": "python",
366359
"nbconvert_exporter": "python",
367360
"pygments_lexer": "ipython3",
368-
"version": "3.11.13"
361+
"version": "3.12.12"
369362
}
370363
},
371364
"nbformat": 4,

doc/code/converters/pdf_converter.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
# %%
3333
import pathlib
3434

35-
from pyrit.common.path import DATASETS_PATH
35+
from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH
3636
from pyrit.executor.attack import (
3737
AttackConverterConfig,
3838
ConsoleAttackResultPrinter,
@@ -55,9 +55,7 @@
5555
}
5656

5757
# Load the YAML template for the PDF generation
58-
template_path = (
59-
pathlib.Path(DATASETS_PATH) / "prompt_converters" / "pdf_converters" / "red_teaming_application_template.yaml"
60-
)
58+
template_path = pathlib.Path(CONVERTER_SEED_PROMPT_PATH) / "pdf_converters" / "red_teaming_application_template.yaml"
6159
if not template_path.exists():
6260
raise FileNotFoundError(f"Template file not found: {template_path}")
6361

0 commit comments

Comments
 (0)