enkryptai-sdk 0.1.5__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 +16 -4
- enkryptai_sdk/ai_proxy.py +70 -0
- enkryptai_sdk/base.py +36 -0
- enkryptai_sdk/datasets.py +142 -0
- enkryptai_sdk/deployments.py +121 -0
- enkryptai_sdk/dto/__init__.py +64 -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 +211 -45
- enkryptai_sdk/dto/red_team.py +279 -62
- enkryptai_sdk/guardrails.py +219 -70
- enkryptai_sdk/guardrails_old.py +195 -0
- enkryptai_sdk/models.py +136 -54
- enkryptai_sdk/red_team.py +167 -63
- enkryptai_sdk-0.1.7.dist-info/METADATA +1205 -0
- enkryptai_sdk-0.1.7.dist-info/RECORD +25 -0
- {enkryptai_sdk-0.1.5.dist-info → enkryptai_sdk-0.1.7.dist-info}/WHEEL +1 -1
- enkryptai_sdk-0.1.5.dist-info/METADATA +0 -301
- enkryptai_sdk-0.1.5.dist-info/RECORD +0 -15
- {enkryptai_sdk-0.1.5.dist-info → enkryptai_sdk-0.1.7.dist-info/licenses}/LICENSE +0 -0
- {enkryptai_sdk-0.1.5.dist-info → enkryptai_sdk-0.1.7.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,43 @@ 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
|
|
43
|
+
class ModelResponse(BaseDTO):
|
|
44
|
+
message: Optional[str] = None
|
|
45
|
+
data: Optional[Dict] = None
|
|
46
|
+
|
|
47
|
+
def to_dict(self):
|
|
48
|
+
return asdict(self)
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, data: dict):
|
|
52
|
+
return cls(**data)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class EndpointConfig(BaseDTO):
|
|
19
57
|
scheme: str = "https"
|
|
20
58
|
host: str = "api.openai.com"
|
|
21
59
|
port: int = 443
|
|
@@ -23,16 +61,19 @@ class EndpointConfig:
|
|
|
23
61
|
|
|
24
62
|
|
|
25
63
|
@dataclass
|
|
26
|
-
class PathsConfig:
|
|
64
|
+
class PathsConfig(BaseDTO):
|
|
27
65
|
completions: str = "/chat/completions"
|
|
28
66
|
chat: str = "chat/completions"
|
|
67
|
+
vision: str = "images"
|
|
68
|
+
embeddings: str = "embeddings"
|
|
29
69
|
|
|
30
70
|
|
|
31
71
|
@dataclass
|
|
32
|
-
class AuthData:
|
|
72
|
+
class AuthData(BaseDTO):
|
|
33
73
|
header_name: str = "Authorization"
|
|
34
74
|
header_prefix: str = "Bearer"
|
|
35
75
|
space_after_prefix: bool = True
|
|
76
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
36
77
|
|
|
37
78
|
def to_dict(self):
|
|
38
79
|
return asdict(self)
|
|
@@ -46,7 +87,8 @@ class AuthData:
|
|
|
46
87
|
class ModelDetailConfig:
|
|
47
88
|
model_version: Optional[str] = None
|
|
48
89
|
model_source: str = ""
|
|
49
|
-
model_provider: str = "openai"
|
|
90
|
+
# model_provider: str = "openai"
|
|
91
|
+
model_provider: ModelProviders = ModelProviders.OPENAI
|
|
50
92
|
system_prompt: str = ""
|
|
51
93
|
|
|
52
94
|
endpoint_url: str = "https://api.openai.com/v1/chat/completions"
|
|
@@ -64,26 +106,53 @@ class DetailModelConfig:
|
|
|
64
106
|
|
|
65
107
|
|
|
66
108
|
@dataclass
|
|
67
|
-
class ModelConfigDetails:
|
|
109
|
+
class ModelConfigDetails(BaseDTO):
|
|
110
|
+
model_id: str = ""
|
|
68
111
|
model_version: Optional[str] = None
|
|
69
112
|
model_source: str = ""
|
|
70
|
-
|
|
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 = ""
|
|
71
124
|
system_prompt: str = ""
|
|
72
125
|
conversation_template: str = ""
|
|
73
|
-
is_compatible_with: str = "openai"
|
|
74
126
|
hosting_type: str = "External"
|
|
75
127
|
endpoint_url: str = "https://api.openai.com/v1/chat/completions"
|
|
128
|
+
paths: Optional[PathsConfig] = None
|
|
76
129
|
auth_data: AuthData = field(default_factory=AuthData)
|
|
77
130
|
apikey: Optional[str] = None
|
|
78
131
|
default_request_options: Dict[str, Any] = field(default_factory=dict)
|
|
132
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
79
133
|
|
|
80
134
|
@classmethod
|
|
81
135
|
def from_dict(cls, data: dict):
|
|
82
136
|
# Create a copy of the data to avoid modifying the original
|
|
83
137
|
data = data.copy()
|
|
84
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
|
+
|
|
85
154
|
# Remove known fields that we don't want in our model
|
|
86
|
-
unwanted_fields = ["queryParams"
|
|
155
|
+
unwanted_fields = ["queryParams"]
|
|
87
156
|
for field in unwanted_fields:
|
|
88
157
|
data.pop(field, None)
|
|
89
158
|
|
|
@@ -93,8 +162,8 @@ class ModelConfigDetails:
|
|
|
93
162
|
if apikeys and not data.get("apikey"):
|
|
94
163
|
data["apikey"] = apikeys[0]
|
|
95
164
|
|
|
96
|
-
# Convert endpoint dict to endpoint_url if present
|
|
97
|
-
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"):
|
|
98
167
|
endpoint = data.pop("endpoint")
|
|
99
168
|
scheme = endpoint.get("scheme", "https")
|
|
100
169
|
host = endpoint.get("host", "")
|
|
@@ -114,14 +183,16 @@ class ModelConfigDetails:
|
|
|
114
183
|
auth_data = data.pop("auth_data", {})
|
|
115
184
|
auth_data_obj = AuthData.from_dict(auth_data)
|
|
116
185
|
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
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
|
+
)
|
|
120
191
|
|
|
121
|
-
return cls(**
|
|
192
|
+
return cls(**data, auth_data=auth_data_obj, paths=paths_obj)
|
|
122
193
|
|
|
123
194
|
def to_dict(self):
|
|
124
|
-
d =
|
|
195
|
+
d = super().to_dict()
|
|
125
196
|
# Handle AuthData specifically
|
|
126
197
|
d["auth_data"] = self.auth_data.to_dict()
|
|
127
198
|
return d
|
|
@@ -135,7 +206,7 @@ class ModelConfigDetails:
|
|
|
135
206
|
|
|
136
207
|
|
|
137
208
|
@dataclass
|
|
138
|
-
class ModelConfig:
|
|
209
|
+
class ModelConfig(BaseDTO):
|
|
139
210
|
created_at: str = ""
|
|
140
211
|
updated_at: str = ""
|
|
141
212
|
model_id: str = ""
|
|
@@ -144,36 +215,21 @@ class ModelConfig:
|
|
|
144
215
|
model_name: str = "gpt-4o-mini"
|
|
145
216
|
model_type: str = "text_2_text"
|
|
146
217
|
modality: Modality = Modality.TEXT
|
|
218
|
+
project_name: str = ""
|
|
147
219
|
certifications: List[str] = field(default_factory=list)
|
|
148
220
|
model_config: ModelConfigDetails = field(default_factory=ModelConfigDetails)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
"""Convert the ModelConfig instance to a dictionary."""
|
|
152
|
-
# First create a shallow copy of self as dict
|
|
153
|
-
d = {}
|
|
154
|
-
for field in self.__dataclass_fields__:
|
|
155
|
-
value = getattr(self, field)
|
|
156
|
-
if field == "modality":
|
|
157
|
-
d[field] = value.value
|
|
158
|
-
elif field == "model_config":
|
|
159
|
-
if isinstance(value, ModelConfigDetails):
|
|
160
|
-
d[field] = value.to_dict()
|
|
161
|
-
else:
|
|
162
|
-
d[field] = value
|
|
163
|
-
else:
|
|
164
|
-
d[field] = value
|
|
165
|
-
return d
|
|
166
|
-
|
|
167
|
-
def to_json(self) -> str:
|
|
168
|
-
"""Convert the ModelConfig instance to a JSON string."""
|
|
169
|
-
return json.dumps(self.to_dict())
|
|
221
|
+
is_sample: bool = False
|
|
222
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
170
223
|
|
|
171
224
|
@classmethod
|
|
172
225
|
def from_dict(cls, data: dict):
|
|
173
226
|
"""Create a ModelConfig instance from a dictionary."""
|
|
174
227
|
# Handle nested ModelConfigDetails
|
|
175
228
|
model_config_data = data.pop("model_config", {})
|
|
176
|
-
|
|
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)}")
|
|
177
233
|
|
|
178
234
|
# Handle Modality enum
|
|
179
235
|
modality_value = data.pop("modality", "text")
|
|
@@ -182,11 +238,6 @@ class ModelConfig:
|
|
|
182
238
|
return cls(**data, modality=modality, model_config=model_config)
|
|
183
239
|
|
|
184
240
|
@classmethod
|
|
185
|
-
def from_json(cls, json_str: str):
|
|
186
|
-
"""Create a ModelConfig instance from a JSON string."""
|
|
187
|
-
data = json.loads(json_str)
|
|
188
|
-
return cls.from_dict(data)
|
|
189
|
-
|
|
190
241
|
def __str__(self):
|
|
191
242
|
"""String representation of the ModelConfig."""
|
|
192
243
|
return f"ModelConfig(name={self.model_saved_name}, model={self.model_name})"
|
|
@@ -198,5 +249,120 @@ class ModelConfig:
|
|
|
198
249
|
)
|
|
199
250
|
|
|
200
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
|
+
|
|
201
367
|
# Default configuration
|
|
202
368
|
DETAIL_MODEL_CONFIG = ModelConfig()
|