qwak-core 0.6.7__py3-none-any.whl → 0.7.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.
Files changed (68) hide show
  1. frogml_storage/__init__.py +1 -0
  2. frogml_storage/artifactory/__init__.py +1 -0
  3. frogml_storage/artifactory/_artifactory_api.py +315 -0
  4. frogml_storage/authentication/login/__init__.py +1 -0
  5. frogml_storage/authentication/login/_login_cli.py +239 -0
  6. frogml_storage/authentication/login/_login_command.py +74 -0
  7. frogml_storage/authentication/models/__init__.py +3 -0
  8. frogml_storage/authentication/models/_auth.py +24 -0
  9. frogml_storage/authentication/models/_auth_config.py +70 -0
  10. frogml_storage/authentication/models/_login.py +22 -0
  11. frogml_storage/authentication/utils/__init__.py +18 -0
  12. frogml_storage/authentication/utils/_authentication_utils.py +284 -0
  13. frogml_storage/authentication/utils/_login_checks_utils.py +114 -0
  14. frogml_storage/base_storage.py +140 -0
  15. frogml_storage/constants.py +56 -0
  16. frogml_storage/exceptions/checksum_verification_error.py +3 -0
  17. frogml_storage/exceptions/validation_error.py +4 -0
  18. frogml_storage/frog_ml.py +668 -0
  19. frogml_storage/http/__init__.py +1 -0
  20. frogml_storage/http/http_client.py +83 -0
  21. frogml_storage/logging/__init__.py +1 -0
  22. frogml_storage/logging/_log_config.py +45 -0
  23. frogml_storage/logging/log_utils.py +21 -0
  24. frogml_storage/models/__init__.py +1 -0
  25. frogml_storage/models/_download_context.py +54 -0
  26. frogml_storage/models/dataset_manifest.py +13 -0
  27. frogml_storage/models/entity_manifest.py +93 -0
  28. frogml_storage/models/frogml_dataset_version.py +21 -0
  29. frogml_storage/models/frogml_entity_type_info.py +50 -0
  30. frogml_storage/models/frogml_entity_version.py +34 -0
  31. frogml_storage/models/frogml_model_version.py +21 -0
  32. frogml_storage/models/model_manifest.py +60 -0
  33. frogml_storage/models/serialization_metadata.py +15 -0
  34. frogml_storage/utils/__init__.py +12 -0
  35. frogml_storage/utils/_environment.py +21 -0
  36. frogml_storage/utils/_input_checks_utility.py +104 -0
  37. frogml_storage/utils/_storage_utils.py +15 -0
  38. frogml_storage/utils/_url_utils.py +27 -0
  39. qwak/__init__.py +1 -1
  40. qwak/clients/model_management/client.py +5 -0
  41. qwak/clients/project/client.py +7 -0
  42. qwak/inner/const.py +8 -0
  43. qwak/inner/di_configuration/account.py +67 -6
  44. qwak/inner/di_configuration/dependency_wiring.py +0 -2
  45. qwak/inner/tool/auth.py +83 -0
  46. qwak/inner/tool/grpc/grpc_auth.py +35 -0
  47. qwak/inner/tool/grpc/grpc_tools.py +37 -14
  48. qwak/inner/tool/grpc/grpc_try_wrapping.py +1 -3
  49. qwak/qwak_client/client.py +6 -0
  50. {qwak_core-0.6.7.dist-info → qwak_core-0.7.0.dist-info}/METADATA +1 -1
  51. {qwak_core-0.6.7.dist-info → qwak_core-0.7.0.dist-info}/RECORD +54 -30
  52. qwak_services_mock/mocks/qwak_mocks.py +2 -8
  53. qwak_services_mock/services_mock.py +0 -24
  54. qwak/clients/vector_store/__init__.py +0 -2
  55. qwak/clients/vector_store/management_client.py +0 -124
  56. qwak/clients/vector_store/serving_client.py +0 -156
  57. qwak/vector_store/__init__.py +0 -4
  58. qwak/vector_store/client.py +0 -150
  59. qwak/vector_store/collection.py +0 -426
  60. qwak/vector_store/filters.py +0 -354
  61. qwak/vector_store/inference_client.py +0 -103
  62. qwak/vector_store/rest_helpers.py +0 -72
  63. qwak/vector_store/utils/__init__.py +0 -0
  64. qwak/vector_store/utils/filter_utils.py +0 -21
  65. qwak/vector_store/utils/upsert_utils.py +0 -217
  66. qwak_services_mock/mocks/vector_serving_api.py +0 -154
  67. qwak_services_mock/mocks/vectors_management_api.py +0 -96
  68. {qwak_core-0.6.7.dist-info → qwak_core-0.7.0.dist-info}/WHEEL +0 -0
