enkryptai-sdk 0.1.6__py3-none-any.whl → 1.0.0__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.
@@ -1,85 +1,252 @@
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 RedTeamResponse:
8
- task_id: Optional[str] = None
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
- def to_dict(self) -> dict:
11
- return asdict(self)
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: dict):
15
- return cls(**data)
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
- def to_dict(self) -> dict:
38
- return asdict(self)
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: dict):
42
- return cls(**data)
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 RedTeamResultSummary:
47
- test_date: Optional[str] = None
48
- test_name: Optional[str] = None
49
- dataset_name: Optional[str] = None
50
- model_name: Optional[str] = None
51
- model_endpoint_url: Optional[str] = None
52
- model_source: Optional[str] = None
53
- model_provider: Optional[str] = None
54
- risk_score: Optional[float] = None
55
- test_type: Optional[List] = None
56
- nist_category: Optional[List] = None
57
- scenario: Optional[List] = None
58
- category: Optional[List] = None
59
- attack_method: Optional[List] = None
77
+ class StatisticItemWithTestType(BaseDTO):
78
+ success_percentage: float
79
+ total: int
80
+ test_type: Optional[str] = None
81
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
60
82
 
61
- def to_dict(self) -> dict:
62
- return asdict(self)
83
+ @classmethod
84
+ def from_dict(cls, data: Dict) -> "StatisticItemWithTestType":
85
+ return cls(
86
+ success_percentage=data.get("success(%)", 0.0),
87
+ total=data.get("total", 0),
88
+ test_type=data.get("test_type", None),
89
+ )
90
+
91
+ def to_dict(self) -> Dict:
92
+ d = super().to_dict()
93
+ # Special handling for success percentage key
94
+ d["success(%)"] = d.pop("success_percentage")
95
+ return d
96
+
97
+
98
+ @dataclass
99
+ class ResultSummary(BaseDTO):
100
+ test_date: str
101
+ test_name: str
102
+ dataset_name: str
103
+ model_name: str
104
+ model_endpoint_url: str
105
+ model_source: str
106
+ model_provider: str
107
+ risk_score: float
108
+ test_type: Dict[str, StatisticItem]
109
+ nist_category: Dict[str, StatisticItem]
110
+ scenario: Dict[str, StatisticItem]
111
+ category: Dict[str, StatisticItemWithTestType]
112
+ attack_method: Dict[str, StatisticItem]
113
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
63
114
 
64
115
  @classmethod
65
- def from_dict(cls, data: dict):
66
- return cls(**data)
116
+ def from_dict(cls, data: Dict) -> "ResultSummary":
117
+ def convert_stat_list(stat_list: List[Dict]) -> Dict[str, StatisticItem]:
118
+ result = {}
119
+ for item in stat_list:
120
+ for key, value in item.items():
121
+ result[key] = StatisticItem.from_dict(value)
122
+ return result
123
+
124
+ def convert_stat_test_type_list(stat_list: List[Dict]) -> Dict[str, StatisticItemWithTestType]:
125
+ result = {}
126
+ for item in stat_list:
127
+ for key, value in item.items():
128
+ result[key] = StatisticItemWithTestType.from_dict(value)
129
+ return result
130
+
131
+ return cls(
132
+ test_date=data.get("test_date", ""),
133
+ test_name=data.get("test_name", ""),
134
+ dataset_name=data.get("dataset_name", ""),
135
+ model_name=data.get("model_name", ""),
136
+ model_endpoint_url=data.get("model_endpoint_url", ""),
137
+ model_source=data.get("model_source", ""),
138
+ model_provider=data.get("model_provider", ""),
139
+ risk_score=data.get("risk_score", 0.0),
140
+ test_type=convert_stat_list(data.get("test_type", [])),
141
+ nist_category=convert_stat_list(data.get("nist_category", [])),
142
+ scenario=convert_stat_list(data.get("scenario", [])),
143
+ category=convert_stat_test_type_list(data.get("category", [])),
144
+ attack_method=convert_stat_list(data.get("attack_method", [])),
145
+ )
146
+
147
+ def to_dict(self) -> Dict:
148
+ def convert_stat_dict(stat_dict: Dict[str, StatisticItem]) -> List[Dict]:
149
+ return [{key: value.to_dict()} for key, value in stat_dict.items()]
150
+
151
+ def convert_stat_test_type_dict(stat_dict: Dict[str, StatisticItemWithTestType]) -> List[Dict]:
152
+ return [{key: value.to_dict()} for key, value in stat_dict.items()]
153
+
154
+ d = super().to_dict()
155
+ # Convert stat dictionaries to lists of dictionaries
156
+ d["test_type"] = convert_stat_dict(self.test_type)
157
+ d["nist_category"] = convert_stat_dict(self.nist_category)
158
+ d["scenario"] = convert_stat_dict(self.scenario)
159
+ d["category"] = convert_stat_test_type_dict(self.category)
160
+ d["attack_method"] = convert_stat_dict(self.attack_method)
161
+ return d
67
162
 
