enkryptai-sdk 0.1.6__py3-none-any.whl → 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- enkryptai_sdk/__init__.py +16 -4
- enkryptai_sdk/ai_proxy.py +70 -0
- enkryptai_sdk/base.py +36 -0
- enkryptai_sdk/datasets.py +142 -0
- enkryptai_sdk/deployments.py +121 -0
- enkryptai_sdk/dto/__init__.py +64 -0
- enkryptai_sdk/dto/ai_proxy.py +325 -0
- enkryptai_sdk/dto/base.py +70 -0
- enkryptai_sdk/dto/datasets.py +152 -0
- enkryptai_sdk/dto/deployments.py +334 -0
- enkryptai_sdk/dto/guardrails.py +1261 -0
- enkryptai_sdk/dto/models.py +199 -46
- enkryptai_sdk/dto/red_team.py +279 -62
- enkryptai_sdk/guardrails.py +219 -70
- enkryptai_sdk/guardrails_old.py +195 -0
- enkryptai_sdk/models.py +118 -52
- enkryptai_sdk/red_team.py +154 -60
- enkryptai_sdk-0.1.7.dist-info/METADATA +1205 -0
- enkryptai_sdk-0.1.7.dist-info/RECORD +25 -0
- {enkryptai_sdk-0.1.6.dist-info → enkryptai_sdk-0.1.7.dist-info}/WHEEL +1 -1
- enkryptai_sdk-0.1.6.dist-info/METADATA +0 -301
- enkryptai_sdk-0.1.6.dist-info/RECORD +0 -15
- {enkryptai_sdk-0.1.6.dist-info → enkryptai_sdk-0.1.7.dist-info/licenses}/LICENSE +0 -0
- {enkryptai_sdk-0.1.6.dist-info → enkryptai_sdk-0.1.7.dist-info}/top_level.txt +0 -0
enkryptai_sdk/dto/red_team.py
CHANGED
|
@@ -1,85 +1,219 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from .base import BaseDTO
|
|
3
|
+
from typing import Dict, List, Optional, Any
|
|
1
4
|
from dataclasses import dataclass, field, asdict
|
|
2
|
-
from typing import Dict, List, Optional
|
|
3
|
-
import json
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
@dataclass
|
|
7
|
-
class
|
|
8
|
-
|
|
8
|
+
class RedteamHealthResponse(BaseDTO):
|
|
9
|
+
status: str
|
|
10
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RedteamHealthResponse":
|
|
14
|
+
return cls(
|
|
15
|
+
status=data.get("status", "")
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
19
|
+
return {
|
|
20
|
+
"status": self.status
|
|
21
|
+
}
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class RedTeamResponse(BaseDTO):
|
|
26
|
+
task_id: Optional[str] = None
|
|
27
|
+
message: Optional[str] = None
|
|
28
|
+
data: Optional[Dict[str, Any]] = None
|
|
29
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
12
30
|
|
|
13
31
|
@classmethod
|
|
14
|
-
def from_dict(cls, data:
|
|
15
|
-
return cls(
|
|
32
|
+
def from_dict(cls, data: Dict) -> "RedTeamResponse":
|
|
33
|
+
return cls(
|
|
34
|
+
task_id=data.get("task_id"),
|
|
35
|
+
message=data.get("message"),
|
|
36
|
+
data=data.get("data"),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def to_dict(self) -> Dict:
|
|
40
|
+
return super().to_dict()
|
|
16
41
|
|
|
17
42
|
|
|
18
43
|
@dataclass
|
|
19
|
-
class RedTeamTaskStatus:
|
|
44
|
+
class RedTeamTaskStatus(BaseDTO):
|
|
20
45
|
status: Optional[str] = None
|
|
21
46
|
|
|
22
|
-
def to_dict(self) -> dict:
|
|
23
|
-
return asdict(self)
|
|
24
|
-
|
|
25
|
-
@classmethod
|
|
26
|
-
def from_dict(cls, data: dict):
|
|
27
|
-
return cls(**data)
|
|
28
|
-
|
|
29
47
|
|
|
30
48
|
@dataclass
|
|
31
|
-
class RedTeamTaskDetails:
|
|
49
|
+
class RedTeamTaskDetails(BaseDTO):
|
|
32
50
|
created_at: Optional[str] = None
|
|
33
51
|
model_name: Optional[str] = None
|
|
34
52
|
status: Optional[str] = None
|
|
53
|
+
test_name: Optional[str] = None
|
|
35
54
|
task_id: Optional[str] = None
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class StatisticItem(BaseDTO):
|
|
59
|
+
success_percentage: float
|
|
60
|
+
total: int
|
|
61
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
39
62
|
|
|
40
63
|
@classmethod
|
|
41
|
-
def from_dict(cls, data:
|
|
42
|
-
return cls(
|
|
64
|
+
def from_dict(cls, data: Dict) -> "StatisticItem":
|
|
65
|
+
return cls(
|
|
66
|
+
success_percentage=data.get("success(%)", 0.0), total=data.get("total", 0)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def to_dict(self) -> Dict:
|
|
70
|
+
d = super().to_dict()
|
|
71
|
+
# Special handling for success percentage key
|
|
72
|
+
d["success(%)"] = d.pop("success_percentage")
|
|
73
|
+
return d
|
|
43
74
|
|
|
44
75
|
|
|
45
76
|
@dataclass
|
|
46
|
-
class
|
|
47
|
-
test_date:
|
|
48
|
-
test_name:
|
|
49
|
-
dataset_name:
|
|
50
|
-
model_name:
|
|
51
|
-
model_endpoint_url:
|
|
52
|
-
model_source:
|
|
53
|
-
model_provider:
|
|
54
|
-
risk_score:
|
|
55
|
-
test_type:
|
|
56
|
-
nist_category:
|
|
57
|
-
scenario:
|
|
58
|
-
category:
|
|
59
|
-
attack_method:
|
|
77
|
+
class ResultSummary(BaseDTO):
|
|
78
|
+
test_date: str
|
|
79
|
+
test_name: str
|
|
80
|
+
dataset_name: str
|
|
81
|
+
model_name: str
|
|
82
|
+
model_endpoint_url: str
|
|
83
|
+
model_source: str
|
|
84
|
+
model_provider: str
|
|
85
|
+
risk_score: float
|
|
86
|
+
test_type: Dict[str, StatisticItem]
|
|
87
|
+
nist_category: Dict[str, StatisticItem]
|
|
88
|
+
scenario: Dict[str, StatisticItem]
|
|
89
|
+
category: Dict[str, StatisticItem]
|
|
90
|
+
attack_method: Dict[str, StatisticItem]
|
|
91
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
60
92
|
|
|
61
|
-
|
|
62
|
-
|
|
93
|
+
@classmethod
|
|
94
|
+
def from_dict(cls, data: Dict) -> "ResultSummary":
|
|
95
|
+
def convert_stat_list(stat_list: List[Dict]) -> Dict[str, StatisticItem]:
|
|
96
|
+
result = {}
|
|
97
|
+
for item in stat_list:
|
|
98
|
+
for key, value in item.items():
|
|
99
|
+
result[key] = StatisticItem.from_dict(value)
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
return cls(
|
|
103
|
+
test_date=data.get("test_date", ""),
|
|
104
|
+
test_name=data.get("test_name", ""),
|
|
105
|
+
dataset_name=data.get("dataset_name", ""),
|
|
106
|
+
model_name=data.get("model_name", ""),
|
|
107
|
+
model_endpoint_url=data.get("model_endpoint_url", ""),
|
|
108
|
+
model_source=data.get("model_source", ""),
|
|
109
|
+
model_provider=data.get("model_provider", ""),
|
|
110
|
+
risk_score=data.get("risk_score", 0.0),
|
|
111
|
+
test_type=convert_stat_list(data.get("test_type", [])),
|
|
112
|
+
nist_category=convert_stat_list(data.get("nist_category", [])),
|
|
113
|
+
scenario=convert_stat_list(data.get("scenario", [])),
|
|
114
|
+
category=convert_stat_list(data.get("category", [])),
|
|
115
|
+
attack_method=convert_stat_list(data.get("attack_method", [])),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def to_dict(self) -> Dict:
|
|
119
|
+
def convert_stat_dict(stat_dict: Dict[str, StatisticItem]) -> List[Dict]:
|
|
120
|
+
return [{key: value.to_dict()} for key, value in stat_dict.items()]
|
|
121
|
+
|
|
122
|
+
d = super().to_dict()
|
|
123
|
+
# Convert stat dictionaries to lists of dictionaries
|
|
124
|
+
d["test_type"] = convert_stat_dict(self.test_type)
|
|
125
|
+
d["nist_category"] = convert_stat_dict(self.nist_category)
|
|
126
|
+
d["scenario"] = convert_stat_dict(self.scenario)
|
|
127
|
+
d["category"] = convert_stat_dict(self.category)
|
|
128
|
+
d["attack_method"] = convert_stat_dict(self.attack_method)
|
|
129
|
+
return d
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass
|
|
133
|
+
class RedTeamResultSummary(BaseDTO):
|
|
134
|
+
summary: ResultSummary
|
|
135
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
63
136
|
|
|
64
137
|
@classmethod
|
|
65
|
-
def from_dict(cls, data:
|
|
66
|
-
|
|
138
|
+
def from_dict(cls, data: Dict) -> "RedTeamResultSummary":
|
|
139
|
+
if not data or "summary" not in data:
|
|
140
|
+
return cls(summary=ResultSummary.from_dict({}))
|
|
141
|
+
return cls(summary=ResultSummary.from_dict(data["summary"]))
|
|
142
|
+
|
|
143
|
+
def to_dict(self) -> Dict:
|
|
144
|
+
return {"summary": self.summary.to_dict()}
|
|
67
145
|
|
|
68
146
|
|
|
69
147
|
@dataclass
|
|
70
|
-
class
|
|
71
|
-
|
|
148
|
+
class TestEvalTokens(BaseDTO):
|
|
149
|
+
prompt_tokens: int
|
|
150
|
+
completion_tokens: int
|
|
151
|
+
total_tokens: int
|
|
152
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@dataclass
|
|
156
|
+
class TestResult(BaseDTO):
|
|
157
|
+
prompt: str
|
|
158
|
+
category: str
|
|
159
|
+
test_type: str
|
|
160
|
+
nist_category: str
|
|
161
|
+
source: str
|
|
162
|
+
attack_method: str
|
|
163
|
+
jailbreak_prompt: str
|
|
164
|
+
response: str
|
|
165
|
+
success: str
|
|
166
|
+
reasoning: str
|
|
167
|
+
detected_language: str
|
|
168
|
+
eval_latency: float
|
|
169
|
+
eval_tokens: TestEvalTokens
|
|
170
|
+
test_name: str
|
|
171
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
72
172
|
|
|
73
|
-
|
|
74
|
-
|
|
173
|
+
|
|
174
|
+
@dataclass
|
|
175
|
+
class RedTeamResultDetails(BaseDTO):
|
|
176
|
+
details: List[TestResult]
|
|
177
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
75
178
|
|
|
76
179
|
@classmethod
|
|
77
|
-
def from_dict(cls, data:
|
|
78
|
-
|
|
180
|
+
def from_dict(cls, data: Dict) -> "RedTeamResultDetails":
|
|
181
|
+
if not data or "details" not in data:
|
|
182
|
+
return cls(details=[])
|
|
183
|
+
|
|
184
|
+
details = []
|
|
185
|
+
for result in data["details"]:
|
|
186
|
+
# Convert eval_tokens dict to TestEvalTokens object
|
|
187
|
+
eval_tokens = TestEvalTokens(**result["eval_tokens"])
|
|
188
|
+
|
|
189
|
+
# Create a copy of the result dict and replace eval_tokens
|
|
190
|
+
result_copy = dict(result)
|
|
191
|
+
result_copy["eval_tokens"] = eval_tokens
|
|
192
|
+
|
|
193
|
+
# Create TestResult object
|
|
194
|
+
test_result = TestResult(**result_copy)
|
|
195
|
+
details.append(test_result)
|
|
196
|
+
|
|
197
|
+
return cls(details=details)
|
|
198
|
+
|
|
199
|
+
def to_dict(self) -> Dict:
|
|
200
|
+
return {
|
|
201
|
+
"details": [
|
|
202
|
+
{**result.to_dict(), "eval_tokens": result.eval_tokens.to_dict()}
|
|
203
|
+
for result in self.details
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
def to_dataframe(self) -> pd.DataFrame:
|
|
208
|
+
data = [
|
|
209
|
+
{**result.to_dict(), "eval_tokens": result.eval_tokens.to_dict()}
|
|
210
|
+
for result in self.details
|
|
211
|
+
]
|
|
212
|
+
return pd.DataFrame(data)
|
|
79
213
|
|
|
80
214
|
|
|
81
215
|
@dataclass
|
|
82
|
-
class AttackMethods:
|
|
216
|
+
class AttackMethods(BaseDTO):
|
|
83
217
|
basic: List[str] = field(default_factory=lambda: ["basic"])
|
|
84
218
|
advanced: Dict[str, List[str]] = field(
|
|
85
219
|
default_factory=lambda: {"static": ["single_shot"], "dynamic": ["iterative"]}
|
|
@@ -94,7 +228,7 @@ class AttackMethods:
|
|
|
94
228
|
|
|
95
229
|
|
|
96
230
|
@dataclass
|
|
97
|
-
class TestConfig:
|
|
231
|
+
class TestConfig(BaseDTO):
|
|
98
232
|
sample_percentage: int = 100
|
|
99
233
|
attack_methods: AttackMethods = field(default_factory=AttackMethods)
|
|
100
234
|
|
|
@@ -111,7 +245,7 @@ class TestConfig:
|
|
|
111
245
|
|
|
112
246
|
|
|
113
247
|
@dataclass
|
|
114
|
-
class RedTeamTestConfigurations:
|
|
248
|
+
class RedTeamTestConfigurations(BaseDTO):
|
|
115
249
|
# Basic tests
|
|
116
250
|
bias_test: TestConfig = field(default=None)
|
|
117
251
|
cbrn_test: TestConfig = field(default=None)
|
|
@@ -122,9 +256,7 @@ class RedTeamTestConfigurations:
|
|
|
122
256
|
adv_info_test: TestConfig = field(default=None)
|
|
123
257
|
adv_bias_test: TestConfig = field(default=None)
|
|
124
258
|
adv_command_test: TestConfig = field(default=None)
|
|
125
|
-
|
|
126
|
-
def to_dict(self) -> dict:
|
|
127
|
-
return asdict(self)
|
|
259
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
128
260
|
|
|
129
261
|
@classmethod
|
|
130
262
|
def from_dict(cls, data: dict):
|
|
@@ -132,9 +264,10 @@ class RedTeamTestConfigurations:
|
|
|
132
264
|
|
|
133
265
|
|
|
134
266
|
@dataclass
|
|
135
|
-
class TargetModelConfiguration:
|
|
267
|
+
class TargetModelConfiguration(BaseDTO):
|
|
136
268
|
testing_for: str = "LLM"
|
|
137
269
|
model_name: str = "gpt-4o-mini"
|
|
270
|
+
model_type: str = "text_2_text"
|
|
138
271
|
model_version: Optional[str] = None
|
|
139
272
|
system_prompt: str = ""
|
|
140
273
|
conversation_template: str = ""
|
|
@@ -142,20 +275,63 @@ class TargetModelConfiguration:
|
|
|
142
275
|
model_provider: str = "openai"
|
|
143
276
|
model_endpoint_url: str = "https://api.openai.com/v1/chat/completions"
|
|
144
277
|
model_api_key: Optional[str] = None
|
|
278
|
+
rate_per_min: int = 20
|
|
279
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
280
|
+
|
|
281
|
+
@classmethod
|
|
282
|
+
def from_dict(cls, data: dict):
|
|
283
|
+
return cls(**data)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@dataclass
|
|
287
|
+
class RedTeamModelHealthConfig(BaseDTO):
|
|
288
|
+
target_model_configuration: TargetModelConfiguration = field(
|
|
289
|
+
default_factory=TargetModelConfiguration
|
|
290
|
+
)
|
|
145
291
|
|
|
146
292
|
def to_dict(self) -> dict:
|
|
147
|
-
|
|
293
|
+
d = asdict(self)
|
|
294
|
+
d["target_model_configuration"] = self.target_model_configuration.to_dict()
|
|
295
|
+
return d
|
|
148
296
|
|
|
149
297
|
@classmethod
|
|
150
298
|
def from_dict(cls, data: dict):
|
|
151
|
-
|
|
299
|
+
data = data.copy()
|
|
300
|
+
target_config = TargetModelConfiguration.from_dict(
|
|
301
|
+
data.pop("target_model_configuration", {})
|
|
302
|
+
)
|
|
303
|
+
return cls(
|
|
304
|
+
# **data,
|
|
305
|
+
target_model_configuration=target_config,
|
|
306
|
+
)
|
|
152
307
|
|
|
153
308
|
|
|
154
309
|
@dataclass
|
|
155
|
-
class
|
|
310
|
+
class RedteamModelHealthResponse(BaseDTO):
|
|
311
|
+
status: str
|
|
312
|
+
error: str
|
|
313
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
314
|
+
|
|
315
|
+
@classmethod
|
|
316
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RedteamModelHealthResponse":
|
|
317
|
+
return cls(
|
|
318
|
+
status=data.get("status", ""),
|
|
319
|
+
error=data.get("error", "")
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
323
|
+
return {
|
|
324
|
+
"status": self.status,
|
|
325
|
+
"error": self.error
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@dataclass
|
|
330
|
+
class RedTeamConfig(BaseDTO):
|
|
156
331
|
test_name: str = "Test Name"
|
|
157
332
|
dataset_name: str = "standard"
|
|
158
|
-
|
|
333
|
+
model_saved_name: str = "gpt-4o-mini"
|
|
334
|
+
|
|
159
335
|
redteam_test_configurations: RedTeamTestConfigurations = field(
|
|
160
336
|
default_factory=RedTeamTestConfigurations
|
|
161
337
|
)
|
|
@@ -163,15 +339,14 @@ class RedTeamConfig:
|
|
|
163
339
|
default_factory=TargetModelConfiguration
|
|
164
340
|
)
|
|
165
341
|
|
|
342
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
343
|
+
|
|
166
344
|
def to_dict(self) -> dict:
|
|
167
345
|
d = asdict(self)
|
|
168
346
|
d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
|
|
169
347
|
d["target_model_configuration"] = self.target_model_configuration.to_dict()
|
|
170
348
|
return d
|
|
171
349
|
|
|
172
|
-
def to_json(self) -> str:
|
|
173
|
-
return json.dumps(self.to_dict())
|
|
174
|
-
|
|
175
350
|
@classmethod
|
|
176
351
|
def from_dict(cls, data: dict):
|
|
177
352
|
data = data.copy()
|
|
@@ -187,9 +362,51 @@ class RedTeamConfig:
|
|
|
187
362
|
target_model_configuration=target_config,
|
|
188
363
|
)
|
|
189
364
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
365
|
+
|
|
366
|
+
# @dataclass
|
|
367
|
+
# class RedTeamConfigWithSavedModel(BaseDTO):
|
|
368
|
+
# test_name: str = "Test Name"
|
|
369
|
+
# dataset_name: str = "standard"
|
|
370
|
+
# model_saved_name: str = "gpt-4o-mini"
|
|
371
|
+
|
|
372
|
+
# redteam_test_configurations: RedTeamTestConfigurations = field(
|
|
373
|
+
# default_factory=RedTeamTestConfigurations
|
|
374
|
+
# )
|
|
375
|
+
# target_model_configuration: TargetModelConfiguration = field(
|
|
376
|
+
# default_factory=TargetModelConfiguration
|
|
377
|
+
# )
|
|
378
|
+
|
|
379
|
+
# _extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
380
|
+
|
|
381
|
+
# def to_dict(self) -> dict:
|
|
382
|
+
# d = asdict(self)
|
|
383
|
+
# d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
|
|
384
|
+
# d["target_model_configuration"] = self.target_model_configuration.to_dict()
|
|
385
|
+
# return d
|
|
386
|
+
|
|
387
|
+
# @classmethod
|
|
388
|
+
# def from_dict(cls, data: dict):
|
|
389
|
+
# data = data.copy()
|
|
390
|
+
# test_configs = RedTeamTestConfigurations.from_dict(
|
|
391
|
+
# data.pop("redteam_test_configurations", {})
|
|
392
|
+
# )
|
|
393
|
+
# target_config = TargetModelConfiguration.from_dict(
|
|
394
|
+
# data.pop("target_model_configuration", {})
|
|
395
|
+
# )
|
|
396
|
+
# return cls(
|
|
397
|
+
# **data,
|
|
398
|
+
# redteam_test_configurations=test_configs,
|
|
399
|
+
# target_model_configuration=target_config,
|
|
400
|
+
# )
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@dataclass
|
|
404
|
+
class RedTeamTaskList(BaseDTO):
|
|
405
|
+
tasks: List[RedTeamTaskDetails] = field(default_factory=list)
|
|
406
|
+
|
|
407
|
+
def to_dataframe(self) -> pd.DataFrame:
|
|
408
|
+
data = [task for task in self.tasks]
|
|
409
|
+
return pd.DataFrame(data)
|
|
193
410
|
|
|
194
411
|
|
|
195
412
|
# Default configurations
|