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
5 changes: 5 additions & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,14 @@ API Reference
AddTextImageConverter
AnsiAttackConverter
AsciiArtConverter
AudioEchoConverter
AsciiSmugglerConverter
AskToDecodeConverter
AtbashConverter
AudioFrequencyConverter
AudioSpeedConverter
AudioVolumeConverter
AudioWhiteNoiseConverter
AzureSpeechAudioToTextConverter
AzureSpeechTextToAudioConverter
Base2048Converter
Expand Down Expand Up @@ -441,6 +445,7 @@ API Reference
MaliciousQuestionGeneratorConverter
MathObfuscationConverter
MathPromptConverter
MultiLanguageTranslationConverter
MorseConverter
NatoConverter
NegationTrapConverter
Expand Down
176 changes: 93 additions & 83 deletions doc/code/converters/1_text_to_text_converters.ipynb

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion doc/code/converters/1_text_to_text_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
DenylistConverter,
MaliciousQuestionGeneratorConverter,
MathPromptConverter,
MultiLanguageTranslationConverter,
NoiseConverter,
PersuasionConverter,
RandomTranslationConverter,
Expand Down Expand Up @@ -279,12 +280,20 @@
translation_converter = TranslationConverter(converter_target=attack_llm, language="French")
print("Translation (French):", await translation_converter.convert_async(prompt=prompt)) # type: ignore

# Random translation through multiple languages
# Random translation translates each word to a random language
random_translation_converter = RandomTranslationConverter(
converter_target=attack_llm, languages=["French", "German", "Spanish", "English"]
)
print("Random Translation:", await random_translation_converter.convert_async(prompt=prompt)) # type: ignore

# Multi-language translation splits the prompt into segments and translates each to a different language.
# Unlike RandomTranslationConverter (word-level, random), this operates on contiguous multi-word segments
# with deterministic language assignment — segment i maps to languages[i].
multi_lang_converter = MultiLanguageTranslationConverter(
converter_target=attack_llm, languages=["French", "Spanish", "Italian"]
)
print("Multi-Language Translation:", await multi_lang_converter.convert_async(prompt=prompt)) # type: ignore

