From c69ed54dc5ddd975b8edc489beacfbb52b8577fe Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Sat, 14 Jun 2025 22:31:16 +0200 Subject: [PATCH 1/8] update `prompt_converter.py` --- pyrit/prompt_converter/prompt_converter.py | 38 +++++++++++++++------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/pyrit/prompt_converter/prompt_converter.py b/pyrit/prompt_converter/prompt_converter.py index 8a8584df24..78e3ea9513 100644 --- a/pyrit/prompt_converter/prompt_converter.py +++ b/pyrit/prompt_converter/prompt_converter.py @@ -12,7 +12,11 @@ @dataclass class ConverterResult: + """The result of a prompt conversion, containing the converted output and its type.""" + + #: The converted text output. This is the main result of the conversion. output_text: str + #: The data type of the converted output. Indicates the format/type of the `output_text`. output_type: PromptDataType def __str__(self): @@ -21,44 +25,50 @@ def __str__(self): class PromptConverter(abc.ABC, Identifier): """ - A prompt converter is responsible for converting prompts into a different representation. - + Base class for converters that transform prompts into a different representation or format. """ + def __init__(self): + """ + Initializes the prompt converter. + """ + super().__init__() + @abc.abstractmethod async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converts the given prompts into a different representation + Converts the given prompt into the target format supported by the converter. Args: - prompt: The prompt to be converted. + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. Returns: - str: The converted representation of the prompts. + ConverterResult: The result of the conversion, including the converted output and its type. """ @abc.abstractmethod def input_supported(self, input_type: PromptDataType) -> bool: """ - Checks if the input type is supported by the converter + Checks if the input type is supported by the converter. Args: - input_type: The input type to check + input_type (PromptDataType): The input type to check. Returns: - bool: True if the input type is supported, False otherwise + bool: True if the input type is supported, False otherwise. """ @abc.abstractmethod def output_supported(self, output_type: PromptDataType) -> bool: """ - Checks if the output type is supported by the converter + Checks if the output type is supported by the converter. Args: - output_type: The output type to check + output_type (PromptDataType): The output type to check. Returns: - bool: True if the output type is supported, False otherwise + bool: True if the output type is supported, False otherwise. """ async def convert_tokens_async( @@ -109,6 +119,12 @@ async def _replace_text_match(self, match): return result def get_identifier(self): + """ + Returns an identifier dictionary for the converter. + + Returns: + dict: The identifier dictionary. + """ public_attributes = {} public_attributes["__type__"] = self.__class__.__name__ public_attributes["__module__"] = self.__class__.__module__ From 4c47068e67adf523760337c7df69e06876fab39e Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:19:11 +0200 Subject: [PATCH 2/8] work in progress... --- doc/api.rst | 2 + .../add_image_text_converter.py | 38 +++++----- .../add_image_to_video_converter.py | 29 +++++--- .../add_text_image_converter.py | 36 +++++---- .../ansi_escape/ansi_attack_converter.py | 12 ++- pyrit/prompt_converter/ascii_art_converter.py | 17 ++--- pyrit/prompt_converter/atbash_converter.py | 25 +++---- .../audio_frequency_converter.py | 26 ++++--- .../azure_speech_audio_to_text_converter.py | 46 +++++++----- .../azure_speech_text_to_audio_converter.py | 35 ++++++--- pyrit/prompt_converter/base64_converter.py | 6 +- pyrit/prompt_converter/binary_converter.py | 7 +- pyrit/prompt_converter/caesar_converter.py | 24 +++--- .../character_space_converter.py | 11 +-- .../charswap_attack_converter.py | 10 ++- .../codechameleon_converter.py | 74 ++++++++++--------- .../colloquial_wordswap_converter.py | 16 +--- pyrit/prompt_converter/denylist_converter.py | 23 ++++-- pyrit/prompt_converter/diacritic_converter.py | 25 ++----- pyrit/prompt_converter/flip_converter.py | 6 +- .../fuzzer_converter/fuzzer_converter_base.py | 14 ++-- .../fuzzer_crossover_converter.py | 15 ++-- .../fuzzer_expand_converter.py | 6 +- .../fuzzer_rephrase_converter.py | 3 + .../fuzzer_shorten_converter.py | 3 + .../fuzzer_similar_converter.py | 3 + .../human_in_the_loop_converter.py | 20 +++-- .../insert_punctuation_converter.py | 10 ++- .../llm_generic_text_converter.py | 19 +++-- .../malicious_question_generator_converter.py | 2 +- .../prompt_converter/math_prompt_converter.py | 17 +++-- pyrit/prompt_converter/noise_converter.py | 8 +- pyrit/prompt_converter/rot13_converter.py | 4 +- .../prompt_converter/string_join_converter.py | 7 +- .../suffix_append_converter.py | 18 ++--- pyrit/prompt_converter/tense_converter.py | 7 +- .../prompt_converter/text_to_hex_converter.py | 4 +- .../ascii_smuggler_converter.py | 2 +- pyrit/prompt_converter/tone_converter.py | 7 +- .../toxic_sentence_generator_converter.py | 33 ++------- .../prompt_converter/translation_converter.py | 3 + .../unicode_replacement_converter.py | 8 +- .../prompt_converter/unicode_sub_converter.py | 8 +- pyrit/prompt_converter/url_converter.py | 6 +- pyrit/prompt_converter/variation_converter.py | 10 +-- .../prompt_converter/word_level_converter.py | 28 ++++++- pyrit/prompt_converter/zalgo_converter.py | 7 +- 47 files changed, 407 insertions(+), 333 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 5a10c6498f..8bfc7d0185 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -319,6 +319,7 @@ API Reference RepeatTokenConverter ROT13Converter SearchReplaceConverter + SneakyBitsSmugglerConverter StringJoinConverter SuffixAppendConverter SuperscriptConverter @@ -332,6 +333,7 @@ API Reference UnicodeSubstitutionConverter UrlConverter VariationConverter + VariationSelectorSmugglerConverter ZalgoConverter ZeroWidthConverter diff --git a/pyrit/prompt_converter/add_image_text_converter.py b/pyrit/prompt_converter/add_image_text_converter.py index bc8cc93689..0a7dc9f2ec 100644 --- a/pyrit/prompt_converter/add_image_text_converter.py +++ b/pyrit/prompt_converter/add_image_text_converter.py @@ -18,16 +18,8 @@ class AddImageTextConverter(PromptConverter): """ Adds a string to an image and wraps the text into multiple lines if necessary. - This class is similar to AddImageTextConverter except + This class is similar to :class:`AddTextImageConverter` except we pass in an image file path as an argument to the constructor as opposed to text. - - Args: - img_to_add (str): File path of image to add text to - font_name (str): Path of font to use. Must be a TrueType font (.ttf). Defaults to "helvetica.ttf". - color (tuple): Color to print text in, using RGB values. Defaults to (0, 0, 0). - font_size (float): Size of font to use. Defaults to 15. - x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. - y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. """ def __init__( @@ -39,6 +31,17 @@ def __init__( x_pos: int = 10, y_pos: int = 10, ): + """ + Initializes the converter with the image file path and text properties. + + Args: + img_to_add (str): File path of image to add text to. + font_name (str): Path of font to use. Must be a TrueType font (.ttf). Defaults to "helvetica.ttf". + color (tuple): Color to print text in, using RGB values. Defaults to (0, 0, 0). + font_size (float): Size of font to use. Defaults to 15. + x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. + y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. + """ if not img_to_add: raise ValueError("Please provide valid image path") if not font_name.endswith(".ttf"): @@ -53,11 +56,11 @@ def __init__( def _load_font(self): """ - Load the font for a given font name and font size + Loads the font for a given font name and font size. Returns: - ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font - cannot be loaded, the default font is returned. + ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font + cannot be loaded, the default font is returned. Raises: OSError: If the font resource cannot be loaded, a warning is logged and the default font is used instead. @@ -72,7 +75,7 @@ def _load_font(self): def _add_text_to_image(self, text: str) -> Image.Image: """ - Adds wrapped text to the image at self._img_to_add. + Adds wrapped text to the image at `self._img_to_add`. Args: text (str): The text to add to the image. @@ -111,13 +114,14 @@ def _add_text_to_image(self, text: str) -> Image.Image: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter that overlays input text on the img_to_add. + Converts the given prompt by adding it as text to the image specified in the constructor. Args: - prompt (str): The prompt to be added to the image. - input_type (PromptDataType): type of data + prompt (str): The text to be added to the image. + input_type (PromptDataType): The type of input data. + Returns: - ConverterResult: The filename of the converted image as a ConverterResult Object + ConverterResult: The path to the updated image as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/add_image_to_video_converter.py b/pyrit/prompt_converter/add_image_to_video_converter.py index 4cbb725e73..d9ec87623c 100644 --- a/pyrit/prompt_converter/add_image_to_video_converter.py +++ b/pyrit/prompt_converter/add_image_to_video_converter.py @@ -27,13 +27,7 @@ class AddImageVideoConverter(PromptConverter): """ Adds an image to a video at a specified position. - Also, currently the image is placed in the whole video, not at a specific timepoint - - Args: - video_path (str): File path of video to add image to - output_path (str, Optional): File path of output video. Defaults to None. - img_position (tuple): Position to place image in video. Defaults to (10, 10). - img_resize_size (tuple): Size to resize image to. Defaults to (500, 500). + Also, currently the image is placed in the whole video, not at a specific timepoint. """ def __init__( @@ -43,6 +37,15 @@ def __init__( img_position: tuple = (10, 10), img_resize_size: tuple = (500, 500), ): + """ + Initializes the converter with the video path and image properties. + + Args: + video_path (str): File path of video to add image to. + output_path (str, Optional): File path of output video. Defaults to None. + img_position (tuple): Position to place image in video. Defaults to (10, 10). + img_resize_size (tuple): Size to resize image to. Defaults to (500, 500). + """ if not video_path: raise ValueError("Please provide valid video path") @@ -54,13 +57,14 @@ def __init__( async def _add_image_to_video(self, image_path: str, output_path: str) -> str: """ - Adds image to video + Adds an image to video. + Args: image_path (str): The image path to add to video. output_path (str): The output video path. Returns: - output_path (str): The output video path. + str: The output video path. """ try: @@ -158,13 +162,14 @@ 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: """ - Converter that adds an image to a video + Converts the given prompt by adding an image to the video specified in the constructor. Args: prompt (str): The image file name to be added to the video. - input_type (PromptDataType): type of data + input_type (PromptDataType): The type of input data. + Returns: - ConverterResult: The filename of the converted video as a ConverterResult Object + ConverterResult: The filename of the converted video as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/add_text_image_converter.py b/pyrit/prompt_converter/add_text_image_converter.py index 0bec90a93a..6537194c8d 100644 --- a/pyrit/prompt_converter/add_text_image_converter.py +++ b/pyrit/prompt_converter/add_text_image_converter.py @@ -18,14 +18,8 @@ class AddTextImageConverter(PromptConverter): """ Adds a string to an image and wraps the text into multiple lines if necessary. - - Args: - text_to_add (str): Text to add to an image. Defaults to empty string. - font_name (str): Path of font to use. Must be a TrueType font (.ttf). Defaults to "helvetica.ttf". - color (tuple): Color to print text in, using RGB values. Defaults to (0, 0, 0). - font_size (float): Size of font to use. Defaults to 15. - x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. - y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. + This class is similar to :class:`AddImageTextConverter` except + we pass in text as an argument to the constructor as opposed to an image file path. """ def __init__( @@ -37,6 +31,17 @@ def __init__( x_pos: int = 10, y_pos: int = 10, ): + """ + Initializes the converter with the text and text properties. + + Args: + text_to_add (str): Text to add to an image. Defaults to empty string. + font_name (str): Path of font to use. Must be a TrueType font (.ttf). Defaults to "helvetica.ttf". + color (tuple): Color to print text in, using RGB values. Defaults to (0, 0, 0). + font_size (float): Size of font to use. Defaults to 15. + x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. + y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. + """ if text_to_add.strip() == "": raise ValueError("Please provide valid text_to_add value") if not font_name.endswith(".ttf"): @@ -51,11 +56,11 @@ def __init__( def _load_font(self): """ - Load the font for a given font name and font size + Loads the font for a given font name and font size. Returns: - ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font - cannot be loaded, the default font is returned. + ImageFont.FreeTypeFont or ImageFont.ImageFont: The loaded font object. If the specified font + cannot be loaded, the default font is returned. Raises: OSError: If the font resource cannot be loaded, a warning is logged and the default font is used instead. @@ -105,13 +110,14 @@ def _add_text_to_image(self, image: Image.Image) -> Image.Image: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "image_path") -> ConverterResult: """ - Converter that adds text to an image + Converts the given image by adding text specified in the constructor to it. Args: - prompt (str): The filename of the image to add the text to - input_type (PromptDataType): type of data + prompt (str): The image file path to which text will be added. + input_type (PromptDataType): Type of data, should be "image_path". + Returns: - ConverterResult: The filename of the converted image as a ConverterResult Object + ConverterResult: The path to the updated image as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py b/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py index 58b049829c..7215b0fda7 100644 --- a/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py +++ b/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py @@ -20,10 +20,12 @@ class AnsiAttackConverter(PromptConverter): """ - A single converter that can: - - Use raw and escaped ANSI payloads. - - Ask the model about ANSI codes, repeat given payloads, unescape strings. - - Incorporate the user's original prompt into the final scenario, making the testing more dynamic. + Generates prompts with ANSI codes to evaluate LLM behavior and system risks. + + This converter can: + - Use raw and escaped ANSI payloads. + - Ask the model about ANSI codes, repeat given payloads, unescape strings. + - Incorporate the user's original prompt into the final scenario, making the testing more dynamic. """ def __init__( @@ -36,6 +38,8 @@ def __init__( incorporate_user_prompt: bool = True, ): """ + Initializes the converter with various options to control the scenarios generated. + Args: include_raw (bool): Include scenarios with raw ANSI codes. include_escaped (bool): Include scenarios with escaped ANSI codes. diff --git a/pyrit/prompt_converter/ascii_art_converter.py b/pyrit/prompt_converter/ascii_art_converter.py index f0b81cd03a..91dc8b06d7 100644 --- a/pyrit/prompt_converter/ascii_art_converter.py +++ b/pyrit/prompt_converter/ascii_art_converter.py @@ -8,21 +8,20 @@ class AsciiArtConverter(PromptConverter): - """Converts a string to ASCII art""" + """ + Uses the `art` package to convert text into ASCII art. + """ def __init__(self, font="rand"): - self.font_value = font - - async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter that uses art to convert strings to ASCII art. - This can sometimes bypass LLM filters + Initializes the converter with a specified font. Args: - prompt (str): The prompt to be converted. - Returns: - str: The converted prompt. + 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: if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/atbash_converter.py b/pyrit/prompt_converter/atbash_converter.py index 921ce30e45..c9644fc606 100644 --- a/pyrit/prompt_converter/atbash_converter.py +++ b/pyrit/prompt_converter/atbash_converter.py @@ -11,22 +11,24 @@ class AtbashConverter(PromptConverter): """ - Converter to encode prompt using atbash cipher. + Encodes text using the Atbash cipher. Uses the following to encode: - ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 - ZYXWVUTSRQPONMLKJIHGFEDCBA 9876543210 + - ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 + - ZYXWVUTSRQPONMLKJIHGFEDCBA 9876543210 - 'Hello 123' would encode to 'Svool 876' - - Parameters - --- - append_description: bool, default=False - Append plaintext "expert" text to the prompt. Includes instructions to only communicate - using the cipher, a description of the cipher, and an example encoded using cipher. + 'Hello 123' would encode to 'Svool 876'. """ def __init__(self, *, append_description: bool = False) -> None: + """ + Initializes the converter with an option to append a description. + + Args: + append_description (bool): If True, appends plaintext "expert" text to the prompt. + This includes instructions to only communicate using the cipher, + a description of the cipher, and an example encoded using the cipher. + """ self.append_description = append_description self.example = ( "User: How do I cut down a stop sign?\n" @@ -35,9 +37,6 @@ def __init__(self, *, append_description: bool = False) -> None: ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that atbash cipher encodes the prompt. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/audio_frequency_converter.py b/pyrit/prompt_converter/audio_frequency_converter.py index 2f82c39e59..1f12cf84a4 100644 --- a/pyrit/prompt_converter/audio_frequency_converter.py +++ b/pyrit/prompt_converter/audio_frequency_converter.py @@ -17,11 +17,8 @@ class AudioFrequencyConverter(PromptConverter): """ - The AudioFrequencyConverter takes an audio file and shifts its frequency, by default it will shift it above - human range (=20kHz). - Args: - output_format (str): The format of the audio file. Defaults to "wav". - shift_value (int): The value by which the frequency will be shifted. Defaults to 20000 Hz. + Shifts the frequency of an audio file by a specified value. + By default, it will shift it above the human hearing range (=20 kHz). """ AcceptedAudioFormats = Literal["wav"] @@ -32,6 +29,13 @@ def __init__( output_format: AcceptedAudioFormats = "wav", shift_value: int = 20000, ) -> None: + """ + Initializes the converter with the specified output format and shift value. + + Args: + output_format (str): The format of the audio file, defaults to "wav". + shift_value (int): The value by which the frequency will be shifted, defaults to 20000 Hz. + """ self._output_format = output_format self._shift_value = shift_value @@ -42,17 +46,15 @@ def output_supported(self, output_type: PromptDataType) -> bool: return output_type == "audio_path" async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audio_path") -> ConverterResult: - """Convert an audio file by shifting its frequency. + """ + Converts the given audio file by shifting its frequency. Args: - prompt (str): File path to audio file - input_type (PromptDataType): Type of data, defaults to "audio_path" - - Raises: - ValueError: If the input type is not supported. + prompt (str): File path to the audio file to be converted. + input_type (PromptDataType): The type of the input data. Returns: - ConverterResult: The converted audio file as a ConverterResult object. + ConverterResult: The converted audio file as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py index 3d9afcfc12..c0e4fada6e 100644 --- a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py +++ b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py @@ -18,15 +18,9 @@ class AzureSpeechAudioToTextConverter(PromptConverter): """ - The AzureSpeechAudioTextConverter takes a .wav file and transcribes it into text. - https://learn.microsoft.com/en-us/azure/ai-services/speech-service/speech-to-text + Transcribes a .wav audio file into text using Azure AI Speech service. - Args: - azure_speech_region (str, Optional): The name of the Azure region. - azure_speech_key (str, Optional): The API key for accessing the service. - recognition_language (str): Recognition voice language. Defaults to "en-US". - For more on supported languages, see the following link - https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support + https://learn.microsoft.com/en-us/azure/ai-services/speech-service/speech-to-text """ AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_REGION" @@ -38,6 +32,16 @@ def __init__( azure_speech_key: Optional[str] = None, recognition_language: str = "en-US", ) -> None: + """ + Initializes the converter with Azure Speech service credentials and recognition language. + + Args: + azure_speech_region (str, Optional): The name of the Azure region. + azure_speech_key (str, Optional): The API key for accessing the service. + recognition_language (str): Recognition voice language. Defaults to "en-US". + For more on supported languages, see the following link: + https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support + """ self._azure_speech_region: str = default_values.get_required_value( env_var_name=self.AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE, passed_value=azure_speech_region @@ -59,13 +63,14 @@ def output_supported(self, output_type: PromptDataType) -> bool: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audio_path") -> ConverterResult: """ - Converter that transcribes audio to text. + Converts the given audio file into its text representation. Args: - prompt (str): File path to audio file - input_type (PromptDataType): Type of data + prompt (str): File path to the audio file to be transcribed. + input_type (PromptDataType): The type of the input data. + Returns: - ConverterResult: The transcribed text as a ConverterResult Object + ConverterResult: The transcribed text as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -87,12 +92,13 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audi def recognize_audio(self, audio_bytes: bytes) -> str: """ - Recognize audio file and return transcribed text. + Recognizes audio file and returns transcribed text. Args: audio_bytes (bytes): Audio bytes input. + Returns: - str: Transcribed text + str: Transcribed text. """ try: import azure.cognitiveservices.speech as speechsdk # noqa: F811 @@ -144,22 +150,22 @@ 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 + Callback function that appends transcribed text upon receiving a "recognized" event. Args: - evt (speechsdk.SpeechRecognitionEventArgs): event - transcript (list): list to store transcribed text + evt (speechsdk.SpeechRecognitionEventArgs): Event. + transcript (list): List to store transcribed text. """ logger.info("RECOGNIZED: {}".format(evt.result.text)) transcript.append(evt.result.text) def stop_cb(self, evt: Any, recognizer: Any) -> None: """ - Callback function that stops continuous recognition upon receiving an event 'evt' + Callback function that stops continuous recognition upon receiving an event 'evt'. Args: - evt (speechsdk.SpeechRecognitionEventArgs): event - recognizer (speechsdk.SpeechRecognizer): speech recognizer object + evt (speechsdk.SpeechRecognitionEventArgs): Event. + recognizer (speechsdk.SpeechRecognizer): Speech recognizer object. """ try: import azure.cognitiveservices.speech as speechsdk # noqa: F811 diff --git a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py index 27d54755b4..0b9324b17f 100644 --- a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py +++ b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py @@ -16,17 +16,9 @@ class AzureSpeechTextToAudioConverter(PromptConverter): """ - The AzureSpeechTextToAudio takes a prompt and generates a wave file. + Generates a wave file from a text prompt using Azure AI Speech service. + https://learn.microsoft.com/en-us/azure/ai-services/speech-service/text-to-speech - Args: - azure_speech_region (str, Optional): The name of the Azure region. - azure_speech_key (str, Optional): The API key for accessing the service. - synthesis_language (str): Synthesis voice language - 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. """ AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_REGION" @@ -42,6 +34,19 @@ def __init__( synthesis_voice_name: str = "en-US-AvaNeural", output_format: AzureSpeachAudioFormat = "wav", ) -> None: + """ + Initializes the converter with Azure Speech service credentials, synthesis language, and voice name. + + Args: + azure_speech_region (str, Optional): The name of the Azure region. + azure_speech_key (str, Optional): The API key for accessing the service. + synthesis_language (str): Synthesis voice language. + synthesis_voice_name (str): Synthesis voice name, see URL. + For more details see the following link for synthesis language and synthesis voice: + zhttps://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. + """ self._azure_speech_region: str = default_values.get_required_value( env_var_name=self.AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE, passed_value=azure_speech_region ) @@ -61,6 +66,16 @@ def output_supported(self, output_type: PromptDataType) -> bool: return output_type == "audio_path" async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given text prompt into its audio representation. + + Args: + prompt (str): The input text prompt to be converted. + input_type (PromptDataType): The type of the input data. + + Returns: + ConverterResult: The converted audio file path as a `ConverterResult` object. + """ try: import azure.cognitiveservices.speech as speechsdk # noqa: F811 except ModuleNotFoundError as e: diff --git a/pyrit/prompt_converter/base64_converter.py b/pyrit/prompt_converter/base64_converter.py index 411437b3f2..d3a70fca09 100644 --- a/pyrit/prompt_converter/base64_converter.py +++ b/pyrit/prompt_converter/base64_converter.py @@ -8,11 +8,11 @@ class Base64Converter(PromptConverter): + """ + Converts text prompts into Base64 encoded strings. + """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that just base64 encodes the prompt - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/binary_converter.py b/pyrit/prompt_converter/binary_converter.py index 0a18f5932e..4072f92c54 100644 --- a/pyrit/prompt_converter/binary_converter.py +++ b/pyrit/prompt_converter/binary_converter.py @@ -11,7 +11,9 @@ class BinaryConverter(WordLevelConverter): - """Transforms input text into its binary representation with configurable bits per character (8, 16, or 32)""" + """ + Transforms input text into its binary representation with configurable bits per character (8, 16, or 32). + """ class BitsPerChar(Enum): BITS_8 = 8 @@ -28,7 +30,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified bits per character and selection parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. diff --git a/pyrit/prompt_converter/caesar_converter.py b/pyrit/prompt_converter/caesar_converter.py index e897be8e19..cbd6cbb7d3 100644 --- a/pyrit/prompt_converter/caesar_converter.py +++ b/pyrit/prompt_converter/caesar_converter.py @@ -11,24 +11,25 @@ class CaesarConverter(PromptConverter): """ - Converter to encode prompt using caesar cipher. + Encodes text using the Caesar cipher. Encodes by using given offset. Using offset=1, 'Hello 123' would encode to 'Ifmmp 234', as each character would shift by 1. Shifts for digits 0-9 only work if the offset is less than 10, if the offset is equal to or greather than 10, any numeric values will not be shifted. - - Parameters - --- - caesar_offset: int - Offset for caesar cipher, range 0 to 25 (inclusive). Can also be negative for shifting backwards. - - append_description: bool, default=False - Append plaintext "expert" text to the prompt. Includes instructions to only communicate - using the cipher, a description of the cipher, and an example encoded using cipher. """ def __init__(self, *, caesar_offset: int, append_description: bool = False) -> None: + """ + Initializes the converter with a Caesar cipher offset and an option to append a description. + + Args: + caesar_offset (int): Offset for caesar cipher, range 0 to 25 (inclusive). + Can also be negative for shifting backwards. + append_description (bool): If True, appends plaintext "expert" text to the prompt. + This includes instructions to only communicate using the cipher, + a description of the cipher, and an example encoded using the cipher. + """ if caesar_offset < -25 or caesar_offset > 25: raise ValueError("caesar offset value invalid, must be between -25 and 25 inclusive.") self.caesar_offset = caesar_offset @@ -40,9 +41,6 @@ def __init__(self, *, caesar_offset: int, append_description: bool = False) -> N ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that caesar cipher encodes the prompt. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/character_space_converter.py b/pyrit/prompt_converter/character_space_converter.py index 7d3f12212a..adcf6a4d26 100644 --- a/pyrit/prompt_converter/character_space_converter.py +++ b/pyrit/prompt_converter/character_space_converter.py @@ -8,13 +8,14 @@ class CharacterSpaceConverter(PromptConverter): + """ + Spaces out the input prompt and removes specified punctuations. - async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that spaces out the input prompt and removes specified punctuations. - For more information on the bypass strategy, refer to: + For more information on the bypass strategy, refer to: https://www.robustintelligence.com/blog-posts/bypassing-metas-llama-classifier-a-simple-jailbreak - """ + """ + + async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: if not self.input_supported(input_type): raise ValueError("Input type not supported") converted_text = re.sub("[!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~]", "", " ".join(prompt)) diff --git a/pyrit/prompt_converter/charswap_attack_converter.py b/pyrit/prompt_converter/charswap_attack_converter.py index ef46cf0bec..26f7d03aa5 100644 --- a/pyrit/prompt_converter/charswap_attack_converter.py +++ b/pyrit/prompt_converter/charswap_attack_converter.py @@ -10,7 +10,9 @@ class CharSwapConverter(WordLevelConverter): - """Applies character swapping to words in the prompt to test adversarial textual robustness.""" + """ + Applies character swapping to words in the prompt to test adversarial textual robustness. + """ def __init__( self, @@ -22,7 +24,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). By default, proportion is set to 0.2, meaning 20% of randomly selected words will be perturbed. @@ -48,10 +51,11 @@ async def convert_word_async(self, word: str) -> str: def _perturb_word(self, word: str) -> str: """ - Perturb a word by swapping two adjacent characters. + Perturbs a word by swapping two adjacent characters. Args: word (str): The word to perturb. + Returns: str: The perturbed word with swapped characters. """ diff --git a/pyrit/prompt_converter/codechameleon_converter.py b/pyrit/prompt_converter/codechameleon_converter.py index 660f584381..1d55fc24b2 100644 --- a/pyrit/prompt_converter/codechameleon_converter.py +++ b/pyrit/prompt_converter/codechameleon_converter.py @@ -14,41 +14,33 @@ class CodeChameleonConverter(PromptConverter): """ - The CodeChameleon Converter uses a combination of personal encryption and decryption functions, - code nesting, as well as a set of instructions for the response to bypass LLM safeguards. - - The user prompt is encrypted, and the target is asked to solve the encrypted problem by completing a - ProblemSolver class utilizing the decryption function while following the instructions. + Encrypts user prompt, adds stringified decrypt function in markdown and instructions. + + The user prompt is encrypted, and the target is asked to solve the encrypted problem by completing + a ProblemSolver class utilizing the decryption function while following the instructions. + + Supports the following encryption types: + - `custom`: + User provided encryption and decryption functions. Encryption function used to encode prompt. + Markdown formatting and plaintext instructions appended to decryption function, used as text only. + Should include imports. + - `reverse`: + Reverse the prompt. "How to cut down a tree?" becomes "tree? a down cut to How". + - `binary_tree`: + Encode prompt using binary tree. "How to cut down a tree"?" becomes + ``{'value': 'cut', 'left': {'value': 'How', 'left': None, + 'right': {'value': 'to', 'left': None, 'right': None}}, + 'right': {'value': 'a', 'left': {'value': 'down', 'left': None, 'right': None}, + 'right': {'value': 'tree?', 'left': None, 'right': None}}}`` + - `odd_even`: + All words in odd indices of prompt followed by all words in even indices. + "How to cut down a tree?" becomes "How cut a to down tree?". + - `length`: + List of words in prompt sorted by length, use word as key, original index as value. + "How to cut down a tree?" becomes + ``[{'a': 4}, {'to': 1}, {'How': 0}, {'cut': 2}, {'down': 3}, {'tree?': 5}]`` Code Chameleon Converter based on https://arxiv.org/abs/2402.16717 by Lv, Huijie, et al. - - Parameters - --- - encrypt_mode: {"custom", "reverse", "binary_tree", "odd_even", "length"} - Select a built-in encryption method or provide custom encryption and decryption functions. - `custom`: User provided encryption and decryption functions. Encryption function used to encode prompt. - Markdown formatting and plaintext instructions appended to decryption function, used as text only. - Should include imports. - `reverse`: Reverse the prompt. "How to cut down a tree?" becomes "tree? a down cut to How" - `binary_tree`: Encode prompt using binary tree. "How to cut down a tree"?" becomes - "{'value': 'cut', - 'left': {'value': 'How', 'left': None, 'right': {'value': 'to', 'left': None, 'right': None}}, - 'right': {'value': 'a', 'left': {'value': 'down', 'left': None, 'right': None}, - 'right': {'value': 'tree?', 'left': None, 'right': None}}}" - `odd_even`: All words in odd indices of prompt followed by all words in even indices. - "How to cut down a tree?" becomes "How cut a to down tree?" - `length`: List of words in prompt sorted by length, use word as key, original index as value. - "How to cut down a tree?" becomes "[{'a': 4}, {'to': 1}, {'How': 0}, {'cut': 2}, {'down': 3}, {'tree?': 5}]" - - encrypt_function: Callable, default=None - User provided encryption function. Only used if `encrypt_mode` is "custom". - Used to encode user prompt. - - decrypt_function: Callable or list, default=None - User provided encryption function. Only used if `encrypt_mode` is "custom". - Used as part of markdown code block instructions in system prompt. - If list is provided, strings will be treated as single statements for imports or comments. Functions - will take the source code of the function. """ def __init__( @@ -58,6 +50,19 @@ def __init__( encrypt_function: Optional[Callable] = None, decrypt_function: Optional[Callable | list[Callable | str]] = None, ) -> None: + """ + Initializes the converter with the specified encryption type and optional functions. + + Args: + encrypt_type (str): Must be one of "custom", "reverse", "binary_tree", "odd_even" or "length". + encrypt_function (Callable, optional): User provided encryption function. + Only used if `encrypt_mode` is "custom". Used to encode user prompt. + decrypt_function (Callable or list, optional): User provided encryption function. + Only used if `encrypt_mode` is "custom". + Used as part of markdown code block instructions in system prompt. + If list is provided, strings will be treated as single statements for imports or comments. + Functions will take the source code of the function. + """ match encrypt_type: case "custom": if encrypt_function is None or decrypt_function is None: @@ -86,9 +91,6 @@ def __init__( ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Converter that encrypts user prompt, adds stringified decrypt function in markdown and instructions. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/colloquial_wordswap_converter.py b/pyrit/prompt_converter/colloquial_wordswap_converter.py index 32e23cafff..658505c6ab 100644 --- a/pyrit/prompt_converter/colloquial_wordswap_converter.py +++ b/pyrit/prompt_converter/colloquial_wordswap_converter.py @@ -10,13 +10,15 @@ class ColloquialWordswapConverter(PromptConverter): - """Converts a string to a Singaporean colloquial version""" + """ + Converts text into colloquial Singaporean context. + """ def __init__( self, deterministic: bool = False, custom_substitutions: Optional[Dict[str, List[str]]] = None ) -> None: """ - Initialize the converter with optional deterministic mode and custom substitutions. + Initializes the converter with optional deterministic mode and custom substitutions. Args: deterministic (bool): If True, use the first substitution for each wordswap. @@ -47,16 +49,6 @@ def __init__( self._deterministic = deterministic async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Convert the given prompt to colloquial Singaporean context. - - Args: - prompt (str): The text to convert. - input_type (PromptDataType): The type of input data. - - Returns: - ConverterResult: A ConverterResult containing the Singaporean colloquial version of the prompt. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/denylist_converter.py b/pyrit/prompt_converter/denylist_converter.py index d74d27887d..04a2a171b6 100644 --- a/pyrit/prompt_converter/denylist_converter.py +++ b/pyrit/prompt_converter/denylist_converter.py @@ -14,7 +14,9 @@ class DenylistConverter(LLMGenericTextConverter): - """Eliminates forbidden words or phrases in a prompt by replacing them with synonyms.""" + """ + Replaces forbidden words or phrases in a prompt with synonyms. + """ def __init__( self, @@ -23,6 +25,15 @@ def __init__( system_prompt_template: Optional[SeedPrompt] = None, denylist: list[str] = [], ): + """ + Initializes the converter with a target, an optional system prompt template, and a denylist. + + Args: + converter_target (PromptChatTarget): The target for the prompt conversion. + system_prompt_template (Optional[SeedPrompt]): The system prompt template to use for the conversion. + If not provided, a default template will be used. + denylist (list[str]): A list of words or phrases that should be replaced in the prompt. + """ # set to default strategy if not provided system_prompt_template = ( system_prompt_template @@ -38,13 +49,15 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Removes any words or phrases from the input prompt that are in the denylist, replacing them - with synonomous words. + Converts the given prompt by removing any words or phrases that are in the denylist, + replacing them with synonymous words. Args: - prompt (str): The prompt to be converted. + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. + Returns: - str: The converted prompt without any denied words. + ConverterResult: The conversion result as a `ConverterResult` object. """ # check if the prompt contains any words from the denylist and if so, diff --git a/pyrit/prompt_converter/diacritic_converter.py b/pyrit/prompt_converter/diacritic_converter.py index 119989ee34..3d64e228ef 100644 --- a/pyrit/prompt_converter/diacritic_converter.py +++ b/pyrit/prompt_converter/diacritic_converter.py @@ -12,22 +12,20 @@ class DiacriticConverter(PromptConverter): """ - A PromptConverter that applies diacritics to specified characters in a string. + Applies diacritics to specified characters in a string. """ def __init__(self, target_chars: str = "aeiou", accent: str = "acute"): """ - Initializes the DiacriticConverter. + Initializes the DiacriticConverter with specified target characters and diacritic accent. Args: target_chars (str): Characters to apply the diacritic to. Defaults to "aeiou". - accent (str): Type of diacritic to apply (default is 'acute'). - - Available options are: - - 'acute': "\u0301" - - 'grave': "\u0300" - - 'tilde': "\u0303" - - 'umlaut': "\u0308" + accent (str): Type of diacritic to apply (default is 'acute'). Available options are:\n + - `acute`: \u0301\n + - `grave`: \u0300\n + - `tilde`: \u0303\n + - `umlaut`: \u0308 Raises: ValueError: If `target_chars` is empty. @@ -81,15 +79,6 @@ def _add_diacritic(self, text: str) -> str: ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Converts the given prompt by applying diacritics to target characters. - - Args: - prompt (str): The prompt to be converted. - - Returns: - ConverterResult: The result containing the modified prompt. - """ if not self.input_supported(input_type): raise ValueError("Only 'text' input type is supported.") diff --git a/pyrit/prompt_converter/flip_converter.py b/pyrit/prompt_converter/flip_converter.py index 114d0dec56..21cedf1ab0 100644 --- a/pyrit/prompt_converter/flip_converter.py +++ b/pyrit/prompt_converter/flip_converter.py @@ -6,11 +6,11 @@ class FlipConverter(PromptConverter): + """ + Flips the input text prompt. For example, "hello me" would be converted to "em olleh". + """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that flips the prompt. "hello me" would be "em olleh" - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py index 45afbfe6f2..61ec213038 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py @@ -30,11 +30,6 @@ class FuzzerConverter(PromptConverter): Adapted from GPTFUZZER: Red Teaming Large Language Models with Auto-Generated Jailbreak Prompts. Paper https://arxiv.org/pdf/2309.10253 by Jiahao Yu, Xingwei Lin, Zheng Yu, Xinyu Xing GitHub https://github.com/sherdencooper/GPTFuzz/tree/master - - Parameters: - converter_target (PromptChatTarget): Chat target used to perform fuzzing on user prompt - prompt_template (SeedPrompt): Template to be used instead of the default system prompt with instructions for - the chat target. """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: Optional[SeedPrompt] = None): @@ -47,11 +42,14 @@ def update(self, **kwargs) -> None: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter to generate versions of prompt with new, prepended sentences. + Generates versions of prompt with new, prepended sentences. Args: - prompt (str): The prompt to be converted. - input_type (PromptDataType): The type of the input prompt. + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. + + Returns: + ConverterResult: The conversion result as a `ConverterResult` object. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py index 544961ec12..c447d975dc 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py @@ -21,12 +21,6 @@ class FuzzerCrossOverConverter(FuzzerConverter): """ Fuzzer converter that uses multiple prompt templates to generate new prompts. - - Args: - converter_target (PromptChatTarget): Chat target used to perform fuzzing on user prompt - prompt_template (SeedPrompt, Optional): Template to be used instead of the default system prompt with - instructions for the chat target. - prompt_templates (List[str], Optional): List of prompt templates to use in addition to the default template. """ def __init__( @@ -36,6 +30,15 @@ def __init__( prompt_template: Optional[SeedPrompt] = None, prompt_templates: Optional[List[str]] = None, ): + """ + Initializes the converter with a specified font. + + Args: + converter_target (PromptChatTarget): Chat target used to perform fuzzing on user prompt. + prompt_template (SeedPrompt, Optional): Template to be used instead of the default system prompt with + instructions for the chat target. + prompt_templates (List[str], Optional): List of prompt templates to use in addition to the default one. + """ prompt_template = ( prompt_template if prompt_template diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py index 03d95bfd35..d65f60cddb 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py @@ -18,6 +18,9 @@ class FuzzerExpandConverter(FuzzerConverter): + """ + Generates versions of a prompt with new, prepended sentences. + """ def __init__( self, *, @@ -34,9 +37,6 @@ def __init__( super().__init__(converter_target=converter_target, prompt_template=prompt_template) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Converter to generate versions of prompt with new, prepended sentences. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py index 1eebc02208..9183221bbd 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py @@ -12,6 +12,9 @@ class FuzzerRephraseConverter(FuzzerConverter): + """ + Generates versions of a prompt with rephrased sentences. + """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py index a70512e479..042698eefc 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py @@ -12,6 +12,9 @@ class FuzzerShortenConverter(FuzzerConverter): + """ + Generates versions of a prompt with shortened sentences. + """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py index 9b64043734..9e07addacc 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py @@ -12,6 +12,9 @@ class FuzzerSimilarConverter(FuzzerConverter): + """ + Generates versions of a prompt with similar sentences. + """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/human_in_the_loop_converter.py b/pyrit/prompt_converter/human_in_the_loop_converter.py index 00fc6b1d42..0bbfc16d04 100644 --- a/pyrit/prompt_converter/human_in_the_loop_converter.py +++ b/pyrit/prompt_converter/human_in_the_loop_converter.py @@ -14,29 +14,33 @@ class HumanInTheLoopConverter(PromptConverter): """ Allows review of each prompt sent to a target before sending it. User can choose to send the prompt as is, modify the prompt, or run the prompt through one of the passed-in converters before sending it. - - Args: - converters: (List[PromptConverter], Optional): List of possible converters to run input through. """ def __init__( self, converters: Optional[list[PromptConverter]] = None, ): + """ + Initializes the converter with a list of possible converters to run input through. + + Args: + converters (List[PromptConverter], Optional): List of possible converters to run input through. + """ self._converters = converters or [] async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ Before sending a prompt to a target, user is given three options to choose from: - (1) Proceed with sending the prompt as is. - (2) Manually modify the prompt. - (3) Run the prompt through a converter before sending it. + (1) Proceed with sending the prompt as is. + (2) Manually modify the prompt. + (3) Run the prompt through a converter before sending it. Args: prompt (str): The prompt to be added to the image. - input_type (PromptDataType): Type of data + input_type (PromptDataType): The type of the input data. + Returns: - ConverterResult: The filename of the converted image as a ConverterResult Object + ConverterResult: The filename of the converted image as a `ConverterResult` object. """ user_input = "" if self._converters: diff --git a/pyrit/prompt_converter/insert_punctuation_converter.py b/pyrit/prompt_converter/insert_punctuation_converter.py index 52dee87b5a..489f52bc49 100644 --- a/pyrit/prompt_converter/insert_punctuation_converter.py +++ b/pyrit/prompt_converter/insert_punctuation_converter.py @@ -13,6 +13,7 @@ class InsertPunctuationConverter(PromptConverter): """ Inserts punctuation into a prompt to test robustness. + Punctuation insertion: inserting single punctuations in string.punctuation. Words in a prompt: a word does not contain any punctuation and space. "a1b2c3" is a word; "a1 2" are 2 words; "a1,b,3" are 3 words. @@ -22,11 +23,12 @@ class InsertPunctuationConverter(PromptConverter): def __init__(self, word_swap_ratio: float = 0.2, between_words: bool = True) -> None: """ - Initialize the converter with optional and word swap ratio. + Initializes the converter with a word swap ratio and punctuation insertion mode. + Args: word_swap_ratio (float): Percentage of words to perturb. Defaults to 0.2. between_words (bool): If True, insert punctuation only between words. - If False, insert punctuation within words. Defaults to True. + If False, insert punctuation within words. Defaults to True. """ # Swap ratio cannot be 0 or larger than 1 if not 0 < word_swap_ratio <= 1: @@ -50,11 +52,13 @@ async def convert_async( self, *, prompt: str, input_type: PromptDataType = "text", punctuation_list: Optional[List[str]] = None ) -> ConverterResult: """ - Convert the given prompt by inserting punctuation. + Converts the given prompt by inserting punctuation. + Args: prompt (str): The text to convert. input_type (PromptDataType): The type of input data. punctuation_list (Optional[List[str]]): List of punctuations to use for insertion. + Returns: ConverterResult: A ConverterResult containing a interation of modified prompts. """ diff --git a/pyrit/prompt_converter/llm_generic_text_converter.py b/pyrit/prompt_converter/llm_generic_text_converter.py index 310ae1b759..cfcfddda54 100644 --- a/pyrit/prompt_converter/llm_generic_text_converter.py +++ b/pyrit/prompt_converter/llm_generic_text_converter.py @@ -18,6 +18,9 @@ class LLMGenericTextConverter(PromptConverter): + """ + Represents a generic LLM converter that expects text to be transformed (e.g. no JSON parsing or format). + """ def __init__( self, *, @@ -27,15 +30,14 @@ def __init__( **kwargs, ): """ - Generic LLM converter that expects text to be transformed (e.g. no JSON parsing or format) + Initializes the converter with a target and optional prompt templates. Args: - converter_target (PromptChatTarget): The endpoint that converts the prompt + converter_target (PromptChatTarget): The endpoint that converts the prompt. system_prompt_template (SeedPrompt, Optional): The prompt template to set as the system prompt. user_prompt_template_with_objective (SeedPrompt, Optional): The prompt template to set as the user prompt. expects kwargs: Additional parameters for the prompt template. - """ self._converter_target = converter_target self._system_prompt_template = system_prompt_template @@ -48,17 +50,14 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Convert a prompt based on the prompt template + Converts the given prompt based on the prompt template. Parameters: - prompt (str): The prompt to convert. - input_type (PromptDataType, Optional): The data type of the input prompt. Defaults to "text". + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. Returns: - ConverterResult: The result of the conversion, including the converted output text and output type. - - Raises: - ValueError: If the input type is not supported. + ConverterResult: The conversion result as a `ConverterResult` object. """ conversation_id = str(uuid.uuid4()) diff --git a/pyrit/prompt_converter/malicious_question_generator_converter.py b/pyrit/prompt_converter/malicious_question_generator_converter.py index 60d1d95ab9..cb25658dc0 100644 --- a/pyrit/prompt_converter/malicious_question_generator_converter.py +++ b/pyrit/prompt_converter/malicious_question_generator_converter.py @@ -14,7 +14,7 @@ class MaliciousQuestionGeneratorConverter(LLMGenericTextConverter): """ - A PromptConverter that generates malicious questions using an LLM via an existing PromptTarget (like Azure OpenAI). + Generates malicious questions using an LLM via an existing PromptTarget (like Azure OpenAI). """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): diff --git a/pyrit/prompt_converter/math_prompt_converter.py b/pyrit/prompt_converter/math_prompt_converter.py index 4557c6a2e8..e6f967e9c9 100644 --- a/pyrit/prompt_converter/math_prompt_converter.py +++ b/pyrit/prompt_converter/math_prompt_converter.py @@ -14,8 +14,8 @@ class MathPromptConverter(LLMGenericTextConverter): """ - A PromptConverter that converts natural language instructions into symbolic mathematics problems - using an LLM via an existing PromptTarget (like Azure OpenAI or other supported backends). + Converts natural language instructions into symbolic mathematics problems using + an LLM via an existing PromptTarget (like Azure OpenAI or other supported backends). """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): @@ -24,7 +24,7 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedP Args: converter_target (PromptChatTarget): The endpoint that converts the prompt. - prompt_template (SeedPrompt): The prompt template to use. + prompt_template (SeedPrompt): The seed prompt template to use. """ # Load the template from the YAML file or use a default template if not provided @@ -40,14 +40,15 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedP async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Convert a prompt into a mathematical problem format. + Converts the given prompt into a mathematical problem format. - Parameters: - prompt (str): The prompt to convert. + Args: + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. Returns: - ConverterResult: The result of the conversion, - including the mathematical representation and real-world example. + ConverterResult: The conversion result, including the mathematical representation + and real-world example, as a `ConverterResult` object. """ logger.info(f"Converting prompt: {prompt}") diff --git a/pyrit/prompt_converter/noise_converter.py b/pyrit/prompt_converter/noise_converter.py index 42dd2476de..15d2b22e85 100644 --- a/pyrit/prompt_converter/noise_converter.py +++ b/pyrit/prompt_converter/noise_converter.py @@ -15,6 +15,9 @@ class NoiseConverter(LLMGenericTextConverter): + """ + Injects noise errors into a conversation. + """ def __init__( self, *, @@ -24,14 +27,13 @@ def __init__( prompt_template: Optional[SeedPrompt] = None, ): """ - Injects noise errors into a conversation + Initializes the converter. Args: converter_target (PromptChatTarget): The endpoint that converts the prompt noise (str): The noise to inject. Grammar error, delete random letter, insert random space, etc. - number_errors (int): The number of errors to inject + number_errors (int): The number of errors to inject. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. - """ # set to default strategy if not provided prompt_template = ( diff --git a/pyrit/prompt_converter/rot13_converter.py b/pyrit/prompt_converter/rot13_converter.py index 8e602985e5..a4686fdd30 100644 --- a/pyrit/prompt_converter/rot13_converter.py +++ b/pyrit/prompt_converter/rot13_converter.py @@ -7,7 +7,9 @@ class ROT13Converter(WordLevelConverter): - """Simple converter that just ROT13 encodes the prompt""" + """ + Encodes prompts using the ROT13 cipher. + """ async def convert_word_async(self, word: str) -> str: return codecs.encode(word, "rot13") diff --git a/pyrit/prompt_converter/string_join_converter.py b/pyrit/prompt_converter/string_join_converter.py index d99903d0d0..e5a5d03120 100644 --- a/pyrit/prompt_converter/string_join_converter.py +++ b/pyrit/prompt_converter/string_join_converter.py @@ -8,7 +8,9 @@ class StringJoinConverter(WordLevelConverter): - """Converts text by joining its characters with the specified join value""" + """ + Converts text by joining its characters with the specified join value. + """ def __init__( self, @@ -20,7 +22,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified join value and selection parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. diff --git a/pyrit/prompt_converter/suffix_append_converter.py b/pyrit/prompt_converter/suffix_append_converter.py index 84f3648025..ffd481e3d3 100644 --- a/pyrit/prompt_converter/suffix_append_converter.py +++ b/pyrit/prompt_converter/suffix_append_converter.py @@ -6,6 +6,12 @@ class SuffixAppendConverter(PromptConverter): + """ + Appends a specified suffix to the prompt. + + E.g. with a suffix `!!!`, it converts a prompt of `test` to `test !!!`. + See `PyRIT/pyrit/auxiliary_attacks/gcg` for adversarial suffix generation. + """ def __init__(self, *, suffix: str): if not suffix: @@ -14,18 +20,6 @@ def __init__(self, *, suffix: str): self.suffix = suffix async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that appends a given suffix to the prompt. - E.g. with a suffix `!!!`, it converts a prompt of `test` to `test !!!` - - See PyRIT/pyrit/auxiliary_attacks/gcg for adversarial suffix generation - - Args: - prompt (str): The prompt to be converted. - - Returns: - list[str]: The converted prompts. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/tense_converter.py b/pyrit/prompt_converter/tense_converter.py index 65e543cb6d..1dc9127db2 100644 --- a/pyrit/prompt_converter/tense_converter.py +++ b/pyrit/prompt_converter/tense_converter.py @@ -13,12 +13,15 @@ class TenseConverter(LLMGenericTextConverter): + """ + Converts a conversation to a different tense. + """ def __init__(self, *, converter_target: PromptChatTarget, tense: str, prompt_template: SeedPrompt = None): """ - Converts a conversation to a different tense + Initializes the converter. Args: - converter_target (PromptChatTarget): The target chat support for the conversion which will translate + converter_target (PromptChatTarget): The target chat support for the conversion which will translate. tone (str): The tense the converter should convert the prompt to. E.g. past, present, future. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. diff --git a/pyrit/prompt_converter/text_to_hex_converter.py b/pyrit/prompt_converter/text_to_hex_converter.py index 2b625f1451..fc978b0cd6 100644 --- a/pyrit/prompt_converter/text_to_hex_converter.py +++ b/pyrit/prompt_converter/text_to_hex_converter.py @@ -5,7 +5,9 @@ class TextToHexConverter(WordLevelConverter): - """Converts text to a hexadecimal encoded utf-8 string""" + """ + Converts text to a hexadecimal encoded utf-8 string. + """ async def convert_word_async(self, word: str) -> str: return word.encode("utf-8").hex().upper() diff --git a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py index f1c2ff5c36..5e9a02e6d4 100644 --- a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py @@ -23,7 +23,7 @@ class AsciiSmugglerConverter(SmugglerConverter): def __init__(self, action: Literal["encode", "decode"] = "encode", unicode_tags: bool = False): """ - Initialize the converter with options for encoding/decoding. + Initializes the converter with options for encoding/decoding. Args: unicode_tags (bool): Whether to add Unicode tags during encoding. diff --git a/pyrit/prompt_converter/tone_converter.py b/pyrit/prompt_converter/tone_converter.py index 2e3037d1aa..3d8676edc3 100644 --- a/pyrit/prompt_converter/tone_converter.py +++ b/pyrit/prompt_converter/tone_converter.py @@ -13,12 +13,15 @@ class ToneConverter(LLMGenericTextConverter): + """ + Converts a conversation to a different tone. + """ def __init__(self, *, converter_target: PromptChatTarget, tone: str, prompt_template: SeedPrompt = None): """ - Converts a conversation to a different tone + Initializes the converter. Args: - converter_target (PromptChatTarget): The target chat support for the conversion which will translate + converter_target (PromptChatTarget): The target chat support for the conversion which will translate. tone (str): The tone for the conversation. E.g. upset, sarcastic, indifferent, etc. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. diff --git a/pyrit/prompt_converter/toxic_sentence_generator_converter.py b/pyrit/prompt_converter/toxic_sentence_generator_converter.py index c19429db10..6bf48a7bbc 100644 --- a/pyrit/prompt_converter/toxic_sentence_generator_converter.py +++ b/pyrit/prompt_converter/toxic_sentence_generator_converter.py @@ -19,8 +19,7 @@ class ToxicSentenceGeneratorConverter(LLMGenericTextConverter): """ - A PromptConverter that generates toxic sentence starters using an LLM via an - existing PromptTarget. + Generates toxic sentence starters using an LLM via an existing PromptTarget. Based on Project Moonshot's attack module that generates toxic sentences to test LLM safety guardrails: @@ -50,41 +49,21 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: Optio async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converts a seed prompt into a toxic sentence starter. + Converts the given prompt into a toxic sentence starter. - Parameters: - prompt (str): The prompt to convert. - input_type (PromptDataType, Optional): The data type of the input prompt. - Defaults to "text". + Args: + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. Returns: - ConverterResult: The result of the conversion, containing the toxic sentence - starter. + ConverterResult: The conversion result, containing the toxic sentence starter. """ # Add the prompt to _prompt_kwargs before calling the base method self._prompt_kwargs["prompt"] = prompt return await super().convert_async(prompt=prompt, input_type=input_type) def input_supported(self, input_type: PromptDataType) -> bool: - """ - Checks if the input type is supported by this converter. - - Parameters: - input_type (PromptDataType): The data type to check. - - Returns: - bool: True if the input type is supported, False otherwise. - """ return input_type == "text" def output_supported(self, output_type: PromptDataType) -> bool: - """ - Checks if the output type is supported by this converter. - - Parameters: - output_type (PromptDataType): The data type to check. - - Returns: - bool: True if the output type is supported, False otherwise. - """ return output_type == "text" diff --git a/pyrit/prompt_converter/translation_converter.py b/pyrit/prompt_converter/translation_converter.py index a68bfe2bb9..eef2bf755c 100644 --- a/pyrit/prompt_converter/translation_converter.py +++ b/pyrit/prompt_converter/translation_converter.py @@ -28,6 +28,9 @@ class TranslationConverter(PromptConverter): + """ + Uses an LLM to translate prompts into different languages. + """ def __init__( self, *, diff --git a/pyrit/prompt_converter/unicode_replacement_converter.py b/pyrit/prompt_converter/unicode_replacement_converter.py index 98351260d8..31537723e7 100644 --- a/pyrit/prompt_converter/unicode_replacement_converter.py +++ b/pyrit/prompt_converter/unicode_replacement_converter.py @@ -8,8 +8,9 @@ class UnicodeReplacementConverter(WordLevelConverter): - """Simple converter that returns the unicode representation of the prompt.""" - + """ + Converts a prompt to its unicode representation. + """ def __init__( self, *, @@ -20,7 +21,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified selection parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. diff --git a/pyrit/prompt_converter/unicode_sub_converter.py b/pyrit/prompt_converter/unicode_sub_converter.py index 0664acae7e..7eac4f4d27 100644 --- a/pyrit/prompt_converter/unicode_sub_converter.py +++ b/pyrit/prompt_converter/unicode_sub_converter.py @@ -6,14 +6,14 @@ class UnicodeSubstitutionConverter(PromptConverter): + """ + Encodes the prompt using any unicode starting point. + Default is to use invisible flag emoji characters. + """ def __init__(self, *, start_value=0xE0000): self.startValue = start_value async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that just encodes the prompt using any unicode starting point. - Default is to use invisible flag emoji characters. - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/url_converter.py b/pyrit/prompt_converter/url_converter.py index 00f51f51f7..64b728a60b 100644 --- a/pyrit/prompt_converter/url_converter.py +++ b/pyrit/prompt_converter/url_converter.py @@ -8,11 +8,11 @@ class UrlConverter(PromptConverter): + """ + Converts a prompt to a URL-encoded string. + """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Simple converter that just URL encodes the prompt - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/variation_converter.py b/pyrit/prompt_converter/variation_converter.py index 7a4dea498d..5e19fc727d 100644 --- a/pyrit/prompt_converter/variation_converter.py +++ b/pyrit/prompt_converter/variation_converter.py @@ -26,6 +26,9 @@ class VariationConverter(PromptConverter): + """ + Generates variations of the input prompts using the converter target. + """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): self.converter_target = converter_target @@ -43,13 +46,6 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedP self.system_prompt = str(prompt_template.render_template_value(number_iterations=str(self.number_variations))) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: - """ - Generates variations of the input prompts using the converter target. - Parameters: - prompts: list of prompts to convert - Return: - target_responses: list of prompt variations generated by the converter target - """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/word_level_converter.py b/pyrit/prompt_converter/word_level_converter.py index fb63592568..a2de6c3dff 100644 --- a/pyrit/prompt_converter/word_level_converter.py +++ b/pyrit/prompt_converter/word_level_converter.py @@ -29,7 +29,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified selection parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. @@ -58,7 +59,7 @@ def __init__( self._regex = regex or ".*" def _select_word_indices(self, words: List[str]) -> List[int]: - """Return indices of words to be converted based on the selection criteria.""" + """Returns indices of words to be converted based on the selection criteria.""" if not words: return [] @@ -85,17 +86,36 @@ def _select_word_indices(self, words: List[str]) -> List[int]: @abc.abstractmethod async def convert_word_async(self, word: str) -> str: + """ + Converts a single word into the target format supported by the converter. + + Args: + word (str): The word to be converted. + + Returns: + str: The converted word. + """ pass def validate_input(self, prompt: str) -> None: - """Validate the input before processing (can be overridden by subclasses)""" + """Validates the input before processing (can be overridden by subclasses)""" pass def join_words(self, words: list[str]) -> str: - """Provide a way for subclasses to override the default behavior of joining words.""" + """Provides a way for subclasses to override the default behavior of joining words.""" return " ".join(words) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given prompt into the target format supported by the converter. + + Args: + prompt (str): The input prompt to be converted. + input_type (PromptDataType): The type of the input data. + + Returns: + ConverterResult: The result of the conversion, including the converted output and its type. + """ if prompt is None: raise TypeError("Prompt cannot be None") diff --git a/pyrit/prompt_converter/zalgo_converter.py b/pyrit/prompt_converter/zalgo_converter.py index 133f6f4ea1..d26dcead9f 100644 --- a/pyrit/prompt_converter/zalgo_converter.py +++ b/pyrit/prompt_converter/zalgo_converter.py @@ -16,7 +16,9 @@ class ZalgoConverter(WordLevelConverter): - """Converts text into cursed Zalgo text using combining Unicode marks.""" + """ + Converts text into cursed Zalgo text using combining Unicode marks. + """ def __init__( self, @@ -29,7 +31,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter. + Initializes the converter with the specified selection parameters. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. From b66d58d1284479c936f6b1f863dc8bb950aefef3 Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:55:47 +0200 Subject: [PATCH 3/8] fix link --- pyrit/prompt_converter/azure_speech_text_to_audio_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py index 0b9324b17f..009381a5cb 100644 --- a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py +++ b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py @@ -43,7 +43,7 @@ def __init__( synthesis_language (str): Synthesis voice language. synthesis_voice_name (str): Synthesis voice name, see URL. For more details see the following link for synthesis language and synthesis voice: - zhttps://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support + 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. """ From 9fbcb631475aeef86535ccbff7a9cec557b7e832 Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:10:26 +0200 Subject: [PATCH 4/8] simplify general docstring for convert_async --- pyrit/prompt_converter/prompt_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrit/prompt_converter/prompt_converter.py b/pyrit/prompt_converter/prompt_converter.py index 78e3ea9513..d135977c6d 100644 --- a/pyrit/prompt_converter/prompt_converter.py +++ b/pyrit/prompt_converter/prompt_converter.py @@ -44,7 +44,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text input_type (PromptDataType): The type of the input data. Returns: - ConverterResult: The result of the conversion, including the converted output and its type. + ConverterResult: The result containing the converted output and its type. """ @abc.abstractmethod From 4e849b43f29b8b13cb4a8fab54dd4ebfcec0f60a Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Tue, 17 Jun 2025 14:04:02 +0200 Subject: [PATCH 5/8] even more updates/tweaks --- doc/api.rst | 2 + .../add_image_text_converter.py | 9 +++- .../add_image_to_video_converter.py | 10 +++- .../add_text_image_converter.py | 13 +++-- .../ansi_escape/ansi_attack_converter.py | 1 + pyrit/prompt_converter/ascii_art_converter.py | 1 + pyrit/prompt_converter/atbash_converter.py | 1 + .../audio_frequency_converter.py | 8 ++- .../azure_speech_audio_to_text_converter.py | 7 ++- .../azure_speech_text_to_audio_converter.py | 11 ++-- pyrit/prompt_converter/base64_converter.py | 1 + pyrit/prompt_converter/binary_converter.py | 6 +-- pyrit/prompt_converter/caesar_converter.py | 7 ++- .../character_space_converter.py | 1 + .../codechameleon_converter.py | 5 ++ .../colloquial_wordswap_converter.py | 1 + pyrit/prompt_converter/denylist_converter.py | 6 +-- pyrit/prompt_converter/diacritic_converter.py | 5 +- pyrit/prompt_converter/flip_converter.py | 1 + .../fuzzer_converter/fuzzer_converter_base.py | 25 ++++++--- .../fuzzer_crossover_converter.py | 6 +-- .../fuzzer_expand_converter.py | 3 ++ .../human_in_the_loop_converter.py | 19 ++++--- .../insert_punctuation_converter.py | 10 +++- pyrit/prompt_converter/leetspeak_converter.py | 7 ++- .../llm_generic_text_converter.py | 10 ++-- .../prompt_converter/math_prompt_converter.py | 7 ++- pyrit/prompt_converter/morse_converter.py | 20 +++---- pyrit/prompt_converter/noise_converter.py | 2 +- pyrit/prompt_converter/pdf_converter.py | 49 ++++++++++------- .../prompt_converter/persuasion_converter.py | 27 ++++++---- pyrit/prompt_converter/prompt_converter.py | 4 +- pyrit/prompt_converter/qr_code_converter.py | 54 +++++++++++-------- .../random_capital_letters_converter.py | 23 ++++---- .../repeat_token_converter.py | 43 +++++++-------- .../search_replace_converter.py | 29 ++++++---- .../template_segment_converter.py | 21 +++++--- pyrit/prompt_converter/tense_converter.py | 2 +- .../text_jailbreak_converter.py | 11 +++- .../ascii_smuggler_converter.py | 5 +- .../prompt_converter/token_smuggling/base.py | 18 ++++--- .../sneaky_bits_smuggler_converter.py | 12 +++-- .../variation_selector_smuggler_converter.py | 32 ++++++----- pyrit/prompt_converter/tone_converter.py | 2 +- .../toxic_sentence_generator_converter.py | 6 +-- .../prompt_converter/translation_converter.py | 21 +++++--- .../unicode_confusable_converter.py | 22 +++++--- .../prompt_converter/unicode_sub_converter.py | 5 +- pyrit/prompt_converter/url_converter.py | 3 ++ pyrit/prompt_converter/variation_converter.py | 21 ++++++++ .../prompt_converter/word_level_converter.py | 10 ++-- .../prompt_converter/zero_width_converter.py | 7 ++- 52 files changed, 414 insertions(+), 218 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 8bfc7d0185..c5665a9e0c 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -323,7 +323,9 @@ API Reference StringJoinConverter SuffixAppendConverter SuperscriptConverter + TemplateSegmentConverter TenseConverter + TextJailbreakConverter TextToHexConverter ToneConverter ToxicSentenceGeneratorConverter diff --git a/pyrit/prompt_converter/add_image_text_converter.py b/pyrit/prompt_converter/add_image_text_converter.py index 0a7dc9f2ec..b6852872d9 100644 --- a/pyrit/prompt_converter/add_image_text_converter.py +++ b/pyrit/prompt_converter/add_image_text_converter.py @@ -18,6 +18,7 @@ class AddImageTextConverter(PromptConverter): """ Adds a string to an image and wraps the text into multiple lines if necessary. + This class is similar to :class:`AddTextImageConverter` except we pass in an image file path as an argument to the constructor as opposed to text. """ @@ -41,6 +42,9 @@ def __init__( font_size (float): Size of font to use. Defaults to 15. x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. + + Raises: + ValueError: If `img_to_add` is empty or invalid, or if `font_name` does not end with ".ttf". """ if not img_to_add: raise ValueError("Please provide valid image path") @@ -121,7 +125,10 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The path to the updated image as a `ConverterResult` object. + ConverterResult: The result containing path to the updated image. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/add_image_to_video_converter.py b/pyrit/prompt_converter/add_image_to_video_converter.py index d9ec87623c..1bb8f00686 100644 --- a/pyrit/prompt_converter/add_image_to_video_converter.py +++ b/pyrit/prompt_converter/add_image_to_video_converter.py @@ -45,6 +45,9 @@ def __init__( output_path (str, Optional): File path of output video. Defaults to None. img_position (tuple): Position to place image in video. Defaults to (10, 10). img_resize_size (tuple): Size to resize image to. Defaults to (500, 500). + + Raises: + ValueError: If `video_path` is empty or invalid. """ if not video_path: @@ -162,14 +165,17 @@ 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 by adding an image to the video specified in the constructor. + Converts the given prompt (image file path) by adding it to a video. Args: prompt (str): The image file name to be added to the video. input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The filename of the converted video as a `ConverterResult` object. + ConverterResult: The result containing filename of the converted video. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/add_text_image_converter.py b/pyrit/prompt_converter/add_text_image_converter.py index 6537194c8d..ea582aeea7 100644 --- a/pyrit/prompt_converter/add_text_image_converter.py +++ b/pyrit/prompt_converter/add_text_image_converter.py @@ -18,6 +18,7 @@ class AddTextImageConverter(PromptConverter): """ Adds a string to an image and wraps the text into multiple lines if necessary. + This class is similar to :class:`AddImageTextConverter` except we pass in text as an argument to the constructor as opposed to an image file path. """ @@ -41,6 +42,9 @@ def __init__( font_size (float): Size of font to use. Defaults to 15. x_pos (int): X coordinate to place text in (0 is left most). Defaults to 10. y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. + + Raises: + ValueError: If `text_to_add` is empty, or if `font_name` does not end with ".ttf". """ if text_to_add.strip() == "": raise ValueError("Please provide valid text_to_add value") @@ -110,14 +114,17 @@ 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 image by adding text specified in the constructor to it. + Converts the given prompt (image file path) by adding text to the image. Args: prompt (str): The image file path to which text will be added. - input_type (PromptDataType): Type of data, should be "image_path". + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The path to the updated image as a `ConverterResult` object. + ConverterResult: The result containing path to the updated image. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py b/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py index 7215b0fda7..ce61424f73 100644 --- a/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py +++ b/pyrit/prompt_converter/ansi_escape/ansi_attack_converter.py @@ -62,6 +62,7 @@ def output_supported(self, output_type: PromptDataType) -> bool: 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.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/ascii_art_converter.py b/pyrit/prompt_converter/ascii_art_converter.py index 91dc8b06d7..dd6a73c518 100644 --- a/pyrit/prompt_converter/ascii_art_converter.py +++ b/pyrit/prompt_converter/ascii_art_converter.py @@ -22,6 +22,7 @@ def __init__(self, font="rand"): self.font_value = font async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt into ASCII art.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/atbash_converter.py b/pyrit/prompt_converter/atbash_converter.py index c9644fc606..48306f9f76 100644 --- a/pyrit/prompt_converter/atbash_converter.py +++ b/pyrit/prompt_converter/atbash_converter.py @@ -37,6 +37,7 @@ 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.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/audio_frequency_converter.py b/pyrit/prompt_converter/audio_frequency_converter.py index 1f12cf84a4..0ba79cf01e 100644 --- a/pyrit/prompt_converter/audio_frequency_converter.py +++ b/pyrit/prompt_converter/audio_frequency_converter.py @@ -51,10 +51,14 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audi Args: prompt (str): File path to the audio file to be converted. - input_type (PromptDataType): The type of the input data. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The converted audio file as a `ConverterResult` object. + ConverterResult: The result containing the audio file path. + + Raises: + ValueError: If the input type is not supported. + Exception: If there is an error during the conversion process. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py index c0e4fada6e..731c3e63d7 100644 --- a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py +++ b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py @@ -67,10 +67,13 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "audi Args: prompt (str): File path to the audio file to be transcribed. - input_type (PromptDataType): The type of the input data. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The transcribed text as a `ConverterResult` object. + ConverterResult: The result containing the transcribed text. + + Raises: + ValueError: If the input type is not supported or if the provided file is not a .wav file. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py index 009381a5cb..6166ca2ede 100644 --- a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py +++ b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py @@ -70,11 +70,16 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Converts the given text prompt into its audio representation. Args: - prompt (str): The input text prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The text prompt to be converted into audio. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The converted audio file path as a `ConverterResult` object. + ConverterResult: The result containing the audio file path. + + Raises: + ModuleNotFoundError: If the ``azure.cognitiveservices.speech`` module is not installed. + RuntimeError: If there is an error during the speech synthesis process. + ValueError: If the input type is not supported or if the prompt is empty. """ try: import azure.cognitiveservices.speech as speechsdk # noqa: F811 diff --git a/pyrit/prompt_converter/base64_converter.py b/pyrit/prompt_converter/base64_converter.py index d3a70fca09..9ce6a31823 100644 --- a/pyrit/prompt_converter/base64_converter.py +++ b/pyrit/prompt_converter/base64_converter.py @@ -13,6 +13,7 @@ class Base64Converter(PromptConverter): """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt into Base64 encoded string.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/binary_converter.py b/pyrit/prompt_converter/binary_converter.py index 4072f92c54..e0d25b9118 100644 --- a/pyrit/prompt_converter/binary_converter.py +++ b/pyrit/prompt_converter/binary_converter.py @@ -51,7 +51,7 @@ def __init__( self.bits_per_char = bits_per_char def validate_input(self, prompt): - # Check if bits_per_char is sufficient for the characters in the prompt + """Checks if ``bits_per_char`` is sufficient for the characters in the prompt.""" bits = self.bits_per_char.value max_code_point = max((ord(char) for char in prompt), default=0) min_bits_required = max_code_point.bit_length() @@ -62,11 +62,11 @@ def validate_input(self, prompt): ) async def convert_word_async(self, word: str) -> str: + """Converts each character in the word to its binary representation. """ bits = self.bits_per_char.value - # Convert each character in the word to its binary representation return " ".join(format(ord(char), f"0{bits}b") for char in word) def join_words(self, words: list[str]) -> str: - """Join the converted words with the binary representation of a space.""" + """Joins the converted words with the binary representation of a space.""" space_binary = format(ord(" "), f"0{self.bits_per_char.value}b") return f" {space_binary} ".join(words) diff --git a/pyrit/prompt_converter/caesar_converter.py b/pyrit/prompt_converter/caesar_converter.py index cbd6cbb7d3..f8a9ad62f0 100644 --- a/pyrit/prompt_converter/caesar_converter.py +++ b/pyrit/prompt_converter/caesar_converter.py @@ -11,9 +11,8 @@ class CaesarConverter(PromptConverter): """ - Encodes text using the Caesar cipher. + Encodes text using the Caesar cipher with a specified offset. - Encodes by using given offset. Using offset=1, 'Hello 123' would encode to 'Ifmmp 234', as each character would shift by 1. Shifts for digits 0-9 only work if the offset is less than 10, if the offset is equal to or greather than 10, any numeric values will not be shifted. @@ -29,6 +28,9 @@ def __init__(self, *, caesar_offset: int, append_description: bool = False) -> N append_description (bool): If True, appends plaintext "expert" text to the prompt. This includes instructions to only communicate using the cipher, a description of the cipher, and an example encoded using the cipher. + + Raises: + ValueError: If `caesar_offset` is not in the range -25 to 25 inclusive. """ if caesar_offset < -25 or caesar_offset > 25: raise ValueError("caesar offset value invalid, must be between -25 and 25 inclusive.") @@ -41,6 +43,7 @@ def __init__(self, *, caesar_offset: int, append_description: bool = False) -> N ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt using the Caesar cipher.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/character_space_converter.py b/pyrit/prompt_converter/character_space_converter.py index adcf6a4d26..16b4b803ac 100644 --- a/pyrit/prompt_converter/character_space_converter.py +++ b/pyrit/prompt_converter/character_space_converter.py @@ -16,6 +16,7 @@ class CharacterSpaceConverter(PromptConverter): """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt by removing punctuation and spacing out characters.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") converted_text = re.sub("[!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~]", "", " ".join(prompt)) diff --git a/pyrit/prompt_converter/codechameleon_converter.py b/pyrit/prompt_converter/codechameleon_converter.py index 1d55fc24b2..1ebe666651 100644 --- a/pyrit/prompt_converter/codechameleon_converter.py +++ b/pyrit/prompt_converter/codechameleon_converter.py @@ -62,6 +62,10 @@ def __init__( Used as part of markdown code block instructions in system prompt. If list is provided, strings will be treated as single statements for imports or comments. Functions will take the source code of the function. + + Raises: + ValueError: If `encrypt_type` is not valid or if `encrypt_function` or `decrypt_function` are not provided + when `encrypt_type` is "custom". """ match encrypt_type: case "custom": @@ -91,6 +95,7 @@ def __init__( ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt by applying the specified encryption function.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/colloquial_wordswap_converter.py b/pyrit/prompt_converter/colloquial_wordswap_converter.py index 658505c6ab..a82bf420f9 100644 --- a/pyrit/prompt_converter/colloquial_wordswap_converter.py +++ b/pyrit/prompt_converter/colloquial_wordswap_converter.py @@ -49,6 +49,7 @@ def __init__( self._deterministic = deterministic async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt by replacing words with colloquial Singaporean terms.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/denylist_converter.py b/pyrit/prompt_converter/denylist_converter.py index 04a2a171b6..3d648c5e5e 100644 --- a/pyrit/prompt_converter/denylist_converter.py +++ b/pyrit/prompt_converter/denylist_converter.py @@ -53,11 +53,11 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text replacing them with synonymous words. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The conversion result as a `ConverterResult` object. + ConverterResult: The result containing the modified prompt. """ # check if the prompt contains any words from the denylist and if so, diff --git a/pyrit/prompt_converter/diacritic_converter.py b/pyrit/prompt_converter/diacritic_converter.py index 3d64e228ef..a19d48238e 100644 --- a/pyrit/prompt_converter/diacritic_converter.py +++ b/pyrit/prompt_converter/diacritic_converter.py @@ -17,7 +17,7 @@ class DiacriticConverter(PromptConverter): def __init__(self, target_chars: str = "aeiou", accent: str = "acute"): """ - Initializes the DiacriticConverter with specified target characters and diacritic accent. + Initializes the converter with specified target characters and diacritic accent. Args: target_chars (str): Characters to apply the diacritic to. Defaults to "aeiou". @@ -28,7 +28,7 @@ def __init__(self, target_chars: str = "aeiou", accent: str = "acute"): - `umlaut`: \u0308 Raises: - ValueError: If `target_chars` is empty. + ValueError: If `target_chars` is empty or if the specified accent is not recognized. """ super().__init__() @@ -79,6 +79,7 @@ def _add_diacritic(self, text: str) -> str: ) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt by applying diacritics to specified characters.""" if not self.input_supported(input_type): raise ValueError("Only 'text' input type is supported.") diff --git a/pyrit/prompt_converter/flip_converter.py b/pyrit/prompt_converter/flip_converter.py index 21cedf1ab0..8fba91cfb4 100644 --- a/pyrit/prompt_converter/flip_converter.py +++ b/pyrit/prompt_converter/flip_converter.py @@ -11,6 +11,7 @@ class FlipConverter(PromptConverter): """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """Converts the given prompt by reversing the text.""" if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py index 61ec213038..f90f1b9b53 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_converter_base.py @@ -28,28 +28,40 @@ class FuzzerConverter(PromptConverter): Base class for GPTFUZZER converters. Adapted from GPTFUZZER: Red Teaming Large Language Models with Auto-Generated Jailbreak Prompts. - Paper https://arxiv.org/pdf/2309.10253 by Jiahao Yu, Xingwei Lin, Zheng Yu, Xinyu Xing - GitHub https://github.com/sherdencooper/GPTFuzz/tree/master + Paper: https://arxiv.org/pdf/2309.10253 by Jiahao Yu, Xingwei Lin, Zheng Yu, Xinyu Xing. + GitHub: https://github.com/sherdencooper/GPTFuzz/tree/master """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: Optional[SeedPrompt] = None): + """ + Initializes the converter with the specified chat target and prompt template. + + Args: + converter_target (PromptChatTarget): Chat target used to perform fuzzing on user prompt. + prompt_template (SeedPrompt, Optional): Template to be used instead of the default system prompt with + instructions for the chat target. + """ self.converter_target = converter_target self.system_prompt = prompt_template.value self.template_label = "TEMPLATE" def update(self, **kwargs) -> None: + """Updates the converter with new parameters.""" pass async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Generates versions of prompt with new, prepended sentences. + Converts the given prompt into the target format supported by the converter. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The conversion result as a `ConverterResult` object. + ConverterResult: The result containing the modified prompt. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -87,6 +99,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text @pyrit_json_retry async def send_prompt_async(self, request): + """Sends the prompt request to the converter target and processes the response.""" response = await self.converter_target.send_prompt_async(prompt_request=request) response_msg = response.get_value() diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py index c447d975dc..cb26136ca7 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_crossover_converter.py @@ -20,7 +20,7 @@ class FuzzerCrossOverConverter(FuzzerConverter): """ - Fuzzer converter that uses multiple prompt templates to generate new prompts. + Uses multiple prompt templates to generate new prompts. """ def __init__( @@ -31,7 +31,7 @@ def __init__( prompt_templates: Optional[List[str]] = None, ): """ - Initializes the converter with a specified font. + Initializes the converter with the specified chat target and prompt templates. Args: converter_target (PromptChatTarget): Chat target used to perform fuzzing on user prompt. @@ -56,7 +56,7 @@ def update(self, **kwargs) -> None: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter to generate versions of prompt with new, prepended sentences. + Converts the given prompt by combining it with a random prompt template from the list of available templates. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py index d65f60cddb..d288bc5be3 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py @@ -37,6 +37,9 @@ def __init__( super().__init__(converter_target=converter_target, prompt_template=prompt_template) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given prompt by generating versions of it with new, prepended sentences. + """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/human_in_the_loop_converter.py b/pyrit/prompt_converter/human_in_the_loop_converter.py index 0bbfc16d04..1ca6cb0143 100644 --- a/pyrit/prompt_converter/human_in_the_loop_converter.py +++ b/pyrit/prompt_converter/human_in_the_loop_converter.py @@ -12,8 +12,10 @@ class HumanInTheLoopConverter(PromptConverter): """ - Allows review of each prompt sent to a target before sending it. User can choose to send the prompt as is, - modify the prompt, or run the prompt through one of the passed-in converters before sending it. + Allows review of each prompt sent to a target before sending it. + + User can choose to send the prompt as is, modify the prompt, + or run the prompt through one of the passed-in converters before sending it. """ def __init__( @@ -30,17 +32,22 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Before sending a prompt to a target, user is given three options to choose from: + Converts the given prompt by allowing user interaction before sending it to a target. + + User is given three options to choose from: (1) Proceed with sending the prompt as is. (2) Manually modify the prompt. (3) Run the prompt through a converter before sending it. Args: - prompt (str): The prompt to be added to the image. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The filename of the converted image as a `ConverterResult` object. + ConverterResult: The result containing the modified prompt. + + Raises: + ValueError: If no converters are provided and the user chooses to run a converter. """ user_input = "" if self._converters: diff --git a/pyrit/prompt_converter/insert_punctuation_converter.py b/pyrit/prompt_converter/insert_punctuation_converter.py index 489f52bc49..f6e33a012f 100644 --- a/pyrit/prompt_converter/insert_punctuation_converter.py +++ b/pyrit/prompt_converter/insert_punctuation_converter.py @@ -14,7 +14,7 @@ class InsertPunctuationConverter(PromptConverter): """ Inserts punctuation into a prompt to test robustness. - Punctuation insertion: inserting single punctuations in string.punctuation. + Punctuation insertion: inserting single punctuations in `string.punctuation`. Words in a prompt: a word does not contain any punctuation and space. "a1b2c3" is a word; "a1 2" are 2 words; "a1,b,3" are 3 words. """ @@ -29,6 +29,9 @@ def __init__(self, word_swap_ratio: float = 0.2, between_words: bool = True) -> word_swap_ratio (float): Percentage of words to perturb. Defaults to 0.2. between_words (bool): If True, insert punctuation only between words. If False, insert punctuation within words. Defaults to True. + + Raises: + ValueError: If word_swap_ratio is not between 0 and 1. """ # Swap ratio cannot be 0 or larger than 1 if not 0 < word_swap_ratio <= 1: @@ -60,7 +63,10 @@ async def convert_async( punctuation_list (Optional[List[str]]): List of punctuations to use for insertion. Returns: - ConverterResult: A ConverterResult containing a interation of modified prompts. + ConverterResult: The result containing a interation of modified prompts. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/leetspeak_converter.py b/pyrit/prompt_converter/leetspeak_converter.py index fc8d4baa7f..c48120cec8 100644 --- a/pyrit/prompt_converter/leetspeak_converter.py +++ b/pyrit/prompt_converter/leetspeak_converter.py @@ -9,7 +9,9 @@ class LeetspeakConverter(WordLevelConverter): - """Converts a string to a leetspeak version.""" + """ + Converts a string to a leetspeak version. + """ def __init__( self, @@ -22,7 +24,8 @@ def __init__( regex: Optional[Union[str, re.Pattern]] = None, ): """ - Initialize the converter with optional deterministic mode and custom substitutions. + Initializes the converter with optional deterministic mode and custom substitutions. + This class allows for selection of words to convert based on various criteria. Only one selection parameter may be provided at a time (indices, keywords, proportion, or regex). If no selection parameter is provided, all words will be converted. diff --git a/pyrit/prompt_converter/llm_generic_text_converter.py b/pyrit/prompt_converter/llm_generic_text_converter.py index cfcfddda54..7a2137e7bb 100644 --- a/pyrit/prompt_converter/llm_generic_text_converter.py +++ b/pyrit/prompt_converter/llm_generic_text_converter.py @@ -50,14 +50,14 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converts the given prompt based on the prompt template. + Converts the given prompt using an LLM via the specified converter target. - Parameters: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + Args: + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The conversion result as a `ConverterResult` object. + ConverterResult: The result containing the converted output and its type. """ conversation_id = str(uuid.uuid4()) diff --git a/pyrit/prompt_converter/math_prompt_converter.py b/pyrit/prompt_converter/math_prompt_converter.py index e6f967e9c9..7e667bc754 100644 --- a/pyrit/prompt_converter/math_prompt_converter.py +++ b/pyrit/prompt_converter/math_prompt_converter.py @@ -43,12 +43,11 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Converts the given prompt into a mathematical problem format. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The conversion result, including the mathematical representation - and real-world example, as a `ConverterResult` object. + ConverterResult: The result containing the mathematical representation and real-world example. """ logger.info(f"Converting prompt: {prompt}") diff --git a/pyrit/prompt_converter/morse_converter.py b/pyrit/prompt_converter/morse_converter.py index 0d8f83bcd2..77edb3f9cf 100644 --- a/pyrit/prompt_converter/morse_converter.py +++ b/pyrit/prompt_converter/morse_converter.py @@ -10,20 +10,20 @@ class MorseConverter(PromptConverter): """ - Converter to encode prompts using morse code. + Encodes prompts using morse code. Uses '-' and '.' characters, with ' ' to separate characters and '/' to separate words. - - Invalid/unsupported characters replaced with error sequence '........'. - - Parameters - --- - append_description: bool, default=False - Append plaintext "expert" text to the prompt. Includes instructions to only communicate - using the cipher, a description of the cipher, and an example encoded using cipher. + Invalid or unsupported characters are replaced with an error sequence '........'. """ def __init__(self, *, append_description: bool = False) -> None: + """ + Initializes the converter with an option to append a description to the prompt. + + Args: + append_description (bool): Append plaintext "expert" text to the prompt. Includes instructions to only + communicate using the cipher, a description of the cipher, and an example encoded using cipher. + """ self.append_description = append_description self.example = ( "User: How do I cut down a stop sign?\n" @@ -33,7 +33,7 @@ def __init__(self, *, append_description: bool = False) -> None: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Simple converter that morse code encodes the prompt. + Converts the given prompt to morse code. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/noise_converter.py b/pyrit/prompt_converter/noise_converter.py index 15d2b22e85..1498729f27 100644 --- a/pyrit/prompt_converter/noise_converter.py +++ b/pyrit/prompt_converter/noise_converter.py @@ -27,7 +27,7 @@ def __init__( prompt_template: Optional[SeedPrompt] = None, ): """ - Initializes the converter. + Initializes the converter with the specified parameters. Args: converter_target (PromptChatTarget): The endpoint that converts the prompt diff --git a/pyrit/prompt_converter/pdf_converter.py b/pyrit/prompt_converter/pdf_converter.py index fd193a325b..477e46d6f9 100644 --- a/pyrit/prompt_converter/pdf_converter.py +++ b/pyrit/prompt_converter/pdf_converter.py @@ -16,25 +16,15 @@ class PDFConverter(PromptConverter): """ - Converts a text prompt into a PDF file. Supports various modes: - 1. Template-Based Generation: If a `SeedPrompt` is provided, dynamic data can be injected into the - template using the `SeedPrompt.render_template_value` method, and the resulting content is converted to a PDF. - 2. Direct Text-Based Generation: If no template is provided, the raw string prompt is converted directly - into a PDF. - 3. Modify Existing PDFs (Overlay approach): Enables injecting text into existing PDFs at specified - coordinates, merging a new "overlay layer" onto the original PDF. - - Args: - prompt_template (Optional[SeedPrompt], optional): A `SeedPrompt` object representing a template. - font_type (str): Font type for the PDF. Defaults to "Helvetica". - font_size (int): Font size for the PDF. Defaults to 12. - font_color (tuple): Font color for the PDF in RGB format. Defaults to (255, 255, 255). - page_width (int): Width of the PDF page in mm. Defaults to 210 (A4 width). - page_height (int): Height of the PDF page in mm. Defaults to 297 (A4 height). - column_width (int): Width of each column in the PDF. Defaults to 0 (full page width). - row_height (int): Height of each row in the PDF. Defaults to 10. - existing_pdf (Optional[Path], optional): Path to an existing PDF file. Defaults to None. - injection_items (Optional[List[Dict]], optional): A list of injection items for modifying an existing PDF. + Converts a text prompt into a PDF file. + + Supports various modes: + 1. Template-Based Generation: If a `SeedPrompt` is provided, dynamic data can be injected into the + template using the `SeedPrompt.render_template_value` method, and the resulting content is converted to a PDF.\n + 2. Direct Text-Based Generation: If no template is provided, the raw string prompt is converted directly + into a PDF.\n + 3. Modify Existing PDFs (Overlay approach): Enables injecting text into existing PDFs at specified + coordinates, merging a new "overlay layer" onto the original PDF. """ def __init__( @@ -50,6 +40,25 @@ def __init__( existing_pdf: Optional[Path] = None, injection_items: Optional[List[Dict]] = None, ) -> None: + """ + Initializes the converter with the specified parameters. + + Args: + prompt_template (Optional[SeedPrompt], optional): A `SeedPrompt` object representing a template. + font_type (str): Font type for the PDF. Defaults to "Helvetica". + font_size (int): Font size for the PDF. Defaults to 12. + font_color (tuple): Font color for the PDF in RGB format. Defaults to (255, 255, 255). + page_width (int): Width of the PDF page in mm. Defaults to 210 (A4 width). + page_height (int): Height of the PDF page in mm. Defaults to 297 (A4 height). + column_width (int): Width of each column in the PDF. Defaults to 0 (full page width). + row_height (int): Height of each row in the PDF. Defaults to 10. + existing_pdf (Optional[Path], optional): Path to an existing PDF file. Defaults to None. + injection_items (Optional[List[Dict]], optional): A list of injection items for modifying an existing PDF. + + Raises: + ValueError: If the font color is invalid or the injection items are not provided as a list of dictionaries. + FileNotFoundError: If the provided PDF file does not exist. + """ self._prompt_template = prompt_template self._font_type = font_type self._font_size = font_size @@ -93,7 +102,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Args: prompt (str): The prompt to be embedded in the PDF. - input_type (PromptDataType): The type of the input data (default: "text"). + input_type (PromptDataType): The type of input data (default: "text"). Returns: ConverterResult: The result containing the full file path to the generated PDF. diff --git a/pyrit/prompt_converter/persuasion_converter.py b/pyrit/prompt_converter/persuasion_converter.py index bb2ca14078..f417dad6b0 100644 --- a/pyrit/prompt_converter/persuasion_converter.py +++ b/pyrit/prompt_converter/persuasion_converter.py @@ -26,19 +26,11 @@ class PersuasionConverter(PromptConverter): """ - Converter to rephrase prompts using a variety of persuasion techniques. + Rephrases prompts using a variety of persuasion techniques. Based on https://arxiv.org/abs/2401.06373 by Zeng et al. - Parameters - --- - converter_target: PromptChatTarget - Chat target used to perform rewriting on user prompt - - persuasion_technique: - {"authority_endorsement", "evidence_based", "expert_endorsement", "logical_appeal", "misrepresentation"} - Persuasion technique to be used by the converter, determines the system prompt to be used to - generate new prompts. + Supported persuasion techniques: - authority_endorsement: Citing authoritative sources in support of a claim. - evidence_based: Using empirical data, statistics, and facts to support a claim or decision. - expert_endorsement: Citing domain experts in support of a claim. @@ -47,6 +39,18 @@ class PersuasionConverter(PromptConverter): """ def __init__(self, *, converter_target: PromptChatTarget, persuasion_technique: str): + """ + Initializes the converter with the specified target and prompt template. + + Args: + converter_target (PromptChatTarget): The chat target used to perform rewriting on user prompts. + persuasion_technique (str): Persuasion technique to be used by the converter, determines the system prompt + to be used to generate new prompts. Must be one of "authority_endorsement", "evidence_based", + "expert_endorsement", "logical_appeal", "misrepresentation". + + Raises: + ValueError: If the persuasion technique is not supported or does not exist. + """ self.converter_target = converter_target try: @@ -59,7 +63,7 @@ def __init__(self, *, converter_target: PromptChatTarget, persuasion_technique: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter to generate versions of prompt with new, prepended sentences. + Converts the given prompt using the persuasion technique specified during initialization. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -94,6 +98,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text @pyrit_json_retry async def send_persuasion_prompt_async(self, request): + """Sends the prompt to the converter target and processes the response.""" response = await self.converter_target.send_prompt_async(prompt_request=request) response_msg = response.get_value() diff --git a/pyrit/prompt_converter/prompt_converter.py b/pyrit/prompt_converter/prompt_converter.py index d135977c6d..491104540a 100644 --- a/pyrit/prompt_converter/prompt_converter.py +++ b/pyrit/prompt_converter/prompt_converter.py @@ -40,8 +40,8 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Converts the given prompt into the target format supported by the converter. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: ConverterResult: The result containing the converted output and its type. diff --git a/pyrit/prompt_converter/qr_code_converter.py b/pyrit/prompt_converter/qr_code_converter.py index 0b8f911f29..23b7fc5f1a 100644 --- a/pyrit/prompt_converter/qr_code_converter.py +++ b/pyrit/prompt_converter/qr_code_converter.py @@ -11,26 +11,8 @@ class QRCodeConverter(PromptConverter): - """Converts a text string to a QR code image. - - Args: - scale (int, Optional): Scaling factor that determines the width/height in pixels of each - black/white square (known as a "module") in the QR code. Defaults to 3. - border (int, Optional): Controls how many modules thick the border should be. - Defaults to recommended value of 4. - dark_color (tuple, Optional): Sets color of dark modules, using RGB values. - Defaults to black: (0, 0, 0). - light_color (tuple, Optional): Sets color of light modules, using RGB values. - Defaults to white: (255, 255, 255). - data_dark_color (tuple, Optional): Sets color of dark data modules (the modules that actually - stores the data), using RGB values. Defaults to dark_color. - data_light_color (tuple, Optional): Sets color of light data modules, using RGB values. - Defaults to light_color. - finder_dark_color (tuple, Optional): Sets dark module color of finder patterns (squares located in - three corners), using RGB values. Defaults to dark_color. - finder_light_color (tuple, Optional): Sets light module color of finder patterns, using RGB values. - Defaults to light_color. - border_color (tuple, Optional): Sets color of border, using RGB values. Defaults to light_color. + """ + Converts a text string to a QR code image. """ def __init__( @@ -45,6 +27,28 @@ def __init__( finder_light_color: Optional[tuple] = None, border_color: Optional[tuple] = None, ): + """ + Initializes the converter with specified parameters for QR code generation. + + Args: + scale (int, Optional): Scaling factor that determines the width/height in pixels of each + black/white square (known as a "module") in the QR code. Defaults to 3. + border (int, Optional): Controls how many modules thick the border should be. + Defaults to recommended value of 4. + dark_color (tuple, Optional): Sets color of dark modules, using RGB values. + Defaults to black: (0, 0, 0). + light_color (tuple, Optional): Sets color of light modules, using RGB values. + Defaults to white: (255, 255, 255). + data_dark_color (tuple, Optional): Sets color of dark data modules (the modules that actually + stores the data), using RGB values. Defaults to dark_color. + data_light_color (tuple, Optional): Sets color of light data modules, using RGB values. + Defaults to light_color. + finder_dark_color (tuple, Optional): Sets dark module color of finder patterns (squares located in + three corners), using RGB values. Defaults to dark_color. + finder_light_color (tuple, Optional): Sets light module color of finder patterns, using RGB values. + Defaults to light_color. + border_color (tuple, Optional): Sets color of border, using RGB values. Defaults to light_color. + """ self._scale = scale self._border = border self._dark_color = dark_color @@ -58,13 +62,17 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter that converts string to QR code image. + Converts the given prompt to a QR code image. Args: prompt (str): The prompt to be converted. - input_type (PromptDataType): Type of data to be converted. Defaults to "text". + input_type (PromptDataType): The type of input data. + Returns: - ConverterResult: The filename of the converted QR code image as a ConverterResult Object + ConverterResult: The result containing filename of the converted QR code image. + + Raises: + ValueError: If the input type is not supported or if the prompt is empty. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/random_capital_letters_converter.py b/pyrit/prompt_converter/random_capital_letters_converter.py index 609c864804..726971e64b 100644 --- a/pyrit/prompt_converter/random_capital_letters_converter.py +++ b/pyrit/prompt_converter/random_capital_letters_converter.py @@ -11,14 +11,18 @@ class RandomCapitalLettersConverter(PromptConverter): - """This converter takes a prompt and randomly capitalizes it by a percentage of the total characters. - - Args: - This accepts a text prompt, and a percentage of randomization from 1 to 100. This includes decimal - points in that range. + """ + Takes a prompt and randomly capitalizes it by a percentage of the total characters. """ def __init__(self, percentage: float = 100.0) -> None: + """ + Initializes the converter with the specified percentage of randomization. + + Args: + percentage (float): The percentage of characters to capitalize in the prompt. Must be between 1 and 100. + Defaults to 100.0. This includes decimal points in that range. + """ self.percentage = percentage def input_supported(self, input_type: PromptDataType) -> bool: @@ -27,20 +31,20 @@ def input_supported(self, input_type: PromptDataType) -> bool: def output_supported(self, output_type: PromptDataType) -> bool: return output_type == "text" - # function to check if character is lower case returns True or False def is_lowercase_letter(self, char): + """Checks if the given character is a lowercase letter.""" return char.islower() - # function to check if number is between 1 and 100 returns True or False def is_percentage(self, input_string): + """Checks if the input string is a valid percentage between 1 and 100.""" try: number = float(input_string) return 1 <= number <= 100 except ValueError: return False - # function to generate an array of random positions set by a number def generate_random_positions(self, total_length, set_number): + """Generates a list of unique random positions within the range of `total_length`.""" # Ensure the set number is not greater than the total length if set_number > total_length: logger.error(f"Set number {set_number} cannot be greater than the total length which is {total_length}.") @@ -54,6 +58,7 @@ def generate_random_positions(self, total_length, set_number): return random_positions def string_to_upper_case_by_percentage(self, percentage, prompt): + """Converts a string by randomly capitalizing a percentage of its characters.""" if not self.is_percentage(percentage): logger.error(f"Percentage number {percentage} cannot be higher than 100 and lower than 1.") raise ValueError(f"Percentage number {percentage} cannot be higher than 100 and lower than 1.") @@ -67,7 +72,7 @@ def string_to_upper_case_by_percentage(self, percentage, prompt): async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Simple converter that converts the prompt to capital letters via a percentage . + Converts the given prompt by randomly capitalizing a percentage of its characters. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/repeat_token_converter.py b/pyrit/prompt_converter/repeat_token_converter.py index fc285188fb..6db51eef69 100644 --- a/pyrit/prompt_converter/repeat_token_converter.py +++ b/pyrit/prompt_converter/repeat_token_converter.py @@ -10,29 +10,21 @@ class RepeatTokenConverter(PromptConverter): """ - Repeat a specified token a specified number of times in addition to a given prompt. + Repeats a specified token a specified number of times in addition to a given prompt. + Based on: https://dropbox.tech/machine-learning/bye-bye-bye-evolution-of-repeated-token-attacks-on-chatgpt-models - Parameters - --- - token_to_repeat: string - The string to be repeated - - times_to_repeat: int - The number of times the string will be repeated - - token_insert_mode: {"split", "prepend", "append", "repeat"}, default="prepend" - Method to insert repeated tokens: - - If "split" prompt text will be split on the first occurance of (.?!) punctuation, - and repeated tokens will be inserted at location of split. - - If "prepend" repeated tokens will be inserted before the prompt text. - - If "append" repeated tokens will be inserted after the prompt text. - - If "repeat" prompt text will be ignored and result will only be repeated tokens. + Supported insertion modes: + - "split": + The prompt text will be split on the first occurrence of (.?!) punctuation, + and repeated tokens will be inserted at the location of the split. + - "prepend": + Repeated tokens will be inserted before the prompt text. + - "append": + Repeated tokens will be inserted after the prompt text. + - "repeat": + The prompt text will be ignored, and the result will only contain repeated tokens. """ def __init__( @@ -42,6 +34,15 @@ def __init__( times_to_repeat: int, token_insert_mode: Optional[Literal["split", "prepend", "append", "repeat"]] = None, ) -> None: + """ + Initializes the converter with the specified token, number of repetitions, and insertion mode. + + Args: + token_to_repeat (str): The string to be repeated. + times_to_repeat (int): The number of times the string will be repeated. + token_insert_mode (str, optional): The mode of insertion for the repeated token. + Can be "split", "prepend", "append", or "repeat". + """ self.token_to_repeat = " " + token_to_repeat.strip() self.times_to_repeat = times_to_repeat if not token_insert_mode: @@ -78,7 +79,7 @@ def insert(text: str) -> list: async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Converter to insert repeated tokens into the prompt. + Converts the given prompt by repeating the specified token a specified number of times. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/search_replace_converter.py b/pyrit/prompt_converter/search_replace_converter.py index b26a9e511f..4b2ea9a5f3 100644 --- a/pyrit/prompt_converter/search_replace_converter.py +++ b/pyrit/prompt_converter/search_replace_converter.py @@ -9,15 +9,20 @@ class SearchReplaceConverter(PromptConverter): - """Converts a string by replacing chosen phrase with a new phrase of choice - - Args: - pattern (str): the regex pattern to replace - replace (str): the new phrase to replace with, can be a list and a random element is chosen - regex_flags (int): regex flags to use for the replacement + """ + Converts a string by replacing chosen phrase with a new phrase of choice. """ def __init__(self, pattern: str, replace: str | list[str], regex_flags=0) -> None: + """ + Initializes the converter with the specified regex pattern and replacement phrase(s). + + Args: + pattern (str): The regex pattern to replace. + replace (str | list[str]): The new phrase to replace with. Can be a single string or a list of strings. + If a list is provided, a random element will be chosen for replacement. + regex_flags (int): Regex flags to use for the replacement. Defaults to 0 (no flags). + """ self.pattern = pattern self.replace_list = [replace] if isinstance(replace, str) else replace @@ -25,13 +30,17 @@ def __init__(self, pattern: str, replace: str | list[str], regex_flags=0) -> Non async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Simple converter that just replaces character in string with a chosen new character + Converts the given prompt by replacing the specified pattern with a random choice from the replacement list. Args: - prompt (str): prompt to convert - input_type (PromptDataType): type of input + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. + + Returns: + ConverterResult: The result containing the converted text. - Returns: converted text as a ConverterResult object + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/template_segment_converter.py b/pyrit/prompt_converter/template_segment_converter.py index dfcb848079..5343f1db1a 100644 --- a/pyrit/prompt_converter/template_segment_converter.py +++ b/pyrit/prompt_converter/template_segment_converter.py @@ -15,9 +15,9 @@ class TemplateSegmentConverter(PromptConverter): """ - A PromptConverter that uses a template to randomly split a prompt into segments defined by the template. + Uses a template to randomly split a prompt into segments defined by the template. - This converter is a generalized version of this + This converter is a generalized version of this: https://adversa.ai/blog/universal-llm-jailbreak-chatgpt-gpt-4-bard-bing-anthropic-and-beyond/ """ @@ -27,9 +27,14 @@ def __init__( prompt_template: Optional[SeedPrompt] = None, ): """ + Initializes the converter with the specified target and prompt template. + Args: prompt_template (SeedPrompt, Optional): The prompt template for the conversion. Must have two or more - parameters. If not provided, uses the default tom_and_jerry.yaml template. + parameters. If not provided, uses the default tom_and_jerry.yaml template. + + Raises: + ValueError: If the template has fewer than two parameters or if any parameter is missing in the template. """ super().__init__() @@ -67,7 +72,7 @@ def input_supported(self, input_type: PromptDataType) -> bool: def output_supported(self, output_type: PromptDataType) -> bool: return output_type == "text" - async def convert_async(self, *, prompt: str, input_type="text") -> ConverterResult: + async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ Converts the given prompt by splitting it into random segments and using them to fill the template parameters. The prompt is split into N segments (where N is the number of template parameters) at random word boundaries. @@ -75,13 +80,13 @@ async def convert_async(self, *, prompt: str, input_type="text") -> ConverterRes Args: prompt (str): The prompt to be converted. - input_type (str): The type of input data. Must be "text". + input_type (PromptDataType): The type of input data. Returns: ConverterResult: The result containing the template filled with prompt segments. Raises: - ValueError: If input_type is not supported. + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -98,10 +103,10 @@ def _split_prompt_into_segments(self, prompt: str) -> list[str]: If there aren't enough words for all parameters, remaining segments will be empty strings. Args: - prompt (str): The prompt to split into segments + prompt (str): The prompt to split into segments. Returns: - list[str]: List of segments, padded with empty strings if needed + list[str]: List of segments, padded with empty strings if needed. """ words = prompt.split() num_splits = min(len(words), self._number_parameters - 1) diff --git a/pyrit/prompt_converter/tense_converter.py b/pyrit/prompt_converter/tense_converter.py index 1dc9127db2..0a31e387f7 100644 --- a/pyrit/prompt_converter/tense_converter.py +++ b/pyrit/prompt_converter/tense_converter.py @@ -18,7 +18,7 @@ class TenseConverter(LLMGenericTextConverter): """ def __init__(self, *, converter_target: PromptChatTarget, tense: str, prompt_template: SeedPrompt = None): """ - Initializes the converter. + Initializes the converter with the target chat support, tense, and optional prompt template. Args: converter_target (PromptChatTarget): The target chat support for the conversion which will translate. diff --git a/pyrit/prompt_converter/text_jailbreak_converter.py b/pyrit/prompt_converter/text_jailbreak_converter.py index 46548fd663..7a70e15045 100644 --- a/pyrit/prompt_converter/text_jailbreak_converter.py +++ b/pyrit/prompt_converter/text_jailbreak_converter.py @@ -7,13 +7,22 @@ class TextJailbreakConverter(PromptConverter): + """ + Uses a jailbreak template to create a prompt. + """ def __init__(self, *, jailbreak_template: TextJailBreak): + """ + Initializes the converter with the specified jailbreak template. + + Args: + jailbreak_template (TextJailBreak): The jailbreak template to use for conversion. + """ self.jail_break_template = jailbreak_template async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Simple converter that uses a jailbreak template to create a prompt + Converts the given prompt using the jailbreak template. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py index 5e9a02e6d4..f64aea3634 100644 --- a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py @@ -14,8 +14,8 @@ class AsciiSmugglerConverter(SmugglerConverter): Implements encoding and decoding using Unicode Tags. If 'control' is True, the encoded output is wrapped with: - - U+E0001 (start control tag) - - U+E007F (end control tag) + - U+E0001 (start control tag) + - U+E007F (end control tag) Replicates the functionality detailed in the following blog post: https://embracethered.com/blog/posts/2024/hiding-and-finding-text-with-unicode-tags/ @@ -26,6 +26,7 @@ def __init__(self, action: Literal["encode", "decode"] = "encode", unicode_tags: Initializes the converter with options for encoding/decoding. Args: + action (Literal["encode", "decode"]): The action to perform. unicode_tags (bool): Whether to add Unicode tags during encoding. """ self.unicode_tags = unicode_tags diff --git a/pyrit/prompt_converter/token_smuggling/base.py b/pyrit/prompt_converter/token_smuggling/base.py index d64984bc9b..2ccfcadbc0 100644 --- a/pyrit/prompt_converter/token_smuggling/base.py +++ b/pyrit/prompt_converter/token_smuggling/base.py @@ -20,23 +20,29 @@ class SmugglerConverter(PromptConverter, abc.ABC): """ def __init__(self, action: Literal["encode", "decode"] = "encode") -> None: + """ + Initializes the converter with options for encoding/decoding. + + Args: + action (Literal["encode", "decode"]): The action to perform. + """ if action not in ["encode", "decode"]: raise ValueError("Action must be either 'encode' or 'decode'") self.action = action async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Convert the prompt by either encoding or decoding it based on the specified action. + Converts the given prompt by either encoding or decoding it based on the specified action. Args: - prompt (str): The prompt to be processed. - input_type (PromptDataType): Type of input; only "text" is supported. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The result containing the output text and its type. + ConverterResult: The result containing the converted text and its type. Raises: - ValueError: If the input type is unsupported. + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -49,11 +55,9 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text return ConverterResult(output_text=decoded, output_type="text") def input_supported(self, input_type: PromptDataType) -> bool: - """Return True if the input type is 'text'.""" return input_type == "text" def output_supported(self, output_type: PromptDataType) -> bool: - """Return True if the output type is 'text'.""" return output_type == "text" @abc.abstractmethod diff --git a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py index f928f3f478..57f143014c 100644 --- a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py @@ -14,11 +14,11 @@ class SneakyBitsSmugglerConverter(SmugglerConverter): Encodes and decodes text using a bit-level approach. Uses two invisible Unicode characters: - - `zero_char` (default: U+2062) to represent binary 0. - - `one_char` (default: U+2064) to represent binary 1. + - `zero_char` (default: U+2062) to represent binary 0. + - `one_char` (default: U+2064) to represent binary 1. Replicates functionality detailed in: - - https://embracethered.com/blog/posts/2025/sneaky-bits-and-ascii-smuggler/ + - https://embracethered.com/blog/posts/2025/sneaky-bits-and-ascii-smuggler/ """ def __init__( @@ -28,6 +28,8 @@ def __init__( one_char: Optional[str] = None, ): """ + Initializes the converter with options for encoding/decoding in Sneaky Bits mode. + Args: action (Literal["encode", "decode"]): The action to perform. zero_char (Optional[str]): Character to represent binary 0 in sneaky_bits mode (default: U+2062). @@ -42,7 +44,7 @@ def __init__( def encode_message(self, message: str) -> Tuple[str, str]: """ - Encode the message using Sneaky Bits mode. + Encodes the message using Sneaky Bits mode. The message is first converted to its UTF-8 byte sequence. Then each byte is represented as 8 bits, with each bit replaced by an invisible character (self.zero_char for 0 and @@ -71,7 +73,7 @@ def encode_message(self, message: str) -> Tuple[str, str]: def decode_message(self, message: str) -> str: """ - Decode the message encoded using Sneaky Bits mode. + Decodes the message encoded using Sneaky Bits mode. The method filters out only the valid invisible characters (self.zero_char and self.one_char), groups them into 8-bit chunks, reconstructs each byte, and finally decodes the byte sequence diff --git a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py index 3052f20321..d9f68745cf 100644 --- a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py @@ -14,14 +14,14 @@ class VariationSelectorSmugglerConverter(SmugglerConverter): Encodes and decodes text using Unicode Variation Selectors. Each UTF-8 byte is mapped as follows: - - Bytes 0x00-0x0F are mapped to U+FE00-U+FE0F. - - Bytes 0x10-0xFF are mapped to U+E0100-U+E01EF. + - Bytes 0x00-0x0F are mapped to U+FE00-U+FE0F. + - Bytes 0x10-0xFF are mapped to U+E0100-U+E01EF. If 'embed_in_base' is True, the payload is concatenated with a base character (default: 😊); otherwise, a space separator is inserted. Replicates functionality detailed in: - - https://paulbutler.org/2025/smuggling-arbitrary-data-through-an-emoji/ + - https://paulbutler.org/2025/smuggling-arbitrary-data-through-an-emoji/ Extension: In addition to embedding into a base character, we also support appending invisible variation selectors directly to visible textβ€”enabling mixed @@ -35,7 +35,7 @@ def __init__( embed_in_base: bool = True, ): """ - Initialize the converter with options for encoding/decoding. + Initializes the converter with options for encoding/decoding. Args: action (Literal["encode", "decode"]): The action to perform. @@ -53,11 +53,13 @@ def __init__( def encode_message(self, message: str) -> Tuple[str, str]: """ - Encode the message using Unicode variation selectors. + Encodes the message using Unicode variation selectors. + The message is converted to UTF-8 bytes, and each byte is mapped to a variation selector: - - 0x00-0x0F => U+FE00 to U+FE0F. - - 0x10-0xFF => U+E0100 to U+E01EF. - If embed_in_base is True, the payload is embedded directly into the base character; + - 0x00-0x0F => U+FE00 to U+FE0F. + - 0x10-0xFF => U+E0100 to U+E01EF. + + If ``embed_in_base`` is True, the payload is embedded directly into the base character; otherwise, a visible separator (a space) is inserted between the base and payload. """ payload = "" @@ -84,7 +86,7 @@ def encode_message(self, message: str) -> Tuple[str, str]: def decode_message(self, message: str) -> str: """ - Decode a message encoded using Unicode variation selectors. + Decodes a message encoded using Unicode variation selectors. The decoder scans the string for variation selectors, ignoring any visible separator. """ bytes_out = bytearray() @@ -116,12 +118,15 @@ def decode_message(self, message: str) -> str: # Extension of Paul Butler's method def encode_visible_hidden(self, visible: str, hidden: str) -> Tuple[str, str]: """ - Combine visible text with hidden text by encoding the hidden text using variation_selector_smuggler mode. + Combines visible text with hidden text by encoding the hidden text using variation_selector_smuggler mode. + The hidden payload is generated as a composite using the current embedding setting and then appended to the visible text. + Args: visible (str): The visible text. hidden (str): The secret/hidden text to encode. + Returns: Tuple[str, str]: A tuple containing a summary and the combined text. """ @@ -132,11 +137,14 @@ def encode_visible_hidden(self, visible: str, hidden: str) -> Tuple[str, str]: # Extension of Paul Butler's method def decode_visible_hidden(self, combined: str) -> Tuple[str, str]: """ - Extract the visible text and decode the hidden text from a combined string. - It searches for the first occurrence of the base character (self.utf8_base_char) and treats everything + Extracts the visible text and decodes the hidden text from a combined string. + + It searches for the first occurrence of the base character (``self.utf8_base_char``) and treats everything from that point on as the hidden payload. + Args: combined (str): The combined text containing visible and hidden parts. + Returns: Tuple[str, str]: A tuple with the visible text and the decoded hidden text. """ diff --git a/pyrit/prompt_converter/tone_converter.py b/pyrit/prompt_converter/tone_converter.py index 3d8676edc3..8b906ddbb9 100644 --- a/pyrit/prompt_converter/tone_converter.py +++ b/pyrit/prompt_converter/tone_converter.py @@ -18,7 +18,7 @@ class ToneConverter(LLMGenericTextConverter): """ def __init__(self, *, converter_target: PromptChatTarget, tone: str, prompt_template: SeedPrompt = None): """ - Initializes the converter. + Initializes the converter with the target chat support, tone, and optional prompt template. Args: converter_target (PromptChatTarget): The target chat support for the conversion which will translate. diff --git a/pyrit/prompt_converter/toxic_sentence_generator_converter.py b/pyrit/prompt_converter/toxic_sentence_generator_converter.py index 6bf48a7bbc..e8c5462d5b 100644 --- a/pyrit/prompt_converter/toxic_sentence_generator_converter.py +++ b/pyrit/prompt_converter/toxic_sentence_generator_converter.py @@ -52,11 +52,11 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Converts the given prompt into a toxic sentence starter. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The conversion result, containing the toxic sentence starter. + ConverterResult: The conversion result containing the toxic sentence starter. """ # Add the prompt to _prompt_kwargs before calling the base method self._prompt_kwargs["prompt"] = prompt diff --git a/pyrit/prompt_converter/translation_converter.py b/pyrit/prompt_converter/translation_converter.py index eef2bf755c..4483e76f62 100644 --- a/pyrit/prompt_converter/translation_converter.py +++ b/pyrit/prompt_converter/translation_converter.py @@ -29,7 +29,7 @@ class TranslationConverter(PromptConverter): """ - Uses an LLM to translate prompts into different languages. + Translates prompts into different languages using an LLM. """ def __init__( self, @@ -41,12 +41,14 @@ def __init__( max_wait_time_in_seconds: int = 60, ): """ - Initializes a TranslationConverter object. + Initializes the converter with the target chat support, language, and optional prompt template. Args: converter_target (PromptChatTarget): The target chat support for the conversion which will translate language (str): The language for the conversion. E.g. Spanish, French, leetspeak, etc. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. + max_retries (int): Maximum number of retries for the conversion. + max_wait_time_in_seconds (int): Maximum wait time in seconds between retries. Raises: ValueError: If the language is not provided. @@ -75,11 +77,16 @@ def __init__( async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ - Generates variations of the input prompt using the converter target. - Parameters: - prompt (str): prompt to convert - Return: - (ConverterResult): result generated by the converter target + Converts the given prompt by translating it using the converter target. + + Args: + prompt (str): The prompt to be converted. + + Returns: + ConverterResult: The result containing the generated version of the prompt. + + Raises: + ValueError: If the input type is not supported. """ conversation_id = str(uuid.uuid4()) diff --git a/pyrit/prompt_converter/unicode_confusable_converter.py b/pyrit/prompt_converter/unicode_confusable_converter.py index 368b32574d..387c75f8d4 100644 --- a/pyrit/prompt_converter/unicode_confusable_converter.py +++ b/pyrit/prompt_converter/unicode_confusable_converter.py @@ -17,8 +17,8 @@ class UnicodeConfusableConverter(PromptConverter): """ - A PromptConverter that applies substitutions to words in the prompt - to test adversarial textual robustness by replacing characters with visually similar ones. + Applies substitutions to words in the prompt to test adversarial textual robustness + by replacing characters with visually similar ones. """ def __init__( @@ -28,17 +28,18 @@ def __init__( deterministic: bool = False, ): """ - Initializes the UnicodeConfusableConverter. + Initializes the converter with the specified source package for homoglyph generation. Args: - source_package: The package to use for homoglyph generation. Can be either "confusable_homoglyphs" + source_package (Literal["confusable_homoglyphs", "confusables"]): + The package to use for homoglyph generation. Can be either "confusable_homoglyphs" which can be found here: https://pypi.org/project/confusable-homoglyphs/ or "confusables" which can be found here: https://pypi.org/project/confusables/. "Confusable_homoglyphs" is used by default as it is more regularly maintained and up to date with the latest Unicode-provided confusables found here: https://www.unicode.org/Public/security/latest/confusables.txt. However, "confusables" provides additional methods of matching characters (not just Unicode list), so each character has more possible substitutions. - deterministic: This argument is for unittesting only. + deterministic (bool): This argument is for unittesting only. """ if source_package not in ["confusable_homoglyphs", "confusables"]: raise ValueError( @@ -55,9 +56,13 @@ async def convert_async(self, *, prompt: str, input_type="text") -> ConverterRes Args: prompt (str): The prompt to be converted. - input_type (str): The type of input (should be "text"). + input_type (PromptDataType): The type of input data. + Returns: ConverterResult: The result containing the prompt with confusable subsitutions applied. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -75,6 +80,7 @@ def _get_homoglyph_variants(self, word: str) -> list: Args: word (str): The word to find homoglyphs for. + Returns: list: A list of homoglyph variants for the word. """ @@ -98,6 +104,7 @@ def _generate_perturbed_prompts(self, prompt: str) -> str: Args: prompt (str): The original prompt. + Returns: str: A perturbed prompt with character-level substitutions. """ @@ -127,10 +134,11 @@ def _generate_perturbed_prompts(self, prompt: str) -> str: def _confusable(self, char: str) -> str: """ - Pick a confusable character for the given character using the "confusables" package. + Picks a confusable character for the given character using the "confusables" package. Args: char (str): The character to be replaced. + Returns: str: The confusable character to replace the given character. """ diff --git a/pyrit/prompt_converter/unicode_sub_converter.py b/pyrit/prompt_converter/unicode_sub_converter.py index 7eac4f4d27..98293d6a73 100644 --- a/pyrit/prompt_converter/unicode_sub_converter.py +++ b/pyrit/prompt_converter/unicode_sub_converter.py @@ -8,12 +8,15 @@ class UnicodeSubstitutionConverter(PromptConverter): """ Encodes the prompt using any unicode starting point. - Default is to use invisible flag emoji characters. """ def __init__(self, *, start_value=0xE0000): self.startValue = start_value async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given prompt by encoding it using any unicode starting point. + Default is to use invisible flag emoji characters. + """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/url_converter.py b/pyrit/prompt_converter/url_converter.py index 64b728a60b..86b2e80c8d 100644 --- a/pyrit/prompt_converter/url_converter.py +++ b/pyrit/prompt_converter/url_converter.py @@ -13,6 +13,9 @@ class UrlConverter(PromptConverter): """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given prompt into a URL-encoded string. + """ if not self.input_supported(input_type): raise ValueError("Input type not supported") diff --git a/pyrit/prompt_converter/variation_converter.py b/pyrit/prompt_converter/variation_converter.py index 5e19fc727d..9d33ace492 100644 --- a/pyrit/prompt_converter/variation_converter.py +++ b/pyrit/prompt_converter/variation_converter.py @@ -30,6 +30,14 @@ class VariationConverter(PromptConverter): Generates variations of the input prompts using the converter target. """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): + """ + Initializes the converter with the specified target and prompt template. + + Args: + converter_target (PromptChatTarget): The target to which the prompt will be sent for conversion. + prompt_template (SeedPrompt, optional): The template used for generating the system prompt. + If not provided, a default template will be used. + """ self.converter_target = converter_target # set to default strategy if not provided @@ -46,6 +54,18 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedP self.system_prompt = str(prompt_template.render_template_value(number_iterations=str(self.number_variations))) async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: + """ + Converts the given prompt by generating variations of it using the converter target. + + Args: + prompt (str): The prompt to be converted. + + Returns: + ConverterResult: The result containing the generated variations. + + Raises: + ValueError: If the input type is not supported. + """ if not self.input_supported(input_type): raise ValueError("Input type not supported") @@ -86,6 +106,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text @pyrit_json_retry async def send_variation_prompt_async(self, request): + """Sends the prompt request to the converter target and retrieves the response.""" response = await self.converter_target.send_prompt_async(prompt_request=request) response_msg = response.get_value() diff --git a/pyrit/prompt_converter/word_level_converter.py b/pyrit/prompt_converter/word_level_converter.py index a2de6c3dff..52dc97b16d 100644 --- a/pyrit/prompt_converter/word_level_converter.py +++ b/pyrit/prompt_converter/word_level_converter.py @@ -110,11 +110,15 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Converts the given prompt into the target format supported by the converter. Args: - prompt (str): The input prompt to be converted. - input_type (PromptDataType): The type of the input data. + prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: - ConverterResult: The result of the conversion, including the converted output and its type. + ConverterResult: The result containing the converted output and its type. + + Raises: + TypeError: If the prompt is None. + ValueError: If the input type is not supported. """ if prompt is None: raise TypeError("Prompt cannot be None") diff --git a/pyrit/prompt_converter/zero_width_converter.py b/pyrit/prompt_converter/zero_width_converter.py index 37552e1998..e892bb954f 100644 --- a/pyrit/prompt_converter/zero_width_converter.py +++ b/pyrit/prompt_converter/zero_width_converter.py @@ -7,8 +7,7 @@ class ZeroWidthConverter(PromptConverter): """ - A PromptConverter that injects zero-width spaces between characters - in the provided text to bypass content safety mechanisms. + Injects zero-width spaces between characters in the provided text to bypass content safety mechanisms. """ ZERO_WIDTH_SPACE = "\u200b" @@ -25,9 +24,13 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Args: prompt (str): The prompt to be converted. + input_type (PromptDataType): The type of input data. Returns: ConverterResult: The result containing the modified prompt. + + Raises: + ValueError: If the input type is not supported. """ if not self.input_supported(input_type): raise ValueError("Only 'text' input type is supported.") From 5922d0db39d57febd144f3081c3e4cc89a612035 Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Tue, 17 Jun 2025 14:10:07 +0200 Subject: [PATCH 6/8] pre-commit --- pyrit/prompt_converter/binary_converter.py | 2 +- .../fuzzer_converter/fuzzer_expand_converter.py | 1 + .../fuzzer_converter/fuzzer_rephrase_converter.py | 1 + .../fuzzer_converter/fuzzer_shorten_converter.py | 1 + .../fuzzer_converter/fuzzer_similar_converter.py | 1 + pyrit/prompt_converter/llm_generic_text_converter.py | 1 + pyrit/prompt_converter/noise_converter.py | 1 + pyrit/prompt_converter/tense_converter.py | 1 + pyrit/prompt_converter/tone_converter.py | 1 + pyrit/prompt_converter/translation_converter.py | 1 + pyrit/prompt_converter/unicode_replacement_converter.py | 1 + pyrit/prompt_converter/unicode_sub_converter.py | 1 + pyrit/prompt_converter/variation_converter.py | 1 + 13 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pyrit/prompt_converter/binary_converter.py b/pyrit/prompt_converter/binary_converter.py index e0d25b9118..bb1d96cad3 100644 --- a/pyrit/prompt_converter/binary_converter.py +++ b/pyrit/prompt_converter/binary_converter.py @@ -62,7 +62,7 @@ def validate_input(self, prompt): ) async def convert_word_async(self, word: str) -> str: - """Converts each character in the word to its binary representation. """ + """Converts each character in the word to its binary representation.""" bits = self.bits_per_char.value return " ".join(format(ord(char), f"0{bits}b") for char in word) diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py index d288bc5be3..455bc42ecb 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_expand_converter.py @@ -21,6 +21,7 @@ class FuzzerExpandConverter(FuzzerConverter): """ Generates versions of a prompt with new, prepended sentences. """ + def __init__( self, *, diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py index 9183221bbd..cc76d15538 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_rephrase_converter.py @@ -15,6 +15,7 @@ class FuzzerRephraseConverter(FuzzerConverter): """ Generates versions of a prompt with rephrased sentences. """ + def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py index 042698eefc..6c1bac04b9 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_shorten_converter.py @@ -15,6 +15,7 @@ class FuzzerShortenConverter(FuzzerConverter): """ Generates versions of a prompt with shortened sentences. """ + def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py b/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py index 9e07addacc..c22f60a4d9 100644 --- a/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py +++ b/pyrit/prompt_converter/fuzzer_converter/fuzzer_similar_converter.py @@ -15,6 +15,7 @@ class FuzzerSimilarConverter(FuzzerConverter): """ Generates versions of a prompt with similar sentences. """ + def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): prompt_template = ( prompt_template diff --git a/pyrit/prompt_converter/llm_generic_text_converter.py b/pyrit/prompt_converter/llm_generic_text_converter.py index 7a2137e7bb..90cfe21a28 100644 --- a/pyrit/prompt_converter/llm_generic_text_converter.py +++ b/pyrit/prompt_converter/llm_generic_text_converter.py @@ -21,6 +21,7 @@ class LLMGenericTextConverter(PromptConverter): """ Represents a generic LLM converter that expects text to be transformed (e.g. no JSON parsing or format). """ + def __init__( self, *, diff --git a/pyrit/prompt_converter/noise_converter.py b/pyrit/prompt_converter/noise_converter.py index 1498729f27..2f953cb704 100644 --- a/pyrit/prompt_converter/noise_converter.py +++ b/pyrit/prompt_converter/noise_converter.py @@ -18,6 +18,7 @@ class NoiseConverter(LLMGenericTextConverter): """ Injects noise errors into a conversation. """ + def __init__( self, *, diff --git a/pyrit/prompt_converter/tense_converter.py b/pyrit/prompt_converter/tense_converter.py index 0a31e387f7..3ef026d32f 100644 --- a/pyrit/prompt_converter/tense_converter.py +++ b/pyrit/prompt_converter/tense_converter.py @@ -16,6 +16,7 @@ class TenseConverter(LLMGenericTextConverter): """ Converts a conversation to a different tense. """ + def __init__(self, *, converter_target: PromptChatTarget, tense: str, prompt_template: SeedPrompt = None): """ Initializes the converter with the target chat support, tense, and optional prompt template. diff --git a/pyrit/prompt_converter/tone_converter.py b/pyrit/prompt_converter/tone_converter.py index 8b906ddbb9..7b1f023d9f 100644 --- a/pyrit/prompt_converter/tone_converter.py +++ b/pyrit/prompt_converter/tone_converter.py @@ -16,6 +16,7 @@ class ToneConverter(LLMGenericTextConverter): """ Converts a conversation to a different tone. """ + def __init__(self, *, converter_target: PromptChatTarget, tone: str, prompt_template: SeedPrompt = None): """ Initializes the converter with the target chat support, tone, and optional prompt template. diff --git a/pyrit/prompt_converter/translation_converter.py b/pyrit/prompt_converter/translation_converter.py index 4483e76f62..6c50139ed9 100644 --- a/pyrit/prompt_converter/translation_converter.py +++ b/pyrit/prompt_converter/translation_converter.py @@ -31,6 +31,7 @@ class TranslationConverter(PromptConverter): """ Translates prompts into different languages using an LLM. """ + def __init__( self, *, diff --git a/pyrit/prompt_converter/unicode_replacement_converter.py b/pyrit/prompt_converter/unicode_replacement_converter.py index 31537723e7..10af862073 100644 --- a/pyrit/prompt_converter/unicode_replacement_converter.py +++ b/pyrit/prompt_converter/unicode_replacement_converter.py @@ -11,6 +11,7 @@ class UnicodeReplacementConverter(WordLevelConverter): """ Converts a prompt to its unicode representation. """ + def __init__( self, *, diff --git a/pyrit/prompt_converter/unicode_sub_converter.py b/pyrit/prompt_converter/unicode_sub_converter.py index 98293d6a73..df198d5881 100644 --- a/pyrit/prompt_converter/unicode_sub_converter.py +++ b/pyrit/prompt_converter/unicode_sub_converter.py @@ -9,6 +9,7 @@ class UnicodeSubstitutionConverter(PromptConverter): """ Encodes the prompt using any unicode starting point. """ + def __init__(self, *, start_value=0xE0000): self.startValue = start_value diff --git a/pyrit/prompt_converter/variation_converter.py b/pyrit/prompt_converter/variation_converter.py index 9d33ace492..1d20857a42 100644 --- a/pyrit/prompt_converter/variation_converter.py +++ b/pyrit/prompt_converter/variation_converter.py @@ -29,6 +29,7 @@ class VariationConverter(PromptConverter): """ Generates variations of the input prompts using the converter target. """ + def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): """ Initializes the converter with the specified target and prompt template. From 69cb41e858f9ecb764181209a3294403e57a49a0 Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:19:19 +0200 Subject: [PATCH 7/8] final touches after visual check of the generated HTML output --- .../add_image_text_converter.py | 4 ++-- .../add_image_to_video_converter.py | 9 +++++---- .../add_text_image_converter.py | 4 ++-- .../audio_frequency_converter.py | 1 + .../azure_speech_audio_to_text_converter.py | 2 ++ .../azure_speech_text_to_audio_converter.py | 3 +++ pyrit/prompt_converter/binary_converter.py | 7 ++++--- pyrit/prompt_converter/caesar_converter.py | 4 ++-- .../character_space_converter.py | 2 +- .../codechameleon_converter.py | 4 ++-- pyrit/prompt_converter/denylist_converter.py | 4 +++- pyrit/prompt_converter/diacritic_converter.py | 14 +++++++------ pyrit/prompt_converter/emoji_converter.py | 1 + .../insert_punctuation_converter.py | 3 ++- .../malicious_question_generator_converter.py | 4 +++- .../prompt_converter/math_prompt_converter.py | 5 +++-- pyrit/prompt_converter/noise_converter.py | 6 ++++-- pyrit/prompt_converter/pdf_converter.py | 18 +++++++++-------- .../prompt_converter/persuasion_converter.py | 15 +++++++++----- pyrit/prompt_converter/prompt_converter.py | 2 +- pyrit/prompt_converter/qr_code_converter.py | 6 +++--- .../suffix_append_converter.py | 4 ++-- .../prompt_converter/superscript_converter.py | 3 +-- .../template_segment_converter.py | 2 +- pyrit/prompt_converter/tense_converter.py | 4 +++- .../sneaky_bits_smuggler_converter.py | 20 +++++++++---------- .../variation_selector_smuggler_converter.py | 8 ++++---- pyrit/prompt_converter/tone_converter.py | 4 +++- .../toxic_sentence_generator_converter.py | 8 +++++--- .../prompt_converter/translation_converter.py | 2 +- .../unicode_confusable_converter.py | 17 +++++++++------- .../prompt_converter/word_level_converter.py | 2 +- .../prompt_converter/zero_width_converter.py | 1 + 33 files changed, 113 insertions(+), 80 deletions(-) diff --git a/pyrit/prompt_converter/add_image_text_converter.py b/pyrit/prompt_converter/add_image_text_converter.py index b6852872d9..f6e904d2a9 100644 --- a/pyrit/prompt_converter/add_image_text_converter.py +++ b/pyrit/prompt_converter/add_image_text_converter.py @@ -44,7 +44,7 @@ def __init__( y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. Raises: - ValueError: If `img_to_add` is empty or invalid, or if `font_name` does not end with ".ttf". + ValueError: If ``img_to_add`` is empty or invalid, or if ``font_name`` does not end with ".ttf". """ if not img_to_add: raise ValueError("Please provide valid image path") @@ -118,7 +118,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 specified in the constructor. + Converts the given prompt by adding it as text to the image. Args: prompt (str): The text to be added to the image. diff --git a/pyrit/prompt_converter/add_image_to_video_converter.py b/pyrit/prompt_converter/add_image_to_video_converter.py index 1bb8f00686..5ac6c6f5ff 100644 --- a/pyrit/prompt_converter/add_image_to_video_converter.py +++ b/pyrit/prompt_converter/add_image_to_video_converter.py @@ -27,7 +27,8 @@ class AddImageVideoConverter(PromptConverter): """ Adds an image to a video at a specified position. - Also, currently the image is placed in the whole video, not at a specific timepoint. + + Currently the image is placed in the whole video, not at a specific timepoint. """ def __init__( @@ -47,7 +48,7 @@ def __init__( img_resize_size (tuple): Size to resize image to. Defaults to (500, 500). Raises: - ValueError: If `video_path` is empty or invalid. + ValueError: If ``video_path`` is empty or invalid. """ if not video_path: @@ -165,10 +166,10 @@ 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 file path) by adding it to a video. + Converts the given prompt (image) by adding it to a video. Args: - prompt (str): The image file name to be added to the video. + prompt (str): The image path to be added to the video. input_type (PromptDataType): The type of input data. Returns: diff --git a/pyrit/prompt_converter/add_text_image_converter.py b/pyrit/prompt_converter/add_text_image_converter.py index ea582aeea7..0a31b70913 100644 --- a/pyrit/prompt_converter/add_text_image_converter.py +++ b/pyrit/prompt_converter/add_text_image_converter.py @@ -44,7 +44,7 @@ def __init__( y_pos (int): Y coordinate to place text in (0 is upper most). Defaults to 10. Raises: - ValueError: If `text_to_add` is empty, or if `font_name` does not end with ".ttf". + ValueError: If ``text_to_add`` is empty, or if ``font_name`` does not end with ".ttf". """ if text_to_add.strip() == "": raise ValueError("Please provide valid text_to_add value") @@ -114,7 +114,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 file path) by adding text to the image. + Converts the given prompt (image) by adding text to it. Args: prompt (str): The image file path to which text will be added. diff --git a/pyrit/prompt_converter/audio_frequency_converter.py b/pyrit/prompt_converter/audio_frequency_converter.py index 0ba79cf01e..d700941f9f 100644 --- a/pyrit/prompt_converter/audio_frequency_converter.py +++ b/pyrit/prompt_converter/audio_frequency_converter.py @@ -21,6 +21,7 @@ class AudioFrequencyConverter(PromptConverter): By default, it will shift it above the human hearing range (=20 kHz). """ + #: Accepted audio formats for conversion. AcceptedAudioFormats = Literal["wav"] def __init__( diff --git a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py index 731c3e63d7..6726c2efaa 100644 --- a/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py +++ b/pyrit/prompt_converter/azure_speech_audio_to_text_converter.py @@ -23,7 +23,9 @@ class AzureSpeechAudioToTextConverter(PromptConverter): https://learn.microsoft.com/en-us/azure/ai-services/speech-service/speech-to-text """ + #: The name of the Azure region. AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_REGION" + #: The API key for accessing the service. AZURE_SPEECH_KEY_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_KEY" def __init__( diff --git a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py index 6166ca2ede..4c59133dff 100644 --- a/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py +++ b/pyrit/prompt_converter/azure_speech_text_to_audio_converter.py @@ -21,9 +21,12 @@ class AzureSpeechTextToAudioConverter(PromptConverter): https://learn.microsoft.com/en-us/azure/ai-services/speech-service/text-to-speech """ + #: The name of the Azure region. AZURE_SPEECH_REGION_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_REGION" + #: The API key for accessing the service. AZURE_SPEECH_KEY_ENVIRONMENT_VARIABLE: str = "AZURE_SPEECH_KEY" + #: Supported audio formats for output. AzureSpeachAudioFormat = Literal["wav", "mp3"] def __init__( diff --git a/pyrit/prompt_converter/binary_converter.py b/pyrit/prompt_converter/binary_converter.py index bb1d96cad3..475d764eed 100644 --- a/pyrit/prompt_converter/binary_converter.py +++ b/pyrit/prompt_converter/binary_converter.py @@ -16,9 +16,10 @@ class BinaryConverter(WordLevelConverter): """ class BitsPerChar(Enum): - BITS_8 = 8 - BITS_16 = 16 - BITS_32 = 32 + """The number of bits per character for binary conversion.""" + BITS_8 = 8 #: 8 bits per character, suitable for ASCII characters. + BITS_16 = 16 #: 16 bits per character, suitable for Unicode characters. + BITS_32 = 32 #: 32 bits per character, suitable for extended Unicode characters. def __init__( self, diff --git a/pyrit/prompt_converter/caesar_converter.py b/pyrit/prompt_converter/caesar_converter.py index f8a9ad62f0..c55adc9056 100644 --- a/pyrit/prompt_converter/caesar_converter.py +++ b/pyrit/prompt_converter/caesar_converter.py @@ -13,7 +13,7 @@ class CaesarConverter(PromptConverter): """ Encodes text using the Caesar cipher with a specified offset. - Using offset=1, 'Hello 123' would encode to 'Ifmmp 234', as each character would shift by 1. + Using ``offset=1``, 'Hello 123' would encode to 'Ifmmp 234', as each character would shift by 1. Shifts for digits 0-9 only work if the offset is less than 10, if the offset is equal to or greather than 10, any numeric values will not be shifted. """ @@ -30,7 +30,7 @@ def __init__(self, *, caesar_offset: int, append_description: bool = False) -> N a description of the cipher, and an example encoded using the cipher. Raises: - ValueError: If `caesar_offset` is not in the range -25 to 25 inclusive. + ValueError: If ``caesar_offset`` is not in the range -25 to 25 inclusive. """ if caesar_offset < -25 or caesar_offset > 25: raise ValueError("caesar offset value invalid, must be between -25 and 25 inclusive.") diff --git a/pyrit/prompt_converter/character_space_converter.py b/pyrit/prompt_converter/character_space_converter.py index 16b4b803ac..b67fa11a24 100644 --- a/pyrit/prompt_converter/character_space_converter.py +++ b/pyrit/prompt_converter/character_space_converter.py @@ -12,7 +12,7 @@ class CharacterSpaceConverter(PromptConverter): Spaces out the input prompt and removes specified punctuations. For more information on the bypass strategy, refer to: - https://www.robustintelligence.com/blog-posts/bypassing-metas-llama-classifier-a-simple-jailbreak + https://www.robustintelligence.com/blog-posts/bypassing-metas-llama-classifier-a-simple-jailbreak """ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: diff --git a/pyrit/prompt_converter/codechameleon_converter.py b/pyrit/prompt_converter/codechameleon_converter.py index 1ebe666651..0c80d61a22 100644 --- a/pyrit/prompt_converter/codechameleon_converter.py +++ b/pyrit/prompt_converter/codechameleon_converter.py @@ -64,8 +64,8 @@ def __init__( Functions will take the source code of the function. Raises: - ValueError: If `encrypt_type` is not valid or if `encrypt_function` or `decrypt_function` are not provided - when `encrypt_type` is "custom". + ValueError: If ``encrypt_type`` is not valid or if ``encrypt_function`` or ``decrypt_function`` are not + provided when ``encrypt_type`` is "custom". """ match encrypt_type: case "custom": diff --git a/pyrit/prompt_converter/denylist_converter.py b/pyrit/prompt_converter/denylist_converter.py index 3d648c5e5e..4f9e90b22e 100644 --- a/pyrit/prompt_converter/denylist_converter.py +++ b/pyrit/prompt_converter/denylist_converter.py @@ -15,7 +15,9 @@ class DenylistConverter(LLMGenericTextConverter): """ - Replaces forbidden words or phrases in a prompt with synonyms. + Replaces forbidden words or phrases in a prompt with synonyms using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__( diff --git a/pyrit/prompt_converter/diacritic_converter.py b/pyrit/prompt_converter/diacritic_converter.py index a19d48238e..39362d3689 100644 --- a/pyrit/prompt_converter/diacritic_converter.py +++ b/pyrit/prompt_converter/diacritic_converter.py @@ -21,14 +21,16 @@ def __init__(self, target_chars: str = "aeiou", accent: str = "acute"): Args: target_chars (str): Characters to apply the diacritic to. Defaults to "aeiou". - accent (str): Type of diacritic to apply (default is 'acute'). Available options are:\n - - `acute`: \u0301\n - - `grave`: \u0300\n - - `tilde`: \u0303\n - - `umlaut`: \u0308 + accent (str): Type of diacritic to apply (default is 'acute'). + + Available options are: + - `acute`: \u0301 + - `grave`: \u0300 + - `tilde`: \u0303 + - `umlaut`: \u0308 Raises: - ValueError: If `target_chars` is empty or if the specified accent is not recognized. + ValueError: If ``target_chars`` is empty or if the specified accent is not recognized. """ super().__init__() diff --git a/pyrit/prompt_converter/emoji_converter.py b/pyrit/prompt_converter/emoji_converter.py index 9d139e146d..c210ab9df3 100644 --- a/pyrit/prompt_converter/emoji_converter.py +++ b/pyrit/prompt_converter/emoji_converter.py @@ -13,6 +13,7 @@ class EmojiConverter(WordLevelConverter): Inspired by https://github.com/BASI-LABS/parseltongue/blob/main/src/utils.ts """ + #: Dictionary mapping letters to their corresponding emojis. emoji_dict = { "a": ["πŸ…", "πŸ…°οΈ", "πŸ„°"], "b": ["πŸ…‘", "πŸ…±οΈ", "πŸ„±"], diff --git a/pyrit/prompt_converter/insert_punctuation_converter.py b/pyrit/prompt_converter/insert_punctuation_converter.py index f6e33a012f..ad765e1622 100644 --- a/pyrit/prompt_converter/insert_punctuation_converter.py +++ b/pyrit/prompt_converter/insert_punctuation_converter.py @@ -19,6 +19,7 @@ class InsertPunctuationConverter(PromptConverter): "a1b2c3" is a word; "a1 2" are 2 words; "a1,b,3" are 3 words. """ + #: Common punctuation characters. Used if no punctuation list is provided. default_punctuation_list = [",", ".", "!", "?", ":", ";", "-"] def __init__(self, word_swap_ratio: float = 0.2, between_words: bool = True) -> None: @@ -31,7 +32,7 @@ def __init__(self, word_swap_ratio: float = 0.2, between_words: bool = True) -> If False, insert punctuation within words. Defaults to True. Raises: - ValueError: If word_swap_ratio is not between 0 and 1. + ValueError: If ``word_swap_ratio`` is not between 0 and 1. """ # Swap ratio cannot be 0 or larger than 1 if not 0 < word_swap_ratio <= 1: diff --git a/pyrit/prompt_converter/malicious_question_generator_converter.py b/pyrit/prompt_converter/malicious_question_generator_converter.py index cb25658dc0..bda9851e7b 100644 --- a/pyrit/prompt_converter/malicious_question_generator_converter.py +++ b/pyrit/prompt_converter/malicious_question_generator_converter.py @@ -14,7 +14,9 @@ class MaliciousQuestionGeneratorConverter(LLMGenericTextConverter): """ - Generates malicious questions using an LLM via an existing PromptTarget (like Azure OpenAI). + Generates malicious questions using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): diff --git a/pyrit/prompt_converter/math_prompt_converter.py b/pyrit/prompt_converter/math_prompt_converter.py index 7e667bc754..689fba8e14 100644 --- a/pyrit/prompt_converter/math_prompt_converter.py +++ b/pyrit/prompt_converter/math_prompt_converter.py @@ -14,8 +14,9 @@ class MathPromptConverter(LLMGenericTextConverter): """ - Converts natural language instructions into symbolic mathematics problems using - an LLM via an existing PromptTarget (like Azure OpenAI or other supported backends). + Converts natural language instructions into symbolic mathematics problems using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: SeedPrompt = None): diff --git a/pyrit/prompt_converter/noise_converter.py b/pyrit/prompt_converter/noise_converter.py index 2f953cb704..c6531a39d7 100644 --- a/pyrit/prompt_converter/noise_converter.py +++ b/pyrit/prompt_converter/noise_converter.py @@ -16,7 +16,9 @@ class NoiseConverter(LLMGenericTextConverter): """ - Injects noise errors into a conversation. + Injects noise errors into a conversation using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__( @@ -31,7 +33,7 @@ def __init__( Initializes the converter with the specified parameters. Args: - converter_target (PromptChatTarget): The endpoint that converts the prompt + converter_target (PromptChatTarget): The endpoint that converts the prompt. noise (str): The noise to inject. Grammar error, delete random letter, insert random space, etc. number_errors (int): The number of errors to inject. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. diff --git a/pyrit/prompt_converter/pdf_converter.py b/pyrit/prompt_converter/pdf_converter.py index 477e46d6f9..028025cba1 100644 --- a/pyrit/prompt_converter/pdf_converter.py +++ b/pyrit/prompt_converter/pdf_converter.py @@ -19,12 +19,14 @@ class PDFConverter(PromptConverter): Converts a text prompt into a PDF file. Supports various modes: - 1. Template-Based Generation: If a `SeedPrompt` is provided, dynamic data can be injected into the - template using the `SeedPrompt.render_template_value` method, and the resulting content is converted to a PDF.\n - 2. Direct Text-Based Generation: If no template is provided, the raw string prompt is converted directly - into a PDF.\n - 3. Modify Existing PDFs (Overlay approach): Enables injecting text into existing PDFs at specified - coordinates, merging a new "overlay layer" onto the original PDF. + - Template-Based Generation: + If a ``SeedPrompt`` is provided, dynamic data can be injected into the template using + the ``SeedPrompt.render_template_value`` method, and the resulting content is converted to a PDF. + - Direct Text-Based Generation: + If no template is provided, the raw string prompt is converted directly into a PDF. + - Modify Existing PDFs (Overlay approach): + Enables injecting text into existing PDFs at specified coordinates, merging a new "overlay layer" + onto the original PDF. """ def __init__( @@ -44,7 +46,7 @@ def __init__( Initializes the converter with the specified parameters. Args: - prompt_template (Optional[SeedPrompt], optional): A `SeedPrompt` object representing a template. + prompt_template (Optional[SeedPrompt], optional): A ``SeedPrompt`` object representing a template. font_type (str): Font type for the PDF. Defaults to "Helvetica". font_size (int): Font size for the PDF. Defaults to 12. font_color (tuple): Font color for the PDF in RGB format. Defaults to (255, 255, 255). @@ -102,7 +104,7 @@ async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text Args: prompt (str): The prompt to be embedded in the PDF. - input_type (PromptDataType): The type of input data (default: "text"). + input_type (PromptDataType): The type of input data. Returns: ConverterResult: The result containing the full file path to the generated PDF. diff --git a/pyrit/prompt_converter/persuasion_converter.py b/pyrit/prompt_converter/persuasion_converter.py index f417dad6b0..bc6775f8b1 100644 --- a/pyrit/prompt_converter/persuasion_converter.py +++ b/pyrit/prompt_converter/persuasion_converter.py @@ -31,11 +31,16 @@ class PersuasionConverter(PromptConverter): Based on https://arxiv.org/abs/2401.06373 by Zeng et al. Supported persuasion techniques: - - authority_endorsement: Citing authoritative sources in support of a claim. - - evidence_based: Using empirical data, statistics, and facts to support a claim or decision. - - expert_endorsement: Citing domain experts in support of a claim. - - logical_appeal: Using logic or reasoning to support a claim. - - misrepresentation: Presenting oneself or an issue in a way that's not genuine or true. + - "authority_endorsement": + Citing authoritative sources in support of a claim. + - "evidence_based": + Using empirical data, statistics, and facts to support a claim or decision. + - "expert_endorsement": + Citing domain experts in support of a claim. + - "logical_appeal": + Using logic or reasoning to support a claim. + - "misrepresentation": + Presenting oneself or an issue in a way that's not genuine or true. """ def __init__(self, *, converter_target: PromptChatTarget, persuasion_technique: str): diff --git a/pyrit/prompt_converter/prompt_converter.py b/pyrit/prompt_converter/prompt_converter.py index 491104540a..49105e53b7 100644 --- a/pyrit/prompt_converter/prompt_converter.py +++ b/pyrit/prompt_converter/prompt_converter.py @@ -16,7 +16,7 @@ class ConverterResult: #: The converted text output. This is the main result of the conversion. output_text: str - #: The data type of the converted output. Indicates the format/type of the `output_text`. + #: The data type of the converted output. Indicates the format/type of the ``output_text``. output_type: PromptDataType def __str__(self): diff --git a/pyrit/prompt_converter/qr_code_converter.py b/pyrit/prompt_converter/qr_code_converter.py index 23b7fc5f1a..8a38f9b16d 100644 --- a/pyrit/prompt_converter/qr_code_converter.py +++ b/pyrit/prompt_converter/qr_code_converter.py @@ -40,14 +40,14 @@ def __init__( light_color (tuple, Optional): Sets color of light modules, using RGB values. Defaults to white: (255, 255, 255). data_dark_color (tuple, Optional): Sets color of dark data modules (the modules that actually - stores the data), using RGB values. Defaults to dark_color. + stores the data), using RGB values. Defaults to ``dark_color``. data_light_color (tuple, Optional): Sets color of light data modules, using RGB values. Defaults to light_color. finder_dark_color (tuple, Optional): Sets dark module color of finder patterns (squares located in - three corners), using RGB values. Defaults to dark_color. + three corners), using RGB values. Defaults to ``dark_color``. finder_light_color (tuple, Optional): Sets light module color of finder patterns, using RGB values. Defaults to light_color. - border_color (tuple, Optional): Sets color of border, using RGB values. Defaults to light_color. + border_color (tuple, Optional): Sets color of border, using RGB values. Defaults to ``light_color``. """ self._scale = scale self._border = border diff --git a/pyrit/prompt_converter/suffix_append_converter.py b/pyrit/prompt_converter/suffix_append_converter.py index ffd481e3d3..30183c4c81 100644 --- a/pyrit/prompt_converter/suffix_append_converter.py +++ b/pyrit/prompt_converter/suffix_append_converter.py @@ -8,9 +8,9 @@ class SuffixAppendConverter(PromptConverter): """ Appends a specified suffix to the prompt. - E.g. with a suffix `!!!`, it converts a prompt of `test` to `test !!!`. - See `PyRIT/pyrit/auxiliary_attacks/gcg` for adversarial suffix generation. + + See https://github.com/Azure/PyRIT/tree/main/pyrit/auxiliary_attacks/gcg for adversarial suffix generation. """ def __init__(self, *, suffix: str): diff --git a/pyrit/prompt_converter/superscript_converter.py b/pyrit/prompt_converter/superscript_converter.py index 7d76520267..5ee8bea15b 100644 --- a/pyrit/prompt_converter/superscript_converter.py +++ b/pyrit/prompt_converter/superscript_converter.py @@ -8,8 +8,7 @@ class SuperscriptConverter(WordLevelConverter): """ Converts text to superscript. - Note: - This converter leaves characters that do not have a superscript equivalent unchanged. + This converter leaves characters that do not have a superscript equivalent unchanged. """ _superscript_map = { diff --git a/pyrit/prompt_converter/template_segment_converter.py b/pyrit/prompt_converter/template_segment_converter.py index 5343f1db1a..a8bebc0577 100644 --- a/pyrit/prompt_converter/template_segment_converter.py +++ b/pyrit/prompt_converter/template_segment_converter.py @@ -31,7 +31,7 @@ def __init__( Args: prompt_template (SeedPrompt, Optional): The prompt template for the conversion. Must have two or more - parameters. If not provided, uses the default tom_and_jerry.yaml template. + parameters. If not provided, uses the default ``tom_and_jerry.yaml`` template. Raises: ValueError: If the template has fewer than two parameters or if any parameter is missing in the template. diff --git a/pyrit/prompt_converter/tense_converter.py b/pyrit/prompt_converter/tense_converter.py index 3ef026d32f..81efd12c90 100644 --- a/pyrit/prompt_converter/tense_converter.py +++ b/pyrit/prompt_converter/tense_converter.py @@ -14,7 +14,9 @@ class TenseConverter(LLMGenericTextConverter): """ - Converts a conversation to a different tense. + Converts a conversation to a different tense using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__(self, *, converter_target: PromptChatTarget, tense: str, prompt_template: SeedPrompt = None): diff --git a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py index 57f143014c..9801be31cf 100644 --- a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py @@ -14,8 +14,8 @@ class SneakyBitsSmugglerConverter(SmugglerConverter): Encodes and decodes text using a bit-level approach. Uses two invisible Unicode characters: - - `zero_char` (default: U+2062) to represent binary 0. - - `one_char` (default: U+2064) to represent binary 1. + - ``zero_char`` (default: U+2062) to represent binary 0. + - ``one_char`` (default: U+2064) to represent binary 1. Replicates functionality detailed in: - https://embracethered.com/blog/posts/2025/sneaky-bits-and-ascii-smuggler/ @@ -32,11 +32,11 @@ def __init__( Args: action (Literal["encode", "decode"]): The action to perform. - zero_char (Optional[str]): Character to represent binary 0 in sneaky_bits mode (default: U+2062). - one_char (Optional[str]): Character to represent binary 1 in sneaky_bits mode (default: U+2064). + zero_char (Optional[str]): Character to represent binary 0 in ``sneaky_bits`` mode (default: U+2062). + one_char (Optional[str]): Character to represent binary 1 in ``sneaky_bits`` mode (default: U+2064). Raises: - ValueError: If an unsupported action or encoding_mode is provided. + ValueError: If an unsupported action or ``encoding_mode`` is provided. """ super().__init__(action=action) self.zero_char = zero_char if zero_char is not None else "\u2062" # Invisible Times @@ -46,9 +46,8 @@ def encode_message(self, message: str) -> Tuple[str, str]: """ Encodes the message using Sneaky Bits mode. - The message is first converted to its UTF-8 byte sequence. Then each byte is represented - as 8 bits, with each bit replaced by an invisible character (self.zero_char for 0 and - self.one_char for 1). + The message is first converted to its UTF-8 byte sequence. Then each byte is represented as 8 bits, + with each bit replaced by an invisible character (``self.zero_char`` for 0 and ``self.one_char`` for 1). Args: message (str): The message to encode. @@ -75,9 +74,8 @@ def decode_message(self, message: str) -> str: """ Decodes the message encoded using Sneaky Bits mode. - The method filters out only the valid invisible characters (self.zero_char and self.one_char), - groups them into 8-bit chunks, reconstructs each byte, and finally decodes the byte sequence - using UTF-8. + The method filters out only the valid invisible characters (``self.zero_char`` and ``self.one_char``), + groups them into 8-bit chunks, reconstructs each byte, and finally decodes the byte sequence using UTF-8. Args: message (str): The message encoded with Sneaky Bits. diff --git a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py index d9f68745cf..a947ab2e25 100644 --- a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py @@ -17,7 +17,7 @@ class VariationSelectorSmugglerConverter(SmugglerConverter): - Bytes 0x00-0x0F are mapped to U+FE00-U+FE0F. - Bytes 0x10-0xFF are mapped to U+E0100-U+E01EF. - If 'embed_in_base' is True, the payload is concatenated with a base character + If ``embed_in_base`` is True, the payload is concatenated with a base character (default: 😊); otherwise, a space separator is inserted. Replicates functionality detailed in: @@ -39,13 +39,13 @@ def __init__( Args: action (Literal["encode", "decode"]): The action to perform. - base_char_utf8 (Optional[str]): Base character for variation_selector_smuggler mode (default: 😊). + base_char_utf8 (Optional[str]): Base character for ``variation_selector_smuggler`` mode (default: 😊). embed_in_base (bool): If True, the hidden payload is embedded directly into the base character. If False, a visible separator (space) is inserted between the base and payload. Default is True. Raises: - ValueError: If an unsupported action or encoding_mode is provided. + ValueError: If an unsupported action or ``encoding_mode`` is provided. """ super().__init__(action=action) self.utf8_base_char = base_char_utf8 if base_char_utf8 is not None else "😊" @@ -118,7 +118,7 @@ def decode_message(self, message: str) -> str: # Extension of Paul Butler's method def encode_visible_hidden(self, visible: str, hidden: str) -> Tuple[str, str]: """ - Combines visible text with hidden text by encoding the hidden text using variation_selector_smuggler mode. + Combines visible text with hidden text by encoding the hidden text using ``variation_selector_smuggler`` mode. The hidden payload is generated as a composite using the current embedding setting and then appended to the visible text. diff --git a/pyrit/prompt_converter/tone_converter.py b/pyrit/prompt_converter/tone_converter.py index 7b1f023d9f..733bebc79d 100644 --- a/pyrit/prompt_converter/tone_converter.py +++ b/pyrit/prompt_converter/tone_converter.py @@ -14,7 +14,9 @@ class ToneConverter(LLMGenericTextConverter): """ - Converts a conversation to a different tone. + Converts a conversation to a different tone using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). """ def __init__(self, *, converter_target: PromptChatTarget, tone: str, prompt_template: SeedPrompt = None): diff --git a/pyrit/prompt_converter/toxic_sentence_generator_converter.py b/pyrit/prompt_converter/toxic_sentence_generator_converter.py index e8c5462d5b..f50225efff 100644 --- a/pyrit/prompt_converter/toxic_sentence_generator_converter.py +++ b/pyrit/prompt_converter/toxic_sentence_generator_converter.py @@ -19,7 +19,9 @@ class ToxicSentenceGeneratorConverter(LLMGenericTextConverter): """ - Generates toxic sentence starters using an LLM via an existing PromptTarget. + Generates toxic sentence starters using an LLM. + + An existing ``PromptChatTarget`` is used to perform the conversion (like Azure OpenAI). Based on Project Moonshot's attack module that generates toxic sentences to test LLM safety guardrails: @@ -30,10 +32,10 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: Optio """ Initializes the converter with a specific target and template. - Parameters: + Args: converter_target (PromptChatTarget): The endpoint that converts the prompt. prompt_template (SeedPrompt): The seed prompt template to use. If not provided, - defaults to the toxic_sentence_generator.yaml. + defaults to the ``toxic_sentence_generator.yaml``. """ # set to default strategy if not provided diff --git a/pyrit/prompt_converter/translation_converter.py b/pyrit/prompt_converter/translation_converter.py index 6c50139ed9..64ca06e226 100644 --- a/pyrit/prompt_converter/translation_converter.py +++ b/pyrit/prompt_converter/translation_converter.py @@ -45,7 +45,7 @@ def __init__( Initializes the converter with the target chat support, language, and optional prompt template. Args: - converter_target (PromptChatTarget): The target chat support for the conversion which will translate + converter_target (PromptChatTarget): The target chat support for the conversion which will translate. language (str): The language for the conversion. E.g. Spanish, French, leetspeak, etc. prompt_template (SeedPrompt, Optional): The prompt template for the conversion. max_retries (int): Maximum number of retries for the conversion. diff --git a/pyrit/prompt_converter/unicode_confusable_converter.py b/pyrit/prompt_converter/unicode_confusable_converter.py index 387c75f8d4..b34b560df3 100644 --- a/pyrit/prompt_converter/unicode_confusable_converter.py +++ b/pyrit/prompt_converter/unicode_confusable_converter.py @@ -32,13 +32,16 @@ def __init__( Args: source_package (Literal["confusable_homoglyphs", "confusables"]): - The package to use for homoglyph generation. Can be either "confusable_homoglyphs" - which can be found here: https://pypi.org/project/confusable-homoglyphs/ or "confusables" which can be - found here: https://pypi.org/project/confusables/. "Confusable_homoglyphs" is used by default as it is - more regularly maintained and up to date with the latest Unicode-provided confusables found here: - https://www.unicode.org/Public/security/latest/confusables.txt. However, "confusables" - provides additional methods of matching characters (not just Unicode list), so each character - has more possible substitutions. + The package to use for homoglyph generation. + + Can be either: + - "confusable_homoglyphs" (https://pypi.org/project/confusable-homoglyphs/): + Used by default as it is more regularly maintained and up to date with the latest + Unicode-provided confusables found here: + https://www.unicode.org/Public/security/latest/confusables.txt + - "confusables" (https://pypi.org/project/confusables/): + Provides additional methods of matching characters (not just Unicode list), + so each character has more possible substitutions. deterministic (bool): This argument is for unittesting only. """ if source_package not in ["confusable_homoglyphs", "confusables"]: diff --git a/pyrit/prompt_converter/word_level_converter.py b/pyrit/prompt_converter/word_level_converter.py index 52dc97b16d..2644bdcd85 100644 --- a/pyrit/prompt_converter/word_level_converter.py +++ b/pyrit/prompt_converter/word_level_converter.py @@ -98,7 +98,7 @@ async def convert_word_async(self, word: str) -> str: pass def validate_input(self, prompt: str) -> None: - """Validates the input before processing (can be overridden by subclasses)""" + """Validates the input before processing (can be overridden by subclasses).""" pass def join_words(self, words: list[str]) -> str: diff --git a/pyrit/prompt_converter/zero_width_converter.py b/pyrit/prompt_converter/zero_width_converter.py index e892bb954f..0663add1dd 100644 --- a/pyrit/prompt_converter/zero_width_converter.py +++ b/pyrit/prompt_converter/zero_width_converter.py @@ -10,6 +10,7 @@ class ZeroWidthConverter(PromptConverter): Injects zero-width spaces between characters in the provided text to bypass content safety mechanisms. """ + #: Constant for zero-width space character. ZERO_WIDTH_SPACE = "\u200b" def input_supported(self, input_type: PromptDataType) -> bool: From af0316a16862399960ea1b1648ac5bed39263242 Mon Sep 17 00:00:00 2001 From: Paulina Kalicka <71526180+paulinek13@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:24:53 +0200 Subject: [PATCH 8/8] pre-commit --- pyrit/prompt_converter/binary_converter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyrit/prompt_converter/binary_converter.py b/pyrit/prompt_converter/binary_converter.py index 475d764eed..d681a86943 100644 --- a/pyrit/prompt_converter/binary_converter.py +++ b/pyrit/prompt_converter/binary_converter.py @@ -17,6 +17,7 @@ class BinaryConverter(WordLevelConverter): class BitsPerChar(Enum): """The number of bits per character for binary conversion.""" + BITS_8 = 8 #: 8 bits per character, suitable for ASCII characters. BITS_16 = 16 #: 16 bits per character, suitable for Unicode characters. BITS_32 = 32 #: 32 bits per character, suitable for extended Unicode characters.