mlrun 1.8.0rc5__py3-none-any.whl → 1.8.0rc9__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 +1 -0
- mlrun/artifacts/__init__.py +1 -1
- mlrun/artifacts/base.py +21 -1
- mlrun/artifacts/document.py +62 -39
- mlrun/artifacts/manager.py +12 -5
- mlrun/common/constants.py +1 -0
- mlrun/common/model_monitoring/__init__.py +0 -2
- mlrun/common/model_monitoring/helpers.py +0 -28
- mlrun/common/schemas/__init__.py +2 -4
- mlrun/common/schemas/alert.py +77 -1
- mlrun/common/schemas/client_spec.py +0 -1
- mlrun/common/schemas/model_monitoring/__init__.py +0 -6
- mlrun/common/schemas/model_monitoring/constants.py +11 -9
- mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
- mlrun/common/schemas/notification.py +6 -0
- mlrun/common/schemas/project.py +3 -0
- mlrun/config.py +2 -3
- mlrun/datastore/datastore_profile.py +57 -17
- mlrun/datastore/sources.py +1 -2
- mlrun/datastore/store_resources.py +7 -2
- mlrun/datastore/vectorstore.py +99 -62
- mlrun/db/base.py +34 -20
- mlrun/db/httpdb.py +249 -163
- mlrun/db/nopdb.py +40 -17
- mlrun/execution.py +14 -7
- mlrun/feature_store/api.py +1 -0
- mlrun/model.py +3 -0
- mlrun/model_monitoring/__init__.py +3 -2
- mlrun/model_monitoring/api.py +64 -53
- mlrun/model_monitoring/applications/_application_steps.py +3 -1
- mlrun/model_monitoring/applications/base.py +115 -15
- mlrun/model_monitoring/applications/context.py +42 -24
- mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
- mlrun/model_monitoring/controller.py +43 -37
- mlrun/model_monitoring/db/__init__.py +0 -2
- mlrun/model_monitoring/db/tsdb/base.py +2 -1
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
- mlrun/model_monitoring/helpers.py +78 -66
- mlrun/model_monitoring/stream_processing.py +83 -270
- mlrun/model_monitoring/writer.py +1 -10
- mlrun/projects/pipelines.py +37 -1
- mlrun/projects/project.py +173 -70
- mlrun/run.py +40 -0
- mlrun/runtimes/nuclio/function.py +7 -6
- mlrun/runtimes/nuclio/serving.py +9 -4
- mlrun/serving/routers.py +158 -145
- mlrun/serving/server.py +6 -0
- mlrun/serving/states.py +21 -7
- mlrun/serving/v2_serving.py +94 -68
- mlrun/utils/helpers.py +23 -33
- mlrun/utils/notifications/notification/mail.py +17 -6
- mlrun/utils/notifications/notification_pusher.py +9 -5
- mlrun/utils/regex.py +8 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/METADATA +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/RECORD +61 -74
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
- mlrun/model_monitoring/db/stores/__init__.py +0 -136
- mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
- mlrun/model_monitoring/db/stores/base/store.py +0 -154
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
- mlrun/model_monitoring/model_endpoint.py +0 -120
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/WHEEL +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/top_level.txt +0 -0
|
@@ -24,6 +24,9 @@ if typing.TYPE_CHECKING:
|
|
|
24
24
|
from mlrun.db.base import RunDBInterface
|
|
25
25
|
from mlrun.projects import MlrunProject
|
|
26
26
|
|
|
27
|
+
from fnmatch import fnmatchcase
|
|
28
|
+
from typing import Optional
|
|
29
|
+
|
|
27
30
|
import mlrun
|
|
28
31
|
import mlrun.artifacts
|
|
29
32
|
import mlrun.common.model_monitoring.helpers
|
|
@@ -31,11 +34,11 @@ import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
|
31
34
|
import mlrun.data_types.infer
|
|
32
35
|
import mlrun.model_monitoring
|
|
33
36
|
import mlrun.utils.helpers
|
|
37
|
+
from mlrun.common.schemas import ModelEndpoint
|
|
34
38
|
from mlrun.common.schemas.model_monitoring.model_endpoints import (
|
|
35
39
|
ModelEndpointMonitoringMetric,
|
|
36
40
|
_compose_full_name,
|
|
37
41
|
)
|
|
38
|
-
from mlrun.model_monitoring.model_endpoint import ModelEndpoint
|
|
39
42
|
from mlrun.utils import logger
|
|
40
43
|
|
|
41
44
|
|
|
@@ -45,6 +48,70 @@ class _BatchDict(typing.TypedDict):
|
|
|
45
48
|
days: int
|
|
46
49
|
|
|
47
50
|
|
|
51
|
+
def _is_results_regex_match(
|
|
52
|
+
existing_result_name: Optional[str],
|
|
53
|
+
result_name_filters: Optional[list[str]],
|
|
54
|
+
) -> bool:
|
|
55
|
+
if existing_result_name.count(".") != 3 or any(
|
|
56
|
+
part == "" for part in existing_result_name.split(".")
|
|
57
|
+
):
|
|
58
|
+
logger.warning(
|
|
59
|
+
f"_is_results_regex_match: existing_result_name illegal, will be ignored."
|
|
60
|
+
f" existing_result_name: {existing_result_name}"
|
|
61
|
+
)
|
|
62
|
+
return False
|
|
63
|
+
existing_result_name = ".".join(existing_result_name.split(".")[i] for i in [1, 3])
|
|
64
|
+
for result_name_filter in result_name_filters:
|
|
65
|
+
if fnmatchcase(existing_result_name, result_name_filter):
|
|
66
|
+
return True
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def filter_results_by_regex(
|
|
71
|
+
existing_result_names: Optional[list[str]] = None,
|
|
72
|
+
result_name_filters: Optional[list[str]] = None,
|
|
73
|
+
) -> list[str]:
|
|
74
|
+
"""
|
|
75
|
+
Filter a list of existing result names by a list of filters.
|
|
76
|
+
|
|
77
|
+
This function returns only the results that match the filters provided. If no filters are given,
|
|
78
|
+
it returns all results. Invalid inputs are ignored.
|
|
79
|
+
|
|
80
|
+
:param existing_result_names: List of existing results' fully qualified names (FQNs)
|
|
81
|
+
in the format: endpoint_id.app_name.type.name.
|
|
82
|
+
Example: mep1.app1.result.metric1
|
|
83
|
+
:param result_name_filters: List of filters in the format: app.result_name.
|
|
84
|
+
Wildcards can be used, such as app.result* or *.result
|
|
85
|
+
|
|
86
|
+
:return: List of FQNs of the matching results
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
if not result_name_filters:
|
|
90
|
+
return existing_result_names
|
|
91
|
+
|
|
92
|
+
if not existing_result_names:
|
|
93
|
+
return []
|
|
94
|
+
|
|
95
|
+
# filters validations
|
|
96
|
+
validated_filters = []
|
|
97
|
+
for result_name_filter in result_name_filters:
|
|
98
|
+
if result_name_filter.count(".") != 1:
|
|
99
|
+
logger.warning(
|
|
100
|
+
f"filter_results_by_regex: result_name_filter illegal, will be ignored."
|
|
101
|
+
f"Filter: {result_name_filter}"
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
validated_filters.append(result_name_filter)
|
|
105
|
+
filtered_metrics_names = []
|
|
106
|
+
for existing_result_name in existing_result_names:
|
|
107
|
+
if _is_results_regex_match(
|
|
108
|
+
existing_result_name=existing_result_name,
|
|
109
|
+
result_name_filters=validated_filters,
|
|
110
|
+
):
|
|
111
|
+
filtered_metrics_names.append(existing_result_name)
|
|
112
|
+
return filtered_metrics_names
|
|
113
|
+
|
|
114
|
+
|
|
48
115
|
def get_stream_path(
|
|
49
116
|
project: str,
|
|
50
117
|
function_name: str = mm_constants.MonitoringFunctionNames.STREAM,
|
|
@@ -162,24 +229,6 @@ def get_monitoring_drift_measures_data(project: str, endpoint_id: str) -> "DataI
|
|
|
162
229
|
)
|
|
163
230
|
|
|
164
231
|
|
|
165
|
-
def get_connection_string(
|
|
166
|
-
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
|
|
167
|
-
) -> str:
|
|
168
|
-
"""Get endpoint store connection string from the project secret. If wasn't set, take it from the system
|
|
169
|
-
configurations.
|
|
170
|
-
|
|
171
|
-
:param secret_provider: An optional secret provider to get the connection string secret.
|
|
172
|
-
|
|
173
|
-
:return: Valid SQL connection string.
|
|
174
|
-
|
|
175
|
-
"""
|
|
176
|
-
|
|
177
|
-
return mlrun.get_secret_or_env(
|
|
178
|
-
key=mm_constants.ProjectSecretKeys.ENDPOINT_STORE_CONNECTION,
|
|
179
|
-
secret_provider=secret_provider,
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
|
|
183
232
|
def get_tsdb_connection_string(
|
|
184
233
|
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
|
|
185
234
|
) -> str:
|
|
@@ -252,19 +301,23 @@ def update_model_endpoint_last_request(
|
|
|
252
301
|
:param current_request: current request time
|
|
253
302
|
:param db: DB interface.
|
|
254
303
|
"""
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
304
|
+
is_batch_endpoint = (
|
|
305
|
+
model_endpoint.metadata.endpoint_type == mm_constants.EndpointType.BATCH_EP
|
|
306
|
+
)
|
|
307
|
+
if not is_batch_endpoint:
|
|
258
308
|
logger.info(
|
|
259
309
|
"Update model endpoint last request time (EP with serving)",
|
|
260
310
|
project=project,
|
|
261
311
|
endpoint_id=model_endpoint.metadata.uid,
|
|
312
|
+
name=model_endpoint.metadata.name,
|
|
313
|
+
function_name=model_endpoint.spec.function_name,
|
|
262
314
|
last_request=model_endpoint.status.last_request,
|
|
263
315
|
current_request=current_request,
|
|
264
316
|
)
|
|
265
317
|
db.patch_model_endpoint(
|
|
266
318
|
project=project,
|
|
267
319
|
endpoint_id=model_endpoint.metadata.uid,
|
|
320
|
+
name=model_endpoint.metadata.name,
|
|
268
321
|
attributes={mm_constants.EventFieldType.LAST_REQUEST: current_request},
|
|
269
322
|
)
|
|
270
323
|
else: # model endpoint without any serving function - close the window "manually"
|
|
@@ -283,7 +336,7 @@ def update_model_endpoint_last_request(
|
|
|
283
336
|
+ datetime.timedelta(
|
|
284
337
|
seconds=mlrun.mlconf.model_endpoint_monitoring.parquet_batching_timeout_secs
|
|
285
338
|
)
|
|
286
|
-
)
|
|
339
|
+
)
|
|
287
340
|
logger.info(
|
|
288
341
|
"Bumping model endpoint last request time (EP without serving)",
|
|
289
342
|
project=project,
|
|
@@ -295,6 +348,8 @@ def update_model_endpoint_last_request(
|
|
|
295
348
|
db.patch_model_endpoint(
|
|
296
349
|
project=project,
|
|
297
350
|
endpoint_id=model_endpoint.metadata.uid,
|
|
351
|
+
name=model_endpoint.metadata.name,
|
|
352
|
+
function_name=model_endpoint.spec.function_name,
|
|
298
353
|
attributes={mm_constants.EventFieldType.LAST_REQUEST: bumped_last_request},
|
|
299
354
|
)
|
|
300
355
|
|
|
@@ -336,17 +391,6 @@ def calculate_inputs_statistics(
|
|
|
336
391
|
return inputs_statistics
|
|
337
392
|
|
|
338
393
|
|
|
339
|
-
def get_endpoint_record(
|
|
340
|
-
project: str,
|
|
341
|
-
endpoint_id: str,
|
|
342
|
-
secret_provider: typing.Optional[typing.Callable[[str], str]] = None,
|
|
343
|
-
) -> dict[str, typing.Any]:
|
|
344
|
-
model_endpoint_store = mlrun.model_monitoring.get_store_object(
|
|
345
|
-
project=project, secret_provider=secret_provider
|
|
346
|
-
)
|
|
347
|
-
return model_endpoint_store.get_model_endpoint(endpoint_id=endpoint_id)
|
|
348
|
-
|
|
349
|
-
|
|
350
394
|
def get_result_instance_fqn(
|
|
351
395
|
model_endpoint_id: str, app_name: str, result_name: str
|
|
352
396
|
) -> str:
|
|
@@ -386,38 +430,6 @@ def get_invocations_metric(project: str) -> ModelEndpointMonitoringMetric:
|
|
|
386
430
|
)
|
|
387
431
|
|
|
388
432
|
|
|
389
|
-
def enrich_model_endpoint_with_model_uri(
|
|
390
|
-
model_endpoint: ModelEndpoint,
|
|
391
|
-
model_obj: mlrun.artifacts.ModelArtifact,
|
|
392
|
-
):
|
|
393
|
-
"""
|
|
394
|
-
Enrich the model endpoint object with the model uri from the model object. We will use a unique reference
|
|
395
|
-
to the model object that includes the project, db_key, iter, and tree.
|
|
396
|
-
In addition, we verify that the model object is of type `ModelArtifact`.
|
|
397
|
-
|
|
398
|
-
:param model_endpoint: An object representing the model endpoint that will be enriched with the model uri.
|
|
399
|
-
:param model_obj: An object representing the model artifact.
|
|
400
|
-
|
|
401
|
-
:raise: `MLRunInvalidArgumentError` if the model object is not of type `ModelArtifact`.
|
|
402
|
-
"""
|
|
403
|
-
mlrun.utils.helpers.verify_field_of_type(
|
|
404
|
-
field_name="model_endpoint.spec.model_uri",
|
|
405
|
-
field_value=model_obj,
|
|
406
|
-
expected_type=mlrun.artifacts.ModelArtifact,
|
|
407
|
-
)
|
|
408
|
-
|
|
409
|
-
# Update model_uri with a unique reference to handle future changes
|
|
410
|
-
model_artifact_uri = mlrun.utils.helpers.generate_artifact_uri(
|
|
411
|
-
project=model_endpoint.metadata.project,
|
|
412
|
-
key=model_obj.db_key,
|
|
413
|
-
iter=model_obj.iter,
|
|
414
|
-
tree=model_obj.tree,
|
|
415
|
-
)
|
|
416
|
-
model_endpoint.spec.model_uri = mlrun.datastore.get_store_uri(
|
|
417
|
-
kind=mlrun.utils.helpers.StorePrefix.Model, uri=model_artifact_uri
|
|
418
|
-
)
|
|
419
|
-
|
|
420
|
-
|
|
421
433
|
def _get_monitoring_schedules_folder_path(project: str) -> str:
|
|
422
434
|
return typing.cast(
|
|
423
435
|
str,
|