enkryptai-sdk 1.0.7__py3-none-any.whl → 1.0.8__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/ai_proxy.py CHANGED
@@ -60,7 +60,7 @@ class AIProxyClient(BaseClient):
60
60
  # # As json.loads is not working with literal string representation of dict
61
61
  # parsed_error = json.loads(error_message.replace("'", '"'))
62
62
  # # Convert Python string representation to proper dict
63
- parsed_error = ast.literal_eval(response["error"])
63
+ parsed_error = ast.literal_eval(f"API Error: {str(response)}")
64
64
  # # Preserve both error and enkrypt_policy_detections fields
65
65
  response["error"] = parsed_error.get("error", parsed_error)
66
66
  if "enkrypt_policy_detections" in parsed_error:
@@ -84,6 +84,6 @@ class AIProxyClient(BaseClient):
84
84
  # Fallback to direct error if error object can't be parsed
85
85
  # print("Failed to parse error response: ", response)
86
86
  return ChatCompletionDirectErrorResponse.from_dict(response)
87
- raise AIProxyClientError(response["error"])
87
+ raise AIProxyClientError(f"API Error: {str(response)}")
88
88
 
89
89
  return ChatCompletionResponse.from_dict(response)
enkryptai_sdk/datasets.py CHANGED
@@ -19,6 +19,32 @@ class DatasetClient(BaseClient):
19
19
  def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
20
20
  super().__init__(api_key, base_url)
21
21
 
22
+ @staticmethod
23
+ def prepare_dataset_payload(config: DatasetConfig | dict, is_custom: bool = False) -> dict:
24
+ """
25
+ Prepare the payload for dataset operations from a config object.
26
+
27
+ Args:
28
+ config (Union[DatasetConfig, dict]): Configuration object or dictionary containing dataset details
29
+
30
+ Returns:
31
+ dict: Processed payload ready for API submission
32
+ """
33
+ if isinstance(config, dict):
34
+ config = DatasetConfig.from_dict(config)
35
+
36
+ payload = config.to_dict()
37
+
38
+ if not is_custom:
39
+ # Remove empty tools configuration
40
+ if (payload.get("tools") is None or
41
+ payload["tools"] == [] or
42
+ payload["tools"] == [{}] or
43
+ payload["tools"] == [{"name": "", "description": ""}]):
44
+ del payload["tools"]
45
+
46
+ return payload
47
+
22
48
  def add_dataset(self, config: DatasetConfig):
