mlrun 1.10.0rc1__py3-none-any.whl → 1.10.0rc2__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/__main__.py +13 -2
- mlrun/common/constants.py +7 -0
- mlrun/common/runtimes/constants.py +8 -1
- mlrun/common/schemas/__init__.py +1 -0
- mlrun/common/schemas/serving.py +17 -0
- mlrun/datastore/datastore_profile.py +5 -55
- mlrun/datastore/sources.py +21 -13
- mlrun/datastore/utils.py +19 -4
- mlrun/db/base.py +1 -1
- mlrun/db/httpdb.py +22 -10
- mlrun/db/nopdb.py +1 -1
- mlrun/errors.py +7 -0
- mlrun/execution.py +9 -0
- mlrun/launcher/client.py +1 -1
- mlrun/model_monitoring/applications/evidently/base.py +59 -71
- mlrun/model_monitoring/controller.py +26 -13
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +13 -5
- mlrun/projects/project.py +95 -33
- mlrun/render.py +5 -9
- mlrun/runtimes/base.py +1 -1
- mlrun/runtimes/utils.py +25 -8
- mlrun/serving/states.py +142 -9
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/METADATA +8 -8
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/RECORD +29 -29
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/WHEEL +1 -1
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc1.dist-info → mlrun-1.10.0rc2.dist-info}/top_level.txt +0 -0
|
@@ -14,19 +14,18 @@
|
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
16
|
import posixpath
|
|
17
|
-
import uuid
|
|
18
17
|
import warnings
|
|
19
18
|
from abc import ABC
|
|
19
|
+
from tempfile import NamedTemporaryFile
|
|
20
|
+
from typing import Optional
|
|
20
21
|
|
|
21
|
-
import pandas as pd
|
|
22
22
|
import semver
|
|
23
|
-
from evidently.ui.storage.local.base import METADATA_PATH, FSLocation
|
|
24
23
|
|
|
25
24
|
import mlrun.model_monitoring.applications.base as mm_base
|
|
26
25
|
import mlrun.model_monitoring.applications.context as mm_context
|
|
27
|
-
from mlrun.errors import MLRunIncompatibleVersionError
|
|
26
|
+
from mlrun.errors import MLRunIncompatibleVersionError, MLRunValueError
|
|
28
27
|
|
|
29
|
-
SUPPORTED_EVIDENTLY_VERSION = semver.Version.parse("0.
|
|
28
|
+
SUPPORTED_EVIDENTLY_VERSION = semver.Version.parse("0.7.5")
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
def _check_evidently_version(*, cur: semver.Version, ref: semver.Version) -> None:
|
|
@@ -60,36 +59,66 @@ except ModuleNotFoundError:
|
|
|
60
59
|
|
|
61
60
|
|
|
62
61
|
if _HAS_EVIDENTLY:
|
|
63
|
-
from evidently.
|
|
64
|
-
from evidently.ui.
|
|
65
|
-
from evidently.ui.workspace import
|
|
66
|
-
|
|
62
|
+
from evidently.core.report import Snapshot
|
|
63
|
+
from evidently.legacy.ui.storage.local.base import METADATA_PATH, FSLocation
|
|
64
|
+
from evidently.ui.workspace import (
|
|
65
|
+
STR_UUID,
|
|
66
|
+
CloudWorkspace,
|
|
67
|
+
Project,
|
|
68
|
+
Workspace,
|
|
69
|
+
WorkspaceBase,
|
|
70
|
+
)
|
|
67
71
|
|
|
68
72
|
|
|
69
73
|
class EvidentlyModelMonitoringApplicationBase(
|
|
70
74
|
mm_base.ModelMonitoringApplicationBase, ABC
|
|
71
75
|
):
|
|
72
76
|
def __init__(
|
|
73
|
-
self,
|
|
77
|
+
self,
|
|
78
|
+
evidently_project_id: "STR_UUID",
|
|
79
|
+
evidently_workspace_path: Optional[str] = None,
|
|
80
|
+
cloud_workspace: bool = False,
|
|
74
81
|
) -> None:
|
|
75
82
|
"""
|
|
76
|
-
A class for integrating Evidently for
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
A class for integrating Evidently for MLRun model monitoring within a monitoring application.
|
|
84
|
+
|
|
85
|
+
.. note::
|
|
86
|
+
|
|
87
|
+
The ``evidently`` package is not installed by default in the mlrun/mlrun image.
|
|
88
|
+
It must be installed separately to use this class.
|
|
79
89
|
|
|
80
|
-
:param evidently_workspace_path: (str) The path to the Evidently workspace.
|
|
81
90
|
:param evidently_project_id: (str) The ID of the Evidently project.
|
|
91
|
+
:param evidently_workspace_path: (str) The path to the Evidently workspace.
|
|
92
|
+
:param cloud_workspace: (bool) Whether the workspace is an Evidently Cloud workspace.
|
|
82
93
|
"""
|
|
83
|
-
|
|
84
|
-
# TODO : more then one project (mep -> project)
|
|
85
94
|
if not _HAS_EVIDENTLY:
|
|
86
95
|
raise ModuleNotFoundError("Evidently is not installed - the app cannot run")
|
|
87
|
-
self.
|
|
88
|
-
|
|
96
|
+
self.evidently_workspace_path = evidently_workspace_path
|
|
97
|
+
if cloud_workspace:
|
|
98
|
+
self.get_workspace = self.get_cloud_workspace
|
|
99
|
+
self.evidently_workspace = self.get_workspace()
|
|
89
100
|
self.evidently_project_id = evidently_project_id
|
|
90
|
-
self.evidently_project = self.
|
|
91
|
-
|
|
92
|
-
|
|
101
|
+
self.evidently_project = self.load_project()
|
|
102
|
+
|
|
103
|
+
def load_project(self) -> Project:
|
|
104
|
+
"""Load the Evidently project."""
|
|
105
|
+
return self.evidently_workspace.get_project(self.evidently_project_id)
|
|
106
|
+
|
|
107
|
+
def get_workspace(self) -> WorkspaceBase:
|
|
108
|
+
"""Get the Evidently workspace. Override this method for customize access to the workspace."""
|
|
109
|
+
if self.evidently_workspace_path:
|
|
110
|
+
self._log_location(self.evidently_workspace_path)
|
|
111
|
+
return Workspace.create(self.evidently_workspace_path)
|
|
112
|
+
else:
|
|
113
|
+
raise MLRunValueError(
|
|
114
|
+
"A local workspace could not be created as `evidently_workspace_path` is not set.\n"
|
|
115
|
+
"If you intend to use a cloud workspace, please use `cloud_workspace=True` and set the "
|
|
116
|
+
"`EVIDENTLY_API_KEY` environment variable. In other cases, override this method."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def get_cloud_workspace(self) -> CloudWorkspace:
|
|
120
|
+
"""Load the Evidently cloud workspace according to the `EVIDENTLY_API_KEY` environment variable."""
|
|
121
|
+
return CloudWorkspace()
|
|
93
122
|
|
|
94
123
|
@staticmethod
|
|
95
124
|
def _log_location(evidently_workspace_path):
|
|
@@ -128,7 +157,7 @@ class EvidentlyModelMonitoringApplicationBase(
|
|
|
128
157
|
@staticmethod
|
|
129
158
|
def log_evidently_object(
|
|
130
159
|
monitoring_context: mm_context.MonitoringApplicationContext,
|
|
131
|
-
evidently_object: "
|
|
160
|
+
evidently_object: "Snapshot",
|
|
132
161
|
artifact_name: str,
|
|
133
162
|
unique_per_endpoint: bool = True,
|
|
134
163
|
) -> None:
|
|
@@ -141,56 +170,15 @@ class EvidentlyModelMonitoringApplicationBase(
|
|
|
141
170
|
This method should be called on special occasions only.
|
|
142
171
|
|
|
143
172
|
:param monitoring_context: (MonitoringApplicationContext) The monitoring context to process.
|
|
144
|
-
:param evidently_object: (
|
|
145
|
-
:param artifact_name: (str) The name for the logged artifact.
|
|
146
|
-
:param unique_per_endpoint: by default ``True``, we will log different artifact for each model endpoint,
|
|
147
|
-
set to ``False`` without changing item key will cause artifact override.
|
|
148
|
-
"""
|
|
149
|
-
evidently_object_html = evidently_object.get_html()
|
|
150
|
-
monitoring_context.log_artifact(
|
|
151
|
-
artifact_name,
|
|
152
|
-
body=evidently_object_html.encode("utf-8"),
|
|
153
|
-
format="html",
|
|
154
|
-
unique_per_endpoint=unique_per_endpoint,
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
def log_project_dashboard(
|
|
158
|
-
self,
|
|
159
|
-
monitoring_context: mm_context.MonitoringApplicationContext,
|
|
160
|
-
timestamp_start: pd.Timestamp,
|
|
161
|
-
timestamp_end: pd.Timestamp,
|
|
162
|
-
artifact_name: str = "dashboard",
|
|
163
|
-
unique_per_endpoint: bool = True,
|
|
164
|
-
) -> None:
|
|
165
|
-
"""
|
|
166
|
-
Logs an Evidently project dashboard.
|
|
167
|
-
|
|
168
|
-
.. caution::
|
|
169
|
-
|
|
170
|
-
Logging Evidently dashboards in every model monitoring window may cause scale issues.
|
|
171
|
-
This method should be called on special occasions only.
|
|
172
|
-
|
|
173
|
-
:param monitoring_context: (MonitoringApplicationContext) The monitoring context to process.
|
|
174
|
-
:param timestamp_start: (pd.Timestamp) The start timestamp for the dashboard data.
|
|
175
|
-
:param timestamp_end: (pd.Timestamp) The end timestamp for the dashboard data.
|
|
173
|
+
:param evidently_object: (Snapshot) The Evidently run to log, e.g. a report run.
|
|
176
174
|
:param artifact_name: (str) The name for the logged artifact.
|
|
177
175
|
:param unique_per_endpoint: by default ``True``, we will log different artifact for each model endpoint,
|
|
178
176
|
set to ``False`` without changing item key will cause artifact override.
|
|
179
177
|
"""
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
additional_graphs={},
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
dashboard_html = file_html_template(params=template_params)
|
|
191
|
-
monitoring_context.log_artifact(
|
|
192
|
-
artifact_name,
|
|
193
|
-
body=dashboard_html.encode("utf-8"),
|
|
194
|
-
format="html",
|
|
195
|
-
unique_per_endpoint=unique_per_endpoint,
|
|
196
|
-
)
|
|
178
|
+
with NamedTemporaryFile(suffix=".html") as file:
|
|
179
|
+
evidently_object.save_html(filename=file.name)
|
|
180
|
+
monitoring_context.log_artifact(
|
|
181
|
+
artifact_name,
|
|
182
|
+
local_path=file.name,
|
|
183
|
+
unique_per_endpoint=unique_per_endpoint,
|
|
184
|
+
)
|
|
@@ -25,6 +25,7 @@ from types import TracebackType
|
|
|
25
25
|
from typing import Any, NamedTuple, Optional, Union, cast
|
|
26
26
|
|
|
27
27
|
import nuclio_sdk
|
|
28
|
+
import pandas as pd
|
|
28
29
|
|
|
29
30
|
import mlrun
|
|
30
31
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
@@ -673,9 +674,15 @@ class MonitoringApplicationController:
|
|
|
673
674
|
"""
|
|
674
675
|
logger.info("Starting monitoring controller chief")
|
|
675
676
|
applications_names = []
|
|
676
|
-
endpoints = self.project_obj.list_model_endpoints(
|
|
677
|
-
|
|
678
|
-
|
|
677
|
+
endpoints = self.project_obj.list_model_endpoints(tsdb_metrics=False).endpoints
|
|
678
|
+
last_request_dict = self.tsdb_connector.get_last_request(
|
|
679
|
+
endpoint_ids=[mep.metadata.uid for mep in endpoints]
|
|
680
|
+
)
|
|
681
|
+
if isinstance(last_request_dict, pd.DataFrame):
|
|
682
|
+
last_request_dict = last_request_dict.set_index(
|
|
683
|
+
mm_constants.EventFieldType.ENDPOINT_ID
|
|
684
|
+
)[mm_constants.ModelEndpointSchema.LAST_REQUEST].to_dict()
|
|
685
|
+
|
|
679
686
|
if not endpoints:
|
|
680
687
|
logger.info("No model endpoints found", project=self.project)
|
|
681
688
|
return
|
|
@@ -721,16 +728,22 @@ class MonitoringApplicationController:
|
|
|
721
728
|
with schedules.ModelMonitoringSchedulesFileChief(
|
|
722
729
|
self.project
|
|
723
730
|
) as schedule_file:
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
731
|
+
for endpoint in endpoints:
|
|
732
|
+
last_request = last_request_dict.get(endpoint.metadata.uid, None)
|
|
733
|
+
if isinstance(last_request, float):
|
|
734
|
+
last_request = pd.to_datetime(last_request, unit="s", utc=True)
|
|
735
|
+
endpoint.status.last_request = (
|
|
736
|
+
last_request or endpoint.status.last_request
|
|
737
|
+
)
|
|
738
|
+
futures = {
|
|
739
|
+
pool.submit(
|
|
740
|
+
self.endpoint_to_regular_event,
|
|
741
|
+
endpoint,
|
|
742
|
+
policy,
|
|
743
|
+
set(applications_names),
|
|
744
|
+
schedule_file,
|
|
745
|
+
): endpoint
|
|
746
|
+
}
|
|
734
747
|
for future in concurrent.futures.as_completed(futures):
|
|
735
748
|
if future.exception():
|
|
736
749
|
exception = future.exception()
|
|
@@ -455,12 +455,20 @@ class V3IOTSDBConnector(TSDBConnector):
|
|
|
455
455
|
# Delete all tables
|
|
456
456
|
tables = mm_schemas.V3IOTSDBTables.list()
|
|
457
457
|
for table_to_delete in tables:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
458
|
+
if table_to_delete in self.tables:
|
|
459
|
+
try:
|
|
460
|
+
self.frames_client.delete(
|
|
461
|
+
backend=_TSDB_BE, table=self.tables[table_to_delete]
|
|
462
|
+
)
|
|
463
|
+
except v3io_frames.DeleteError as e:
|
|
464
|
+
logger.warning(
|
|
465
|
+
f"Failed to delete TSDB table '{table_to_delete}'",
|
|
466
|
+
err=mlrun.errors.err_to_str(e),
|
|
467
|
+
)
|
|
468
|
+
else:
|
|
461
469
|
logger.warning(
|
|
462
|
-
f"
|
|
463
|
-
|
|
470
|
+
f"Skipping deletion: table '{table_to_delete}' is not among the initialized tables.",
|
|
471
|
+
initialized_tables=list(self.tables.keys()),
|
|
464
472
|
)
|
|
465
473
|
|
|
466
474
|
# Final cleanup of tsdb path
|
mlrun/projects/project.py
CHANGED
|
@@ -30,6 +30,7 @@ from copy import deepcopy
|
|
|
30
30
|
from os import environ, makedirs, path
|
|
31
31
|
from typing import Callable, Optional, Union, cast
|
|
32
32
|
|
|
33
|
+
import deprecated
|
|
33
34
|
import dotenv
|
|
34
35
|
import git
|
|
35
36
|
import git.exc
|
|
@@ -2860,6 +2861,20 @@ class MlrunProject(ModelObj):
|
|
|
2860
2861
|
|
|
2861
2862
|
self.spec.set_function(name, function_object, func)
|
|
2862
2863
|
|
|
2864
|
+
# TODO: Remove this in 1.11.0
|
|
2865
|
+
@deprecated.deprecated(
|
|
2866
|
+
version="1.8.0",
|
|
2867
|
+
reason="'remove_function' is deprecated and will be removed in 1.11.0. "
|
|
2868
|
+
"Please use `delete_function` instead.",
|
|
2869
|
+
category=FutureWarning,
|
|
2870
|
+
)
|
|
2871
|
+
def remove_function(self, name):
|
|
2872
|
+
"""remove the specified function from the project
|
|
2873
|
+
|
|
2874
|
+
:param name: name of the function (under the project)
|
|
2875
|
+
"""
|
|
2876
|
+
self.spec.remove_function(name)
|
|
2877
|
+
|
|
2863
2878
|
def delete_function(self, name, delete_from_db=False):
|
|
2864
2879
|
"""deletes the specified function from the project
|
|
2865
2880
|
|
|
@@ -3695,7 +3710,7 @@ class MlrunProject(ModelObj):
|
|
|
3695
3710
|
brokers=["<kafka-broker-ip-address>:9094"],
|
|
3696
3711
|
topics=[], # Keep the topics list empty
|
|
3697
3712
|
## SASL is supported
|
|
3698
|
-
# sasl_user="
|
|
3713
|
+
# sasl_user="<kafka-sasl-user>",
|
|
3699
3714
|
# sasl_pass="<kafka-sasl-password>",
|
|
3700
3715
|
)
|
|
3701
3716
|
project.register_datastore_profile(stream_profile)
|
|
@@ -3728,6 +3743,29 @@ class MlrunProject(ModelObj):
|
|
|
3728
3743
|
|
|
3729
3744
|
In the V3IO datastore, you must provide an explicit access key to the stream, but not to the TSDB.
|
|
3730
3745
|
|
|
3746
|
+
An external Confluent Kafka stream is also supported. Here is an example:
|
|
3747
|
+
|
|
3748
|
+
.. code-block:: python
|
|
3749
|
+
|
|
3750
|
+
from mlrun.datastore.datastore_profile import DatastoreProfileKafkaSource
|
|
3751
|
+
|
|
3752
|
+
stream_profile = DatastoreProfileKafkaSource(
|
|
3753
|
+
name="confluent-kafka",
|
|
3754
|
+
brokers=["<server-domain-start>.confluent.cloud:9092"],
|
|
3755
|
+
topics=[],
|
|
3756
|
+
sasl_user="<API-key>",
|
|
3757
|
+
sasl_pass="<API-secret>",
|
|
3758
|
+
kwargs_public={
|
|
3759
|
+
"security_protocol": "SASL_SSL",
|
|
3760
|
+
"api_version_auto_timeout_ms": 15_000, # 15 seconds
|
|
3761
|
+
"tls": {"enable": True},
|
|
3762
|
+
"new_topic": {"replication_factor": 3},
|
|
3763
|
+
},
|
|
3764
|
+
)
|
|
3765
|
+
|
|
3766
|
+
The replication factor and timeout configuration might need to be adjusted according to your Confluent cluster
|
|
3767
|
+
type and settings.
|
|
3768
|
+
|
|
3731
3769
|
:param tsdb_profile_name: The datastore profile name of the time-series database to be used in model
|
|
3732
3770
|
monitoring. The supported profiles are:
|
|
3733
3771
|
|
|
@@ -3781,7 +3819,7 @@ class MlrunProject(ModelObj):
|
|
|
3781
3819
|
top_level: bool = False,
|
|
3782
3820
|
uids: Optional[list[str]] = None,
|
|
3783
3821
|
latest_only: bool = False,
|
|
3784
|
-
tsdb_metrics: bool =
|
|
3822
|
+
tsdb_metrics: bool = False,
|
|
3785
3823
|
metric_list: Optional[list[str]] = None,
|
|
3786
3824
|
) -> mlrun.common.schemas.ModelEndpointList:
|
|
3787
3825
|
"""
|
|
@@ -4003,8 +4041,10 @@ class MlrunProject(ModelObj):
|
|
|
4003
4041
|
e.g. builder_env={"GIT_TOKEN": token}, does not work yet in KFP
|
|
4004
4042
|
:param overwrite_build_params: Overwrite existing build configuration (currently applies to
|
|
4005
4043
|
requirements and commands)
|
|
4044
|
+
|
|
4006
4045
|
* False: The new params are merged with the existing
|
|
4007
4046
|
* True: The existing params are replaced by the new ones
|
|
4047
|
+
|
|
4008
4048
|
:param extra_args: A string containing additional builder arguments in the format of command-line options,
|
|
4009
4049
|
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
4010
4050
|
:param force_build: force building the image, even when no changes were made
|
|
@@ -4055,8 +4095,10 @@ class MlrunProject(ModelObj):
|
|
|
4055
4095
|
:param requirements_file: requirements file to install on the built image
|
|
4056
4096
|
:param overwrite_build_params: Overwrite existing build configuration (currently applies to
|
|
4057
4097
|
requirements and commands)
|
|
4098
|
+
|
|
4058
4099
|
* False: The new params are merged with the existing
|
|
4059
4100
|
* True: The existing params are replaced by the new ones
|
|
4101
|
+
|
|
4060
4102
|
:param builder_env: Kaniko builder pod env vars dict (for config/credentials)
|
|
4061
4103
|
e.g. builder_env={"GIT_TOKEN": token}, does not work yet in KFP
|
|
4062
4104
|
:param extra_args: A string containing additional builder arguments in the format of command-line options,
|
|
@@ -4128,8 +4170,10 @@ class MlrunProject(ModelObj):
|
|
|
4128
4170
|
e.g. builder_env={"GIT_TOKEN": token}, does not work yet in KFP
|
|
4129
4171
|
:param overwrite_build_params: Overwrite existing build configuration (currently applies to
|
|
4130
4172
|
requirements and commands)
|
|
4173
|
+
|
|
4131
4174
|
* False: The new params are merged with the existing
|
|
4132
4175
|
* True: The existing params are replaced by the new ones
|
|
4176
|
+
|
|
4133
4177
|
:param extra_args: A string containing additional builder arguments in the format of command-line options,
|
|
4134
4178
|
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
4135
4179
|
:param target_dir: Path on the image where source code would be extracted (by default `/home/mlrun_code`)
|
|
@@ -4307,12 +4351,14 @@ class MlrunProject(ModelObj):
|
|
|
4307
4351
|
``my_Name_1`` or ``surname``.
|
|
4308
4352
|
:param tag: Return artifacts assigned this tag.
|
|
4309
4353
|
:param labels: Filter artifacts by label key-value pairs or key existence. This can be provided as:
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4354
|
+
|
|
4355
|
+
- A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
|
|
4356
|
+
or `{"label": None}` to check for key existence.
|
|
4357
|
+
- A list of strings formatted as `"label=value"` to match specific label key-value pairs,
|
|
4358
|
+
or just `"label"` for key existence.
|
|
4359
|
+
- A comma-separated string formatted as `"label1=value1,label2"` to match entities with
|
|
4360
|
+
the specified key-value pairs or key existence.
|
|
4361
|
+
|
|
4316
4362
|
:param since: Not in use in :py:class:`HTTPRunDB`.
|
|
4317
4363
|
:param until: Not in use in :py:class:`HTTPRunDB`.
|
|
4318
4364
|
:param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
|
|
@@ -4323,7 +4369,7 @@ class MlrunProject(ModelObj):
|
|
|
4323
4369
|
:param kind: Return artifacts of the requested kind.
|
|
4324
4370
|
:param category: Return artifacts of the requested category.
|
|
4325
4371
|
:param tree: Return artifacts of the requested tree.
|
|
4326
|
-
:param limit: Maximum number of artifacts to return.
|
|
4372
|
+
:param limit: Deprecated - Maximum number of artifacts to return (will be removed in 1.11.0).
|
|
4327
4373
|
:param format_: The format in which to return the artifacts. Default is 'full'.
|
|
4328
4374
|
:param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
|
|
4329
4375
|
parameter must be provided as well.
|
|
@@ -4334,6 +4380,14 @@ class MlrunProject(ModelObj):
|
|
|
4334
4380
|
:param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
|
|
4335
4381
|
"""
|
|
4336
4382
|
db = mlrun.db.get_run_db(secrets=self._secrets)
|
|
4383
|
+
|
|
4384
|
+
if limit:
|
|
4385
|
+
# TODO: Remove this in 1.11.0
|
|
4386
|
+
warnings.warn(
|
|
4387
|
+
"'limit' is deprecated and will be removed in 1.11.0. Use 'page' and 'page_size' instead.",
|
|
4388
|
+
FutureWarning,
|
|
4389
|
+
)
|
|
4390
|
+
|
|
4337
4391
|
return db.list_artifacts(
|
|
4338
4392
|
name,
|
|
4339
4393
|
self.metadata.name,
|
|
@@ -4446,12 +4500,14 @@ class MlrunProject(ModelObj):
|
|
|
4446
4500
|
``my_Name_1`` or ``surname``.
|
|
4447
4501
|
:param tag: Return artifacts assigned this tag.
|
|
4448
4502
|
:param labels: Filter model artifacts by label key-value pairs or key existence. This can be provided as:
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4503
|
+
|
|
4504
|
+
- A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
|
|
4505
|
+
or `{"label": None}` to check for key existence.
|
|
4506
|
+
- A list of strings formatted as `"label=value"` to match specific label key-value pairs,
|
|
4507
|
+
or just `"label"` for key existence.
|
|
4508
|
+
- A comma-separated string formatted as `"label1=value1,label2"` to match entities with
|
|
4509
|
+
the specified key-value pairs or key existence.
|
|
4510
|
+
|
|
4455
4511
|
:param since: Not in use in :py:class:`HTTPRunDB`.
|
|
4456
4512
|
:param until: Not in use in :py:class:`HTTPRunDB`.
|
|
4457
4513
|
:param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
|
|
@@ -4557,12 +4613,14 @@ class MlrunProject(ModelObj):
|
|
|
4557
4613
|
:param name: Return only functions with a specific name.
|
|
4558
4614
|
:param tag: Return function versions with specific tags. To return only tagged functions, set tag to ``"*"``.
|
|
4559
4615
|
:param labels: Filter functions by label key-value pairs or key existence. This can be provided as:
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4616
|
+
|
|
4617
|
+
- A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
|
|
4618
|
+
or `{"label": None}` to check for key existence.
|
|
4619
|
+
- A list of strings formatted as `"label=value"` to match specific label key-value pairs,
|
|
4620
|
+
or just `"label"` for key existence.
|
|
4621
|
+
- A comma-separated string formatted as `"label1=value1,label2"` to match entities with
|
|
4622
|
+
the specified key-value pairs or key existence.
|
|
4623
|
+
|
|
4566
4624
|
:param kind: Return functions of the specified kind. If not provided, all function kinds will be returned.
|
|
4567
4625
|
:param format_: The format in which to return the functions. Default is 'full'.
|
|
4568
4626
|
:returns: List of function objects.
|
|
@@ -4656,12 +4714,14 @@ class MlrunProject(ModelObj):
|
|
|
4656
4714
|
:param name: Return only functions with a specific name.
|
|
4657
4715
|
:param tag: Return function versions with specific tags.
|
|
4658
4716
|
:param labels: Filter functions by label key-value pairs or key existence. This can be provided as:
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4717
|
+
|
|
4718
|
+
- A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
|
|
4719
|
+
or `{"label": None}` to check for key existence.
|
|
4720
|
+
- A list of strings formatted as `"label=value"` to match specific label key-value pairs,
|
|
4721
|
+
or just `"label"` for key existence.
|
|
4722
|
+
- A comma-separated string formatted as `"label1=value1,label2"` to match entities with
|
|
4723
|
+
the specified key-value pairs or key existence.
|
|
4724
|
+
|
|
4665
4725
|
:returns: List of function objects.
|
|
4666
4726
|
"""
|
|
4667
4727
|
|
|
@@ -4717,12 +4777,14 @@ class MlrunProject(ModelObj):
|
|
|
4717
4777
|
:param name: Name of the run to retrieve.
|
|
4718
4778
|
:param uid: Unique ID of the run.
|
|
4719
4779
|
:param labels: Filter runs by label key-value pairs or key existence. This can be provided as:
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4780
|
+
|
|
4781
|
+
- A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
|
|
4782
|
+
or `{"label": None}` to check for key existence.
|
|
4783
|
+
- A list of strings formatted as `"label=value"` to match specific label key-value pairs,
|
|
4784
|
+
or just `"label"` for key existence.
|
|
4785
|
+
- A comma-separated string formatted as `"label1=value1,label2"` to match entities with
|
|
4786
|
+
the specified key-value pairs or key existence.
|
|
4787
|
+
|
|
4726
4788
|
:param state: Deprecated - List only runs whose state is specified.
|
|
4727
4789
|
:param states: List only runs whose state is one of the provided states.
|
|
4728
4790
|
:param sort: Whether to sort the result according to their start time. Otherwise, results will be
|
mlrun/render.py
CHANGED
|
@@ -361,9 +361,6 @@ def get_tblframe(df, display, classes=None):
|
|
|
361
361
|
return ipython_display(html, display)
|
|
362
362
|
|
|
363
363
|
|
|
364
|
-
uid_template = '<div title="{}"><a href="{}/{}/{}/jobs/monitor/{}/overview" target="_blank" >...{}</a></div>'
|
|
365
|
-
|
|
366
|
-
|
|
367
364
|
def runs_to_html(
|
|
368
365
|
df: pd.DataFrame,
|
|
369
366
|
display: bool = True,
|
|
@@ -379,15 +376,14 @@ def runs_to_html(
|
|
|
379
376
|
df["results"] = df["results"].apply(dict_html)
|
|
380
377
|
df["start"] = df["start"].apply(time_str)
|
|
381
378
|
df["parameters"] = df["parameters"].apply(dict_html)
|
|
379
|
+
uid_template = '<div title="{}"><a href="{}" target="_blank" >...{}</a></div>'
|
|
380
|
+
|
|
382
381
|
if config.resolve_ui_url():
|
|
383
382
|
df["uid"] = df.apply(
|
|
384
383
|
lambda x: uid_template.format(
|
|
385
|
-
x
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
x.project,
|
|
389
|
-
x.uid,
|
|
390
|
-
x.uid[-8:],
|
|
384
|
+
x["uid"],
|
|
385
|
+
mlrun.utils.get_run_url(x["project"], x["uid"], x["name"]),
|
|
386
|
+
x["uid"][-8:],
|
|
391
387
|
),
|
|
392
388
|
axis=1,
|
|
393
389
|
)
|
mlrun/runtimes/base.py
CHANGED
|
@@ -499,7 +499,7 @@ class BaseRuntime(ModelObj):
|
|
|
499
499
|
def _store_function(self, runspec, meta, db):
|
|
500
500
|
meta.labels["kind"] = self.kind
|
|
501
501
|
mlrun.runtimes.utils.enrich_run_labels(
|
|
502
|
-
meta.labels, [
|
|
502
|
+
meta.labels, [mlrun_constants.MLRunInternalLabels.owner]
|
|
503
503
|
)
|
|
504
504
|
if runspec.spec.output_path:
|
|
505
505
|
runspec.spec.output_path = runspec.spec.output_path.replace(
|
mlrun/runtimes/utils.py
CHANGED
|
@@ -11,6 +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
|
+
import enum
|
|
14
15
|
import getpass
|
|
15
16
|
import hashlib
|
|
16
17
|
import json
|
|
@@ -28,7 +29,6 @@ import mlrun.common.constants as mlrun_constants
|
|
|
28
29
|
import mlrun.common.schemas
|
|
29
30
|
import mlrun.utils.regex
|
|
30
31
|
from mlrun.artifacts import TableArtifact
|
|
31
|
-
from mlrun.common.runtimes.constants import RunLabels
|
|
32
32
|
from mlrun.config import config
|
|
33
33
|
from mlrun.errors import err_to_str
|
|
34
34
|
from mlrun.frameworks.parallel_coordinates import gen_pcp_plot
|
|
@@ -433,18 +433,35 @@ def enrich_function_from_dict(function, function_dict):
|
|
|
433
433
|
|
|
434
434
|
def enrich_run_labels(
|
|
435
435
|
labels: dict,
|
|
436
|
-
labels_to_enrich: Optional[list[
|
|
436
|
+
labels_to_enrich: Optional[list[mlrun_constants.MLRunInternalLabels]] = None,
|
|
437
437
|
):
|
|
438
|
+
"""
|
|
439
|
+
Enrich the run labels with the internal labels and the labels enrichment extension
|
|
440
|
+
:param labels: The run labels dict
|
|
441
|
+
:param labels_to_enrich: The label keys to enrich from MLRunInternalLabels.default_run_labels_to_enrich
|
|
442
|
+
:return: The enriched labels dict
|
|
443
|
+
"""
|
|
444
|
+
# Merge the labels with the labels enrichment extension
|
|
438
445
|
labels_enrichment = {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
446
|
+
mlrun_constants.MLRunInternalLabels.owner: os.environ.get("V3IO_USERNAME")
|
|
447
|
+
or getpass.getuser(),
|
|
448
|
+
# TODO: remove this in 1.10.0
|
|
449
|
+
mlrun_constants.MLRunInternalLabels.v3io_user: os.environ.get("V3IO_USERNAME"),
|
|
442
450
|
}
|
|
443
|
-
|
|
451
|
+
|
|
452
|
+
# Resolve which label keys to enrich
|
|
453
|
+
if labels_to_enrich is None:
|
|
454
|
+
labels_to_enrich = (
|
|
455
|
+
mlrun_constants.MLRunInternalLabels.default_run_labels_to_enrich()
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
# Enrich labels
|
|
444
459
|
for label in labels_to_enrich:
|
|
460
|
+
if isinstance(label, enum.Enum):
|
|
461
|
+
label = label.value
|
|
445
462
|
enrichment = labels_enrichment.get(label)
|
|
446
|
-
if label
|
|
447
|
-
labels[label
|
|
463
|
+
if label not in labels and enrichment:
|
|
464
|
+
labels[label] = enrichment
|
|
448
465
|
return labels
|
|
449
466
|
|
|
450
467
|
|