mlrun 1.8.0rc1__py3-none-any.whl → 1.8.0rc3__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 +5 -7
- mlrun/__main__.py +1 -1
- mlrun/artifacts/__init__.py +1 -0
- mlrun/artifacts/document.py +313 -0
- mlrun/artifacts/manager.py +2 -0
- mlrun/common/formatters/project.py +9 -0
- mlrun/common/schemas/__init__.py +4 -0
- mlrun/common/schemas/alert.py +31 -18
- mlrun/common/schemas/api_gateway.py +3 -3
- mlrun/common/schemas/artifact.py +7 -7
- mlrun/common/schemas/auth.py +6 -4
- mlrun/common/schemas/background_task.py +7 -7
- mlrun/common/schemas/client_spec.py +2 -2
- mlrun/common/schemas/clusterization_spec.py +2 -2
- mlrun/common/schemas/common.py +5 -5
- mlrun/common/schemas/constants.py +15 -0
- mlrun/common/schemas/datastore_profile.py +1 -1
- mlrun/common/schemas/feature_store.py +9 -9
- mlrun/common/schemas/frontend_spec.py +4 -4
- mlrun/common/schemas/function.py +10 -10
- mlrun/common/schemas/hub.py +1 -1
- mlrun/common/schemas/k8s.py +3 -3
- mlrun/common/schemas/memory_reports.py +3 -3
- mlrun/common/schemas/model_monitoring/grafana.py +1 -1
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +1 -1
- mlrun/common/schemas/model_monitoring/model_endpoints.py +1 -1
- mlrun/common/schemas/notification.py +18 -3
- mlrun/common/schemas/object.py +1 -1
- mlrun/common/schemas/pagination.py +4 -4
- mlrun/common/schemas/partition.py +16 -1
- mlrun/common/schemas/pipeline.py +2 -2
- mlrun/common/schemas/project.py +22 -17
- mlrun/common/schemas/runs.py +2 -2
- mlrun/common/schemas/runtime_resource.py +5 -5
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/secret.py +1 -1
- mlrun/common/schemas/tag.py +3 -3
- mlrun/common/schemas/workflow.py +5 -5
- mlrun/config.py +23 -1
- mlrun/datastore/datastore_profile.py +38 -19
- mlrun/datastore/vectorstore.py +186 -0
- mlrun/db/base.py +58 -6
- mlrun/db/httpdb.py +267 -15
- mlrun/db/nopdb.py +44 -5
- mlrun/execution.py +47 -1
- mlrun/model.py +2 -2
- mlrun/model_monitoring/applications/results.py +2 -2
- mlrun/model_monitoring/db/tsdb/base.py +2 -2
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +37 -13
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +32 -40
- mlrun/model_monitoring/helpers.py +4 -10
- mlrun/model_monitoring/stream_processing.py +14 -11
- mlrun/platforms/__init__.py +44 -13
- mlrun/projects/__init__.py +6 -1
- mlrun/projects/pipelines.py +184 -55
- mlrun/projects/project.py +309 -33
- mlrun/run.py +4 -1
- mlrun/runtimes/base.py +2 -1
- mlrun/runtimes/mounts.py +572 -0
- mlrun/runtimes/nuclio/function.py +1 -2
- mlrun/runtimes/pod.py +82 -18
- mlrun/runtimes/remotesparkjob.py +1 -1
- mlrun/runtimes/sparkjob/spark3job.py +1 -1
- mlrun/utils/clones.py +1 -1
- mlrun/utils/helpers.py +12 -2
- mlrun/utils/logger.py +2 -2
- mlrun/utils/notifications/notification/__init__.py +22 -19
- mlrun/utils/notifications/notification/base.py +12 -12
- mlrun/utils/notifications/notification/console.py +6 -6
- mlrun/utils/notifications/notification/git.py +6 -6
- mlrun/utils/notifications/notification/ipython.py +6 -6
- mlrun/utils/notifications/notification/mail.py +149 -0
- mlrun/utils/notifications/notification/slack.py +6 -6
- mlrun/utils/notifications/notification/webhook.py +6 -6
- mlrun/utils/notifications/notification_pusher.py +20 -12
- mlrun/utils/regex.py +2 -0
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/METADATA +190 -186
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/RECORD +83 -79
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/WHEEL +1 -1
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc3.dist-info}/top_level.txt +0 -0
mlrun/__init__.py
CHANGED
|
@@ -31,8 +31,6 @@ from typing import Optional
|
|
|
31
31
|
|
|
32
32
|
import dotenv
|
|
33
33
|
|
|
34
|
-
import mlrun_pipelines
|
|
35
|
-
|
|
36
34
|
from .config import config as mlconf
|
|
37
35
|
from .datastore import DataItem, store_manager
|
|
38
36
|
from .db import get_run_db
|
|
@@ -63,16 +61,16 @@ from .run import (
|
|
|
63
61
|
new_function,
|
|
64
62
|
wait_for_pipeline_completion,
|
|
65
63
|
)
|
|
66
|
-
from .runtimes import new_model_server
|
|
64
|
+
from .runtimes import mounts, new_model_server
|
|
67
65
|
from .secrets import get_secret_or_env
|
|
68
66
|
from .utils.version import Version
|
|
69
67
|
|
|
70
68
|
__version__ = Version().get()["version"]
|
|
71
69
|
|
|
72
|
-
VolumeMount =
|
|
73
|
-
mount_v3io =
|
|
74
|
-
v3io_cred =
|
|
75
|
-
auto_mount =
|
|
70
|
+
VolumeMount = mounts.VolumeMount
|
|
71
|
+
mount_v3io = mounts.mount_v3io
|
|
72
|
+
v3io_cred = mounts.v3io_cred
|
|
73
|
+
auto_mount = mounts.auto_mount
|
|
76
74
|
|
|
77
75
|
|
|
78
76
|
def get_version():
|
mlrun/__main__.py
CHANGED
|
@@ -33,7 +33,7 @@ import mlrun
|
|
|
33
33
|
import mlrun.common.constants as mlrun_constants
|
|
34
34
|
import mlrun.common.schemas
|
|
35
35
|
from mlrun.common.helpers import parse_versioned_object_uri
|
|
36
|
-
from
|
|
36
|
+
from mlrun.runtimes.mounts import auto_mount as auto_mount_modifier
|
|
37
37
|
|
|
38
38
|
from .config import config as mlconf
|
|
39
39
|
from .db import get_run_db
|
mlrun/artifacts/__init__.py
CHANGED
|
@@ -23,6 +23,7 @@ from .base import (
|
|
|
23
23
|
get_artifact_meta,
|
|
24
24
|
)
|
|
25
25
|
from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
|
|
26
|
+
from .document import DocumentArtifact, DocumentLoader, DocumentLoaderSpec
|
|
26
27
|
from .manager import (
|
|
27
28
|
ArtifactManager,
|
|
28
29
|
ArtifactProducer,
|
|
@@ -0,0 +1,313 @@
|
|
|
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
|
+
import ast
|
|
16
|
+
import re
|
|
17
|
+
import tempfile
|
|
18
|
+
from collections.abc import Iterator
|
|
19
|
+
from copy import deepcopy
|
|
20
|
+
from importlib import import_module
|
|
21
|
+
from typing import Optional, Union
|
|
22
|
+
|
|
23
|
+
import mlrun
|
|
24
|
+
from mlrun.artifacts import Artifact, ArtifactSpec
|
|
25
|
+
from mlrun.model import ModelObj
|
|
26
|
+
|
|
27
|
+
from ..utils import generate_artifact_uri
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DocumentLoaderSpec(ModelObj):
|
|
31
|
+
"""
|
|
32
|
+
A class to load a document from a file path using a specified loader class.
|
|
33
|
+
|
|
34
|
+
This class is responsible for loading documents from a given source path using a specified loader class.
|
|
35
|
+
The loader class is dynamically imported and instantiated with the provided arguments. The loaded documents
|
|
36
|
+
can be optionally uploaded as artifacts.
|
|
37
|
+
|
|
38
|
+
Attributes:
|
|
39
|
+
loader_class_name (str): The name of the loader class to use for loading documents.
|
|
40
|
+
src_name (str): The name of the source attribute to pass to the loader class.
|
|
41
|
+
kwargs (Optional[dict]): Additional keyword arguments to pass to the loader class.
|
|
42
|
+
|
|
43
|
+
Methods:
|
|
44
|
+
make_loader(src_path): Creates an instance of the loader class with the specified source path.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
_dict_fields = ["loader_class_name", "src_name", "kwargs"]
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
loader_class_name: str = "langchain_community.document_loaders.TextLoader",
|
|
52
|
+
src_name: str = "file_path",
|
|
53
|
+
kwargs: Optional[dict] = None,
|
|
54
|
+
):
|
|
55
|
+
"""
|
|
56
|
+
Initialize the document loader.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
loader_class_name (str): The name of the loader class to use.
|
|
60
|
+
src_name (str): The source name for the document.
|
|
61
|
+
kwargs (Optional[dict]): Additional keyword arguments to pass to the loader class.
|
|
62
|
+
"""
|
|
63
|
+
self.loader_class_name = loader_class_name
|
|
64
|
+
self.src_name = src_name
|
|
65
|
+
self.kwargs = kwargs
|
|
66
|
+
|
|
67
|
+
def make_loader(self, src_path):
|
|
68
|
+
module_name, class_name = self.loader_class_name.rsplit(".", 1)
|
|
69
|
+
module = import_module(module_name)
|
|
70
|
+
loader_class = getattr(module, class_name)
|
|
71
|
+
kwargs = deepcopy(self.kwargs or {})
|
|
72
|
+
kwargs[self.src_name] = src_path
|
|
73
|
+
loader = loader_class(**kwargs)
|
|
74
|
+
return loader
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class DocumentLoader:
|
|
78
|
+
"""
|
|
79
|
+
A factory class for creating instances of a dynamically defined document loader.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
artifact_key (str): The key for the artifact to be logged.It can include '%%' which will be replaced
|
|
83
|
+
by a hex-encoded version of the source path.
|
|
84
|
+
source_path (str): The source path of the document to be loaded.
|
|
85
|
+
loader_spec (DocumentLoaderSpec): Specification for the document loader.
|
|
86
|
+
producer (Optional[Union[MlrunProject, str, MLClientCtx]], optional): The producer of the document
|
|
87
|
+
upload (bool, optional): Flag indicating whether to upload the document.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
DynamicDocumentLoader: An instance of a dynamically defined subclass of BaseLoader.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __new__(
|
|
94
|
+
cls,
|
|
95
|
+
source_path: str,
|
|
96
|
+
loader_spec: "DocumentLoaderSpec",
|
|
97
|
+
artifact_key="doc%%",
|
|
98
|
+
producer: Optional[Union["MlrunProject", str, "MLClientCtx"]] = None, # noqa: F821
|
|
99
|
+
upload: bool = False,
|
|
100
|
+
):
|
|
101
|
+
# Dynamically import BaseLoader
|
|
102
|
+
from langchain_community.document_loaders.base import BaseLoader
|
|
103
|
+
|
|
104
|
+
class DynamicDocumentLoader(BaseLoader):
|
|
105
|
+
def __init__(
|
|
106
|
+
self,
|
|
107
|
+
source_path,
|
|
108
|
+
loader_spec,
|
|
109
|
+
artifact_key,
|
|
110
|
+
producer,
|
|
111
|
+
upload,
|
|
112
|
+
):
|
|
113
|
+
self.producer = producer
|
|
114
|
+
self.artifact_key = (
|
|
115
|
+
DocumentLoader.artifact_key_instance(artifact_key, source_path)
|
|
116
|
+
if "%%" in artifact_key
|
|
117
|
+
else artifact_key
|
|
118
|
+
)
|
|
119
|
+
self.loader_spec = loader_spec
|
|
120
|
+
self.source_path = source_path
|
|
121
|
+
self.upload = upload
|
|
122
|
+
|
|
123
|
+
# Resolve the producer
|
|
124
|
+
if not self.producer:
|
|
125
|
+
self.producer = mlrun.mlconf.default_project
|
|
126
|
+
if isinstance(self.producer, str):
|
|
127
|
+
self.producer = mlrun.get_or_create_project(self.producer)
|
|
128
|
+
|
|
129
|
+
def lazy_load(self) -> Iterator["Document"]: # noqa: F821
|
|
130
|
+
artifact = self.producer.log_document(
|
|
131
|
+
key=self.artifact_key,
|
|
132
|
+
document_loader=self.loader_spec,
|
|
133
|
+
src_path=self.source_path,
|
|
134
|
+
upload=self.upload,
|
|
135
|
+
)
|
|
136
|
+
yield artifact.to_langchain_documents()
|
|
137
|
+
|
|
138
|
+
# Return an instance of the dynamically defined subclass
|
|
139
|
+
instance = DynamicDocumentLoader(
|
|
140
|
+
artifact_key=artifact_key,
|
|
141
|
+
source_path=source_path,
|
|
142
|
+
loader_spec=loader_spec,
|
|
143
|
+
producer=producer,
|
|
144
|
+
upload=upload,
|
|
145
|
+
)
|
|
146
|
+
return instance
|
|
147
|
+
|
|
148
|
+
@staticmethod
|
|
149
|
+
def artifact_key_instance(artifact_key: str, src_path: str) -> str:
|
|
150
|
+
if "%%" in artifact_key:
|
|
151
|
+
pattern = mlrun.utils.regex.artifact_key[0]
|
|
152
|
+
# Convert anchored pattern (^...$) to non-anchored version for finditer
|
|
153
|
+
search_pattern = pattern.strip("^$")
|
|
154
|
+
result = []
|
|
155
|
+
current_pos = 0
|
|
156
|
+
|
|
157
|
+
# Find all valid sequences
|
|
158
|
+
for match in re.finditer(search_pattern, src_path):
|
|
159
|
+
# Add hex values for characters between matches
|
|
160
|
+
for char in src_path[current_pos : match.start()]:
|
|
161
|
+
result.append(hex(ord(char))[2:].zfill(2))
|
|
162
|
+
|
|
163
|
+
# Add the valid sequence
|
|
164
|
+
result.append(match.group())
|
|
165
|
+
current_pos = match.end()
|
|
166
|
+
|
|
167
|
+
# Handle any remaining characters after the last match
|
|
168
|
+
for char in src_path[current_pos:]:
|
|
169
|
+
result.append(hex(ord(char))[2:].zfill(2))
|
|
170
|
+
|
|
171
|
+
resolved_path = "".join(result)
|
|
172
|
+
|
|
173
|
+
artifact_key = artifact_key.replace("%%", resolved_path)
|
|
174
|
+
|
|
175
|
+
return artifact_key
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class DocumentArtifact(Artifact):
|
|
179
|
+
"""
|
|
180
|
+
A specific artifact class inheriting from generic artifact, used to maintain Document meta-data.
|
|
181
|
+
|
|
182
|
+
Methods:
|
|
183
|
+
to_langchain_documents(splitter): Create LC documents from the artifact.
|
|
184
|
+
collection_add(collection_id): Add a collection ID to the artifact.
|
|
185
|
+
collection_remove(collection_id): Remove a collection ID from the artifact.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
class DocumentArtifactSpec(ArtifactSpec):
|
|
189
|
+
_dict_fields = ArtifactSpec._dict_fields + [
|
|
190
|
+
"document_loader",
|
|
191
|
+
"collections",
|
|
192
|
+
"original_source",
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
def __init__(
|
|
196
|
+
self,
|
|
197
|
+
*args,
|
|
198
|
+
**kwargs,
|
|
199
|
+
):
|
|
200
|
+
super().__init__(*args, **kwargs)
|
|
201
|
+
self.document_loader = None
|
|
202
|
+
self.collections = set()
|
|
203
|
+
self.original_source = None
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
A specific artifact class inheriting from generic artifact, used to maintain Document meta-data.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
kind = "document"
|
|
210
|
+
|
|
211
|
+
METADATA_SOURCE_KEY = "source"
|
|
212
|
+
METADATA_ORIGINAL_SOURCE_KEY = "original_source"
|
|
213
|
+
METADATA_CHUNK_KEY = "mlrun_chunk"
|
|
214
|
+
METADATA_ARTIFACT_URI_KEY = "mlrun_object_uri"
|
|
215
|
+
METADATA_ARTIFACT_TARGET_PATH_KEY = "mlrun_target_path"
|
|
216
|
+
|
|
217
|
+
def __init__(
|
|
218
|
+
self,
|
|
219
|
+
key=None,
|
|
220
|
+
document_loader: DocumentLoaderSpec = DocumentLoaderSpec(),
|
|
221
|
+
**kwargs,
|
|
222
|
+
):
|
|
223
|
+
super().__init__(key, **kwargs)
|
|
224
|
+
self.spec.document_loader = document_loader.to_str()
|
|
225
|
+
if "src_path" in kwargs:
|
|
226
|
+
self.spec.original_source = kwargs["src_path"]
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def spec(self) -> DocumentArtifactSpec:
|
|
230
|
+
return self._spec
|
|
231
|
+
|
|
232
|
+
@spec.setter
|
|
233
|
+
def spec(self, spec):
|
|
234
|
+
self._spec = self._verify_dict(
|
|
235
|
+
spec, "spec", DocumentArtifact.DocumentArtifactSpec
|
|
236
|
+
)
|
|
237
|
+
# _verify_dict doesn't handle set, so we need to convert it back
|
|
238
|
+
if isinstance(self._spec.collections, str):
|
|
239
|
+
self._spec.collections = ast.literal_eval(self._spec.collections)
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def inputs(self):
|
|
243
|
+
# To keep the interface consistent with the project.update_artifact() when we update the artifact
|
|
244
|
+
return None
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def source(self):
|
|
248
|
+
return generate_artifact_uri(self.metadata.project, self.spec.db_key)
|
|
249
|
+
|
|
250
|
+
def to_langchain_documents(
|
|
251
|
+
self,
|
|
252
|
+
splitter: Optional["TextSplitter"] = None, # noqa: F821
|
|
253
|
+
) -> list["Document"]: # noqa: F821
|
|
254
|
+
from langchain.schema import Document
|
|
255
|
+
|
|
256
|
+
"""
|
|
257
|
+
Create LC documents from the artifact
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
splitter (Optional[TextSplitter]): A LangChain TextSplitter to split the document into chunks.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
list[Document]: A list of LangChain Document objects.
|
|
264
|
+
"""
|
|
265
|
+
dictionary = ast.literal_eval(self.spec.document_loader)
|
|
266
|
+
loader_spec = DocumentLoaderSpec.from_dict(dictionary)
|
|
267
|
+
|
|
268
|
+
if self.get_target_path():
|
|
269
|
+
with tempfile.NamedTemporaryFile() as tmp_file:
|
|
270
|
+
mlrun.datastore.store_manager.object(
|
|
271
|
+
url=self.get_target_path()
|
|
272
|
+
).download(tmp_file.name)
|
|
273
|
+
loader = loader_spec.make_loader(tmp_file.name)
|
|
274
|
+
documents = loader.load()
|
|
275
|
+
elif self.src_path:
|
|
276
|
+
loader = loader_spec.make_loader(self.src_path)
|
|
277
|
+
documents = loader.load()
|
|
278
|
+
else:
|
|
279
|
+
raise ValueError(
|
|
280
|
+
"No src_path or target_path provided. Cannot load document."
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
results = []
|
|
284
|
+
for document in documents:
|
|
285
|
+
if splitter:
|
|
286
|
+
texts = splitter.split_text(document.page_content)
|
|
287
|
+
else:
|
|
288
|
+
texts = [document.page_content]
|
|
289
|
+
|
|
290
|
+
metadata = document.metadata
|
|
291
|
+
|
|
292
|
+
metadata[self.METADATA_ORIGINAL_SOURCE_KEY] = self.src_path
|
|
293
|
+
metadata[self.METADATA_SOURCE_KEY] = self.source
|
|
294
|
+
metadata[self.METADATA_ARTIFACT_URI_KEY] = self.uri
|
|
295
|
+
if self.get_target_path():
|
|
296
|
+
metadata[self.METADATA_ARTIFACT_TARGET_PATH_KEY] = (
|
|
297
|
+
self.get_target_path()
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
for idx, text in enumerate(texts):
|
|
301
|
+
metadata[self.METADATA_CHUNK_KEY] = str(idx)
|
|
302
|
+
doc = Document(
|
|
303
|
+
page_content=text,
|
|
304
|
+
metadata=metadata,
|
|
305
|
+
)
|
|
306
|
+
results.append(doc)
|
|
307
|
+
return results
|
|
308
|
+
|
|
309
|
+
def collection_add(self, collection_id: str) -> None:
|
|
310
|
+
self.spec.collections.add(collection_id)
|
|
311
|
+
|
|
312
|
+
def collection_remove(self, collection_id: str) -> None:
|
|
313
|
+
return self.spec.collections.discard(collection_id)
|
mlrun/artifacts/manager.py
CHANGED
|
@@ -41,6 +41,7 @@ from .dataset import (
|
|
|
41
41
|
DatasetArtifact,
|
|
42
42
|
TableArtifact,
|
|
43
43
|
)
|
|
44
|
+
from .document import DocumentArtifact
|
|
44
45
|
from .model import ModelArtifact
|
|
45
46
|
from .plots import (
|
|
46
47
|
PlotArtifact,
|
|
@@ -57,6 +58,7 @@ artifact_types = {
|
|
|
57
58
|
"model": ModelArtifact,
|
|
58
59
|
"dataset": DatasetArtifact,
|
|
59
60
|
"plotly": PlotlyArtifact,
|
|
61
|
+
"document": DocumentArtifact,
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
15
|
|
|
16
|
+
import datetime
|
|
16
17
|
import typing
|
|
17
18
|
|
|
18
19
|
import mlrun.common.schemas
|
|
@@ -30,11 +31,18 @@ class ProjectFormat(ObjectFormat, mlrun.common.types.StrEnum):
|
|
|
30
31
|
# internal - allowed only in follower mode, only for the leader for upgrade purposes
|
|
31
32
|
leader = "leader"
|
|
32
33
|
|
|
34
|
+
name_and_creation_time = "name_and_creation_time"
|
|
35
|
+
|
|
33
36
|
@staticmethod
|
|
34
37
|
def format_method(_format: str) -> typing.Optional[typing.Callable]:
|
|
35
38
|
def _name_only(project: mlrun.common.schemas.Project) -> str:
|
|
36
39
|
return project.metadata.name
|
|
37
40
|
|
|
41
|
+
def _name_and_creation_time(
|
|
42
|
+
project: mlrun.common.schemas.Project,
|
|
43
|
+
) -> tuple[str, datetime.datetime]:
|
|
44
|
+
return project.metadata.name, project.metadata.created
|
|
45
|
+
|
|
38
46
|
def _minimal(
|
|
39
47
|
project: mlrun.common.schemas.Project,
|
|
40
48
|
) -> mlrun.common.schemas.Project:
|
|
@@ -48,4 +56,5 @@ class ProjectFormat(ObjectFormat, mlrun.common.types.StrEnum):
|
|
|
48
56
|
ProjectFormat.name_only: _name_only,
|
|
49
57
|
ProjectFormat.minimal: _minimal,
|
|
50
58
|
ProjectFormat.leader: None,
|
|
59
|
+
ProjectFormat.name_and_creation_time: _name_and_creation_time,
|
|
51
60
|
}[_format]
|
mlrun/common/schemas/__init__.py
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from .alert import (
|
|
16
|
+
AlertActivation,
|
|
16
17
|
AlertActiveState,
|
|
17
18
|
AlertConfig,
|
|
18
19
|
AlertNotification,
|
|
@@ -61,6 +62,7 @@ from .clusterization_spec import (
|
|
|
61
62
|
from .common import ImageBuilder
|
|
62
63
|
from .constants import (
|
|
63
64
|
APIStates,
|
|
65
|
+
ArtifactPartitionByField,
|
|
64
66
|
ClusterizationRole,
|
|
65
67
|
DeletionStrategy,
|
|
66
68
|
FeatureStorePartitionByField,
|
|
@@ -161,11 +163,13 @@ from .notification import (
|
|
|
161
163
|
Notification,
|
|
162
164
|
NotificationKind,
|
|
163
165
|
NotificationSeverity,
|
|
166
|
+
NotificationState,
|
|
164
167
|
NotificationStatus,
|
|
165
168
|
SetNotificationRequest,
|
|
166
169
|
)
|
|
167
170
|
from .object import ObjectKind, ObjectMetadata, ObjectSpec, ObjectStatus
|
|
168
171
|
from .pagination import PaginationInfo
|
|
172
|
+
from .partition import PartitionInterval
|
|
169
173
|
from .pipeline import PipelinesOutput, PipelinesPagination
|
|
170
174
|
from .project import (
|
|
171
175
|
IguazioProject,
|
mlrun/common/schemas/alert.py
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
from typing import Annotated, Optional, Union
|
|
17
17
|
|
|
18
|
-
import pydantic
|
|
18
|
+
import pydantic.v1
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
import mlrun.common.schemas.notification as notification_objects
|
|
21
21
|
from mlrun.common.types import StrEnum
|
|
22
22
|
|
|
23
23
|
|
|
@@ -27,10 +27,10 @@ class EventEntityKind(StrEnum):
|
|
|
27
27
|
JOB = "job"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class EventEntities(pydantic.BaseModel):
|
|
30
|
+
class EventEntities(pydantic.v1.BaseModel):
|
|
31
31
|
kind: EventEntityKind
|
|
32
32
|
project: str
|
|
33
|
-
ids: pydantic.conlist(str, min_items=1, max_items=1)
|
|
33
|
+
ids: pydantic.v1.conlist(str, min_items=1, max_items=1)
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class EventKind(StrEnum):
|
|
@@ -64,11 +64,11 @@ _event_kind_entity_map = {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
class Event(pydantic.BaseModel):
|
|
67
|
+
class Event(pydantic.v1.BaseModel):
|
|
68
68
|
kind: EventKind
|
|
69
69
|
timestamp: Union[str, datetime] = None # occurrence time
|
|
70
70
|
entity: EventEntities
|
|
71
|
-
value_dict: Optional[dict] = pydantic.Field(default_factory=dict)
|
|
71
|
+
value_dict: Optional[dict] = pydantic.v1.Field(default_factory=dict)
|
|
72
72
|
|
|
73
73
|
def is_valid(self):
|
|
74
74
|
return self.entity.kind in _event_kind_entity_map[self.kind]
|
|
@@ -86,7 +86,7 @@ class AlertSeverity(StrEnum):
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
# what should trigger the alert. must be either event (at least 1), or prometheus query
|
|
89
|
-
class AlertTrigger(pydantic.BaseModel):
|
|
89
|
+
class AlertTrigger(pydantic.v1.BaseModel):
|
|
90
90
|
events: list[EventKind] = []
|
|
91
91
|
prometheus_alert: str = None
|
|
92
92
|
|
|
@@ -97,16 +97,16 @@ class AlertTrigger(pydantic.BaseModel):
|
|
|
97
97
|
)
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
class AlertCriteria(pydantic.BaseModel):
|
|
100
|
+
class AlertCriteria(pydantic.v1.BaseModel):
|
|
101
101
|
count: Annotated[
|
|
102
102
|
int,
|
|
103
|
-
pydantic.Field(
|
|
103
|
+
pydantic.v1.Field(
|
|
104
104
|
description="Number of events to wait until notification is sent"
|
|
105
105
|
),
|
|
106
106
|
] = 1
|
|
107
107
|
period: Annotated[
|
|
108
108
|
str,
|
|
109
|
-
pydantic.Field(
|
|
109
|
+
pydantic.v1.Field(
|
|
110
110
|
description="Time period during which event occurred. e.g. 1d, 3h, 5m, 15s"
|
|
111
111
|
),
|
|
112
112
|
] = None
|
|
@@ -120,11 +120,11 @@ class ResetPolicy(StrEnum):
|
|
|
120
120
|
AUTO = "auto"
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
class AlertNotification(pydantic.BaseModel):
|
|
124
|
-
notification: Notification
|
|
123
|
+
class AlertNotification(pydantic.v1.BaseModel):
|
|
124
|
+
notification: notification_objects.Notification
|
|
125
125
|
cooldown_period: Annotated[
|
|
126
126
|
str,
|
|
127
|
-
pydantic.Field(
|
|
127
|
+
pydantic.v1.Field(
|
|
128
128
|
description="Period during which notifications "
|
|
129
129
|
"will not be sent after initial send. The format of this would be in time."
|
|
130
130
|
" e.g. 1d, 3h, 5m, 15s"
|
|
@@ -132,14 +132,14 @@ class AlertNotification(pydantic.BaseModel):
|
|
|
132
132
|
] = None
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
class AlertConfig(pydantic.BaseModel):
|
|
135
|
+
class AlertConfig(pydantic.v1.BaseModel):
|
|
136
136
|
project: str
|
|
137
137
|
id: int = None
|
|
138
138
|
name: str
|
|
139
139
|
description: Optional[str] = ""
|
|
140
140
|
summary: Annotated[
|
|
141
141
|
str,
|
|
142
|
-
pydantic.Field(
|
|
142
|
+
pydantic.v1.Field(
|
|
143
143
|
description=(
|
|
144
144
|
"String to be sent in the notifications generated."
|
|
145
145
|
"e.g. 'Model {{project}}/{{entity}} is drifting.'"
|
|
@@ -153,11 +153,11 @@ class AlertConfig(pydantic.BaseModel):
|
|
|
153
153
|
trigger: AlertTrigger
|
|
154
154
|
criteria: Optional[AlertCriteria]
|
|
155
155
|
reset_policy: ResetPolicy = ResetPolicy.AUTO
|
|
156
|
-
notifications: pydantic.conlist(AlertNotification, min_items=1)
|
|
156
|
+
notifications: pydantic.v1.conlist(AlertNotification, min_items=1)
|
|
157
157
|
state: AlertActiveState = AlertActiveState.INACTIVE
|
|
158
158
|
count: Optional[int] = 0
|
|
159
159
|
|
|
160
|
-
def get_raw_notifications(self) -> list[Notification]:
|
|
160
|
+
def get_raw_notifications(self) -> list[notification_objects.Notification]:
|
|
161
161
|
return [
|
|
162
162
|
alert_notification.notification for alert_notification in self.notifications
|
|
163
163
|
]
|
|
@@ -169,7 +169,7 @@ class AlertsModes(StrEnum):
|
|
|
169
169
|
|
|
170
170
|
|
|
171
171
|
class AlertTemplate(
|
|
172
|
-
pydantic.BaseModel
|
|
172
|
+
pydantic.v1.BaseModel
|
|
173
173
|
): # Template fields that are not shared with created configs
|
|
174
174
|
template_id: int = None
|
|
175
175
|
template_name: str
|
|
@@ -200,3 +200,16 @@ class AlertTemplate(
|
|
|
200
200
|
or self.reset_policy != other.reset_policy
|
|
201
201
|
or self.criteria != other.criteria
|
|
202
202
|
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class AlertActivation(pydantic.v1.BaseModel):
|
|
206
|
+
name: str
|
|
207
|
+
project: str
|
|
208
|
+
severity: AlertSeverity
|
|
209
|
+
activation_time: datetime
|
|
210
|
+
entity_id: str
|
|
211
|
+
entity_kind: EventEntityKind
|
|
212
|
+
criteria: AlertCriteria
|
|
213
|
+
event_kind: EventKind
|
|
214
|
+
number_of_events: int
|
|
215
|
+
notifications: list[notification_objects.NotificationState]
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import typing
|
|
16
16
|
from typing import Optional
|
|
17
17
|
|
|
18
|
-
import pydantic
|
|
18
|
+
import pydantic.v1
|
|
19
19
|
|
|
20
20
|
import mlrun.common.constants as mlrun_constants
|
|
21
21
|
import mlrun.common.types
|
|
@@ -49,9 +49,9 @@ class APIGatewayState(mlrun.common.types.StrEnum):
|
|
|
49
49
|
waiting_for_provisioning = "waitingForProvisioning"
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class _APIGatewayBaseModel(pydantic.BaseModel):
|
|
52
|
+
class _APIGatewayBaseModel(pydantic.v1.BaseModel):
|
|
53
53
|
class Config:
|
|
54
|
-
extra = pydantic.Extra.allow
|
|
54
|
+
extra = pydantic.v1.Extra.allow
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
class APIGatewayMetadata(_APIGatewayBaseModel):
|
mlrun/common/schemas/artifact.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
import typing
|
|
16
16
|
|
|
17
|
-
import pydantic
|
|
17
|
+
import pydantic.v1
|
|
18
18
|
from deprecated import deprecated
|
|
19
19
|
|
|
20
20
|
import mlrun.common.types
|
|
@@ -48,7 +48,7 @@ class ArtifactCategories(mlrun.common.types.StrEnum):
|
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
class ArtifactIdentifier(pydantic.BaseModel):
|
|
51
|
+
class ArtifactIdentifier(pydantic.v1.BaseModel):
|
|
52
52
|
# artifact kind
|
|
53
53
|
kind: typing.Optional[str]
|
|
54
54
|
key: typing.Optional[str]
|
|
@@ -69,7 +69,7 @@ class ArtifactsFormat(mlrun.common.types.StrEnum):
|
|
|
69
69
|
full = "full"
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
class ArtifactMetadata(pydantic.BaseModel):
|
|
72
|
+
class ArtifactMetadata(pydantic.v1.BaseModel):
|
|
73
73
|
key: str
|
|
74
74
|
project: str
|
|
75
75
|
iter: typing.Optional[int]
|
|
@@ -77,10 +77,10 @@ class ArtifactMetadata(pydantic.BaseModel):
|
|
|
77
77
|
tag: typing.Optional[str]
|
|
78
78
|
|
|
79
79
|
class Config:
|
|
80
|
-
extra = pydantic.Extra.allow
|
|
80
|
+
extra = pydantic.v1.Extra.allow
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
class ArtifactSpec(pydantic.BaseModel):
|
|
83
|
+
class ArtifactSpec(pydantic.v1.BaseModel):
|
|
84
84
|
src_path: typing.Optional[str]
|
|
85
85
|
target_path: typing.Optional[str]
|
|
86
86
|
viewer: typing.Optional[str]
|
|
@@ -91,10 +91,10 @@ class ArtifactSpec(pydantic.BaseModel):
|
|
|
91
91
|
unpackaging_instructions: typing.Optional[dict[str, typing.Any]]
|
|
92
92
|
|
|
93
93
|
class Config:
|
|
94
|
-
extra = pydantic.Extra.allow
|
|
94
|
+
extra = pydantic.v1.Extra.allow
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
class Artifact(pydantic.BaseModel):
|
|
97
|
+
class Artifact(pydantic.v1.BaseModel):
|
|
98
98
|
kind: str
|
|
99
99
|
metadata: ArtifactMetadata
|
|
100
100
|
spec: ArtifactSpec
|