enkryptai-sdk 1.0.25__py3-none-any.whl → 1.0.27__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/dto/__init__.py +1 -0
- enkryptai_sdk/dto/datasets.py +66 -16
- enkryptai_sdk/dto/guardrails.py +76 -0
- enkryptai_sdk/dto/models.py +48 -23
- enkryptai_sdk/dto/red_team.py +178 -120
- enkryptai_sdk/guardrails.py +79 -5
- enkryptai_sdk/red_team.py +80 -84
- {enkryptai_sdk-1.0.25.dist-info → enkryptai_sdk-1.0.27.dist-info}/METADATA +1 -1
- {enkryptai_sdk-1.0.25.dist-info → enkryptai_sdk-1.0.27.dist-info}/RECORD +12 -12
- {enkryptai_sdk-1.0.25.dist-info → enkryptai_sdk-1.0.27.dist-info}/WHEEL +1 -1
- {enkryptai_sdk-1.0.25.dist-info → enkryptai_sdk-1.0.27.dist-info}/licenses/LICENSE +0 -0
- {enkryptai_sdk-1.0.25.dist-info → enkryptai_sdk-1.0.27.dist-info}/top_level.txt +0 -0
enkryptai_sdk/dto/__init__.py
CHANGED
enkryptai_sdk/dto/datasets.py
CHANGED
|
@@ -10,32 +10,78 @@ class Tool(BaseDTO):
|
|
|
10
10
|
|
|
11
11
|
@classmethod
|
|
12
12
|
def from_dict(cls, data: Dict[str, Any]) -> "Tool":
|
|
13
|
-
return cls(
|
|
14
|
-
name=data.get("name", ""),
|
|
15
|
-
description=data.get("description", "")
|
|
16
|
-
)
|
|
13
|
+
return cls(name=data.get("name", ""), description=data.get("description", ""))
|
|
17
14
|
|
|
18
15
|
def to_dict(self) -> Dict[str, Any]:
|
|
19
|
-
return {
|
|
20
|
-
"name": self.name,
|
|
21
|
-
"description": self.description
|
|
22
|
-
}
|
|
16
|
+
return {"name": self.name, "description": self.description}
|
|
23
17
|
|
|
24
18
|
|
|
25
19
|
@dataclass
|
|
26
20
|
class DatasetConfig(BaseDTO):
|
|
27
|
-
system_description: str = None
|
|
28
|
-
dataset_name: str = None
|
|
29
|
-
policy_description: str = None
|
|
30
|
-
risk_categories: str = None
|
|
31
|
-
tools: List[Tool] = None
|
|
32
|
-
info_pdf_url: str = None
|
|
21
|
+
system_description: Optional[str] = None
|
|
22
|
+
dataset_name: Optional[str] = None
|
|
23
|
+
policy_description: Optional[str] = None
|
|
24
|
+
risk_categories: Optional[str] = None
|
|
25
|
+
tools: Optional[List[Tool]] = None
|
|
26
|
+
info_pdf_url: Optional[str] = None
|
|
33
27
|
max_prompts: int = 100
|
|
34
28
|
scenarios: int = 2
|
|
35
29
|
categories: int = 2
|
|
36
30
|
depth: int = 2
|
|
37
31
|
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
38
32
|
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_dict(cls, data: Dict[str, Any]) -> "DatasetConfig":
|
|
35
|
+
# Handle tools conversion if present
|
|
36
|
+
tools = None
|
|
37
|
+
if "tools" in data and data["tools"] is not None:
|
|
38
|
+
tools = [
|
|
39
|
+
Tool.from_dict(tool) if isinstance(tool, dict) else tool
|
|
40
|
+
for tool in data["tools"]
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
return cls(
|
|
44
|
+
system_description=data.get("system_description"),
|
|
45
|
+
dataset_name=data.get("dataset_name"),
|
|
46
|
+
policy_description=data.get("policy_description"),
|
|
47
|
+
risk_categories=data.get("risk_categories"),
|
|
48
|
+
tools=tools,
|
|
49
|
+
info_pdf_url=data.get("info_pdf_url"),
|
|
50
|
+
max_prompts=data.get("max_prompts", 100),
|
|
51
|
+
scenarios=data.get("scenarios", 2),
|
|
52
|
+
categories=data.get("categories", 2),
|
|
53
|
+
depth=data.get("depth", 2),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
57
|
+
result = {}
|
|
58
|
+
|
|
59
|
+
# Only include optional fields if they are not None
|
|
60
|
+
if self.system_description is not None:
|
|
61
|
+
result["system_description"] = self.system_description
|
|
62
|
+
if self.dataset_name is not None:
|
|
63
|
+
result["dataset_name"] = self.dataset_name
|
|
64
|
+
if self.policy_description is not None:
|
|
65
|
+
result["policy_description"] = self.policy_description
|
|
66
|
+
if self.risk_categories is not None:
|
|
67
|
+
result["risk_categories"] = self.risk_categories
|
|
68
|
+
if self.tools is not None:
|
|
69
|
+
result["tools"] = [
|
|
70
|
+
tool.to_dict() if hasattr(tool, "to_dict") else tool
|
|
71
|
+
for tool in self.tools
|
|
72
|
+
]
|
|
73
|
+
if self.info_pdf_url is not None:
|
|
74
|
+
result["info_pdf_url"] = self.info_pdf_url
|
|
75
|
+
|
|
76
|
+
# Always include fields with default values
|
|
77
|
+
result["max_prompts"] = self.max_prompts
|
|
78
|
+
result["scenarios"] = self.scenarios
|
|
79
|
+
result["categories"] = self.categories
|
|
80
|
+
result["depth"] = self.depth
|
|
81
|
+
|
|
82
|
+
result.update(self._extra_fields)
|
|
83
|
+
return result
|
|
84
|
+
|
|
39
85
|
|
|
40
86
|
@dataclass
|
|
41
87
|
class DatasetCollection(BaseDTO):
|
|
@@ -63,7 +109,9 @@ class DatasetResponse(BaseDTO):
|
|
|
63
109
|
|
|
64
110
|
@classmethod
|
|
65
111
|
def from_dict(cls, data: Dict[str, Any]) -> "DatasetResponse":
|
|
66
|
-
dataset_items = [
|
|
112
|
+
dataset_items = [
|
|
113
|
+
DatasetDataPoint.from_dict(item) for item in data.get("dataset", [])
|
|
114
|
+
]
|
|
67
115
|
return cls(dataset=dataset_items)
|
|
68
116
|
|
|
69
117
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -149,7 +197,9 @@ class DatasetTaskStatus(BaseDTO):
|
|
|
149
197
|
|
|
150
198
|
@classmethod
|
|
151
199
|
def from_dict(cls, data: Dict[str, Any]) -> "DatasetTaskStatus":
|
|
152
|
-
return cls(
|
|
200
|
+
return cls(
|
|
201
|
+
status=data.get("status", ""), dataset_name=data.get("dataset_name", "")
|
|
202
|
+
)
|
|
153
203
|
|
|
154
204
|
def to_dict(self) -> Dict[str, Any]:
|
|
155
205
|
return {"status": self.status, "dataset_name": self.dataset_name}
|
enkryptai_sdk/dto/guardrails.py
CHANGED
|
@@ -1751,3 +1751,79 @@ class GuardrailsScanUrlResponse(BaseDTO):
|
|
|
1751
1751
|
|
|
1752
1752
|
return f"URL Scan Result for {self.url}\nStatus: {status}\n{violation_str}"
|
|
1753
1753
|
|
|
1754
|
+
|
|
1755
|
+
# -------------------------------------
|
|
1756
|
+
# Guardrails Scan PDF
|
|
1757
|
+
# -------------------------------------
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
@dataclass
|
|
1761
|
+
class ScanPdfDetails(BaseDTO):
|
|
1762
|
+
total_pages: int = 0
|
|
1763
|
+
pages_with_detections: int = 0
|
|
1764
|
+
detections: List[Dict[str, Any]] = field(default_factory=list)
|
|
1765
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
1766
|
+
|
|
1767
|
+
@classmethod
|
|
1768
|
+
def from_dict(cls, data: Dict[str, Any]) -> "ScanPdfDetails":
|
|
1769
|
+
return cls(
|
|
1770
|
+
total_pages=data.get("total_pages", 0),
|
|
1771
|
+
pages_with_detections=data.get("pages_with_detections", 0),
|
|
1772
|
+
detections=data.get("detections", [])
|
|
1773
|
+
)
|
|
1774
|
+
|
|
1775
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
1776
|
+
result = {
|
|
1777
|
+
"total_pages": self.total_pages,
|
|
1778
|
+
"pages_with_detections": self.pages_with_detections,
|
|
1779
|
+
"detections": self.detections
|
|
1780
|
+
}
|
|
1781
|
+
result.update(self._extra_fields)
|
|
1782
|
+
return result
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
@dataclass
|
|
1786
|
+
class GuardrailsScanPdfResponse(BaseDTO):
|
|
1787
|
+
summary: Dict[str, int] = field(default_factory=dict)
|
|
1788
|
+
details: ScanPdfDetails = field(default_factory=ScanPdfDetails)
|
|
1789
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
1790
|
+
|
|
1791
|
+
@classmethod
|
|
1792
|
+
def from_dict(cls, data: Dict[str, Any]) -> "GuardrailsScanPdfResponse":
|
|
1793
|
+
return cls(
|
|
1794
|
+
summary=data.get("summary", {}),
|
|
1795
|
+
details=ScanPdfDetails.from_dict(data.get("details", {}))
|
|
1796
|
+
)
|
|
1797
|
+
|
|
1798
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
1799
|
+
result = {
|
|
1800
|
+
"summary": self.summary,
|
|
1801
|
+
"details": self.details.to_dict()
|
|
1802
|
+
}
|
|
1803
|
+
result.update(self._extra_fields)
|
|
1804
|
+
return result
|
|
1805
|
+
|
|
1806
|
+
def has_detections(self) -> bool:
|
|
1807
|
+
return self.details.pages_with_detections > 0 or len(self.details.detections) > 0
|
|
1808
|
+
|
|
1809
|
+
def is_safe(self) -> bool:
|
|
1810
|
+
return not self.has_detections()
|
|
1811
|
+
|
|
1812
|
+
def is_attack(self) -> bool:
|
|
1813
|
+
return self.has_detections()
|
|
1814
|
+
|
|
1815
|
+
def __str__(self) -> str:
|
|
1816
|
+
status = "UNSAFE" if self.has_detections() else "SAFE"
|
|
1817
|
+
flagged = [k for k, v in self.summary.items() if v > 0]
|
|
1818
|
+
if flagged:
|
|
1819
|
+
detection_str = f"Detections: {', '.join(flagged)}"
|
|
1820
|
+
else:
|
|
1821
|
+
detection_str = "No detections"
|
|
1822
|
+
return (
|
|
1823
|
+
f"PDF Scan Result\n"
|
|
1824
|
+
f"Status: {status}\n"
|
|
1825
|
+
f"Total Pages: {self.details.total_pages}\n"
|
|
1826
|
+
f"Pages With Detections: {self.details.pages_with_detections}\n"
|
|
1827
|
+
f"{detection_str}"
|
|
1828
|
+
)
|
|
1829
|
+
|
enkryptai_sdk/dto/models.py
CHANGED
|
@@ -43,6 +43,8 @@ class ModelProviders(str, Enum):
|
|
|
43
43
|
URL = "url"
|
|
44
44
|
ENKRYPTAI = "enkryptai"
|
|
45
45
|
BOXAI = "boxai"
|
|
46
|
+
NUTANIX = "nutanix"
|
|
47
|
+
XACTLY = "xactly"
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
@dataclass
|
|
@@ -92,11 +94,12 @@ class AuthData(BaseDTO):
|
|
|
92
94
|
@dataclass
|
|
93
95
|
class BoxAIAuthData(AuthData):
|
|
94
96
|
"""BoxAI-specific authentication data."""
|
|
97
|
+
|
|
95
98
|
boxai_client_id: Optional[str] = None
|
|
96
99
|
boxai_client_secret: Optional[str] = None
|
|
97
100
|
boxai_user_id: Optional[str] = None
|
|
98
101
|
boxai_default_file_id: Optional[str] = None
|
|
99
|
-
|
|
102
|
+
|
|
100
103
|
def __post_init__(self):
|
|
101
104
|
# Store BoxAI fields in extra_fields for backward compatibility
|
|
102
105
|
if self.boxai_client_id:
|
|
@@ -107,22 +110,32 @@ class BoxAIAuthData(AuthData):
|
|
|
107
110
|
self._extra_fields["boxai_user_id"] = self.boxai_user_id
|
|
108
111
|
if self.boxai_default_file_id:
|
|
109
112
|
self._extra_fields["boxai_default_file_id"] = self.boxai_default_file_id
|
|
110
|
-
|
|
113
|
+
|
|
111
114
|
@classmethod
|
|
112
115
|
def from_dict(cls, data: dict):
|
|
113
116
|
# Extract BoxAI fields from extra_fields if they exist
|
|
114
117
|
boxai_data = {}
|
|
115
118
|
if "_extra_fields" in data:
|
|
116
119
|
extra_fields = data["_extra_fields"]
|
|
117
|
-
for field in [
|
|
120
|
+
for field in [
|
|
121
|
+
"boxai_client_id",
|
|
122
|
+
"boxai_client_secret",
|
|
123
|
+
"boxai_user_id",
|
|
124
|
+
"boxai_default_file_id",
|
|
125
|
+
]:
|
|
118
126
|
if field in extra_fields:
|
|
119
127
|
boxai_data[field] = extra_fields[field]
|
|
120
|
-
|
|
128
|
+
|
|
121
129
|
# Merge with direct field values
|
|
122
|
-
for field in [
|
|
130
|
+
for field in [
|
|
131
|
+
"boxai_client_id",
|
|
132
|
+
"boxai_client_secret",
|
|
133
|
+
"boxai_user_id",
|
|
134
|
+
"boxai_default_file_id",
|
|
135
|
+
]:
|
|
123
136
|
if field in data:
|
|
124
137
|
boxai_data[field] = data[field]
|
|
125
|
-
|
|
138
|
+
|
|
126
139
|
# Create the instance
|
|
127
140
|
return cls(**boxai_data)
|
|
128
141
|
|
|
@@ -168,8 +181,8 @@ class OutputModality(str, Enum):
|
|
|
168
181
|
|
|
169
182
|
@dataclass
|
|
170
183
|
class ModelConfigDetails(BaseDTO):
|
|
171
|
-
model_id: str = None
|
|
172
|
-
model_source: str = None
|
|
184
|
+
model_id: Optional[str] = None
|
|
185
|
+
model_source: Optional[str] = None
|
|
173
186
|
# model_provider: str = "openai"
|
|
174
187
|
model_provider: ModelProviders = ModelProviders.OPENAI
|
|
175
188
|
model_api_value: str = ""
|
|
@@ -207,21 +220,29 @@ class ModelConfigDetails(BaseDTO):
|
|
|
207
220
|
data = data.copy()
|
|
208
221
|
|
|
209
222
|
if "custom_headers" in data:
|
|
210
|
-
data["custom_headers"] = [
|
|
223
|
+
data["custom_headers"] = [
|
|
224
|
+
CustomHeader.from_dict(h) for h in data["custom_headers"]
|
|
225
|
+
]
|
|
211
226
|
|
|
212
227
|
if "model_auth_type" in data:
|
|
213
228
|
data["model_auth_type"] = ModelAuthTypeEnum(data["model_auth_type"])
|
|
214
229
|
|
|
215
230
|
if "model_jwt_config" in data:
|
|
216
|
-
data["model_jwt_config"] = ModelJwtConfig.from_dict(
|
|
231
|
+
data["model_jwt_config"] = ModelJwtConfig.from_dict(
|
|
232
|
+
data["model_jwt_config"]
|
|
233
|
+
)
|
|
217
234
|
|
|
218
235
|
# Convert input_modalities strings to enum values
|
|
219
236
|
if "input_modalities" in data:
|
|
220
|
-
data["input_modalities"] = [
|
|
221
|
-
|
|
237
|
+
data["input_modalities"] = [
|
|
238
|
+
InputModality(m) for m in data["input_modalities"]
|
|
239
|
+
]
|
|
240
|
+
|
|
222
241
|
# Convert output_modalities strings to enum values
|
|
223
242
|
if "output_modalities" in data:
|
|
224
|
-
data["output_modalities"] = [
|
|
243
|
+
data["output_modalities"] = [
|
|
244
|
+
OutputModality(m) for m in data["output_modalities"]
|
|
245
|
+
]
|
|
225
246
|
|
|
226
247
|
# Validate model_provider if present
|
|
227
248
|
if "model_provider" in data:
|
|
@@ -232,11 +253,15 @@ class ModelConfigDetails(BaseDTO):
|
|
|
232
253
|
data["model_provider"] = ModelProviders(provider)
|
|
233
254
|
except ValueError:
|
|
234
255
|
valid_providers = [p.value for p in ModelProviders]
|
|
235
|
-
raise ValueError(
|
|
256
|
+
raise ValueError(
|
|
257
|
+
f"Invalid model_provider: '{provider}'. Must be one of: {valid_providers}"
|
|
258
|
+
)
|
|
236
259
|
# If it's already an enum instance, keep it as is
|
|
237
260
|
elif not isinstance(provider, ModelProviders):
|
|
238
261
|
valid_providers = [p.value for p in ModelProviders]
|
|
239
|
-
raise ValueError(
|
|
262
|
+
raise ValueError(
|
|
263
|
+
f"Invalid model_provider type. Valid values: {valid_providers}"
|
|
264
|
+
)
|
|
240
265
|
|
|
241
266
|
# # Remove known fields that we don't want in our model
|
|
242
267
|
# unwanted_fields = ["queryParams"]
|
|
@@ -305,16 +330,16 @@ class ModelConfigDetails(BaseDTO):
|
|
|
305
330
|
|
|
306
331
|
@dataclass
|
|
307
332
|
class ModelConfig(BaseDTO):
|
|
308
|
-
created_at: str = None
|
|
309
|
-
updated_at: str = None
|
|
310
|
-
created_by: str = None
|
|
311
|
-
updated_by: str = None
|
|
312
|
-
model_id: str = None
|
|
313
|
-
model_saved_name: str = None
|
|
314
|
-
model_version: str = None
|
|
333
|
+
created_at: Optional[str] = None
|
|
334
|
+
updated_at: Optional[str] = None
|
|
335
|
+
created_by: Optional[str] = None
|
|
336
|
+
updated_by: Optional[str] = None
|
|
337
|
+
model_id: Optional[str] = None
|
|
338
|
+
model_saved_name: Optional[str] = None
|
|
339
|
+
model_version: Optional[str] = None
|
|
315
340
|
testing_for: str = "foundationModels"
|
|
316
341
|
# modality: Modality = Modality.TEXT
|
|
317
|
-
project_name: str = None
|
|
342
|
+
project_name: Optional[str] = None
|
|
318
343
|
model_name: Optional[str] = "gpt-4o-mini"
|
|
319
344
|
certifications: List[str] = field(default_factory=list)
|
|
320
345
|
model_config: ModelConfigDetails = field(default_factory=ModelConfigDetails)
|