Skip to content

Commit

Permalink
initial commit adding changed converters
Browse files Browse the repository at this point in the history
  • Loading branch information
jbolor21 committed May 16, 2024
1 parent 1a123a2 commit 84b9347
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 6 deletions.
10 changes: 9 additions & 1 deletion pyrit/prompt_converter/ascii_art_converter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import concurrent.futures
import asyncio

from pyrit.models import PromptDataType
from pyrit.prompt_converter import PromptConverter, ConverterResult
Expand All @@ -11,8 +13,14 @@ class AsciiArtConverter(PromptConverter):

def __init__(self, font="rand"):
self.font_value = font

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converter that uses art to convert strings to ASCII art.
This can sometimes bypass LLM filters
Expand Down
11 changes: 10 additions & 1 deletion pyrit/prompt_converter/base64_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@
# Licensed under the MIT license.

import base64
import concurrent.futures
import asyncio

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


class Base64Converter(PromptConverter):
def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter that just base64 encodes the prompt
"""
Expand All @@ -19,6 +28,6 @@ def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> Conver
encoded_bytes = base64.b64encode(string_bytes)

return ConverterResult(output_text=encoded_bytes.decode("utf-8"), output_type="text")

def input_supported(self, input_type: PromptDataType) -> bool:
return input_type == "text"
12 changes: 11 additions & 1 deletion pyrit/prompt_converter/leetspeak_converter.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import random
import concurrent.futures
import asyncio

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


class LeetspeakConverter(PromptConverter):
Expand All @@ -25,6 +28,13 @@ def __init__(self) -> None:
}

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter to generate leatspeak version of a prompt.
Since there are multiple character variations, this is non-deterministic.
Expand Down
13 changes: 13 additions & 0 deletions pyrit/prompt_converter/prompt_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> Conver
str: The converted representation of the prompts.
"""
pass

@abc.abstractmethod
async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given prompts into a different representation
Args:
prompt: The prompt to be converted.
Returns:
str: The converted representation of the prompts.
"""
pass

@abc.abstractmethod
def input_supported(self, input_type: PromptDataType) -> bool:
Expand Down
10 changes: 10 additions & 0 deletions pyrit/prompt_converter/random_capital_letters_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import random
import logging
import concurrent.futures
import asyncio

from pyrit.models import PromptDataType
from pyrit.prompt_converter import PromptConverter, ConverterResult
Expand Down Expand Up @@ -64,6 +66,13 @@ def string_to_upper_case_by_percentage(self, percentage, prompt):
return "".join(output)

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter that converts the prompt to capital letters via a percentage .
"""
Expand All @@ -73,3 +82,4 @@ def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> Conver
output = self.string_to_upper_case_by_percentage(self.percentage, prompt)

return ConverterResult(output_text=output, output_type="text")

11 changes: 11 additions & 0 deletions pyrit/prompt_converter/rot13_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@
# Licensed under the MIT license.

import codecs
import concurrent.futures
import asyncio

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


class ROT13Converter(PromptConverter):

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter that just ROT13 encodes the prompts
"""
Expand All @@ -17,5 +27,6 @@ def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> Conver

return ConverterResult(output_text=codecs.encode(prompt, "rot13"), output_type="text")


def input_supported(self, input_type: PromptDataType) -> bool:
return input_type == "text"
9 changes: 9 additions & 0 deletions pyrit/prompt_converter/search_replace_converter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import concurrent.futures
import asyncio

from pyrit.models import PromptDataType
from pyrit.prompt_converter import PromptConverter, ConverterResult
Expand All @@ -18,6 +20,13 @@ def __init__(self, old_value: str, new_value: str) -> None:
self.new_value = new_value

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter that just replaces character in string with a chosen new character
Expand Down
12 changes: 11 additions & 1 deletion pyrit/prompt_converter/string_join_converter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import concurrent.futures
import asyncio

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

Expand All @@ -9,8 +12,15 @@ class StringJoinConverter(PromptConverter):

def __init__(self, *, join_value="-"):
self.join_value = join_value

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Simple converter that uses str join for letters between. E.g. with a `-`
it converts a prompt of `test` to `t-e-s-t`
Expand Down
9 changes: 9 additions & 0 deletions pyrit/prompt_converter/unicode_confusable_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Licensed under the MIT license.

import random
import concurrent.futures
import asyncio

from pyrit.models import PromptDataType
from pyrit.prompt_converter import PromptConverter, ConverterResult
Expand All @@ -14,6 +16,13 @@ def __init__(self, deterministic: bool = False):
self.deterministic = deterministic

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Converts the given prompts into things that look similar, but are actually different,
using Unicode confusables -- e.g., replacing a Latin 'a' with a Cyrillic 'а'.
Expand Down
10 changes: 10 additions & 0 deletions pyrit/prompt_converter/unicode_sub_converter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import concurrent.futures
import asyncio

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

Expand All @@ -10,6 +13,13 @@ def __init__(self, *, start_value=0xE0000):
self.startValue = start_value

def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

async def async_convert(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.
Expand Down
15 changes: 13 additions & 2 deletions pyrit/prompt_converter/variation_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import logging
import uuid
import pathlib
import concurrent.futures
import asyncio

from pyrit.models import PromptDataType
from pyrit.models import PromptRequestPiece, PromptRequestResponse
Expand Down Expand Up @@ -33,15 +35,23 @@ def __init__(self, *, converter_target: PromptChatTarget, prompt_template: Promp
prompt_template.apply_custom_metaprompt_parameters(number_iterations=str(self.number_variations))
)

@retry(stop=stop_after_attempt(2), wait=wait_fixed(1))
def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> ConverterResult:
"""
Deprecated. Use async_convert instead.
"""
pool = concurrent.futures.ThreadPoolExecutor()
return pool.submit(asyncio.run, self.async_convert(prompt=prompt, input_type=input_type)).result()

@retry(stop=stop_after_attempt(2), wait=wait_fixed(1))
async def async_convert(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")

Expand Down Expand Up @@ -69,7 +79,8 @@ def convert(self, *, prompt: str, input_type: PromptDataType = "text") -> Conver
]
)

response_msg = self.converter_target.send_prompt(prompt_request=request).request_pieces[0].converted_value
response = await self.converter_target.send_prompt_async(prompt_request=request)
response_msg = response.request_pieces[0].converted_value

try:
ret_text = json.loads(response_msg)[0]
Expand Down

0 comments on commit 84b9347

Please sign in to comment.