wizata-dsapi 1.3.39__tar.gz → 1.3.41__tar.gz
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.
- {wizata_dsapi-1.3.39/wizata_dsapi.egg-info → wizata_dsapi-1.3.41}/PKG-INFO +1 -1
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/api_dto.py +6 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/mlmodel.py +59 -6
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/pipeline.py +23 -3
- wizata_dsapi-1.3.41/wizata_dsapi/version.py +1 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/wizata_dsapi_client.py +62 -6
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41/wizata_dsapi.egg-info}/PKG-INFO +1 -1
- wizata_dsapi-1.3.39/wizata_dsapi/version.py +0 -1
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/LICENSE.txt +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/README.rst +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/setup.cfg +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/setup.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/__init__.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/api_config.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/api_interface.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/bucket.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/business_label.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/context.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/dataframe_toolkit.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/datapoint.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/datastore.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/ds_dataframe.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/dsapi_json_encoder.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/evaluation.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/execution.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/experiment.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/group_system.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/ilogger.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/insight.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/model_toolkit.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/models/__init__.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/models/common.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/paged_query_result.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/pipeline_image.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/plot.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/plots/__init__.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/plots/common.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/request.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/script.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/scripts/__init__.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/scripts/common.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/solution_component.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/streamlit_utils.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/template.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/trigger.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/twin.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/twinregistration.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/wizard_function.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/wizard_request.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi/words.py +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi.egg-info/SOURCES.txt +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi.egg-info/dependency_links.txt +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi.egg-info/requires.txt +0 -0
- {wizata_dsapi-1.3.39 → wizata_dsapi-1.3.41}/wizata_dsapi.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import List, Iterator, Union, Optional
|
|
2
2
|
import os
|
|
3
|
-
from .api_dto import ApiDto
|
|
3
|
+
from .api_dto import ApiDto, ApiDtoInterface
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
5
|
|
|
6
6
|
|
|
@@ -132,7 +132,8 @@ class ModelInfo:
|
|
|
132
132
|
property_name: str = None,
|
|
133
133
|
trained_model = None,
|
|
134
134
|
scaler = None,
|
|
135
|
-
files = None
|
|
135
|
+
files = None,
|
|
136
|
+
updated_date = None
|
|
136
137
|
):
|
|
137
138
|
# information identifying a model
|
|
138
139
|
self.key = key
|
|
@@ -152,6 +153,7 @@ class ModelInfo:
|
|
|
152
153
|
if not isinstance(file, ModelFile):
|
|
153
154
|
raise TypeError("file is not a ModelFile with files")
|
|
154
155
|
self.is_active = False
|
|
156
|
+
self.updated_date = None
|
|
155
157
|
|
|
156
158
|
# files attached to model when loaded
|
|
157
159
|
self.trained_model = trained_model
|
|
@@ -163,6 +165,17 @@ class ModelInfo:
|
|
|
163
165
|
self.has_target_feat = False
|
|
164
166
|
self.label_counts = 0
|
|
165
167
|
|
|
168
|
+
# api
|
|
169
|
+
self._api = None
|
|
170
|
+
|
|
171
|
+
def bind_api(self, api:ApiDtoInterface):
|
|
172
|
+
"""
|
|
173
|
+
internal method to bind the api to the dto.
|
|
174
|
+
:param api: api client
|
|
175
|
+
:return: None
|
|
176
|
+
"""
|
|
177
|
+
self._api = api
|
|
178
|
+
|
|
166
179
|
@classmethod
|
|
167
180
|
def split_identifier(cls, identifier: str):
|
|
168
181
|
"""
|
|
@@ -249,6 +262,8 @@ class ModelInfo:
|
|
|
249
262
|
obj["identifier"] = self.identifier(include_alias=True)
|
|
250
263
|
if len(self.files) > 0:
|
|
251
264
|
obj["files"] = [file.to_json() for file in self.files]
|
|
265
|
+
if self.updated_date is not None:
|
|
266
|
+
obj["updatedDate"] = str(self.updated_date)
|
|
252
267
|
return obj
|
|
253
268
|
|
|
254
269
|
def from_json(self, obj):
|
|
@@ -273,6 +288,21 @@ class ModelInfo:
|
|
|
273
288
|
self.property_name = obj["property_name"]
|
|
274
289
|
if "is_active" in obj.keys():
|
|
275
290
|
self.is_active = get_bool(obj, name="is_active")
|
|
291
|
+
if "updatedDate" in obj.keys() and obj["updatedDate"] is not None:
|
|
292
|
+
self.updated_date = obj["updatedDate"]
|
|
293
|
+
if "files" in obj.keys():
|
|
294
|
+
for obj_file in obj["files"]:
|
|
295
|
+
model_file = ModelFile()
|
|
296
|
+
model_file.from_json(obj_file)
|
|
297
|
+
self.add_file(model_file)
|
|
298
|
+
|
|
299
|
+
def load(self):
|
|
300
|
+
"""
|
|
301
|
+
load the trained model from the repository.
|
|
302
|
+
"""
|
|
303
|
+
if self._api is None:
|
|
304
|
+
raise RuntimeError("api is not bound to the dto use bind_api()")
|
|
305
|
+
self._api.load_model(self)
|
|
276
306
|
|
|
277
307
|
|
|
278
308
|
class ModelList:
|
|
@@ -298,15 +328,23 @@ class ModelList:
|
|
|
298
328
|
"""
|
|
299
329
|
return any(model_in_list.identifier(include_alias=True) == model.identifier(include_alias=True) for model_in_list in self.models)
|
|
300
330
|
|
|
301
|
-
def __getitem__(self, key: Union[int, ModelInfo]) -> ModelInfo:
|
|
331
|
+
def __getitem__(self, key: Union[int, str, ModelInfo]) -> ModelInfo:
|
|
302
332
|
"""
|
|
303
|
-
find a model within list based on
|
|
304
|
-
:param key: ModelInfo or index
|
|
333
|
+
find a model within list based on index, identifier or ModelInfo.
|
|
334
|
+
:param key: identifier or ModelInfo or index
|
|
305
335
|
:return: the model_info
|
|
306
336
|
"""
|
|
307
337
|
if isinstance(key, int):
|
|
308
338
|
return self.models[key]
|
|
309
339
|
|
|
340
|
+
elif isinstance(key, str):
|
|
341
|
+
if "@" not in key:
|
|
342
|
+
return self.select_active_model(identifier=key)
|
|
343
|
+
for model in self.models:
|
|
344
|
+
if model.identifier(include_alias=True) == key:
|
|
345
|
+
return model
|
|
346
|
+
raise KeyError(f"model with identifier '{key}' not found within this ModelList.")
|
|
347
|
+
|
|
310
348
|
elif isinstance(key, ModelInfo):
|
|
311
349
|
identifier = key.identifier(include_alias=True)
|
|
312
350
|
for model in self.models:
|
|
@@ -315,7 +353,22 @@ class ModelList:
|
|
|
315
353
|
raise KeyError(f"model with identifier '{identifier}' not found within this ModelList.")
|
|
316
354
|
|
|
317
355
|
else:
|
|
318
|
-
raise TypeError("ModelList indices must be int or ModelInfo.")
|
|
356
|
+
raise TypeError("ModelList indices must be int, str or ModelInfo.")
|
|
357
|
+
|
|
358
|
+
def select_active_model(self, identifier: str) -> ModelInfo:
|
|
359
|
+
"""
|
|
360
|
+
return the active model based on active status or latest one if none active.
|
|
361
|
+
:param identifier: identifier
|
|
362
|
+
:return: active model
|
|
363
|
+
"""
|
|
364
|
+
models = []
|
|
365
|
+
for model in self.models:
|
|
366
|
+
if model.identifier(include_alias=False) == identifier:
|
|
367
|
+
if model.is_active:
|
|
368
|
+
return model
|
|
369
|
+
else:
|
|
370
|
+
models.append(model)
|
|
371
|
+
return max(models, key=lambda f: f.updated_date, default=None)
|
|
319
372
|
|
|
320
373
|
def append(self, model: ModelInfo):
|
|
321
374
|
self.models.append(model)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
import json
|
|
3
|
+
import sys
|
|
3
4
|
|
|
4
5
|
import pandas
|
|
5
6
|
import wizata_dsapi
|
|
@@ -159,13 +160,13 @@ class PipelineIO(ApiDto):
|
|
|
159
160
|
obj["columns"] = self.columns
|
|
160
161
|
return obj
|
|
161
162
|
|
|
162
|
-
def
|
|
163
|
+
def _prepare_df(self, df: pandas.DataFrame) -> pandas.DataFrame:
|
|
163
164
|
"""
|
|
164
|
-
prepare
|
|
165
|
-
perform mapping, selection and drops.
|
|
165
|
+
prepare dataframe in both 3.9 and 3.11+
|
|
166
166
|
:param pandas.DataFrame df: dataframe to prepare.
|
|
167
167
|
:return: prepared dataframe.
|
|
168
168
|
"""
|
|
169
|
+
|
|
169
170
|
try:
|
|
170
171
|
prepare_df = df.copy()
|
|
171
172
|
|
|
@@ -186,6 +187,25 @@ class PipelineIO(ApiDto):
|
|
|
186
187
|
except Exception as e:
|
|
187
188
|
raise RuntimeError(f'not able to prepare your dataframe following Pipeline I/O directives {e}')
|
|
188
189
|
|
|
190
|
+
if sys.version_info >= (3, 11):
|
|
191
|
+
|
|
192
|
+
## with torch support
|
|
193
|
+
import torch
|
|
194
|
+
from typing import Union
|
|
195
|
+
|
|
196
|
+
def prepare(self, df: Union[pandas.DataFrame, torch.Tensor]) -> Union[pandas.DataFrame, torch.Tensor]:
|
|
197
|
+
import torch
|
|
198
|
+
if isinstance(df, torch.Tensor):
|
|
199
|
+
return df
|
|
200
|
+
else:
|
|
201
|
+
return self._prepare_df(df)
|
|
202
|
+
|
|
203
|
+
else:
|
|
204
|
+
|
|
205
|
+
## without torch support
|
|
206
|
+
def prepare(self, df: pandas.DataFrame) -> pandas.DataFrame:
|
|
207
|
+
return self._prepare_df(df)
|
|
208
|
+
|
|
189
209
|
@classmethod
|
|
190
210
|
def from_obj(cls, obj):
|
|
191
211
|
"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.41"
|
|
@@ -16,11 +16,13 @@ import types
|
|
|
16
16
|
import wizata_dsapi
|
|
17
17
|
import urllib.parse
|
|
18
18
|
import base64
|
|
19
|
+
import joblib
|
|
20
|
+
import io
|
|
19
21
|
|
|
20
22
|
import string
|
|
21
23
|
import random
|
|
22
24
|
|
|
23
|
-
from .api_dto import ApiDto, VarType
|
|
25
|
+
from .api_dto import ApiDto, VarType, ApiDtoInterface
|
|
24
26
|
from .business_label import BusinessLabel
|
|
25
27
|
from .plot import Plot
|
|
26
28
|
from .request import Request
|
|
@@ -69,7 +71,7 @@ def parse_string_list(s):
|
|
|
69
71
|
return []
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
class WizataDSAPIClient(ApiInterface):
|
|
74
|
+
class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
|
|
73
75
|
"""
|
|
74
76
|
client wrapper to cloud data science API
|
|
75
77
|
|
|
@@ -1100,17 +1102,24 @@ class WizataDSAPIClient(ApiInterface):
|
|
|
1100
1102
|
raise self.__raise_error(response)
|
|
1101
1103
|
|
|
1102
1104
|
def upload_model(self,
|
|
1103
|
-
model_info: ModelInfo
|
|
1105
|
+
model_info: ModelInfo,
|
|
1106
|
+
bytes_content = None):
|
|
1104
1107
|
"""
|
|
1105
1108
|
upload a model within the model repository.
|
|
1109
|
+
- by default use model_info.trained_model and convert it to a pickle
|
|
1110
|
+
- for already torch or pickle please pass the bytes_content
|
|
1111
|
+
- model_info.file_format must be set properly to 'pkl' or 'pt'
|
|
1106
1112
|
:param model_info: model info, with at least key (+twin, +property, +alias) and trained_model.
|
|
1113
|
+
:param bytes_content: bytes[] of your torch or pickle model.
|
|
1107
1114
|
"""
|
|
1108
|
-
if model_info.trained_model is None:
|
|
1109
|
-
raise ValueError("model_info must have a trained model
|
|
1115
|
+
if model_info.trained_model is None and bytes_content is None:
|
|
1116
|
+
raise ValueError("model_info must have a trained model (to pickle) or bytes content")
|
|
1117
|
+
if bytes_content is None:
|
|
1118
|
+
bytes_content = pickle.dumps(model_info.trained_model)
|
|
1110
1119
|
files = {
|
|
1111
1120
|
"trained_model": (
|
|
1112
1121
|
"trained_model." + model_info.file_format ,
|
|
1113
|
-
|
|
1122
|
+
bytes_content,
|
|
1114
1123
|
"application/octet-stream",
|
|
1115
1124
|
)
|
|
1116
1125
|
}
|
|
@@ -1849,6 +1858,27 @@ class WizataDSAPIClient(ApiInterface):
|
|
|
1849
1858
|
else:
|
|
1850
1859
|
raise self.__raise_error(response)
|
|
1851
1860
|
|
|
1861
|
+
def search_models(self) -> ModelList:
|
|
1862
|
+
"""
|
|
1863
|
+
get all information related to models stored on Wizata.
|
|
1864
|
+
:return: ModelList structure model list
|
|
1865
|
+
"""
|
|
1866
|
+
response = requests.request("GET",
|
|
1867
|
+
self.__url() + "models",
|
|
1868
|
+
headers=self.__header()
|
|
1869
|
+
)
|
|
1870
|
+
if response.status_code == 200:
|
|
1871
|
+
response_json = response.json()
|
|
1872
|
+
model_list = ModelList()
|
|
1873
|
+
for model_json in response_json:
|
|
1874
|
+
model_info = ModelInfo(model_json["key"])
|
|
1875
|
+
model_info.from_json(model_json)
|
|
1876
|
+
model_info._api = self
|
|
1877
|
+
model_list.append(model_info)
|
|
1878
|
+
return model_list
|
|
1879
|
+
else:
|
|
1880
|
+
raise self.__raise_error(response)
|
|
1881
|
+
|
|
1852
1882
|
def abort(self, executions: list) -> str:
|
|
1853
1883
|
"""
|
|
1854
1884
|
send an abort request for executions and return a result message
|
|
@@ -1905,6 +1935,32 @@ class WizataDSAPIClient(ApiInterface):
|
|
|
1905
1935
|
image = PipelineImage.loads(pipeline_image_id=pipeline_image_id, g_bytes=response_bytes)
|
|
1906
1936
|
return image
|
|
1907
1937
|
|
|
1938
|
+
def load_model(self, model):
|
|
1939
|
+
"""
|
|
1940
|
+
load a model pickle or torch from the repository ready to be used.
|
|
1941
|
+
:param model: ModelInfo to load
|
|
1942
|
+
:return: ModelInfo with the trained model.
|
|
1943
|
+
"""
|
|
1944
|
+
if not isinstance(model, ModelInfo):
|
|
1945
|
+
raise TypeError('model must be an instance of ModelInfo')
|
|
1946
|
+
|
|
1947
|
+
identifier = model.identifier(include_alias=True)
|
|
1948
|
+
extension = model.file_format
|
|
1949
|
+
response = requests.get(self.__url() + f"models/{identifier}/files/trained_model.{extension}/",
|
|
1950
|
+
headers=self.__header())
|
|
1951
|
+
if response.status_code == 200:
|
|
1952
|
+
if extension == 'pkl':
|
|
1953
|
+
model.trained_model = joblib.load(io.BytesIO(response.content))
|
|
1954
|
+
return model
|
|
1955
|
+
elif extension == 'pt':
|
|
1956
|
+
import torch
|
|
1957
|
+
model.trained_model = torch.jit.load(io.BytesIO(response.content))
|
|
1958
|
+
return model
|
|
1959
|
+
else:
|
|
1960
|
+
raise ValueError(f'unsupported file format {extension}')
|
|
1961
|
+
else:
|
|
1962
|
+
self.__raise_error(response)
|
|
1963
|
+
|
|
1908
1964
|
|
|
1909
1965
|
def api() -> WizataDSAPIClient:
|
|
1910
1966
|
"""
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.3.39"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|