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/dto/models.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from .base import BaseDTO
|
|
5
|
+
from tabulate import tabulate
|
|
1
6
|
from dataclasses import dataclass, field, asdict
|
|
2
7
|
from typing import Optional, List, Set, Dict, Any
|
|
3
|
-
from enum import Enum
|
|
4
|
-
import json
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
class Modality(Enum):
|
|
@@ -14,8 +17,30 @@ class Modality(Enum):
|
|
|
14
17
|
return self.value
|
|
15
18
|
|
|
16
19
|
|
|
20
|
+
class ModelProviders(str, Enum):
|
|
21
|
+
OPENAI = "openai"
|
|
22
|
+
AZURE_OPENAI = "azure_openai"
|
|
23
|
+
ANTHROPIC = "anthropic"
|
|
24
|
+
COHERE = "cohere"
|
|
25
|
+
MISTRAL = "mistral"
|
|
26
|
+
LLAMA = "llama"
|
|
27
|
+
BEDROCK = "bedrock"
|
|
28
|
+
GEMINI = "gemini"
|
|
29
|
+
HUGGINGFACE = "huggingface"
|
|
30
|
+
TOGETHER = "together"
|
|
31
|
+
GROQ = "groq"
|
|
32
|
+
AI21 = "ai21"
|
|
33
|
+
FIREWORKS = "fireworks"
|
|
34
|
+
ALIBABA = "alibaba"
|
|
35
|
+
PORTKEY = "portkey"
|
|
36
|
+
DEEPSEEK = "deepseek"
|
|
37
|
+
OPENAI_COMPATIBLE = "openai_compatible"
|
|
38
|
+
COHERE_COMPATIBLE = "cohere_compatible"
|
|
39
|
+
ANTHROPIC_COMPATIBLE = "anthropic_compatible"
|
|
40
|
+
|
|
41
|
+
|
|
17
42
|
@dataclass
|
|
18
|
-
class ModelResponse:
|
|
43
|
+
class ModelResponse(BaseDTO):
|
|
19
44
|
message: Optional[str] = None
|
|
20
45
|
data: Optional[Dict] = None
|
|
21
46
|
|
|
@@ -28,7 +53,7 @@ class ModelResponse:
|
|
|
28
53
|
|
|
29
54
|
|
|
30
55
|
@dataclass
|
|
31
|
-
class EndpointConfig:
|
|
56
|
+
class EndpointConfig(BaseDTO):
|
|
32
57
|
scheme: str = "https"
|
|
33
58
|
host: str = "api.openai.com"
|
|
34
59
|
port: int = 443
|
|
@@ -36,16 +61,19 @@ class EndpointConfig:
|
|
|
36
61
|
|
|
37
62
|
|
|
38
63
|
@dataclass
|
|
39
|
-
class PathsConfig:
|
|
64
|
+
class PathsConfig(BaseDTO):
|
|
40
65
|
completions: str = "/chat/completions"
|
|
41
66
|
chat: str = "chat/completions"
|
|
67
|
+
vision: str = "images"
|
|
68
|
+
embeddings: str = "embeddings"
|
|
42
69
|
|
|
43
70
|
|
|
44
71
|
@dataclass
|
|
45
|
-
class AuthData:
|
|
72
|
+
class AuthData(BaseDTO):
|
|
46
73
|
header_name: str = "Authorization"
|
|
47
74
|
header_prefix: str = "Bearer"
|
|
48
75
|
space_after_prefix: bool = True
|
|
76
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
49
77
|
|
|
50
78
|
def to_dict(self):
|
|
51
79
|
return asdict(self)
|
|
@@ -59,7 +87,8 @@ class AuthData:
|
|
|
59
87
|
class ModelDetailConfig:
|
|
60
88
|
model_version: Optional[str] = None
|
|
61
89
|
model_source: str = ""
|
|
62
|
-
model_provider: str = "openai"
|
|
90
|
+
# model_provider: str = "openai"
|
|
91
|
+
model_provider: ModelProviders = ModelProviders.OPENAI
|
|
63
92
|
system_prompt: str = ""
|
|
64
93
|
|
|
65
94
|
endpoint_url: str = "https://api.openai.com/v1/chat/completions"
|
|
@@ -77,26 +106,53 @@ class DetailModelConfig:
|
|
|
77
106
|
|
|
78
107
|
|
|
79
108
|
@dataclass
|
|
80
|
-
class ModelConfigDetails:
|
|
109
|
+
class ModelConfigDetails(BaseDTO):
|
|
110
|
+
model_id: str = ""
|
|
81
111
|
model_version: Optional[str] = None
|
|
82
112
|
model_source: str = ""
|
|
83
|
-
|
|
113
|
+
model_name: str = ""
|
|
114
|
+
# model_provider: str = "openai"
|
|
115
|
+
model_provider: ModelProviders = ModelProviders.OPENAI
|
|
116
|
+
model_api_value: str = ""
|
|
117
|
+
model_bearer_token: str = ""
|
|
118
|
+
model_auth_type: str = ""
|
|
119
|
+
model_api_key: str = ""
|
|
120
|
+
model_endpoint_url: str = ""
|
|
121
|
+
rate_per_min: int = 20
|
|
122
|
+
testing_for: str = "LLM"
|
|
123
|
+
headers: str = ""
|
|
84
124
|
system_prompt: str = ""
|
|
85
125
|
conversation_template: str = ""
|
|
86
|
-
is_compatible_with: str = "openai"
|
|
87
126
|
hosting_type: str = "External"
|
|
88
127
|
endpoint_url: str = "https://api.openai.com/v1/chat/completions"
|
|
128
|
+
paths: Optional[PathsConfig] = None
|
|
89
129
|
auth_data: AuthData = field(default_factory=AuthData)
|
|
90
130
|
apikey: Optional[str] = None
|
|
91
131
|
default_request_options: Dict[str, Any] = field(default_factory=dict)
|
|
132
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
92
133
|
|
|
93
134
|
@classmethod
|
|
94
135
|
def from_dict(cls, data: dict):
|
|
95
136
|
# Create a copy of the data to avoid modifying the original
|
|
96
137
|
data = data.copy()
|
|
97
138
|
|
|
139
|
+
# Validate model_provider if present
|
|
140
|
+
if "model_provider" in data:
|
|
141
|
+
provider = data["model_provider"]
|
|
142
|
+
# If it's a string, try to convert it to enum
|
|
143
|
+
if isinstance(provider, str):
|
|
144
|
+
try:
|
|
145
|
+
data["model_provider"] = ModelProviders(provider)
|
|
146
|
+
except ValueError:
|
|
147
|
+
valid_providers = [p.value for p in ModelProviders]
|
|
148
|
+
raise ValueError(f"Invalid model_provider: '{provider}'. Must be one of: {valid_providers}")
|
|
149
|
+
# If it's already an enum instance, keep it as is
|
|
150
|
+
elif not isinstance(provider, ModelProviders):
|
|
151
|
+
valid_providers = [p.value for p in ModelProviders]
|
|
152
|
+
raise ValueError(f"Invalid model_provider type. Valid values: {valid_providers}")
|
|
153
|
+
|
|
98
154
|
# Remove known fields that we don't want in our model
|
|
99
|
-
unwanted_fields = ["queryParams"
|
|
155
|
+
unwanted_fields = ["queryParams"]
|
|
100
156
|
for field in unwanted_fields:
|
|
101
157
|
data.pop(field, None)
|
|
102
158
|
|
|
@@ -106,8 +162,8 @@ class ModelConfigDetails:
|
|
|
106
162
|
if apikeys and not data.get("apikey"):
|
|
107
163
|
data["apikey"] = apikeys[0]
|
|
108
164
|
|
|
109
|
-
# Convert endpoint dict to endpoint_url if present
|
|
110
|
-
if "endpoint" in data:
|
|
165
|
+
# Convert endpoint dict to endpoint_url if present and endpoint_url is not already set
|
|
166
|
+
if "endpoint" in data and not data.get("endpoint_url"):
|
|
111
167
|
endpoint = data.pop("endpoint")
|
|
112
168
|
scheme = endpoint.get("scheme", "https")
|
|
113
169
|
host = endpoint.get("host", "")
|
|
@@ -127,14 +183,16 @@ class ModelConfigDetails:
|
|
|
127
183
|
auth_data = data.pop("auth_data", {})
|
|
128
184
|
auth_data_obj = AuthData.from_dict(auth_data)
|
|
129
185
|
|
|
130
|
-
#
|
|
131
|
-
|
|
132
|
-
|
|
186
|
+
# Handle nested PathsConfig only if present in data
|
|
187
|
+
paths_data = data.pop("paths", None)
|
|
188
|
+
paths_obj = (
|
|
189
|
+
PathsConfig.from_dict(paths_data) if paths_data is not None else None
|
|
190
|
+
)
|
|
133
191
|
|
|
134
|
-
return cls(**
|
|
192
|
+
return cls(**data, auth_data=auth_data_obj, paths=paths_obj)
|
|
135
193
|
|
|
136
194
|
def to_dict(self):
|
|
137
|
-
d =
|
|
195
|
+
d = super().to_dict()
|
|
138
196
|
# Handle AuthData specifically
|
|
139
197
|
d["auth_data"] = self.auth_data.to_dict()
|
|
140
198
|
return d
|
|
@@ -148,7 +206,7 @@ class ModelConfigDetails:
|
|
|
148
206
|
|
|
149
207
|
|
|
150
208
|
@dataclass
|
|
151
|
-
class ModelConfig:
|
|
209
|
+
class ModelConfig(BaseDTO):
|
|
152
210
|
created_at: str = ""
|
|
153
211
|
updated_at: str = ""
|
|
154
212
|
model_id: str = ""
|
|
@@ -157,36 +215,21 @@ class ModelConfig:
|
|
|
157
215
|
model_name: str = "gpt-4o-mini"
|
|
158
216
|
model_type: str = "text_2_text"
|
|
159
217
|
modality: Modality = Modality.TEXT
|
|
218
|
+
project_name: str = ""
|
|
160
219
|
certifications: List[str] = field(default_factory=list)
|
|
161
220
|
model_config: ModelConfigDetails = field(default_factory=ModelConfigDetails)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
"""Convert the ModelConfig instance to a dictionary."""
|
|
165
|
-
# First create a shallow copy of self as dict
|
|
166
|
-
d = {}
|
|
167
|
-
for field in self.__dataclass_fields__:
|
|
168
|
-
value = getattr(self, field)
|
|
169
|
-
if field == "modality":
|
|
170
|
-
d[field] = value.value
|
|
171
|
-
elif field == "model_config":
|
|
172
|
-
if isinstance(value, ModelConfigDetails):
|
|
173
|
-
d[field] = value.to_dict()
|
|
174
|
-
else:
|
|
175
|
-
d[field] = value
|
|
176
|
-
else:
|
|
177
|
-
d[field] = value
|
|
178
|
-
return d
|
|
179
|
-
|
|
180
|
-
def to_json(self) -> str:
|
|
181
|
-
"""Convert the ModelConfig instance to a JSON string."""
|
|
182
|
-
return json.dumps(self.to_dict())
|
|
221
|
+
is_sample: bool = False
|
|
222
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
183
223
|
|
|
184
224
|
@classmethod
|
|
185
225
|
def from_dict(cls, data: dict):
|
|
186
226
|
"""Create a ModelConfig instance from a dictionary."""
|
|
187
227
|
# Handle nested ModelConfigDetails
|
|
188
228
|
model_config_data = data.pop("model_config", {})
|
|
189
|
-
|
|
229
|
+
try:
|
|
230
|
+
model_config = ModelConfigDetails.from_dict(model_config_data)
|
|
231
|
+
except ValueError as e:
|
|
232
|
+
raise ValueError(f"Error in model_config: {str(e)}")
|
|
190
233
|
|
|
191
234
|
# Handle Modality enum
|
|
192
235
|
modality_value = data.pop("modality", "text")
|
|
@@ -195,11 +238,6 @@ class ModelConfig:
|
|
|
195
238
|
return cls(**data, modality=modality, model_config=model_config)
|
|
196
239
|
|
|
197
240
|
@classmethod
|
|
198
|
-
def from_json(cls, json_str: str):
|
|
199
|
-
"""Create a ModelConfig instance from a JSON string."""
|
|
200
|
-
data = json.loads(json_str)
|
|
201
|
-
return cls.from_dict(data)
|
|
202
|
-
|
|
203
241
|
def __str__(self):
|
|
204
242
|
"""String representation of the ModelConfig."""
|
|
205
243
|
return f"ModelConfig(name={self.model_saved_name}, model={self.model_name})"
|
|
@@ -211,5 +249,120 @@ class ModelConfig:
|
|
|
211
249
|
)
|
|
212
250
|
|
|
213
251
|
|
|
252
|
+
@dataclass
|
|
253
|
+
class ModelCollection(BaseDTO):
|
|
254
|
+
models: List[ModelConfig] = field(default_factory=list)
|
|
255
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
256
|
+
|
|
257
|
+
@classmethod
|
|
258
|
+
def from_dict(cls, data: dict):
|
|
259
|
+
"""Create a ModelCollection instance from a dictionary."""
|
|
260
|
+
models_data = data.get("models", [])
|
|
261
|
+
models = [ModelConfig.from_dict(model_data) for model_data in models_data]
|
|
262
|
+
return cls(models=models)
|
|
263
|
+
|
|
264
|
+
def to_dict(self) -> dict:
|
|
265
|
+
return {"models": [model.to_dict() for model in self.models]}
|
|
266
|
+
|
|
267
|
+
def to_json(self) -> str:
|
|
268
|
+
"""Convert the ModelCollection instance to a JSON string."""
|
|
269
|
+
return json.dumps(self.to_dict())
|
|
270
|
+
|
|
271
|
+
def to_dataframe(self) -> pd.DataFrame:
|
|
272
|
+
"""
|
|
273
|
+
Convert the model collection to a pandas DataFrame.
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
pd.DataFrame: DataFrame containing model data
|
|
277
|
+
"""
|
|
278
|
+
data = [model.get_all_fields() for model in self.models]
|
|
279
|
+
return pd.DataFrame(data)
|
|
280
|
+
|
|
281
|
+
def display_table(self, style: str = "default") -> str:
|
|
282
|
+
"""
|
|
283
|
+
Create a formatted table representation using pandas.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
style (str): Style of the output. Options:
|
|
287
|
+
- 'default': Standard pandas HTML table
|
|
288
|
+
- 'styled': Styled HTML table with custom formatting
|
|
289
|
+
- 'markdown': Markdown formatted table
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
str: Formatted table string
|
|
293
|
+
"""
|
|
294
|
+
if not self.models:
|
|
295
|
+
return "No models available"
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
df = self.to_dataframe()
|
|
299
|
+
|
|
300
|
+
if style == "styled":
|
|
301
|
+
styled_df = df.style.set_properties(
|
|
302
|
+
**{
|
|
303
|
+
"text-align": "left",
|
|
304
|
+
"padding": "8px",
|
|
305
|
+
"border": "1px solid #ddd",
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
styled_df = styled_df.set_table_styles(
|
|
309
|
+
[
|
|
310
|
+
{
|
|
311
|
+
"selector": "thead th",
|
|
312
|
+
"props": [
|
|
313
|
+
("background-color", "#f4f4f4"),
|
|
314
|
+
("color", "black"),
|
|
315
|
+
("font-weight", "bold"),
|
|
316
|
+
("padding", "10px"),
|
|
317
|
+
("border", "1px solid #ddd"),
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"selector": "tbody tr:nth-child(even)",
|
|
322
|
+
"props": [("background-color", "#f8f8f8")],
|
|
323
|
+
},
|
|
324
|
+
]
|
|
325
|
+
)
|
|
326
|
+
return styled_df.hide(axis="index").to_html()
|
|
327
|
+
|
|
328
|
+
elif style == "markdown":
|
|
329
|
+
return df.to_markdown(index=False)
|
|
330
|
+
|
|
331
|
+
else: # default
|
|
332
|
+
return df.to_html(index=False, classes="model-table")
|
|
333
|
+
|
|
334
|
+
except Exception as e:
|
|
335
|
+
return f"Error creating table: {str(e)}"
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
@dataclass
|
|
339
|
+
class Task(BaseDTO):
|
|
340
|
+
"""Represents an individual task in a task list."""
|
|
341
|
+
|
|
342
|
+
task_id: str
|
|
343
|
+
status: str
|
|
344
|
+
model_name: str
|
|
345
|
+
test_name: Optional[str] = None
|
|
346
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@dataclass
|
|
350
|
+
class TaskList(BaseDTO):
|
|
351
|
+
"""Represents a list of tasks."""
|
|
352
|
+
|
|
353
|
+
tasks: List[Task] = field(default_factory=list)
|
|
354
|
+
|
|
355
|
+
@classmethod
|
|
356
|
+
def from_dict(cls, data: Dict[str, Any]):
|
|
357
|
+
"""Create a TaskList instance from a dictionary."""
|
|
358
|
+
tasks_data = data.get("tasks", [])
|
|
359
|
+
tasks = [Task.from_dict(task_data) for task_data in tasks_data]
|
|
360
|
+
return cls(tasks=tasks)
|
|
361
|
+
|
|
362
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
363
|
+
"""Convert the TaskList instance to a dictionary."""
|
|
364
|
+
return {"tasks": [task.to_dict() for task in self.tasks]}
|
|
365
|
+
|
|
366
|
+
|
|
214
367
|
# Default configuration
|
|
215
368
|
DETAIL_MODEL_CONFIG = ModelConfig()
|