Skip to content
Merged
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ notice-rgx = "Copyright \\(c\\) Microsoft Corporation\\.\\s*\\n.*Licensed under
# Temporary ignores for pyrit/ subdirectories until issue #1176
# https://github.com/Azure/PyRIT/issues/1176 is fully resolved
# TODO: Remove these ignores once the issues are fixed
"pyrit/{auxiliary_attacks,exceptions,models,prompt_converter,ui}/**/*.py" = ["D101", "D102", "D103", "D104", "D105", "D106", "D107", "D401", "D404", "D417", "D418", "DOC102", "DOC201", "DOC202", "DOC402", "DOC501"]
"pyrit/{auxiliary_attacks,exceptions,models,ui}/**/*.py" = ["D101", "D102", "D103", "D104", "D105", "D106", "D107", "D401", "D404", "D417", "D418", "DOC102", "DOC201", "DOC202", "DOC402", "DOC501"]
"pyrit/__init__.py" = ["D104"]

[tool.ruff.lint.pydocstyle]
Expand Down
10 changes: 10 additions & 0 deletions pyrit/prompt_converter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

"""
Prompt converters for transforming prompts before sending them to targets in red teaming workflows.

Converters are organized into categories: Text-to-Text (encoding, obfuscation, translation, variation),
Audio (text-to-audio, audio-to-text, audio-to-audio), Image (text-to-image, image-to-image),
Video (image-to-video), File (text-to-PDF/URL), Selective Converting (partial prompt transformation),
and Human-in-the-Loop (interactive review). Converters can be stacked together to create complex
transformation pipelines for testing AI system robustness.
"""

from pyrit.prompt_converter.add_image_text_converter import AddImageTextConverter
from pyrit.prompt_converter.add_image_to_video_converter import AddImageVideoConverter
from pyrit.prompt_converter.add_text_image_converter import AddTextImageConverter
Expand Down
11 changes: 7 additions & 4 deletions pyrit/prompt_converter/add_image_text_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(
y_pos: int = 10,
):
"""
Initializes the converter with the image file path and text properties.
Initialize the converter with the image file path and text properties.

Args:
img_to_add (str): File path of image to add text to.
Expand All @@ -65,7 +65,7 @@ def __init__(

def _load_font(self) -> FreeTypeFont:
"""
Loads the font for a given font name and font size.
Load the font for a given font name and font size.

Returns:
ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font
Expand All @@ -84,13 +84,16 @@ def _load_font(self) -> FreeTypeFont:

def _add_text_to_image(self, text: str) -> Image.Image:
"""
Adds wrapped text to the image at `self._img_to_add`.
Add wrapped text to the image at `self._img_to_add`.

Args:
text (str): The text to add to the image.

Returns:
Image.Image: The image with added text.

Raises:
ValueError: If ``text`` is empty.
"""
if not text:
raise ValueError("Please provide valid text value")
Expand Down Expand Up @@ -123,7 +126,7 @@ def _add_text_to_image(self, text: str) -> Image.Image:

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given prompt by adding it as text to the image.
Convert the given prompt by adding it as text to the image.

Args:
prompt (str): The text to be added to the image.
Expand Down
10 changes: 7 additions & 3 deletions pyrit/prompt_converter/add_image_to_video_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(
img_resize_size: tuple[int, int] = (500, 500),
):
"""
Initializes the converter with the video path and image properties.
Initialize the converter with the video path and image properties.

Args:
video_path (str): File path of video to add image to.
Expand All @@ -63,14 +63,18 @@ def __init__(

async def _add_image_to_video(self, image_path: str, output_path: str) -> str:
"""
Adds an image to video.
Add an image to video.

Args:
image_path (str): The image path to add to video.
output_path (str): The output video path.

Returns:
str: The output video path.

Raises:
ModuleNotFoundError: If OpenCV is not installed.
ValueError: If the image path is invalid or unsupported video format.
"""
try:
import cv2 # noqa: F401
Expand Down Expand Up @@ -167,7 +171,7 @@ async def _add_image_to_video(self, image_path: str, output_path: str) -> str:

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "image_path") -> ConverterResult:
"""
Converts the given prompt (image) by adding it to a video.
Convert the given prompt (image) by adding it to a video.

