Skip to content

Commit 1e5ceb6

Browse files
authored
Merge pull request Azure#8 from slister1001/restructure-red-team
Restructure RedTeamAgent
2 parents 75248c9 + 8bc8f0a commit 1e5ceb6

File tree

11 files changed

+404
-441
lines changed

11 files changed

+404
-441
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,3 @@
11
# ---------------------------------------------------------
22
# Copyright (c) Microsoft Corporation. All rights reserved.
3-
# ---------------------------------------------------------
4-
5-
from enum import Enum
6-
from ._red_team_agent import RedTeamAgent, AttackStrategy
7-
8-
class RiskCategory(str, Enum):
9-
"""Risk categories for attack objectives."""
10-
HateUnfairness = "HateUnfairness"
11-
Violence = "Violence"
12-
Sexual = "Sexual"
13-
SelfHarm = "SelfHarm"
14-
ProtectedMaterial = "ProtectedMaterial"
15-
IndirectJailbreak = "IndirectJailbreak"
16-
DirectJailbreak = "DirectJailbreak"
17-
CodeVulnerability = "CodeVulnerability"
18-
InferenceSensitiveAttributes = "InferenceSensitiveAttributes"
19-
20-
class AttackObjectiveGenerator:
21-
"""Generator for creating attack objectives.
22-
23-
:param risk_categories: List of risk categories to generate attack objectives for
24-
:type risk_categories: List[RiskCategory]
25-
"""
26-
def __init__(self, risk_categories: list[RiskCategory], num_objectives: int = 10):
27-
self.risk_categories = risk_categories
28-
self.num_objectives = num_objectives
29-
30-
__all__ = ["RedTeamAgent", "AttackStrategy", "RiskCategory", "AttackObjectiveGenerator"]
3+
# ---------------------------------------------------------

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_safety_evaluation/_safety_evaluation.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from azure.ai.evaluation.simulator import Simulator, AdversarialSimulator, AdversarialScenario, AdversarialScenarioJailbreak, IndirectAttackSimulator, DirectAttackSimulator
1919
from azure.ai.evaluation.simulator._utils import JsonLineList
2020
from azure.ai.evaluation._common.utils import validate_azure_ai_project
21-
from pyrit.prompt_target import PromptChatTarget #TODO: Remove this once eval logic for red team agent is moved to red team agent
2221
from azure.ai.evaluation._model_configurations import AzureOpenAIModelConfiguration, OpenAIModelConfiguration
2322
from azure.core.credentials import TokenCredential
2423
import json
@@ -460,7 +459,7 @@ def _check_target_is_callback(target:Callable) -> bool:
460459
def _validate_inputs(
461460
self,
462461
evaluators: List[_SafetyEvaluator],
463-
target: Union[Callable, AzureOpenAIModelConfiguration, OpenAIModelConfiguration, PromptChatTarget], #TODO: Remove this once eval logic for red team agent is moved to red team agent
462+
target: Union[Callable, AzureOpenAIModelConfiguration, OpenAIModelConfiguration],
464463
num_turns: int = 1,
465464
scenario: Optional[Union[AdversarialScenario, AdversarialScenarioJailbreak]] = None,
466465
source_text: Optional[str] = None,
@@ -478,10 +477,10 @@ def _validate_inputs(
478477
:param source_text: The source text to use as grounding document in the evaluation.
479478
:type source_text: Optional[str]
480479
'''
481-
if not callable(target) and not isinstance(target, PromptChatTarget): #TODO: Remove this once eval logic for red team agent is moved to red team agent
480+
if not callable(target):
482481
self._validate_model_config(target)
483482
#TODO: Remove self._check_target_is_callback(target)) once eval logic for red team agent is moved to red team agent
484-
elif not isinstance(target, PromptChatTarget) and not (self._check_target_returns_str(target) or self._check_target_is_callback(target)):
483+
elif self._check_target_returns_str(target):
485484
self.logger.error(f"Target function {target} does not return a string.")
486485
msg = f"Target function {target} does not return a string."
487486
raise EvaluationException(
@@ -574,7 +573,7 @@ def _calculate_defect_rate(self, evaluation_result_dict) -> EvaluationResult:
574573

575574
async def __call__(
576575
self,
577-
target: Union[Callable, AzureOpenAIModelConfiguration, OpenAIModelConfiguration, PromptChatTarget],
576+
target: Union[Callable, AzureOpenAIModelConfiguration, OpenAIModelConfiguration],
578577
evaluators: List[_SafetyEvaluator] = [],
579578
evaluation_name: Optional[str] = None,
580579
num_turns : int = 1,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# ---------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# ---------------------------------------------------------
4+
5+
from enum import Enum
6+
from typing import List
7+
from .red_team_agent import RedTeamAgent
8+
from .attack_strategy import AttackStrategy
9+
from .attack_objective_generator import AttackObjectiveGenerator, RiskCategory
10+
11+
__all__ = ["RedTeamAgent", "AttackStrategy", "RiskCategory", "AttackObjectiveGenerator"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# ---------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# ---------------------------------------------------------
4+
from enum import Enum
5+
from typing import List
6+
7+
class RiskCategory(str, Enum):
8+
"""Risk categories for attack objectives."""
9+
HateUnfairness = "hate_unfairness"
10+
Violence = "violence"
11+
Sexual = "sexual"
12+
SelfHarm = "self_harm"
13+
ProtectedMaterial = "protected_material"
14+
IndirectJailbreak = "indirect_jailbreak"
15+
DirectJailbreak = "direct_jailbreak"
16+
CodeVulnerability = "code_vulnerability"
17+
InferenceSensitiveAttributes = "inference_sensitive_attributes"
18+
19+
class AttackObjectiveGenerator:
20+
"""Generator for creating attack objectives.
21+
22+
:param risk_categories: List of risk categories to generate attack objectives for
23+
:type risk_categories: List[RiskCategory]
24+
"""
25+
def __init__(self, risk_categories: List[RiskCategory], num_objectives: int = 10):
26+
self.risk_categories = risk_categories
27+
self.num_objectives = num_objectives
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# ---------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# ---------------------------------------------------------
4+
from enum import Enum
5+
from typing import List
6+
7+
class AttackStrategy(Enum):
8+
"""Strategies for attacks."""
9+
EASY = "easy"
10+
MODERATE = "moderate"
11+
DIFFICULT = "difficult"
12+
AnsiAttack = "ansi_attack"
13+
AsciiArt = "ascii_art"
14+
AsciiSmuggler = "ascii_smuggler"
15+
Atbash = "atbash"
16+
Base64 = "base64"
17+
Binary = "binary"
18+
Caesar = "caesar"
19+
CharacterSpace = "character_space"
20+
CharSwap = "char_swap"
21+
Diacritic = "diacritic"
22+
Flip = "flip"
23+
Leetspeak = "leetspeak"
24+
MaliciousQuestion = "malicious_question"
25+
Math = "math"
26+
Morse = "morse"
27+
Persuasion = "persuasion"
28+
ROT13 = "rot13"
29+
RepeatToken = "repeat_token"
30+
SuffixAppend = "suffix_append"
31+
StringJoin = "string_join"
32+
Tense = "tense"
33+
Tone = "tone"
34+
Translation = "translation"
35+
UnicodeConfusable = "unicode_confusable"
36+
UnicodeSubstitution = "unicode_substitution"
37+
Url = "url"
38+
Variation = "variation"
39+
Baseline = "baseline"
40+
Jailbreak = "jailbreak"
41+
42+
@classmethod
43+
def Compose(cls, items: List["AttackStrategy"]) -> List["AttackStrategy"]:
44+
for item in items:
45+
if not isinstance(item, cls):
46+
raise ValueError("All items must be instances of AttackStrategy")
47+
if len(items) > 2:
48+
raise ValueError("Composed strategies must have at most 2 items")
49+
return items
+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# ---------------------------------------------------------
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# ---------------------------------------------------------
4-
54
import logging
65
from typing import Any, Callable, Dict, List, Optional
76

@@ -24,7 +23,7 @@ def __init__(
2423
"""
2524
Initializes an instance of the CallbackChatTarget class.
2625
27-
It is intended to be used with PYRIT where users define a callback function
26+
It is intended to be used with PyRIT where users define a callback function
2827
that handles sending a prompt to a target and receiving a response.
2928
The CallbackChatTarget class is a wrapper around the callback function that allows it to be used
3029
as a target in the PyRIT framework.

0 commit comments

Comments
 (0)