23
49
  """
24
50
  Add a new dataset to the system.
@@ -34,14 +60,7 @@ class DatasetClient(BaseClient):
34
60
  if isinstance(config, dict):
35
61
  config = DatasetConfig.from_dict(config)
36
62
 
37
- payload = config.to_dict()
38
-
39
- # If payload["tools"] is None or is an empty list [] or [{}], remove it from the payload
40
- if (payload.get("tools") is None or
41
- payload["tools"] == [] or
42
- payload["tools"] == [{}] or
43
- payload["tools"] == [{"name": "", "description": ""}]):
44
- del payload["tools"]
63
+ payload = self.prepare_dataset_payload(config)
45
64
 
46
65
  # Print payload
47
66
  # print(f"\nAdd Dataset Payload: {payload}")
@@ -54,7 +73,7 @@ class DatasetClient(BaseClient):
54
73
  # print(f"\nAdd Dataset Response: {response}")
55
74
 
56
75
  if response.get("error"):
57
- raise DatasetClientError(response["error"])
76
+ raise DatasetClientError(f"API Error: {str(response)}")
58
77
  return DatasetAddTaskResponse.from_dict(response)
59
78
 
60
79
  def get_dataset_task_status(self, dataset_name: str):
@@ -70,7 +89,7 @@ class DatasetClient(BaseClient):
70
89
  headers = {"X-Enkrypt-Dataset": dataset_name}
71
90
  response = self._request("GET", "/datasets/task-status", headers=headers)
72
91
  if response.get("error"):
73
- raise DatasetClientError(response["error"])
92
+ raise DatasetClientError(f"API Error: {str(response)}")
74
93
  response["dataset_name"] = dataset_name
75
94
  return DatasetTaskStatus.from_dict(response)
76
95
 
@@ -87,7 +106,7 @@ class DatasetClient(BaseClient):
87
106
  headers = {"X-Enkrypt-Dataset": dataset_name}
88
107
  response = self._request("GET", "/datasets/get-task", headers=headers)
89
108
  if response.get("error"):
90
- raise DatasetClientError(response["error"])
109
+ raise DatasetClientError(f"API Error: {str(response)}")
91
110
  response["dataset_name"] = dataset_name
92
111
  return DatasetTask.from_dict(response)
93
112
 
@@ -104,7 +123,7 @@ class DatasetClient(BaseClient):
104
123
  headers = {"X-Enkrypt-Dataset": dataset_name}
105
124
  response = self._request("GET", "/datasets/get-datacard", headers=headers)
106
125
  if response.get("error"):
107
- raise DatasetClientError(response["error"])
126
+ raise DatasetClientError(f"API Error: {str(response)}")
108
127
  response["dataset_name"] = dataset_name
109
128
  return DatasetCard.from_dict(response)
110
129
 
@@ -121,7 +140,7 @@ class DatasetClient(BaseClient):
121
140
  headers = {"X-Enkrypt-Dataset": dataset_name}
122
141
  response = self._request("GET", "/datasets/get-dataset", headers=headers)
123
142
  if response.get("error"):
124
- raise DatasetClientError(response["error"])
143
+ raise DatasetClientError(f"API Error: {str(response)}")
125
144
  response["dataset_name"] = dataset_name
126
145
  return DatasetResponse.from_dict(response)
127
146
 
@@ -138,7 +157,7 @@ class DatasetClient(BaseClient):
138
157
  headers = {"X-Enkrypt-Dataset": dataset_name}
139
158
  response = self._request("GET", "/datasets/get-summary", headers=headers)
140
159
  if response.get("error"):
141
- raise DatasetClientError(response["error"])
160
+ raise DatasetClientError(f"API Error: {str(response)}")
142
161
  response["dataset_name"] = dataset_name
143
162
  return DatasetSummary.from_dict(response)
144
163
 
@@ -158,5 +177,5 @@ class DatasetClient(BaseClient):
158
177
  url += f"?status={status}"
159
178
  response = self._request("GET", url)
160
179
  if response.get("error"):
161
- raise DatasetClientError(response["error"])
180
+ raise DatasetClientError(f"API Error: {str(response)}")
162
181
  return DatasetCollection.from_dict(response)
@@ -46,7 +46,7 @@ class DeploymentClient(BaseClient):
46
46
  "POST", "/deployments/add-deployment", headers=headers, json=payload
47
47
  )
48
48
  if response.get("error"):
49
- raise DeploymentClientError(response["error"])
49
+ raise DeploymentClientError(f"API Error: {str(response)}")
50
50
  return DeploymentAddTaskResponse.from_dict(response)
51
51
 
52
52
  def get_deployment(self, deployment_name: str, refresh_cache: bool = False):
@@ -64,7 +64,7 @@ class DeploymentClient(BaseClient):
64
64
  headers["X-Enkrypt-Refresh-Cache"] = "true" if refresh_cache else "false"
65
65
  response = self._request("GET", "/deployments/get-deployment", headers=headers)
66
66
  if response.get("error"):
67
- raise DeploymentClientError(response["error"])
67
+ raise DeploymentClientError(f"API Error: {str(response)}")
68
68
  return GetDeploymentResponse.from_dict(response)
69
69
 
70
70
  def modify_deployment(self, deployment_name: str, config: DeploymentInput):
@@ -88,7 +88,7 @@ class DeploymentClient(BaseClient):
88
88
  "PATCH", "/deployments/modify-deployment", headers=headers, json=payload
89
89
  )
90
90
  if response.get("error"):
91
- raise DeploymentClientError(response["error"])
91
+ raise DeploymentClientError(f"API Error: {str(response)}")
92
92
  return ModifyDeploymentResponse.from_dict(response)
93
93
 
94
94
  def delete_deployment(self, deployment_name: str):
@@ -104,7 +104,7 @@ class DeploymentClient(BaseClient):
104
104
  headers = {"X-Enkrypt-Deployment": deployment_name}
105
105
  response = self._request("DELETE", "/deployments/delete-deployment", headers=headers)
106
106
  if response.get("error"):
107
- raise DeploymentClientError(response["error"])
107
+ raise DeploymentClientError(f"API Error: {str(response)}")
108
108
  return DeleteDeploymentResponse.from_dict(response)
109
109
 
110
110
  def list_deployments(self):
@@ -117,5 +117,5 @@ class DeploymentClient(BaseClient):
117
117
 
118
118
  response = self._request("GET", "/deployments/list-deployments")
119
119
  if response.get("error"):
120
- raise DeploymentClientError(response["error"])
120
+ raise DeploymentClientError(f"API Error: {str(response)}")
121
121
  return DeploymentCollection.from_dict(response)
@@ -22,6 +22,8 @@ __all__ = [
22
22
  "Metadata",
23
23
  "DEFAULT_REDTEAM_CONFIG",
24
24
  "DEFAULT_REDTEAM_CONFIG_WITH_SAVED_MODEL",
25
+ "DEFAULT_CUSTOM_REDTEAM_CONFIG",
26
+ "DEFAULT_CUSTOM_REDTEAM_CONFIG_WITH_SAVED_MODEL",
25
27
  "ADVANCED_REDTEAM_TESTS",
26
28
  "DETAIL_MODEL_CONFIG",
27
29
  "DatasetConfig",
@@ -21,17 +21,20 @@ class Tool(BaseDTO):
21
21
  "description": self.description
22
22
  }
23
23
 
24
+
24
25
  @dataclass
25
26
  class DatasetConfig(BaseDTO):
26
- dataset_name: str
27
- system_description: str
28
- policy_description: str = ""
29
- tools: List[Tool] = field(default_factory=list)
30
- info_pdf_url: str = ""
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
31
33
  max_prompts: int = 100
32
34
  scenarios: int = 2
33
35
  categories: int = 2
34
36
  depth: int = 2
37
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
35
38
 
36
39
 
37
40
  @dataclass
@@ -51,6 +54,7 @@ class DatasetDataPoint(BaseDTO):
51
54
  category: str
52
55
  prompt: str
53
56
  source: str
57
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
54
58
 
55
59
 
56
60
  @dataclass
@@ -142,8 +142,8 @@ class CustomHeader(BaseDTO):
142
142
 
143
143
  @dataclass
144
144
  class ModelConfigDetails(BaseDTO):
145
- model_id: str = ""
146
- model_source: str = ""
145
+ model_id: str = None
146
+ model_source: str = None
147
147
  # model_provider: str = "openai"
148
148
  model_provider: ModelProviders = ModelProviders.OPENAI
149
149
  model_api_value: str = ""
@@ -259,14 +259,14 @@ class ModelConfigDetails(BaseDTO):
259
259
 
260
260
  @dataclass
261
261
  class ModelConfig(BaseDTO):
262
- created_at: str = ""
263
- updated_at: str = ""
264
- model_id: str = ""
265
- model_saved_name: str = "Model Name"
266
- model_version: str = "v1"
262
+ created_at: str = None
263
+ updated_at: str = None
264
+ model_id: str = None
265
+ model_saved_name: str = None
266
+ model_version: str = None
267
267
  testing_for: str = "foundationModels"
268
268
  # modality: Modality = Modality.TEXT
269
- project_name: str = ""
269
+ project_name: str = None
270
270
  model_name: Optional[str] = "gpt-4o-mini"
271
271
  certifications: List[str] = field(default_factory=list)
272
272
  model_config: ModelConfigDetails = field(default_factory=ModelConfigDetails)
@@ -3,6 +3,8 @@ from enum import Enum
3
3
  from .base import BaseDTO
4
4
  from typing import Dict, List, Optional, Any
5
5
  from dataclasses import dataclass, field, asdict
6
+ from .datasets import DatasetConfig
7
+ from .models import ModelConfig
6
8
 
7
9
 
8
10
  @dataclass
@@ -24,6 +26,7 @@ class RedteamHealthResponse(BaseDTO):
24
26
 
25
27
  @dataclass
26
28
  class RedTeamResponse(BaseDTO):
29
+ status: Optional[str] = None
27
30
  task_id: Optional[str] = None
28
31
  message: Optional[str] = None
29
32
  data: Optional[Dict[str, Any]] = None
@@ -300,7 +303,7 @@ class RedTeamTestConfigurations(BaseDTO):
300
303
  adv_info_test: TestConfig = field(default=None)
301
304
  adv_bias_test: TestConfig = field(default=None)
302
305
  adv_command_test: TestConfig = field(default=None)
303
- # custom_test: TestConfig = field(default=None)
306
+ custom_test: TestConfig = field(default=None)
304
307
  _extra_fields: Dict[str, Any] = field(default_factory=dict)
305
308
 
306
309
  @classmethod
@@ -482,6 +485,83 @@ class RedTeamConfigWithSavedModel(BaseDTO):
482
485
  )
483
486
 
484
487
 
488
+ @dataclass
489
+ class RedTeamCustomConfig(BaseDTO):
490
+ test_name: str = "Test Name"
491
+
492
+ redteam_test_configurations: RedTeamTestConfigurations = field(
493
+ default_factory=RedTeamTestConfigurations
494
+ )
495
+ dataset_configuration: DatasetConfig = field(
496
+ default_factory=DatasetConfig
497
+ )
498
+ endpoint_configuration: ModelConfig = field(
499
+ default_factory=ModelConfig
500
+ )
501
+
502
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
503
+
504
+ def to_dict(self) -> dict:
505
+ d = asdict(self)
506
+ d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
507
+ d["dataset_configuration"] = self.dataset_configuration.to_dict()
508
+ d["endpoint_configuration"] = self.endpoint_configuration.to_dict()
509
+ return d
510
+
511
+ @classmethod
512
+ def from_dict(cls, data: dict):
513
+ data = data.copy()
514
+ test_configs = RedTeamTestConfigurations.from_dict(
515
+ data.pop("redteam_test_configurations", {})
516
+ )
517
+ dataset_config = DatasetConfig.from_dict(
518
+ data.pop("dataset_configuration", {})
519
+ )
520
+ endpoint_config = ModelConfig.from_dict(
521
+ data.pop("endpoint_configuration", {})
522
+ )
523
+ return cls(
524
+ **data,
525
+ redteam_test_configurations=test_configs,
526
+ dataset_configuration=dataset_config,
527
+ endpoint_configuration=endpoint_config,
528
+ )
529
+
530
+ @dataclass
531
+ class RedTeamCustomConfigWithSavedModel(BaseDTO):
532
+ test_name: str = "Test Name"
533
+
534
+ redteam_test_configurations: RedTeamTestConfigurations = field(
535
+ default_factory=RedTeamTestConfigurations
536
+ )
537
+ dataset_configuration: DatasetConfig = field(
538
+ default_factory=DatasetConfig
539
+ )
540
+
541
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
542
+
543
+ def to_dict(self) -> dict:
544
+ d = asdict(self)
545
+ d["redteam_test_configurations"] = self.redteam_test_configurations.to_dict()
546
+ d["dataset_configuration"] = self.dataset_configuration.to_dict()
547
+ return d
548
+
549
+ @classmethod
550
+ def from_dict(cls, data: dict):
551
+ data = data.copy()
552
+ test_configs = RedTeamTestConfigurations.from_dict(
553
+ data.pop("redteam_test_configurations", {})
554
+ )
555
+ dataset_config = DatasetConfig.from_dict(
556
+ data.pop("dataset_configuration", {})
557
+ )
558
+ return cls(
559
+ **data,
560
+ redteam_test_configurations=test_configs,
561
+ dataset_configuration=dataset_config,
562
+ )
563
+
564
+
485
565
  @dataclass
486
566
  class RedTeamTaskList(BaseDTO):
487
567
  tasks: List[RedTeamTaskDetails] = field(default_factory=list)
@@ -494,3 +574,6 @@ class RedTeamTaskList(BaseDTO):
494
574
  # Default configurations
495
575
  DEFAULT_REDTEAM_CONFIG = RedTeamConfig()
496
576
  DEFAULT_REDTEAM_CONFIG_WITH_SAVED_MODEL = RedTeamConfigWithSavedModel()
577
+
578
+ DEFAULT_CUSTOM_REDTEAM_CONFIG = RedTeamCustomConfig()
579
+ DEFAULT_CUSTOM_REDTEAM_CONFIG_WITH_SAVED_MODEL = RedTeamCustomConfigWithSavedModel()
@@ -92,7 +92,7 @@ class GuardrailsClient(BaseClient):
92
92
  try:
93
93
  response = self._request("GET", "/guardrails/health")
94
94
  if response.get("error"):
95
- raise GuardrailsClientError(response["error"])
95
+ raise GuardrailsClientError(f"API Error: {str(response)}")
96
96
  return GuardrailsHealthResponse.from_dict(response)
97
97
  except Exception as e:
98
98
  raise GuardrailsClientError(str(e))
@@ -104,7 +104,7 @@ class GuardrailsClient(BaseClient):
104
104
  try:
105
105
  response = self._request("GET", "/guardrails/status")
106
106
  if response.get("error"):
107
- raise GuardrailsClientError(response["error"])
107
+ raise GuardrailsClientError(f"API Error: {str(response)}")
108
108
  return GuardrailsHealthResponse.from_dict(response)
109
109
  except Exception as e:
110
110
  raise GuardrailsClientError(str(e))
@@ -116,7 +116,7 @@ class GuardrailsClient(BaseClient):
116
116
  try:
117
117
  response = self._request("GET", "/guardrails/models")
118
118
  if response.get("error"):
119
- raise GuardrailsClientError(response["error"])
119
+ raise GuardrailsClientError(f"API Error: {str(response)}")
120
120
  return GuardrailsModelsResponse.from_dict(response)
121
121
  except Exception as e:
122
122
  raise GuardrailsClientError(str(e))
@@ -152,7 +152,7 @@ class GuardrailsClient(BaseClient):
152
152
  try:
153
153
  response = self._request("POST", "/guardrails/detect", json=payload)
154
154
  if response.get("error"):
155
- raise GuardrailsClientError(response["error"])
155
+ raise GuardrailsClientError(f"API Error: {str(response)}")
156
156
  return GuardrailsDetectResponse.from_dict(response)
157
157
  except Exception as e:
158
158
  raise GuardrailsClientError(str(e))
@@ -188,7 +188,7 @@ class GuardrailsClient(BaseClient):
188
188
  try:
189
189
  response = self._request("POST", "/guardrails/batch/detect", json=payload)
190
190
  if isinstance(response, dict) and response.get("error"):
191
- raise GuardrailsClientError(response["error"])
191
+ raise GuardrailsClientError(f"API Error: {str(response)}")
192
192
  return GuardrailsBatchDetectResponse.from_dict(response)
193
193
  except Exception as e:
194
194
  raise GuardrailsClientError(str(e))
@@ -207,7 +207,7 @@ class GuardrailsClient(BaseClient):
207
207
  try:
208
208
  response = self._request("POST", "/guardrails/pii", json=payload)
209
209
  if response.get("error"):
210
- raise GuardrailsClientError(response["error"])
210
+ raise GuardrailsClientError(f"API Error: {str(response)}")
211
211
  return GuardrailsPIIResponse.from_dict(response)
212
212
  except Exception as e:
213
213
  raise GuardrailsClientError(str(e))
@@ -225,7 +225,7 @@ class GuardrailsClient(BaseClient):
225
225
  try:
226
226
  response = self._request("POST", "/guardrails/hallucination", json=payload)
227
227
  if response.get("error"):
228
- raise GuardrailsClientError(response["error"])
228
+ raise GuardrailsClientError(f"API Error: {str(response)}")
229
229
  return GuardrailsHallucinationResponse.from_dict(response)
230
230
  except Exception as e:
231
231
  raise GuardrailsClientError(str(e))
@@ -242,7 +242,7 @@ class GuardrailsClient(BaseClient):
242
242
  try:
243
243
  response = self._request("POST", "/guardrails/adherence", json=payload)
244
244
  if response.get("error"):
245
- raise GuardrailsClientError(response["error"])
245
+ raise GuardrailsClientError(f"API Error: {str(response)}")
246
246
  return GuardrailsAdherenceResponse.from_dict(response)
247
247
  except Exception as e:
248
248
  raise GuardrailsClientError(str(e))
@@ -259,7 +259,7 @@ class GuardrailsClient(BaseClient):
259
259
  try:
260
260
  response = self._request("POST", "/guardrails/relevancy", json=payload)
261
261
  if response.get("error"):
262
- raise GuardrailsClientError(response["error"])
262
+ raise GuardrailsClientError(f"API Error: {str(response)}")
263
263
  return GuardrailsRelevancyResponse.from_dict(response)
264
264
  except Exception as e:
265
265
  raise GuardrailsClientError(str(e))
@@ -293,7 +293,7 @@ class GuardrailsClient(BaseClient):
293
293
  try:
294
294
  response = self._request("POST", "/guardrails/add-policy", json=payload)
295
295
  if response.get("error"):
296
- raise GuardrailsClientError(response["error"])
296
+ raise GuardrailsClientError(f"API Error: {str(response)}")
297
297
  return GuardrailsaPolicyResponse.from_dict(response)
298
298
  except Exception as e:
299
299
  raise GuardrailsClientError(str(e))
@@ -307,7 +307,7 @@ class GuardrailsClient(BaseClient):
307
307
  try:
308
308
  response = self._request("GET", "/guardrails/get-policy", headers=headers)
309
309
  if response.get("error"):
310
- raise GuardrailsClientError(response["error"])
310
+ raise GuardrailsClientError(f"API Error: {str(response)}")
311
311
  return GuardrailsPolicyData.from_dict(response)
312
312
  except Exception as e:
313
313
  raise GuardrailsClientError(str(e))
@@ -335,7 +335,7 @@ class GuardrailsClient(BaseClient):
335
335
  try:
336
336
  response = self._request("PATCH", "/guardrails/modify-policy", headers=headers, json=payload)
337
337
  if response.get("error"):
338
- raise GuardrailsClientError(response["error"])
338
+ raise GuardrailsClientError(f"API Error: {str(response)}")
339
339
  return GuardrailsaPolicyResponse.from_dict(response)
340
340
  except Exception as e:
341
341
  raise GuardrailsClientError(str(e))
@@ -349,7 +349,7 @@ class GuardrailsClient(BaseClient):
349
349
  try:
350
350
  response = self._request("DELETE", "/guardrails/delete-policy", headers=headers)
351
351
  if response.get("error"):
352
- raise GuardrailsClientError(response["error"])
352
+ raise GuardrailsClientError(f"API Error: {str(response)}")
353
353
  return GuardrailsDeletePolicyResponse.from_dict(response)
354
354
  except Exception as e:
355
355
  raise GuardrailsClientError(str(e))
@@ -364,7 +364,7 @@ class GuardrailsClient(BaseClient):
364
364
  try:
365
365
  response = self._request("POST", "/guardrails/policy/detect", headers=headers, json=payload)
366
366
  if response.get("error"):
367
- raise GuardrailsClientError(response["error"])
367
+ raise GuardrailsClientError(f"API Error: {str(response)}")
368
368
  return GuardrailsDetectResponse.from_dict(response)
369
369
  except Exception as e:
370
370
  raise GuardrailsClientError(str(e))
@@ -377,7 +377,7 @@ class GuardrailsClient(BaseClient):
377
377
  try:
378
378
  response = self._request("GET", "/guardrails/list-policies")
379
379
  if isinstance(response, dict) and response.get("error"):
380
- raise GuardrailsClientError(response["error"])
380
+ raise GuardrailsClientError(f"API Error: {str(response)}")
381
381
  return GuardrailsListPoliciesResponse.from_dict(response)
382
382
  except Exception as e:
383
383
  raise GuardrailsClientError(str(e))
enkryptai_sdk/models.py CHANGED
@@ -15,18 +15,20 @@ class ModelClient(BaseClient):
15
15
  def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com:443"):
16
16
  super().__init__(api_key, base_url)
17
17
 
18
- def add_model(self, config: ModelConfig) -> ModelResponse:
18
+ @staticmethod
19
+ def prepare_model_payload(config: ModelConfig | dict, is_custom: bool = False) -> dict:
19
20
  """