Args:
prompt (str): The image path to be added to the video.
Expand Down
8 changes: 4 additions & 4 deletions pyrit/prompt_converter/add_text_image_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(
y_pos: int = 10,
):
"""
Initializes the converter with the text and text properties.
Initialize the converter with the text and text properties.

Args:
text_to_add (str): Text to add to an image. Defaults to empty string.
Expand All @@ -65,7 +65,7 @@ def __init__(

def _load_font(self) -> FreeTypeFont:
"""
Loads the font for a given font name and font size.
Load the font for a given font name and font size.

Returns:
ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font
Expand All @@ -84,7 +84,7 @@ def _load_font(self) -> FreeTypeFont:

def _add_text_to_image(self, image: Image.Image) -> Image.Image:
"""
Adds wrapped text to the image.
Add wrapped text to the image.

Args:
image (Image.Image): The image to which text will be added.
Expand Down Expand Up @@ -119,7 +119,7 @@ def _add_text_to_image(self, image: Image.Image) -> Image.Image:

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "image_path") -> ConverterResult:
"""
Converts the given prompt (image) by adding text to it.
Convert the given prompt (image) by adding text to it.

Args:
prompt (str): The image file path to which text will be added.
Expand Down
34 changes: 32 additions & 2 deletions pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(
incorporate_user_prompt: bool = True,
):
"""
Initializes the converter with various options to control the scenarios generated.
Initialize the converter with various options to control the scenarios generated.

Args:
include_raw (bool): Include scenarios with raw ANSI codes.
Expand All @@ -59,13 +59,43 @@ def __init__(
self.incorporate_user_prompt = incorporate_user_prompt

def input_supported(self, input_type: PromptDataType) -> bool:
"""
Check if the input type is supported.

Args:
input_type (PromptDataType): The type of input data.

Returns:
bool: True if the input type is supported, False otherwise.
"""
return input_type == "text"

def output_supported(self, output_type: PromptDataType) -> bool:
"""
Check if the output type is supported.

Args:
output_type (PromptDataType): The type of output data.

Returns:
bool: True if the output type is supported, False otherwise.
"""
return output_type == "text"

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""Converts the given prompt into an ANSI attack scenario."""
"""
Convert the given prompt into an ANSI attack scenario.

Args:
prompt (str): The original user prompt.
input_type (PromptDataType): The type of input data.

Returns:
ConverterResult: The result containing the generated ANSI scenario prompt.

Raises:
ValueError: If the input type is not supported.
"""
if not self.input_supported(input_type):
raise ValueError("Input type not supported")

Expand Down
16 changes: 14 additions & 2 deletions pyrit/prompt_converter/ascii_art_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,27 @@ class AsciiArtConverter(PromptConverter):

def __init__(self, font: str = "rand") -> None:
"""
Initializes the converter with a specified font.
Initialize the converter with a specified font.

Args:
font (str): The font to use for ASCII art. Defaults to "rand" which selects a random font.
"""
self.font_value = font

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""Converts the given prompt into ASCII art."""
"""
Convert the given prompt into ASCII art.

Args:
prompt (str): The prompt to be converted.
input_type (PromptDataType): The type of input data.

Returns:
ConverterResult: The result containing the ASCII art representation of the prompt.

Raises:
ValueError: If the input type is not supported.
"""
if not self.input_supported(input_type):
raise ValueError("Input type not supported")

Expand Down
6 changes: 3 additions & 3 deletions pyrit/prompt_converter/ask_to_decode_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class AskToDecodeConverter(PromptConverter):

def __init__(self, template: Optional[str] = None, encoding_name: str = "cipher") -> None:
"""
Initializes the converter with a specified encoding name and template.
Initialize the converter with a specified encoding name and template.