68
163
 
69
164
  @dataclass
70
- class RedTeamResultDetails: # To Be Updated
71
- details: Optional[Dict] = None
165
+ class RedTeamResultSummary(BaseDTO):
166
+ summary: ResultSummary
167
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
72
168
 
73
- def to_dict(self) -> dict:
74
- return asdict(self)
169
+ @classmethod
170
+ def from_dict(cls, data: Dict) -> "RedTeamResultSummary":
171
+ if not data or "summary" not in data:
172
+ return cls(summary=ResultSummary.from_dict({}))
173
+ return cls(summary=ResultSummary.from_dict(data["summary"]))
174
+
175
+ def to_dict(self) -> Dict:
176
+ return {"summary": self.summary.to_dict()}
177
+
178
+
179
+ @dataclass
180
+ class TestEvalTokens(BaseDTO):
181
+ prompt_tokens: int
182
+ completion_tokens: int
183
+ total_tokens: int
184
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
185
+
186
+
187
+ @dataclass
188
+ class TestResult(BaseDTO):
189
+ prompt: str
190
+ category: str
191
+ test_type: str
192
+ nist_category: str
193
+ source: str
194
+ attack_method: str
195
+ jailbreak_prompt: str
196
+ response: str
197
+ success: str
198
+ reasoning: str
199
+ detected_language: str
200
+ eval_latency: float
201
+ eval_tokens: TestEvalTokens
202
+ test_name: str
203
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
204
+
205
+
206
+ @dataclass
207
+ class RedTeamResultDetails(BaseDTO):
208
+ details: List[TestResult]
209
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
75
210
 
76
211
  @classmethod
77
- def from_dict(cls, data: dict):
78
- return cls(**data)
212
+ def from_dict(cls, data: Dict) -> "RedTeamResultDetails":
213
+ if not data or "details" not in data:
214
+ return cls(details=[])
215
+
216
+ # details = []
217
+ # for result in data["details"]:
218
+ # Convert eval_tokens dict to TestEvalTokens object
219
+ # eval_tokens = TestEvalTokens(**result["eval_tokens"])
220
+
221
+ # Create a copy of the result dict and replace eval_tokens
222
+ # result_copy = dict(result["details"])
223
+ # result_copy["eval_tokens"] = eval_tokens
224
+
225
+ # Create TestResult object
226
+ # test_result = TestResult(**result_copy)
227
+ # details.append(test_result)
228
+
229
+ return cls(details=data["details"])
230
+
231
+ def to_dict(self) -> Dict:
232
+ return {
233
+ # "details": [
234
+ # {**result.to_dict(), "eval_tokens": result.eval_tokens.to_dict()}
235
+ # for result in self.details
236
+ # ]
237
+ "details": self.details
238
+ }
239
+
240
+ # def to_dataframe(self) -> pd.DataFrame:
241
+ # data = [
242
+ # {**result.to_dict(), "eval_tokens": result.eval_tokens.to_dict()}
243
+ # for result in self.details
244
+ # ]
245
+ # return pd.DataFrame(data)
79
246
 
80
247
 
81
248
  @dataclass
82
- class AttackMethods:
249
+ class AttackMethods(BaseDTO):
83
250
  basic: List[str] = field(default_factory=lambda: ["basic"])
