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.
@@ -0,0 +1,325 @@
1
+ from .base import BaseDTO
2
+ from dataclasses import dataclass, field
3
+ from typing import List, Dict, Any, Set, Optional
4
+
5
+
6
+ @dataclass
7
+ class ChatCompletionMessage(BaseDTO):
8
+ role: str
9
+ content: str
10
+
11
+ @classmethod
12
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionMessage":
13
+ return cls(
14
+ role=data.get("role", ""),
15
+ content=data.get("content", "")
16
+ )
17
+
18
+ def to_dict(self) -> Dict[str, Any]:
19
+ return {
20
+ "role": self.role,
21
+ "content": self.content
22
+ }
23
+
24
+
25
+ @dataclass
26
+ class ChatCompletionRequest(BaseDTO):
27
+ model: str
28
+ messages: List[ChatCompletionMessage]
29
+ enkrypt_context: Optional[str] = None
30
+ temperature: Optional[float] = None
31
+ top_p: Optional[float] = None
32
+ max_tokens: Optional[int] = None
33
+ presence_penalty: Optional[float] = None
34
+ frequency_penalty: Optional[float] = None
35
+ n: Optional[int] = None
36
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
37
+
38
+ @classmethod
39
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionRequest":
40
+ messages_data = data.get("messages", [])
41
+
42
+ # Create a copy of the data without the fields we're explicitly processing
43
+ extra_fields = {k: v for k, v in data.items()
44
+ if k not in ["messages", "model", "enkrypt_context",
45
+ "temperature", "top_p", "max_tokens",
46
+ "presence_penalty", "frequency_penalty", "n"]}
47
+
48
+ return cls(
49
+ messages=[ChatCompletionMessage.from_dict(msg) for msg in messages_data],
50
+ model=data.get("model", ""),
51
+ enkrypt_context=data.get("enkrypt_context", None),
52
+ temperature=data.get("temperature", None),
53
+ top_p=data.get("top_p", None),
54
+ max_tokens=data.get("max_tokens", None),
55
+ presence_penalty=data.get("presence_penalty", None),
56
+ frequency_penalty=data.get("frequency_penalty", None),
57
+ n=data.get("n", 1),
58
+ _extra_fields=extra_fields
59
+ )
60
+
61
+ def to_dict(self) -> Dict[str, Any]:
62
+ result = {
63
+ "messages": [message.to_dict() for message in self.messages],
64
+ "model": self.model
65
+ }
66
+
67
+ # Add optional fields only if they are not None or default values
68
+ if self.enkrypt_context is not None:
69
+ result["enkrypt_context"] = self.enkrypt_context
70
+ if self.temperature is not None:
71
+ result["temperature"] = self.temperature
72
+ if self.top_p is not None:
73
+ result["top_p"] = self.top_p
74
+ if self.max_tokens is not None:
75
+ result["max_tokens"] = self.max_tokens
76
+ if self.presence_penalty is not None:
77
+ result["presence_penalty"] = self.presence_penalty
78
+ if self.frequency_penalty is not None:
79
+ result["frequency_penalty"] = self.frequency_penalty
80
+ if self.n is not None:
81
+ result["n"] = self.n
82
+
83
+ # Add any extra fields that weren't explicitly defined
84
+ result.update(self._extra_fields)
85
+ return result
86
+
87
+
88
+ @dataclass
89
+ class ChatCompletionResponseMessage(BaseDTO):
90
+ role: str
91
+ content: str
92
+ tool_calls: List[Dict[str, Any]] = field(default_factory=list)
93
+
94
+ @classmethod
95
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionResponseMessage":
96
+ return cls(
97
+ role=data.get("role", ""),
98
+ content=data.get("content", ""),
99
+ tool_calls=data.get("tool_calls", [])
100
+ )
101
+
102
+ def to_dict(self) -> Dict[str, Any]:
103
+ result = {
104
+ "role": self.role,
105
+ "content": self.content
106
+ }
107
+ if self.tool_calls:
108
+ result["tool_calls"] = self.tool_calls
109
+ return result
110
+
111
+
112
+ @dataclass
113
+ class ChatCompletionChoice(BaseDTO):
114
+ index: int
115
+ message: ChatCompletionResponseMessage
116
+ finish_reason: Optional[str] = None
117
+ seed: Optional[int] = None
118
+ logprobs: Optional[Any] = None
119
+
120
+ @classmethod
121
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionChoice":
122
+ return cls(
123
+ index=data.get("index", 0),
124
+ message=ChatCompletionResponseMessage.from_dict(data.get("message", {})),
125
+ finish_reason=data.get("finish_reason", None),
126
+ seed=data.get("seed", None),
127
+ logprobs=data.get("logprobs", None)
128
+ )
129
+
130
+ def to_dict(self) -> Dict[str, Any]:
131
+ result = {
132
+ "index": self.index,
133
+ "message": self.message.to_dict()
134
+ }
135
+ if self.finish_reason is not None:
136
+ result["finish_reason"] = self.finish_reason
137
+ if self.seed is not None:
138
+ result["seed"] = self.seed
139
+ if self.logprobs is not None:
140
+ result["logprobs"] = self.logprobs
141
+ return result
142
+
143
+
144
+ @dataclass
145
+ class ChatCompletionUsage(BaseDTO):
146
+ prompt_tokens: int
147
+ completion_tokens: int
148
+ total_tokens: int
149
+
150
+ @classmethod
151
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionUsage":
152
+ return cls(
153
+ prompt_tokens=data.get("prompt_tokens", 0),
154
+ completion_tokens=data.get("completion_tokens", 0),
155
+ total_tokens=data.get("total_tokens", 0)
156
+ )
157
+
158
+ def to_dict(self) -> Dict[str, Any]:
159
+ return {
160
+ "prompt_tokens": self.prompt_tokens,
161
+ "completion_tokens": self.completion_tokens,
162
+ "total_tokens": self.total_tokens
163
+ }
164
+
165
+
166
+ @dataclass
167
+ class ChatCompletionResponse(BaseDTO):
168
+ id: str
169
+ object: str
170
+ created: int
171
+ model: str
172
+ choices: List[ChatCompletionChoice]
173
+ usage: ChatCompletionUsage
174
+ prompt: List[Any] = field(default_factory=list)
175
+ enkrypt_policy_detections: Dict[str, Any] = field(default_factory=dict)
176
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
177
+
178
+ @classmethod
179
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionResponse":
180
+ # Extract fields we're explicitly handling
181
+ choices_data = data.get("choices", [])
182
+ usage_data = data.get("usage", {})
183
+
184
+ # Create a copy of the data without the fields we're explicitly processing
185
+ extra_fields = {k: v for k, v in data.items()
186
+ if k not in ["id", "object", "created", "model",
187
+ "choices", "usage", "prompt", "enkrypt_policy_detections"]}
188
+
189
+ return cls(
190
+ id=data.get("id", ""),
191
+ object=data.get("object", ""),
192
+ created=data.get("created", 0),
193
+ model=data.get("model", ""),
194
+ choices=[ChatCompletionChoice.from_dict(choice) for choice in choices_data],
195
+ usage=ChatCompletionUsage.from_dict(usage_data),
196
+ prompt=data.get("prompt", []),
197
+ enkrypt_policy_detections=data.get("enkrypt_policy_detections", {}),
198
+ _extra_fields=extra_fields
199
+ )
200
+
201
+ def to_dict(self) -> Dict[str, Any]:
202
+ result = {
203
+ "id": self.id,
204
+ "object": self.object,
205
+ "created": self.created,
206
+ "model": self.model,
207
+ "choices": [choice.to_dict() for choice in self.choices],
208
+ "usage": self.usage.to_dict(),
209
+ "prompt": self.prompt,
210
+ "enkrypt_policy_detections": self.enkrypt_policy_detections
211
+ }
212
+
213
+ # Add any extra fields
214
+ result.update(self._extra_fields)
215
+ return result
216
+
217
+
218
+ @dataclass
219
+ class ChatCompletionError(BaseDTO):
220
+ code: str
221
+ param: Optional[str] = None
222
+ type: Optional[str] = None
223
+ message: Optional[str] = None
224
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
225
+
226
+ @classmethod
227
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionError":
228
+ # If data is string, then parse the json
229
+ if isinstance(data, str):
230
+ import json
231
+ data = json.loads(data)
232
+ # Create a copy of the data without the fields we're explicitly processing
233
+ extra_fields = {k: v for k, v in data.items()
234
+ if k not in ["code", "param", "type", "message"]}
235
+
236
+ return cls(
237
+ code=data.get("code", ""),
238
+ param=data.get("param", None),
239
+ type=data.get("type", None),
240
+ message=data.get("message", None),
241
+ _extra_fields=extra_fields
242
+ )
243
+
244
+ def to_dict(self) -> Dict[str, Any]:
245
+ result = {
246
+ "code": self.code
247
+ }
248
+
249
+ # Add optional fields only if they are not None
250
+ if self.param is not None:
251
+ result["param"] = self.param
252
+ if self.type is not None:
253
+ result["type"] = self.type
254
+ if self.message is not None:
255
+ result["message"] = self.message
256
+
257
+ # Add any extra fields
258
+ result.update(self._extra_fields)
259
+ return result
260
+
261
+
262
+ @dataclass
263
+ class ChatCompletionErrorResponse(BaseDTO):
264
+ error: ChatCompletionError
265
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
266
+
267
+ @classmethod
268
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionErrorResponse":
269
+ error_data = data.get("error", {})
270
+
271
+ # Create a copy of the data without the fields we're explicitly processing
272
+ extra_fields = {k: v for k, v in data.items()
273
+ if k not in ["error"]}
274
+
275
+ return cls(
276
+ error=ChatCompletionError.from_dict(error_data),
277
+ _extra_fields=extra_fields
278
+ )
279
+
280
+ def to_dict(self) -> Dict[str, Any]:
281
+ result = {
282
+ "error": self.error.to_dict()
283
+ }
284
+
285
+ # Add any extra fields
286
+ result.update(self._extra_fields)
287
+ return result
288
+
289
+
290
+ @dataclass
291
+ class ChatCompletionDirectErrorResponse(BaseDTO):
292
+ error: str
293
+ message: str
294
+ request_id: Optional[str] = None
295
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
296
+
297
+ @classmethod
298
+ def from_dict(cls, data: Dict[str, Any]) -> "ChatCompletionDirectErrorResponse":
299
+ # Create a copy of the data without the fields we're explicitly processing
300
+ extra_fields = {k: v for k, v in data.items()
301
+ if k not in ["error", "message", "request_id"]}
302
+
303
+ return cls(
304
+ error=data.get("error", None),
305
+ message=data.get("message", None),
306
+ request_id=data.get("request_id", None),
307
+ _extra_fields=extra_fields
308
+ )
309
+
310
+ def to_dict(self) -> Dict[str, Any]:
311
+ result = {
312
+ # "message": self.message
313
+ }
314
+
315
+ # Add optional fields only if they are not None
316
+ if self.error is not None:
317
+ result["error"] = self.error
318
+ if self.message is not None:
319
+ result["message"] = self.message
320
+ if self.request_id is not None:
321
+ result["request_id"] = self.request_id
322
+
323
+ # Add any extra fields
324
+ result.update(self._extra_fields)
325
+ return result
@@ -0,0 +1,70 @@
1
+ import json
2
+ from dataclasses import dataclass, field
3
+ from typing import Type, Dict, Any, TypeVar
4
+
5
+ T = TypeVar("T", bound="BaseDTO")
6
+
7
+
8
+ @dataclass
9
+ class BaseDTO:
10
+ """Base class for all DTO classes with common serialization methods."""
11
+
12
+ def __getattr__(self, name):
13
+ """Called when an attribute is not found in the normal places."""
14
+ try:
15
+ extra_fields = object.__getattribute__(self, "_extra_fields")
16
+ if name in extra_fields:
17
+ return extra_fields[name]
18
+ except AttributeError:
19
+ pass
20
+
21
+ raise AttributeError(
22
+ f"'{self.__class__.__name__}' object has no attribute '{name}'"
23
+ )
24
+
25
+ def __setattr__(self, name, value):
26
+ """Handle setting attributes, storing unknown ones in _extra_fields."""
27
+ if name in self.__class__.__annotations__ or name == "_extra_fields":
28
+ super().__setattr__(name, value)
29
+ else:
30
+ self._extra_fields[name] = value
31
+
32
+ @classmethod
33
+ def from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
34
+ """Create an instance from a dictionary."""
35
+ known_fields = cls.__annotations__.keys()
36
+ base_data = {k: v for k, v in data.items() if k in known_fields}
37
+ extra_fields = {
38
+ k: v
39
+ for k, v in data.items()
40
+ if k not in known_fields and k != "_extra_fields"
41
+ }
42
+
43
+ instance = cls(**base_data)
44
+ instance._extra_fields = extra_fields
45
+ return instance
46
+
47
+ @classmethod
48
+ def from_json(cls: Type[T], json_str: str) -> T:
49
+ """Create an instance from a JSON string."""
50
+ data = json.loads(json_str)
51
+ return cls.from_dict(data)
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ """Convert the instance to a dictionary."""
55
+ d = {k: v for k, v in self.__dict__.items() if k != "_extra_fields"}
56
+ d.update(self._extra_fields)
57
+ return d
58
+
59
+ def to_json(self) -> str:
60
+ """Convert the instance to a JSON string."""
61
+ return json.dumps(self.to_dict())
62
+
63
+ def get_all_fields(self) -> Dict[str, Any]:
64
+ """Safely get all fields including extra fields."""
65
+ regular_fields = {k: v for k, v in vars(self).items() if not k.startswith("_")}
66
+ extra_fields = vars(self).get("_extra_fields", {})
67
+
68
+ result = regular_fields.copy()
69
+ result.update(extra_fields)
70
+ return result
@@ -0,0 +1,152 @@
1
+ from .base import BaseDTO
2
+ from dataclasses import dataclass, field
3
+ from typing import Dict, List, Optional, Any
4
+
5
+
6
+ @dataclass
7
+ class DatasetConfig(BaseDTO):
8
+ dataset_name: str
9
+ system_description: str
10
+ policy_description: str = ""
11
+ tools: List[str] = field(default_factory=list)
12
+ info_pdf_url: str = ""
13
+ max_prompts: int = 100
14
+ # scenarios: int = 2
15
+ # categories: int = 2
16
+ # depth: int = 2
17
+
18
+
19
+ @dataclass
20
+ class DatasetCollection(BaseDTO):
21
+ datasets: List[str] = field(default_factory=list)
22
+
23
+
24
+ @dataclass
25
+ class DatasetSummary(BaseDTO):
26
+ test_types: List[str] = field(default_factory=list)
27
+
28
+
29
+ @dataclass
30
+ class DatasetDataPoint(BaseDTO):
31
+ test_type: str
32
+ scenario: str
33
+ category: str
34
+ prompt: str
35
+ source: str
36
+
37
+
38
+ @dataclass
39
+ class DatasetResponse(BaseDTO):
40
+ dataset: List[DatasetDataPoint] = field(default_factory=list)
41
+
42
+ @classmethod
43
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetResponse":
44
+ dataset_items = [DatasetDataPoint.from_dict(item) for item in data.get("dataset", [])]
45
+ return cls(dataset=dataset_items)
46
+
47
+ def to_dict(self) -> Dict[str, Any]:
48
+ return {"dataset": [item.to_dict() for item in self.dataset]}
49
+
50
+
51
+ @dataclass
52
+ class DatasetContent(BaseDTO):
53
+ description: str
54
+ test_types: dict
55
+ scenarios: dict
56
+ categories: dict
57
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
58
+
59
+ @classmethod
60
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetContent":
61
+ return cls(
62
+ description=data.get("description", ""),
63
+ test_types=data.get("test_types", {}),
64
+ scenarios=data.get("scenarios", {}),
65
+ categories=data.get("categories", {}),
66
+ )
67
+
68
+
69
+ @dataclass
70
+ class DatasetTaskData(BaseDTO):
71
+ dataset_name: str
72
+ created_at: str
73
+ started_at: str
74
+ status: str
75
+ system_description: str
76
+ scenarios: int
77
+ categories: int
78
+ depth: int
79
+ policy_description: str
80
+ project_name: str
81
+ info_pdf_url: str
82
+ tools: list
83
+ task_id: str
84
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
85
+
86
+ @classmethod
87
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetTaskData":
88
+ return cls(
89
+ dataset_name=data.get("dataset_name", ""),
90
+ created_at=data.get("created_at", ""),
91
+ started_at=data.get("started_at", ""),
92
+ status=data.get("status", ""),
93
+ system_description=data.get("system_description", ""),
94
+ scenarios=data.get("scenarios", 0),
95
+ categories=data.get("categories", 0),
96
+ depth=data.get("depth", 0),
97
+ policy_description=data.get("policy_description", ""),
98
+ project_name=data.get("project_name", ""),
99
+ info_pdf_url=data.get("info_pdf_url", ""),
100
+ tools=data.get("tools", []),
101
+ task_id=data.get("task_id", ""),
102
+ )
103
+
104
+
105
+ @dataclass
106
+ class DatasetCard(BaseDTO):
107
+ datacard: DatasetContent
108
+ dataset_name: str
109
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
110
+
111
+ @classmethod
112
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetCard":
113
+ datacard_content = DatasetContent.from_dict(data.get("datacard", {}))
114
+ return cls(datacard=datacard_content, dataset_name=data.get("dataset_name", ""))
115
+
116
+ def to_dict(self) -> Dict[str, Any]:
117
+ return {"datacard": self.datacard.to_dict(), "dataset_name": self.dataset_name}
118
+
119
+
120
+ @dataclass
121
+ class DatasetTaskStatus(BaseDTO):
122
+ status: str
123
+ dataset_name: str
124
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
125
+
126
+ @classmethod
127
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetTaskStatus":
128
+ return cls(status=data.get("status", ""), dataset_name=data.get("dataset_name", ""))
129
+
130
+ def to_dict(self) -> Dict[str, Any]:
131
+ return {"status": self.status, "dataset_name": self.dataset_name}
132
+
133
+
134
+ @dataclass
135
+ class DatasetTask(BaseDTO):
136
+ data: DatasetTaskData
137
+ dataset_name: str
138
+ _extra_fields: Dict[str, Any] = field(default_factory=dict)
139
+
140
+ @classmethod
141
+ def from_dict(cls, data: Dict[str, Any]) -> "DatasetTask":
142
+ task_data = DatasetTaskData.from_dict(data.get("data", {}))
143
+ return cls(data=task_data, dataset_name=data.get("dataset_name", ""))
144
+
145
+ def to_dict(self) -> Dict[str, Any]:
146
+ return {"data": self.data.to_dict(), "dataset_name": self.dataset_name}
147
+
148
+
149
+ @dataclass
150
+ class DatasetAddTaskResponse(BaseDTO):
151
+ task_id: str
152
+ message: Optional[str] = None