Source code for pyrit.prompt_converter.random_translation_converter
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import logging
import random
from pathlib import Path
from typing import List, Optional
from pyrit.common.apply_defaults import REQUIRED_VALUE, apply_defaults
from pyrit.common.path import CONVERTER_SEED_PROMPT_PATH, DATASETS_PATH
from pyrit.models import PromptDataType, SeedDataset, SeedPrompt
from pyrit.prompt_converter import ConverterResult, LLMGenericTextConverter
from pyrit.prompt_converter.text_selection_strategy import WordSelectionStrategy
from pyrit.prompt_converter.word_level_converter import WordLevelConverter
from pyrit.prompt_target import PromptChatTarget
logger = logging.getLogger(__name__)
[docs]
class RandomTranslationConverter(LLMGenericTextConverter, WordLevelConverter):
"""
Translates each individual word in a prompt to a random language using an LLM.
An existing ``PromptChatTarget`` is used to perform the translation (like Azure OpenAI).
"""
# Default language list
_DEFAULT_LANGUAGES_SEED_PROMPT_PATH = Path(DATASETS_PATH) / "lexicons" / "languages_most_spoken.yaml"
[docs]
@apply_defaults
def __init__(
self,
*,
converter_target: PromptChatTarget = REQUIRED_VALUE, # type: ignore[assignment]
system_prompt_template: Optional[SeedPrompt] = None,
languages: Optional[List[str]] = None,
word_selection_strategy: Optional[WordSelectionStrategy] = None,
):
"""
Initializes the converter with a target, an optional system prompt template, and language options.
Args:
converter_target (PromptChatTarget): The target for the prompt conversion.
Can be omitted if a default has been configured via PyRIT initialization.
system_prompt_template (Optional[SeedPrompt]): The system prompt template to use for the conversion.
If not provided, a default template will be used.
languages (Optional[List[str]]): The list of available languages to use for translation.
word_selection_strategy (Optional[WordSelectionStrategy]): Strategy for selecting which words to convert.
If None, all words will be converted.
Raises:
ValueError: If converter_target is not provided and no default has been configured.
"""
if converter_target is None:
raise ValueError(
"converter_target is required for LLM-based converters. "
"Either pass it explicitly or configure a default via PyRIT initialization "
"(e.g., initialize_pyrit_async with SimpleInitializer or AIRTInitializer)."
)
# set to default strategy if not provided
system_prompt_template = (
system_prompt_template
if system_prompt_template
else SeedPrompt.from_yaml_file(Path(CONVERTER_SEED_PROMPT_PATH) / "random_translation_converter.yaml")
)
LLMGenericTextConverter.__init__(
self,
converter_target=converter_target,
system_prompt_template=system_prompt_template,
)
WordLevelConverter.__init__(self, word_selection_strategy=word_selection_strategy, word_split_separator=None)
if not languages:
default_languages = SeedDataset.from_yaml_file(
RandomTranslationConverter._DEFAULT_LANGUAGES_SEED_PROMPT_PATH
)
self.languages = [prompt.value for prompt in default_languages.prompts]
else:
self.languages = languages
[docs]
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 prompt to be converted.
input_type (PromptDataType): The type of input data.
Returns:
ConverterResult: The result containing the converted output and its type.
"""
words = prompt.split()
selected_indices = self._word_selection_strategy.select_words(words=words)
language_word_pairs = [f"NOOP: {word}" for word in words]
# Translate only selected words
for idx in selected_indices:
language_word_pairs[idx] = await self.convert_word_async(words[idx])
llm_prompt = ""
for pair in language_word_pairs:
llm_prompt += f"{pair}\n"
return await LLMGenericTextConverter.convert_async(self, prompt=llm_prompt, input_type="text")
[docs]
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.
"""
language = random.choice(self.languages)
return f"{language}: {word}"