mlrun 1.7.2rc3__py3-none-any.whl → 1.8.0rc1__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.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +14 -12
- mlrun/__main__.py +3 -3
- mlrun/alerts/alert.py +19 -12
- mlrun/artifacts/__init__.py +0 -2
- mlrun/artifacts/base.py +34 -11
- mlrun/artifacts/dataset.py +16 -16
- mlrun/artifacts/manager.py +13 -13
- mlrun/artifacts/model.py +66 -53
- mlrun/common/constants.py +6 -0
- mlrun/common/formatters/__init__.py +1 -0
- mlrun/common/formatters/feature_set.py +1 -0
- mlrun/common/formatters/function.py +1 -0
- mlrun/common/formatters/model_endpoint.py +30 -0
- mlrun/common/formatters/pipeline.py +1 -2
- mlrun/common/model_monitoring/__init__.py +0 -3
- mlrun/common/model_monitoring/helpers.py +1 -1
- mlrun/common/runtimes/constants.py +1 -2
- mlrun/common/schemas/__init__.py +4 -2
- mlrun/common/schemas/artifact.py +0 -6
- mlrun/common/schemas/common.py +50 -0
- mlrun/common/schemas/model_monitoring/__init__.py +8 -1
- mlrun/common/schemas/model_monitoring/constants.py +62 -12
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +149 -0
- mlrun/common/schemas/model_monitoring/model_endpoints.py +21 -5
- mlrun/common/schemas/partition.py +122 -0
- mlrun/config.py +43 -15
- mlrun/data_types/__init__.py +0 -2
- mlrun/data_types/data_types.py +0 -1
- mlrun/data_types/infer.py +3 -1
- mlrun/data_types/spark.py +4 -4
- mlrun/data_types/to_pandas.py +2 -11
- mlrun/datastore/__init__.py +0 -2
- mlrun/datastore/alibaba_oss.py +4 -1
- mlrun/datastore/azure_blob.py +4 -1
- mlrun/datastore/base.py +12 -4
- mlrun/datastore/datastore.py +9 -3
- mlrun/datastore/datastore_profile.py +1 -1
- mlrun/datastore/dbfs_store.py +4 -1
- mlrun/datastore/filestore.py +4 -1
- mlrun/datastore/google_cloud_storage.py +4 -1
- mlrun/datastore/hdfs.py +4 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +4 -1
- mlrun/datastore/s3.py +4 -1
- mlrun/datastore/sources.py +51 -49
- mlrun/datastore/store_resources.py +0 -2
- mlrun/datastore/targets.py +22 -23
- mlrun/datastore/utils.py +2 -2
- mlrun/datastore/v3io.py +4 -1
- mlrun/datastore/wasbfs/fs.py +13 -12
- mlrun/db/base.py +126 -62
- mlrun/db/factory.py +3 -0
- mlrun/db/httpdb.py +767 -231
- mlrun/db/nopdb.py +126 -57
- mlrun/errors.py +2 -2
- mlrun/execution.py +55 -29
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +40 -40
- mlrun/feature_store/common.py +9 -9
- mlrun/feature_store/feature_set.py +20 -18
- mlrun/feature_store/feature_vector.py +27 -24
- mlrun/feature_store/retrieval/base.py +14 -9
- mlrun/feature_store/retrieval/job.py +2 -1
- mlrun/feature_store/steps.py +2 -2
- mlrun/features.py +30 -13
- mlrun/frameworks/__init__.py +1 -2
- mlrun/frameworks/_common/__init__.py +1 -2
- mlrun/frameworks/_common/artifacts_library.py +2 -2
- mlrun/frameworks/_common/mlrun_interface.py +10 -6
- mlrun/frameworks/_common/model_handler.py +29 -27
- mlrun/frameworks/_common/producer.py +3 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
- mlrun/frameworks/_ml_common/__init__.py +1 -2
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_ml_common/model_handler.py +21 -21
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/auto_mlrun/__init__.py +1 -2
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
- mlrun/frameworks/huggingface/__init__.py +1 -2
- mlrun/frameworks/huggingface/model_server.py +9 -9
- mlrun/frameworks/lgbm/__init__.py +47 -44
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
- mlrun/frameworks/lgbm/model_handler.py +15 -11
- mlrun/frameworks/lgbm/model_server.py +11 -7
- mlrun/frameworks/lgbm/utils.py +2 -2
- mlrun/frameworks/onnx/__init__.py +1 -2
- mlrun/frameworks/onnx/dataset.py +3 -3
- mlrun/frameworks/onnx/mlrun_interface.py +2 -2
- mlrun/frameworks/onnx/model_handler.py +7 -5
- mlrun/frameworks/onnx/model_server.py +8 -6
- mlrun/frameworks/parallel_coordinates.py +11 -11
- mlrun/frameworks/pytorch/__init__.py +22 -23
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
- mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
- mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
- mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
- mlrun/frameworks/pytorch/model_handler.py +21 -17
- mlrun/frameworks/pytorch/model_server.py +13 -9
- mlrun/frameworks/sklearn/__init__.py +19 -18
- mlrun/frameworks/sklearn/estimator.py +2 -2
- mlrun/frameworks/sklearn/metric.py +3 -3
- mlrun/frameworks/sklearn/metrics_library.py +8 -6
- mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
- mlrun/frameworks/sklearn/model_handler.py +4 -3
- mlrun/frameworks/tf_keras/__init__.py +11 -12
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
- mlrun/frameworks/tf_keras/model_handler.py +17 -13
- mlrun/frameworks/tf_keras/model_server.py +12 -8
- mlrun/frameworks/xgboost/__init__.py +19 -18
- mlrun/frameworks/xgboost/model_handler.py +13 -9
- mlrun/launcher/base.py +3 -4
- mlrun/launcher/local.py +1 -1
- mlrun/launcher/remote.py +1 -1
- mlrun/lists.py +4 -3
- mlrun/model.py +108 -44
- mlrun/model_monitoring/__init__.py +1 -2
- mlrun/model_monitoring/api.py +6 -6
- mlrun/model_monitoring/applications/_application_steps.py +13 -15
- mlrun/model_monitoring/applications/histogram_data_drift.py +41 -15
- mlrun/model_monitoring/applications/results.py +55 -3
- mlrun/model_monitoring/controller.py +185 -223
- mlrun/model_monitoring/db/_schedules.py +156 -0
- mlrun/model_monitoring/db/_stats.py +189 -0
- mlrun/model_monitoring/db/stores/__init__.py +1 -1
- mlrun/model_monitoring/db/stores/base/store.py +6 -65
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -97
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +2 -58
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -15
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +6 -257
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +9 -271
- mlrun/model_monitoring/db/tsdb/base.py +74 -22
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +66 -35
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +284 -51
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -17
- mlrun/model_monitoring/helpers.py +97 -1
- mlrun/model_monitoring/model_endpoint.py +4 -2
- mlrun/model_monitoring/stream_processing.py +2 -2
- mlrun/model_monitoring/tracking_policy.py +10 -3
- mlrun/model_monitoring/writer.py +47 -26
- mlrun/package/__init__.py +3 -6
- mlrun/package/context_handler.py +1 -1
- mlrun/package/packager.py +12 -9
- mlrun/package/packagers/__init__.py +0 -2
- mlrun/package/packagers/default_packager.py +14 -11
- mlrun/package/packagers/numpy_packagers.py +16 -7
- mlrun/package/packagers/pandas_packagers.py +18 -18
- mlrun/package/packagers/python_standard_library_packagers.py +25 -11
- mlrun/package/packagers_manager.py +31 -14
- mlrun/package/utils/__init__.py +0 -3
- mlrun/package/utils/_pickler.py +6 -6
- mlrun/platforms/__init__.py +3 -3
- mlrun/platforms/iguazio.py +4 -1
- mlrun/projects/__init__.py +1 -6
- mlrun/projects/operations.py +27 -27
- mlrun/projects/pipelines.py +85 -215
- mlrun/projects/project.py +444 -158
- mlrun/run.py +9 -9
- mlrun/runtimes/__init__.py +1 -3
- mlrun/runtimes/base.py +13 -10
- mlrun/runtimes/daskjob.py +9 -9
- mlrun/runtimes/generators.py +2 -1
- mlrun/runtimes/kubejob.py +4 -5
- mlrun/runtimes/mpijob/__init__.py +0 -2
- mlrun/runtimes/mpijob/abstract.py +7 -6
- mlrun/runtimes/nuclio/api_gateway.py +7 -7
- mlrun/runtimes/nuclio/application/application.py +11 -11
- mlrun/runtimes/nuclio/function.py +14 -13
- mlrun/runtimes/nuclio/serving.py +9 -9
- mlrun/runtimes/pod.py +74 -29
- mlrun/runtimes/remotesparkjob.py +3 -2
- mlrun/runtimes/sparkjob/__init__.py +0 -2
- mlrun/runtimes/sparkjob/spark3job.py +21 -11
- mlrun/runtimes/utils.py +6 -5
- mlrun/serving/merger.py +6 -4
- mlrun/serving/remote.py +18 -17
- mlrun/serving/routers.py +27 -27
- mlrun/serving/server.py +1 -1
- mlrun/serving/states.py +76 -71
- mlrun/serving/utils.py +13 -2
- mlrun/serving/v1_serving.py +3 -2
- mlrun/serving/v2_serving.py +4 -4
- mlrun/track/__init__.py +1 -1
- mlrun/track/tracker.py +2 -2
- mlrun/track/trackers/mlflow_tracker.py +6 -5
- mlrun/utils/async_http.py +1 -1
- mlrun/utils/helpers.py +72 -28
- mlrun/utils/logger.py +104 -2
- mlrun/utils/notifications/notification/base.py +23 -4
- mlrun/utils/notifications/notification/console.py +1 -1
- mlrun/utils/notifications/notification/git.py +6 -6
- mlrun/utils/notifications/notification/ipython.py +5 -4
- mlrun/utils/notifications/notification/slack.py +1 -1
- mlrun/utils/notifications/notification/webhook.py +13 -17
- mlrun/utils/notifications/notification_pusher.py +23 -19
- mlrun/utils/regex.py +1 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/METADATA +186 -186
- mlrun-1.8.0rc1.dist-info/RECORD +356 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/WHEEL +1 -1
- mlrun-1.7.2rc3.dist-info/RECORD +0 -351
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/LICENSE +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.2rc3.dist-info → mlrun-1.8.0rc1.dist-info}/top_level.txt +0 -0
mlrun/serving/states.py
CHANGED
|
@@ -25,7 +25,7 @@ import pathlib
|
|
|
25
25
|
import traceback
|
|
26
26
|
from copy import copy, deepcopy
|
|
27
27
|
from inspect import getfullargspec, signature
|
|
28
|
-
from typing import Any, Union
|
|
28
|
+
from typing import Any, Optional, Union
|
|
29
29
|
|
|
30
30
|
import storey.utils
|
|
31
31
|
|
|
@@ -104,7 +104,12 @@ class BaseStep(ModelObj):
|
|
|
104
104
|
default_shape = "ellipse"
|
|
105
105
|
_dict_fields = ["kind", "comment", "after", "on_error"]
|
|
106
106
|
|
|
107
|
-
def __init__(
|
|
107
|
+
def __init__(
|
|
108
|
+
self,
|
|
109
|
+
name: Optional[str] = None,
|
|
110
|
+
after: Optional[list] = None,
|
|
111
|
+
shape: Optional[str] = None,
|
|
112
|
+
):
|
|
108
113
|
self.name = name
|
|
109
114
|
self._parent = None
|
|
110
115
|
self.comment = None
|
|
@@ -154,14 +159,14 @@ class BaseStep(ModelObj):
|
|
|
154
159
|
|
|
155
160
|
def error_handler(
|
|
156
161
|
self,
|
|
157
|
-
name: str = None,
|
|
162
|
+
name: Optional[str] = None,
|
|
158
163
|
class_name=None,
|
|
159
164
|
handler=None,
|
|
160
165
|
before=None,
|
|
161
166
|
function=None,
|
|
162
|
-
full_event: bool = None,
|
|
163
|
-
input_path: str = None,
|
|
164
|
-
result_path: str = None,
|
|
167
|
+
full_event: Optional[bool] = None,
|
|
168
|
+
input_path: Optional[str] = None,
|
|
169
|
+
result_path: Optional[str] = None,
|
|
165
170
|
**class_args,
|
|
166
171
|
):
|
|
167
172
|
"""set error handler on a step or the entire graph (to be executed on failure/raise)
|
|
@@ -297,13 +302,13 @@ class BaseStep(ModelObj):
|
|
|
297
302
|
def to(
|
|
298
303
|
self,
|
|
299
304
|
class_name: Union[str, StepToDict] = None,
|
|
300
|
-
name: str = None,
|
|
301
|
-
handler: str = None,
|
|
302
|
-
graph_shape: str = None,
|
|
303
|
-
function: str = None,
|
|
304
|
-
full_event: bool = None,
|
|
305
|
-
input_path: str = None,
|
|
306
|
-
result_path: str = None,
|
|
305
|
+
name: Optional[str] = None,
|
|
306
|
+
handler: Optional[str] = None,
|
|
307
|
+
graph_shape: Optional[str] = None,
|
|
308
|
+
function: Optional[str] = None,
|
|
309
|
+
full_event: Optional[bool] = None,
|
|
310
|
+
input_path: Optional[str] = None,
|
|
311
|
+
result_path: Optional[str] = None,
|
|
307
312
|
**class_args,
|
|
308
313
|
):
|
|
309
314
|
"""add a step right after this step and return the new step
|
|
@@ -404,16 +409,16 @@ class TaskStep(BaseStep):
|
|
|
404
409
|
|
|
405
410
|
def __init__(
|
|
406
411
|
self,
|
|
407
|
-
class_name: Union[str, type] = None,
|
|
408
|
-
class_args: dict = None,
|
|
409
|
-
handler: str = None,
|
|
410
|
-
name: str = None,
|
|
411
|
-
after: list = None,
|
|
412
|
-
full_event: bool = None,
|
|
413
|
-
function: str = None,
|
|
414
|
-
responder: bool = None,
|
|
415
|
-
input_path: str = None,
|
|
416
|
-
result_path: str = None,
|
|
412
|
+
class_name: Optional[Union[str, type]] = None,
|
|
413
|
+
class_args: Optional[dict] = None,
|
|
414
|
+
handler: Optional[str] = None,
|
|
415
|
+
name: Optional[str] = None,
|
|
416
|
+
after: Optional[list] = None,
|
|
417
|
+
full_event: Optional[bool] = None,
|
|
418
|
+
function: Optional[str] = None,
|
|
419
|
+
responder: Optional[bool] = None,
|
|
420
|
+
input_path: Optional[str] = None,
|
|
421
|
+
result_path: Optional[str] = None,
|
|
417
422
|
):
|
|
418
423
|
super().__init__(name, after)
|
|
419
424
|
self.class_name = class_name
|
|
@@ -607,16 +612,16 @@ class MonitoringApplicationStep(TaskStep):
|
|
|
607
612
|
|
|
608
613
|
def __init__(
|
|
609
614
|
self,
|
|
610
|
-
class_name: Union[str, type] = None,
|
|
611
|
-
class_args: dict = None,
|
|
612
|
-
handler: str = None,
|
|
613
|
-
name: str = None,
|
|
614
|
-
after: list = None,
|
|
615
|
-
full_event: bool = None,
|
|
616
|
-
function: str = None,
|
|
617
|
-
responder: bool = None,
|
|
618
|
-
input_path: str = None,
|
|
619
|
-
result_path: str = None,
|
|
615
|
+
class_name: Optional[Union[str, type]] = None,
|
|
616
|
+
class_args: Optional[dict] = None,
|
|
617
|
+
handler: Optional[str] = None,
|
|
618
|
+
name: Optional[str] = None,
|
|
619
|
+
after: Optional[list] = None,
|
|
620
|
+
full_event: Optional[bool] = None,
|
|
621
|
+
function: Optional[str] = None,
|
|
622
|
+
responder: Optional[bool] = None,
|
|
623
|
+
input_path: Optional[str] = None,
|
|
624
|
+
result_path: Optional[str] = None,
|
|
620
625
|
):
|
|
621
626
|
super().__init__(
|
|
622
627
|
class_name=class_name,
|
|
@@ -641,16 +646,16 @@ class ErrorStep(TaskStep):
|
|
|
641
646
|
|
|
642
647
|
def __init__(
|
|
643
648
|
self,
|
|
644
|
-
class_name: Union[str, type] = None,
|
|
645
|
-
class_args: dict = None,
|
|
646
|
-
handler: str = None,
|
|
647
|
-
name: str = None,
|
|
648
|
-
after: list = None,
|
|
649
|
-
full_event: bool = None,
|
|
650
|
-
function: str = None,
|
|
651
|
-
responder: bool = None,
|
|
652
|
-
input_path: str = None,
|
|
653
|
-
result_path: str = None,
|
|
649
|
+
class_name: Optional[Union[str, type]] = None,
|
|
650
|
+
class_args: Optional[dict] = None,
|
|
651
|
+
handler: Optional[str] = None,
|
|
652
|
+
name: Optional[str] = None,
|
|
653
|
+
after: Optional[list] = None,
|
|
654
|
+
full_event: Optional[bool] = None,
|
|
655
|
+
function: Optional[str] = None,
|
|
656
|
+
responder: Optional[bool] = None,
|
|
657
|
+
input_path: Optional[str] = None,
|
|
658
|
+
result_path: Optional[str] = None,
|
|
654
659
|
):
|
|
655
660
|
super().__init__(
|
|
656
661
|
class_name=class_name,
|
|
@@ -678,14 +683,14 @@ class RouterStep(TaskStep):
|
|
|
678
683
|
|
|
679
684
|
def __init__(
|
|
680
685
|
self,
|
|
681
|
-
class_name: Union[str, type] = None,
|
|
682
|
-
class_args: dict = None,
|
|
683
|
-
handler: str = None,
|
|
684
|
-
routes: list = None,
|
|
685
|
-
name: str = None,
|
|
686
|
-
function: str = None,
|
|
687
|
-
input_path: str = None,
|
|
688
|
-
result_path: str = None,
|
|
686
|
+
class_name: Optional[Union[str, type]] = None,
|
|
687
|
+
class_args: Optional[dict] = None,
|
|
688
|
+
handler: Optional[str] = None,
|
|
689
|
+
routes: Optional[list] = None,
|
|
690
|
+
name: Optional[str] = None,
|
|
691
|
+
function: Optional[str] = None,
|
|
692
|
+
input_path: Optional[str] = None,
|
|
693
|
+
result_path: Optional[str] = None,
|
|
689
694
|
):
|
|
690
695
|
super().__init__(
|
|
691
696
|
class_name,
|
|
@@ -813,12 +818,12 @@ class QueueStep(BaseStep):
|
|
|
813
818
|
|
|
814
819
|
def __init__(
|
|
815
820
|
self,
|
|
816
|
-
name: str = None,
|
|
817
|
-
path: str = None,
|
|
818
|
-
after: list = None,
|
|
819
|
-
shards: int = None,
|
|
820
|
-
retention_in_hours: int = None,
|
|
821
|
-
trigger_args: dict = None,
|
|
821
|
+
name: Optional[str] = None,
|
|
822
|
+
path: Optional[str] = None,
|
|
823
|
+
after: Optional[list] = None,
|
|
824
|
+
shards: Optional[int] = None,
|
|
825
|
+
retention_in_hours: Optional[int] = None,
|
|
826
|
+
trigger_args: Optional[dict] = None,
|
|
822
827
|
**options,
|
|
823
828
|
):
|
|
824
829
|
super().__init__(name, after)
|
|
@@ -850,13 +855,13 @@ class QueueStep(BaseStep):
|
|
|
850
855
|
def to(
|
|
851
856
|
self,
|
|
852
857
|
class_name: Union[str, StepToDict] = None,
|
|
853
|
-
name: str = None,
|
|
854
|
-
handler: str = None,
|
|
855
|
-
graph_shape: str = None,
|
|
856
|
-
function: str = None,
|
|
857
|
-
full_event: bool = None,
|
|
858
|
-
input_path: str = None,
|
|
859
|
-
result_path: str = None,
|
|
858
|
+
name: Optional[str] = None,
|
|
859
|
+
handler: Optional[str] = None,
|
|
860
|
+
graph_shape: Optional[str] = None,
|
|
861
|
+
function: Optional[str] = None,
|
|
862
|
+
full_event: Optional[bool] = None,
|
|
863
|
+
input_path: Optional[str] = None,
|
|
864
|
+
result_path: Optional[str] = None,
|
|
860
865
|
**class_args,
|
|
861
866
|
):
|
|
862
867
|
if not function:
|
|
@@ -905,7 +910,7 @@ class FlowStep(BaseStep):
|
|
|
905
910
|
self,
|
|
906
911
|
name=None,
|
|
907
912
|
steps=None,
|
|
908
|
-
after: list = None,
|
|
913
|
+
after: Optional[list] = None,
|
|
909
914
|
engine=None,
|
|
910
915
|
final_step=None,
|
|
911
916
|
):
|
|
@@ -948,9 +953,9 @@ class FlowStep(BaseStep):
|
|
|
948
953
|
before=None,
|
|
949
954
|
graph_shape=None,
|
|
950
955
|
function=None,
|
|
951
|
-
full_event: bool = None,
|
|
952
|
-
input_path: str = None,
|
|
953
|
-
result_path: str = None,
|
|
956
|
+
full_event: Optional[bool] = None,
|
|
957
|
+
input_path: Optional[str] = None,
|
|
958
|
+
result_path: Optional[str] = None,
|
|
954
959
|
**class_args,
|
|
955
960
|
):
|
|
956
961
|
"""add task, queue or router step/class to the flow
|
|
@@ -1037,7 +1042,7 @@ class FlowStep(BaseStep):
|
|
|
1037
1042
|
self._last_added = step
|
|
1038
1043
|
return step
|
|
1039
1044
|
|
|
1040
|
-
def clear_children(self, steps: list = None):
|
|
1045
|
+
def clear_children(self, steps: Optional[list] = None):
|
|
1041
1046
|
"""remove some or all of the states, empty/None for all"""
|
|
1042
1047
|
if not steps:
|
|
1043
1048
|
steps = self._steps.keys()
|
|
@@ -1554,8 +1559,8 @@ def params_to_step(
|
|
|
1554
1559
|
graph_shape=None,
|
|
1555
1560
|
function=None,
|
|
1556
1561
|
full_event=None,
|
|
1557
|
-
input_path: str = None,
|
|
1558
|
-
result_path: str = None,
|
|
1562
|
+
input_path: Optional[str] = None,
|
|
1563
|
+
result_path: Optional[str] = None,
|
|
1559
1564
|
class_args=None,
|
|
1560
1565
|
):
|
|
1561
1566
|
"""return step object from provided params or classes/objects"""
|
mlrun/serving/utils.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
15
|
import inspect
|
|
16
|
+
from typing import Optional
|
|
16
17
|
|
|
17
18
|
from mlrun.utils import get_in, update_in
|
|
18
19
|
|
|
@@ -55,7 +56,12 @@ class StepToDict:
|
|
|
55
56
|
"kwargs",
|
|
56
57
|
]
|
|
57
58
|
|
|
58
|
-
def to_dict(
|
|
59
|
+
def to_dict(
|
|
60
|
+
self,
|
|
61
|
+
fields: Optional[list] = None,
|
|
62
|
+
exclude: Optional[list] = None,
|
|
63
|
+
strip: bool = False,
|
|
64
|
+
):
|
|
59
65
|
"""convert the step object to a python dictionary"""
|
|
60
66
|
fields = fields or getattr(self, "_dict_fields", None)
|
|
61
67
|
if not fields:
|
|
@@ -105,5 +111,10 @@ class MonitoringApplicationToDict(StepToDict):
|
|
|
105
111
|
class RouterToDict(StepToDict):
|
|
106
112
|
_STEP_KIND = "router"
|
|
107
113
|
|
|
108
|
-
def to_dict(
|
|
114
|
+
def to_dict(
|
|
115
|
+
self,
|
|
116
|
+
fields: Optional[list] = None,
|
|
117
|
+
exclude: Optional[list] = None,
|
|
118
|
+
strip: bool = False,
|
|
119
|
+
):
|
|
109
120
|
return super().to_dict(exclude=["routes"], strip=strip)
|
mlrun/serving/v1_serving.py
CHANGED
|
@@ -18,6 +18,7 @@ import socket
|
|
|
18
18
|
from copy import deepcopy
|
|
19
19
|
from datetime import datetime
|
|
20
20
|
from io import BytesIO
|
|
21
|
+
from typing import Optional
|
|
21
22
|
from urllib.request import urlopen
|
|
22
23
|
|
|
23
24
|
import nuclio
|
|
@@ -33,7 +34,7 @@ serving_handler = "handler"
|
|
|
33
34
|
def new_v1_model_server(
|
|
34
35
|
name,
|
|
35
36
|
model_class: str,
|
|
36
|
-
models: dict = None,
|
|
37
|
+
models: Optional[dict] = None,
|
|
37
38
|
filename="",
|
|
38
39
|
protocol="",
|
|
39
40
|
image="",
|
|
@@ -68,7 +69,7 @@ def new_v1_model_server(
|
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
class MLModelServer:
|
|
71
|
-
def __init__(self, name: str, model_dir: str = None, model=None):
|
|
72
|
+
def __init__(self, name: str, model_dir: Optional[str] = None, model=None):
|
|
72
73
|
self.name = name
|
|
73
74
|
self.ready = False
|
|
74
75
|
self.model_dir = model_dir
|
mlrun/serving/v2_serving.py
CHANGED
|
@@ -33,12 +33,12 @@ class V2ModelServer(StepToDict):
|
|
|
33
33
|
def __init__(
|
|
34
34
|
self,
|
|
35
35
|
context=None,
|
|
36
|
-
name: str = None,
|
|
37
|
-
model_path: str = None,
|
|
36
|
+
name: Optional[str] = None,
|
|
37
|
+
model_path: Optional[str] = None,
|
|
38
38
|
model=None,
|
|
39
39
|
protocol=None,
|
|
40
|
-
input_path: str = None,
|
|
41
|
-
result_path: str = None,
|
|
40
|
+
input_path: Optional[str] = None,
|
|
41
|
+
result_path: Optional[str] = None,
|
|
42
42
|
shard_by_endpoint: Optional[bool] = None,
|
|
43
43
|
**kwargs,
|
|
44
44
|
):
|
mlrun/track/__init__.py
CHANGED
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
from mlrun.track.tracker import Tracker
|
|
16
16
|
from mlrun.track.tracker_manager import TrackerManager
|
mlrun/track/tracker.py
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from abc import ABC, abstractmethod
|
|
16
|
-
from typing import Any, Union
|
|
16
|
+
from typing import Any, Optional, Union
|
|
17
17
|
|
|
18
18
|
from mlrun.artifacts import Artifact, ModelArtifact
|
|
19
19
|
from mlrun.execution import MLClientCtx
|
|
@@ -63,7 +63,7 @@ class Tracker(ABC):
|
|
|
63
63
|
project: MlrunProject,
|
|
64
64
|
reference_id: Any,
|
|
65
65
|
function_name: str,
|
|
66
|
-
handler: str = None,
|
|
66
|
+
handler: Optional[str] = None,
|
|
67
67
|
**kwargs,
|
|
68
68
|
) -> RunObject:
|
|
69
69
|
"""
|
|
@@ -15,6 +15,7 @@ import os
|
|
|
15
15
|
import pathlib
|
|
16
16
|
import tempfile
|
|
17
17
|
import zipfile
|
|
18
|
+
from typing import Optional
|
|
18
19
|
|
|
19
20
|
import mlflow
|
|
20
21
|
import mlflow.entities
|
|
@@ -190,7 +191,7 @@ class MLFlowTracker(Tracker):
|
|
|
190
191
|
project: MlrunProject,
|
|
191
192
|
reference_id: str,
|
|
192
193
|
function_name: str,
|
|
193
|
-
handler: str = None,
|
|
194
|
+
handler: Optional[str] = None,
|
|
194
195
|
**kwargs,
|
|
195
196
|
) -> RunObject:
|
|
196
197
|
"""
|
|
@@ -251,9 +252,9 @@ class MLFlowTracker(Tracker):
|
|
|
251
252
|
self,
|
|
252
253
|
project: MlrunProject,
|
|
253
254
|
reference_id: str,
|
|
254
|
-
key: str = None,
|
|
255
|
-
metrics: dict = None,
|
|
256
|
-
extra_data: dict = None,
|
|
255
|
+
key: Optional[str] = None,
|
|
256
|
+
metrics: Optional[dict] = None,
|
|
257
|
+
extra_data: Optional[dict] = None,
|
|
257
258
|
) -> ModelArtifact:
|
|
258
259
|
"""
|
|
259
260
|
Import a model from MLFlow to MLRun.
|
|
@@ -290,7 +291,7 @@ class MLFlowTracker(Tracker):
|
|
|
290
291
|
return model
|
|
291
292
|
|
|
292
293
|
def import_artifact(
|
|
293
|
-
self, project: MlrunProject, reference_id: str, key: str = None
|
|
294
|
+
self, project: MlrunProject, reference_id: str, key: Optional[str] = None
|
|
294
295
|
) -> Artifact:
|
|
295
296
|
"""
|
|
296
297
|
Import an artifact from MLFlow to MLRun.
|
mlrun/utils/async_http.py
CHANGED
|
@@ -42,7 +42,7 @@ class AsyncClientWithRetry(RetryClient):
|
|
|
42
42
|
retry_on_exception: bool = True,
|
|
43
43
|
raise_for_status: bool = True,
|
|
44
44
|
blacklisted_methods: typing.Optional[list[str]] = None,
|
|
45
|
-
logger: logging.Logger = None,
|
|
45
|
+
logger: Optional[logging.Logger] = None,
|
|
46
46
|
*args,
|
|
47
47
|
**kwargs,
|
|
48
48
|
):
|
mlrun/utils/helpers.py
CHANGED
|
@@ -40,7 +40,6 @@ import pandas
|
|
|
40
40
|
import semver
|
|
41
41
|
import yaml
|
|
42
42
|
from dateutil import parser
|
|
43
|
-
from mlrun_pipelines.models import PipelineRun
|
|
44
43
|
from pandas import Timedelta, Timestamp
|
|
45
44
|
from yaml.representer import RepresenterError
|
|
46
45
|
|
|
@@ -52,6 +51,7 @@ import mlrun.utils.regex
|
|
|
52
51
|
import mlrun.utils.version.version
|
|
53
52
|
from mlrun.common.constants import MYSQL_MEDIUMBLOB_SIZE_BYTES
|
|
54
53
|
from mlrun.config import config
|
|
54
|
+
from mlrun_pipelines.models import PipelineRun
|
|
55
55
|
|
|
56
56
|
from .logger import create_logger
|
|
57
57
|
from .retryer import ( # noqa: F401
|
|
@@ -167,6 +167,7 @@ class RunKeys:
|
|
|
167
167
|
inputs = "inputs"
|
|
168
168
|
returns = "returns"
|
|
169
169
|
artifacts = "artifacts"
|
|
170
|
+
artifact_uris = "artifact_uris"
|
|
170
171
|
outputs = "outputs"
|
|
171
172
|
data_stores = "data_stores"
|
|
172
173
|
secrets = "secret_sources"
|
|
@@ -220,7 +221,7 @@ def verify_field_regex(
|
|
|
220
221
|
|
|
221
222
|
|
|
222
223
|
def validate_builder_source(
|
|
223
|
-
source: str, pull_at_runtime: bool = False, workdir: str = None
|
|
224
|
+
source: str, pull_at_runtime: bool = False, workdir: Optional[str] = None
|
|
224
225
|
):
|
|
225
226
|
if pull_at_runtime or not source:
|
|
226
227
|
return
|
|
@@ -268,12 +269,14 @@ def validate_tag_name(
|
|
|
268
269
|
def validate_artifact_key_name(
|
|
269
270
|
artifact_key: str, field_name: str, raise_on_failure: bool = True
|
|
270
271
|
) -> bool:
|
|
272
|
+
field_type = "key" if field_name == "artifact.key" else "db_key"
|
|
271
273
|
return mlrun.utils.helpers.verify_field_regex(
|
|
272
274
|
field_name,
|
|
273
275
|
artifact_key,
|
|
274
276
|
mlrun.utils.regex.artifact_key,
|
|
275
277
|
raise_on_failure=raise_on_failure,
|
|
276
|
-
log_message="
|
|
278
|
+
log_message=f"Artifact {field_type} must start and end with an alphanumeric character, and may only contain "
|
|
279
|
+
"letters, numbers, hyphens, underscores, and dots.",
|
|
277
280
|
)
|
|
278
281
|
|
|
279
282
|
|
|
@@ -354,8 +357,8 @@ def verify_field_list_of_type(
|
|
|
354
357
|
def verify_dict_items_type(
|
|
355
358
|
name: str,
|
|
356
359
|
dictionary: dict,
|
|
357
|
-
expected_keys_types: list = None,
|
|
358
|
-
expected_values_types: list = None,
|
|
360
|
+
expected_keys_types: Optional[list] = None,
|
|
361
|
+
expected_values_types: Optional[list] = None,
|
|
359
362
|
):
|
|
360
363
|
if dictionary:
|
|
361
364
|
if not isinstance(dictionary, dict):
|
|
@@ -372,7 +375,7 @@ def verify_dict_items_type(
|
|
|
372
375
|
) from exc
|
|
373
376
|
|
|
374
377
|
|
|
375
|
-
def verify_list_items_type(list_, expected_types: list = None):
|
|
378
|
+
def verify_list_items_type(list_, expected_types: Optional[list] = None):
|
|
376
379
|
if list_ and expected_types:
|
|
377
380
|
list_items_types = set(map(type, list_))
|
|
378
381
|
expected_types = set(expected_types)
|
|
@@ -396,6 +399,10 @@ def now_date(tz: timezone = timezone.utc) -> datetime:
|
|
|
396
399
|
return datetime.now(tz=tz)
|
|
397
400
|
|
|
398
401
|
|
|
402
|
+
def datetime_min(tz: timezone = timezone.utc) -> datetime:
|
|
403
|
+
return datetime(1970, 1, 1, tzinfo=tz)
|
|
404
|
+
|
|
405
|
+
|
|
399
406
|
datetime_now = now_date
|
|
400
407
|
|
|
401
408
|
|
|
@@ -816,7 +823,9 @@ def _convert_python_package_version_to_image_tag(version: typing.Optional[str]):
|
|
|
816
823
|
|
|
817
824
|
|
|
818
825
|
def enrich_image_url(
|
|
819
|
-
image_url: str,
|
|
826
|
+
image_url: str,
|
|
827
|
+
client_version: Optional[str] = None,
|
|
828
|
+
client_python_version: Optional[str] = None,
|
|
820
829
|
) -> str:
|
|
821
830
|
client_version = _convert_python_package_version_to_image_tag(client_version)
|
|
822
831
|
server_version = _convert_python_package_version_to_image_tag(
|
|
@@ -856,7 +865,7 @@ def enrich_image_url(
|
|
|
856
865
|
|
|
857
866
|
|
|
858
867
|
def resolve_image_tag_suffix(
|
|
859
|
-
mlrun_version: str = None, python_version: str = None
|
|
868
|
+
mlrun_version: Optional[str] = None, python_version: Optional[str] = None
|
|
860
869
|
) -> str:
|
|
861
870
|
"""
|
|
862
871
|
resolves what suffix should be appended to the image tag
|
|
@@ -947,6 +956,36 @@ def fill_function_hash(function_dict, tag=""):
|
|
|
947
956
|
return fill_object_hash(function_dict, "hash", tag)
|
|
948
957
|
|
|
949
958
|
|
|
959
|
+
def fill_model_endpoint_hash(
|
|
960
|
+
model_endpoint: mlrun.common.schemas.ModelEndpointV2,
|
|
961
|
+
created_time: typing.Union[str, datetime],
|
|
962
|
+
) -> str:
|
|
963
|
+
"""
|
|
964
|
+
Fill the model endpoint uid field in the model endpoint object and returns it.
|
|
965
|
+
The uid is generated by hashing the following model endpoint fields:
|
|
966
|
+
- name
|
|
967
|
+
- model_tag
|
|
968
|
+
- function_name
|
|
969
|
+
- project
|
|
970
|
+
- created_time
|
|
971
|
+
"""
|
|
972
|
+
|
|
973
|
+
name = model_endpoint.metadata.name
|
|
974
|
+
model_tag = model_endpoint.spec.model_tag
|
|
975
|
+
function_name = model_endpoint.spec.function_name
|
|
976
|
+
project = model_endpoint.metadata.project
|
|
977
|
+
created_time = (
|
|
978
|
+
created_time
|
|
979
|
+
if isinstance(created_time, str)
|
|
980
|
+
else created_time.isoformat(sep=" ", timespec="microseconds")
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
unique_string = f"{name}_{model_tag}_{function_name}_{project}_{created_time}"
|
|
984
|
+
uid = hashlib.sha1(unique_string.encode("utf-8")).hexdigest()
|
|
985
|
+
model_endpoint.metadata.uid = uid
|
|
986
|
+
return uid
|
|
987
|
+
|
|
988
|
+
|
|
950
989
|
def retry_until_successful(
|
|
951
990
|
backoff: int, timeout: int, logger, verbose: bool, _function, *args, **kwargs
|
|
952
991
|
):
|
|
@@ -1175,7 +1214,7 @@ def get_function(function, namespaces, reload_modules: bool = False):
|
|
|
1175
1214
|
def get_handler_extended(
|
|
1176
1215
|
handler_path: str,
|
|
1177
1216
|
context=None,
|
|
1178
|
-
class_args: dict = None,
|
|
1217
|
+
class_args: Optional[dict] = None,
|
|
1179
1218
|
namespaces=None,
|
|
1180
1219
|
reload_modules: bool = False,
|
|
1181
1220
|
):
|
|
@@ -1226,24 +1265,14 @@ def datetime_to_iso(time_obj: Optional[datetime]) -> Optional[str]:
|
|
|
1226
1265
|
return time_obj.isoformat()
|
|
1227
1266
|
|
|
1228
1267
|
|
|
1229
|
-
def enrich_datetime_with_tz_info(timestamp_string)
|
|
1268
|
+
def enrich_datetime_with_tz_info(timestamp_string):
|
|
1230
1269
|
if not timestamp_string:
|
|
1231
1270
|
return timestamp_string
|
|
1232
1271
|
|
|
1233
1272
|
if timestamp_string and not mlrun.utils.helpers.has_timezone(timestamp_string):
|
|
1234
1273
|
timestamp_string += datetime.now(timezone.utc).astimezone().strftime("%z")
|
|
1235
1274
|
|
|
1236
|
-
|
|
1237
|
-
# e.g: 2021-08-25 12:00:00.000Z
|
|
1238
|
-
"%Y-%m-%d %H:%M:%S.%f%z",
|
|
1239
|
-
# e.g: 2024-11-11 07:44:56+0000
|
|
1240
|
-
"%Y-%m-%d %H:%M:%S%z",
|
|
1241
|
-
]:
|
|
1242
|
-
try:
|
|
1243
|
-
return datetime.strptime(timestamp_string, _format)
|
|
1244
|
-
except ValueError as exc:
|
|
1245
|
-
last_exc = exc
|
|
1246
|
-
raise last_exc
|
|
1275
|
+
return datetime.strptime(timestamp_string, "%Y-%m-%d %H:%M:%S.%f%z")
|
|
1247
1276
|
|
|
1248
1277
|
|
|
1249
1278
|
def has_timezone(timestamp):
|
|
@@ -1694,17 +1723,22 @@ def merge_dicts_with_precedence(*dicts: dict) -> dict:
|
|
|
1694
1723
|
|
|
1695
1724
|
|
|
1696
1725
|
def validate_component_version_compatibility(
|
|
1697
|
-
component_name: typing.Literal["iguazio", "nuclio"],
|
|
1726
|
+
component_name: typing.Literal["iguazio", "nuclio", "mlrun-client"],
|
|
1727
|
+
*min_versions: str,
|
|
1728
|
+
mlrun_client_version: Optional[str] = None,
|
|
1698
1729
|
):
|
|
1699
1730
|
"""
|
|
1700
1731
|
:param component_name: Name of the component to validate compatibility for.
|
|
1701
1732
|
:param min_versions: Valid minimum version(s) required, assuming no 2 versions has equal major and minor.
|
|
1733
|
+
:param mlrun_client_version: Client version to validate when component_name is "mlrun-client".
|
|
1702
1734
|
"""
|
|
1703
1735
|
parsed_min_versions = [
|
|
1704
1736
|
semver.VersionInfo.parse(min_version) for min_version in min_versions
|
|
1705
1737
|
]
|
|
1706
1738
|
parsed_current_version = None
|
|
1707
1739
|
component_current_version = None
|
|
1740
|
+
# For mlrun client we don't assume compatability if we fail to parse the client version
|
|
1741
|
+
assume_compatible = component_name not in ["mlrun-client"]
|
|
1708
1742
|
try:
|
|
1709
1743
|
if component_name == "iguazio":
|
|
1710
1744
|
component_current_version = mlrun.mlconf.igz_version
|
|
@@ -1721,18 +1755,29 @@ def validate_component_version_compatibility(
|
|
|
1721
1755
|
parsed_current_version = semver.VersionInfo.parse(
|
|
1722
1756
|
mlrun.mlconf.nuclio_version
|
|
1723
1757
|
)
|
|
1758
|
+
if component_name == "mlrun-client":
|
|
1759
|
+
# dev version, assume compatible
|
|
1760
|
+
if mlrun_client_version and (
|
|
1761
|
+
mlrun_client_version.startswith("0.0.0+")
|
|
1762
|
+
or "unstable" in mlrun_client_version
|
|
1763
|
+
):
|
|
1764
|
+
return True
|
|
1765
|
+
|
|
1766
|
+
component_current_version = mlrun_client_version
|
|
1767
|
+
parsed_current_version = semver.Version.parse(mlrun_client_version)
|
|
1724
1768
|
if not parsed_current_version:
|
|
1725
|
-
return
|
|
1769
|
+
return assume_compatible
|
|
1726
1770
|
except ValueError:
|
|
1727
1771
|
# only log when version is set but invalid
|
|
1728
1772
|
if component_current_version:
|
|
1729
1773
|
logger.warning(
|
|
1730
|
-
"Unable to parse current version
|
|
1774
|
+
"Unable to parse current version",
|
|
1731
1775
|
component_name=component_name,
|
|
1732
1776
|
current_version=component_current_version,
|
|
1733
1777
|
min_versions=min_versions,
|
|
1778
|
+
assume_compatible=assume_compatible,
|
|
1734
1779
|
)
|
|
1735
|
-
return
|
|
1780
|
+
return assume_compatible
|
|
1736
1781
|
|
|
1737
1782
|
# Feature might have been back-ported e.g. nuclio node selection is supported from
|
|
1738
1783
|
# 1.5.20 and 1.6.10 but not in 1.6.9 - therefore we reverse sort to validate against 1.6.x 1st and
|
|
@@ -1797,9 +1842,8 @@ def _reload(module, max_recursion_depth):
|
|
|
1797
1842
|
def run_with_retry(
|
|
1798
1843
|
retry_count: int,
|
|
1799
1844
|
func: typing.Callable,
|
|
1800
|
-
retry_on_exceptions:
|
|
1801
|
-
type[Exception],
|
|
1802
|
-
tuple[type[Exception]],
|
|
1845
|
+
retry_on_exceptions: Optional[
|
|
1846
|
+
typing.Union[type[Exception], tuple[type[Exception]]]
|
|
1803
1847
|
] = None,
|
|
1804
1848
|
*args,
|
|
1805
1849
|
**kwargs,
|