mlrun 1.8.0rc16__py3-none-any.whl → 1.8.0rc18__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/artifacts/document.py +9 -4
- mlrun/common/model_monitoring/helpers.py +2 -20
- mlrun/common/schemas/model_monitoring/constants.py +1 -0
- mlrun/config.py +1 -4
- mlrun/datastore/datastore_profile.py +30 -1
- mlrun/db/base.py +1 -1
- mlrun/db/httpdb.py +1 -1
- mlrun/db/nopdb.py +1 -1
- mlrun/execution.py +6 -0
- mlrun/model_monitoring/__init__.py +0 -2
- mlrun/model_monitoring/applications/base.py +72 -29
- mlrun/model_monitoring/applications/context.py +3 -8
- mlrun/model_monitoring/helpers.py +47 -27
- mlrun/model_monitoring/writer.py +0 -53
- mlrun/projects/pipelines.py +2 -1
- mlrun/projects/project.py +20 -3
- mlrun/serving/states.py +6 -3
- mlrun/serving/v2_serving.py +3 -3
- mlrun/utils/notifications/notification_pusher.py +33 -3
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/METADATA +5 -7
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/RECORD +26 -26
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/WHEEL +0 -0
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc16.dist-info → mlrun-1.8.0rc18.dist-info}/top_level.txt +0 -0
mlrun/artifacts/document.py
CHANGED
|
@@ -47,6 +47,7 @@ class DocumentLoaderSpec(ModelObj):
|
|
|
47
47
|
self,
|
|
48
48
|
loader_class_name: str = "langchain_community.document_loaders.TextLoader",
|
|
49
49
|
src_name: str = "file_path",
|
|
50
|
+
download_object: bool = False,
|
|
50
51
|
kwargs: Optional[dict] = None,
|
|
51
52
|
):
|
|
52
53
|
"""
|
|
@@ -56,7 +57,9 @@ class DocumentLoaderSpec(ModelObj):
|
|
|
56
57
|
loader_class_name (str): The name of the loader class to use.
|
|
57
58
|
src_name (str): The source name for the document.
|
|
58
59
|
kwargs (Optional[dict]): Additional keyword arguments to pass to the loader class.
|
|
59
|
-
|
|
60
|
+
download_object (bool, optional): If True, the file will be downloaded before launching
|
|
61
|
+
the loader. If False, the loader accepts a link that should not be downloaded.
|
|
62
|
+
Defaults to False.
|
|
60
63
|
Example:
|
|
61
64
|
>>> # Create a loader specification for PDF documents
|
|
62
65
|
>>> loader_spec = DocumentLoaderSpec(
|
|
@@ -72,6 +75,7 @@ class DocumentLoaderSpec(ModelObj):
|
|
|
72
75
|
"""
|
|
73
76
|
self.loader_class_name = loader_class_name
|
|
74
77
|
self.src_name = src_name
|
|
78
|
+
self.download_object = download_object
|
|
75
79
|
self.kwargs = kwargs
|
|
76
80
|
|
|
77
81
|
def make_loader(self, src_path):
|
|
@@ -251,6 +255,9 @@ class DocumentArtifact(Artifact):
|
|
|
251
255
|
"collections",
|
|
252
256
|
"original_source",
|
|
253
257
|
]
|
|
258
|
+
_exclude_fields_from_uid_hash = ArtifactSpec._exclude_fields_from_uid_hash + [
|
|
259
|
+
"collections",
|
|
260
|
+
]
|
|
254
261
|
|
|
255
262
|
def __init__(
|
|
256
263
|
self,
|
|
@@ -270,7 +277,6 @@ class DocumentArtifact(Artifact):
|
|
|
270
277
|
METADATA_SOURCE_KEY = "source"
|
|
271
278
|
METADATA_ORIGINAL_SOURCE_KEY = "original_source"
|
|
272
279
|
METADATA_CHUNK_KEY = "mlrun_chunk"
|
|
273
|
-
METADATA_ARTIFACT_URI_KEY = "mlrun_object_uri"
|
|
274
280
|
METADATA_ARTIFACT_TARGET_PATH_KEY = "mlrun_target_path"
|
|
275
281
|
METADATA_ARTIFACT_TAG = "mlrun_tag"
|
|
276
282
|
METADATA_ARTIFACT_KEY = "mlrun_key"
|
|
@@ -321,7 +327,7 @@ class DocumentArtifact(Artifact):
|
|
|
321
327
|
"""
|
|
322
328
|
|
|
323
329
|
loader_spec = DocumentLoaderSpec.from_dict(self.spec.document_loader)
|
|
324
|
-
if self.get_target_path():
|
|
330
|
+
if loader_spec.download_object and self.get_target_path():
|
|
325
331
|
with tempfile.NamedTemporaryFile() as tmp_file:
|
|
326
332
|
mlrun.datastore.store_manager.object(
|
|
327
333
|
url=self.get_target_path()
|
|
@@ -348,7 +354,6 @@ class DocumentArtifact(Artifact):
|
|
|
348
354
|
|
|
349
355
|
metadata[self.METADATA_ORIGINAL_SOURCE_KEY] = self.spec.original_source
|
|
350
356
|
metadata[self.METADATA_SOURCE_KEY] = self.get_source()
|
|
351
|
-
metadata[self.METADATA_ARTIFACT_URI_KEY] = self.uri
|
|
352
357
|
metadata[self.METADATA_ARTIFACT_TAG] = self.tag or "latest"
|
|
353
358
|
metadata[self.METADATA_ARTIFACT_KEY] = self.key
|
|
354
359
|
metadata[self.METADATA_ARTIFACT_PROJECT] = self.metadata.project
|
|
@@ -38,12 +38,10 @@ def parse_model_endpoint_store_prefix(store_prefix: str):
|
|
|
38
38
|
|
|
39
39
|
def parse_monitoring_stream_path(
|
|
40
40
|
stream_uri: str, project: str, function_name: typing.Optional[str] = None
|
|
41
|
-
):
|
|
41
|
+
) -> str:
|
|
42
42
|
if stream_uri.startswith("kafka://"):
|
|
43
43
|
if "?topic" in stream_uri:
|
|
44
|
-
raise mlrun.errors.
|
|
45
|
-
"Custom kafka topic is not allowed"
|
|
46
|
-
)
|
|
44
|
+
raise mlrun.errors.MLRunValueError("Custom kafka topic is not allowed")
|
|
47
45
|
# Add topic to stream kafka uri
|
|
48
46
|
if (
|
|
49
47
|
function_name is None
|
|
@@ -53,22 +51,6 @@ def parse_monitoring_stream_path(
|
|
|
53
51
|
else:
|
|
54
52
|
stream_uri += f"?topic=monitoring_stream_{project}_{function_name}"
|
|
55
53
|
|
|
56
|
-
elif stream_uri.startswith("v3io://") and mlrun.mlconf.is_ce_mode():
|
|
57
|
-
# V3IO is not supported in CE mode, generating a default http stream path
|
|
58
|
-
if function_name is None:
|
|
59
|
-
stream_uri = (
|
|
60
|
-
mlrun.mlconf.model_endpoint_monitoring.default_http_sink.format(
|
|
61
|
-
project=project, namespace=mlrun.mlconf.namespace
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
|
-
else:
|
|
65
|
-
stream_uri = (
|
|
66
|
-
mlrun.mlconf.model_endpoint_monitoring.default_http_sink_app.format(
|
|
67
|
-
project=project,
|
|
68
|
-
application_name=function_name,
|
|
69
|
-
namespace=mlrun.mlconf.namespace,
|
|
70
|
-
)
|
|
71
|
-
)
|
|
72
54
|
return stream_uri
|
|
73
55
|
|
|
74
56
|
|
mlrun/config.py
CHANGED
|
@@ -169,6 +169,7 @@ default_config = {
|
|
|
169
169
|
"max_chunk_size": 1024 * 1024 * 1, # 1MB
|
|
170
170
|
"max_preview_size": 1024 * 1024 * 10, # 10MB
|
|
171
171
|
"max_download_size": 1024 * 1024 * 100, # 100MB
|
|
172
|
+
"max_deletions": 200,
|
|
172
173
|
},
|
|
173
174
|
},
|
|
174
175
|
# FIXME: Adding these defaults here so we won't need to patch the "installing component" (provazio-controller) to
|
|
@@ -603,10 +604,6 @@ default_config = {
|
|
|
603
604
|
# Offline storage path can be either relative or a full path. This path is used for general offline data
|
|
604
605
|
# storage such as the parquet file which is generated from the monitoring stream function for the drift analysis
|
|
605
606
|
"offline_storage_path": "model-endpoints/{kind}",
|
|
606
|
-
# Default http path that points to the monitoring stream nuclio function. Will be used as a stream path
|
|
607
|
-
# when the user is working in CE environment and has not provided any stream path.
|
|
608
|
-
"default_http_sink": "http://nuclio-{project}-model-monitoring-stream.{namespace}.svc.cluster.local:8080",
|
|
609
|
-
"default_http_sink_app": "http://nuclio-{project}-{application_name}.{namespace}.svc.cluster.local:8080",
|
|
610
607
|
"parquet_batching_max_events": 10_000,
|
|
611
608
|
"parquet_batching_timeout_secs": timedelta(minutes=1).total_seconds(),
|
|
612
609
|
# See mlrun.model_monitoring.db.tsdb.ObjectTSDBFactory for available options
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
import ast
|
|
16
16
|
import base64
|
|
17
17
|
import json
|
|
@@ -549,6 +549,35 @@ class DatastoreProfile2Json(pydantic.v1.BaseModel):
|
|
|
549
549
|
|
|
550
550
|
|
|
551
551
|
def datastore_profile_read(url, project_name="", secrets: typing.Optional[dict] = None):
|
|
552
|
+
"""
|
|
553
|
+
Read and retrieve a datastore profile from a given URL.
|
|
554
|
+
|
|
555
|
+
This function retrieves a datastore profile either from temporary client storage,
|
|
556
|
+
or from the MLRun database. It handles both client-side and server-side profile formats
|
|
557
|
+
and performs necessary conversions.
|
|
558
|
+
|
|
559
|
+
Args:
|
|
560
|
+
url (str): A URL with 'ds' scheme pointing to the datastore profile
|
|
561
|
+
(e.g., 'ds://profile-name').
|
|
562
|
+
project_name (str, optional): The project name where the profile is stored.
|
|
563
|
+
Defaults to MLRun's default project.
|
|
564
|
+
secrets (dict, optional): Dictionary containing secrets needed for profile retrieval.
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
DatastoreProfile: The retrieved datastore profile object.
|
|
568
|
+
|
|
569
|
+
Raises:
|
|
570
|
+
MLRunInvalidArgumentError: In the following cases:
|
|
571
|
+
- If the URL scheme is not 'ds'
|
|
572
|
+
- If the profile cannot be retrieved from either server or local environment
|
|
573
|
+
|
|
574
|
+
Note:
|
|
575
|
+
When running from a client environment (outside MLRun pods), private profile information
|
|
576
|
+
is not accessible. In this case, use register_temporary_client_datastore_profile() to
|
|
577
|
+
register the profile with credentials for your local session. When running inside MLRun
|
|
578
|
+
pods, the private information is automatically available and no temporary registration is needed.
|
|
579
|
+
"""
|
|
580
|
+
|
|
552
581
|
parsed_url = urlparse(url)
|
|
553
582
|
if parsed_url.scheme.lower() != "ds":
|
|
554
583
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
mlrun/db/base.py
CHANGED
mlrun/db/httpdb.py
CHANGED
mlrun/db/nopdb.py
CHANGED
mlrun/execution.py
CHANGED
|
@@ -884,6 +884,7 @@ class MLClientCtx:
|
|
|
884
884
|
upload: Optional[bool] = False,
|
|
885
885
|
labels: Optional[dict[str, str]] = None,
|
|
886
886
|
target_path: Optional[str] = None,
|
|
887
|
+
db_key: Optional[str] = None,
|
|
887
888
|
**kwargs,
|
|
888
889
|
) -> DocumentArtifact:
|
|
889
890
|
"""
|
|
@@ -914,6 +915,8 @@ class MLClientCtx:
|
|
|
914
915
|
:param upload: Whether to upload the artifact
|
|
915
916
|
:param labels: Key-value labels
|
|
916
917
|
:param target_path: Path to the local file
|
|
918
|
+
:param db_key: The key to use in the artifact DB table, by default its run name + '_' + key
|
|
919
|
+
db_key=False will not register it in the artifacts table
|
|
917
920
|
:param kwargs: Additional keyword arguments
|
|
918
921
|
:return: DocumentArtifact object
|
|
919
922
|
|
|
@@ -943,6 +946,9 @@ class MLClientCtx:
|
|
|
943
946
|
tag=tag,
|
|
944
947
|
upload=upload,
|
|
945
948
|
labels=labels,
|
|
949
|
+
local_path=local_path,
|
|
950
|
+
target_path=target_path,
|
|
951
|
+
db_key=db_key,
|
|
946
952
|
)
|
|
947
953
|
self._update_run()
|
|
948
954
|
return item
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
import socket
|
|
16
16
|
from abc import ABC, abstractmethod
|
|
17
|
-
from
|
|
17
|
+
from collections.abc import Iterator
|
|
18
|
+
from datetime import datetime, timedelta
|
|
18
19
|
from typing import Any, Optional, Union, cast
|
|
19
20
|
|
|
20
21
|
import pandas as pd
|
|
@@ -93,9 +94,10 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
93
94
|
context: "mlrun.MLClientCtx",
|
|
94
95
|
sample_data: Optional[pd.DataFrame] = None,
|
|
95
96
|
reference_data: Optional[pd.DataFrame] = None,
|
|
96
|
-
|
|
97
|
+
endpoints: Optional[list[tuple[str, str]]] = None,
|
|
97
98
|
start: Optional[datetime] = None,
|
|
98
99
|
end: Optional[datetime] = None,
|
|
100
|
+
base_period: Optional[int] = None,
|
|
99
101
|
):
|
|
100
102
|
"""
|
|
101
103
|
A custom handler that wraps the application's logic implemented in
|
|
@@ -121,32 +123,60 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
121
123
|
)
|
|
122
124
|
return self.do_tracking(monitoring_context)
|
|
123
125
|
|
|
124
|
-
if
|
|
125
|
-
start, end = self._validate_times(start, end)
|
|
126
|
-
for
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
if endpoints is not None:
|
|
127
|
+
start, end = self._validate_times(start, end, base_period)
|
|
128
|
+
for window_start, window_end in self._window_generator(
|
|
129
|
+
start, end, base_period
|
|
130
|
+
):
|
|
131
|
+
for endpoint_name, endpoint_id in endpoints:
|
|
132
|
+
result = call_do_tracking(
|
|
133
|
+
event={
|
|
134
|
+
mm_constants.ApplicationEvent.ENDPOINT_NAME: endpoint_name,
|
|
135
|
+
mm_constants.ApplicationEvent.ENDPOINT_ID: endpoint_id,
|
|
136
|
+
mm_constants.ApplicationEvent.START_INFER_TIME: window_start,
|
|
137
|
+
mm_constants.ApplicationEvent.END_INFER_TIME: window_end,
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
context.log_result(
|
|
141
|
+
f"{endpoint_name}_{window_start.isoformat()}_{window_end.isoformat()}",
|
|
142
|
+
result,
|
|
143
|
+
)
|
|
137
144
|
else:
|
|
138
145
|
return call_do_tracking()
|
|
139
146
|
|
|
140
147
|
@staticmethod
|
|
141
148
|
def _validate_times(
|
|
142
|
-
start: Optional[datetime],
|
|
149
|
+
start: Optional[datetime],
|
|
150
|
+
end: Optional[datetime],
|
|
151
|
+
base_period: Optional[int],
|
|
143
152
|
) -> tuple[datetime, datetime]:
|
|
144
153
|
if (start is None) or (end is None):
|
|
145
154
|
raise mlrun.errors.MLRunValueError(
|
|
146
155
|
"When `endpoint_names` is provided, you must also pass the start and end times"
|
|
147
156
|
)
|
|
157
|
+
if (base_period is not None) and not (
|
|
158
|
+
isinstance(base_period, int) and base_period > 0
|
|
159
|
+
):
|
|
160
|
+
raise mlrun.errors.MLRunValueError(
|
|
161
|
+
"`base_period` must be a nonnegative integer - the number of minutes in a monitoring window"
|
|
162
|
+
)
|
|
148
163
|
return start, end
|
|
149
164
|
|
|
165
|
+
@staticmethod
|
|
166
|
+
def _window_generator(
|
|
167
|
+
start: datetime, end: datetime, base_period: Optional[int]
|
|
168
|
+
) -> Iterator[tuple[datetime, datetime]]:
|
|
169
|
+
if base_period is None:
|
|
170
|
+
yield start, end
|
|
171
|
+
return
|
|
172
|
+
|
|
173
|
+
window_length = timedelta(minutes=base_period)
|
|
174
|
+
current_start_time = start
|
|
175
|
+
while current_start_time < end:
|
|
176
|
+
current_end_time = min(current_start_time + window_length, end)
|
|
177
|
+
yield current_start_time, current_end_time
|
|
178
|
+
current_start_time = current_end_time
|
|
179
|
+
|
|
150
180
|
@classmethod
|
|
151
181
|
def deploy(
|
|
152
182
|
cls,
|
|
@@ -199,31 +229,39 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
199
229
|
with_repo: Optional[bool] = False,
|
|
200
230
|
requirements: Optional[Union[str, list[str]]] = None,
|
|
201
231
|
requirements_file: str = "",
|
|
202
|
-
|
|
232
|
+
endpoints: Optional[list[tuple[str, str]]] = None,
|
|
203
233
|
start: Optional[datetime] = None,
|
|
204
234
|
end: Optional[datetime] = None,
|
|
235
|
+
base_period: Optional[int] = None,
|
|
205
236
|
) -> "mlrun.RunObject":
|
|
206
237
|
"""
|
|
207
238
|
Call this function to run the application's
|
|
208
239
|
:py:meth:`~mlrun.model_monitoring.applications.ModelMonitoringApplicationBase.do_tracking`
|
|
209
240
|
model monitoring logic as a :py:class:`~mlrun.runtimes.KubejobRuntime`, which is an MLRun function.
|
|
210
241
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
:param
|
|
215
|
-
:param
|
|
242
|
+
This method has default values for all of its arguments. You should be change them when you want to pass
|
|
243
|
+
data to the application.
|
|
244
|
+
|
|
245
|
+
:param func_path: The path to the function. If ``None``, the current notebook is used.
|
|
246
|
+
:param func_name: The name of the function. If not ``None``, the class name is used.
|
|
247
|
+
:param tag: Tag for the function.
|
|
248
|
+
:param run_local: Whether to run the function locally or remotely.
|
|
249
|
+
:param sample_data: Pandas data-frame as the current dataset.
|
|
216
250
|
When set, it replaces the data read from the model endpoint's offline source.
|
|
217
|
-
:param reference_data:
|
|
251
|
+
:param reference_data: Pandas data-frame of the reference dataset.
|
|
218
252
|
When set, its statistics override the model endpoint's feature statistics.
|
|
219
253
|
:param image: Docker image to run the job on.
|
|
220
254
|
:param with_repo: Whether to clone the current repo to the build source.
|
|
221
255
|
:param requirements: List of Python requirements to be installed in the image.
|
|
222
256
|
:param requirements_file: Path to a Python requirements file to be installed in the image.
|
|
223
|
-
:param
|
|
224
|
-
you have to provide also the start and end times of the data to analyze.
|
|
257
|
+
:param endpoints: A list of tuples of the model endpoint (name, uid) to get the data from.
|
|
258
|
+
If provided, you have to provide also the start and end times of the data to analyze.
|
|
225
259
|
:param start: The start time of the sample data.
|
|
226
260
|
:param end: The end time of the sample data.
|
|
261
|
+
:param base_period: The window length in minutes. If ``None``, the whole window from ``start`` to ``end``
|
|
262
|
+
is taken. If an integer is specified, the application is run from ``start`` to ``end``
|
|
263
|
+
in ``base_period`` length windows, except for the last window that ends at ``end`` and
|
|
264
|
+
therefore may be shorter.
|
|
227
265
|
|
|
228
266
|
:returns: The output of the
|
|
229
267
|
:py:meth:`~mlrun.model_monitoring.applications.ModelMonitoringApplicationBase.do_tracking`
|
|
@@ -249,12 +287,17 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
249
287
|
),
|
|
250
288
|
)
|
|
251
289
|
|
|
252
|
-
params: dict[str, Union[list[str], datetime]] = {}
|
|
253
|
-
if
|
|
254
|
-
start, end = cls._validate_times(start, end)
|
|
255
|
-
params["
|
|
290
|
+
params: dict[str, Union[list[tuple[str, str]], datetime, int, None]] = {}
|
|
291
|
+
if endpoints:
|
|
292
|
+
start, end = cls._validate_times(start, end, base_period)
|
|
293
|
+
params["endpoints"] = endpoints
|
|
256
294
|
params["start"] = start
|
|
257
295
|
params["end"] = end
|
|
296
|
+
params["base_period"] = base_period
|
|
297
|
+
elif start or end or base_period:
|
|
298
|
+
raise mlrun.errors.MLRunValueError(
|
|
299
|
+
"Custom start and end times or base_period are supported only with endpoints data"
|
|
300
|
+
)
|
|
258
301
|
|
|
259
302
|
inputs: dict[str, str] = {}
|
|
260
303
|
for data, identifier in [
|
|
@@ -190,18 +190,13 @@ class MonitoringApplicationContext:
|
|
|
190
190
|
)
|
|
191
191
|
|
|
192
192
|
def _get_default_labels(self) -> dict[str, str]:
|
|
193
|
-
|
|
193
|
+
return {
|
|
194
194
|
mlrun_constants.MLRunInternalLabels.runner_pod: socket.gethostname(),
|
|
195
195
|
mlrun_constants.MLRunInternalLabels.producer_type: "model-monitoring-app",
|
|
196
196
|
mlrun_constants.MLRunInternalLabels.app_name: self.application_name,
|
|
197
|
+
mlrun_constants.MLRunInternalLabels.endpoint_id: self.endpoint_id,
|
|
198
|
+
mlrun_constants.MLRunInternalLabels.endpoint_name: self.endpoint_name,
|
|
197
199
|
}
|
|
198
|
-
for key, value in [
|
|
199
|
-
(mlrun_constants.MLRunInternalLabels.endpoint_id, self.endpoint_id),
|
|
200
|
-
(mlrun_constants.MLRunInternalLabels.endpoint_name, self.endpoint_name),
|
|
201
|
-
]:
|
|
202
|
-
if value:
|
|
203
|
-
labels[key] = value
|
|
204
|
-
return labels
|
|
205
200
|
|
|
206
201
|
def _add_default_labels(self, labels: Optional[dict[str, str]]) -> dict[str, str]:
|
|
207
202
|
"""Add the default labels to logged artifacts labels"""
|
|
@@ -13,20 +13,14 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import datetime
|
|
16
|
+
import functools
|
|
16
17
|
import os
|
|
17
|
-
import
|
|
18
|
+
from fnmatch import fnmatchcase
|
|
19
|
+
from typing import TYPE_CHECKING, Callable, Optional, TypedDict, cast
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
20
22
|
import pandas as pd
|
|
21
23
|
|
|
22
|
-
if typing.TYPE_CHECKING:
|
|
23
|
-
from mlrun.datastore import DataItem
|
|
24
|
-
from mlrun.db.base import RunDBInterface
|
|
25
|
-
from mlrun.projects import MlrunProject
|
|
26
|
-
|
|
27
|
-
from fnmatch import fnmatchcase
|
|
28
|
-
from typing import Optional
|
|
29
|
-
|
|
30
24
|
import mlrun
|
|
31
25
|
import mlrun.artifacts
|
|
32
26
|
import mlrun.common.model_monitoring.helpers
|
|
@@ -42,8 +36,13 @@ from mlrun.common.schemas.model_monitoring.model_endpoints import (
|
|
|
42
36
|
)
|
|
43
37
|
from mlrun.utils import logger
|
|
44
38
|
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from mlrun.datastore import DataItem
|
|
41
|
+
from mlrun.db.base import RunDBInterface
|
|
42
|
+
from mlrun.projects import MlrunProject
|
|
43
|
+
|
|
45
44
|
|
|
46
|
-
class _BatchDict(
|
|
45
|
+
class _BatchDict(TypedDict):
|
|
47
46
|
minutes: int
|
|
48
47
|
hours: int
|
|
49
48
|
days: int
|
|
@@ -116,20 +115,30 @@ def filter_results_by_regex(
|
|
|
116
115
|
def get_stream_path(
|
|
117
116
|
project: str,
|
|
118
117
|
function_name: str = mm_constants.MonitoringFunctionNames.STREAM,
|
|
119
|
-
stream_uri:
|
|
118
|
+
stream_uri: Optional[str] = None,
|
|
119
|
+
secret_provider: Optional[Callable[[str], str]] = None,
|
|
120
120
|
) -> str:
|
|
121
121
|
"""
|
|
122
122
|
Get stream path from the project secret. If wasn't set, take it from the system configurations
|
|
123
123
|
|
|
124
124
|
:param project: Project name.
|
|
125
125
|
:param function_name: Application name. Default is model_monitoring_stream.
|
|
126
|
-
:param stream_uri: Stream URI. If provided, it will be used instead of the one from the project secret.
|
|
127
|
-
|
|
126
|
+
:param stream_uri: Stream URI. If provided, it will be used instead of the one from the project's secret.
|
|
127
|
+
:param secret_provider: Optional secret provider to get the connection string secret.
|
|
128
|
+
If not set, the env vars are used.
|
|
128
129
|
:return: Monitoring stream path to the relevant application.
|
|
129
130
|
"""
|
|
130
131
|
|
|
132
|
+
try:
|
|
133
|
+
profile = _get_stream_profile(project=project, secret_provider=secret_provider)
|
|
134
|
+
except mlrun.errors.MLRunNotFoundError:
|
|
135
|
+
profile = None
|
|
136
|
+
|
|
137
|
+
if isinstance(profile, mlrun.datastore.datastore_profile.DatastoreProfileV3io):
|
|
138
|
+
stream_uri = "v3io"
|
|
139
|
+
|
|
131
140
|
stream_uri = stream_uri or mlrun.get_secret_or_env(
|
|
132
|
-
mm_constants.ProjectSecretKeys.STREAM_PATH
|
|
141
|
+
key=mm_constants.ProjectSecretKeys.STREAM_PATH, secret_provider=secret_provider
|
|
133
142
|
)
|
|
134
143
|
|
|
135
144
|
if not stream_uri or stream_uri == "v3io":
|
|
@@ -231,7 +240,7 @@ def get_monitoring_drift_measures_data(project: str, endpoint_id: str) -> "DataI
|
|
|
231
240
|
|
|
232
241
|
|
|
233
242
|
def get_tsdb_connection_string(
|
|
234
|
-
secret_provider:
|
|
243
|
+
secret_provider: Optional[Callable[[str], str]] = None,
|
|
235
244
|
) -> str:
|
|
236
245
|
"""Get TSDB connection string from the project secret. If wasn't set, take it from the system
|
|
237
246
|
configurations.
|
|
@@ -245,29 +254,40 @@ def get_tsdb_connection_string(
|
|
|
245
254
|
)
|
|
246
255
|
|
|
247
256
|
|
|
248
|
-
def
|
|
249
|
-
project: str
|
|
250
|
-
secret_provider:
|
|
257
|
+
def _get_profile(
|
|
258
|
+
project: str,
|
|
259
|
+
secret_provider: Optional[Callable[[str], str]],
|
|
260
|
+
profile_name_key: str,
|
|
251
261
|
) -> mlrun.datastore.datastore_profile.DatastoreProfile:
|
|
252
262
|
"""
|
|
253
|
-
Get
|
|
263
|
+
Get the datastore profile from the project name and secret provider, where the profile's name
|
|
264
|
+
is saved as a secret named `profile_name_key`.
|
|
254
265
|
|
|
255
|
-
:param project:
|
|
256
|
-
:param secret_provider:
|
|
257
|
-
|
|
258
|
-
:return:
|
|
266
|
+
:param project: The project name.
|
|
267
|
+
:param secret_provider: Secret provider to get the secrets from, or `None` for env vars.
|
|
268
|
+
:param profile_name_key: The profile name key in the secret store.
|
|
269
|
+
:return: Datastore profile.
|
|
259
270
|
"""
|
|
260
271
|
profile_name = mlrun.get_secret_or_env(
|
|
261
|
-
key=
|
|
262
|
-
secret_provider=secret_provider,
|
|
272
|
+
key=profile_name_key, secret_provider=secret_provider
|
|
263
273
|
)
|
|
264
274
|
if not profile_name:
|
|
265
|
-
raise mlrun.errors.MLRunNotFoundError(
|
|
275
|
+
raise mlrun.errors.MLRunNotFoundError(
|
|
276
|
+
f"Not found `{profile_name_key}` profile name"
|
|
277
|
+
)
|
|
266
278
|
return mlrun.datastore.datastore_profile.datastore_profile_read(
|
|
267
279
|
url=f"ds://{profile_name}", project_name=project, secrets=secret_provider
|
|
268
280
|
)
|
|
269
281
|
|
|
270
282
|
|
|
283
|
+
_get_tsdb_profile = functools.partial(
|
|
284
|
+
_get_profile, profile_name_key=mm_constants.ProjectSecretKeys.TSDB_PROFILE_NAME
|
|
285
|
+
)
|
|
286
|
+
_get_stream_profile = functools.partial(
|
|
287
|
+
_get_profile, profile_name_key=mm_constants.ProjectSecretKeys.STREAM_PROFILE_NAME
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
271
291
|
def batch_dict2timedelta(batch_dict: _BatchDict) -> datetime.timedelta:
|
|
272
292
|
"""
|
|
273
293
|
Convert a batch dictionary to timedelta.
|
|
@@ -455,7 +475,7 @@ def get_invocations_metric(project: str) -> ModelEndpointMonitoringMetric:
|
|
|
455
475
|
|
|
456
476
|
|
|
457
477
|
def _get_monitoring_schedules_folder_path(project: str) -> str:
|
|
458
|
-
return
|
|
478
|
+
return cast(
|
|
459
479
|
str,
|
|
460
480
|
mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
461
481
|
project=project, kind=mm_constants.FileTargetKind.MONITORING_SCHEDULES
|
mlrun/model_monitoring/writer.py
CHANGED
|
@@ -31,7 +31,6 @@ from mlrun.common.schemas.model_monitoring.constants import (
|
|
|
31
31
|
WriterEvent,
|
|
32
32
|
WriterEventKind,
|
|
33
33
|
)
|
|
34
|
-
from mlrun.common.schemas.notification import NotificationKind, NotificationSeverity
|
|
35
34
|
from mlrun.model_monitoring.db._stats import (
|
|
36
35
|
ModelMonitoringCurrentStatsFile,
|
|
37
36
|
ModelMonitoringDriftMeasuresFile,
|
|
@@ -39,7 +38,6 @@ from mlrun.model_monitoring.db._stats import (
|
|
|
39
38
|
from mlrun.model_monitoring.helpers import get_result_instance_fqn
|
|
40
39
|
from mlrun.serving.utils import StepToDict
|
|
41
40
|
from mlrun.utils import logger
|
|
42
|
-
from mlrun.utils.notifications.notification_pusher import CustomNotificationPusher
|
|
43
41
|
|
|
44
42
|
_RawEvent = dict[str, Any]
|
|
45
43
|
_AppResultEvent = NewType("_AppResultEvent", _RawEvent)
|
|
@@ -57,50 +55,6 @@ class _WriterEventTypeError(_WriterEventError, TypeError):
|
|
|
57
55
|
pass
|
|
58
56
|
|
|
59
57
|
|
|
60
|
-
class _Notifier:
|
|
61
|
-
def __init__(
|
|
62
|
-
self,
|
|
63
|
-
event: _AppResultEvent,
|
|
64
|
-
notification_pusher: CustomNotificationPusher,
|
|
65
|
-
severity: NotificationSeverity = NotificationSeverity.WARNING,
|
|
66
|
-
) -> None:
|
|
67
|
-
"""
|
|
68
|
-
Event notifier - send push notification when appropriate to the notifiers in
|
|
69
|
-
`notification pusher`.
|
|
70
|
-
Note that if you use a Slack App webhook, you need to define it as an MLRun secret
|
|
71
|
-
`SLACK_WEBHOOK`.
|
|
72
|
-
"""
|
|
73
|
-
self._event = event
|
|
74
|
-
self._custom_notifier = notification_pusher
|
|
75
|
-
self._severity = severity
|
|
76
|
-
|
|
77
|
-
def _should_send_event(self) -> bool:
|
|
78
|
-
return self._event[ResultData.RESULT_STATUS] >= ResultStatusApp.detected.value
|
|
79
|
-
|
|
80
|
-
def _generate_message(self) -> str:
|
|
81
|
-
return f"""\
|
|
82
|
-
The monitoring app `{self._event[WriterEvent.APPLICATION_NAME]}` \
|
|
83
|
-
of kind `{self._event[ResultData.RESULT_KIND]}` \
|
|
84
|
-
detected a problem in model endpoint ID `{self._event[WriterEvent.ENDPOINT_ID]}` \
|
|
85
|
-
at time `{self._event[WriterEvent.START_INFER_TIME]}`.
|
|
86
|
-
|
|
87
|
-
Result data:
|
|
88
|
-
Name: `{self._event[ResultData.RESULT_NAME]}`
|
|
89
|
-
Value: `{self._event[ResultData.RESULT_VALUE]}`
|
|
90
|
-
Status: `{self._event[ResultData.RESULT_STATUS]}`
|
|
91
|
-
Extra data: `{self._event[ResultData.RESULT_EXTRA_DATA]}`\
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
def notify(self) -> None:
|
|
95
|
-
"""Send notification if appropriate"""
|
|
96
|
-
if not self._should_send_event():
|
|
97
|
-
logger.debug("Not sending a notification")
|
|
98
|
-
return
|
|
99
|
-
message = self._generate_message()
|
|
100
|
-
self._custom_notifier.push(message=message, severity=self._severity)
|
|
101
|
-
logger.debug("A notification should have been sent")
|
|
102
|
-
|
|
103
|
-
|
|
104
58
|
class ModelMonitoringWriter(StepToDict):
|
|
105
59
|
"""
|
|
106
60
|
Write monitoring application results to the target databases
|
|
@@ -116,10 +70,6 @@ class ModelMonitoringWriter(StepToDict):
|
|
|
116
70
|
self.project = project
|
|
117
71
|
self.name = project # required for the deployment process
|
|
118
72
|
|
|
119
|
-
self._custom_notifier = CustomNotificationPusher(
|
|
120
|
-
notification_types=[NotificationKind.slack]
|
|
121
|
-
)
|
|
122
|
-
|
|
123
73
|
self._tsdb_connector = mlrun.model_monitoring.get_tsdb_connector(
|
|
124
74
|
project=self.project, secret_provider=secret_provider
|
|
125
75
|
)
|
|
@@ -250,9 +200,6 @@ class ModelMonitoringWriter(StepToDict):
|
|
|
250
200
|
|
|
251
201
|
logger.info("Completed event DB writes")
|
|
252
202
|
|
|
253
|
-
if kind == WriterEventKind.RESULT:
|
|
254
|
-
_Notifier(event=event, notification_pusher=self._custom_notifier).notify()
|
|
255
|
-
|
|
256
203
|
if (
|
|
257
204
|
mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.enabled
|
|
258
205
|
and kind == WriterEventKind.RESULT
|
mlrun/projects/pipelines.py
CHANGED
|
@@ -748,7 +748,8 @@ class _LocalRunner(_PipelineRunner):
|
|
|
748
748
|
project.set_source(source=source)
|
|
749
749
|
pipeline_context.workflow_artifact_path = artifact_path
|
|
750
750
|
|
|
751
|
-
|
|
751
|
+
# TODO: we should create endpoint for sending custom notification from BE
|
|
752
|
+
project.notifiers.push_pipeline_start_message_from_client(
|
|
752
753
|
project.metadata.name, pipeline_id=workflow_id
|
|
753
754
|
)
|
|
754
755
|
err = None
|
mlrun/projects/project.py
CHANGED
|
@@ -1962,6 +1962,11 @@ class MlrunProject(ModelObj):
|
|
|
1962
1962
|
... )
|
|
1963
1963
|
|
|
1964
1964
|
"""
|
|
1965
|
+
if not document_loader_spec.download_object and upload:
|
|
1966
|
+
raise ValueError(
|
|
1967
|
+
"This document loader expects direct links/URLs and does not support file uploads. "
|
|
1968
|
+
"Either set download_object=True or set upload=False"
|
|
1969
|
+
)
|
|
1965
1970
|
doc_artifact = DocumentArtifact(
|
|
1966
1971
|
key=key,
|
|
1967
1972
|
original_source=local_path or target_path,
|
|
@@ -3603,17 +3608,29 @@ class MlrunProject(ModelObj):
|
|
|
3603
3608
|
"""
|
|
3604
3609
|
db = mlrun.db.get_run_db(secrets=self._secrets)
|
|
3605
3610
|
if tsdb_connection == "v3io":
|
|
3606
|
-
|
|
3611
|
+
tsdb_profile = mlrun.datastore.datastore_profile.DatastoreProfileV3io(
|
|
3607
3612
|
name="mm-infra-tsdb"
|
|
3608
3613
|
)
|
|
3609
|
-
self.register_datastore_profile(
|
|
3614
|
+
self.register_datastore_profile(tsdb_profile)
|
|
3615
|
+
tsdb_profile_name = tsdb_profile.name
|
|
3616
|
+
else:
|
|
3617
|
+
tsdb_profile_name = None
|
|
3618
|
+
if stream_path == "v3io":
|
|
3619
|
+
stream_profile = mlrun.datastore.datastore_profile.DatastoreProfileV3io(
|
|
3620
|
+
name="mm-infra-stream"
|
|
3621
|
+
)
|
|
3622
|
+
self.register_datastore_profile(stream_profile)
|
|
3623
|
+
stream_profile_name = stream_profile.name
|
|
3624
|
+
else:
|
|
3625
|
+
stream_profile_name = None
|
|
3610
3626
|
db.set_model_monitoring_credentials(
|
|
3611
3627
|
project=self.name,
|
|
3612
3628
|
credentials={
|
|
3613
3629
|
"access_key": access_key,
|
|
3614
3630
|
"stream_path": stream_path,
|
|
3615
3631
|
"tsdb_connection": tsdb_connection,
|
|
3616
|
-
"tsdb_profile_name":
|
|
3632
|
+
"tsdb_profile_name": tsdb_profile_name,
|
|
3633
|
+
"stream_profile_name": stream_profile_name,
|
|
3617
3634
|
},
|
|
3618
3635
|
replace_creds=replace_creds,
|
|
3619
3636
|
)
|
mlrun/serving/states.py
CHANGED
|
@@ -126,6 +126,9 @@ class BaseStep(ModelObj):
|
|
|
126
126
|
self.shape = shape
|
|
127
127
|
self.on_error = None
|
|
128
128
|
self._on_error_handler = None
|
|
129
|
+
self.model_endpoint_creation_strategy = (
|
|
130
|
+
schemas.ModelEndpointCreationStrategy.SKIP
|
|
131
|
+
)
|
|
129
132
|
|
|
130
133
|
def get_shape(self):
|
|
131
134
|
"""graphviz shape"""
|
|
@@ -697,7 +700,7 @@ class RouterStep(TaskStep):
|
|
|
697
700
|
|
|
698
701
|
kind = "router"
|
|
699
702
|
default_shape = "doubleoctagon"
|
|
700
|
-
_dict_fields = _task_step_fields + ["routes"]
|
|
703
|
+
_dict_fields = _task_step_fields + ["routes", "name"]
|
|
701
704
|
_default_class = "mlrun.serving.ModelRouter"
|
|
702
705
|
|
|
703
706
|
def __init__(
|
|
@@ -715,7 +718,7 @@ class RouterStep(TaskStep):
|
|
|
715
718
|
class_name,
|
|
716
719
|
class_args,
|
|
717
720
|
handler,
|
|
718
|
-
name=name,
|
|
721
|
+
name=get_name(name, class_name or RouterStep.kind),
|
|
719
722
|
function=function,
|
|
720
723
|
input_path=input_path,
|
|
721
724
|
result_path=result_path,
|
|
@@ -1704,7 +1707,7 @@ def get_name(name, class_name):
|
|
|
1704
1707
|
raise MLRunInvalidArgumentError("name or class_name must be provided")
|
|
1705
1708
|
if isinstance(class_name, type):
|
|
1706
1709
|
return class_name.__name__
|
|
1707
|
-
return class_name
|
|
1710
|
+
return class_name.split(".")[-1]
|
|
1708
1711
|
|
|
1709
1712
|
|
|
1710
1713
|
def params_to_step(
|
mlrun/serving/v2_serving.py
CHANGED
|
@@ -96,7 +96,7 @@ class V2ModelServer(StepToDict):
|
|
|
96
96
|
self.name = name
|
|
97
97
|
self.version = ""
|
|
98
98
|
if name and ":" in name:
|
|
99
|
-
self.
|
|
99
|
+
self.version = name.split(":", 1)[-1]
|
|
100
100
|
self.context = context
|
|
101
101
|
self.ready = False
|
|
102
102
|
self.error = ""
|
|
@@ -277,7 +277,7 @@ class V2ModelServer(StepToDict):
|
|
|
277
277
|
|
|
278
278
|
response = {
|
|
279
279
|
"id": event_id,
|
|
280
|
-
"model_name": self.name,
|
|
280
|
+
"model_name": self.name.split(":")[0],
|
|
281
281
|
"outputs": outputs,
|
|
282
282
|
"timestamp": start.isoformat(sep=" ", timespec="microseconds"),
|
|
283
283
|
}
|
|
@@ -308,7 +308,7 @@ class V2ModelServer(StepToDict):
|
|
|
308
308
|
# get model metadata operation
|
|
309
309
|
setattr(event, "terminated", True)
|
|
310
310
|
event_body = {
|
|
311
|
-
"name": self.name,
|
|
311
|
+
"name": self.name.split(":")[0],
|
|
312
312
|
"version": self.version or "",
|
|
313
313
|
"inputs": [],
|
|
314
314
|
"outputs": [],
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import asyncio
|
|
16
16
|
import datetime
|
|
17
|
+
import os
|
|
17
18
|
import re
|
|
18
19
|
import traceback
|
|
19
20
|
import typing
|
|
@@ -30,6 +31,7 @@ import mlrun.model
|
|
|
30
31
|
import mlrun.utils.helpers
|
|
31
32
|
import mlrun.utils.notifications.notification as notification_module
|
|
32
33
|
import mlrun.utils.notifications.notification.base as base
|
|
34
|
+
import mlrun_pipelines.common.constants
|
|
33
35
|
import mlrun_pipelines.common.ops
|
|
34
36
|
import mlrun_pipelines.models
|
|
35
37
|
import mlrun_pipelines.utils
|
|
@@ -499,9 +501,9 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
499
501
|
steps.append(function)
|
|
500
502
|
|
|
501
503
|
step_methods = {
|
|
502
|
-
mlrun_pipelines.common.
|
|
503
|
-
mlrun_pipelines.common.
|
|
504
|
-
mlrun_pipelines.common.
|
|
504
|
+
mlrun_pipelines.common.constants.PipelineRunType.run: _add_run_step,
|
|
505
|
+
mlrun_pipelines.common.constants.PipelineRunType.build: _add_deploy_function_step,
|
|
506
|
+
mlrun_pipelines.common.constants.PipelineRunType.deploy: _add_deploy_function_step,
|
|
505
507
|
}
|
|
506
508
|
|
|
507
509
|
workflow_id = run.status.results.get("workflow_id", None)
|
|
@@ -684,6 +686,34 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
684
686
|
db = mlrun.get_run_db()
|
|
685
687
|
db.push_run_notifications(pipeline_id, project)
|
|
686
688
|
|
|
689
|
+
def push_pipeline_start_message_from_client(
|
|
690
|
+
self,
|
|
691
|
+
project: str,
|
|
692
|
+
commit_id: typing.Optional[str] = None,
|
|
693
|
+
pipeline_id: typing.Optional[str] = None,
|
|
694
|
+
has_workflow_url: bool = False,
|
|
695
|
+
):
|
|
696
|
+
message = f"Workflow started in project {project}"
|
|
697
|
+
if pipeline_id:
|
|
698
|
+
message += f" id={pipeline_id}"
|
|
699
|
+
commit_id = (
|
|
700
|
+
commit_id or os.environ.get("GITHUB_SHA") or os.environ.get("CI_COMMIT_SHA")
|
|
701
|
+
)
|
|
702
|
+
if commit_id:
|
|
703
|
+
message += f", commit={commit_id}"
|
|
704
|
+
if has_workflow_url:
|
|
705
|
+
url = mlrun.utils.helpers.get_workflow_url(project, pipeline_id)
|
|
706
|
+
else:
|
|
707
|
+
url = mlrun.utils.helpers.get_ui_url(project)
|
|
708
|
+
html = ""
|
|
709
|
+
if url:
|
|
710
|
+
html = (
|
|
711
|
+
message
|
|
712
|
+
+ f'<div><a href="{url}" target="_blank">click here to view progress</a></div>'
|
|
713
|
+
)
|
|
714
|
+
message = message + f", check progress in {url}"
|
|
715
|
+
self.push(message, "info", custom_html=html)
|
|
716
|
+
|
|
687
717
|
def push_pipeline_run_results(
|
|
688
718
|
self,
|
|
689
719
|
runs: typing.Union[mlrun.lists.RunList, list],
|
mlrun/utils/version/version.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mlrun
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.0rc18
|
|
4
4
|
Summary: Tracking and config of machine learning runs
|
|
5
5
|
Home-page: https://github.com/mlrun/mlrun
|
|
6
6
|
Author: Yaron Haviv
|
|
@@ -51,12 +51,10 @@ Requires-Dist: setuptools>=75.2
|
|
|
51
51
|
Requires-Dist: deprecated~=1.2
|
|
52
52
|
Requires-Dist: jinja2>=3.1.3,~=3.1
|
|
53
53
|
Requires-Dist: orjson<4,>=3.9.15
|
|
54
|
-
Requires-Dist: mlrun-pipelines-kfp-common~=0.3.
|
|
55
|
-
Requires-Dist: mlrun-pipelines-kfp-v1-8~=0.3.
|
|
54
|
+
Requires-Dist: mlrun-pipelines-kfp-common~=0.3.5
|
|
55
|
+
Requires-Dist: mlrun-pipelines-kfp-v1-8~=0.3.5; python_version < "3.11"
|
|
56
56
|
Requires-Dist: docstring_parser~=0.16
|
|
57
57
|
Requires-Dist: aiosmtplib~=3.0
|
|
58
|
-
Requires-Dist: grpcio-tools~=1.48.2; python_version < "3.11"
|
|
59
|
-
Requires-Dist: grpcio~=1.48.2; python_version < "3.11"
|
|
60
58
|
Provides-Extra: s3
|
|
61
59
|
Requires-Dist: boto3<1.36,>=1.28.0; extra == "s3"
|
|
62
60
|
Requires-Dist: aiobotocore<2.16,>=2.5.0; extra == "s3"
|
|
@@ -121,7 +119,7 @@ Requires-Dist: timelength~=1.1; extra == "api"
|
|
|
121
119
|
Requires-Dist: memray~=1.12; sys_platform != "win32" and extra == "api"
|
|
122
120
|
Requires-Dist: aiosmtplib~=3.0; extra == "api"
|
|
123
121
|
Requires-Dist: pydantic<2,>=1; extra == "api"
|
|
124
|
-
Requires-Dist: mlrun-pipelines-kfp-v1-8[kfp]~=0.3.
|
|
122
|
+
Requires-Dist: mlrun-pipelines-kfp-v1-8[kfp]~=0.3.5; python_version < "3.11" and extra == "api"
|
|
125
123
|
Provides-Extra: all
|
|
126
124
|
Requires-Dist: adlfs==2023.9.0; extra == "all"
|
|
127
125
|
Requires-Dist: aiobotocore<2.16,>=2.5.0; extra == "all"
|
|
@@ -210,7 +208,7 @@ Requires-Dist: igz-mgmt~=0.4.1; extra == "complete-api"
|
|
|
210
208
|
Requires-Dist: kafka-python~=2.0; extra == "complete-api"
|
|
211
209
|
Requires-Dist: memray~=1.12; sys_platform != "win32" and extra == "complete-api"
|
|
212
210
|
Requires-Dist: mlflow~=2.16; extra == "complete-api"
|
|
213
|
-
Requires-Dist: mlrun-pipelines-kfp-v1-8[kfp]~=0.3.
|
|
211
|
+
Requires-Dist: mlrun-pipelines-kfp-v1-8[kfp]~=0.3.5; python_version < "3.11" and extra == "complete-api"
|
|
214
212
|
Requires-Dist: msrest~=0.6.21; extra == "complete-api"
|
|
215
213
|
Requires-Dist: objgraph~=3.6; extra == "complete-api"
|
|
216
214
|
Requires-Dist: oss2==2.18.1; extra == "complete-api"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
mlrun/__init__.py,sha256=7vuMpUiigXXDrghLRq680LKWy1faC0kQyGCZb_7cwyE,7473
|
|
2
2
|
mlrun/__main__.py,sha256=o65gXHhmFA9GV_n2mqmAO80nW3MAwo_s7j80IKgCzRE,45949
|
|
3
|
-
mlrun/config.py,sha256=
|
|
3
|
+
mlrun/config.py,sha256=jjjpcnTjmYPc5ptvetYMJ-BPWaOiQW1b9Phdh9A8wo0,70605
|
|
4
4
|
mlrun/errors.py,sha256=5raKb1PXQpTcIvWQ4sr1qn2IS7P_GT_FydBJ0dXkVuc,8097
|
|
5
|
-
mlrun/execution.py,sha256=
|
|
5
|
+
mlrun/execution.py,sha256=Up9U6xonTElRIaesF9Vej2JK1Isk2AZNK9ke0XcF5Dg,49030
|
|
6
6
|
mlrun/features.py,sha256=ReBaNGsBYXqcbgI012n-SO_j6oHIbk_Vpv0CGPXbUmo,15842
|
|
7
7
|
mlrun/k8s_utils.py,sha256=mRQMs6NzPq36vx1n5_2BfFapXysc8wv3NcrZ77_2ANA,8949
|
|
8
8
|
mlrun/lists.py,sha256=1hFv3Iyu5DVX1kdBGJmwUoY0CqrzauhKdSq9g3piHb4,8442
|
|
@@ -16,7 +16,7 @@ mlrun/api/schemas/__init__.py,sha256=fEWH4I8hr5AdRJ7yoW44RlFB6NHkYDxyomP5J6ct1z4
|
|
|
16
16
|
mlrun/artifacts/__init__.py,sha256=ofC2extBCOC1wg1YtdTzWzH3eeG_f-sFBUkHjYtZJpk,1175
|
|
17
17
|
mlrun/artifacts/base.py,sha256=nz2ZqC74JGfWN0M6_hOXXQj3bXSTxNp4eUgvWHVcdvY,29979
|
|
18
18
|
mlrun/artifacts/dataset.py,sha256=QTot5vCgLHatlIWwNnKbWdZ8HHTxaZ7wk4gWQDoqQ2k,16655
|
|
19
|
-
mlrun/artifacts/document.py,sha256=
|
|
19
|
+
mlrun/artifacts/document.py,sha256=mbmos5LPkwOh0kHM0dFSi4RgbnPgfI3eMWiC4fk-ALI,15586
|
|
20
20
|
mlrun/artifacts/manager.py,sha256=bXb70mKF6wIGs7syCiFfGnjalqx4g9bO_J5DaVzUUKw,16163
|
|
21
21
|
mlrun/artifacts/model.py,sha256=jeOjUq_iZSHoNqlPyGgOz6acwje1Yqpg1yZwF9GbyG8,21615
|
|
22
22
|
mlrun/artifacts/plots.py,sha256=dS0mHGt1b20tN2JyEH9H5o5I0oMKZkzn3Uz_3Hf4WjU,4813
|
|
@@ -37,7 +37,7 @@ mlrun/common/formatters/pipeline.py,sha256=oATD3znsuq3s7LipPnZivDPelTX0hJ0MFeeXO
|
|
|
37
37
|
mlrun/common/formatters/project.py,sha256=0G4lhcTAsxQCxd40dKC4894cMH8nKt03BcGyp9wQO14,2102
|
|
38
38
|
mlrun/common/formatters/run.py,sha256=Gcf9lVDqxPMNfWcPX0RJasjTC_N_U0yTBkQ02jOPJ7A,1062
|
|
39
39
|
mlrun/common/model_monitoring/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
|
|
40
|
-
mlrun/common/model_monitoring/helpers.py,sha256=
|
|
40
|
+
mlrun/common/model_monitoring/helpers.py,sha256=lV86teJYoE3MNDx4yhpbzO1KylWmvDbuNODw5yGZwgs,2943
|
|
41
41
|
mlrun/common/runtimes/constants.py,sha256=Mok3m9Rv182TTMp7uYNfWalm9Xcz86yva-4fTxfMOPI,10988
|
|
42
42
|
mlrun/common/schemas/__init__.py,sha256=PBuIAhXSkVEVxxKcv5hR_xvTwNAUqxOXHVPugOoWTyM,5386
|
|
43
43
|
mlrun/common/schemas/alert.py,sha256=G9lFTXFYDor-RVLpJxMorIPlLWr_-GYCFKRN9DkKwXs,10124
|
|
@@ -72,7 +72,7 @@ mlrun/common/schemas/secret.py,sha256=CCxFYiPwJtDxwg2VVJH9nUG9cAZ2a34IjeuaWv-BYl
|
|
|
72
72
|
mlrun/common/schemas/tag.py,sha256=HRZi5QZ4vVGaCr2AMk9eJgcNiAIXmH4YDc8a4fvF770,893
|
|
73
73
|
mlrun/common/schemas/workflow.py,sha256=rwYzDJYxpE9k4kC88j_eUCmqK4ZsWV_h-_nli7Fs7Ow,2078
|
|
74
74
|
mlrun/common/schemas/model_monitoring/__init__.py,sha256=noj7DPPia59PBWORsQZO20Ym0yhUwyoNJ3EeG8gVxlQ,1875
|
|
75
|
-
mlrun/common/schemas/model_monitoring/constants.py,sha256=
|
|
75
|
+
mlrun/common/schemas/model_monitoring/constants.py,sha256=VA1fEETbiyTKGiAG4WBSzo69Revd1_sgr8to6N0rp6U,11543
|
|
76
76
|
mlrun/common/schemas/model_monitoring/grafana.py,sha256=Rq10KKOyyUYr7qOQFZfwGZtUim0LY9O0LQ5uc9jmIVQ,1562
|
|
77
77
|
mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=GVWePSdaKyJm7-QdBiAQdMymlp2QgZIJwXO9EA6Q7AI,11727
|
|
78
78
|
mlrun/data_types/__init__.py,sha256=unRo9GGwCmj0hBKBRsXJ2P4BzpQaddlQTvIrVQaKluI,984
|
|
@@ -85,7 +85,7 @@ mlrun/datastore/alibaba_oss.py,sha256=k-OHVe08HjMewlkpsT657CbOiVFAfSq9_EqhCE-k86
|
|
|
85
85
|
mlrun/datastore/azure_blob.py,sha256=SzAcHYSXkm8Zpopz2Ea-rWVClH0URocUazcNK04S9W0,12776
|
|
86
86
|
mlrun/datastore/base.py,sha256=Dqg8PqX0TFKHZg27Dgguc3RnQ1GABZiLf87p5ErTqJs,26448
|
|
87
87
|
mlrun/datastore/datastore.py,sha256=frUYYP4i8ZmnY8GNXSgN_3x_exRgRPfxrCtAGEUifEU,9478
|
|
88
|
-
mlrun/datastore/datastore_profile.py,sha256=
|
|
88
|
+
mlrun/datastore/datastore_profile.py,sha256=QGL4cgnpNDGugIAKkSWldgFxZMMMOcFfXS-k95gwfwQ,22212
|
|
89
89
|
mlrun/datastore/dbfs_store.py,sha256=QkDRzwFnvm7CgEg4NuGxes6tBgKDyhX0CiBUvK8c9pk,6568
|
|
90
90
|
mlrun/datastore/filestore.py,sha256=OcykjzhbUAZ6_Cb9bGAXRL2ngsOpxXSb4rR0lyogZtM,3773
|
|
91
91
|
mlrun/datastore/google_cloud_storage.py,sha256=MnToY6irdhBZ8Wcapqnr1Yq2724LAh2uPO7MAtdWfUY,8716
|
|
@@ -107,10 +107,10 @@ mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev
|
|
|
107
107
|
mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
|
|
108
108
|
mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
|
|
109
109
|
mlrun/db/auth_utils.py,sha256=hpg8D2r82oN0BWabuWN04BTNZ7jYMAF242YSUpK7LFM,5211
|
|
110
|
-
mlrun/db/base.py,sha256=
|
|
110
|
+
mlrun/db/base.py,sha256=ZCvjAN68L4kRZsytkuqqz4JTLROxczmbXjJwU1vaK8c,29855
|
|
111
111
|
mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
|
|
112
|
-
mlrun/db/httpdb.py,sha256=
|
|
113
|
-
mlrun/db/nopdb.py,sha256=
|
|
112
|
+
mlrun/db/httpdb.py,sha256=eGuQ05kwU8h_DbtuzlPo1aBMU4ZbfIsrRPWxiqb4v_Y,226141
|
|
113
|
+
mlrun/db/nopdb.py,sha256=v285LHP_Onfuo8KRF078IAPHIXTeEhQsU58QoY7x-b0,26673
|
|
114
114
|
mlrun/feature_store/__init__.py,sha256=AVnY2AFUNc2dKxLLUMx2K3Wo1eGviv0brDcYlDnmtf4,1506
|
|
115
115
|
mlrun/feature_store/api.py,sha256=qkojZpzqGAn3r9ww0ynBRKOs8ji8URaK4DSYD4SE-CE,50395
|
|
116
116
|
mlrun/feature_store/common.py,sha256=Z7USI-d1fo0iwBMsqMBtJflJfyuiV3BLoDXQPSAoBAs,12826
|
|
@@ -215,18 +215,18 @@ mlrun/launcher/client.py,sha256=FXzQQqrSVE9oapLjjUYvx5qhZPG1r4ynUjUUFZVPekE,6228
|
|
|
215
215
|
mlrun/launcher/factory.py,sha256=RW7mfzEFi8fR0M-4W1JQg1iq3_muUU6OTqT_3l4Ubrk,2338
|
|
216
216
|
mlrun/launcher/local.py,sha256=9zNiuswHnSINDj4yYP2Vd192b5d4FUtSA8O2ICKjsKo,11279
|
|
217
217
|
mlrun/launcher/remote.py,sha256=rLJW4UAnUT5iUb4BsGBOAV3K4R29a0X4lFtRkVKlyYU,7709
|
|
218
|
-
mlrun/model_monitoring/__init__.py,sha256=
|
|
218
|
+
mlrun/model_monitoring/__init__.py,sha256=ELy7njEtZnz09Dc6PGZSFFEGtnwI15bJNWM3Pj4_YIs,753
|
|
219
219
|
mlrun/model_monitoring/api.py,sha256=nH5aEUkmUEJF0CurrWJxmxVv1tQed2yzCLhQByG1L00,28561
|
|
220
220
|
mlrun/model_monitoring/controller.py,sha256=dBfZQswF67vqeUFnmgsm9jU_5sOs9dLwMPEiYHG-Kk8,19786
|
|
221
221
|
mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
|
|
222
|
-
mlrun/model_monitoring/helpers.py,sha256=
|
|
222
|
+
mlrun/model_monitoring/helpers.py,sha256=Ul7-EHqzbf1GprB53Tf4WcbOHdD65sK3BgF2mpPYakg,17938
|
|
223
223
|
mlrun/model_monitoring/stream_processing.py,sha256=ltCVgo_b3yay16CUbqeGkRfzCHZSn14lVeBng5m9keY,31738
|
|
224
224
|
mlrun/model_monitoring/tracking_policy.py,sha256=PBIGrUYWrwcE5gwXupBIVzOb0QRRwPJsgQm_yLGQxB4,5595
|
|
225
|
-
mlrun/model_monitoring/writer.py,sha256
|
|
225
|
+
mlrun/model_monitoring/writer.py,sha256=vbL7bqTyNu8q4bNcebX72sUMybVDAoTWg-CXq4fov3Y,8429
|
|
226
226
|
mlrun/model_monitoring/applications/__init__.py,sha256=QYvzgCutFdAkzqKPD3mvkX_3c1X4tzd-kW8ojUOE9ic,889
|
|
227
227
|
mlrun/model_monitoring/applications/_application_steps.py,sha256=NvrYJs6N0Kpp3s_t6s9LkCk5hY7kWYmkVoIhz_ZZx_8,7178
|
|
228
|
-
mlrun/model_monitoring/applications/base.py,sha256=
|
|
229
|
-
mlrun/model_monitoring/applications/context.py,sha256=
|
|
228
|
+
mlrun/model_monitoring/applications/base.py,sha256=pqmZ67zaslIkcJlsjcUG6TWjbBTD_fYci6rlEvbFttc,15091
|
|
229
|
+
mlrun/model_monitoring/applications/context.py,sha256=kE_8h7eoUES_bFG2s7nENRziMFB72fJvAZ3KpIBWxOo,15084
|
|
230
230
|
mlrun/model_monitoring/applications/evidently_base.py,sha256=hRjXuXf6xf8sbjGt9yYfGDUGnvS5rV3W7tkJroF3QJA,5098
|
|
231
231
|
mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=G26_4gQfcwDZe3S6SIZ4Uc_qyrHAJ6lDTFOQGkbfQR8,14455
|
|
232
232
|
mlrun/model_monitoring/applications/results.py,sha256=oh1z9oacWWP4azVXm_Fx7j8uXSfdkB9T4mtGwyPBveE,5748
|
|
@@ -266,8 +266,8 @@ mlrun/platforms/__init__.py,sha256=ZuyeHCHHUxYEoZRmaJqzFSfwhaTyUdBZXMeVp75ql1w,3
|
|
|
266
266
|
mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13749
|
|
267
267
|
mlrun/projects/__init__.py,sha256=0Krf0WIKfnZa71WthYOg0SoaTodGg3sV_hK3f_OlTPI,1220
|
|
268
268
|
mlrun/projects/operations.py,sha256=VXUlMrouFTls-I-bMhdN5pPfQ34TR7bFQ-NUSWNvl84,20029
|
|
269
|
-
mlrun/projects/pipelines.py,sha256=
|
|
270
|
-
mlrun/projects/project.py,sha256=
|
|
269
|
+
mlrun/projects/pipelines.py,sha256=vZpyiERUzwPMS7NCC5ghI0KB_DItIddr7MMWGTwLawY,47437
|
|
270
|
+
mlrun/projects/project.py,sha256=fApkLLMJKPQi-Q69O-pZP5sh6eVsLmBt1KqZUFwcZoM,228225
|
|
271
271
|
mlrun/runtimes/__init__.py,sha256=J9Sy2HiyMlztNv6VUurMzF5H2XzttNil8nRsWDsqLyg,8923
|
|
272
272
|
mlrun/runtimes/base.py,sha256=Yt2l7srrXjK783cunBEKH0yQxQZRH8lkedXNOXuLbbo,37841
|
|
273
273
|
mlrun/runtimes/daskjob.py,sha256=JwuGvOiPsxEDHHMMUS4Oie4hLlYYIZwihAl6DjroTY0,19521
|
|
@@ -303,10 +303,10 @@ mlrun/serving/remote.py,sha256=gxJkj_J3j-sZcVUbUzbAmJafP6t6y4NVFsu0kWmYngA,18818
|
|
|
303
303
|
mlrun/serving/routers.py,sha256=A_R34_N6uYw2veK58WpffEp1NsFwq0XbNU9is2Nd7s8,50901
|
|
304
304
|
mlrun/serving/server.py,sha256=xP88X7_C4mHIk0R7TJBCl-jSl-VomctblipiYepQTaQ,22512
|
|
305
305
|
mlrun/serving/serving_wrapper.py,sha256=R670-S6PX_d5ER6jiHtRvacuPyFzQH0mEf2K0sBIIOM,836
|
|
306
|
-
mlrun/serving/states.py,sha256=
|
|
306
|
+
mlrun/serving/states.py,sha256=g6UIeaS6B9v8k4eDMmOxyoB8Gdqm9PiNIkeuzDyTJA8,67565
|
|
307
307
|
mlrun/serving/utils.py,sha256=k2EIYDWHUGkE-IBI6T0UNT32fw-KySsccIJM_LObI00,4171
|
|
308
308
|
mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
|
|
309
|
-
mlrun/serving/v2_serving.py,sha256=
|
|
309
|
+
mlrun/serving/v2_serving.py,sha256=B1Vmca2_YidXyit4wuxR6JGooMGdaeZI3Ja90JHCz10,21882
|
|
310
310
|
mlrun/track/__init__.py,sha256=yVXbT52fXvGKRlc_ByHqIVt7-9L3DRE634RSeQwgXtU,665
|
|
311
311
|
mlrun/track/tracker.py,sha256=CyTU6Qd3_5GGEJ_hpocOj71wvV65EuFYUjaYEUKAL6Q,3575
|
|
312
312
|
mlrun/track/tracker_manager.py,sha256=IYBl99I62IC6VCCmG1yt6JoHNOQXa53C4DURJ2sWgio,5726
|
|
@@ -327,7 +327,7 @@ mlrun/utils/singleton.py,sha256=p1Y-X0mPSs_At092GS-pZCA8CTR62HOqPU07_ZH6-To,869
|
|
|
327
327
|
mlrun/utils/v3io_clients.py,sha256=0aCFiQFBmgdSeLzJr_nEP6SG-zyieSgH8RdtcUq4dc0,1294
|
|
328
328
|
mlrun/utils/vault.py,sha256=xUiKL17dCXjwQJ33YRzQj0oadUXATlFWPzKKYAESoQk,10447
|
|
329
329
|
mlrun/utils/notifications/__init__.py,sha256=eUzQDBxSQmMZASRY-YAnYS6tL5801P0wEjycp3Dvoe0,990
|
|
330
|
-
mlrun/utils/notifications/notification_pusher.py,sha256=
|
|
330
|
+
mlrun/utils/notifications/notification_pusher.py,sha256=Y30ZG8MDk0oxPPHPjqd9kDxQaOewTuE5uwZhxlM5V-s,29269
|
|
331
331
|
mlrun/utils/notifications/notification/__init__.py,sha256=9Rfy6Jm8n0LaEDO1VAQb6kIbr7_uVuQhK1pS_abELIY,2581
|
|
332
332
|
mlrun/utils/notifications/notification/base.py,sha256=VOgrzRakRfjYYBqvkc0cgEC5pl7KMidP7u-TL4HpGCY,5280
|
|
333
333
|
mlrun/utils/notifications/notification/console.py,sha256=ICbIhOf9fEBJky_3j9TFiKAewDGyDHJr9l4VeT7G2sc,2745
|
|
@@ -337,11 +337,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
|
|
|
337
337
|
mlrun/utils/notifications/notification/slack.py,sha256=NKV4RFiY3gLsS8uPppgniPLyag8zJ9O1VhixoXkM7kw,7108
|
|
338
338
|
mlrun/utils/notifications/notification/webhook.py,sha256=M-pSBM2VTKVUPRERocjORlH6mKqo1K9ihVL5Qrn2GyM,4789
|
|
339
339
|
mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
|
|
340
|
-
mlrun/utils/version/version.json,sha256=
|
|
340
|
+
mlrun/utils/version/version.json,sha256=fuKq-DQzj4VU91pAfeQ6y9--Wzwya8hmUG1brhepAzQ,89
|
|
341
341
|
mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
|
|
342
|
-
mlrun-1.8.
|
|
343
|
-
mlrun-1.8.
|
|
344
|
-
mlrun-1.8.
|
|
345
|
-
mlrun-1.8.
|
|
346
|
-
mlrun-1.8.
|
|
347
|
-
mlrun-1.8.
|
|
342
|
+
mlrun-1.8.0rc18.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
343
|
+
mlrun-1.8.0rc18.dist-info/METADATA,sha256=LmjjU6uSheHxPOGP4V2giVzBleaHV45fl9bCB_xqyBo,24885
|
|
344
|
+
mlrun-1.8.0rc18.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
345
|
+
mlrun-1.8.0rc18.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
|
|
346
|
+
mlrun-1.8.0rc18.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
|
|
347
|
+
mlrun-1.8.0rc18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|