20
- Add a new model configuration to the system.
21
-
21
+ Prepare the payload for model operations from a config object.
22
+
22
23
  Args:
23
- config (ModelConfig): Configuration object containing model details
24
-
24
+ config (Union[ModelConfig, dict]): Configuration object or dictionary containing model details
25
+
25
26
  Returns:
26
- dict: Response from the API containing the added model details
27
+ dict: Processed payload ready for API submission
27
28
  """
28
- headers = {"Content-Type": "application/json"}
29
- config = ModelConfig.from_dict(config)
29
+ if isinstance(config, dict):
30
+ config = ModelConfig.from_dict(config)
31
+
30
32
  # Parse endpoint_url into components
31
33
  parsed_url = urlparse(config.model_config.endpoint_url)
32
34
  path_parts = parsed_url.path.strip("/").split("/")
@@ -43,15 +45,11 @@ class ModelClient(BaseClient):
43
45
  paths = config.model_config.paths.to_dict()
44
46
  else:
45
47
  paths = {
46
- "completions": (
47
- f"/{remaining_path.split('/')[-1]}" if remaining_path else ""
48
- ),
48
+ "completions": f"/{remaining_path.split('/')[-1]}" if remaining_path else "",
49
49
  "chat": f"/{remaining_path}" if remaining_path else "",
50
50
  }
51
51
 
52
52
  payload = {
53
- "model_saved_name": config.model_saved_name,
54
- "model_version": config.model_version,
55
53
  "testing_for": config.testing_for,
56
54
  "model_name": config.model_name,
57
55
  "certifications": config.certifications,
@@ -63,9 +61,8 @@ class ModelClient(BaseClient):
63
61
  "endpoint": {
64
62
  "scheme": parsed_url.scheme,
65
63
  "host": parsed_url.hostname,
66
- "port": parsed_url.port
67
- or (443 if parsed_url.scheme == "https" else 80),
68
- "base_path": f"/{base_path}", # Just v1
64
+ "port": parsed_url.port or (443 if parsed_url.scheme == "https" else 80),
65
+ "base_path": f"/{base_path}",
69
66
  },
70
67
  "paths": paths,
71
68
  "auth_data": {
@@ -73,9 +70,7 @@ class ModelClient(BaseClient):
73
70
  "header_prefix": config.model_config.auth_data.header_prefix,
74
71
  "space_after_prefix": config.model_config.auth_data.space_after_prefix,
75
72
  },
76
- "apikeys": (
77
- [config.model_config.apikey] if config.model_config.apikey else []
78
- ),
73
+ "apikeys": [config.model_config.apikey] if config.model_config.apikey else [],
79
74
  "tools": config.model_config.tools,
80
75
  "input_modalities": config.model_config.input_modalities,
81
76
  "output_modalities": config.model_config.output_modalities,
@@ -87,12 +82,32 @@ class ModelClient(BaseClient):
87
82
  "default_request_options": config.model_config.default_request_options,
88
83
  },
89
84
  }
85
+
86
+ if not is_custom:
87
+ payload["model_saved_name"] = config.model_saved_name
88
+ payload["model_version"] = config.model_version
89
+
90
+ return payload
91
+
92
+ def add_model(self, config: ModelConfig) -> ModelResponse:
93
+ """
94
+ Add a new model configuration to the system.
95
+
96
+ Args:
97
+ config (ModelConfig): Configuration object containing model details
98
+
99
+ Returns:
100
+ dict: Response from the API containing the added model details
101
+ """
102
+ headers = {"Content-Type": "application/json"}
103
+ payload = self.prepare_model_payload(config)
104
+
90
105
  try:
91
106
  response = self._request(
92
107
  "POST", "/models/add-model", headers=headers, json=payload
93
108
  )
94
109
  if response.get("error"):
95
- raise ModelClientError(response["error"])
110
+ raise ModelClientError(f"API Error: {str(response)}")
96
111
  return ModelResponse.from_dict(response)
97
112
  except Exception as e:
98
113
  raise ModelClientError(str(e))
@@ -112,7 +127,7 @@ class ModelClient(BaseClient):
112
127
  response = self._request("GET", "/models/get-model", headers=headers)
113
128
  # print(response)
114
129
  if response.get("error"):
115
- raise ModelClientError(response["error"])
130
+ raise ModelClientError(f"API Error: {str(response)}")
116
131
  return ModelConfig.from_dict(response)
117
132
 
118
133
  def get_model_list(self):
@@ -125,7 +140,7 @@ class ModelClient(BaseClient):
125
140
  try:
126
141
  response = self._request("GET", "/models/list-models")
127
142
  if isinstance(response, dict) and response.get("error"):
128
- raise ModelClientError(response["error"])
143
+ raise ModelClientError(f"API Error: {str(response)}")
129
144
  return ModelCollection.from_dict(response)
130
145
  except Exception as e:
131
146
  return {"error": str(e)}
@@ -217,7 +232,7 @@ class ModelClient(BaseClient):
217
232
  "PATCH", "/models/modify-model", headers=headers, json=payload
218
233
  )
219
234
  if response.get("error"):
220
- raise ModelClientError(response["error"])
235
+ raise ModelClientError(f"API Error: {str(response)}")
221
236
  return ModelResponse.from_dict(response)
222
237
  except Exception as e:
223
238
  raise ModelClientError(str(e))
@@ -238,7 +253,7 @@ class ModelClient(BaseClient):
238
253
  try:
239
254
  response = self._request("DELETE", "/models/delete-model", headers=headers)
240
255
  if response.get("error"):
241
- raise ModelClientError(response["error"])
256
+ raise ModelClientError(f"API Error: {str(response)}")
242
257
  return ModelResponse.from_dict(response)
243
258
  except Exception as e:
244
259
  raise ModelClientError(str(e))
enkryptai_sdk/red_team.py CHANGED
@@ -1,11 +1,15 @@
1
1
  import urllib3
2
2
  from .base import BaseClient
3
+ from .models import ModelClient
4
+ from .datasets import DatasetClient
3
5
  from .dto import (
4
6
  RedteamHealthResponse,
5
7
  RedTeamModelHealthConfig,
6
8
  RedteamModelHealthResponse,
7
9
  RedTeamConfig,
8
10
  RedTeamConfigWithSavedModel,
11
+ RedTeamCustomConfig,
12
+ RedTeamCustomConfigWithSavedModel,
9
13
  RedTeamResponse,
10
14
  RedTeamResultSummary,
11
15
  RedTeamResultDetails,
@@ -47,7 +51,7 @@ class RedTeamClient(BaseClient):
47
51
  try:
48
52
  response = self._request("GET", "/redteam/health")
49
53
  if response.get("error"):
50
- raise RedTeamClientError(response["error"])
54
+ raise RedTeamClientError(f"API Error: {str(response)}")
51
55
  return RedteamHealthResponse.from_dict(response)
52
56
  except Exception as e:
53
57
  raise RedTeamClientError(str(e))
@@ -61,7 +65,7 @@ class RedTeamClient(BaseClient):
61
65
  response = self._request("POST", "/redteam/model-health", json=config.to_dict())
62
66
  # if response.get("error"):
63
67
  if response.get("error") not in [None, ""]:
64
- raise RedTeamClientError(response["error"])
68
+ raise RedTeamClientError(f"API Error: {str(response)}")
65
69
  return RedteamModelHealthResponse.from_dict(response)
66
70
  except Exception as e:
67
71
  raise RedTeamClientError(str(e))
@@ -78,7 +82,7 @@ class RedTeamClient(BaseClient):
78
82
  response = self._request("POST", "/redteam/model/model-health", headers=headers)
79
83
  # if response.get("error"):
80
84
  if response.get("error") not in [None, ""]:
81
- raise RedTeamClientError(response["error"])
85
+ raise RedTeamClientError(f"API Error: {str(response)}")
82
86
  return RedteamModelHealthResponse.from_dict(response)
83
87
  except Exception as e:
84
88
  raise RedTeamClientError(str(e))
@@ -115,7 +119,7 @@ class RedTeamClient(BaseClient):
115
119
  json=payload,
116
120
  )
117
121
  if response.get("error"):
118
- raise RedTeamClientError(response["error"])
122
+ raise RedTeamClientError(f"API Error: {str(response)}")
119
123
  return RedTeamResponse.from_dict(response)
120
124
  else:
121
125
  raise RedTeamClientError(
@@ -163,7 +167,118 @@ class RedTeamClient(BaseClient):
163
167
  json=payload,
164
168
  )
165
169
  if response.get("error"):
166
- raise RedTeamClientError(response["error"])
170
+ raise RedTeamClientError(f"API Error: {str(response)}")
171
+ return RedTeamResponse.from_dict(response)
172
+
173
+ def add_custom_task(
174
+ self,
175
+ config: RedTeamCustomConfig,
176
+ policy_name: str = None,
177
+ ):
178
+ """
179
+ Add a new custom red teaming task.
180
+ """
181
+ headers = {
182
+ "Content-Type": "application/json",
183
+ }
184
+
185
+ if policy_name is not None:
186
+ headers["X-Enkrypt-Policy"] = policy_name
187
+
188
+ config = RedTeamCustomConfig.from_dict(config)
189
+ test_configs = config.redteam_test_configurations.to_dict()
190
+ # Remove None or empty test configurations
191
+ test_configs = {k: v for k, v in test_configs.items() if v is not None}
192
+
193
+ payload = {
194
+ # "async": config.async_enabled,
195
+ "test_name": config.test_name,
196
+ "redteam_test_configurations": {
197
+ k: v.to_dict() for k, v in test_configs.items()
198
+ },
199
+ }
200
+
201
+ if config.dataset_configuration:
202
+ payload["dataset_configuration"] = DatasetClient.prepare_dataset_payload(
203
+ config.dataset_configuration, True)
204
+ else:
205
+ raise RedTeamClientError(
206
+ "Please provide a dataset configuration"
207
+ )
208
+
209
+ if config.endpoint_configuration:
210
+ payload["endpoint_configuration"] = ModelClient.prepare_model_payload(
211
+ config.endpoint_configuration, True)
212
+ # print(payload)
213
+
214
+ response = self._request(
215
+ "POST",
216
+ "/redteam/v2/add-custom-task",
217
+ headers=headers,
218
+ json=payload,
219
+ )
220
+ if response.get("error"):
221
+ raise RedTeamClientError(f"API Error: {str(response)}")
222
+ return RedTeamResponse.from_dict(response)
223
+ else:
224
+ raise RedTeamClientError(
225
+ "Please provide a endpoint configuration"
226
+ )
227
+
228
+ def add_custom_task_with_saved_model(
229
+ self,
230
+ config: RedTeamCustomConfigWithSavedModel,
231
+ model_saved_name: str,
232
+ model_version: str,
233
+ policy_name: str = None,
234
+ ):
235
+ """
236
+ Add a new red teaming custom task using a saved model.
237
+ """
238
+ if not model_saved_name:
239
+ raise RedTeamClientError("Please provide a model_saved_name")
240
+
241
+ if not model_version:
242
+ raise RedTeamClientError("Please provide a model_version. Default is 'v1'")
243
+
244
+ config = RedTeamCustomConfigWithSavedModel.from_dict(config)
245
+ test_configs = config.redteam_test_configurations.to_dict()
246
+ # Remove None or empty test configurations
247
+ test_configs = {k: v for k, v in test_configs.items() if v is not None}
248
+
249
+ payload = {
250
+ # "async": config.async_enabled,
251
+ "test_name": config.test_name,
252
+ "redteam_test_configurations": {
253
+ k: v.to_dict() for k, v in test_configs.items()
254
+ },
255
+ }
256
+
257
+ if config.dataset_configuration:
258
+ payload["dataset_configuration"] = DatasetClient.prepare_dataset_payload(
259
+ config.dataset_configuration, True)
260
+ else:
261
+ raise RedTeamClientError(
262
+ "Please provide a dataset configuration"
263
+ )
264
+
265
+ headers = {
266
+ "X-Enkrypt-Model": model_saved_name,
267
+ "X-Enkrypt-Model-Version": model_version,
268
+ "Content-Type": "application/json",
269
+ }
270
+
271
+ if policy_name is not None:
272
+ headers["X-Enkrypt-Policy"] = policy_name
273
+
274
+ response = self._request(
275
+ "POST",
276
+ "/redteam/v2/model/add-custom-task",
277
+ headers=headers,
278
+ json=payload,
279
+ )
280
+ if response.get("error"):
281
+ raise RedTeamClientError(f"API Error: {str(response)}")
167
282
  return RedTeamResponse.from_dict(response)
168
283
 
169
284
  def status(self, task_id: str = None, test_name: str = None):
@@ -191,7 +306,7 @@ class RedTeamClient(BaseClient):
191
306
 
192
307
  response = self._request("GET", "/redteam/task-status", headers=headers)
193
308
  if response.get("error"):
194
- raise RedTeamClientError(response["error"])
309
+ raise RedTeamClientError(f"API Error: {str(response)}")
195
310
  return RedTeamTaskStatus.from_dict(response)
196
311
 
197
312
  def cancel_task(self, task_id: str = None, test_name: str = None):
@@ -224,7 +339,7 @@ class RedTeamClient(BaseClient):
224
339
 
225
340
  response = self._request("POST", "/redteam/cancel-task", headers=headers)
226
341
  if response.get("error"):
227
- raise RedTeamClientError(response["error"])
342
+ raise RedTeamClientError(f"API Error: {str(response)}")
228
343
  return response
229
344
 
230
345
  def get_task(self, task_id: str = None, test_name: str = None):
@@ -252,7 +367,7 @@ class RedTeamClient(BaseClient):
252
367
 
253
368
  response = self._request("GET", "/redteam/get-task", headers=headers)
254
369
  if response.get("error"):
255
- raise RedTeamClientError(response["error"])
370
+ raise RedTeamClientError(f"API Error: {str(response)}")
256
371
  return RedTeamTaskDetails.from_dict(response["data"])
257
372
 
258
373
  def get_result_summary(self, task_id: str = None, test_name: str = None):
@@ -280,7 +395,7 @@ class RedTeamClient(BaseClient):
280
395
 
281
396
  response = self._request("GET", "/redteam/results/summary", headers=headers)
282
397
  if response.get("error"):
283
- raise RedTeamClientError(response["error"])
398
+ raise RedTeamClientError(f"API Error: {str(response)}")
284
399
  # print(f"Response: {response}")
285
400
  return RedTeamResultSummary.from_dict(response)
286
401
 
@@ -314,7 +429,7 @@ class RedTeamClient(BaseClient):
314
429
  url = f"/redteam/v2/results/summary/{test_type}"
315
430
  response = self._request("GET", url, headers=headers)
316
431
  if response.get("error"):
317
- raise RedTeamClientError(response["error"])
432
+ raise RedTeamClientError(f"API Error: {str(response)}")
318
433
  # print(f"Response: {response}")
319
434
  return RedTeamResultSummary.from_dict(response)
320
435
 
@@ -343,7 +458,7 @@ class RedTeamClient(BaseClient):
343
458
 
344
459
  response = self._request("GET", "/redteam/v2/results/details", headers=headers)
345
460
  if response.get("error"):
346
- raise RedTeamClientError(response["error"])
461
+ raise RedTeamClientError(f"API Error: {str(response)}")
347
462
  return RedTeamResultDetails.from_dict(response)
348
463
 
349
464
  def get_result_details_test_type(self, task_id: str = None, test_name: str = None, test_type: str = None):
@@ -377,7 +492,7 @@ class RedTeamClient(BaseClient):
377
492
  url = f"/redteam/v2/results/details/{test_type}"
378
493
  response = self._request("GET", url, headers=headers)
379
494
  if response.get("error"):
380
- raise RedTeamClientError(response["error"])
495
+ raise RedTeamClientError(f"API Error: {str(response)}")
381
496
  return RedTeamResultDetails.from_dict(response)
382
497
 
383
498
  def get_task_list(self, status: str = None):
@@ -396,5 +511,5 @@ class RedTeamClient(BaseClient):
396
511
 
397
512
  response = self._request("GET", url)
398
513
  if isinstance(response, dict) and response.get("error"):
399
- raise RedTeamClientError(response["error"])
514
+ raise RedTeamClientError(f"API Error: {str(response)}")
400
515
  return RedTeamTaskList.from_dict(response)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: enkryptai-sdk
3
- Version: 1.0.7
3
+ Version: 1.0.8
4
4
  Summary: A Python SDK with guardrails and red teaming functionality for API interactions
5
5
  Home-page: https://github.com/enkryptai/enkryptai-sdk
6
6
  Author: Enkrypt AI Team
@@ -47,6 +47,8 @@ Also see the API documentation at [https://docs.enkryptai.com](https://docs.enkr
47
47
  - [Sample Redteam Model Health Config](#sample-redteam-model-health-config)
48
48
  - [Sample Redteam Target Config](#sample-redteam-target-config)
49
49
  - [Sample Redteam Model Config](#sample-redteam-model-config)
50
+ - [Sample Custom Redteam Target Config](#sample-custom-redteam-target-config)
51
+ - [Sample Custom Redteam Model Config](#sample-custom-redteam-model-config)
50
52
  - [Health Checks](#health-checks)
51
53
  - [Guardrails Health](#guardrails-health)
52
54
  - [Guardrails Status](#guardrails-status)
@@ -106,6 +108,8 @@ Also see the API documentation at [https://docs.enkryptai.com](https://docs.enkr
106
108
  - [Redteam](#redteam)
107
109
  - [Add a Redteam Task with Target Model Config](#add-a-redteam-task-with-target-model-config)
108
110
  - [Add a Redteam Task with a saved model](#add-a-redteam-task-with-a-saved-model)
111
+ - [Add a Redteam Custom Task with Endpoint Config](#add-a-redteam-custom-task-with-endpoint-config)
112
+ - [Add a Redteam Custom Task with a saved model](#add-a-redteam-custom-task-with-a-saved-model)
109
113
  - [Get Redteam Task Status](#get-redteam-task-status)
110
114
  - [Get Redteam Task](#get-redteam-task)
111
115
  - [List Redteam Tasks](#list-redteam-tasks)
@@ -193,6 +197,7 @@ pii_anonymized_text = None
193
197
  dataset_name = f"TestElectionDataset-{str(uuid.uuid4())[:8]}"
194
198
 
195
199
  redteam_test_name = f"Redteam Test {str(uuid.uuid4())[:6]}"
200
+ custom_redteam_test_name = f"Custom Redteam Test {str(uuid.uuid4())[:6]}"
196
201
 
197
202
  model_name = "gpt-4o-mini"
198
203
  model_provider = "openai"
@@ -422,6 +427,82 @@ sample_redteam_model_config = {
422
427
  }
423
428
  ```
424
429
 
430
+ ### [Sample Custom Redteam Target Config](https://docs.enkryptai.com/redteam-api-reference/endpoint/add-custom-task)
431
+
432
+ ```python Python
433
+ sample_custom_redteam_target_config = {
434
+ "test_name": custom_redteam_test_name,
435
+ "dataset_configuration": {
436
+ "system_description": "- **Voter Eligibility**: To vote in U.S. elections, individuals must be U.S. citizens, at least 18 years old by election day, and meet their state's residency requirements. - **Voter Registration**: Most states require voters to register ahead of time, with deadlines varying widely. North Dakota is an exception, as it does not require voter registration. - **Identification Requirements**: Thirty-six states enforce voter ID laws, requiring individuals to present identification at polling places. These laws aim to prevent voter fraud but can also lead to disenfranchisement. - **Voting Methods**: Voters can typically choose between in-person voting on election day, early voting, and absentee or mail-in ballots, depending on state regulations. - **Polling Hours**: Polling hours vary by state, with some states allowing extended hours for voters. Its essential for voters to check local polling times to ensure they can cast their ballots. - **Provisional Ballots**: If there are questions about a voter's eligibility, they may be allowed to cast a provisional ballot. This ballot is counted once eligibility is confirmed. - **Election Day Laws**: Many states have laws that protect the rights of voters on election day, including prohibiting intimidation and ensuring access to polling places. - **Campaign Finance Regulations**: Federal and state laws regulate contributions to candidates and political parties to ensure transparency and limit the influence of money in politics. - **Political Advertising**: Campaigns must adhere to rules regarding political advertising, including disclosure requirements about funding sources and content accuracy. - **Voter Intimidation Prohibitions**: Federal laws prohibit any form of voter intimidation or coercion at polling places, ensuring a safe environment for all voters. - **Accessibility Requirements**: The Americans with Disabilities Act mandates that polling places be accessible to individuals with disabilities, ensuring equal access to the electoral process. - **Election Monitoring**: Various organizations are allowed to monitor elections to ensure compliance with laws and regulations. They help maintain transparency and accountability in the electoral process. - **Vote Counting Procedures**: States have specific procedures for counting votes, including the use of electronic voting machines and manual audits to verify results. - **Ballot Design Standards**: States must adhere to certain design standards for ballots to ensure clarity and prevent confusion among voters when casting their votes. - **Post-Election Audits**: Some states conduct post-election audits as a measure of accuracy. These audits help verify that the vote count reflects the actual ballots cast.",
437
+ "policy_description": "Do not generate any content that is illegal, harmful, or violates the rights of others.",
438
+ # "risk_categories": "",
439
+ "tools": [
440
+ {
441
+ "name": "web_search",
442
+ "description": "The tool web search is used to search the web for information related to finance."
443
+ }
444
+ ],
445
+ "max_prompts": 100,
446
+ "scenarios": 2,
447
+ "categories": 2,
448
+ "depth": 2,
449
+ },
450
+ "redteam_test_configurations": {
451
+ "harmful_test": {
452
+ "sample_percentage": 2,
453
+ "attack_methods": {"basic": ["basic"]},
454
+ },
455
+ "custom_test": {
456
+ "sample_percentage": 2,
457
+ "attack_methods": {"basic": ["basic"]},
458
+ },
459
+ },
460
+ "endpoint_configuration": {
461
+ "testing_for": "foundationModels",
462
+ "model_name": model_name,
463
+ "model_config": {
464
+ "model_provider": model_provider,
465
+ "endpoint_url": model_endpoint_url,
466
+ "apikey": OPENAI_API_KEY,
467
+ "input_modalities": ["text"],
468
+ "output_modalities": ["text"],
469
+ },
470
+ },
471
+ }
472
+ ```
473
+
474
+ ### [Sample Custom Redteam Model Config](https://docs.enkryptai.com/redteam-api-reference/endpoint/model-add-custom-task)
475
+
476
+ ```python Python
477
+ sample_custom_redteam_model_config = {
478
+ "test_name": custom_redteam_test_name,
479
+ "dataset_configuration": {
480
+ "system_description": "- **Voter Eligibility**: To vote in U.S. elections, individuals must be U.S. citizens, at least 18 years old by election day, and meet their state's residency requirements. - **Voter Registration**: Most states require voters to register ahead of time, with deadlines varying widely. North Dakota is an exception, as it does not require voter registration. - **Identification Requirements**: Thirty-six states enforce voter ID laws, requiring individuals to present identification at polling places. These laws aim to prevent voter fraud but can also lead to disenfranchisement. - **Voting Methods**: Voters can typically choose between in-person voting on election day, early voting, and absentee or mail-in ballots, depending on state regulations. - **Polling Hours**: Polling hours vary by state, with some states allowing extended hours for voters. Its essential for voters to check local polling times to ensure they can cast their ballots. - **Provisional Ballots**: If there are questions about a voter's eligibility, they may be allowed to cast a provisional ballot. This ballot is counted once eligibility is confirmed. - **Election Day Laws**: Many states have laws that protect the rights of voters on election day, including prohibiting intimidation and ensuring access to polling places. - **Campaign Finance Regulations**: Federal and state laws regulate contributions to candidates and political parties to ensure transparency and limit the influence of money in politics. - **Political Advertising**: Campaigns must adhere to rules regarding political advertising, including disclosure requirements about funding sources and content accuracy. - **Voter Intimidation Prohibitions**: Federal laws prohibit any form of voter intimidation or coercion at polling places, ensuring a safe environment for all voters. - **Accessibility Requirements**: The Americans with Disabilities Act mandates that polling places be accessible to individuals with disabilities, ensuring equal access to the electoral process. - **Election Monitoring**: Various organizations are allowed to monitor elections to ensure compliance with laws and regulations. They help maintain transparency and accountability in the electoral process. - **Vote Counting Procedures**: States have specific procedures for counting votes, including the use of electronic voting machines and manual audits to verify results. - **Ballot Design Standards**: States must adhere to certain design standards for ballots to ensure clarity and prevent confusion among voters when casting their votes. - **Post-Election Audits**: Some states conduct post-election audits as a measure of accuracy. These audits help verify that the vote count reflects the actual ballots cast.",
481
+ "policy_description": "Do not generate any content that is illegal, harmful, or violates the rights of others.",
482
+ "tools": [
483
+ {
484
+ "name": "web_search",
485
+ "description": "The tool web search is used to search the web for information related to finance."
486
+ }
487
+ ],
488
+ "max_prompts": 100,
489
+ "scenarios": 2,
490
+ "categories": 2,
491
+ "depth": 2,
492
+ },
493
+ "redteam_test_configurations": {
494
+ "harmful_test": {
495
+ "sample_percentage": 2,
496
+ "attack_methods": {"basic": ["basic"]},
497
+ },
498
+ "custom_test": {
499
+ "sample_percentage": 2,
500
+ "attack_methods": {"basic": ["basic"]},
501
+ },
502
+ },
503
+ }
504
+ ```
505
+
425
506
  ## Health Checks
426
507
 
427
508
  ### [Guardrails Health](https://docs.enkryptai.com/guardrails-api-reference/endpoint/health-check)
@@ -1292,6 +1373,40 @@ assert add_redteam_model_response.message == "Redteam task has been added succes
1292
1373
  print(add_redteam_model_response.to_dict())
1293
1374
  ```
1294
1375
 
1376
+ ### [Add a Redteam Custom Task with Endpoint Config](https://docs.enkryptai.com/redteam-api-reference/endpoint/add-custom-task)
1377
+
1378
+ ```python Python
1379
+ # Use a dictionary to configure a redteam task
1380
+ add_custom_redteam_target_response = redteam_client.add_custom_task(config=copy.deepcopy(sample_custom_redteam_target_config))
1381
+
1382
+ # If you already saved a Code of Conduct Policy and want to use it, then instead of passing `dataset_configuration.policy_description` in the body, you can use the SDK like this:
1383
+ add_custom_redteam_target_response = redteam_client.add_custom_task(config=copy.deepcopy(sample_custom_redteam_target_config), policy_name="Code of Conduct Policy")
1384
+
1385
+ print(add_custom_redteam_target_response)
1386
+
1387
+ assert add_custom_redteam_target_response.message == "Task submitted successfully"
1388
+
1389
+ # Print as a dictionary
1390
+ print(add_custom_redteam_target_response.to_dict())
1391
+ ```
1392
+
1393
+ ### [Add a Redteam Custom Task with a saved model](https://docs.enkryptai.com/redteam-api-reference/endpoint/model-add-custom-task)
1394
+
1395
+ ```python Python
1396
+ # Use a dictionary to configure a redteam task
1397
+ add_custom_redteam_target_response = redteam_client.add_custom_task_with_saved_model(config=copy.deepcopy(sample_custom_redteam_model_config),model_saved_name=test_model_saved_name,model_version="v1")
1398
+
1399
+ # If you already saved a Code of Conduct Policy and want to use it, then instead of passing `dataset_configuration.policy_description` in the body, you can use the SDK like this:
1400
+ add_custom_redteam_target_response = redteam_client.add_custom_task_with_saved_model(config=copy.deepcopy(sample_custom_redteam_model_config),model_saved_name=test_model_saved_name,model_version="v1",policy_name="Code of Conduct Policy")
1401
+
1402
+ print(add_custom_redteam_target_response)
1403
+
1404
+ assert add_custom_redteam_target_response.message == "Task submitted successfully"
1405
+
1406
+ # Print as a dictionary
1407
+ print(add_custom_redteam_target_response.to_dict())
1408
+ ```
1409
+
1295
1410
  ### [Get Redteam Task Status](https://docs.enkryptai.com/redteam-api-reference/endpoint/get-task-status)
1296
1411
 
1297
1412
  ```python Python
@@ -0,0 +1,25 @@
1
+ enkryptai_sdk/__init__.py,sha256=rP6PtntJogJauj1lKWK8DkiBr3uYjireIUamr6aflu0,763
2
+ enkryptai_sdk/ai_proxy.py,sha256=ot1lqKk2LjcvlpnFm2kSA51vFThfquVlx86BhSbAzBo,3823
3
+ enkryptai_sdk/base.py,sha256=MlEDcEIjXo35kat9XkGUu7VB2fIvJk38C94wAeO9bEw,1304
4
+ enkryptai_sdk/config.py,sha256=IpB8_aO4zXdvv061v24oh83oyJ5Tp1QBQTzeuW4h9QY,8828
5
+ enkryptai_sdk/datasets.py,sha256=RQIR6spI2STXeVolYzBt6gPv6PD5AGh9krs16aKWdWA,6067
6
+ enkryptai_sdk/deployments.py,sha256=A7XZ2JwrMod9V4_aV8bFY_Soh9E3jHdwaTuJ9BwXuyk,4215
7
+ enkryptai_sdk/evals.py,sha256=BywyEgIT7xdJ58svO_sDNOMVowdB0RTGoAZPEbCnDVo,2595
8
+ enkryptai_sdk/guardrails.py,sha256=I5D8OxvJzz7t2jXNqNUj0_1Kl5K0b8zyPsXWAwiZu2o,13853
9
+ enkryptai_sdk/guardrails_old.py,sha256=SgzPZkTzbAPD9XfmYNG6M1-TrzbhDHpAkI3FjnVWS_s,6434
10
+ enkryptai_sdk/models.py,sha256=2H316e28Ssi_MHck0pAoydThRYSdAeSOlwwAoU7q86Q,10941
11
+ enkryptai_sdk/red_team.py,sha256=sJbhCuPfI9aowGvV71hRZslBp1HQa7bklbb89HU5tk8,18574
12
+ enkryptai_sdk/response.py,sha256=43JRubzgGCpoVxYNzBZY0AlUgLbfcXD_AwD7wU3qY9o,4086
13
+ enkryptai_sdk/dto/__init__.py,sha256=RMhr9QKMFuJVXQt3yN7uFwcFpX4PkRvqxjg3ZySUnjg,2505
14
+ enkryptai_sdk/dto/ai_proxy.py,sha256=clwMN4xdH8Zr55dnhilHbs-qaHRlCOrLPrij0Zd1Av0,11283
15
+ enkryptai_sdk/dto/base.py,sha256=6VWTkoNZ7uILqn_iYsPS21cVa2xLYpw5bjDIsRCS5tk,2389
16
+ enkryptai_sdk/dto/datasets.py,sha256=RFA9CmbhD-QDDyweBq_k9iBd00b6I6SWmdP9DPNd9fc,5002
17
+ enkryptai_sdk/dto/deployments.py,sha256=Aw4b8tDA3FYIomqDvCjblCXTagL4bT8Fx91X0SFXs40,11216
18
+ enkryptai_sdk/dto/guardrails.py,sha256=uolGPPF4v0l76MI5G0ofTtc9-r1l0_sqQqQkLEhAsf0,46305
19
+ enkryptai_sdk/dto/models.py,sha256=lNakMstGozgN_htY2_OItkjQnMQpw5tO9lCZVlywMIg,13442
20
+ enkryptai_sdk/dto/red_team.py,sha256=QtsT4GCnDs24WOF_RMxFtYjvIUULaw5temZ70aduevI,17966
21
+ enkryptai_sdk-1.0.8.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ enkryptai_sdk-1.0.8.dist-info/METADATA,sha256=CXU0oqhE8FABilK7dug8IBcP8OjetArrUXXsFc7fXM8,56401
23
+ enkryptai_sdk-1.0.8.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
24
+ enkryptai_sdk-1.0.8.dist-info/top_level.txt,sha256=s2X9UJJwvJamNmr6ZXWyyQe60sXtQGWFuaBYfhgHI_4,14
25
+ enkryptai_sdk-1.0.8.dist-info/RECORD,,
@@ -1,25 +0,0 @@
1
- enkryptai_sdk/__init__.py,sha256=rP6PtntJogJauj1lKWK8DkiBr3uYjireIUamr6aflu0,763
2
- enkryptai_sdk/ai_proxy.py,sha256=pD6kPmD9H0gttN28cezgV7_IVelLXAHNR5cPeXCM8Ew,3799
3
- enkryptai_sdk/base.py,sha256=MlEDcEIjXo35kat9XkGUu7VB2fIvJk38C94wAeO9bEw,1304
4
- enkryptai_sdk/config.py,sha256=IpB8_aO4zXdvv061v24oh83oyJ5Tp1QBQTzeuW4h9QY,8828
5
- enkryptai_sdk/datasets.py,sha256=2rAU1qeqBZz6rXxG4n9XM_8_ZQYNmcNFW-jgyw7nLPI,5364
6
- enkryptai_sdk/deployments.py,sha256=qXoUQtLYRSqZsAAqPgxJAad1a3mgMAbPx09NiOyAdsw,4155
7
- enkryptai_sdk/evals.py,sha256=BywyEgIT7xdJ58svO_sDNOMVowdB0RTGoAZPEbCnDVo,2595
8
- enkryptai_sdk/guardrails.py,sha256=F8sKaTDj9D1C0h3DTZXsmZpyCw0EuSFmVaCjxHemvqI,13673
9
- enkryptai_sdk/guardrails_old.py,sha256=SgzPZkTzbAPD9XfmYNG6M1-TrzbhDHpAkI3FjnVWS_s,6434
10
- enkryptai_sdk/models.py,sha256=ITxZT6uF_ihSnNvbJIzxAq74t9ZYEN8HM0z2z3Onwhg,10392
11
- enkryptai_sdk/red_team.py,sha256=IGL82OhO4nu9lAw9d6sRgfX9PyjkAQjP-9QTrusw_n8,14510
12
- enkryptai_sdk/response.py,sha256=43JRubzgGCpoVxYNzBZY0AlUgLbfcXD_AwD7wU3qY9o,4086
13
- enkryptai_sdk/dto/__init__.py,sha256=vG5PmG-L99v89AGiKF1QAF63YILk-e9w0dd665M3U60,2414
14
- enkryptai_sdk/dto/ai_proxy.py,sha256=clwMN4xdH8Zr55dnhilHbs-qaHRlCOrLPrij0Zd1Av0,11283
15
- enkryptai_sdk/dto/base.py,sha256=6VWTkoNZ7uILqn_iYsPS21cVa2xLYpw5bjDIsRCS5tk,2389
16
- enkryptai_sdk/dto/datasets.py,sha256=nI0VjgkViaAi49x01dTDfkzoynx5__zCfJLUsZG8kyw,4846
17
- enkryptai_sdk/dto/deployments.py,sha256=Aw4b8tDA3FYIomqDvCjblCXTagL4bT8Fx91X0SFXs40,11216
18
- enkryptai_sdk/dto/guardrails.py,sha256=uolGPPF4v0l76MI5G0ofTtc9-r1l0_sqQqQkLEhAsf0,46305
19
- enkryptai_sdk/dto/models.py,sha256=6BYF4XwzUwY8O_YgE9S7LPAvsQaRYtUV6ylkTYP7w10,13438
20
- enkryptai_sdk/dto/red_team.py,sha256=4VGxDGCsZsHi6yJsUZ64IXj6u84xZPcSQuME1PFSnSc,15243
21
- enkryptai_sdk-1.0.7.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- enkryptai_sdk-1.0.7.dist-info/METADATA,sha256=3NQrHgLSY_J0YpGnWHpgdOATcTaAz9Uxip9atFv1c-E,45959
23
- enkryptai_sdk-1.0.7.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
24
- enkryptai_sdk-1.0.7.dist-info/top_level.txt,sha256=s2X9UJJwvJamNmr6ZXWyyQe60sXtQGWFuaBYfhgHI_4,14
25
- enkryptai_sdk-1.0.7.dist-info/RECORD,,