By default, if no template is provided, a random template from basic_templates
will be used. If an encoding_name is provided, both basic_templates and
Expand All @@ -60,14 +60,14 @@ def __init__(self, template: Optional[str] = None, encoding_name: str = "cipher"

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given encoded text by wrapping it with a decoding request prompt.
Convert the given encoded text by wrapping it with a decoding request prompt.

Args:
prompt (str): The encoded text to be wrapped with a decoding request.
input_type (PromptDataType, optional): Type of input data. Defaults to "text".

Returns:
ConverterResult: The encoded text wrapped in a decoding prompt.
ConverterResult: The result containing the converted prompt.

Raises:
ValueError: If the input type is not supported (only "text" is supported).
Expand Down
16 changes: 14 additions & 2 deletions pyrit/prompt_converter/atbash_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AtbashConverter(PromptConverter):

def __init__(self, *, append_description: bool = False) -> None:
"""
Initializes the converter with an option to append a description.
Initialize the converter with an option to append a description.

Args:
append_description (bool): If True, appends plaintext "expert" text to the prompt.
Expand All @@ -40,7 +40,19 @@ def __init__(self, *, append_description: bool = False) -> None:
)

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""Converts the given prompt using the Atbash cipher."""
"""
Convert the given prompt using the Atbash cipher.

Args:
prompt (str): The prompt to be converted.
input_type (PromptDataType): The type of input data.

Returns:
ConverterResult: The result containing the encoded prompt.

Raises:
ValueError: If the input type is not supported.
"""
if not self.input_supported(input_type):
raise ValueError("Input type not supported")

Expand Down
4 changes: 2 additions & 2 deletions pyrit/prompt_converter/audio_frequency_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
shift_value: int = 20000,
) -> None:
"""
Initializes the converter with the specified output format and shift value.
Initialize the converter with the specified output format and shift value.

Args:
output_format (str): The format of the audio file, defaults to "wav".
Expand All @@ -44,7 +44,7 @@ def __init__(

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audio_path") -> ConverterResult:
"""
Converts the given audio file by shifting its frequency.
Convert the given audio file by shifting its frequency.

Args:
prompt (str): File path to the audio file to be converted.
Expand Down
16 changes: 11 additions & 5 deletions pyrit/prompt_converter/azure_speech_audio_to_text_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(
recognition_language: str = "en-US",
) -> None:
"""
Initializes the converter with Azure Speech service credentials and recognition language.
Initialize the converter with Azure Speech service credentials and recognition language.

Args:
azure_speech_region (str, Optional): The name of the Azure region.
Expand Down Expand Up @@ -88,7 +88,7 @@ def __init__(

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audio_path") -> ConverterResult:
"""
Converts the given audio file into its text representation.
Convert the given audio file into its text representation.

Args:
prompt (str): File path to the audio file to be transcribed.
Expand Down Expand Up @@ -120,13 +120,16 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audi

def recognize_audio(self, audio_bytes: bytes) -> str:
"""
Recognizes audio file and returns transcribed text.
Recognize audio file and return transcribed text.

Args:
audio_bytes (bytes): Audio bytes input.

Returns:
str: Transcribed text.

Raises:
ModuleNotFoundError: If the azure.cognitiveservices.speech module is not installed.
"""
try:
import azure.cognitiveservices.speech as speechsdk # noqa: F811
Expand Down Expand Up @@ -177,7 +180,7 @@ def recognize_audio(self, audio_bytes: bytes) -> str:

def transcript_cb(self, evt: Any, transcript: list[str]) -> None:
"""
Callback function that appends transcribed text upon receiving a "recognized" event.
Append transcribed text upon receiving a "recognized" event.

Args:
evt (speechsdk.SpeechRecognitionEventArgs): Event.
Expand All @@ -188,11 +191,14 @@ def transcript_cb(self, evt: Any, transcript: list[str]) -> None:

def stop_cb(self, evt: Any, recognizer: Any) -> None:
"""
Callback function that stops continuous recognition upon receiving an event 'evt'.
Stop continuous recognition upon receiving an event 'evt'.

Args:
evt (speechsdk.SpeechRecognitionEventArgs): Event.
recognizer (speechsdk.SpeechRecognizer): Speech recognizer object.

Raises:
ModuleNotFoundError: If the azure.cognitiveservices.speech module is not installed.
"""
try:
import azure.cognitiveservices.speech as speechsdk # noqa: F811
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(
output_format: AzureSpeechAudioFormat = "wav",
) -> None:
"""
Initializes the converter with Azure Speech service credentials, synthesis language, and voice name.
Initialize the converter with Azure Speech service credentials, synthesis language, and voice name.

Args:
azure_speech_region (str, Optional): The name of the Azure region.
Expand All @@ -61,7 +61,6 @@ def __init__(
synthesis_voice_name (str): Synthesis voice name, see URL.
For more details see the following link for synthesis language and synthesis voice:
https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support
filename (str): File name to be generated. Please include either .wav or .mp3.
output_format (str): Either wav or mp3. Must match the file prefix.

Raises:
Expand Down Expand Up @@ -96,7 +95,7 @@ def __init__(

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given text prompt into its audio representation.
Convert the given text prompt into its audio representation.

Args:
prompt (str): The text prompt to be converted into audio.
Expand Down
2 changes: 1 addition & 1 deletion pyrit/prompt_converter/base2048_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(self) -> None:

async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given prompt to base2048 encoding.
Convert the given prompt to base2048 encoding.

Args:
prompt: The prompt to be converted.
Expand Down
Loading