# Tense changes verb tense
tense_converter = TenseConverter(converter_target=attack_llm, tense="far future")
print("Tense (future):", await tense_converter.convert_async(prompt=prompt)) # type: ignore
Expand Down
105 changes: 95 additions & 10 deletions doc/code/converters/2_audio_converters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"\n",
"- **[Text to Audio](#text-to-audio)**: Convert text into spoken audio files\n",
"- **[Audio to Text](#audio-to-text)**: Transcribe audio files into text\n",
"- **[Audio to Audio](#audio-to-audio)**: Modify audio files (e.g., frequency changes)"
"- **[Audio to Audio](#audio-to-audio)**: Modify audio files (speed, volume, echo, frequency, noise)"
]
},
{
Expand All @@ -39,16 +39,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['/home/vscode/.pyrit/.env', '/home/vscode/.pyrit/.env.local']\n",
"Loaded environment file: /home/vscode/.pyrit/.env\n",
"Loaded environment file: /home/vscode/.pyrit/.env.local\n"
"No default environment files found. Using system environment variables only.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"audio_path: /workspace/dbdata/prompt-memory-entries/audio/1767054630224156.wav\n"
"audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385538448420.wav\n"
]
}
],
Expand Down Expand Up @@ -122,7 +120,15 @@
"<a id=\"audio-to-audio\"></a>\n",
"## Audio to Audio\n",
"\n",
"The `AudioFrequencyConverter` modifies audio files by increasing their frequency, enabling the probing of audio modality targets with heightened frequencies."
"Audio-to-audio converters modify existing audio files. All of these converters accept `audio_path` input\n",
"and produce `audio_path` output, preserving the original sample rate, bit depth, and channel count.\n",
"\n",
"Available converters:\n",
"- **`AudioFrequencyConverter`** — Shifts the audio frequency (pitch) higher\n",
"- **`AudioSpeedConverter`** — Changes playback speed without altering pitch\n",
"- **`AudioVolumeConverter`** — Scales the amplitude (louder or quieter)\n",
"- **`AudioEchoConverter`** — Adds an echo effect with configurable delay and decay\n",
"- **`AudioWhiteNoiseConverter`** — Mixes white noise into the signal"
]
},
{
Expand All @@ -135,21 +141,100 @@
"name": "stdout",
"output_type": "stream",
"text": [
"audio_path: /workspace/dbdata/prompt-memory-entries/audio/1767054635425663.wav\n"
"Frequency shift: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540595766.wav\n",
"Speed (0.5x): audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540602793.wav\n",
"Volume (2x): audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540607791.wav\n",
"Echo: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540611791.wav\n",
"White noise: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540617281.wav\n"
]
}
],
"source": [
"from pyrit.prompt_converter import AudioFrequencyConverter\n",
"from pyrit.prompt_converter import (\n",
" AudioEchoConverter,\n",
" AudioFrequencyConverter,\n",
" AudioSpeedConverter,\n",
" AudioVolumeConverter,\n",
" AudioWhiteNoiseConverter,\n",
")\n",
"\n",
"# Use audio file created above\n",
"assert os.path.exists(audio_convert_result.output_text)\n",
"prompt = str(pathlib.Path(DB_DATA_PATH) / \"dbdata\" / \"audio\" / audio_convert_result.output_text)\n",
"\n",
"# Frequency shift — increases the audio frequency (pitch)\n",
"audio_frequency_converter = AudioFrequencyConverter()\n",
"converted_audio_file = await audio_frequency_converter.convert_async(prompt=prompt) # type: ignore\n",
"converted = await audio_frequency_converter.convert_async(prompt=prompt) # type: ignore\n",
"print(\"Frequency shift:\", converted)\n",
"\n",
"# Speed change — speeds up (>1.0) or slows down (<1.0) without pitch change\n",
"audio_speed_converter = AudioSpeedConverter(speed_factor=0.5)\n",
"converted = await audio_speed_converter.convert_async(prompt=prompt) # type: ignore\n",
"print(\"Speed (0.5x):\", converted)\n",
"\n",
"# Volume scaling — amplifies (>1.0) or reduces (<1.0) the audio amplitude\n",
"audio_volume_converter = AudioVolumeConverter(volume_factor=2.0)\n",
"converted = await audio_volume_converter.convert_async(prompt=prompt) # type: ignore\n",
"print(\"Volume (2x):\", converted)\n",
"\n",
"# Echo — adds a delayed, attenuated copy of the signal\n",
"audio_echo_converter = AudioEchoConverter(delay=0.3, decay=0.5)\n",
"converted = await audio_echo_converter.convert_async(prompt=prompt) # type: ignore\n",
"print(\"Echo:\", converted)\n",
"\n",
"# White noise — mixes random noise into the audio\n",
"audio_noise_converter = AudioWhiteNoiseConverter(noise_scale=0.05)\n",
"converted = await audio_noise_converter.convert_async(prompt=prompt) # type: ignore\n",
"print(\"White noise:\", converted)"
]
},
{
"cell_type": "markdown",
"id": "7",
"metadata": {},
"source": [
"### Chaining Audio Converters\n",
"\n",
"Audio-to-audio converters can be chained together to build a multi-step audio perturbation pipeline.\n",
"Each converter takes the output of the previous one as input."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AudioSpeedConverter: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540632000.wav\n",
"AudioVolumeConverter: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540650996.wav\n",
"AudioEchoConverter: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540668320.wav\n",
"AudioWhiteNoiseConverter: audio_path: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540685896.wav\n",
"\n",
"Final output: PyRIT\\dbdata\\prompt-memory-entries\\audio\\1771385540685896.wav\n"
]
}
],
"source": [
"# Chain: slow down → increase volume → add echo → add white noise\n",
"pipeline = [\n",
" AudioSpeedConverter(speed_factor=0.5),\n",
" AudioVolumeConverter(volume_factor=1.5),\n",
" AudioEchoConverter(delay=0.3, decay=0.5),\n",
" AudioWhiteNoiseConverter(noise_scale=0.02),\n",
"]\n",
"\n",
"# Start with the original audio file\n",
"current_prompt = prompt\n",
"for converter in pipeline:\n",
" result = await converter.convert_async(prompt=current_prompt) # type: ignore\n",
" current_prompt = result.output_text\n",
" print(f\"{converter.__class__.__name__}: {result}\")\n",
"\n",
"print(converted_audio_file)"
"print(f\"\\nFinal output: {current_prompt}\")"
]
}
],
Expand Down
68 changes: 63 additions & 5 deletions doc/code/converters/2_audio_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#
# - **[Text to Audio](#text-to-audio)**: Convert text into spoken audio files
# - **[Audio to Text](#audio-to-text)**: Transcribe audio files into text
# - **[Audio to Audio](#audio-to-audio)**: Modify audio files (e.g., frequency changes)
# - **[Audio to Audio](#audio-to-audio)**: Modify audio files (speed, volume, echo, frequency, noise)

# %% [markdown]
# <a id="text-to-audio"></a>
Expand Down Expand Up @@ -73,16 +73,74 @@
# <a id="audio-to-audio"></a>
# ## Audio to Audio
#
# The `AudioFrequencyConverter` modifies audio files by increasing their frequency, enabling the probing of audio modality targets with heightened frequencies.
# Audio-to-audio converters modify existing audio files. All of these converters accept `audio_path` input
# and produce `audio_path` output, preserving the original sample rate, bit depth, and channel count.
#
# Available converters:
# - **`AudioFrequencyConverter`** — Shifts the audio frequency (pitch) higher
# - **`AudioSpeedConverter`** — Changes playback speed without altering pitch
# - **`AudioVolumeConverter`** — Scales the amplitude (louder or quieter)
# - **`AudioEchoConverter`** — Adds an echo effect with configurable delay and decay
# - **`AudioWhiteNoiseConverter`** — Mixes white noise into the signal

