enkryptai-sdk 0.1.6__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
enkryptai_sdk/__init__.py CHANGED
@@ -1,13 +1,25 @@
1
- from .guardrails import GuardrailsClient
2
- from .config import GuardrailsConfig
3
1
  from .evals import EvalsClient
4
- from .models import ModelClient
5
- from .red_team import RedTeamClient
2
+ from .config import GuardrailsConfig
3
+ from .guardrails import GuardrailsClient, GuardrailsClientError
4
+ from .models import ModelClient, ModelClientError
5
+ from .red_team import RedTeamClient, RedTeamClientError
6
+ from .datasets import DatasetClient, DatasetClientError
7
+ from .deployments import DeploymentClient, DeploymentClientError
8
+ from .ai_proxy import AIProxyClient, AIProxyClientError
6
9
 
7
10
  __all__ = [
8
11
  "GuardrailsClient",
12
+ "GuardrailsClientError",
9
13
  "GuardrailsConfig",
10
14
  "EvalsClient",
11
15
  "ModelClient",
12
16
  "RedTeamClient",
17
+ "DatasetClient",
18
+ "DeploymentClient",
19
+ "ModelClientError",
20
+ "RedTeamClientError",
21
+ "DatasetClientError",
22
+ "DeploymentClientError",
23
+ "AIProxyClient",
24
+ "AIProxyClientError",
13
25
  ]
