mlrun 1.6.4rc8__py3-none-any.whl → 1.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.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +11 -1
- mlrun/__main__.py +40 -122
- mlrun/alerts/__init__.py +15 -0
- mlrun/alerts/alert.py +248 -0
- mlrun/api/schemas/__init__.py +5 -4
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +47 -257
- mlrun/artifacts/dataset.py +11 -192
- mlrun/artifacts/manager.py +79 -47
- mlrun/artifacts/model.py +31 -159
- mlrun/artifacts/plots.py +23 -380
- mlrun/common/constants.py +74 -1
- mlrun/common/db/sql_session.py +5 -5
- mlrun/common/formatters/__init__.py +21 -0
- mlrun/common/formatters/artifact.py +45 -0
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/feature_set.py +33 -0
- mlrun/common/formatters/function.py +46 -0
- mlrun/common/formatters/pipeline.py +53 -0
- mlrun/common/formatters/project.py +51 -0
- mlrun/common/formatters/run.py +29 -0
- mlrun/common/helpers.py +12 -3
- mlrun/common/model_monitoring/helpers.py +9 -5
- mlrun/{runtimes → common/runtimes}/constants.py +37 -9
- mlrun/common/schemas/__init__.py +31 -5
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +196 -0
- mlrun/common/schemas/artifact.py +25 -4
- mlrun/common/schemas/auth.py +16 -5
- mlrun/common/schemas/background_task.py +1 -1
- mlrun/common/schemas/client_spec.py +4 -2
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/constants.py +3 -0
- mlrun/common/schemas/feature_store.py +74 -44
- mlrun/common/schemas/frontend_spec.py +15 -7
- mlrun/common/schemas/function.py +12 -1
- mlrun/common/schemas/hub.py +11 -18
- mlrun/common/schemas/memory_reports.py +2 -2
- mlrun/common/schemas/model_monitoring/__init__.py +20 -4
- mlrun/common/schemas/model_monitoring/constants.py +123 -42
- mlrun/common/schemas/model_monitoring/grafana.py +13 -9
- mlrun/common/schemas/model_monitoring/model_endpoints.py +101 -54
- mlrun/common/schemas/notification.py +71 -14
- mlrun/common/schemas/object.py +2 -2
- mlrun/{model_monitoring/controller_handler.py → common/schemas/pagination.py} +9 -12
- mlrun/common/schemas/pipeline.py +8 -1
- mlrun/common/schemas/project.py +69 -18
- mlrun/common/schemas/runs.py +7 -1
- mlrun/common/schemas/runtime_resource.py +8 -12
- mlrun/common/schemas/schedule.py +4 -4
- mlrun/common/schemas/tag.py +1 -2
- mlrun/common/schemas/workflow.py +12 -4
- mlrun/common/types.py +14 -1
- mlrun/config.py +154 -69
- mlrun/data_types/data_types.py +6 -1
- mlrun/data_types/spark.py +2 -2
- mlrun/data_types/to_pandas.py +67 -37
- mlrun/datastore/__init__.py +6 -8
- mlrun/datastore/alibaba_oss.py +131 -0
- mlrun/datastore/azure_blob.py +143 -42
- mlrun/datastore/base.py +102 -58
- mlrun/datastore/datastore.py +34 -13
- mlrun/datastore/datastore_profile.py +146 -20
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -4
- mlrun/datastore/google_cloud_storage.py +97 -33
- mlrun/datastore/hdfs.py +56 -0
- mlrun/datastore/inmem.py +6 -3
- mlrun/datastore/redis.py +7 -2
- mlrun/datastore/s3.py +34 -12
- mlrun/datastore/snowflake_utils.py +45 -0
- mlrun/datastore/sources.py +303 -111
- mlrun/datastore/spark_utils.py +31 -2
- mlrun/datastore/store_resources.py +9 -7
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +453 -176
- mlrun/datastore/utils.py +72 -58
- mlrun/datastore/v3io.py +6 -1
- mlrun/db/base.py +274 -41
- mlrun/db/factory.py +1 -1
- mlrun/db/httpdb.py +893 -225
- mlrun/db/nopdb.py +291 -33
- mlrun/errors.py +36 -6
- mlrun/execution.py +115 -42
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +65 -73
- mlrun/feature_store/common.py +7 -12
- mlrun/feature_store/feature_set.py +76 -55
- mlrun/feature_store/feature_vector.py +39 -31
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +16 -11
- mlrun/feature_store/retrieval/dask_merger.py +2 -0
- mlrun/feature_store/retrieval/job.py +13 -4
- mlrun/feature_store/retrieval/local_merger.py +2 -0
- mlrun/feature_store/retrieval/spark_merger.py +24 -32
- mlrun/feature_store/steps.py +45 -34
- mlrun/features.py +11 -21
- mlrun/frameworks/_common/artifacts_library.py +9 -9
- mlrun/frameworks/_common/mlrun_interface.py +5 -5
- mlrun/frameworks/_common/model_handler.py +48 -48
- mlrun/frameworks/_common/plan.py +5 -6
- mlrun/frameworks/_common/producer.py +3 -4
- mlrun/frameworks/_common/utils.py +5 -5
- mlrun/frameworks/_dl_common/loggers/logger.py +6 -7
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +9 -9
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +23 -47
- mlrun/frameworks/_ml_common/artifacts_library.py +1 -2
- mlrun/frameworks/_ml_common/loggers/logger.py +3 -4
- mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +4 -5
- mlrun/frameworks/_ml_common/model_handler.py +24 -24
- mlrun/frameworks/_ml_common/pkl_model_server.py +2 -2
- mlrun/frameworks/_ml_common/plan.py +2 -2
- mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +2 -3
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +2 -3
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/_ml_common/utils.py +4 -4
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +9 -9
- mlrun/frameworks/huggingface/model_server.py +4 -4
- mlrun/frameworks/lgbm/__init__.py +33 -33
- mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -5
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -5
- mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -3
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +6 -6
- mlrun/frameworks/lgbm/model_handler.py +10 -10
- mlrun/frameworks/lgbm/model_server.py +6 -6
- mlrun/frameworks/lgbm/utils.py +5 -5
- mlrun/frameworks/onnx/dataset.py +8 -8
- mlrun/frameworks/onnx/mlrun_interface.py +3 -3
- mlrun/frameworks/onnx/model_handler.py +6 -6
- mlrun/frameworks/onnx/model_server.py +7 -7
- mlrun/frameworks/parallel_coordinates.py +6 -6
- mlrun/frameworks/pytorch/__init__.py +18 -18
- mlrun/frameworks/pytorch/callbacks/callback.py +4 -5
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +17 -17
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +11 -11
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +23 -29
- mlrun/frameworks/pytorch/callbacks_handler.py +38 -38
- mlrun/frameworks/pytorch/mlrun_interface.py +20 -20
- mlrun/frameworks/pytorch/model_handler.py +17 -17
- mlrun/frameworks/pytorch/model_server.py +7 -7
- mlrun/frameworks/sklearn/__init__.py +13 -13
- mlrun/frameworks/sklearn/estimator.py +4 -4
- mlrun/frameworks/sklearn/metrics_library.py +14 -14
- mlrun/frameworks/sklearn/mlrun_interface.py +16 -9
- mlrun/frameworks/sklearn/model_handler.py +2 -2
- mlrun/frameworks/tf_keras/__init__.py +10 -7
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +15 -15
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +11 -11
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +19 -23
- mlrun/frameworks/tf_keras/mlrun_interface.py +9 -11
- mlrun/frameworks/tf_keras/model_handler.py +14 -14
- mlrun/frameworks/tf_keras/model_server.py +6 -6
- mlrun/frameworks/xgboost/__init__.py +13 -13
- mlrun/frameworks/xgboost/model_handler.py +6 -6
- mlrun/k8s_utils.py +61 -17
- mlrun/launcher/__init__.py +1 -1
- mlrun/launcher/base.py +16 -15
- mlrun/launcher/client.py +13 -11
- mlrun/launcher/factory.py +1 -1
- mlrun/launcher/local.py +23 -13
- mlrun/launcher/remote.py +17 -10
- mlrun/lists.py +7 -6
- mlrun/model.py +478 -103
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +163 -371
- mlrun/{runtimes/mpijob/v1alpha1.py → model_monitoring/applications/__init__.py} +9 -15
- mlrun/model_monitoring/applications/_application_steps.py +188 -0
- mlrun/model_monitoring/applications/base.py +108 -0
- mlrun/model_monitoring/applications/context.py +341 -0
- mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
- mlrun/model_monitoring/applications/histogram_data_drift.py +354 -0
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +131 -278
- mlrun/model_monitoring/db/__init__.py +18 -0
- mlrun/model_monitoring/db/stores/__init__.py +136 -0
- mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
- mlrun/model_monitoring/db/stores/base/store.py +213 -0
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
- mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
- mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
- mlrun/model_monitoring/db/tsdb/base.py +448 -0
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +279 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +507 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
- mlrun/model_monitoring/features_drift_table.py +134 -106
- mlrun/model_monitoring/helpers.py +199 -55
- mlrun/model_monitoring/metrics/__init__.py +13 -0
- mlrun/model_monitoring/metrics/histogram_distance.py +127 -0
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +134 -398
- mlrun/model_monitoring/tracking_policy.py +9 -2
- mlrun/model_monitoring/writer.py +161 -125
- mlrun/package/__init__.py +6 -6
- mlrun/package/context_handler.py +5 -5
- mlrun/package/packager.py +7 -7
- mlrun/package/packagers/default_packager.py +8 -8
- mlrun/package/packagers/numpy_packagers.py +15 -15
- mlrun/package/packagers/pandas_packagers.py +5 -5
- mlrun/package/packagers/python_standard_library_packagers.py +10 -10
- mlrun/package/packagers_manager.py +19 -23
- mlrun/package/utils/_formatter.py +6 -6
- mlrun/package/utils/_pickler.py +2 -2
- mlrun/package/utils/_supported_format.py +4 -4
- mlrun/package/utils/log_hint_utils.py +2 -2
- mlrun/package/utils/type_hint_utils.py +4 -9
- mlrun/platforms/__init__.py +11 -10
- mlrun/platforms/iguazio.py +24 -203
- mlrun/projects/operations.py +52 -25
- mlrun/projects/pipelines.py +191 -197
- mlrun/projects/project.py +1227 -400
- mlrun/render.py +16 -19
- mlrun/run.py +209 -184
- mlrun/runtimes/__init__.py +83 -15
- mlrun/runtimes/base.py +51 -35
- mlrun/runtimes/daskjob.py +17 -10
- mlrun/runtimes/databricks_job/databricks_cancel_task.py +1 -1
- mlrun/runtimes/databricks_job/databricks_runtime.py +8 -7
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -29
- mlrun/runtimes/function_reference.py +1 -1
- mlrun/runtimes/kubejob.py +34 -128
- mlrun/runtimes/local.py +40 -11
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/abstract.py +9 -10
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/{model_monitoring/stores/models/sqlite.py → runtimes/nuclio/__init__.py} +7 -9
- mlrun/runtimes/nuclio/api_gateway.py +769 -0
- mlrun/runtimes/nuclio/application/__init__.py +15 -0
- mlrun/runtimes/nuclio/application/application.py +758 -0
- mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
- mlrun/runtimes/{function.py → nuclio/function.py} +200 -83
- mlrun/runtimes/{nuclio.py → nuclio/nuclio.py} +6 -6
- mlrun/runtimes/{serving.py → nuclio/serving.py} +65 -68
- mlrun/runtimes/pod.py +281 -101
- mlrun/runtimes/remotesparkjob.py +12 -9
- mlrun/runtimes/sparkjob/spark3job.py +67 -51
- mlrun/runtimes/utils.py +41 -75
- mlrun/secrets.py +9 -5
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/remote.py +2 -7
- mlrun/serving/routers.py +85 -69
- mlrun/serving/server.py +69 -44
- mlrun/serving/states.py +209 -36
- mlrun/serving/utils.py +22 -14
- mlrun/serving/v1_serving.py +6 -7
- mlrun/serving/v2_serving.py +133 -54
- mlrun/track/tracker.py +2 -1
- mlrun/track/tracker_manager.py +3 -3
- mlrun/track/trackers/mlflow_tracker.py +6 -2
- mlrun/utils/async_http.py +6 -8
- mlrun/utils/azure_vault.py +1 -1
- mlrun/utils/clones.py +1 -2
- mlrun/utils/condition_evaluator.py +3 -3
- mlrun/utils/db.py +21 -3
- mlrun/utils/helpers.py +405 -225
- mlrun/utils/http.py +3 -6
- mlrun/utils/logger.py +112 -16
- mlrun/utils/notifications/notification/__init__.py +17 -13
- mlrun/utils/notifications/notification/base.py +50 -2
- mlrun/utils/notifications/notification/console.py +2 -0
- mlrun/utils/notifications/notification/git.py +24 -1
- mlrun/utils/notifications/notification/ipython.py +3 -1
- mlrun/utils/notifications/notification/slack.py +96 -21
- mlrun/utils/notifications/notification/webhook.py +59 -2
- mlrun/utils/notifications/notification_pusher.py +149 -30
- mlrun/utils/regex.py +9 -0
- mlrun/utils/retryer.py +208 -0
- mlrun/utils/singleton.py +1 -1
- mlrun/utils/v3io_clients.py +4 -6
- mlrun/utils/version/version.json +2 -2
- mlrun/utils/version/version.py +2 -6
- mlrun-1.7.0.dist-info/METADATA +378 -0
- mlrun-1.7.0.dist-info/RECORD +351 -0
- {mlrun-1.6.4rc8.dist-info → mlrun-1.7.0.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -273
- mlrun/kfpops.py +0 -868
- mlrun/model_monitoring/application.py +0 -310
- mlrun/model_monitoring/batch.py +0 -1095
- mlrun/model_monitoring/prometheus.py +0 -219
- mlrun/model_monitoring/stores/__init__.py +0 -111
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -576
- mlrun/model_monitoring/stores/model_endpoint_store.py +0 -147
- mlrun/model_monitoring/stores/models/__init__.py +0 -27
- mlrun/model_monitoring/stores/models/base.py +0 -84
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -384
- mlrun/platforms/other.py +0 -306
- mlrun-1.6.4rc8.dist-info/METADATA +0 -272
- mlrun-1.6.4rc8.dist-info/RECORD +0 -314
- {mlrun-1.6.4rc8.dist-info → mlrun-1.7.0.dist-info}/LICENSE +0 -0
- {mlrun-1.6.4rc8.dist-info → mlrun-1.7.0.dist-info}/entry_points.txt +0 -0
- {mlrun-1.6.4rc8.dist-info → mlrun-1.7.0.dist-info}/top_level.txt +0 -0
mlrun/serving/states.py
CHANGED
|
@@ -12,20 +12,31 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
__all__ = [
|
|
15
|
+
__all__ = [
|
|
16
|
+
"TaskStep",
|
|
17
|
+
"RouterStep",
|
|
18
|
+
"RootFlowStep",
|
|
19
|
+
"ErrorStep",
|
|
20
|
+
"MonitoringApplicationStep",
|
|
21
|
+
]
|
|
16
22
|
|
|
17
23
|
import os
|
|
18
24
|
import pathlib
|
|
19
25
|
import traceback
|
|
20
26
|
from copy import copy, deepcopy
|
|
21
27
|
from inspect import getfullargspec, signature
|
|
22
|
-
from typing import Union
|
|
28
|
+
from typing import Any, Union
|
|
29
|
+
|
|
30
|
+
import storey.utils
|
|
23
31
|
|
|
24
32
|
import mlrun
|
|
25
33
|
|
|
26
34
|
from ..config import config
|
|
27
35
|
from ..datastore import get_stream_pusher
|
|
28
|
-
from ..datastore.utils import
|
|
36
|
+
from ..datastore.utils import (
|
|
37
|
+
get_kafka_brokers_from_dict,
|
|
38
|
+
parse_kafka_url,
|
|
39
|
+
)
|
|
29
40
|
from ..errors import MLRunInvalidArgumentError, err_to_str
|
|
30
41
|
from ..model import ModelObj, ObjectDict
|
|
31
42
|
from ..platforms.iguazio import parse_path
|
|
@@ -52,6 +63,7 @@ class StepKinds:
|
|
|
52
63
|
choice = "choice"
|
|
53
64
|
root = "root"
|
|
54
65
|
error_step = "error_step"
|
|
66
|
+
monitoring_application = "monitoring_application"
|
|
55
67
|
|
|
56
68
|
|
|
57
69
|
_task_step_fields = [
|
|
@@ -72,6 +84,9 @@ _task_step_fields = [
|
|
|
72
84
|
]
|
|
73
85
|
|
|
74
86
|
|
|
87
|
+
MAX_ALLOWED_STEPS = 4500
|
|
88
|
+
|
|
89
|
+
|
|
75
90
|
def new_model_endpoint(class_name, model_path, handler=None, **class_args):
|
|
76
91
|
class_args = deepcopy(class_args)
|
|
77
92
|
class_args["model_path"] = model_path
|
|
@@ -324,7 +339,7 @@ class BaseStep(ModelObj):
|
|
|
324
339
|
parent = self._parent
|
|
325
340
|
else:
|
|
326
341
|
raise GraphError(
|
|
327
|
-
f"step {self.name} parent is not set or
|
|
342
|
+
f"step {self.name} parent is not set or it's not part of a graph"
|
|
328
343
|
)
|
|
329
344
|
|
|
330
345
|
name, step = params_to_step(
|
|
@@ -346,6 +361,39 @@ class BaseStep(ModelObj):
|
|
|
346
361
|
parent._last_added = step
|
|
347
362
|
return step
|
|
348
363
|
|
|
364
|
+
def set_flow(
|
|
365
|
+
self,
|
|
366
|
+
steps: list[Union[str, StepToDict, dict[str, Any]]],
|
|
367
|
+
force: bool = False,
|
|
368
|
+
):
|
|
369
|
+
"""set list of steps as downstream from this step, in the order specified. This will overwrite any existing
|
|
370
|
+
downstream steps.
|
|
371
|
+
|
|
372
|
+
:param steps: list of steps to follow this one
|
|
373
|
+
:param force: whether to overwrite existing downstream steps. If False, this method will fail if any downstream
|
|
374
|
+
steps have already been defined. Defaults to False.
|
|
375
|
+
:return: the last step added to the flow
|
|
376
|
+
|
|
377
|
+
example:
|
|
378
|
+
The below code sets the downstream nodes of step1 by using a list of steps (provided to `set_flow()`) and a
|
|
379
|
+
single step (provided to `to()`), resulting in the graph (step1 -> step2 -> step3 -> step4).
|
|
380
|
+
Notice that using `force=True` is required in case step1 already had downstream nodes (e.g. if the existing
|
|
381
|
+
graph is step1 -> step2_old) and that following the execution of this code the existing downstream steps
|
|
382
|
+
are removed. If the intention is to split the graph (and not to overwrite), please use `to()`.
|
|
383
|
+
|
|
384
|
+
step1.set_flow(
|
|
385
|
+
[
|
|
386
|
+
dict(name="step2", handler="step2_handler"),
|
|
387
|
+
dict(name="step3", class_name="Step3Class"),
|
|
388
|
+
],
|
|
389
|
+
force=True,
|
|
390
|
+
).to(dict(name="step4", class_name="Step4Class"))
|
|
391
|
+
"""
|
|
392
|
+
raise NotImplementedError("set_flow() can only be called on a FlowStep")
|
|
393
|
+
|
|
394
|
+
def supports_termination(self):
|
|
395
|
+
return False
|
|
396
|
+
|
|
349
397
|
|
|
350
398
|
class TaskStep(BaseStep):
|
|
351
399
|
"""task execution step, runs a class or handler"""
|
|
@@ -452,13 +500,15 @@ class TaskStep(BaseStep):
|
|
|
452
500
|
class_args[key] = arg
|
|
453
501
|
class_args.update(extra_kwargs)
|
|
454
502
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
503
|
+
if not isinstance(self, MonitoringApplicationStep):
|
|
504
|
+
# add common args (name, context, ..) only if target class can accept them
|
|
505
|
+
argspec = getfullargspec(class_object)
|
|
506
|
+
|
|
507
|
+
for key in ["name", "context", "input_path", "result_path", "full_event"]:
|
|
508
|
+
if argspec.varkw or key in argspec.args:
|
|
509
|
+
class_args[key] = getattr(self, key)
|
|
510
|
+
if argspec.varkw or "graph_step" in argspec.args:
|
|
511
|
+
class_args["graph_step"] = self
|
|
462
512
|
return class_args
|
|
463
513
|
|
|
464
514
|
def get_step_class_object(self, namespace):
|
|
@@ -549,6 +599,39 @@ class TaskStep(BaseStep):
|
|
|
549
599
|
return event
|
|
550
600
|
|
|
551
601
|
|
|
602
|
+
class MonitoringApplicationStep(TaskStep):
|
|
603
|
+
"""monitoring application execution step, runs users class code"""
|
|
604
|
+
|
|
605
|
+
kind = "monitoring_application"
|
|
606
|
+
_default_class = ""
|
|
607
|
+
|
|
608
|
+
def __init__(
|
|
609
|
+
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,
|
|
620
|
+
):
|
|
621
|
+
super().__init__(
|
|
622
|
+
class_name=class_name,
|
|
623
|
+
class_args=class_args,
|
|
624
|
+
handler=handler,
|
|
625
|
+
name=name,
|
|
626
|
+
after=after,
|
|
627
|
+
full_event=full_event,
|
|
628
|
+
function=function,
|
|
629
|
+
responder=responder,
|
|
630
|
+
input_path=input_path,
|
|
631
|
+
result_path=result_path,
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
|
|
552
635
|
class ErrorStep(TaskStep):
|
|
553
636
|
"""error execution step, runs a class or handler"""
|
|
554
637
|
|
|
@@ -556,6 +639,34 @@ class ErrorStep(TaskStep):
|
|
|
556
639
|
_dict_fields = _task_step_fields + ["before", "base_step"]
|
|
557
640
|
_default_class = ""
|
|
558
641
|
|
|
642
|
+
def __init__(
|
|
643
|
+
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,
|
|
654
|
+
):
|
|
655
|
+
super().__init__(
|
|
656
|
+
class_name=class_name,
|
|
657
|
+
class_args=class_args,
|
|
658
|
+
handler=handler,
|
|
659
|
+
name=name,
|
|
660
|
+
after=after,
|
|
661
|
+
full_event=full_event,
|
|
662
|
+
function=function,
|
|
663
|
+
responder=responder,
|
|
664
|
+
input_path=input_path,
|
|
665
|
+
result_path=result_path,
|
|
666
|
+
)
|
|
667
|
+
self.before = None
|
|
668
|
+
self.base_step = None
|
|
669
|
+
|
|
559
670
|
|
|
560
671
|
class RouterStep(TaskStep):
|
|
561
672
|
"""router step, implement routing logic for running child routes"""
|
|
@@ -625,6 +736,11 @@ class RouterStep(TaskStep):
|
|
|
625
736
|
if not route:
|
|
626
737
|
route = TaskStep(class_name, class_args, handler=handler)
|
|
627
738
|
route.function = function or route.function
|
|
739
|
+
|
|
740
|
+
if len(self._routes) >= MAX_ALLOWED_STEPS:
|
|
741
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
742
|
+
f"Cannot create the serving graph: the maximum number of steps is {MAX_ALLOWED_STEPS}"
|
|
743
|
+
)
|
|
628
744
|
route = self._routes.update(key, route)
|
|
629
745
|
route.set_parent(self)
|
|
630
746
|
return route
|
|
@@ -729,13 +845,45 @@ class QueueStep(BaseStep):
|
|
|
729
845
|
def async_object(self):
|
|
730
846
|
return self._async_object
|
|
731
847
|
|
|
848
|
+
def to(
|
|
849
|
+
self,
|
|
850
|
+
class_name: Union[str, StepToDict] = None,
|
|
851
|
+
name: str = None,
|
|
852
|
+
handler: str = None,
|
|
853
|
+
graph_shape: str = None,
|
|
854
|
+
function: str = None,
|
|
855
|
+
full_event: bool = None,
|
|
856
|
+
input_path: str = None,
|
|
857
|
+
result_path: str = None,
|
|
858
|
+
**class_args,
|
|
859
|
+
):
|
|
860
|
+
if not function:
|
|
861
|
+
name = get_name(name, class_name)
|
|
862
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
863
|
+
f"step '{name}' must specify a function, because it follows a queue step"
|
|
864
|
+
)
|
|
865
|
+
return super().to(
|
|
866
|
+
class_name,
|
|
867
|
+
name,
|
|
868
|
+
handler,
|
|
869
|
+
graph_shape,
|
|
870
|
+
function,
|
|
871
|
+
full_event,
|
|
872
|
+
input_path,
|
|
873
|
+
result_path,
|
|
874
|
+
**class_args,
|
|
875
|
+
)
|
|
876
|
+
|
|
732
877
|
def run(self, event, *args, **kwargs):
|
|
733
878
|
data = event.body
|
|
734
879
|
if not data:
|
|
735
880
|
return event
|
|
736
881
|
|
|
737
882
|
if self._stream:
|
|
738
|
-
self.
|
|
883
|
+
full_event = self.options.get("full_event")
|
|
884
|
+
if full_event or full_event is None and self.next:
|
|
885
|
+
data = storey.utils.wrap_event_for_serialization(event, data)
|
|
886
|
+
self._stream.push(data)
|
|
739
887
|
event.terminated = True
|
|
740
888
|
event.body = None
|
|
741
889
|
return event
|
|
@@ -1132,23 +1280,17 @@ class FlowStep(BaseStep):
|
|
|
1132
1280
|
if self._controller:
|
|
1133
1281
|
# async flow (using storey)
|
|
1134
1282
|
event._awaitable_result = None
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
return resp_awaitable
|
|
1141
|
-
return self._await_and_return_id(resp_awaitable, event)
|
|
1142
|
-
else:
|
|
1143
|
-
resp = self._controller.emit(
|
|
1144
|
-
event, return_awaitable_result=self._wait_for_result
|
|
1145
|
-
)
|
|
1146
|
-
if self._wait_for_result and resp:
|
|
1147
|
-
return resp.await_result()
|
|
1283
|
+
resp = self._controller.emit(
|
|
1284
|
+
event, return_awaitable_result=self._wait_for_result
|
|
1285
|
+
)
|
|
1286
|
+
if self._wait_for_result and resp:
|
|
1287
|
+
return resp.await_result()
|
|
1148
1288
|
event = copy(event)
|
|
1149
1289
|
event.body = {"id": event.id}
|
|
1150
1290
|
return event
|
|
1151
1291
|
|
|
1292
|
+
event = storey.utils.unpack_event_if_wrapped(event)
|
|
1293
|
+
|
|
1152
1294
|
if len(self._start_steps) == 0:
|
|
1153
1295
|
return event
|
|
1154
1296
|
next_obj = self._start_steps[0]
|
|
@@ -1182,6 +1324,7 @@ class FlowStep(BaseStep):
|
|
|
1182
1324
|
|
|
1183
1325
|
def wait_for_completion(self):
|
|
1184
1326
|
"""wait for completion of run in async flows"""
|
|
1327
|
+
|
|
1185
1328
|
if self._controller:
|
|
1186
1329
|
if hasattr(self._controller, "terminate"):
|
|
1187
1330
|
self._controller.terminate()
|
|
@@ -1234,6 +1377,30 @@ class FlowStep(BaseStep):
|
|
|
1234
1377
|
)
|
|
1235
1378
|
self[step_name].after_step(name)
|
|
1236
1379
|
|
|
1380
|
+
def set_flow(
|
|
1381
|
+
self,
|
|
1382
|
+
steps: list[Union[str, StepToDict, dict[str, Any]]],
|
|
1383
|
+
force: bool = False,
|
|
1384
|
+
):
|
|
1385
|
+
if not force and self.steps:
|
|
1386
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
1387
|
+
"set_flow() called on a step that already has downstream steps. "
|
|
1388
|
+
"If you want to overwrite existing steps, set force=True."
|
|
1389
|
+
)
|
|
1390
|
+
|
|
1391
|
+
self.steps = None
|
|
1392
|
+
step = self
|
|
1393
|
+
for next_step in steps:
|
|
1394
|
+
if isinstance(next_step, dict):
|
|
1395
|
+
step = step.to(**next_step)
|
|
1396
|
+
else:
|
|
1397
|
+
step = step.to(next_step)
|
|
1398
|
+
|
|
1399
|
+
return step
|
|
1400
|
+
|
|
1401
|
+
def supports_termination(self):
|
|
1402
|
+
return self.engine != "sync"
|
|
1403
|
+
|
|
1237
1404
|
|
|
1238
1405
|
class RootFlowStep(FlowStep):
|
|
1239
1406
|
"""root flow step"""
|
|
@@ -1248,6 +1415,7 @@ classes_map = {
|
|
|
1248
1415
|
"flow": FlowStep,
|
|
1249
1416
|
"queue": QueueStep,
|
|
1250
1417
|
"error_step": ErrorStep,
|
|
1418
|
+
"monitoring_application": MonitoringApplicationStep,
|
|
1251
1419
|
}
|
|
1252
1420
|
|
|
1253
1421
|
|
|
@@ -1471,15 +1639,17 @@ def _init_async_objects(context, steps):
|
|
|
1471
1639
|
if step.path and not skip_stream:
|
|
1472
1640
|
stream_path = step.path
|
|
1473
1641
|
endpoint = None
|
|
1474
|
-
|
|
1642
|
+
# in case of a queue, we default to a full_event=True
|
|
1643
|
+
full_event = step.options.get("full_event")
|
|
1644
|
+
options = {
|
|
1645
|
+
"full_event": full_event or full_event is None and step.next
|
|
1646
|
+
}
|
|
1475
1647
|
options.update(step.options)
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
if stream_path.startswith("kafka://") or
|
|
1480
|
-
topic,
|
|
1481
|
-
stream_path, kafka_bootstrap_servers
|
|
1482
|
-
)
|
|
1648
|
+
|
|
1649
|
+
kafka_brokers = get_kafka_brokers_from_dict(options, pop=True)
|
|
1650
|
+
|
|
1651
|
+
if stream_path.startswith("kafka://") or kafka_brokers:
|
|
1652
|
+
topic, brokers = parse_kafka_url(stream_path, kafka_brokers)
|
|
1483
1653
|
|
|
1484
1654
|
kafka_producer_options = options.pop(
|
|
1485
1655
|
"kafka_producer_options", None
|
|
@@ -1487,7 +1657,7 @@ def _init_async_objects(context, steps):
|
|
|
1487
1657
|
|
|
1488
1658
|
step._async_object = storey.KafkaTarget(
|
|
1489
1659
|
topic=topic,
|
|
1490
|
-
|
|
1660
|
+
brokers=brokers,
|
|
1491
1661
|
producer_options=kafka_producer_options,
|
|
1492
1662
|
context=context,
|
|
1493
1663
|
**options,
|
|
@@ -1514,6 +1684,7 @@ def _init_async_objects(context, steps):
|
|
|
1514
1684
|
result_path=step.result_path,
|
|
1515
1685
|
name=step.name,
|
|
1516
1686
|
context=context,
|
|
1687
|
+
pass_context=step._inject_context,
|
|
1517
1688
|
)
|
|
1518
1689
|
if (
|
|
1519
1690
|
respond_supported
|
|
@@ -1526,9 +1697,11 @@ def _init_async_objects(context, steps):
|
|
|
1526
1697
|
wait_for_result = True
|
|
1527
1698
|
|
|
1528
1699
|
source_args = context.get_param("source_args", {})
|
|
1700
|
+
explicit_ack = (
|
|
1701
|
+
is_explicit_ack_supported(context) and mlrun.mlconf.is_explicit_ack_enabled()
|
|
1702
|
+
)
|
|
1529
1703
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1704
|
+
# TODO: Change to AsyncEmitSource once we can drop support for nuclio<1.12.10
|
|
1532
1705
|
default_source = storey.SyncEmitSource(
|
|
1533
1706
|
context=context,
|
|
1534
1707
|
explicit_ack=explicit_ack,
|
mlrun/serving/utils.py
CHANGED
|
@@ -46,7 +46,16 @@ def _update_result_body(result_path, event_body, result):
|
|
|
46
46
|
class StepToDict:
|
|
47
47
|
"""auto serialization of graph steps to a python dictionary"""
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
meta_keys = [
|
|
50
|
+
"context",
|
|
51
|
+
"name",
|
|
52
|
+
"input_path",
|
|
53
|
+
"result_path",
|
|
54
|
+
"full_event",
|
|
55
|
+
"kwargs",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
|
|
50
59
|
"""convert the step object to a python dictionary"""
|
|
51
60
|
fields = fields or getattr(self, "_dict_fields", None)
|
|
52
61
|
if not fields:
|
|
@@ -54,24 +63,16 @@ class StepToDict:
|
|
|
54
63
|
if exclude:
|
|
55
64
|
fields = [field for field in fields if field not in exclude]
|
|
56
65
|
|
|
57
|
-
meta_keys = [
|
|
58
|
-
"context",
|
|
59
|
-
"name",
|
|
60
|
-
"input_path",
|
|
61
|
-
"result_path",
|
|
62
|
-
"full_event",
|
|
63
|
-
"kwargs",
|
|
64
|
-
]
|
|
65
66
|
args = {
|
|
66
67
|
key: getattr(self, key)
|
|
67
68
|
for key in fields
|
|
68
|
-
if getattr(self, key, None) is not None and key not in meta_keys
|
|
69
|
+
if getattr(self, key, None) is not None and key not in self.meta_keys
|
|
69
70
|
}
|
|
70
71
|
# add storey kwargs or extra kwargs
|
|
71
72
|
if "kwargs" in fields and (hasattr(self, "kwargs") or hasattr(self, "_kwargs")):
|
|
72
73
|
kwargs = getattr(self, "kwargs", {}) or getattr(self, "_kwargs", {})
|
|
73
74
|
for key, value in kwargs.items():
|
|
74
|
-
if key not in meta_keys:
|
|
75
|
+
if key not in self.meta_keys:
|
|
75
76
|
args[key] = value
|
|
76
77
|
|
|
77
78
|
mod_name = self.__class__.__module__
|
|
@@ -80,7 +81,9 @@ class StepToDict:
|
|
|
80
81
|
class_path = f"{mod_name}.{class_path}"
|
|
81
82
|
struct = {
|
|
82
83
|
"class_name": class_path,
|
|
83
|
-
"name": self.name
|
|
84
|
+
"name": self.name
|
|
85
|
+
if hasattr(self, "name") and self.name
|
|
86
|
+
else self.__class__.__name__,
|
|
84
87
|
"class_args": args,
|
|
85
88
|
}
|
|
86
89
|
if hasattr(self, "_STEP_KIND"):
|
|
@@ -94,8 +97,13 @@ class StepToDict:
|
|
|
94
97
|
return struct
|
|
95
98
|
|
|
96
99
|
|
|
100
|
+
class MonitoringApplicationToDict(StepToDict):
|
|
101
|
+
_STEP_KIND = "monitoring_application"
|
|
102
|
+
meta_keys = []
|
|
103
|
+
|
|
104
|
+
|
|
97
105
|
class RouterToDict(StepToDict):
|
|
98
106
|
_STEP_KIND = "router"
|
|
99
107
|
|
|
100
|
-
def to_dict(self, fields=None, exclude=None):
|
|
101
|
-
return super().to_dict(exclude=["routes"])
|
|
108
|
+
def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
|
|
109
|
+
return super().to_dict(exclude=["routes"], strip=strip)
|
mlrun/serving/v1_serving.py
CHANGED
|
@@ -18,7 +18,6 @@ import socket
|
|
|
18
18
|
from copy import deepcopy
|
|
19
19
|
from datetime import datetime
|
|
20
20
|
from io import BytesIO
|
|
21
|
-
from typing import Dict
|
|
22
21
|
from urllib.request import urlopen
|
|
23
22
|
|
|
24
23
|
import nuclio
|
|
@@ -26,7 +25,7 @@ import nuclio
|
|
|
26
25
|
import mlrun
|
|
27
26
|
from mlrun.errors import err_to_str
|
|
28
27
|
from mlrun.platforms.iguazio import OutputStream
|
|
29
|
-
from mlrun.runtimes import RemoteRuntime
|
|
28
|
+
from mlrun.runtimes.nuclio.function import RemoteRuntime
|
|
30
29
|
|
|
31
30
|
serving_handler = "handler"
|
|
32
31
|
|
|
@@ -97,16 +96,16 @@ class MLModelServer:
|
|
|
97
96
|
if not self.ready and not self.model:
|
|
98
97
|
raise ValueError("please specify a load method or a model object")
|
|
99
98
|
|
|
100
|
-
def preprocess(self, request:
|
|
99
|
+
def preprocess(self, request: dict) -> dict:
|
|
101
100
|
return request
|
|
102
101
|
|
|
103
|
-
def postprocess(self, request:
|
|
102
|
+
def postprocess(self, request: dict) -> dict:
|
|
104
103
|
return request
|
|
105
104
|
|
|
106
|
-
def predict(self, request:
|
|
105
|
+
def predict(self, request: dict) -> dict:
|
|
107
106
|
raise NotImplementedError()
|
|
108
107
|
|
|
109
|
-
def explain(self, request:
|
|
108
|
+
def explain(self, request: dict) -> dict:
|
|
110
109
|
raise NotImplementedError()
|
|
111
110
|
|
|
112
111
|
|
|
@@ -200,7 +199,7 @@ class _ServerInfo:
|
|
|
200
199
|
class HTTPHandler:
|
|
201
200
|
kind = ""
|
|
202
201
|
|
|
203
|
-
def __init__(self, models:
|
|
202
|
+
def __init__(self, models: dict, server: _ServerInfo = None):
|
|
204
203
|
self.models = models
|
|
205
204
|
self.srvinfo = server
|
|
206
205
|
self.context = None
|