mlrun 1.7.0rc15__py3-none-any.whl → 1.7.0rc16__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 +10 -1
- mlrun/__main__.py +18 -4
- mlrun/alerts/__init__.py +15 -0
- mlrun/alerts/alert.py +141 -0
- mlrun/artifacts/__init__.py +7 -1
- mlrun/artifacts/base.py +28 -3
- mlrun/artifacts/dataset.py +8 -0
- mlrun/artifacts/manager.py +18 -0
- mlrun/artifacts/model.py +7 -0
- mlrun/artifacts/plots.py +13 -0
- mlrun/common/schemas/__init__.py +4 -2
- mlrun/common/schemas/alert.py +46 -4
- mlrun/common/schemas/api_gateway.py +4 -0
- mlrun/common/schemas/artifact.py +15 -0
- mlrun/common/schemas/auth.py +2 -0
- mlrun/common/schemas/model_monitoring/__init__.py +4 -1
- mlrun/common/schemas/model_monitoring/constants.py +16 -1
- mlrun/common/schemas/model_monitoring/model_endpoints.py +60 -1
- mlrun/common/schemas/project.py +2 -0
- mlrun/config.py +4 -1
- mlrun/datastore/datastore_profile.py +10 -7
- mlrun/db/base.py +23 -3
- mlrun/db/httpdb.py +97 -43
- mlrun/db/nopdb.py +20 -2
- mlrun/errors.py +5 -0
- mlrun/launcher/base.py +3 -2
- mlrun/lists.py +2 -0
- mlrun/model.py +7 -2
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/applications/_application_steps.py +1 -2
- mlrun/model_monitoring/applications/context.py +1 -1
- mlrun/model_monitoring/applications/histogram_data_drift.py +64 -38
- mlrun/model_monitoring/db/__init__.py +2 -0
- mlrun/model_monitoring/db/stores/base/store.py +9 -36
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +63 -110
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +56 -202
- mlrun/model_monitoring/db/tsdb/__init__.py +71 -0
- mlrun/model_monitoring/db/tsdb/base.py +135 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +404 -0
- mlrun/model_monitoring/db/v3io_tsdb_reader.py +134 -0
- mlrun/model_monitoring/stream_processing.py +46 -210
- mlrun/model_monitoring/writer.py +49 -99
- mlrun/platforms/__init__.py +10 -9
- mlrun/platforms/iguazio.py +19 -200
- mlrun/projects/operations.py +11 -7
- mlrun/projects/pipelines.py +13 -76
- mlrun/projects/project.py +55 -14
- mlrun/render.py +9 -3
- mlrun/run.py +5 -38
- mlrun/runtimes/base.py +3 -3
- mlrun/runtimes/kubejob.py +2 -1
- mlrun/runtimes/nuclio/api_gateway.py +75 -9
- mlrun/runtimes/nuclio/function.py +8 -34
- mlrun/runtimes/pod.py +16 -36
- mlrun/runtimes/remotesparkjob.py +1 -1
- mlrun/runtimes/sparkjob/spark3job.py +1 -1
- mlrun/runtimes/utils.py +0 -38
- mlrun/utils/helpers.py +45 -31
- mlrun/utils/notifications/notification/base.py +1 -1
- mlrun/utils/notifications/notification/slack.py +9 -4
- mlrun/utils/notifications/notification/webhook.py +1 -1
- mlrun/utils/notifications/notification_pusher.py +15 -14
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/METADATA +3 -2
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/RECORD +71 -65
- mlrun/kfpops.py +0 -860
- mlrun/platforms/other.py +0 -305
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/WHEEL +0 -0
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc16.dist-info}/top_level.txt +0 -0
mlrun/__init__.py
CHANGED
|
@@ -22,11 +22,16 @@ __all__ = [
|
|
|
22
22
|
"handler",
|
|
23
23
|
"ArtifactType",
|
|
24
24
|
"get_secret_or_env",
|
|
25
|
+
"mount_v3io",
|
|
26
|
+
"v3io_cred",
|
|
27
|
+
"auto_mount",
|
|
28
|
+
"VolumeMount",
|
|
25
29
|
]
|
|
26
30
|
|
|
27
31
|
from os import environ, path
|
|
28
32
|
|
|
29
33
|
import dotenv
|
|
34
|
+
import mlrun_pipelines
|
|
30
35
|
|
|
31
36
|
from .config import config as mlconf
|
|
32
37
|
from .datastore import DataItem, store_manager
|
|
@@ -35,7 +40,6 @@ from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
|
|
|
35
40
|
from .execution import MLClientCtx
|
|
36
41
|
from .model import RunObject, RunTemplate, new_task
|
|
37
42
|
from .package import ArtifactType, DefaultPackager, Packager, handler
|
|
38
|
-
from .platforms import VolumeMount, auto_mount, mount_v3io, v3io_cred
|
|
39
43
|
from .projects import (
|
|
40
44
|
ProjectMetadata,
|
|
41
45
|
build_function,
|
|
@@ -65,6 +69,11 @@ from .utils.version import Version
|
|
|
65
69
|
|
|
66
70
|
__version__ = Version().get()["version"]
|
|
67
71
|
|
|
72
|
+
VolumeMount = mlrun_pipelines.common.mounts.VolumeMount
|
|
73
|
+
mount_v3io = mlrun_pipelines.mounts.mount_v3io
|
|
74
|
+
v3io_cred = mlrun_pipelines.mounts.v3io_cred
|
|
75
|
+
auto_mount = mlrun_pipelines.mounts.auto_mount
|
|
76
|
+
|
|
68
77
|
|
|
69
78
|
def get_version():
|
|
70
79
|
"""get current mlrun version"""
|
mlrun/__main__.py
CHANGED
|
@@ -27,6 +27,7 @@ import click
|
|
|
27
27
|
import dotenv
|
|
28
28
|
import pandas as pd
|
|
29
29
|
import yaml
|
|
30
|
+
from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
|
|
30
31
|
from tabulate import tabulate
|
|
31
32
|
|
|
32
33
|
import mlrun
|
|
@@ -37,7 +38,6 @@ from .config import config as mlconf
|
|
|
37
38
|
from .db import get_run_db
|
|
38
39
|
from .errors import err_to_str
|
|
39
40
|
from .model import RunTemplate
|
|
40
|
-
from .platforms import auto_mount as auto_mount_modifier
|
|
41
41
|
from .projects import load_project
|
|
42
42
|
from .run import (
|
|
43
43
|
get_object,
|
|
@@ -466,6 +466,17 @@ def run(
|
|
|
466
466
|
is_flag=True,
|
|
467
467
|
help="ensure the project exists, if not, create project",
|
|
468
468
|
)
|
|
469
|
+
@click.option(
|
|
470
|
+
"--state-file-path", default="/tmp/state", help="path to file with state data"
|
|
471
|
+
)
|
|
472
|
+
@click.option(
|
|
473
|
+
"--image-file-path", default="/tmp/image", help="path to file with image data"
|
|
474
|
+
)
|
|
475
|
+
@click.option(
|
|
476
|
+
"--full-image-file-path",
|
|
477
|
+
default="/tmp/fullimage",
|
|
478
|
+
help="path to file with full image data",
|
|
479
|
+
)
|
|
469
480
|
def build(
|
|
470
481
|
func_url,
|
|
471
482
|
name,
|
|
@@ -485,6 +496,9 @@ def build(
|
|
|
485
496
|
skip,
|
|
486
497
|
env_file,
|
|
487
498
|
ensure_project,
|
|
499
|
+
state_file_path,
|
|
500
|
+
image_file_path,
|
|
501
|
+
full_image_file_path,
|
|
488
502
|
):
|
|
489
503
|
"""Build a container image from code and requirements."""
|
|
490
504
|
|
|
@@ -574,12 +588,12 @@ def build(
|
|
|
574
588
|
state = func.status.state
|
|
575
589
|
image = func.spec.image
|
|
576
590
|
if kfp:
|
|
577
|
-
with open(
|
|
591
|
+
with open(state_file_path, "w") as fp:
|
|
578
592
|
fp.write(state or "none")
|
|
579
593
|
full_image = func.full_image_path(image) or ""
|
|
580
|
-
with open(
|
|
594
|
+
with open(image_file_path, "w") as fp:
|
|
581
595
|
fp.write(image)
|
|
582
|
-
with open(
|
|
596
|
+
with open(full_image_file_path, "w") as fp:
|
|
583
597
|
fp.write(full_image)
|
|
584
598
|
print("Full image path = ", full_image)
|
|
585
599
|
|
mlrun/alerts/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Copyright 2024 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from .alert import AlertConfig
|
mlrun/alerts/alert.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Copyright 2024 Iguazio
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import Union
|
|
16
|
+
|
|
17
|
+
import mlrun
|
|
18
|
+
import mlrun.common.schemas.alert as alert_constants
|
|
19
|
+
from mlrun.common.schemas.notification import Notification
|
|
20
|
+
from mlrun.model import ModelObj
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AlertConfig(ModelObj):
|
|
24
|
+
_dict_fields = [
|
|
25
|
+
"project",
|
|
26
|
+
"name",
|
|
27
|
+
"description",
|
|
28
|
+
"summary",
|
|
29
|
+
"severity",
|
|
30
|
+
"criteria",
|
|
31
|
+
"reset_policy",
|
|
32
|
+
"state",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
project: str = None,
|
|
38
|
+
name: str = None,
|
|
39
|
+
template: Union[alert_constants.AlertTemplate, str] = None,
|
|
40
|
+
description: str = None,
|
|
41
|
+
summary: str = None,
|
|
42
|
+
severity: alert_constants.AlertSeverity = None,
|
|
43
|
+
trigger: alert_constants.AlertTrigger = None,
|
|
44
|
+
criteria: alert_constants.AlertCriteria = None,
|
|
45
|
+
reset_policy: alert_constants.ResetPolicy = None,
|
|
46
|
+
notifications: list[Notification] = None,
|
|
47
|
+
entities: alert_constants.EventEntities = None,
|
|
48
|
+
id: int = None,
|
|
49
|
+
state: alert_constants.AlertActiveState = None,
|
|
50
|
+
created: str = None,
|
|
51
|
+
count: int = None,
|
|
52
|
+
):
|
|
53
|
+
self.project = project
|
|
54
|
+
self.name = name
|
|
55
|
+
self.description = description
|
|
56
|
+
self.summary = summary
|
|
57
|
+
self.severity = severity
|
|
58
|
+
self.trigger = trigger
|
|
59
|
+
self.criteria = criteria
|
|
60
|
+
self.reset_policy = reset_policy
|
|
61
|
+
self.notifications = notifications or []
|
|
62
|
+
self.entities = entities
|
|
63
|
+
self.id = id
|
|
64
|
+
self.state = state
|
|
65
|
+
self.created = created
|
|
66
|
+
self.count = count
|
|
67
|
+
|
|
68
|
+
if template:
|
|
69
|
+
self._apply_template(template)
|
|
70
|
+
|
|
71
|
+
def validate_required_fields(self):
|
|
72
|
+
if not self.project or not self.name:
|
|
73
|
+
raise mlrun.errors.MLRunBadRequestError("Project and name must be provided")
|
|
74
|
+
|
|
75
|
+
def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
|
|
76
|
+
data = super().to_dict(self._dict_fields)
|
|
77
|
+
|
|
78
|
+
data["entities"] = (
|
|
79
|
+
self.entities.dict()
|
|
80
|
+
if not isinstance(self.entities, dict)
|
|
81
|
+
else self.entities
|
|
82
|
+
)
|
|
83
|
+
data["notifications"] = [
|
|
84
|
+
notification.dict() if not isinstance(notification, dict) else notification
|
|
85
|
+
for notification in self.notifications
|
|
86
|
+
]
|
|
87
|
+
data["trigger"] = (
|
|
88
|
+
self.trigger.dict() if not isinstance(self.trigger, dict) else self.trigger
|
|
89
|
+
)
|
|
90
|
+
return data
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
|
|
94
|
+
new_obj = super().from_dict(struct, fields=fields)
|
|
95
|
+
|
|
96
|
+
entity_data = struct.get("entities")
|
|
97
|
+
if entity_data:
|
|
98
|
+
entity_obj = alert_constants.EventEntities.parse_obj(entity_data)
|
|
99
|
+
new_obj.entities = entity_obj
|
|
100
|
+
|
|
101
|
+
notifications_data = struct.get("notifications")
|
|
102
|
+
if notifications_data:
|
|
103
|
+
notifications_objs = [
|
|
104
|
+
Notification.parse_obj(notification_data)
|
|
105
|
+
for notification_data in notifications_data
|
|
106
|
+
]
|
|
107
|
+
new_obj.notifications = notifications_objs
|
|
108
|
+
|
|
109
|
+
trigger_data = struct.get("trigger")
|
|
110
|
+
if trigger_data:
|
|
111
|
+
trigger_obj = alert_constants.AlertTrigger.parse_obj(trigger_data)
|
|
112
|
+
new_obj.trigger = trigger_obj
|
|
113
|
+
|
|
114
|
+
return new_obj
|
|
115
|
+
|
|
116
|
+
def with_notifications(self, notifications: list[Notification]):
|
|
117
|
+
if not isinstance(notifications, list) or not all(
|
|
118
|
+
isinstance(item, Notification) for item in notifications
|
|
119
|
+
):
|
|
120
|
+
raise ValueError("Notifications parameter must be a list of notifications")
|
|
121
|
+
for notification in notifications:
|
|
122
|
+
self.notifications.append(notification)
|
|
123
|
+
return self
|
|
124
|
+
|
|
125
|
+
def with_entities(self, entities: alert_constants.EventEntities):
|
|
126
|
+
if not isinstance(entities, alert_constants.EventEntities):
|
|
127
|
+
raise ValueError("Entities parameter must be of type: EventEntities")
|
|
128
|
+
self.entities = entities
|
|
129
|
+
return self
|
|
130
|
+
|
|
131
|
+
def _apply_template(self, template):
|
|
132
|
+
if isinstance(template, str):
|
|
133
|
+
db = mlrun.get_run_db()
|
|
134
|
+
template = db.get_alert_template(template)
|
|
135
|
+
|
|
136
|
+
# Extract parameters from the template and apply them to the AlertConfig object
|
|
137
|
+
self.description = template.description
|
|
138
|
+
self.severity = template.severity
|
|
139
|
+
self.criteria = template.criteria
|
|
140
|
+
self.trigger = template.trigger
|
|
141
|
+
self.reset_policy = template.reset_policy
|
mlrun/artifacts/__init__.py
CHANGED
|
@@ -17,7 +17,13 @@
|
|
|
17
17
|
# Don't remove this, used by sphinx documentation
|
|
18
18
|
__all__ = ["get_model", "update_model"]
|
|
19
19
|
|
|
20
|
-
from .base import
|
|
20
|
+
from .base import (
|
|
21
|
+
Artifact,
|
|
22
|
+
ArtifactMetadata,
|
|
23
|
+
ArtifactSpec,
|
|
24
|
+
DirArtifact,
|
|
25
|
+
get_artifact_meta,
|
|
26
|
+
)
|
|
21
27
|
from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
|
|
22
28
|
from .manager import (
|
|
23
29
|
ArtifactManager,
|
mlrun/artifacts/base.py
CHANGED
|
@@ -191,12 +191,30 @@ class Artifact(ModelObj):
|
|
|
191
191
|
format=None,
|
|
192
192
|
size=None,
|
|
193
193
|
target_path=None,
|
|
194
|
-
# All params up until here are legacy params for compatibility with legacy artifacts.
|
|
195
194
|
project=None,
|
|
195
|
+
src_path: str = None,
|
|
196
|
+
# All params up until here are legacy params for compatibility with legacy artifacts.
|
|
197
|
+
# TODO: remove them in 1.9.0.
|
|
196
198
|
metadata: ArtifactMetadata = None,
|
|
197
199
|
spec: ArtifactSpec = None,
|
|
198
|
-
src_path: str = None,
|
|
199
200
|
):
|
|
201
|
+
if (
|
|
202
|
+
key
|
|
203
|
+
or body
|
|
204
|
+
or viewer
|
|
205
|
+
or is_inline
|
|
206
|
+
or format
|
|
207
|
+
or size
|
|
208
|
+
or target_path
|
|
209
|
+
or project
|
|
210
|
+
or src_path
|
|
211
|
+
):
|
|
212
|
+
warnings.warn(
|
|
213
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
214
|
+
"Use the metadata and spec parameters instead.",
|
|
215
|
+
DeprecationWarning,
|
|
216
|
+
)
|
|
217
|
+
|
|
200
218
|
self._metadata = None
|
|
201
219
|
self.metadata = metadata
|
|
202
220
|
self._spec = None
|
|
@@ -698,11 +716,18 @@ class LinkArtifact(Artifact):
|
|
|
698
716
|
link_iteration=None,
|
|
699
717
|
link_key=None,
|
|
700
718
|
link_tree=None,
|
|
701
|
-
# All params up until here are legacy params for compatibility with legacy artifacts.
|
|
702
719
|
project=None,
|
|
720
|
+
# All params up until here are legacy params for compatibility with legacy artifacts.
|
|
721
|
+
# TODO: remove them in 1.9.0.
|
|
703
722
|
metadata: ArtifactMetadata = None,
|
|
704
723
|
spec: LinkArtifactSpec = None,
|
|
705
724
|
):
|
|
725
|
+
if key or target_path or link_iteration or link_key or link_tree or project:
|
|
726
|
+
warnings.warn(
|
|
727
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
728
|
+
"Use the metadata and spec parameters instead.",
|
|
729
|
+
DeprecationWarning,
|
|
730
|
+
)
|
|
706
731
|
super().__init__(
|
|
707
732
|
key, target_path=target_path, project=project, metadata=metadata, spec=spec
|
|
708
733
|
)
|
mlrun/artifacts/dataset.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import os
|
|
15
15
|
import pathlib
|
|
16
|
+
import warnings
|
|
16
17
|
from io import StringIO
|
|
17
18
|
from typing import Optional
|
|
18
19
|
|
|
@@ -160,6 +161,13 @@ class DatasetArtifact(Artifact):
|
|
|
160
161
|
label_column: str = None,
|
|
161
162
|
**kwargs,
|
|
162
163
|
):
|
|
164
|
+
if key or format or target_path:
|
|
165
|
+
warnings.warn(
|
|
166
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
167
|
+
"Use the metadata and spec parameters instead.",
|
|
168
|
+
DeprecationWarning,
|
|
169
|
+
)
|
|
170
|
+
|
|
163
171
|
format = (format or "").lower()
|
|
164
172
|
super().__init__(key, None, format=format, target_path=target_path)
|
|
165
173
|
if format and format not in self.SUPPORTED_FORMATS:
|
mlrun/artifacts/manager.py
CHANGED
|
@@ -16,6 +16,7 @@ import typing
|
|
|
16
16
|
from os.path import exists, isdir
|
|
17
17
|
from urllib.parse import urlparse
|
|
18
18
|
|
|
19
|
+
import mlrun.common.schemas.artifact
|
|
19
20
|
import mlrun.config
|
|
20
21
|
from mlrun.utils.helpers import (
|
|
21
22
|
get_local_file_schema,
|
|
@@ -343,6 +344,23 @@ class ArtifactManager:
|
|
|
343
344
|
project=project,
|
|
344
345
|
)
|
|
345
346
|
|
|
347
|
+
def delete_artifact(
|
|
348
|
+
self,
|
|
349
|
+
item: Artifact,
|
|
350
|
+
deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
|
|
351
|
+
mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
|
|
352
|
+
),
|
|
353
|
+
secrets: dict = None,
|
|
354
|
+
):
|
|
355
|
+
self.artifact_db.del_artifact(
|
|
356
|
+
key=item.db_key,
|
|
357
|
+
project=item.project,
|
|
358
|
+
tag=item.tag,
|
|
359
|
+
tree=item.tree,
|
|
360
|
+
deletion_strategy=deletion_strategy,
|
|
361
|
+
secrets=secrets,
|
|
362
|
+
)
|
|
363
|
+
|
|
346
364
|
|
|
347
365
|
def extend_artifact_path(artifact_path: str, default_artifact_path: str):
|
|
348
366
|
artifact_path = str(artifact_path or "")
|
mlrun/artifacts/model.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import tempfile
|
|
16
|
+
import warnings
|
|
16
17
|
from os import path
|
|
17
18
|
from typing import Any, Optional
|
|
18
19
|
|
|
@@ -148,6 +149,12 @@ class ModelArtifact(Artifact):
|
|
|
148
149
|
model_dir=None,
|
|
149
150
|
**kwargs,
|
|
150
151
|
):
|
|
152
|
+
if key or body or format or target_path:
|
|
153
|
+
warnings.warn(
|
|
154
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
155
|
+
"Use the metadata and spec parameters instead.",
|
|
156
|
+
DeprecationWarning,
|
|
157
|
+
)
|
|
151
158
|
super().__init__(key, body, format=format, target_path=target_path, **kwargs)
|
|
152
159
|
model_file = str(model_file or "")
|
|
153
160
|
if model_file and "/" in model_file:
|
mlrun/artifacts/plots.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import base64
|
|
15
15
|
import typing
|
|
16
|
+
import warnings
|
|
16
17
|
from io import BytesIO
|
|
17
18
|
|
|
18
19
|
import mlrun
|
|
@@ -34,6 +35,12 @@ class PlotArtifact(Artifact):
|
|
|
34
35
|
def __init__(
|
|
35
36
|
self, key=None, body=None, is_inline=False, target_path=None, title=None
|
|
36
37
|
):
|
|
38
|
+
if key or body or is_inline or target_path:
|
|
39
|
+
warnings.warn(
|
|
40
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
41
|
+
"Use the metadata and spec parameters instead.",
|
|
42
|
+
DeprecationWarning,
|
|
43
|
+
)
|
|
37
44
|
super().__init__(key, body, format="html", target_path=target_path)
|
|
38
45
|
self.metadata.description = title
|
|
39
46
|
|
|
@@ -87,6 +94,12 @@ class PlotlyArtifact(Artifact):
|
|
|
87
94
|
:param key: Key for the artifact to be stored in the database.
|
|
88
95
|
:param target_path: Path to save the artifact.
|
|
89
96
|
"""
|
|
97
|
+
if key or target_path:
|
|
98
|
+
warnings.warn(
|
|
99
|
+
"Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
|
|
100
|
+
"Use the metadata and spec parameters instead.",
|
|
101
|
+
DeprecationWarning,
|
|
102
|
+
)
|
|
90
103
|
# Validate the plotly package:
|
|
91
104
|
try:
|
|
92
105
|
from plotly.graph_objs import Figure
|
mlrun/common/schemas/__init__.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
16
|
|
|
17
|
-
from .alert import AlertActiveState, AlertConfig, Event
|
|
17
|
+
from .alert import AlertActiveState, AlertConfig, AlertTemplate, Event
|
|
18
18
|
from .api_gateway import (
|
|
19
19
|
APIGateway,
|
|
20
20
|
APIGatewayAuthenticationMode,
|
|
@@ -142,8 +142,10 @@ from .model_monitoring import (
|
|
|
142
142
|
ModelMonitoringMode,
|
|
143
143
|
ModelMonitoringStoreKinds,
|
|
144
144
|
MonitoringFunctionNames,
|
|
145
|
+
MonitoringTSDBTables,
|
|
145
146
|
PrometheusEndpoints,
|
|
146
|
-
|
|
147
|
+
TimeSeriesConnector,
|
|
148
|
+
TSDBTarget,
|
|
147
149
|
)
|
|
148
150
|
from .notification import (
|
|
149
151
|
Notification,
|
mlrun/common/schemas/alert.py
CHANGED
|
@@ -26,10 +26,10 @@ class EventEntityKind(StrEnum):
|
|
|
26
26
|
JOB = "job"
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class EventEntities(pydantic.BaseModel):
|
|
30
30
|
kind: EventEntityKind
|
|
31
31
|
project: str
|
|
32
|
-
|
|
32
|
+
ids: pydantic.conlist(str, min_items=1, max_items=1)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class EventKind(StrEnum):
|
|
@@ -48,7 +48,7 @@ _event_kind_entity_map = {
|
|
|
48
48
|
class Event(pydantic.BaseModel):
|
|
49
49
|
kind: EventKind
|
|
50
50
|
timestamp: Union[str, datetime] = None # occurrence time
|
|
51
|
-
entity:
|
|
51
|
+
entity: EventEntities
|
|
52
52
|
value_dict: Optional[dict] = pydantic.Field(default_factory=dict)
|
|
53
53
|
|
|
54
54
|
def is_valid(self):
|
|
@@ -71,6 +71,12 @@ class AlertTrigger(pydantic.BaseModel):
|
|
|
71
71
|
events: list[EventKind] = []
|
|
72
72
|
prometheus_alert: str = None
|
|
73
73
|
|
|
74
|
+
def __eq__(self, other):
|
|
75
|
+
return (
|
|
76
|
+
self.prometheus_alert == other.prometheus_alert
|
|
77
|
+
and self.events == other.events
|
|
78
|
+
)
|
|
79
|
+
|
|
74
80
|
|
|
75
81
|
class AlertCriteria(pydantic.BaseModel):
|
|
76
82
|
count: Annotated[
|
|
@@ -86,6 +92,9 @@ class AlertCriteria(pydantic.BaseModel):
|
|
|
86
92
|
),
|
|
87
93
|
] = None
|
|
88
94
|
|
|
95
|
+
def __eq__(self, other):
|
|
96
|
+
return self.count == other.count and self.period == other.period
|
|
97
|
+
|
|
89
98
|
|
|
90
99
|
class ResetPolicy(StrEnum):
|
|
91
100
|
MANUAL = "manual"
|
|
@@ -108,7 +117,7 @@ class AlertConfig(pydantic.BaseModel):
|
|
|
108
117
|
]
|
|
109
118
|
created: Union[str, datetime] = None
|
|
110
119
|
severity: AlertSeverity
|
|
111
|
-
|
|
120
|
+
entities: EventEntities
|
|
112
121
|
trigger: AlertTrigger
|
|
113
122
|
criteria: Optional[AlertCriteria]
|
|
114
123
|
reset_policy: ResetPolicy = ResetPolicy.MANUAL
|
|
@@ -120,3 +129,36 @@ class AlertConfig(pydantic.BaseModel):
|
|
|
120
129
|
class AlertsModes(StrEnum):
|
|
121
130
|
enabled = "enabled"
|
|
122
131
|
disabled = "disabled"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class AlertTemplate(
|
|
135
|
+
pydantic.BaseModel
|
|
136
|
+
): # Template fields that are not shared with created configs
|
|
137
|
+
template_id: int = None
|
|
138
|
+
template_name: str
|
|
139
|
+
template_description: Optional[str] = (
|
|
140
|
+
"String explaining the purpose of this template"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# A property that identifies templates that were created by the system and cannot be modified/deleted by the user
|
|
144
|
+
system_generated: bool = False
|
|
145
|
+
|
|
146
|
+
# AlertConfig fields that are pre-defined
|
|
147
|
+
description: Optional[str] = (
|
|
148
|
+
"String to be sent in the generated notifications e.g. 'Model {{ $project }}/{{ $entity }} is drifting.'"
|
|
149
|
+
)
|
|
150
|
+
severity: AlertSeverity
|
|
151
|
+
trigger: AlertTrigger
|
|
152
|
+
criteria: Optional[AlertCriteria]
|
|
153
|
+
reset_policy: ResetPolicy = ResetPolicy.MANUAL
|
|
154
|
+
|
|
155
|
+
# This is slightly different than __eq__ as it doesn't compare everything
|
|
156
|
+
def templates_differ(self, other):
|
|
157
|
+
return (
|
|
158
|
+
self.template_description != other.template_description
|
|
159
|
+
or self.description != other.description
|
|
160
|
+
or self.severity != other.severity
|
|
161
|
+
or self.trigger != other.trigger
|
|
162
|
+
or self.reset_policy != other.reset_policy
|
|
163
|
+
or self.criteria != other.criteria
|
|
164
|
+
)
|
|
@@ -23,6 +23,7 @@ import mlrun.common.types
|
|
|
23
23
|
class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
|
|
24
24
|
basic = "basicAuth"
|
|
25
25
|
none = "none"
|
|
26
|
+
access_key = "accessKey"
|
|
26
27
|
|
|
27
28
|
@classmethod
|
|
28
29
|
def from_str(cls, authentication_mode: str):
|
|
@@ -30,6 +31,8 @@ class APIGatewayAuthenticationMode(mlrun.common.types.StrEnum):
|
|
|
30
31
|
return cls.none
|
|
31
32
|
elif authentication_mode == "basicAuth":
|
|
32
33
|
return cls.basic
|
|
34
|
+
elif authentication_mode == "accessKey":
|
|
35
|
+
return cls.access_key
|
|
33
36
|
else:
|
|
34
37
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
35
38
|
f"Authentication mode `{authentication_mode}` is not supported",
|
|
@@ -63,6 +66,7 @@ class APIGatewayUpstream(_APIGatewayBaseModel):
|
|
|
63
66
|
kind: Optional[str] = "nucliofunction"
|
|
64
67
|
nucliofunction: dict[str, str]
|
|
65
68
|
percentage: Optional[int] = 0
|
|
69
|
+
port: Optional[int] = 0
|
|
66
70
|
|
|
67
71
|
|
|
68
72
|
class APIGatewaySpec(_APIGatewayBaseModel):
|
mlrun/common/schemas/artifact.py
CHANGED
|
@@ -93,3 +93,18 @@ class Artifact(pydantic.BaseModel):
|
|
|
93
93
|
metadata: ArtifactMetadata
|
|
94
94
|
spec: ArtifactSpec
|
|
95
95
|
status: ObjectStatus
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ArtifactsDeletionStrategies(mlrun.common.types.StrEnum):
|
|
99
|
+
"""Artifacts deletion strategies types."""
|
|
100
|
+
|
|
101
|
+
metadata_only = "metadata-only"
|
|
102
|
+
"""Only removes the artifact db record, leaving all related artifact data in-place"""
|
|
103
|
+
|
|
104
|
+
data_optional = "data-optional"
|
|
105
|
+
"""Delete the artifact data of the artifact as a best-effort.
|
|
106
|
+
If artifact data deletion fails still try to delete the artifact db record"""
|
|
107
|
+
|
|
108
|
+
data_force = "data-force"
|
|
109
|
+
"""Delete the artifact data, and if cannot delete it fail the deletion
|
|
110
|
+
and don’t delete the artifact db record"""
|
mlrun/common/schemas/auth.py
CHANGED
|
@@ -59,6 +59,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
|
|
|
59
59
|
hub_source = "hub-source"
|
|
60
60
|
workflow = "workflow"
|
|
61
61
|
alert = "alert"
|
|
62
|
+
alert_templates = "alert-templates"
|
|
62
63
|
event = "event"
|
|
63
64
|
datastore_profile = "datastore-profile"
|
|
64
65
|
api_gateway = "api-gateway"
|
|
@@ -87,6 +88,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
|
|
|
87
88
|
AuthorizationResourceTypes.run: "/projects/{project_name}/runs/{resource_name}",
|
|
88
89
|
AuthorizationResourceTypes.event: "/projects/{project_name}/events/{resource_name}",
|
|
89
90
|
AuthorizationResourceTypes.alert: "/projects/{project_name}/alerts/{resource_name}",
|
|
91
|
+
AuthorizationResourceTypes.alert_templates: "/alert-templates/{resource_name}",
|
|
90
92
|
# runtime resource doesn't have an identifier, we don't need any auth granularity behind project level
|
|
91
93
|
AuthorizationResourceTypes.runtime_resource: "/projects/{project_name}/runtime-resources",
|
|
92
94
|
AuthorizationResourceTypes.model_endpoint: "/projects/{project_name}/model-endpoints/{resource_name}",
|
|
@@ -30,14 +30,17 @@ from .constants import (
|
|
|
30
30
|
ModelMonitoringMode,
|
|
31
31
|
ModelMonitoringStoreKinds,
|
|
32
32
|
MonitoringFunctionNames,
|
|
33
|
+
MonitoringTSDBTables,
|
|
33
34
|
ProjectSecretKeys,
|
|
34
35
|
PrometheusEndpoints,
|
|
35
36
|
PrometheusMetric,
|
|
36
37
|
ResultData,
|
|
37
38
|
SchedulingKeys,
|
|
38
|
-
|
|
39
|
+
TimeSeriesConnector,
|
|
40
|
+
TSDBTarget,
|
|
39
41
|
VersionedModel,
|
|
40
42
|
WriterEvent,
|
|
43
|
+
WriterEventKind,
|
|
41
44
|
)
|
|
42
45
|
from .grafana import (
|
|
43
46
|
GrafanaColumn,
|
|
@@ -156,7 +156,7 @@ class EventKeyMetrics:
|
|
|
156
156
|
REAL_TIME = "real_time"
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-
class
|
|
159
|
+
class TimeSeriesConnector:
|
|
160
160
|
TSDB = "tsdb"
|
|
161
161
|
|
|
162
162
|
|
|
@@ -194,6 +194,7 @@ class FileTargetKind:
|
|
|
194
194
|
LOG_STREAM = "log_stream"
|
|
195
195
|
APP_RESULTS = "app_results"
|
|
196
196
|
MONITORING_SCHEDULES = "monitoring_schedules"
|
|
197
|
+
MONITORING_APPLICATION = "monitoring_application"
|
|
197
198
|
|
|
198
199
|
|
|
199
200
|
class ModelMonitoringMode(str, Enum):
|
|
@@ -228,6 +229,12 @@ class MonitoringFunctionNames(MonitoringStrEnum):
|
|
|
228
229
|
WRITER = "model-monitoring-writer"
|
|
229
230
|
|
|
230
231
|
|
|
232
|
+
class MonitoringTSDBTables(MonitoringStrEnum):
|
|
233
|
+
APP_RESULTS = "app-results"
|
|
234
|
+
METRICS = "metrics"
|
|
235
|
+
EVENTS = "events"
|
|
236
|
+
|
|
237
|
+
|
|
231
238
|
@dataclass
|
|
232
239
|
class FunctionURI:
|
|
233
240
|
project: str
|
|
@@ -329,6 +336,14 @@ class ControllerPolicy:
|
|
|
329
336
|
BASE_PERIOD = "base_period"
|
|
330
337
|
|
|
331
338
|
|
|
339
|
+
class TSDBTarget:
|
|
340
|
+
V3IO_TSDB = "v3io-tsdb"
|
|
341
|
+
PROMETHEUS = "prometheus"
|
|
342
|
+
APP_RESULTS_TABLE = "app-results"
|
|
343
|
+
V3IO_BE = "tsdb"
|
|
344
|
+
V3IO_RATE = "1/s"
|
|
345
|
+
|
|
346
|
+
|
|
332
347
|
class HistogramDataDriftApplicationConstants:
|
|
333
348
|
NAME = "histogram-data-drift"
|
|
334
349
|
GENERAL_RESULT_NAME = "general_drift"
|