@@ -1,354 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from dataclasses import dataclass
3
- from typing import Any
4
-
5
- from _qwak_proto.qwak.vectors.v1.filters_pb2 import (
6
- And as ProtoAnd,
7
- AtomicLiteral as ProtoAtomicLiteral,
8
- Equal as ProtoEqual,
9
- Filter as ProtoFilter,
10
- GreaterThan as ProtoGreaterThan,
11
- GreaterThanEqual as ProtoGreaterThanEqual,
12
- IsNotNull as ProtoIsNotNull,
13
- IsNull as ProtoIsNull,
14
- LessThan as ProtoLessThan,
15
- LessThanEqual as ProtoLessThanEqual,
16
- Like as ProtoLike,
17
- NotEqual as ProtoNotEqual,
18
- Or as ProtoOr,
19
- )
20
- from google.protobuf.json_format import MessageToDict, ParseDict
21
- from qwak.vector_store.utils.filter_utils import transform
22
-
23
-
24
- class Filter(ABC):
25
- """Abstract base class for filter objects."""
26
-
27
- def And(self, other):
28
- """Logical AND operation with another filter.
29
-
30
- Usage Example:
31
- ```
32
- filter1 = Equal("age", 30)
33
- filter2 = GreaterThan("score", 90)
34
- combined_filter = filter1.And(filter2)
35
- ```
36
- """
37
- return And(self, other)
38
-
39
- def Or(self, other):
40
- """Logical OR operation with another filter.
41
-
42
- Usage Example:
43
- ```
44
- filter1 = Equal("age", 30)
45
- filter2 = GreaterThan("score", 90)
46
- combined_filter = filter1.Or(filter2)
47
- ```
48
- """
49
- return Or(self, other)
50
-
51
- @abstractmethod
52
- def _to_proto(self):
53
- """Convert the filter to a protobuf representation."""
54
- pass
55
-
56
-
57
- @dataclass
58
- class And(Filter):
59
- """Logical And operation with another filter.
60
-
61
- Usage Example:
62
- ```
63
- filter1 = Equal("age", 30)
64
- filter2 = GreaterThan("score", 90)
65
- combined_filter = And(left=filter1, right=filter2)
66
- ```
67
- """
68
-
69
- left: Filter
70
- right: Filter
71
-
72
- def _to_proto(self):
73
- proto_filter = ProtoFilter()
74
- proto_filter_dict = MessageToDict(proto_filter)
75
- proto_and_dict = MessageToDict(
76
- ProtoAnd(left=self.left._to_proto(), right=self.right._to_proto())
77
- )
78
- proto_filter_dict["and"] = proto_and_dict
79
- return ParseDict(proto_filter_dict, proto_filter, ignore_unknown_fields=True)
80
-
81
-
82
- @dataclass
83
- class Or(Filter):
84
- """Logical OR operation with another filter.
85
-
86
- Usage Example:
87
- ```
88
- filter1 = Equal("age", 30)
89
- filter2 = GreaterThan("score", 90)
90
- combined_filter = Or(left=filter1, right=filter2)
91
- ```
92
- """
93
-
94
- left: Filter
95
- right: Filter
96
-
97
- def _to_proto(self):
98
- proto_filter = ProtoFilter()
99
- proto_filter_dict = MessageToDict(proto_filter)
100
- proto_or_dict = MessageToDict(
101
- ProtoOr(left=self.left._to_proto(), right=self.right._to_proto())
102
- )
103
- proto_filter_dict["or"] = proto_or_dict
104
- return ParseDict(proto_filter_dict, proto_filter, ignore_unknown_fields=True)
105
-
106
-
107
- @dataclass
108
- class _UnaryFilter(Filter):
109
- property: str
110
- value: Any
111
-
112
- def _to_proto(self):
113
- # Each UnaryFilter implements its own _to_proto
114
- pass
115
-
116
-
117
- class Equal(_UnaryFilter):
118
- """Equal operation.
119
-
120
- Usage Example:
121
- ```
122
- filter = Equal(property="age", value=30)
123
- ```
124
- """
125
-
126
- def _to_proto(self):
127
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
128
- return ProtoFilter(eq=ProtoEqual(property=self.property, value=atomic_literal))
129
-
130
-
131
- class NotEqual(_UnaryFilter):
132
- """NotEqual operation.
133
-
134
- Usage Example:
135
- ```
136
- filter = NotEqual(property="age", value=30)
137
- ```
138
- """
139
-
140
- def _to_proto(self):
141
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
142
- return ProtoFilter(
143
- ne=ProtoNotEqual(property=self.property, value=atomic_literal)
144
- )
145
-
146
-
147
- class LessThanEqual(_UnaryFilter):
148
- """LessThanEqual operation.
149
-
150
- Usage Example:
151
- ```
152
- filter = LessThanEqual(property="age", value=30)
153
- ```
154
- """
155
-
156
- def _to_proto(self):
157
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
158
- return ProtoFilter(
159
- lte=ProtoLessThanEqual(property=self.property, value=atomic_literal)
160
- )
161
-
162
-
163
- class LessThan(_UnaryFilter):
164
- """LessThan operation.
165
-
166
- Usage Example:
167
- ```
168
- filter = LessThan(property="age", value=30)
169
- ```
170
- """
171
-
172
- def _to_proto(self):
173
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
174
- return ProtoFilter(
175
- lt=ProtoLessThan(property=self.property, value=atomic_literal)
176
- )
177
-
178
-
179
- class GreaterThanEqual(_UnaryFilter):
180
- """GreaterThanEqual operation.
181
-
182
- Usage Example:
183
- ```
184
- filter = GreaterThanEqual(property="age", value=30)
185
- ```
186
- """
187
-
188
- def _to_proto(self):
189
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
190
- return ProtoFilter(
191
- gte=ProtoGreaterThanEqual(property=self.property, value=atomic_literal)
192
- )
193
-
194
-
195
- class GreaterThan(_UnaryFilter):
196
- """GreaterThan operation.
197
-
198
- Usage Example:
199
- ```
200
- filter = GreaterThan(property="age", value=30)
201
- ```
202
- """
203
-
204
- def _to_proto(self):
205
- atomic_literal: ProtoAtomicLiteral = transform(value=self.value)
206
- return ProtoFilter(
207
- gt=ProtoGreaterThan(property=self.property, value=atomic_literal)
208
- )
209
-
210
-
211
- @dataclass
212
- class Like(Filter):
213
- """Like operation.
214
-
215
- Usage Example:
216
- ```
217
- filter = Like(property="name", pattern="Tal")
218
- ```
219
- """
220
-
221
- property: str
222
- pattern: str
223
-
224
- def _to_proto(self):
225
- return ProtoFilter(like=ProtoLike(property=self.property, pattern=self.pattern))
226
-
227
-
228
- @dataclass
229
- class IsNull(Filter):
230
- """IsNull operation.
231
-
232
- Usage Example:
233
- ```
234
- filter = IsNull(property="zipcode)
235
- ```
236
- """
237
-
238
- property: str
239
-
240
- def _to_proto(self):
241
- return ProtoFilter(is_null=ProtoIsNull(property=self.property))
242
-
243
-
244
- @dataclass
245
- class IsNotNull(Filter):
246
- """IsNotNull operation.
247
-
248
- Usage Example:
249
- ```
250
- filter = IsNotNull(property="zipcode)
251
- ```
252
- """
253
-
254
- property: str
255
-
256
- def _to_proto(self):
257
- return ProtoFilter(is_not_null=ProtoIsNotNull(property=self.property))
258
-
259
-
260
- @dataclass
261
- class Property:
262
- """Represents a property for building filter conditions."""
263
-
264
- name: str
265
-
266
- def gt(self, value: Any):
267
- """Create a GreaterThan filter for this property.
268
-
269
- Usage Example:
270
- ```
271
- filter = Property("age").gt(30)
272
- ```
273
- """
274
- return GreaterThan(self.name, value)
275
-
276
- def gte(self, value: Any):
277
- """Create a GreaterThanEqual filter for this property.
278
-
279
- Usage Example:
280
- ```
281
- filter = Property("score").gte(90)
282
- ```
283
- """
284
- return GreaterThanEqual(self.name, value)
285
-
286
- def lt(self, value: Any):
287
- """Create a LessThan filter for this property.
288
-
289
- Usage Example:
290
- ```
291
- filter = Property("age").lt(30)
292
- ```
293
- """
294
- return LessThan(self.name, value)
295
-
296
- def lte(self, value: Any):
297
- """Create a LessThanEqual filter for this property.
298
-
299
- Usage Example:
300
- ```
301
- filter = Property("score").lte(90)
302
- ```
303
- """
304
- return LessThanEqual(self.name, value)
305
-
306
- def eq(self, value: Any):
307
- """Create an Equal filter for this property.
308
-
309
- Usage Example:
310
- ```
311
- filter = Property("score").eq(90)
312
- ```
313
- """
314
- return Equal(self.name, value)
315
-
316
- def ne(self, value: Any):
317
- """Create an NotEqual filter for this property.
318
-
319
- Usage Example:
320
- ```
321
- filter = Property("age").ne(30)
322
- ```
323
- """
324
- return NotEqual(self.name, value)
325
-
326
- def is_null(self):
327
- """Create an IsNull filter for this property.
328
-
329
- Usage Example:
330
- ```
331
- filter = Property("zipcode").is_null()
332
- ```
333
- """
334
- return IsNull(self.name)
335
-
336
- def is_not_null(self):
337
- """Create an IsNotNull filter for this property.
338
-
339
- Usage Example:
340
- ```
341
- filter = Property("zipcode").is_not_null()
342
- ```
343
- """
344
- return IsNotNull(self.name)
345
-
346
- def like(self, pattern: str):
347
- """Create a Like filter for this property.
348
-
349
- Usage Example:
350
- ```
351
- filter = Property("name").like("Tal")
352
- ```
353
- """
354
- return Like(self.name, pattern)
@@ -1,103 +0,0 @@
1
- import json
2
-
3
- from qwak.clients.administration.eco_system.client import EcosystemClient
4
- from qwak.exceptions import QwakException, QwakHTTPException
5
- from qwak.vector_store.rest_helpers import RestSession
6
-
7
-
8
- class VectorStoreInferenceClient:
9
- def __init__(
10
- self,
11
- model_id: str,
12
- ):
13
- """
14
- :param model_id: The model id to invoke against.
15
- """
16
-
17
- self.r_session = RestSession()
18
- self.ecosystem_client = EcosystemClient()
19
-
20
- authenticated_user_context = (
21
- self.ecosystem_client.get_authenticated_user_context()
22
- )
23
- account_details = authenticated_user_context.user.account_details
24
- default_environment_id = account_details.default_environment_id
25
- model_url_prefix = account_details.environment_by_id[
26
- default_environment_id
27
- ].configuration.model_api_url
28
-
29
- self.model_id = model_id
30
- self.content_type = "application/json; format=pandas-split"
31
- self.model_api = _get_model_url(
32
- model_id=model_id, model_url_prefix=model_url_prefix
33
- )
34
-
35
- def predict(
36
- self,
37
- feature_vectors,
38
- ):
39
- """
40
- Perform a prediction request against a Qwak based model
41
-
42
- :param feature_vectors: A list of feature vectors to predict against. Each feature vector is modeled as a python
43
- dictionary
44
- :return: Prediction response from the model
45
- """
46
-
47
- if feature_vectors.__class__.__name__ == "DataFrame":
48
- feature_vectors = feature_vectors.to_json(orient="split")
49
-
50
- if isinstance(feature_vectors, dict) or isinstance(feature_vectors, list):
51
- feature_vectors = json.dumps(feature_vectors)
52
-
53
- try:
54
- response = self.r_session.post(
55
- self.model_api, data=feature_vectors, headers={}
56
- )
57
-
58
- if response.status_code >= 400:
59
- exception_class_name = response.headers.get("X-Exception-Class")
60
- msg = f"{response.status_code}: {response.text}"
61
- raise QwakHTTPException(response.status_code, msg, exception_class_name)
62
-
63
- elif response.status_code != 200:
64
- raise QwakHTTPException(response.status_code, response.content)
65
-
66
- dict_response = json.loads(response.content)
67
- return dict_response
68
- except QwakHTTPException as e:
69
- raise e
70
- except Exception as e:
71
- raise RuntimeError(f"Failed to make a prediction request. Error is: {e}")
72
-
73
- def get_embedding(self, natural_input: str):
74
- feature_vector = [
75
- {
76
- "input": natural_input,
77
- }
78
- ]
79
- try:
80
- result_list = self.predict(feature_vector)
81
- except Exception as e:
82
- raise QwakException(
83
- f"Vectorizer {self.model_id} failed to transform input {feature_vector} to vectors. Error is: {str(e)}"
84
- )
85
- try:
86
- vector = result_list[0]["embeddings"]
87
- except Exception:
88
- raise QwakException(
89
- f"Vectorizer {self.model_id} must return a dataframe containing an 'embeddings' column"
90
- )
91
- if not vector:
92
- raise QwakException(
93
- f"Vectorizer {self.model_id} did not return embeddings for the given natural input. Unable to continue with the query."
94
- )
95
- return vector
96
-
97
-
98
- def _get_model_url(model_id: str, model_url_prefix: str) -> str:
99
- scheme = "http" if model_url_prefix.startswith("localhost") else "https"
100
- effective_model_id = model_id.replace("-", "_")
101
- return (
102
- f"{scheme}://{model_url_prefix}/v1/{effective_model_id}/predict" # noqa: E231
103
- )
@@ -1,72 +0,0 @@
1
- import base64
2
- import json
3
- import socket
4
- from datetime import datetime
5
-
6
- import requests
7
- from qwak.inner.tool.auth import Auth0ClientBase
8
-
9
-
10
- def _get_authorization():
11
- auth_client = Auth0ClientBase()
12
- token = auth_client.get_token()
13
- token_split = token.split(".")
14
- decoded_token = json.loads(_base64url_decode(token_split[1]).decode("utf-8"))
15
- token_expiration = datetime.fromtimestamp(decoded_token["exp"])
16
- return f"Bearer {token}", token_expiration
17
-
18
-
19
- def _base64url_decode(input):
20
- rem = len(input) % 4
21
- if rem > 0:
22
- input += "=" * (4 - rem)
23
-
24
- return base64.urlsafe_b64decode(input)
25
-
26
-
27
- class SocketAdapter(requests.adapters.HTTPAdapter):
28
- def __init__(self, *args, socket_params=None, **kwargs):
29
- self.socket_params = socket_params
30
- super().__init__(*args, **kwargs)
31
-
32
- def init_poolmanager(self, *args, **kwargs):
33
- if self.socket_params:
34
- kwargs["socket_options"] = self.socket_params
35
- super().init_poolmanager(*args, **kwargs)
36
-
37
-
38
- # Configure only TCP attributes that are available in the OS
39
- def validate_socket_config(socket_options):
40
- config = []
41
- for line in socket_options:
42
- if hasattr(socket, line[0]) and hasattr(socket, line[1]):
43
- config.append((getattr(socket, line[0]), getattr(socket, line[1]), line[2]))
44
- return config
45
-
46
-
47
- class RestSession(requests.Session):
48
- def __init__(self):
49
- super().__init__()
50
- self.headers.update({"Content-Type": "application/json"})
51
- socket_options = [
52
- ("SOL_SOCKET", "SO_KEEPALIVE", 1),
53
- ("SOL_TCP", "TCP_KEEPIDLE", 120),
54
- ("SOL_TCP", "TCP_KEEPINTVL", 75),
55
- ("SOL_TCP", "TCP_KEEPCNT", 9),
56
- ]
57
- socket_options = validate_socket_config(socket_options)
58
- adapter = SocketAdapter(socket_params=socket_options)
59
- self.mount("https://", adapter)
60
-
61
- def prepare_request(self, request):
62
- if "Authorization" not in self.headers:
63
- self.prepare_request_token()
64
- else:
65
- if self.jwt_expiration <= datetime.utcnow():
66
- self.prepare_request_token()
67
-
68
- return super().prepare_request(request)
69
-
70
- def prepare_request_token(self):
71
- auth_token, self.jwt_expiration = _get_authorization()
72
- self.headers["Authorization"] = auth_token
File without changes
@@ -1,21 +0,0 @@
1
- from datetime import datetime
2
- from typing import Any
3
-
4
- from _qwak_proto.qwak.vectors.v1.filters_pb2 import AtomicLiteral as ProtoAtomicLiteral
5
- from qwak.utils.datetime_utils import datetime_to_pts
6
-
7
-
8
- def transform(value: Any) -> ProtoAtomicLiteral:
9
- if isinstance(value, bool):
10
- return ProtoAtomicLiteral(bool_literal=value)
11
- elif isinstance(value, str):
12
- return ProtoAtomicLiteral(string_literal=value)
13
- elif isinstance(value, int):
14
- return ProtoAtomicLiteral(int_literal=value)
15
- elif isinstance(value, float):
16
- return ProtoAtomicLiteral(double_literal=value)
17
- elif isinstance(value, datetime):
18
- # Assuming that timestamp is a datetime
19
- return ProtoAtomicLiteral(timestamp_literal=datetime_to_pts(value))
20
- else:
21
- raise ValueError(f"Unsupported data type: {type(value)}")