# %%
from pyrit.prompt_converter import AudioFrequencyConverter
from pyrit.prompt_converter import (
AudioEchoConverter,
AudioFrequencyConverter,
AudioSpeedConverter,
AudioVolumeConverter,
AudioWhiteNoiseConverter,
)

# Use audio file created above
assert os.path.exists(audio_convert_result.output_text)
prompt = str(pathlib.Path(DB_DATA_PATH) / "dbdata" / "audio" / audio_convert_result.output_text)

# Frequency shift — increases the audio frequency (pitch)
audio_frequency_converter = AudioFrequencyConverter()
converted_audio_file = await audio_frequency_converter.convert_async(prompt=prompt) # type: ignore
converted = await audio_frequency_converter.convert_async(prompt=prompt) # type: ignore
print("Frequency shift:", converted)

# Speed change — speeds up (>1.0) or slows down (<1.0) without pitch change
audio_speed_converter = AudioSpeedConverter(speed_factor=0.5)
converted = await audio_speed_converter.convert_async(prompt=prompt) # type: ignore
print("Speed (0.5x):", converted)

# Volume scaling — amplifies (>1.0) or reduces (<1.0) the audio amplitude
audio_volume_converter = AudioVolumeConverter(volume_factor=2.0)
converted = await audio_volume_converter.convert_async(prompt=prompt) # type: ignore
print("Volume (2x):", converted)

# Echo — adds a delayed, attenuated copy of the signal
audio_echo_converter = AudioEchoConverter(delay=0.3, decay=0.5)
converted = await audio_echo_converter.convert_async(prompt=prompt) # type: ignore
print("Echo:", converted)

# White noise — mixes random noise into the audio
audio_noise_converter = AudioWhiteNoiseConverter(noise_scale=0.05)
converted = await audio_noise_converter.convert_async(prompt=prompt) # type: ignore
print("White noise:", converted)

print(converted_audio_file)
# %% [markdown]
# ### Chaining Audio Converters
#
# Audio-to-audio converters can be chained together to build a multi-step audio perturbation pipeline.
# Each converter takes the output of the previous one as input.

# %%
# Chain: slow down → increase volume → add echo → add white noise
pipeline = [
AudioSpeedConverter(speed_factor=0.5),
AudioVolumeConverter(volume_factor=1.5),
AudioEchoConverter(delay=0.3, decay=0.5),
AudioWhiteNoiseConverter(noise_scale=0.02),
]

# Start with the original audio file
current_prompt = prompt
for converter in pipeline:
result = await converter.convert_async(prompt=current_prompt) # type: ignore
current_prompt = result.output_text
print(f"{converter.__class__.__name__}: {result}")

print(f"\nFinal output: {current_prompt}")
10 changes: 10 additions & 0 deletions pyrit/prompt_converter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
from pyrit.prompt_converter.ascii_art_converter import AsciiArtConverter
from pyrit.prompt_converter.ask_to_decode_converter import AskToDecodeConverter
from pyrit.prompt_converter.atbash_converter import AtbashConverter
from pyrit.prompt_converter.audio_echo_converter import AudioEchoConverter
from pyrit.prompt_converter.audio_frequency_converter import AudioFrequencyConverter
from pyrit.prompt_converter.audio_speed_converter import AudioSpeedConverter
from pyrit.prompt_converter.audio_volume_converter import AudioVolumeConverter
from pyrit.prompt_converter.audio_white_noise_converter import AudioWhiteNoiseConverter
from pyrit.prompt_converter.azure_speech_audio_to_text_converter import AzureSpeechAudioToTextConverter
from pyrit.prompt_converter.azure_speech_text_to_audio_converter import AzureSpeechTextToAudioConverter
from pyrit.prompt_converter.base64_converter import Base64Converter
Expand Down Expand Up @@ -47,6 +51,7 @@
from pyrit.prompt_converter.math_obfuscation_converter import MathObfuscationConverter
from pyrit.prompt_converter.math_prompt_converter import MathPromptConverter
from pyrit.prompt_converter.morse_converter import MorseConverter
from pyrit.prompt_converter.multi_language_translation_converter import MultiLanguageTranslationConverter
from pyrit.prompt_converter.nato_converter import NatoConverter
from pyrit.prompt_converter.negation_trap_converter import NegationTrapConverter
from pyrit.prompt_converter.noise_converter import NoiseConverter
Expand Down Expand Up @@ -110,7 +115,11 @@
"AsciiSmugglerConverter",
"AskToDecodeConverter",
"AtbashConverter",
"AudioEchoConverter",
"AudioFrequencyConverter",
"AudioSpeedConverter",
"AudioVolumeConverter",
"AudioWhiteNoiseConverter",
"AzureSpeechAudioToTextConverter",
"AzureSpeechTextToAudioConverter",
"Base2048Converter",
Expand Down Expand Up @@ -142,6 +151,7 @@
"MathObfuscationConverter",
"MathPromptConverter",
"MorseConverter",
"MultiLanguageTranslationConverter",
"NatoConverter",
"NegationTrapConverter",
"NoiseConverter",
Expand Down
Loading