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.
- enkryptai_sdk/__init__.py +16 -4
- enkryptai_sdk/ai_proxy.py +70 -0
- enkryptai_sdk/base.py +36 -0
- enkryptai_sdk/datasets.py +148 -0
- enkryptai_sdk/deployments.py +121 -0
- enkryptai_sdk/dto/__init__.py +65 -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 +303 -61
- enkryptai_sdk/guardrails.py +219 -70
- enkryptai_sdk/guardrails_old.py +195 -0
- enkryptai_sdk/models.py +118 -52
- enkryptai_sdk/red_team.py +272 -73
- enkryptai_sdk-1.0.0.dist-info/METADATA +1312 -0
- enkryptai_sdk-1.0.0.dist-info/RECORD +25 -0
- {enkryptai_sdk-0.1.6.dist-info → enkryptai_sdk-1.0.0.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-1.0.0.dist-info/licenses}/LICENSE +0 -0
- {enkryptai_sdk-0.1.6.dist-info → enkryptai_sdk-1.0.0.dist-info}/top_level.txt +0 -0
enkryptai_sdk/models.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
from .dto import ModelConfig, ModelResponse
|
|
1
|
+
from .base import BaseClient
|
|
3
2
|
from urllib.parse import urlparse, urlsplit
|
|
3
|
+
from .dto import ModelConfig, ModelResponse, ModelCollection
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class ModelClientError(Exception):
|
|
@@ -11,41 +11,11 @@ class ModelClientError(Exception):
|
|
|
11
11
|
pass
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class ModelClient:
|
|
14
|
+
class ModelClient(BaseClient):
|
|
15
15
|
def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com:443"):
|
|
16
|
-
|
|
17
|
-
self.base_url = base_url
|
|
18
|
-
self.http = urllib3.PoolManager()
|
|
19
|
-
self.headers = {"apikey": self.api_key}
|
|
20
|
-
|
|
21
|
-
def _request(self, method, endpoint, payload=None, headers=None, **kwargs):
|
|
22
|
-
url = self.base_url + endpoint
|
|
23
|
-
request_headers = {
|
|
24
|
-
"Accept-Encoding": "gzip", # Add required gzip encoding
|
|
25
|
-
**self.headers,
|
|
26
|
-
}
|
|
27
|
-
if headers:
|
|
28
|
-
request_headers.update(headers)
|
|
29
|
-
|
|
30
|
-
try:
|
|
31
|
-
response = self.http.request(method, url, headers=request_headers, **kwargs)
|
|
32
|
-
|
|
33
|
-
if response.status >= 400:
|
|
34
|
-
error_data = (
|
|
35
|
-
response.json()
|
|
36
|
-
if response.data
|
|
37
|
-
else {"message": f"HTTP {response.status}"}
|
|
38
|
-
)
|
|
39
|
-
error_message = error_data.get("message", str(error_data))
|
|
40
|
-
raise urllib3.exceptions.HTTPError(error_message)
|
|
41
|
-
return response.json()
|
|
42
|
-
except urllib3.exceptions.HTTPError as e:
|
|
43
|
-
return {"error": str(e)}
|
|
44
|
-
|
|
45
|
-
def health(self):
|
|
46
|
-
return self._request("GET", "/models/health")
|
|
16
|
+
super().__init__(api_key, base_url)
|
|
47
17
|
|
|
48
|
-
def add_model(self, config: ModelConfig):
|
|
18
|
+
def add_model(self, config: ModelConfig) -> ModelResponse:
|
|
49
19
|
"""
|
|
50
20
|
Add a new model configuration to the system.
|
|
51
21
|
|
|
@@ -69,11 +39,15 @@ class ModelClient:
|
|
|
69
39
|
base_path = ""
|
|
70
40
|
remaining_path = ""
|
|
71
41
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
42
|
+
if config.model_config.paths:
|
|
43
|
+
paths = config.model_config.paths.to_dict()
|
|
44
|
+
else:
|
|
45
|
+
paths = {
|
|
46
|
+
"completions": (
|
|
47
|
+
f"/{remaining_path.split('/')[-1]}" if remaining_path else ""
|
|
48
|
+
),
|
|
49
|
+
"chat": f"/{remaining_path}" if remaining_path else "",
|
|
50
|
+
}
|
|
77
51
|
|
|
78
52
|
payload = {
|
|
79
53
|
"model_saved_name": config.model_saved_name,
|
|
@@ -82,11 +56,10 @@ class ModelClient:
|
|
|
82
56
|
"model_type": config.model_type,
|
|
83
57
|
"certifications": config.certifications,
|
|
84
58
|
"model_config": {
|
|
85
|
-
"
|
|
59
|
+
"model_provider": config.model_config.model_provider,
|
|
86
60
|
"model_version": config.model_config.model_version,
|
|
87
61
|
"hosting_type": config.model_config.hosting_type,
|
|
88
62
|
"model_source": config.model_config.model_source,
|
|
89
|
-
"model_provider": config.model_config.model_provider,
|
|
90
63
|
"system_prompt": config.model_config.system_prompt,
|
|
91
64
|
"conversation_template": config.model_config.conversation_template,
|
|
92
65
|
"endpoint": {
|
|
@@ -94,7 +67,7 @@ class ModelClient:
|
|
|
94
67
|
"host": parsed_url.hostname,
|
|
95
68
|
"port": parsed_url.port
|
|
96
69
|
or (443 if parsed_url.scheme == "https" else 80),
|
|
97
|
-
"base_path": f"/{base_path}
|
|
70
|
+
"base_path": f"/{base_path}", # Just v1
|
|
98
71
|
},
|
|
99
72
|
"paths": paths,
|
|
100
73
|
"auth_data": {
|
|
@@ -118,18 +91,19 @@ class ModelClient:
|
|
|
118
91
|
except Exception as e:
|
|
119
92
|
raise ModelClientError(str(e))
|
|
120
93
|
|
|
121
|
-
def get_model(self,
|
|
94
|
+
def get_model(self, model_saved_name: str) -> ModelConfig:
|
|
122
95
|
"""
|
|
123
|
-
Get model configuration by model
|
|
96
|
+
Get model configuration by model saved name.
|
|
124
97
|
|
|
125
98
|
Args:
|
|
126
|
-
|
|
99
|
+
model_saved_name (str): Saved name of the model to retrieve
|
|
127
100
|
|
|
128
101
|
Returns:
|
|
129
102
|
ModelConfig: Configuration object containing model details
|
|
130
103
|
"""
|
|
131
|
-
headers = {"X-Enkrypt-Model":
|
|
104
|
+
headers = {"X-Enkrypt-Model": model_saved_name}
|
|
132
105
|
response = self._request("GET", "/models/get-model", headers=headers)
|
|
106
|
+
print(response)
|
|
133
107
|
if response.get("error"):
|
|
134
108
|
raise ModelClientError(response["error"])
|
|
135
109
|
return ModelConfig.from_dict(response)
|
|
@@ -142,19 +116,111 @@ class ModelClient:
|
|
|
142
116
|
dict: Response from the API containing the list of models
|
|
143
117
|
"""
|
|
144
118
|
try:
|
|
145
|
-
|
|
119
|
+
response = self._request("GET", "/models/list-models")
|
|
120
|
+
if response.get("error"):
|
|
121
|
+
raise ModelClientError(response["error"])
|
|
122
|
+
return ModelCollection.from_dict(response)
|
|
146
123
|
except Exception as e:
|
|
147
124
|
return {"error": str(e)}
|
|
148
125
|
|
|
149
|
-
def
|
|
126
|
+
def modify_model(self, config: ModelConfig, old_model_saved_name=None) -> ModelResponse:
|
|
127
|
+
"""
|
|
128
|
+
Modify an existing model in the system.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
model_saved_name (str): The saved name of the model to modify
|
|
132
|
+
config (ModelConfig): Configuration object containing model details
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
dict: Response from the API containing the modified model details
|
|
136
|
+
"""
|
|
137
|
+
if old_model_saved_name is None:
|
|
138
|
+
old_model_saved_name = config["model_saved_name"]
|
|
139
|
+
|
|
140
|
+
headers = {"Content-Type": "application/json", "X-Enkrypt-Model": old_model_saved_name}
|
|
141
|
+
# print(config)
|
|
142
|
+
config = ModelConfig.from_dict(config)
|
|
143
|
+
# Parse endpoint_url into components
|
|
144
|
+
parsed_url = urlparse(config.model_config.endpoint_url)
|
|
145
|
+
path_parts = parsed_url.path.strip("/").split("/")
|
|
146
|
+
|
|
147
|
+
# Extract base_path and endpoint path
|
|
148
|
+
if len(path_parts) >= 1:
|
|
149
|
+
base_path = path_parts[0] # Usually 'v1'
|
|
150
|
+
remaining_path = "/".join(path_parts[1:]) # The rest of the path
|
|
151
|
+
else:
|
|
152
|
+
base_path = ""
|
|
153
|
+
remaining_path = ""
|
|
154
|
+
|
|
155
|
+
if config.model_config.paths:
|
|
156
|
+
paths = config.model_config.paths.to_dict()
|
|
157
|
+
else:
|
|
158
|
+
# Determine paths based on the endpoint
|
|
159
|
+
paths = {
|
|
160
|
+
"completions": (
|
|
161
|
+
f"/{remaining_path.split('/')[-1]}" if remaining_path else ""
|
|
162
|
+
),
|
|
163
|
+
"chat": f"/{remaining_path}" if remaining_path else "",
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
payload = {
|
|
167
|
+
"model_saved_name": config.model_saved_name,
|
|
168
|
+
"testing_for": config.testing_for,
|
|
169
|
+
"model_name": config.model_name,
|
|
170
|
+
"model_type": config.model_type,
|
|
171
|
+
"certifications": config.certifications,
|
|
172
|
+
"model_config": {
|
|
173
|
+
"model_provider": config.model_config.model_provider,
|
|
174
|
+
"model_version": config.model_config.model_version,
|
|
175
|
+
"hosting_type": config.model_config.hosting_type,
|
|
176
|
+
"model_source": config.model_config.model_source,
|
|
177
|
+
"system_prompt": config.model_config.system_prompt,
|
|
178
|
+
"conversation_template": config.model_config.conversation_template,
|
|
179
|
+
"endpoint": {
|
|
180
|
+
"scheme": parsed_url.scheme,
|
|
181
|
+
"host": parsed_url.hostname,
|
|
182
|
+
"port": parsed_url.port
|
|
183
|
+
or (443 if parsed_url.scheme == "https" else 80),
|
|
184
|
+
"base_path": f"/{base_path}", # Just v1
|
|
185
|
+
},
|
|
186
|
+
"paths": paths,
|
|
187
|
+
"auth_data": {
|
|
188
|
+
"header_name": config.model_config.auth_data.header_name,
|
|
189
|
+
"header_prefix": config.model_config.auth_data.header_prefix,
|
|
190
|
+
"space_after_prefix": config.model_config.auth_data.space_after_prefix,
|
|
191
|
+
},
|
|
192
|
+
"apikeys": (
|
|
193
|
+
[config.model_config.apikey] if config.model_config.apikey else []
|
|
194
|
+
),
|
|
195
|
+
"default_request_options": config.model_config.default_request_options,
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
try:
|
|
199
|
+
response = self._request(
|
|
200
|
+
"PATCH", "/models/modify-model", headers=headers, json=payload
|
|
201
|
+
)
|
|
202
|
+
if response.get("error"):
|
|
203
|
+
raise ModelClientError(response["error"])
|
|
204
|
+
return ModelResponse.from_dict(response)
|
|
205
|
+
except Exception as e:
|
|
206
|
+
raise ModelClientError(str(e))
|
|
207
|
+
|
|
208
|
+
def delete_model(self, model_saved_name: str) -> ModelResponse:
|
|
150
209
|
"""
|
|
151
210
|
Delete a specific model from the system.
|
|
152
211
|
|
|
153
212
|
Args:
|
|
154
|
-
|
|
213
|
+
model_saved_name (str): The saved name of the model to delete
|
|
155
214
|
|
|
156
215
|
Returns:
|
|
157
216
|
dict: Response from the API containing the deletion status
|
|
158
217
|
"""
|
|
159
|
-
headers = {"X-Enkrypt-Model":
|
|
160
|
-
|
|
218
|
+
headers = {"X-Enkrypt-Model": model_saved_name}
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
response = self._request("DELETE", "/models/delete-model", headers=headers)
|
|
222
|
+
if response.get("error"):
|
|
223
|
+
raise ModelClientError(response["error"])
|
|
224
|
+
return ModelResponse.from_dict(response)
|
|
225
|
+
except Exception as e:
|
|
226
|
+
raise ModelClientError(str(e))
|
enkryptai_sdk/red_team.py
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import urllib3
|
|
2
|
+
from .base import BaseClient
|
|
2
3
|
from .dto import (
|
|
4
|
+
RedteamHealthResponse,
|
|
5
|
+
RedTeamModelHealthConfig,
|
|
6
|
+
RedteamModelHealthResponse,
|
|
3
7
|
RedTeamConfig,
|
|
8
|
+
RedTeamConfigWithSavedModel,
|
|
4
9
|
RedTeamResponse,
|
|
5
10
|
RedTeamResultSummary,
|
|
6
11
|
RedTeamResultDetails,
|
|
7
12
|
RedTeamTaskStatus,
|
|
8
13
|
RedTeamTaskDetails,
|
|
14
|
+
RedTeamTaskList,
|
|
9
15
|
)
|
|
10
16
|
|
|
11
17
|
|
|
@@ -17,47 +23,64 @@ class RedTeamClientError(Exception):
|
|
|
17
23
|
pass
|
|
18
24
|
|
|
19
25
|
|
|
20
|
-
class RedTeamClient:
|
|
26
|
+
class RedTeamClient(BaseClient):
|
|
21
27
|
"""
|
|
22
28
|
A client for interacting with the Red Team API.
|
|
23
29
|
"""
|
|
24
30
|
|
|
25
31
|
def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
if headers:
|
|
38
|
-
request_headers.update(headers)
|
|
32
|
+
super().__init__(api_key, base_url)
|
|
33
|
+
|
|
34
|
+
# def get_model(self, model):
|
|
35
|
+
# models = self._request("GET", "/models/list-models")
|
|
36
|
+
# models = models["models"]
|
|
37
|
+
# for _model_data in models:
|
|
38
|
+
# if _model_data["model_saved_name"] == model:
|
|
39
|
+
# return _model_data["model_saved_name"]
|
|
40
|
+
# else:
|
|
41
|
+
# return None
|
|
39
42
|
|
|
43
|
+
def get_health(self):
|
|
44
|
+
"""
|
|
45
|
+
Get the health status of the service.
|
|
46
|
+
"""
|
|
40
47
|
try:
|
|
41
|
-
response = self.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
response = self._request("GET", "/redteam/health")
|
|
49
|
+
if response.get("error"):
|
|
50
|
+
raise RedTeamClientError(response["error"])
|
|
51
|
+
return RedteamHealthResponse.from_dict(response)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
raise RedTeamClientError(str(e))
|
|
54
|
+
|
|
55
|
+
def check_model_health(self, config: RedTeamModelHealthConfig):
|
|
56
|
+
"""
|
|
57
|
+
Get the health status of a model.
|
|
58
|
+
"""
|
|
59
|
+
try:
|
|
60
|
+
config = RedTeamModelHealthConfig.from_dict(config)
|
|
61
|
+
response = self._request("POST", "/redteam/model-health", json=config.to_dict())
|
|
62
|
+
# if response.get("error"):
|
|
63
|
+
if response.get("error") not in [None, ""]:
|
|
64
|
+
raise RedTeamClientError(response["error"])
|
|
65
|
+
return RedteamModelHealthResponse.from_dict(response)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
raise RedTeamClientError(str(e))
|
|
68
|
+
|
|
69
|
+
def check_saved_model_health(self, model_saved_name: str):
|
|
70
|
+
"""
|
|
71
|
+
Get the health status of a saved model.
|
|
72
|
+
"""
|
|
73
|
+
try:
|
|
74
|
+
headers = {
|
|
75
|
+
"X-Enkrypt-Model": model_saved_name,
|
|
76
|
+
}
|
|
77
|
+
response = self._request("POST", "/redteam/model/model-health", headers=headers)
|
|
78
|
+
# if response.get("error"):
|
|
79
|
+
if response.get("error") not in [None, ""]:
|
|
80
|
+
raise RedTeamClientError(response["error"])
|
|
81
|
+
return RedteamModelHealthResponse.from_dict(response)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise RedTeamClientError(str(e))
|
|
61
84
|
|
|
62
85
|
def add_task(
|
|
63
86
|
self,
|
|
@@ -75,26 +98,12 @@ class RedTeamClient:
|
|
|
75
98
|
# "async": config.async_enabled,
|
|
76
99
|
"dataset_name": config.dataset_name,
|
|
77
100
|
"test_name": config.test_name,
|
|
78
|
-
"redteam_test_configurations":
|
|
101
|
+
"redteam_test_configurations": {
|
|
102
|
+
k: v.to_dict() for k, v in test_configs.items()
|
|
103
|
+
},
|
|
79
104
|
}
|
|
80
105
|
|
|
81
|
-
|
|
82
|
-
saved_model = self.get_model(model)
|
|
83
|
-
|
|
84
|
-
if saved_model:
|
|
85
|
-
print("saved model found")
|
|
86
|
-
headers = {
|
|
87
|
-
"X-Enkrypt-Model": saved_model,
|
|
88
|
-
"Content-Type": "application/json",
|
|
89
|
-
}
|
|
90
|
-
payload["location"] = {"storage": "supabase", "container_name": "supabase"}
|
|
91
|
-
return self._request(
|
|
92
|
-
"POST",
|
|
93
|
-
"/redteam/v2/model/add-task",
|
|
94
|
-
headers=headers,
|
|
95
|
-
json=payload,
|
|
96
|
-
)
|
|
97
|
-
elif config.target_model_configuration:
|
|
106
|
+
if config.target_model_configuration:
|
|
98
107
|
payload["target_model_configuration"] = (
|
|
99
108
|
config.target_model_configuration.to_dict()
|
|
100
109
|
)
|
|
@@ -109,87 +118,277 @@ class RedTeamClient:
|
|
|
109
118
|
return RedTeamResponse.from_dict(response)
|
|
110
119
|
else:
|
|
111
120
|
raise RedTeamClientError(
|
|
112
|
-
"Please
|
|
121
|
+
"Please provide a target model configuration"
|
|
113
122
|
)
|
|
114
123
|
|
|
115
|
-
def
|
|
124
|
+
def add_task_with_saved_model(
|
|
125
|
+
self,
|
|
126
|
+
config: RedTeamConfigWithSavedModel,
|
|
127
|
+
model_saved_name: str,
|
|
128
|
+
):
|
|
129
|
+
"""
|
|
130
|
+
Add a new red teaming task using a saved model.
|
|
131
|
+
"""
|
|
132
|
+
if not model_saved_name:
|
|
133
|
+
raise RedTeamClientError("Please provide a model_saved_name")
|
|
134
|
+
|
|
135
|
+
config = RedTeamConfigWithSavedModel.from_dict(config)
|
|
136
|
+
test_configs = config.redteam_test_configurations.to_dict()
|
|
137
|
+
# Remove None or empty test configurations
|
|
138
|
+
test_configs = {k: v for k, v in test_configs.items() if v is not None}
|
|
139
|
+
|
|
140
|
+
payload = {
|
|
141
|
+
# "async": config.async_enabled,
|
|
142
|
+
"dataset_name": config.dataset_name,
|
|
143
|
+
"test_name": config.test_name,
|
|
144
|
+
"redteam_test_configurations": {
|
|
145
|
+
k: v.to_dict() for k, v in test_configs.items()
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
headers = {
|
|
150
|
+
"X-Enkrypt-Model": model_saved_name,
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
}
|
|
153
|
+
response = self._request(
|
|
154
|
+
"POST",
|
|
155
|
+
"/redteam/v2/model/add-task",
|
|
156
|
+
headers=headers,
|
|
157
|
+
json=payload,
|
|
158
|
+
)
|
|
159
|
+
if response.get("error"):
|
|
160
|
+
raise RedTeamClientError(response["error"])
|
|
161
|
+
return RedTeamResponse.from_dict(response)
|
|
162
|
+
|
|
163
|
+
def status(self, task_id: str = None, test_name: str = None):
|
|
116
164
|
"""
|
|
117
165
|
Get the status of a specific red teaming task.
|
|
118
166
|
|
|
119
167
|
Args:
|
|
120
|
-
task_id (str): The ID of the task to check status
|
|
168
|
+
task_id (str, optional): The ID of the task to check status
|
|
169
|
+
test_name (str, optional): The name of the test to check status
|
|
121
170
|
|
|
122
171
|
Returns:
|
|
123
172
|
dict: The task status information
|
|
173
|
+
|
|
174
|
+
Raises:
|
|
175
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
124
176
|
"""
|
|
125
|
-
|
|
177
|
+
if not task_id and not test_name:
|
|
178
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
179
|
+
|
|
180
|
+
headers = {}
|
|
181
|
+
if task_id:
|
|
182
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
183
|
+
if test_name:
|
|
184
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
126
185
|
|
|
127
186
|
response = self._request("GET", "/redteam/task-status", headers=headers)
|
|
128
187
|
if response.get("error"):
|
|
129
188
|
raise RedTeamClientError(response["error"])
|
|
130
189
|
return RedTeamTaskStatus.from_dict(response)
|
|
131
190
|
|
|
132
|
-
def cancel_task(self, task_id: str):
|
|
191
|
+
def cancel_task(self, task_id: str = None, test_name: str = None):
|
|
133
192
|
"""
|
|
134
193
|
Cancel a specific red teaming task.
|
|
135
194
|
|
|
136
195
|
Args:
|
|
137
|
-
task_id (str): The ID of the task to cancel
|
|
196
|
+
task_id (str, optional): The ID of the task to cancel
|
|
197
|
+
test_name (str, optional): The name of the test to cancel
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
dict: The cancellation response
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
138
204
|
"""
|
|
139
205
|
raise RedTeamClientError(
|
|
140
206
|
"This feature is currently under development. Please check our documentation "
|
|
141
207
|
"at https://docs.enkrypt.ai for updates or contact support@enkrypt.ai for assistance."
|
|
142
208
|
)
|
|
143
209
|
|
|
144
|
-
|
|
210
|
+
if not task_id and not test_name:
|
|
211
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
212
|
+
|
|
213
|
+
headers = {}
|
|
214
|
+
if task_id:
|
|
215
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
216
|
+
if test_name:
|
|
217
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
218
|
+
|
|
219
|
+
response = self._request("POST", "/redteam/cancel-task", headers=headers)
|
|
220
|
+
if response.get("error"):
|
|
221
|
+
raise RedTeamClientError(response["error"])
|
|
222
|
+
return response
|
|
223
|
+
|
|
224
|
+
def get_task(self, task_id: str = None, test_name: str = None):
|
|
145
225
|
"""
|
|
146
226
|
Get the status and details of a specific red teaming task.
|
|
147
227
|
|
|
148
228
|
Args:
|
|
149
|
-
task_id (str): The ID of the task to retrieve
|
|
229
|
+
task_id (str, optional): The ID of the task to retrieve
|
|
230
|
+
test_name (str, optional): The name of the test to retrieve
|
|
150
231
|
|
|
151
232
|
Returns:
|
|
152
233
|
dict: The task details and status
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
153
237
|
"""
|
|
154
|
-
|
|
238
|
+
if not task_id and not test_name:
|
|
239
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
240
|
+
|
|
241
|
+
headers = {}
|
|
242
|
+
if task_id:
|
|
243
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
244
|
+
if test_name:
|
|
245
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
155
246
|
|
|
156
247
|
response = self._request("GET", "/redteam/get-task", headers=headers)
|
|
157
248
|
if response.get("error"):
|
|
158
249
|
raise RedTeamClientError(response["error"])
|
|
159
|
-
if response.get("data").get("job_id "):
|
|
160
|
-
response["data"]["task_id"] = response["data"].pop("job_id")
|
|
161
250
|
return RedTeamTaskDetails.from_dict(response["data"])
|
|
162
251
|
|
|
163
|
-
def get_result_summary(self, task_id: str):
|
|
252
|
+
def get_result_summary(self, task_id: str = None, test_name: str = None):
|
|
164
253
|
"""
|
|
165
254
|
Get the summary of results for a specific red teaming task.
|
|
166
255
|
|
|
167
256
|
Args:
|
|
168
|
-
task_id (str): The ID of the task to get results for
|
|
257
|
+
task_id (str, optional): The ID of the task to get results for
|
|
258
|
+
test_name (str, optional): The name of the test to get results for
|
|
169
259
|
|
|
170
260
|
Returns:
|
|
171
261
|
dict: The summary of the task results
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
172
265
|
"""
|
|
173
|
-
|
|
266
|
+
if not task_id and not test_name:
|
|
267
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
268
|
+
|
|
269
|
+
headers = {}
|
|
270
|
+
if task_id:
|
|
271
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
272
|
+
if test_name:
|
|
273
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
174
274
|
|
|
175
275
|
response = self._request("GET", "/redteam/results/summary", headers=headers)
|
|
176
276
|
if response.get("error"):
|
|
177
277
|
raise RedTeamClientError(response["error"])
|
|
178
|
-
|
|
278
|
+
print(f"Response: {response}")
|
|
279
|
+
return RedTeamResultSummary.from_dict(response)
|
|
280
|
+
|
|
281
|
+
def get_result_summary_test_type(self, task_id: str = None, test_name: str = None, test_type: str = None):
|
|
282
|
+
"""
|
|
283
|
+
Get the summary of results for a specific red teaming task for a specific test type.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
task_id (str, optional): The ID of the task to get results for
|
|
287
|
+
test_name (str, optional): The name of the test to get results for
|
|
288
|
+
test_type (str, optional): The type of test to get results for
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
dict: The summary of the task results for the specified test type
|
|
292
|
+
|
|
293
|
+
Raises:
|
|
294
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
295
|
+
"""
|
|
296
|
+
if not task_id and not test_name:
|
|
297
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
298
|
+
|
|
299
|
+
if not test_type:
|
|
300
|
+
raise RedTeamClientError("test_type must be provided")
|
|
301
|
+
|
|
302
|
+
headers = {}
|
|
303
|
+
if task_id:
|
|
304
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
305
|
+
if test_name:
|
|
306
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
307
|
+
|
|
308
|
+
url = f"/redteam/v2/results/summary/{test_type}"
|
|
309
|
+
response = self._request("GET", url, headers=headers)
|
|
310
|
+
if response.get("error"):
|
|
311
|
+
raise RedTeamClientError(response["error"])
|
|
312
|
+
print(f"Response: {response}")
|
|
313
|
+
return RedTeamResultSummary.from_dict(response)
|
|
179
314
|
|
|
180
|
-
def get_result_details(self, task_id: str):
|
|
315
|
+
def get_result_details(self, task_id: str = None, test_name: str = None):
|
|
181
316
|
"""
|
|
182
317
|
Get the detailed results for a specific red teaming task.
|
|
183
318
|
|
|
184
319
|
Args:
|
|
185
|
-
task_id (str): The ID of the task to get detailed results for
|
|
320
|
+
task_id (str, optional): The ID of the task to get detailed results for
|
|
321
|
+
test_name (str, optional): The name of the test to get detailed results for
|
|
186
322
|
|
|
187
323
|
Returns:
|
|
188
324
|
dict: The detailed task results
|
|
325
|
+
|
|
326
|
+
Raises:
|
|
327
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
189
328
|
"""
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
329
|
+
if not task_id and not test_name:
|
|
330
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
331
|
+
|
|
332
|
+
headers = {}
|
|
333
|
+
if task_id:
|
|
334
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
335
|
+
if test_name:
|
|
336
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
337
|
+
|
|
338
|
+
response = self._request("GET", "/redteam/v2/results/details", headers=headers)
|
|
339
|
+
if response.get("error"):
|
|
340
|
+
raise RedTeamClientError(response["error"])
|
|
341
|
+
return RedTeamResultDetails.from_dict(response)
|
|
342
|
+
|
|
343
|
+
def get_result_details_test_type(self, task_id: str = None, test_name: str = None, test_type: str = None):
|
|
344
|
+
"""
|
|
345
|
+
Get the detailed results for a specific red teaming task for a specific test type.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
task_id (str, optional): The ID of the task to get detailed results for
|
|
349
|
+
test_name (str, optional): The name of the test to get detailed results for
|
|
350
|
+
test_type (str, optional): The type of test to get detailed results for
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
dict: The detailed task results
|
|
354
|
+
|
|
355
|
+
Raises:
|
|
356
|
+
RedTeamClientError: If neither task_id nor test_name is provided, or if there's an error from the API
|
|
357
|
+
"""
|
|
358
|
+
if not task_id and not test_name:
|
|
359
|
+
raise RedTeamClientError("Either task_id or test_name must be provided")
|
|
360
|
+
|
|
361
|
+
if not test_type:
|
|
362
|
+
raise RedTeamClientError("test_type must be provided")
|
|
363
|
+
|
|
364
|
+
headers = {}
|
|
365
|
+
if task_id:
|
|
366
|
+
headers["X-Enkrypt-Task-ID"] = task_id
|
|
367
|
+
if test_name:
|
|
368
|
+
headers["X-Enkrypt-Test-Name"] = test_name
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
url = f"/redteam/v2/results/details/{test_type}"
|
|
372
|
+
response = self._request("GET", url, headers=headers)
|
|
373
|
+
if response.get("error"):
|
|
374
|
+
raise RedTeamClientError(response["error"])
|
|
375
|
+
return RedTeamResultDetails.from_dict(response)
|
|
376
|
+
|
|
377
|
+
def get_task_list(self, status: str = None):
|
|
378
|
+
"""
|
|
379
|
+
Get a list of red teaming tasks.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
status (str, optional): The status of the tasks to retrieve
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
dict: The list of tasks
|
|
386
|
+
"""
|
|
387
|
+
url = "/redteam/list-tasks"
|
|
388
|
+
if status:
|
|
389
|
+
url += f"?status={status}"
|
|
390
|
+
|
|
391
|
+
response = self._request("GET", url)
|
|
193
392
|
if response.get("error"):
|
|
194
393
|
raise RedTeamClientError(response["error"])
|
|
195
|
-
return
|
|
394
|
+
return RedTeamTaskList.from_dict(response)
|