@@ -0,0 +1,70 @@
1
+ from .base import BaseClient
2
+ from .dto import (
3
+ ChatCompletionRequest,
4
+ ChatCompletionResponse,
5
+ ChatCompletionErrorResponse,
6
+ ChatCompletionDirectErrorResponse,
7
+ )
8
+
9
+
10
+ class AIProxyClientError(Exception):
11
+ pass
12
+
13
+
14
+ class AIProxyClient(BaseClient):
15
+ def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
16
+ super().__init__(api_key, base_url)
17
+
18
+ def chat(self, chat_body: ChatCompletionRequest, deployment_name: str, tags: str = None, refresh_cache: bool = False, return_error: bool = False):
19
+ """
20
+ Get chat completion response for a given prompt.
21
+
22
+ Args:
23
+ chat_body (ChatCompletionRequest): Configuration object containing chat details
24
+
25
+ Returns:
26
+ dict: Response from the API containing the chat completion response
27
+ """
28
+ headers = {"Content-Type": "application/json"}
29
+
30
+ if deployment_name is None:
31
+ raise AIProxyClientError("Deployment name is required")
32
+ headers["X-Enkrypt-Deployment"] = deployment_name
33
+
34
+ if tags is not None:
35
+ headers["X-Enkrypt-Tags"] = tags
36
+
37
+ if refresh_cache is not None:
38
+ headers["X-Enkrypt-Refresh-Cache"] = str(refresh_cache).lower()
39
+
40
+ if isinstance(chat_body, dict):
41
+ chat_body = ChatCompletionRequest.from_dict(chat_body)
42
+
43
+ payload = chat_body.to_dict()
44
+
45
+ response = self._request(
46
+ "POST", "/ai-proxy/chat/completions", headers=headers, json=payload
47
+ )
48
+
49
+ if response.get("error"):
50
+ error_message = response["error"]
51
+ is_json_str = error_message.startswith("{") and error_message.endswith("}")
52
+ # Try to parse nested JSON error if it's a string
53
+ if isinstance(error_message, str) and is_json_str:
54
+ import json
55
+ try:
56
+ error_message = json.loads(error_message.replace("'", '"'))
57
+ response["error"] = error_message.get("error", error_message)
58
+ except json.JSONDecodeError:
59
+ # If parsing fails, keep the original error
60
+ pass
61
+
62
+ # print("Error in response: ", response)
63
+ if return_error:
64
+ if is_json_str:
65
+ return ChatCompletionErrorResponse.from_dict(response)
66
+ else:
67
+ return ChatCompletionDirectErrorResponse.from_dict(response)
68
+ raise AIProxyClientError(response["error"])
69
+
70
+ return ChatCompletionResponse.from_dict(response)
enkryptai_sdk/base.py ADDED
@@ -0,0 +1,36 @@
1
+ import urllib3
2
+ from typing import Dict, Any
3
+
4
+
5
+ class BaseClient:
6
+ def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
7
+ if api_key is None:
8
+ raise ValueError("API key is required")
9
+ self.api_key = api_key
10
+ self.base_url = base_url.rstrip('/')
11
+ self.http = urllib3.PoolManager()
12
+ self.headers = {"apikey": self.api_key}
13
+
14
+ def _request(self, method, endpoint, payload=None, headers=None, **kwargs):
15
+ url = self.base_url + endpoint
16
+ request_headers = {
17
+ "Accept-Encoding": "gzip", # Add required gzip encoding
18
+ **self.headers,
19
+ }
20
+ if headers:
21
+ request_headers.update(headers)
22
+
23
+ try:
24
+ response = self.http.request(method, url, headers=request_headers, **kwargs)
25
+
26
+ if response.status >= 400:
27
+ error_data = (
28
+ response.json()
29
+ if response.data
30
+ else {"message": f"HTTP {response.status}"}
31
+ )
32
+ error_message = error_data.get("message", str(error_data))
33
+ raise urllib3.exceptions.HTTPError(error_message)
34
+ return response.json()
35
+ except urllib3.exceptions.HTTPError as e:
36
+ return {"error": str(e)}
@@ -0,0 +1,142 @@
1
+ from .base import BaseClient
2
+ from .dto import (
3
+ DatasetConfig,
4
+ DatasetCollection,
5
+ DatasetSummary,
6
+ DatasetResponse,
7
+ DatasetCard,
8
+ DatasetTaskStatus,
9
+ DatasetTask,
10
+ DatasetAddTaskResponse,
11
+ )
12
+
13
+
14
+ class DatasetClientError(Exception):
15
+ pass
16
+
17
+
18
+ class DatasetClient(BaseClient):
19
+ def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
20
+ super().__init__(api_key, base_url)
21
+
22
+ def add_dataset(self, config: DatasetConfig):
23
+ """
24
+ Add a new dataset to the system.
25
+
26
+ Args:
27
+ config (DatasetConfig): Configuration object containing dataset details
28
+
29
+ Returns:
30
+ dict: Response from the API containing the added dataset details
31
+ """
32
+ headers = {"Content-Type": "application/json"}
33
+
34
+ if isinstance(config, dict):
35
+ config = DatasetConfig.from_dict(config)
36
+
37
+ payload = config.to_dict()
38
+
39
+ response = self._request(
40
+ "POST", "/datasets/add-task", headers=headers, json=payload
41
+ )
42
+ if response.get("error"):
43
+ raise DatasetClientError(response["error"])
44
+ return DatasetAddTaskResponse.from_dict(response)
45
+
46
+ def get_dataset_task_status(self, dataset_name: str):
47
+ """
48
+ Get dataset task status for a specific dataset task.
49
+
50
+ Args:
51
+ dataset_name (str): The name of the dataset
52
+
53
+ Returns:
54
+ dict: Response from the API containing the dataset task status
55
+ """
56
+ headers = {"X-Enkrypt-Dataset": dataset_name}
57
+ response = self._request("GET", "/datasets/task-status", headers=headers)
58
+ if response.get("error"):
59
+ raise DatasetClientError(response["error"])
60
+ response["dataset_name"] = dataset_name
61
+ return DatasetTaskStatus.from_dict(response)
62
+
63
+ def get_dataset_task(self, dataset_name: str):
64
+ """
65
+ Get detailed information for a specific dataset task.
66
+
67
+ Args:
68
+ dataset_name (str): The name of the dataset
69
+
70
+ Returns:
71
+ dict: Response from the API containing the dataset task information
72
+ """
73
+ headers = {"X-Enkrypt-Dataset": dataset_name}
74
+ response = self._request("GET", "/datasets/get-task", headers=headers)
75
+ if response.get("error"):
76
+ raise DatasetClientError(response["error"])
77
+ response["dataset_name"] = dataset_name
78
+ return DatasetTask.from_dict(response)
79
+
80
+ def get_datacard(self, dataset_name: str):
81
+ """
82
+ Get datacard information for a specific dataset.
83
+
84
+ Args:
85
+ dataset_name (str): The name of the dataset
86
+
87
+ Returns:
88
+ dict: Response from the API containing the datacard information
89
+ """
90
+ headers = {"X-Enkrypt-Dataset": dataset_name}
91
+ response = self._request("GET", "/datasets/get-datacard", headers=headers)
92
+ if response.get("error"):
93
+ raise DatasetClientError(response["error"])
94
+ response["dataset_name"] = dataset_name
95
+ return DatasetCard.from_dict(response)
96
+
97
+ def get_dataset(self, dataset_name: str):
98
+ """
99
+ Get detailed information for a specific dataset.
100
+
101
+ Args:
102
+ dataset_name (str): The name of the dataset
103
+
104
+ Returns:
105
+ dict: Response from the API containing the dataset information
106
+ """
107
+ headers = {"X-Enkrypt-Dataset": dataset_name}
108
+ response = self._request("GET", "/datasets/get-dataset", headers=headers)
109
+ if response.get("error"):
110
+ raise DatasetClientError(response["error"])
111
+ response["dataset_name"] = dataset_name
112
+ return DatasetResponse.from_dict(response)
113
+
114
+ def get_summary(self, dataset_name: str):
115
+ """
116
+ Get summary information for a specific dataset.
117
+
118
+ Args:
119
+ dataset_name (str): The name of the dataset
120
+
121
+ Returns:
122
+ dict: Response from the API containing the dataset summary
123
+ """
124
+ headers = {"X-Enkrypt-Dataset": dataset_name}
125
+ response = self._request("GET", "/datasets/get-summary", headers=headers)
126
+ if response.get("error"):
127
+ raise DatasetClientError(response["error"])
128
+ response["dataset_name"] = dataset_name
129
+ return DatasetSummary.from_dict(response)
130
+
131
+ def list_datasets(self):
132
+ """
133
+ Get a list of all available dataset tasks.
134
+
135
+ Returns:
136
+ dict: Response from the API containing the list of dataset tasks
137
+ """
138
+
139
+ response = self._request("GET", "/datasets/list-tasks")
140
+ if response.get("error"):
141
+ raise DatasetClientError(response["error"])
142
+ return DatasetCollection.from_dict(response)
@@ -0,0 +1,121 @@
1
+ from .base import BaseClient
2
+ from .dto import (
3
+ # InputGuardrailBlockType,
4
+ # OutputGuardrailBlockType,
5
+ # InputGuardrailsAdditionalConfig,
6
+ # OutputGuardrailsAdditionalConfig,
7
+ # InputGuardrailsPolicy,
8
+ # OutputGuardrailsPolicy,
9
+ DeploymentInput,
10
+ DeploymentAddTaskResponse,
11
+ GetDeploymentResponse,
12
+ ModifyDeploymentResponse,
13
+ # DeleteDeploymentData,
14
+ DeleteDeploymentResponse,
15
+ # DeploymentSummary,
16
+ DeploymentCollection,
17
+ )
18
+
19
+
20
+ class DeploymentClientError(Exception):
21
+ pass
22
+
23
+
24
+ class DeploymentClient(BaseClient):
25
+ def __init__(self, api_key: str, base_url: str = "https://api.enkryptai.com"):
26
+ super().__init__(api_key, base_url)
27
+
28
+ def add_deployment(self, config: DeploymentInput):
29
+ """
30
+ Add a new deployment to the system.
31
+
32
+ Args:
33
+ config (DeploymentInput): Configuration object containing deployment details
34
+
35
+ Returns:
36
+ dict: Response from the API containing the added deployment details
37
+ """
38
+ headers = {"Content-Type": "application/json"}
39
+
40
+ if isinstance(config, dict):
41
+ config = DeploymentInput.from_dict(config)
42
+
43
+ payload = config.to_dict()
44
+
45
+ response = self._request(
46
+ "POST", "/deployments/add-deployment", headers=headers, json=payload
47
+ )
48
+ if response.get("error"):
49
+ raise DeploymentClientError(response["error"])
50
+ return DeploymentAddTaskResponse.from_dict(response)
51
+
52
+ def get_deployment(self, deployment_name: str, refresh_cache: bool = False):
53
+ """
54
+ Get detailed information for a specific deployment.
55
+
56
+ Args:
57
+ deployment_name (str): The name of the deployment
58
+ refresh_cache (bool): Whether to refresh the cache
59
+
60
+ Returns:
61
+ dict: Response from the API containing the deployment information
62
+ """
63
+ headers = {"X-Enkrypt-Deployment": deployment_name}
64
+ headers["X-Enkrypt-Refresh-Cache"] = "true" if refresh_cache else "false"
65
+ response = self._request("GET", "/deployments/get-deployment", headers=headers)
66
+ if response.get("error"):
67
+ raise DeploymentClientError(response["error"])
68
+ return GetDeploymentResponse.from_dict(response)
69
+
70
+ def modify_deployment(self, deployment_name: str, config: DeploymentInput):
71
+ """
72
+ Modify an existing deployment in the system.
73
+
74
+ Args:
75
+ config (DeploymentInput): Configuration object containing deployment details
76
+
77
+ Returns:
78
+ dict: Response from the API containing the modified deployment details
79
+ """
80
+ headers = {"Content-Type": "application/json", "X-Enkrypt-Deployment": deployment_name}
81
+
82
+ if isinstance(config, dict):
83
+ config = DeploymentInput.from_dict(config)
84
+
85
+ payload = config.to_dict()
86
+
87
+ response = self._request(
88
+ "PATCH", "/deployments/modify-deployment", headers=headers, json=payload
89
+ )
90
+ if response.get("error"):
91
+ raise DeploymentClientError(response["error"])
92
+ return ModifyDeploymentResponse.from_dict(response)
93
+
94
+ def delete_deployment(self, deployment_name: str):
95
+ """
96
+ Delete a deployment from the system.
97
+
98
+ Args:
99
+ deployment_name (str): The name of the deployment
100
+
101
+ Returns:
102
+ dict: Response from the API containing the deployment deleted
103
+ """
104
+ headers = {"X-Enkrypt-Deployment": deployment_name}
105
+ response = self._request("DELETE", "/deployments/delete-deployment", headers=headers)
106
+ if response.get("error"):
107
+ raise DeploymentClientError(response["error"])
108
+ return DeleteDeploymentResponse.from_dict(response)
109
+
110
+ def list_deployments(self):
111
+ """
112
+ Get a list of all available deployments.
113
+
114
+ Returns:
115
+ dict: Response from the API containing the list of deployments
116
+ """
117
+
118
+ response = self._request("GET", "/deployments/list-deployments")
119
+ if response.get("error"):
120
+ raise DeploymentClientError(response["error"])
121
+ return DeploymentCollection.from_dict(response)
@@ -1,7 +1,15 @@
1
1
  from .models import *
