Source code for pyrit.prompt_converter.braille_converter

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.


from pyrit.models import PromptDataType
from pyrit.prompt_converter import ConverterResult, PromptConverter


[docs] class BrailleConverter(PromptConverter): """ Converts text into Braille Unicode representation. This converter transforms standard text into Braille patterns using Unicode Braille characters (U+2800 to U+28FF). It supports lowercase and uppercase letters, numbers, common punctuation, and spaces. Uppercase letters are prefixed with the Braille capitalization indicator. The Braille mapping is based on the implementation from Garak: https://github.com/NVIDIA/garak/blob/main/garak/probes/encoding.py Note: This converter is useful for testing how AI systems handle Braille-encoded text, which can be used to obfuscate potentially harmful content. """
[docs] async def convert_async(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult: """ Converts the given text into Braille Unicode representation. Args: prompt (str): The text to be converted to Braille. input_type (PromptDataType, optional): Type of input data. Defaults to "text". Returns: ConverterResult: The text converted to Braille Unicode characters. Raises: ValueError: If the input type is not supported (only "text" is supported). """ if not self.input_supported(input_type): raise ValueError("Input type not supported") brail_text = self._get_braile(prompt) return ConverterResult(output_text=brail_text, output_type="text")
[docs] def input_supported(self, input_type: PromptDataType) -> bool: return input_type == "text"
[docs] def output_supported(self, output_type: PromptDataType) -> bool: return output_type == "text"
def _get_braile(self, text) -> str: """ This retrieves the braille representation of the input text. Taken from Garak https://github.com/NVIDIA/garak/blob/main/garak/probes/encoding.py """ characterUnicodes = { "a": "\u2801", "b": "\u2803", "k": "\u2805", "l": "\u2807", "c": "\u2809", "i": "\u280a", "f": "\u280b", "m": "\u280d", "s": "\u280e", "p": "\u280f", "e": "\u2811", "h": "\u2813", "o": "\u2815", "r": "\u2817", "d": "\u2819", "j": "\u281a", "g": "\u281b", "n": "\u281d", "t": "\u281e", "q": "\u281f", "u": "\u2825", "v": "\u2827", "x": "\u282d", "z": "\u2835", "w": "\u283a", "y": "\u283d", "num": "\u283c", "caps": "\u2820", ".": "\u2832", "'": "\u2804", ",": "\u2802", "-": "\u2824", "/": "\u280c", "!": "\u2816", "?": "\u2826", "$": "\u2832", ":": "\u2812", ";": "\u2830", "(": "\u2836", ")": "\u2836", "1": "\u2801", "2": "\u2803", "3": "\u2809", "4": "\u2819", "5": "\u2811", "6": "\u280b", "7": "\u281b", "8": "\u2813", "9": "\u280a", "0": "\u281a", " ": " ", } numberPunctuations = [".", ",", "-", "/", "$"] escapeCharacters = ["\n", "\r", "\t"] output = "" for char in text: is_number = False if char in escapeCharacters: output += char elif char.isupper(): if char.lower() in characterUnicodes: output += characterUnicodes["caps"] output += characterUnicodes[char.lower()] elif char in characterUnicodes: if char.isdigit(): if not is_number: is_number = True output += characterUnicodes["num"] output += characterUnicodes[char] if is_number and char not in numberPunctuations: is_number = False return output