mlrun 1.7.0rc5__py3-none-any.whl → 1.7.2__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 +39 -121
- mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
- mlrun/alerts/alert.py +248 -0
- mlrun/api/schemas/__init__.py +4 -3
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +39 -254
- mlrun/artifacts/dataset.py +9 -190
- mlrun/artifacts/manager.py +73 -46
- mlrun/artifacts/model.py +30 -158
- mlrun/artifacts/plots.py +23 -380
- mlrun/common/constants.py +73 -2
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/formatters/__init__.py +21 -0
- mlrun/common/formatters/artifact.py +46 -0
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/feature_set.py +44 -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 +11 -1
- mlrun/{runtimes → common/runtimes}/constants.py +32 -4
- mlrun/common/schemas/__init__.py +21 -4
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +113 -2
- mlrun/common/schemas/artifact.py +28 -1
- mlrun/common/schemas/auth.py +11 -0
- mlrun/common/schemas/client_spec.py +2 -1
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/constants.py +3 -0
- mlrun/common/schemas/feature_store.py +58 -28
- mlrun/common/schemas/frontend_spec.py +8 -0
- mlrun/common/schemas/function.py +11 -0
- mlrun/common/schemas/hub.py +7 -9
- mlrun/common/schemas/model_monitoring/__init__.py +21 -4
- mlrun/common/schemas/model_monitoring/constants.py +136 -42
- mlrun/common/schemas/model_monitoring/grafana.py +9 -5
- mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
- mlrun/common/schemas/notification.py +69 -12
- mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
- mlrun/common/schemas/pipeline.py +7 -0
- mlrun/common/schemas/project.py +67 -16
- mlrun/common/schemas/runs.py +17 -0
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/workflow.py +10 -2
- mlrun/common/types.py +14 -1
- mlrun/config.py +224 -58
- mlrun/data_types/data_types.py +11 -1
- mlrun/data_types/spark.py +5 -4
- mlrun/data_types/to_pandas.py +75 -34
- mlrun/datastore/__init__.py +8 -10
- mlrun/datastore/alibaba_oss.py +131 -0
- mlrun/datastore/azure_blob.py +131 -43
- mlrun/datastore/base.py +107 -47
- mlrun/datastore/datastore.py +17 -7
- mlrun/datastore/datastore_profile.py +91 -7
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +92 -32
- mlrun/datastore/hdfs.py +5 -0
- mlrun/datastore/inmem.py +6 -3
- mlrun/datastore/redis.py +3 -2
- mlrun/datastore/s3.py +30 -12
- mlrun/datastore/snowflake_utils.py +45 -0
- mlrun/datastore/sources.py +274 -59
- mlrun/datastore/spark_utils.py +30 -0
- mlrun/datastore/store_resources.py +9 -7
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +374 -102
- mlrun/datastore/utils.py +68 -5
- mlrun/datastore/v3io.py +28 -50
- mlrun/db/auth_utils.py +152 -0
- mlrun/db/base.py +231 -22
- mlrun/db/factory.py +1 -4
- mlrun/db/httpdb.py +864 -228
- mlrun/db/nopdb.py +268 -16
- mlrun/errors.py +35 -5
- mlrun/execution.py +111 -38
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +46 -53
- mlrun/feature_store/common.py +6 -11
- mlrun/feature_store/feature_set.py +48 -23
- mlrun/feature_store/feature_vector.py +13 -2
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +9 -4
- 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 +38 -19
- mlrun/features.py +6 -14
- mlrun/frameworks/_common/plan.py +3 -3
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +4 -4
- mlrun/frameworks/pytorch/__init__.py +2 -2
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/frameworks/tf_keras/__init__.py +5 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/k8s_utils.py +57 -12
- mlrun/launcher/__init__.py +1 -1
- mlrun/launcher/base.py +6 -5
- mlrun/launcher/client.py +13 -11
- mlrun/launcher/factory.py +1 -1
- mlrun/launcher/local.py +15 -5
- mlrun/launcher/remote.py +10 -3
- mlrun/lists.py +6 -2
- mlrun/model.py +297 -48
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +152 -357
- mlrun/model_monitoring/applications/__init__.py +10 -0
- mlrun/model_monitoring/applications/_application_steps.py +190 -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 +227 -91
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +130 -303
- mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
- 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 +298 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -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 +34 -22
- mlrun/model_monitoring/helpers.py +177 -39
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +165 -398
- mlrun/model_monitoring/tracking_policy.py +7 -1
- mlrun/model_monitoring/writer.py +161 -125
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/package/packagers_manager.py +1 -0
- mlrun/package/utils/_formatter.py +2 -2
- mlrun/platforms/__init__.py +11 -10
- mlrun/platforms/iguazio.py +67 -228
- mlrun/projects/__init__.py +6 -1
- mlrun/projects/operations.py +47 -20
- mlrun/projects/pipelines.py +396 -249
- mlrun/projects/project.py +1125 -414
- mlrun/render.py +28 -22
- mlrun/run.py +207 -180
- mlrun/runtimes/__init__.py +76 -11
- mlrun/runtimes/base.py +40 -14
- mlrun/runtimes/daskjob.py +9 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -29
- mlrun/runtimes/kubejob.py +34 -128
- mlrun/runtimes/local.py +39 -10
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/abstract.py +8 -8
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/runtimes/nuclio/api_gateway.py +646 -177
- 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/nuclio/function.py +188 -68
- mlrun/runtimes/nuclio/serving.py +57 -60
- mlrun/runtimes/pod.py +191 -58
- mlrun/runtimes/remotesparkjob.py +11 -8
- mlrun/runtimes/sparkjob/spark3job.py +17 -18
- mlrun/runtimes/utils.py +40 -73
- mlrun/secrets.py +6 -2
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/remote.py +2 -3
- mlrun/serving/routers.py +89 -64
- mlrun/serving/server.py +54 -26
- mlrun/serving/states.py +187 -56
- mlrun/serving/utils.py +19 -11
- mlrun/serving/v2_serving.py +136 -63
- mlrun/track/tracker.py +2 -1
- mlrun/track/trackers/mlflow_tracker.py +5 -0
- mlrun/utils/async_http.py +26 -6
- mlrun/utils/db.py +18 -0
- mlrun/utils/helpers.py +375 -105
- mlrun/utils/http.py +2 -2
- mlrun/utils/logger.py +75 -9
- mlrun/utils/notifications/notification/__init__.py +14 -10
- mlrun/utils/notifications/notification/base.py +48 -0
- mlrun/utils/notifications/notification/console.py +2 -0
- mlrun/utils/notifications/notification/git.py +24 -1
- mlrun/utils/notifications/notification/ipython.py +2 -0
- mlrun/utils/notifications/notification/slack.py +96 -21
- mlrun/utils/notifications/notification/webhook.py +63 -2
- mlrun/utils/notifications/notification_pusher.py +146 -16
- mlrun/utils/regex.py +9 -0
- mlrun/utils/retryer.py +3 -2
- mlrun/utils/v3io_clients.py +2 -3
- mlrun/utils/version/version.json +2 -2
- mlrun-1.7.2.dist-info/METADATA +390 -0
- mlrun-1.7.2.dist-info/RECORD +351 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -271
- mlrun/kfpops.py +0 -868
- mlrun/model_monitoring/application.py +0 -310
- mlrun/model_monitoring/batch.py +0 -974
- mlrun/model_monitoring/controller_handler.py +0 -37
- mlrun/model_monitoring/prometheus.py +0 -216
- mlrun/model_monitoring/stores/__init__.py +0 -111
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
- mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
- 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 -382
- mlrun/platforms/other.py +0 -305
- mlrun-1.7.0rc5.dist-info/METADATA +0 -269
- mlrun-1.7.0rc5.dist-info/RECORD +0 -323
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
|
@@ -21,9 +21,34 @@ import plotly.graph_objects as go
|
|
|
21
21
|
from plotly.subplots import make_subplots
|
|
22
22
|
|
|
23
23
|
import mlrun.common.schemas.model_monitoring
|
|
24
|
+
from mlrun.artifacts import PlotlyArtifact
|
|
24
25
|
|
|
25
26
|
# A type for representing a drift result, a tuple of the status and the drift mean:
|
|
26
|
-
DriftResultType = tuple[
|
|
27
|
+
DriftResultType = tuple[
|
|
28
|
+
mlrun.common.schemas.model_monitoring.constants.ResultStatusApp, float
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _PlotlyTableArtifact(PlotlyArtifact):
|
|
33
|
+
"""A custom class for plotly table artifacts"""
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def _disable_table_dragging(figure_html: str) -> str:
|
|
37
|
+
"""
|
|
38
|
+
Disable the table columns dragging by adding the following
|
|
39
|
+
JavaScript code
|
|
40
|
+
"""
|
|
41
|
+
start, end = figure_html.rsplit(";", 1)
|
|
42
|
+
middle = (
|
|
43
|
+
';for (const element of document.getElementsByClassName("table")) '
|
|
44
|
+
'{element.style.pointerEvents = "none";}'
|
|
45
|
+
)
|
|
46
|
+
figure_html = start + middle + end
|
|
47
|
+
return figure_html
|
|
48
|
+
|
|
49
|
+
def get_body(self) -> str:
|
|
50
|
+
"""Get the adjusted HTML representation of the figure"""
|
|
51
|
+
return self._disable_table_dragging(super().get_body())
|
|
27
52
|
|
|
28
53
|
|
|
29
54
|
class FeaturesDriftTablePlot:
|
|
@@ -62,9 +87,9 @@ class FeaturesDriftTablePlot:
|
|
|
62
87
|
|
|
63
88
|
# Status configurations:
|
|
64
89
|
_STATUS_COLORS = {
|
|
65
|
-
mlrun.common.schemas.model_monitoring.
|
|
66
|
-
mlrun.common.schemas.model_monitoring.
|
|
67
|
-
mlrun.common.schemas.model_monitoring.
|
|
90
|
+
mlrun.common.schemas.model_monitoring.constants.ResultStatusApp.no_detection: "rgb(0,176,80)", # Green
|
|
91
|
+
mlrun.common.schemas.model_monitoring.constants.ResultStatusApp.potential_detection: "rgb(255,192,0)", # Orange
|
|
92
|
+
mlrun.common.schemas.model_monitoring.constants.ResultStatusApp.detected: "rgb(208,0,106)", # Magenta
|
|
68
93
|
}
|
|
69
94
|
|
|
70
95
|
# Font configurations:
|
|
@@ -97,7 +122,7 @@ class FeaturesDriftTablePlot:
|
|
|
97
122
|
inputs_statistics: dict,
|
|
98
123
|
metrics: dict[str, Union[dict, float]],
|
|
99
124
|
drift_results: dict[str, DriftResultType],
|
|
100
|
-
) ->
|
|
125
|
+
) -> _PlotlyTableArtifact:
|
|
101
126
|
"""
|
|
102
127
|
Produce the html code of the table plot with the given information and the stored configurations in the class.
|
|
103
128
|
|
|
@@ -106,9 +131,8 @@ class FeaturesDriftTablePlot:
|
|
|
106
131
|
:param metrics: The drift detection metrics calculated on the sample set and inputs.
|
|
107
132
|
:param drift_results: The drift results per feature according to the rules of the monitor.
|
|
108
133
|
|
|
109
|
-
:return: The
|
|
134
|
+
:return: The drift table as a plotly artifact.
|
|
110
135
|
"""
|
|
111
|
-
# Plot the drift table:
|
|
112
136
|
figure = self._plot(
|
|
113
137
|
features=list(inputs_statistics.keys()),
|
|
114
138
|
sample_set_statistics=sample_set_statistics,
|
|
@@ -116,19 +140,7 @@ class FeaturesDriftTablePlot:
|
|
|
116
140
|
metrics=metrics,
|
|
117
141
|
drift_results=drift_results,
|
|
118
142
|
)
|
|
119
|
-
|
|
120
|
-
# Get its HTML representation:
|
|
121
|
-
figure_html = figure.to_html()
|
|
122
|
-
|
|
123
|
-
# Turn off the table columns dragging by injecting the following JavaScript code:
|
|
124
|
-
start, end = figure_html.rsplit(";", 1)
|
|
125
|
-
middle = (
|
|
126
|
-
';for (const element of document.getElementsByClassName("table")) '
|
|
127
|
-
'{element.style.pointerEvents = "none";}'
|
|
128
|
-
)
|
|
129
|
-
figure_html = start + middle + end
|
|
130
|
-
|
|
131
|
-
return figure_html
|
|
143
|
+
return _PlotlyTableArtifact(figure=figure, key="drift_table_plot")
|
|
132
144
|
|
|
133
145
|
def _read_columns_names(self, statistics_dictionary: dict, drift_metrics: dict):
|
|
134
146
|
"""
|
|
@@ -366,10 +378,10 @@ class FeaturesDriftTablePlot:
|
|
|
366
378
|
bins = np.array(bins)
|
|
367
379
|
if bins[0] == -sys.float_info.max:
|
|
368
380
|
bins[0] = bins[1] - (bins[2] - bins[1])
|
|
369
|
-
hovertext[0] = f"(
|
|
381
|
+
hovertext[0] = f"(-inf, {bins[1]})"
|
|
370
382
|
if bins[-1] == sys.float_info.max:
|
|
371
383
|
bins[-1] = bins[-2] + (bins[-2] - bins[-3])
|
|
372
|
-
hovertext[-1] = f"({bins[-2]},
|
|
384
|
+
hovertext[-1] = f"({bins[-2]}, inf)"
|
|
373
385
|
# Center the bins (leave the first one):
|
|
374
386
|
bins = 0.5 * (bins[:-1] + bins[1:])
|
|
375
387
|
# Plot the histogram as a line with filled background below it:
|
|
@@ -15,19 +15,25 @@
|
|
|
15
15
|
import datetime
|
|
16
16
|
import typing
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import mlrun.common.schemas
|
|
21
|
-
from mlrun.common.schemas.model_monitoring import (
|
|
22
|
-
EventFieldType,
|
|
23
|
-
)
|
|
24
|
-
from mlrun.model_monitoring.model_endpoint import ModelEndpoint
|
|
25
|
-
from mlrun.utils import logger
|
|
18
|
+
import numpy as np
|
|
19
|
+
import pandas as pd
|
|
26
20
|
|
|
27
21
|
if typing.TYPE_CHECKING:
|
|
28
22
|
from mlrun.db.base import RunDBInterface
|
|
29
23
|
from mlrun.projects import MlrunProject
|
|
24
|
+
|
|
25
|
+
import mlrun
|
|
26
|
+
import mlrun.artifacts
|
|
27
|
+
import mlrun.common.model_monitoring.helpers
|
|
30
28
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
29
|
+
import mlrun.data_types.infer
|
|
30
|
+
import mlrun.model_monitoring
|
|
31
|
+
from mlrun.common.schemas.model_monitoring.model_endpoints import (
|
|
32
|
+
ModelEndpointMonitoringMetric,
|
|
33
|
+
_compose_full_name,
|
|
34
|
+
)
|
|
35
|
+
from mlrun.model_monitoring.model_endpoint import ModelEndpoint
|
|
36
|
+
from mlrun.utils import logger
|
|
31
37
|
|
|
32
38
|
|
|
33
39
|
class _BatchDict(typing.TypedDict):
|
|
@@ -36,34 +42,33 @@ class _BatchDict(typing.TypedDict):
|
|
|
36
42
|
days: int
|
|
37
43
|
|
|
38
44
|
|
|
39
|
-
class _MLRunNoRunsFoundError(Exception):
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
|
|
43
45
|
def get_stream_path(
|
|
44
|
-
project: str
|
|
46
|
+
project: str,
|
|
45
47
|
function_name: str = mm_constants.MonitoringFunctionNames.STREAM,
|
|
46
|
-
|
|
48
|
+
stream_uri: typing.Optional[str] = None,
|
|
49
|
+
) -> str:
|
|
47
50
|
"""
|
|
48
51
|
Get stream path from the project secret. If wasn't set, take it from the system configurations
|
|
49
52
|
|
|
50
53
|
:param project: Project name.
|
|
51
|
-
:param function_name:
|
|
54
|
+
:param function_name: Application name. Default is model_monitoring_stream.
|
|
55
|
+
:param stream_uri: Stream URI. If provided, it will be used instead of the one from the project secret.
|
|
52
56
|
|
|
53
57
|
:return: Monitoring stream path to the relevant application.
|
|
54
58
|
"""
|
|
55
59
|
|
|
56
|
-
stream_uri = mlrun.get_secret_or_env(
|
|
57
|
-
|
|
58
|
-
if function_name is mm_constants.MonitoringFunctionNames.STREAM
|
|
59
|
-
else ""
|
|
60
|
-
) or mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
61
|
-
project=project,
|
|
62
|
-
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.STREAM,
|
|
63
|
-
target="online",
|
|
64
|
-
function_name=function_name,
|
|
60
|
+
stream_uri = stream_uri or mlrun.get_secret_or_env(
|
|
61
|
+
mm_constants.ProjectSecretKeys.STREAM_PATH
|
|
65
62
|
)
|
|
66
63
|
|
|
64
|
+
if not stream_uri or stream_uri == "v3io":
|
|
65
|
+
stream_uri = mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
66
|
+
project=project,
|
|
67
|
+
kind=mm_constants.FileTargetKind.STREAM,
|
|
68
|
+
target="online",
|
|
69
|
+
function_name=function_name,
|
|
70
|
+
)
|
|
71
|
+
|
|
67
72
|
return mlrun.common.model_monitoring.helpers.parse_monitoring_stream_path(
|
|
68
73
|
stream_uri=stream_uri, project=project, function_name=function_name
|
|
69
74
|
)
|
|
@@ -71,7 +76,7 @@ def get_stream_path(
|
|
|
71
76
|
|
|
72
77
|
def get_monitoring_parquet_path(
|
|
73
78
|
project: "MlrunProject",
|
|
74
|
-
kind: str =
|
|
79
|
+
kind: str = mm_constants.FileTargetKind.PARQUET,
|
|
75
80
|
) -> str:
|
|
76
81
|
"""Get model monitoring parquet target for the current project and kind. The parquet target path is based on the
|
|
77
82
|
project artifact path. If project artifact path is not defined, the parquet target path will be based on MLRun
|
|
@@ -93,7 +98,7 @@ def get_monitoring_parquet_path(
|
|
|
93
98
|
return parquet_path
|
|
94
99
|
|
|
95
100
|
|
|
96
|
-
def get_connection_string(secret_provider: typing.Callable = None) -> str:
|
|
101
|
+
def get_connection_string(secret_provider: typing.Callable[[str], str] = None) -> str:
|
|
97
102
|
"""Get endpoint store connection string from the project secret. If wasn't set, take it from the system
|
|
98
103
|
configurations.
|
|
99
104
|
|
|
@@ -103,12 +108,24 @@ def get_connection_string(secret_provider: typing.Callable = None) -> str:
|
|
|
103
108
|
|
|
104
109
|
"""
|
|
105
110
|
|
|
106
|
-
return (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
return mlrun.get_secret_or_env(
|
|
112
|
+
key=mm_constants.ProjectSecretKeys.ENDPOINT_STORE_CONNECTION,
|
|
113
|
+
secret_provider=secret_provider,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def get_tsdb_connection_string(
|
|
118
|
+
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
|
|
119
|
+
) -> str:
|
|
120
|
+
"""Get TSDB connection string from the project secret. If wasn't set, take it from the system
|
|
121
|
+
configurations.
|
|
122
|
+
:param secret_provider: An optional secret provider to get the connection string secret.
|
|
123
|
+
:return: Valid TSDB connection string.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
return mlrun.get_secret_or_env(
|
|
127
|
+
key=mm_constants.ProjectSecretKeys.TSDB_CONNECTION,
|
|
128
|
+
secret_provider=secret_provider,
|
|
112
129
|
)
|
|
113
130
|
|
|
114
131
|
|
|
@@ -158,7 +175,7 @@ def _get_monitoring_time_window_from_controller_run(
|
|
|
158
175
|
def update_model_endpoint_last_request(
|
|
159
176
|
project: str,
|
|
160
177
|
model_endpoint: ModelEndpoint,
|
|
161
|
-
current_request: datetime,
|
|
178
|
+
current_request: datetime.datetime,
|
|
162
179
|
db: "RunDBInterface",
|
|
163
180
|
) -> None:
|
|
164
181
|
"""
|
|
@@ -169,7 +186,8 @@ def update_model_endpoint_last_request(
|
|
|
169
186
|
:param current_request: current request time
|
|
170
187
|
:param db: DB interface.
|
|
171
188
|
"""
|
|
172
|
-
|
|
189
|
+
is_model_server_endpoint = model_endpoint.spec.stream_path != ""
|
|
190
|
+
if is_model_server_endpoint:
|
|
173
191
|
current_request = current_request.isoformat()
|
|
174
192
|
logger.info(
|
|
175
193
|
"Update model endpoint last request time (EP with serving)",
|
|
@@ -181,14 +199,15 @@ def update_model_endpoint_last_request(
|
|
|
181
199
|
db.patch_model_endpoint(
|
|
182
200
|
project=project,
|
|
183
201
|
endpoint_id=model_endpoint.metadata.uid,
|
|
184
|
-
attributes={EventFieldType.LAST_REQUEST: current_request},
|
|
202
|
+
attributes={mm_constants.EventFieldType.LAST_REQUEST: current_request},
|
|
185
203
|
)
|
|
186
|
-
else:
|
|
204
|
+
else: # model endpoint without any serving function - close the window "manually"
|
|
187
205
|
try:
|
|
188
206
|
time_window = _get_monitoring_time_window_from_controller_run(project, db)
|
|
189
207
|
except mlrun.errors.MLRunNotFoundError:
|
|
190
|
-
logger.
|
|
191
|
-
"Not bumping model endpoint last request time - the monitoring controller isn't deployed yet"
|
|
208
|
+
logger.warn(
|
|
209
|
+
"Not bumping model endpoint last request time - the monitoring controller isn't deployed yet.\n"
|
|
210
|
+
"Call `project.enable_model_monitoring()` first."
|
|
192
211
|
)
|
|
193
212
|
return
|
|
194
213
|
|
|
@@ -210,5 +229,124 @@ def update_model_endpoint_last_request(
|
|
|
210
229
|
db.patch_model_endpoint(
|
|
211
230
|
project=project,
|
|
212
231
|
endpoint_id=model_endpoint.metadata.uid,
|
|
213
|
-
attributes={EventFieldType.LAST_REQUEST: bumped_last_request},
|
|
232
|
+
attributes={mm_constants.EventFieldType.LAST_REQUEST: bumped_last_request},
|
|
214
233
|
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def calculate_inputs_statistics(
|
|
237
|
+
sample_set_statistics: dict, inputs: pd.DataFrame
|
|
238
|
+
) -> mlrun.common.model_monitoring.helpers.FeatureStats:
|
|
239
|
+
"""
|
|
240
|
+
Calculate the inputs data statistics for drift monitoring purpose.
|
|
241
|
+
|
|
242
|
+
:param sample_set_statistics: The sample set (stored end point's dataset to reference) statistics. The bins of the
|
|
243
|
+
histograms of each feature will be used to recalculate the histograms of the inputs.
|
|
244
|
+
:param inputs: The inputs to calculate their statistics and later on - the drift with respect to the
|
|
245
|
+
sample set.
|
|
246
|
+
|
|
247
|
+
:returns: The calculated statistics of the inputs data.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
# Use `DFDataInfer` to calculate the statistics over the inputs:
|
|
251
|
+
inputs_statistics = mlrun.data_types.infer.DFDataInfer.get_stats(
|
|
252
|
+
df=inputs, options=mlrun.data_types.infer.InferOptions.Histogram
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Recalculate the histograms over the bins that are set in the sample-set of the end point:
|
|
256
|
+
for feature in list(inputs_statistics):
|
|
257
|
+
if feature in sample_set_statistics:
|
|
258
|
+
counts, bins = np.histogram(
|
|
259
|
+
inputs[feature].to_numpy(),
|
|
260
|
+
bins=sample_set_statistics[feature]["hist"][1],
|
|
261
|
+
)
|
|
262
|
+
inputs_statistics[feature]["hist"] = [
|
|
263
|
+
counts.tolist(),
|
|
264
|
+
bins.tolist(),
|
|
265
|
+
]
|
|
266
|
+
else:
|
|
267
|
+
# If the feature is not in the sample set and doesn't have a histogram, remove it from the statistics:
|
|
268
|
+
inputs_statistics.pop(feature)
|
|
269
|
+
|
|
270
|
+
return inputs_statistics
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def get_endpoint_record(
|
|
274
|
+
project: str,
|
|
275
|
+
endpoint_id: str,
|
|
276
|
+
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
|
|
277
|
+
) -> dict[str, typing.Any]:
|
|
278
|
+
model_endpoint_store = mlrun.model_monitoring.get_store_object(
|
|
279
|
+
project=project, secret_provider=secret_provider
|
|
280
|
+
)
|
|
281
|
+
return model_endpoint_store.get_model_endpoint(endpoint_id=endpoint_id)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def get_result_instance_fqn(
|
|
285
|
+
model_endpoint_id: str, app_name: str, result_name: str
|
|
286
|
+
) -> str:
|
|
287
|
+
return f"{model_endpoint_id}.{app_name}.result.{result_name}"
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def get_default_result_instance_fqn(model_endpoint_id: str) -> str:
|
|
291
|
+
return get_result_instance_fqn(
|
|
292
|
+
model_endpoint_id,
|
|
293
|
+
mm_constants.HistogramDataDriftApplicationConstants.NAME,
|
|
294
|
+
mm_constants.HistogramDataDriftApplicationConstants.GENERAL_RESULT_NAME,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def get_invocations_fqn(project: str) -> str:
|
|
299
|
+
return _compose_full_name(
|
|
300
|
+
project=project,
|
|
301
|
+
app=mm_constants.SpecialApps.MLRUN_INFRA,
|
|
302
|
+
name=mm_constants.PredictionsQueryConstants.INVOCATIONS,
|
|
303
|
+
type=mm_constants.ModelEndpointMonitoringMetricType.METRIC,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def get_invocations_metric(project: str) -> ModelEndpointMonitoringMetric:
|
|
308
|
+
"""
|
|
309
|
+
Return the invocations metric of any model endpoint in the given project.
|
|
310
|
+
|
|
311
|
+
:param project: The project name.
|
|
312
|
+
:returns: The model monitoring metric object.
|
|
313
|
+
"""
|
|
314
|
+
return ModelEndpointMonitoringMetric(
|
|
315
|
+
project=project,
|
|
316
|
+
app=mm_constants.SpecialApps.MLRUN_INFRA,
|
|
317
|
+
type=mm_constants.ModelEndpointMonitoringMetricType.METRIC,
|
|
318
|
+
name=mm_constants.PredictionsQueryConstants.INVOCATIONS,
|
|
319
|
+
full_name=get_invocations_fqn(project),
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def enrich_model_endpoint_with_model_uri(
|
|
324
|
+
model_endpoint: ModelEndpoint,
|
|
325
|
+
model_obj: mlrun.artifacts.ModelArtifact,
|
|
326
|
+
):
|
|
327
|
+
"""
|
|
328
|
+
Enrich the model endpoint object with the model uri from the model object. We will use a unique reference
|
|
329
|
+
to the model object that includes the project, db_key, iter, and tree.
|
|
330
|
+
In addition, we verify that the model object is of type `ModelArtifact`.
|
|
331
|
+
|
|
332
|
+
:param model_endpoint: An object representing the model endpoint that will be enriched with the model uri.
|
|
333
|
+
:param model_obj: An object representing the model artifact.
|
|
334
|
+
|
|
335
|
+
:raise: `MLRunInvalidArgumentError` if the model object is not of type `ModelArtifact`.
|
|
336
|
+
"""
|
|
337
|
+
mlrun.utils.helpers.verify_field_of_type(
|
|
338
|
+
field_name="model_endpoint.spec.model_uri",
|
|
339
|
+
field_value=model_obj,
|
|
340
|
+
expected_type=mlrun.artifacts.ModelArtifact,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
# Update model_uri with a unique reference to handle future changes
|
|
344
|
+
model_artifact_uri = mlrun.utils.helpers.generate_artifact_uri(
|
|
345
|
+
project=model_endpoint.metadata.project,
|
|
346
|
+
key=model_obj.db_key,
|
|
347
|
+
iter=model_obj.iter,
|
|
348
|
+
tree=model_obj.tree,
|
|
349
|
+
)
|
|
350
|
+
model_endpoint.spec.model_uri = mlrun.datastore.get_store_uri(
|
|
351
|
+
kind=mlrun.utils.helpers.StorePrefix.Model, uri=model_artifact_uri
|
|
352
|
+
)
|
|
@@ -17,6 +17,7 @@ from dataclasses import dataclass, field
|
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
19
|
import mlrun.model
|
|
20
|
+
from mlrun.common.model_monitoring.helpers import FeatureStats
|
|
20
21
|
from mlrun.common.schemas.model_monitoring.constants import (
|
|
21
22
|
EndpointType,
|
|
22
23
|
EventKeyMetrics,
|
|
@@ -42,8 +43,8 @@ class ModelEndpointSpec(mlrun.model.ModelObj):
|
|
|
42
43
|
|
|
43
44
|
@dataclass
|
|
44
45
|
class ModelEndpointStatus(mlrun.model.ModelObj):
|
|
45
|
-
feature_stats:
|
|
46
|
-
current_stats:
|
|
46
|
+
feature_stats: FeatureStats = field(default_factory=dict)
|
|
47
|
+
current_stats: FeatureStats = field(default_factory=dict)
|
|
47
48
|
first_request: str = ""
|
|
48
49
|
last_request: str = ""
|
|
49
50
|
error_count: int = 0
|