2
2
  from .red_team import *
3
+ from .datasets import *
4
+ from .deployments import *
5
+ from .ai_proxy import *
6
+ from .guardrails import *
7
+
3
8
 
4
9
  __all__ = [
10
+ "RedteamHealthResponse",
11
+ "RedTeamModelHealthConfig",
12
+ "RedteamModelHealthResponse",
5
13
  "DetailModelConfig",
6
14
  "ModelConfig",
7
15
  "RedTeamConfig",
@@ -15,4 +23,60 @@ __all__ = [
15
23
  "DEFAULT_REDTEAM_CONFIG",
16
24
  "ADVANCED_REDTEAM_TESTS",
17
25
  "DETAIL_MODEL_CONFIG",
26
+ "DatasetConfig",
27
+ "DatasetCollection",
28
+ "DatasetSummary",
29
+ "DatasetDataPoint",
30
+ "DatasetResponse",
31
+ "DatasetContent",
32
+ "DatasetTaskData",
33
+ "DatasetCard",
34
+ "DatasetTaskStatus",
35
+ "DatasetTask",
36
+ "DatasetAddTaskResponse",
37
+ "InputGuardrailBlockType",
38
+ "OutputGuardrailBlockType",
39
+ "InputGuardrailsAdditionalConfig",
40
+ "OutputGuardrailsAdditionalConfig",
41
+ "InputGuardrailsPolicy",
42
+ "OutputGuardrailsPolicy",
43
+ "DeploymentInput",
44
+ "DeploymentAddTaskResponse",
45
+ "GetDeploymentResponse",
46
+ "ModifyDeploymentResponse",
47
+ "DeleteDeploymentData",
48
+ "DeleteDeploymentResponse",
49
+ "DeploymentSummary",
50
+ "DeploymentCollection",
51
+ "ChatCompletionMessage",
52
+ "ChatCompletionRequest",
53
+ "ChatCompletionResponseMessage",
54
+ "ChatCompletionChoice",
55
+ "ChatCompletionUsage",
56
+ "ChatCompletionResponse",
57
+ "ChatCompletionError",
58
+ "ChatCompletionErrorResponse",
59
+ "ChatCompletionDirectErrorResponse",
60
+ "GuardrailsHealthResponse",
61
+ "GuardrailsModelsResponse",
62
+ "GuardrailDetectors",
63
+ "GuardrailsDetectRequest",
64
+ "GuardrailsPolicyDetectRequest",
65
+ "DetectResponseSummary",
66
+ "DetectResponseDetails",
67
+ "GuardrailsDetectResponse",
68
+ "GuardrailsPIIRequest",
69
+ "GuardrailsPIIResponse",
70
+ "GuardrailsHallucinationRequest",
71
+ "GuardrailsHallucinationResponse",
72
+ "GuardrailsAdherenceRequest",
73
+ "GuardrailsAdherenceResponse",
74
+ "GuardrailsRelevancyRequest",
75
+ "GuardrailsRelevancyResponse",
76
+ "GuardrailsPolicyRequest",
77
+ "GuardrailsPolicyData",
78
+ "GuardrailsaPolicyResponse",
79
+ "GuardrailsDeletePolicyData",
80
+ "GuardrailsDeletePolicyResponse",
81
+ "GuardrailsListPoliciesResponse",
18
82
  ]