84
251
  advanced: Dict[str, List[str]] = field(
85
252
  default_factory=lambda: {"static": ["single_shot"], "dynamic": ["iterative"]}
@@ -94,7 +261,7 @@ class AttackMethods:
94
261
 
95
262
 
96
263
  @dataclass
97
- class TestConfig:
264
+ class TestConfig(BaseDTO):
98
265
  sample_percentage: int = 100
99
266
  attack_methods: AttackMethods = field(default_factory=AttackMethods)
100
267
 
@@ -111,7 +278,7 @@ class TestConfig:
111
278
 
112
279
 
113
280
  @dataclass
114
- class RedTeamTestConfigurations:
281
+ class RedTeamTestConfigurations(BaseDTO):
115
282
  # Basic tests
116
283
  bias_test: TestConfig = field(default=None)
117
284
  cbrn_test: TestConfig = field(default=None)
@@ -122,9 +289,7 @@ class RedTeamTestConfigurations:
122
289
  adv_info_test: TestConfig = field(default=None)
123
290
  adv_bias_test: TestConfig = field(default=None)
124
291
  adv_command_test: TestConfig = field(default=None)
125
-
126
- def to_dict(self) -> dict:
127
- return asdict(self)
292
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
128
293
 
129
294
  @classmethod
130
295
  def from_dict(cls, data: dict):
@@ -132,9 +297,10 @@ class RedTeamTestConfigurations:
132
297
 
133
298
 
134
299
  @dataclass
135
- class TargetModelConfiguration:
300
+ class TargetModelConfiguration(BaseDTO):
136
301
  testing_for: str = "LLM"
137
302
  model_name: str = "gpt-4o-mini"
303
+ model_type: str = "text_2_text"
138
304
  model_version: Optional[str] = None
139
305
  system_prompt: str = ""
140
306
  conversation_template: str = ""
@@ -142,20 +308,62 @@ class TargetModelConfiguration:
142
308
  model_provider: str = "openai"
143
309
  model_endpoint_url: str = "https://api.openai.com/v1/chat/completions"
144
310
  model_api_key: Optional[str] = None
311
+ rate_per_min: int = 20
312
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
313
+
314
+ @classmethod
315
+ def from_dict(cls, data: dict):
316
+ return cls(**data)
317
+
318
+
319
+ @dataclass
320
+ class RedTeamModelHealthConfig(BaseDTO):
321
+ target_model_configuration: TargetModelConfiguration = field(
322
+ default_factory=TargetModelConfiguration
323
+ )
145
324
 
146
325
  def to_dict(self) -> dict:
147
- return asdict(self)
326
+ d = asdict(self)
327
+ d["target_model_configuration"] = self.target_model_configuration.to_dict()
328
+ return d
148
329
 
149
330
  @classmethod
150
331
  def from_dict(cls, data: dict):
151
- return cls(**data)
332
+ data = data.copy()
333
+ target_config = TargetModelConfiguration.from_dict(
334
+ data.pop("target_model_configuration", {})
335
+ )
336
+ return cls(
337
+ # **data,
338
+ target_model_configuration=target_config,
339
+ )
340
+
341
+
342
+ @dataclass
343
+ class RedteamModelHealthResponse(BaseDTO):
344
+ status: str
345
+ error: str
346
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
347
+
348
+ @classmethod
349
+ def from_dict(cls, data: Dict[str, Any]) -> "RedteamModelHealthResponse":
350
+ return cls(
351
+ status=data.get("status", ""),
352
+ error=data.get("error", "")
353
+ )
354
+
355
+ def to_dict(self) -> Dict[str, Any]:
356
+ return {
357
+ "status": self.status,
358
+ "error": self.error
359
+ }
152
360
 
153
361
 
154
362
  @dataclass
155
- class RedTeamConfig:
363
+ class RedTeamConfig(BaseDTO):
156
364
  test_name: str = "Test Name"
157
365
  dataset_name: str = "standard"
158
- model_name: str = "gpt-4o-mini"
366
+
159
367
  redteam_test_configurations: RedTeamTestConfigurations = field(
160
368
  default_factory=RedTeamTestConfigurations
161
369
  )
@@ -163,15 +371,14 @@ class RedTeamConfig:
163
371
  default_factory=TargetModelConfiguration
164
372
  )
165
373
 
374
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
375
+
166
376
  def to_dict(self) -> dict:
167
377
  d = asdict(self)
168
378
  d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
169
379
  d["target_model_configuration"] = self.target_model_configuration.to_dict()
170
380
  return d
171
381
 
172
- def to_json(self) -> str:
173
- return json.dumps(self.to_dict())
174
-
175
382
  @classmethod
176
383
  def from_dict(cls, data: dict):
177
384
  data = data.copy()
@@ -187,10 +394,45 @@ class RedTeamConfig:
187
394
  target_model_configuration=target_config,
188
395
  )
189
396
 
397
+
398
+ @dataclass
399
+ class RedTeamConfigWithSavedModel(BaseDTO):
400
+ test_name: str = "Test Name"
401
+ dataset_name: str = "standard"
402
+ model_saved_name: str = "gpt-4o-mini"
403
+
404
+ redteam_test_configurations: RedTeamTestConfigurations = field(
405
+ default_factory=RedTeamTestConfigurations
406
+ )
407
+
408
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
409
+
410
+ def to_dict(self) -> dict:
411
+ d = asdict(self)
412
+ d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
413
+ return d
414
+
190
415
  @classmethod
191
- def from_json(cls, json_str: str):
192
- return cls.from_dict(json.loads(json_str))
416
+ def from_dict(cls, data: dict):
417
+ data = data.copy()
418
+ test_configs = RedTeamTestConfigurations.from_dict(
419
+ data.pop("redteam_test_configurations", {})
420
+ )
421
+ return cls(
422
+ **data,
423
+ redteam_test_configurations=test_configs,
424
+ )
425
+
426
+
427
+ @dataclass
428
+ class RedTeamTaskList(BaseDTO):
429
+ tasks: List[RedTeamTaskDetails] = field(default_factory=list)
430
+
431
+ def to_dataframe(self) -> pd.DataFrame:
432
+ data = [task for task in self.tasks]
433
+ return pd.DataFrame(data)
193
434
 
194
435
 
195
436
  # Default configurations
196
437
  DEFAULT_REDTEAM_CONFIG = RedTeamConfig()
438
+ DEFAULT_REDTEAM_CONFIG_WITH_SAVED_MODEL = RedTeamConfigWithSavedModel()