mlrun 1.7.0rc14__py3-none-any.whl → 1.7.0rc22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +10 -1
- mlrun/__main__.py +23 -111
- mlrun/alerts/__init__.py +15 -0
- mlrun/alerts/alert.py +169 -0
- mlrun/api/schemas/__init__.py +4 -3
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +36 -253
- mlrun/artifacts/dataset.py +9 -190
- mlrun/artifacts/manager.py +46 -42
- mlrun/artifacts/model.py +9 -141
- mlrun/artifacts/plots.py +14 -375
- mlrun/common/constants.py +65 -3
- mlrun/common/formatters/__init__.py +19 -0
- mlrun/{runtimes/mpijob/v1alpha1.py → common/formatters/artifact.py} +6 -14
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/function.py +46 -0
- mlrun/common/formatters/pipeline.py +53 -0
- mlrun/common/formatters/project.py +51 -0
- mlrun/{runtimes → common/runtimes}/constants.py +32 -4
- mlrun/common/schemas/__init__.py +10 -5
- mlrun/common/schemas/alert.py +92 -11
- mlrun/common/schemas/api_gateway.py +56 -0
- mlrun/common/schemas/artifact.py +15 -5
- mlrun/common/schemas/auth.py +2 -0
- mlrun/common/schemas/client_spec.py +1 -0
- mlrun/common/schemas/frontend_spec.py +1 -0
- mlrun/common/schemas/function.py +4 -0
- mlrun/common/schemas/model_monitoring/__init__.py +15 -3
- mlrun/common/schemas/model_monitoring/constants.py +58 -7
- mlrun/common/schemas/model_monitoring/grafana.py +9 -5
- mlrun/common/schemas/model_monitoring/model_endpoints.py +86 -2
- mlrun/common/schemas/pipeline.py +0 -9
- mlrun/common/schemas/project.py +5 -11
- mlrun/common/types.py +1 -0
- mlrun/config.py +30 -9
- mlrun/data_types/to_pandas.py +9 -9
- mlrun/datastore/base.py +41 -9
- mlrun/datastore/datastore.py +6 -2
- mlrun/datastore/datastore_profile.py +56 -4
- mlrun/datastore/inmem.py +2 -2
- mlrun/datastore/redis.py +2 -2
- mlrun/datastore/s3.py +5 -0
- mlrun/datastore/sources.py +147 -7
- mlrun/datastore/store_resources.py +7 -7
- mlrun/datastore/targets.py +110 -42
- mlrun/datastore/utils.py +42 -0
- mlrun/db/base.py +54 -10
- mlrun/db/httpdb.py +282 -79
- mlrun/db/nopdb.py +52 -10
- mlrun/errors.py +11 -0
- mlrun/execution.py +26 -9
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +12 -47
- mlrun/feature_store/feature_set.py +9 -0
- mlrun/feature_store/feature_vector.py +8 -0
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +9 -4
- mlrun/feature_store/retrieval/conversion.py +9 -9
- mlrun/feature_store/retrieval/dask_merger.py +2 -0
- mlrun/feature_store/retrieval/job.py +9 -3
- mlrun/feature_store/retrieval/local_merger.py +2 -0
- mlrun/feature_store/retrieval/spark_merger.py +16 -0
- mlrun/frameworks/__init__.py +6 -0
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
- mlrun/frameworks/parallel_coordinates.py +2 -1
- mlrun/frameworks/tf_keras/__init__.py +4 -1
- mlrun/k8s_utils.py +10 -11
- mlrun/launcher/base.py +4 -3
- mlrun/launcher/client.py +5 -3
- mlrun/launcher/local.py +12 -2
- mlrun/launcher/remote.py +9 -2
- mlrun/lists.py +6 -2
- mlrun/model.py +47 -21
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +42 -18
- mlrun/model_monitoring/application.py +5 -305
- mlrun/model_monitoring/applications/__init__.py +11 -0
- mlrun/model_monitoring/applications/_application_steps.py +157 -0
- mlrun/model_monitoring/applications/base.py +280 -0
- mlrun/model_monitoring/applications/context.py +214 -0
- mlrun/model_monitoring/applications/evidently_base.py +211 -0
- mlrun/model_monitoring/applications/histogram_data_drift.py +132 -91
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +3 -1
- mlrun/model_monitoring/db/__init__.py +2 -0
- mlrun/model_monitoring/db/stores/__init__.py +0 -2
- mlrun/model_monitoring/db/stores/base/store.py +22 -37
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +43 -21
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +39 -8
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +27 -7
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +5 -0
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +246 -224
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +232 -216
- mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
- mlrun/model_monitoring/db/tsdb/base.py +316 -0
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +401 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +658 -0
- mlrun/model_monitoring/evidently_application.py +6 -118
- mlrun/model_monitoring/helpers.py +63 -1
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +57 -216
- mlrun/model_monitoring/writer.py +134 -124
- mlrun/package/__init__.py +13 -1
- mlrun/package/packagers/__init__.py +6 -1
- mlrun/package/utils/_formatter.py +2 -2
- mlrun/platforms/__init__.py +10 -9
- mlrun/platforms/iguazio.py +21 -202
- mlrun/projects/operations.py +24 -12
- mlrun/projects/pipelines.py +79 -102
- mlrun/projects/project.py +271 -103
- mlrun/render.py +15 -14
- mlrun/run.py +16 -46
- mlrun/runtimes/__init__.py +6 -3
- mlrun/runtimes/base.py +14 -7
- mlrun/runtimes/daskjob.py +1 -0
- mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +0 -28
- mlrun/runtimes/kubejob.py +2 -1
- mlrun/runtimes/local.py +12 -3
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/runtimes/nuclio/api_gateway.py +194 -84
- mlrun/runtimes/nuclio/application/application.py +170 -8
- mlrun/runtimes/nuclio/function.py +39 -49
- mlrun/runtimes/pod.py +16 -36
- mlrun/runtimes/remotesparkjob.py +9 -3
- mlrun/runtimes/sparkjob/spark3job.py +1 -1
- mlrun/runtimes/utils.py +6 -45
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/server.py +2 -1
- mlrun/serving/states.py +51 -8
- mlrun/serving/utils.py +19 -11
- mlrun/serving/v2_serving.py +5 -1
- mlrun/track/tracker.py +2 -1
- mlrun/utils/async_http.py +25 -5
- mlrun/utils/helpers.py +157 -83
- mlrun/utils/logger.py +39 -7
- mlrun/utils/notifications/notification/__init__.py +14 -9
- mlrun/utils/notifications/notification/base.py +1 -1
- mlrun/utils/notifications/notification/slack.py +34 -7
- mlrun/utils/notifications/notification/webhook.py +1 -1
- mlrun/utils/notifications/notification_pusher.py +147 -16
- mlrun/utils/regex.py +9 -0
- mlrun/utils/v3io_clients.py +0 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/METADATA +14 -6
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/RECORD +158 -138
- mlrun/kfpops.py +0 -865
- mlrun/platforms/other.py +0 -305
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/WHEEL +0 -0
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc22.dist-info}/top_level.txt +0 -0
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
|
+
|
|
15
16
|
import pandas as pd
|
|
16
17
|
import semver
|
|
17
18
|
|
|
18
19
|
import mlrun
|
|
20
|
+
from mlrun.datastore.sources import ParquetSource
|
|
19
21
|
from mlrun.datastore.targets import get_offline_target
|
|
22
|
+
from mlrun.utils.helpers import additional_filters_warning
|
|
20
23
|
|
|
21
24
|
from ...runtimes import RemoteSparkRuntime
|
|
22
25
|
from ...runtimes.sparkjob import Spark3Runtime
|
|
@@ -225,7 +228,12 @@ class SparkFeatureMerger(BaseMerger):
|
|
|
225
228
|
start_time=None,
|
|
226
229
|
end_time=None,
|
|
227
230
|
time_column=None,
|
|
231
|
+
additional_filters=None,
|
|
228
232
|
):
|
|
233
|
+
mlrun.utils.helpers.additional_filters_warning(
|
|
234
|
+
additional_filters, self.__class__
|
|
235
|
+
)
|
|
236
|
+
|
|
229
237
|
source_kwargs = {}
|
|
230
238
|
if feature_set.spec.passthrough:
|
|
231
239
|
if not feature_set.spec.source:
|
|
@@ -235,6 +243,7 @@ class SparkFeatureMerger(BaseMerger):
|
|
|
235
243
|
source_kind = feature_set.spec.source.kind
|
|
236
244
|
source_path = feature_set.spec.source.path
|
|
237
245
|
source_kwargs.update(feature_set.spec.source.attributes)
|
|
246
|
+
source_kwargs.pop("additional_filters", None)
|
|
238
247
|
else:
|
|
239
248
|
target = get_offline_target(feature_set)
|
|
240
249
|
if not target:
|
|
@@ -248,12 +257,19 @@ class SparkFeatureMerger(BaseMerger):
|
|
|
248
257
|
# entity_timestamp_column is from a specific feature set (can't be entity timestamp)
|
|
249
258
|
source_driver = mlrun.datastore.sources.source_kind_to_driver[source_kind]
|
|
250
259
|
|
|
260
|
+
if source_driver != ParquetSource:
|
|
261
|
+
additional_filters_warning(additional_filters, source_driver)
|
|
262
|
+
additional_filters = None
|
|
263
|
+
additional_filters_dict = (
|
|
264
|
+
{"additional_filters": additional_filters} if additional_filters else {}
|
|
265
|
+
)
|
|
251
266
|
source = source_driver(
|
|
252
267
|
name=self.vector.metadata.name,
|
|
253
268
|
path=source_path,
|
|
254
269
|
time_field=time_column,
|
|
255
270
|
start_time=start_time,
|
|
256
271
|
end_time=end_time,
|
|
272
|
+
**additional_filters_dict,
|
|
257
273
|
**source_kwargs,
|
|
258
274
|
)
|
|
259
275
|
|
mlrun/frameworks/__init__.py
CHANGED
|
@@ -12,5 +12,11 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
|
+
"""
|
|
16
|
+
MLRun provides a quick and easy integration into your code with mlrun.frameworks: a collection of sub-modules
|
|
17
|
+
for the most commonly used machine and deep learning frameworks, providing features such as automatic logging,
|
|
18
|
+
model management, and distributed training.
|
|
19
|
+
"""
|
|
20
|
+
|
|
15
21
|
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
22
|
from .parallel_coordinates import compare_db_runs, compare_run_objects
|
|
@@ -547,9 +547,9 @@ class TensorboardLogger(Logger, Generic[DLTypes.WeightType]):
|
|
|
547
547
|
"inputs",
|
|
548
548
|
"parameters",
|
|
549
549
|
]:
|
|
550
|
-
text +=
|
|
551
|
-
property_name.capitalize()
|
|
552
|
-
self._markdown_print(value=property_value, tabs=2)
|
|
550
|
+
text += (
|
|
551
|
+
f"\n * **{property_name.capitalize()}**: "
|
|
552
|
+
f"{self._markdown_print(value=property_value, tabs=2)}"
|
|
553
553
|
)
|
|
554
554
|
else:
|
|
555
555
|
for property_name, property_value in self._extract_epoch_results().items():
|
|
@@ -614,13 +614,8 @@ class TensorboardLogger(Logger, Generic[DLTypes.WeightType]):
|
|
|
614
614
|
:return: The generated link.
|
|
615
615
|
"""
|
|
616
616
|
return (
|
|
617
|
-
'<a href="{}/{}/{}
|
|
618
|
-
|
|
619
|
-
config.ui.projects_prefix,
|
|
620
|
-
context.project,
|
|
621
|
-
context.uid,
|
|
622
|
-
link_text,
|
|
623
|
-
)
|
|
617
|
+
f'<a href="{config.resolve_ui_url()}/{config.ui.projects_prefix}/{context.project}'
|
|
618
|
+
f'/jobs/monitor/{context.uid}/overview" target="_blank">{link_text}</a>'
|
|
624
619
|
)
|
|
625
620
|
|
|
626
621
|
@staticmethod
|
|
@@ -653,13 +648,13 @@ class TensorboardLogger(Logger, Generic[DLTypes.WeightType]):
|
|
|
653
648
|
if isinstance(value, list):
|
|
654
649
|
if len(value) == 0:
|
|
655
650
|
return ""
|
|
656
|
-
text = "\n" + yaml.
|
|
651
|
+
text = "\n" + yaml.safe_dump(value)
|
|
657
652
|
text = " \n".join([" " * tabs + line for line in text.splitlines()])
|
|
658
653
|
return text
|
|
659
654
|
if isinstance(value, dict):
|
|
660
655
|
if len(value) == 0:
|
|
661
656
|
return ""
|
|
662
|
-
text = yaml.
|
|
657
|
+
text = yaml.safe_dump(value)
|
|
663
658
|
text = " \n".join(
|
|
664
659
|
[" " * tabs + "- " + line for line in text.splitlines()]
|
|
665
660
|
)
|
|
@@ -295,7 +295,7 @@ def compare_db_runs(
|
|
|
295
295
|
iter=False,
|
|
296
296
|
start_time_from: datetime = None,
|
|
297
297
|
hide_identical: bool = True,
|
|
298
|
-
exclude: list =
|
|
298
|
+
exclude: list = None,
|
|
299
299
|
show=None,
|
|
300
300
|
colorscale: str = "Blues",
|
|
301
301
|
filename=None,
|
|
@@ -332,6 +332,7 @@ def compare_db_runs(
|
|
|
332
332
|
**query_args,
|
|
333
333
|
)
|
|
334
334
|
|
|
335
|
+
exclude = exclude or []
|
|
335
336
|
runs_df = _runs_list_to_df(runs_list)
|
|
336
337
|
plot_as_html = gen_pcp_plot(
|
|
337
338
|
runs_df,
|
|
@@ -18,6 +18,7 @@ from typing import Any, Union
|
|
|
18
18
|
from tensorflow import keras
|
|
19
19
|
|
|
20
20
|
import mlrun
|
|
21
|
+
import mlrun.common.constants as mlrun_constants
|
|
21
22
|
|
|
22
23
|
from .callbacks import MLRunLoggingCallback, TensorboardLoggingCallback
|
|
23
24
|
from .mlrun_interface import TFKerasMLRunInterface
|
|
@@ -126,7 +127,9 @@ def apply_mlrun(
|
|
|
126
127
|
# # Use horovod:
|
|
127
128
|
if use_horovod is None:
|
|
128
129
|
use_horovod = (
|
|
129
|
-
context.labels.get(
|
|
130
|
+
context.labels.get(mlrun_constants.MLRunInternalLabels.kind, "") == "mpijob"
|
|
131
|
+
if context is not None
|
|
132
|
+
else False
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
# Create a model handler:
|
mlrun/k8s_utils.py
CHANGED
|
@@ -141,17 +141,6 @@ def verify_label_key(key: str):
|
|
|
141
141
|
if not key:
|
|
142
142
|
raise mlrun.errors.MLRunInvalidArgumentError("label key cannot be empty")
|
|
143
143
|
|
|
144
|
-
mlrun.utils.helpers.verify_field_regex(
|
|
145
|
-
f"project.metadata.labels.'{key}'",
|
|
146
|
-
key,
|
|
147
|
-
mlrun.utils.regex.k8s_character_limit,
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
if key.startswith("k8s.io/") or key.startswith("kubernetes.io/"):
|
|
151
|
-
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
152
|
-
"Labels cannot start with 'k8s.io/' or 'kubernetes.io/'"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
144
|
parts = key.split("/")
|
|
156
145
|
if len(parts) == 1:
|
|
157
146
|
name = parts[0]
|
|
@@ -173,12 +162,22 @@ def verify_label_key(key: str):
|
|
|
173
162
|
"Label key can only contain one '/'"
|
|
174
163
|
)
|
|
175
164
|
|
|
165
|
+
mlrun.utils.helpers.verify_field_regex(
|
|
166
|
+
f"project.metadata.labels.'{key}'",
|
|
167
|
+
name,
|
|
168
|
+
mlrun.utils.regex.k8s_character_limit,
|
|
169
|
+
)
|
|
176
170
|
mlrun.utils.helpers.verify_field_regex(
|
|
177
171
|
f"project.metadata.labels.'{key}'",
|
|
178
172
|
name,
|
|
179
173
|
mlrun.utils.regex.qualified_name,
|
|
180
174
|
)
|
|
181
175
|
|
|
176
|
+
if key.startswith("k8s.io/") or key.startswith("kubernetes.io/"):
|
|
177
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
178
|
+
"Labels cannot start with 'k8s.io/' or 'kubernetes.io/'"
|
|
179
|
+
)
|
|
180
|
+
|
|
182
181
|
|
|
183
182
|
def verify_label_value(value, label_key):
|
|
184
183
|
mlrun.utils.helpers.verify_field_regex(
|
mlrun/launcher/base.py
CHANGED
|
@@ -18,10 +18,11 @@ import os
|
|
|
18
18
|
import uuid
|
|
19
19
|
from typing import Any, Callable, Optional, Union
|
|
20
20
|
|
|
21
|
+
import mlrun_pipelines.common.ops
|
|
22
|
+
|
|
21
23
|
import mlrun.common.schemas
|
|
22
24
|
import mlrun.config
|
|
23
25
|
import mlrun.errors
|
|
24
|
-
import mlrun.kfpops
|
|
25
26
|
import mlrun.lists
|
|
26
27
|
import mlrun.model
|
|
27
28
|
import mlrun.runtimes
|
|
@@ -390,7 +391,7 @@ class BaseLauncher(abc.ABC):
|
|
|
390
391
|
return
|
|
391
392
|
|
|
392
393
|
if result and runtime.kfp and err is None:
|
|
393
|
-
|
|
394
|
+
mlrun_pipelines.common.ops.write_kfpmeta(result)
|
|
394
395
|
|
|
395
396
|
self._log_track_results(runtime.is_child, result, run)
|
|
396
397
|
|
|
@@ -403,7 +404,7 @@ class BaseLauncher(abc.ABC):
|
|
|
403
404
|
)
|
|
404
405
|
if (
|
|
405
406
|
run.status.state
|
|
406
|
-
in mlrun.runtimes.constants.RunStates.error_and_abortion_states()
|
|
407
|
+
in mlrun.common.runtimes.constants.RunStates.error_and_abortion_states()
|
|
407
408
|
):
|
|
408
409
|
if runtime._is_remote and not runtime.is_child:
|
|
409
410
|
logger.error(
|
mlrun/launcher/client.py
CHANGED
|
@@ -16,6 +16,7 @@ from typing import Optional
|
|
|
16
16
|
|
|
17
17
|
import IPython
|
|
18
18
|
|
|
19
|
+
import mlrun.common.constants as mlrun_constants
|
|
19
20
|
import mlrun.errors
|
|
20
21
|
import mlrun.launcher.base as launcher
|
|
21
22
|
import mlrun.lists
|
|
@@ -69,13 +70,14 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
|
|
|
69
70
|
def _store_function(
|
|
70
71
|
runtime: "mlrun.runtimes.BaseRuntime", run: "mlrun.run.RunObject"
|
|
71
72
|
):
|
|
72
|
-
run.metadata.labels[
|
|
73
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.kind] = runtime.kind
|
|
73
74
|
mlrun.runtimes.utils.enrich_run_labels(
|
|
74
|
-
run.metadata.labels, [mlrun.runtimes.constants.RunLabels.owner]
|
|
75
|
+
run.metadata.labels, [mlrun.common.runtimes.constants.RunLabels.owner]
|
|
75
76
|
)
|
|
76
77
|
if run.spec.output_path:
|
|
77
78
|
run.spec.output_path = run.spec.output_path.replace(
|
|
78
|
-
"{{run.user}}",
|
|
79
|
+
"{{run.user}}",
|
|
80
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.owner],
|
|
79
81
|
)
|
|
80
82
|
db = runtime._get_db()
|
|
81
83
|
if db and runtime.kind != "handler":
|
mlrun/launcher/local.py
CHANGED
|
@@ -15,6 +15,7 @@ import os
|
|
|
15
15
|
import pathlib
|
|
16
16
|
from typing import Callable, Optional, Union
|
|
17
17
|
|
|
18
|
+
import mlrun.common.constants as mlrun_constants
|
|
18
19
|
import mlrun.common.schemas.schedule
|
|
19
20
|
import mlrun.errors
|
|
20
21
|
import mlrun.launcher.client as launcher
|
|
@@ -68,6 +69,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
68
69
|
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
69
70
|
returns: Optional[list[Union[str, dict[str, str]]]] = None,
|
|
70
71
|
state_thresholds: Optional[dict[str, int]] = None,
|
|
72
|
+
reset_on_run: Optional[bool] = None,
|
|
71
73
|
) -> "mlrun.run.RunObject":
|
|
72
74
|
# do not allow local function to be scheduled
|
|
73
75
|
if self._is_run_local and schedule is not None:
|
|
@@ -87,6 +89,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
87
89
|
name=name,
|
|
88
90
|
workdir=workdir,
|
|
89
91
|
handler=handler,
|
|
92
|
+
reset_on_run=reset_on_run,
|
|
90
93
|
)
|
|
91
94
|
|
|
92
95
|
# sanity check
|
|
@@ -132,8 +135,13 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
132
135
|
runtime: "mlrun.runtimes.BaseRuntime",
|
|
133
136
|
run: Optional[Union["mlrun.run.RunTemplate", "mlrun.run.RunObject"]] = None,
|
|
134
137
|
):
|
|
135
|
-
if
|
|
136
|
-
|
|
138
|
+
if (
|
|
139
|
+
"V3IO_USERNAME" in os.environ
|
|
140
|
+
and mlrun_constants.MLRunInternalLabels.v3io_user not in run.metadata.labels
|
|
141
|
+
):
|
|
142
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.v3io_user] = (
|
|
143
|
+
os.environ.get("V3IO_USERNAME")
|
|
144
|
+
)
|
|
137
145
|
|
|
138
146
|
# store function object in db unless running from within a run pod
|
|
139
147
|
if not runtime.is_child:
|
|
@@ -206,6 +214,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
206
214
|
name: Optional[str] = "",
|
|
207
215
|
workdir: Optional[str] = "",
|
|
208
216
|
handler: Optional[str] = None,
|
|
217
|
+
reset_on_run: Optional[bool] = None,
|
|
209
218
|
):
|
|
210
219
|
project = project or runtime.metadata.project
|
|
211
220
|
function_name = name or runtime.metadata.name
|
|
@@ -244,6 +253,7 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
244
253
|
fn.spec.build = runtime.spec.build
|
|
245
254
|
|
|
246
255
|
run.spec.handler = handler
|
|
256
|
+
run.spec.reset_on_run = reset_on_run
|
|
247
257
|
return fn
|
|
248
258
|
|
|
249
259
|
@staticmethod
|
mlrun/launcher/remote.py
CHANGED
|
@@ -17,6 +17,7 @@ from typing import Optional, Union
|
|
|
17
17
|
import pandas as pd
|
|
18
18
|
import requests
|
|
19
19
|
|
|
20
|
+
import mlrun.common.constants as mlrun_constants
|
|
20
21
|
import mlrun.common.schemas.schedule
|
|
21
22
|
import mlrun.db
|
|
22
23
|
import mlrun.errors
|
|
@@ -58,6 +59,7 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
58
59
|
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
59
60
|
returns: Optional[list[Union[str, dict[str, str]]]] = None,
|
|
60
61
|
state_thresholds: Optional[dict[str, int]] = None,
|
|
62
|
+
reset_on_run: Optional[bool] = None,
|
|
61
63
|
) -> "mlrun.run.RunObject":
|
|
62
64
|
self.enrich_runtime(runtime, project)
|
|
63
65
|
run = self._create_run_object(task)
|
|
@@ -100,8 +102,13 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
100
102
|
if runtime.verbose:
|
|
101
103
|
logger.info(f"runspec:\n{run.to_yaml()}")
|
|
102
104
|
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
+
if (
|
|
106
|
+
"V3IO_USERNAME" in os.environ
|
|
107
|
+
and mlrun_constants.MLRunInternalLabels.v3io_user not in run.metadata.labels
|
|
108
|
+
):
|
|
109
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.v3io_user] = (
|
|
110
|
+
os.environ.get("V3IO_USERNAME")
|
|
111
|
+
)
|
|
105
112
|
|
|
106
113
|
logger.info(
|
|
107
114
|
"Storing function",
|
mlrun/lists.py
CHANGED
|
@@ -21,7 +21,7 @@ import mlrun.frameworks
|
|
|
21
21
|
from .artifacts import Artifact, dict_to_artifact
|
|
22
22
|
from .config import config
|
|
23
23
|
from .render import artifacts_to_html, runs_to_html
|
|
24
|
-
from .utils import flatten, get_artifact_target, get_in
|
|
24
|
+
from .utils import flatten, get_artifact_target, get_in
|
|
25
25
|
|
|
26
26
|
list_header = [
|
|
27
27
|
"project",
|
|
@@ -29,12 +29,14 @@ list_header = [
|
|
|
29
29
|
"iter",
|
|
30
30
|
"start",
|
|
31
31
|
"state",
|
|
32
|
+
"kind",
|
|
32
33
|
"name",
|
|
33
34
|
"labels",
|
|
34
35
|
"inputs",
|
|
35
36
|
"parameters",
|
|
36
37
|
"results",
|
|
37
38
|
"artifacts",
|
|
39
|
+
"artifact_uris",
|
|
38
40
|
"error",
|
|
39
41
|
]
|
|
40
42
|
|
|
@@ -56,12 +58,14 @@ class RunList(list):
|
|
|
56
58
|
get_in(run, "metadata.iteration", ""),
|
|
57
59
|
get_in(run, "status.start_time", ""),
|
|
58
60
|
get_in(run, "status.state", ""),
|
|
61
|
+
get_in(run, "step_kind", get_in(run, "kind", "")),
|
|
59
62
|
get_in(run, "metadata.name", ""),
|
|
60
63
|
get_in(run, "metadata.labels", ""),
|
|
61
64
|
get_in(run, "spec.inputs", ""),
|
|
62
65
|
get_in(run, "spec.parameters", ""),
|
|
63
66
|
get_in(run, "status.results", ""),
|
|
64
67
|
get_in(run, "status.artifacts", []),
|
|
68
|
+
get_in(run, "status.artifact_uris", {}),
|
|
65
69
|
get_in(run, "status.error", ""),
|
|
66
70
|
]
|
|
67
71
|
if extend_iterations and iterations:
|
|
@@ -184,7 +188,7 @@ class ArtifactList(list):
|
|
|
184
188
|
"uri": ["uri", "uri"],
|
|
185
189
|
}
|
|
186
190
|
for artifact in self:
|
|
187
|
-
fields_index =
|
|
191
|
+
fields_index = 1
|
|
188
192
|
row = [get_in(artifact, v[fields_index], "") for k, v in head.items()]
|
|
189
193
|
artifact_uri = dict_to_artifact(artifact).uri
|
|
190
194
|
last_index = len(row) - 1
|
mlrun/model.py
CHANGED
|
@@ -27,13 +27,14 @@ from typing import Any, Optional, Union
|
|
|
27
27
|
import pydantic.error_wrappers
|
|
28
28
|
|
|
29
29
|
import mlrun
|
|
30
|
+
import mlrun.common.constants as mlrun_constants
|
|
30
31
|
import mlrun.common.schemas.notification
|
|
32
|
+
import mlrun.utils.regex
|
|
31
33
|
|
|
32
34
|
from .utils import (
|
|
33
35
|
dict_to_json,
|
|
34
36
|
dict_to_yaml,
|
|
35
37
|
get_artifact_target,
|
|
36
|
-
is_legacy_artifact,
|
|
37
38
|
logger,
|
|
38
39
|
template_artifact_path,
|
|
39
40
|
)
|
|
@@ -682,10 +683,14 @@ class Notification(ModelObj):
|
|
|
682
683
|
|
|
683
684
|
def __init__(
|
|
684
685
|
self,
|
|
685
|
-
kind=
|
|
686
|
+
kind: mlrun.common.schemas.notification.NotificationKind = (
|
|
687
|
+
mlrun.common.schemas.notification.NotificationKind.slack
|
|
688
|
+
),
|
|
686
689
|
name=None,
|
|
687
690
|
message=None,
|
|
688
|
-
severity=
|
|
691
|
+
severity: mlrun.common.schemas.notification.NotificationSeverity = (
|
|
692
|
+
mlrun.common.schemas.notification.NotificationSeverity.INFO
|
|
693
|
+
),
|
|
689
694
|
when=None,
|
|
690
695
|
condition=None,
|
|
691
696
|
secret_params=None,
|
|
@@ -694,12 +699,10 @@ class Notification(ModelObj):
|
|
|
694
699
|
sent_time=None,
|
|
695
700
|
reason=None,
|
|
696
701
|
):
|
|
697
|
-
self.kind = kind
|
|
702
|
+
self.kind = kind
|
|
698
703
|
self.name = name or ""
|
|
699
704
|
self.message = message or ""
|
|
700
|
-
self.severity =
|
|
701
|
-
severity or mlrun.common.schemas.notification.NotificationSeverity.INFO
|
|
702
|
-
)
|
|
705
|
+
self.severity = severity
|
|
703
706
|
self.when = when or ["completed"]
|
|
704
707
|
self.condition = condition or ""
|
|
705
708
|
self.secret_params = secret_params or {}
|
|
@@ -769,7 +772,10 @@ class RunMetadata(ModelObj):
|
|
|
769
772
|
def is_workflow_runner(self):
|
|
770
773
|
if not self.labels:
|
|
771
774
|
return False
|
|
772
|
-
return
|
|
775
|
+
return (
|
|
776
|
+
self.labels.get(mlrun_constants.MLRunInternalLabels.job_type, "")
|
|
777
|
+
== "workflow-runner"
|
|
778
|
+
)
|
|
773
779
|
|
|
774
780
|
|
|
775
781
|
class HyperParamStrategies:
|
|
@@ -866,6 +872,7 @@ class RunSpec(ModelObj):
|
|
|
866
872
|
returns=None,
|
|
867
873
|
notifications=None,
|
|
868
874
|
state_thresholds=None,
|
|
875
|
+
reset_on_run=None,
|
|
869
876
|
):
|
|
870
877
|
# A dictionary of parsing configurations that will be read from the inputs the user set. The keys are the inputs
|
|
871
878
|
# keys (parameter names) and the values are the type hint given in the input keys after the colon.
|
|
@@ -902,6 +909,7 @@ class RunSpec(ModelObj):
|
|
|
902
909
|
self.allow_empty_resources = allow_empty_resources
|
|
903
910
|
self._notifications = notifications or []
|
|
904
911
|
self.state_thresholds = state_thresholds or {}
|
|
912
|
+
self.reset_on_run = reset_on_run
|
|
905
913
|
|
|
906
914
|
def _serialize_field(
|
|
907
915
|
self, struct: dict, field_name: str = None, strip: bool = False
|
|
@@ -1208,6 +1216,7 @@ class RunStatus(ModelObj):
|
|
|
1208
1216
|
ui_url=None,
|
|
1209
1217
|
reason: str = None,
|
|
1210
1218
|
notifications: dict[str, Notification] = None,
|
|
1219
|
+
artifact_uris: dict[str, str] = None,
|
|
1211
1220
|
):
|
|
1212
1221
|
self.state = state or "created"
|
|
1213
1222
|
self.status_text = status_text
|
|
@@ -1222,6 +1231,8 @@ class RunStatus(ModelObj):
|
|
|
1222
1231
|
self.ui_url = ui_url
|
|
1223
1232
|
self.reason = reason
|
|
1224
1233
|
self.notifications = notifications or {}
|
|
1234
|
+
# Artifact key -> URI mapping, since the full artifacts are not stored in the runs DB table
|
|
1235
|
+
self.artifact_uris = artifact_uris or {}
|
|
1225
1236
|
|
|
1226
1237
|
def is_failed(self) -> Optional[bool]:
|
|
1227
1238
|
"""
|
|
@@ -1435,11 +1446,14 @@ class RunObject(RunTemplate):
|
|
|
1435
1446
|
unknown_error = ""
|
|
1436
1447
|
if (
|
|
1437
1448
|
self.status.state
|
|
1438
|
-
in mlrun.runtimes.constants.RunStates.abortion_states()
|
|
1449
|
+
in mlrun.common.runtimes.constants.RunStates.abortion_states()
|
|
1439
1450
|
):
|
|
1440
1451
|
unknown_error = "Run was aborted"
|
|
1441
1452
|
|
|
1442
|
-
elif
|
|
1453
|
+
elif (
|
|
1454
|
+
self.status.state
|
|
1455
|
+
in mlrun.common.runtimes.constants.RunStates.error_states()
|
|
1456
|
+
):
|
|
1443
1457
|
unknown_error = "Unknown error"
|
|
1444
1458
|
|
|
1445
1459
|
return (
|
|
@@ -1477,7 +1491,7 @@ class RunObject(RunTemplate):
|
|
|
1477
1491
|
outputs = {k: v for k, v in self.status.results.items()}
|
|
1478
1492
|
if self.status.artifacts:
|
|
1479
1493
|
for a in self.status.artifacts:
|
|
1480
|
-
key = a["
|
|
1494
|
+
key = a["metadata"]["key"]
|
|
1481
1495
|
outputs[key] = get_artifact_target(a, self.metadata.project)
|
|
1482
1496
|
return outputs
|
|
1483
1497
|
|
|
@@ -1520,7 +1534,10 @@ class RunObject(RunTemplate):
|
|
|
1520
1534
|
|
|
1521
1535
|
def state(self):
|
|
1522
1536
|
"""current run state"""
|
|
1523
|
-
if
|
|
1537
|
+
if (
|
|
1538
|
+
self.status.state
|
|
1539
|
+
in mlrun.common.runtimes.constants.RunStates.terminal_states()
|
|
1540
|
+
):
|
|
1524
1541
|
return self.status.state
|
|
1525
1542
|
self.refresh()
|
|
1526
1543
|
return self.status.state or "unknown"
|
|
@@ -1534,8 +1551,10 @@ class RunObject(RunTemplate):
|
|
|
1534
1551
|
iter=self.metadata.iteration,
|
|
1535
1552
|
)
|
|
1536
1553
|
if run:
|
|
1537
|
-
|
|
1538
|
-
|
|
1554
|
+
run_status = run.get("status", {})
|
|
1555
|
+
# Artifacts are not stored in the DB, so we need to preserve them here
|
|
1556
|
+
run_status["artifacts"] = self.status.artifacts
|
|
1557
|
+
self.status = RunStatus.from_dict(run_status)
|
|
1539
1558
|
return self
|
|
1540
1559
|
|
|
1541
1560
|
def show(self):
|
|
@@ -1582,7 +1601,7 @@ class RunObject(RunTemplate):
|
|
|
1582
1601
|
last_pull_log_time = None
|
|
1583
1602
|
logs_enabled = show_logs is not False
|
|
1584
1603
|
state = self.state()
|
|
1585
|
-
if state not in mlrun.runtimes.constants.RunStates.terminal_states():
|
|
1604
|
+
if state not in mlrun.common.runtimes.constants.RunStates.terminal_states():
|
|
1586
1605
|
logger.info(
|
|
1587
1606
|
f"run {self.metadata.name} is not completed yet, waiting for it to complete",
|
|
1588
1607
|
current_state=state,
|
|
@@ -1592,7 +1611,8 @@ class RunObject(RunTemplate):
|
|
|
1592
1611
|
if (
|
|
1593
1612
|
logs_enabled
|
|
1594
1613
|
and logs_interval
|
|
1595
|
-
and state
|
|
1614
|
+
and state
|
|
1615
|
+
not in mlrun.common.runtimes.constants.RunStates.terminal_states()
|
|
1596
1616
|
and (
|
|
1597
1617
|
last_pull_log_time is None
|
|
1598
1618
|
or (datetime.now() - last_pull_log_time).seconds > logs_interval
|
|
@@ -1601,7 +1621,7 @@ class RunObject(RunTemplate):
|
|
|
1601
1621
|
last_pull_log_time = datetime.now()
|
|
1602
1622
|
state, offset = self.logs(watch=False, offset=offset)
|
|
1603
1623
|
|
|
1604
|
-
if state in mlrun.runtimes.constants.RunStates.terminal_states():
|
|
1624
|
+
if state in mlrun.common.runtimes.constants.RunStates.terminal_states():
|
|
1605
1625
|
if logs_enabled and logs_interval:
|
|
1606
1626
|
self.logs(watch=False, offset=offset)
|
|
1607
1627
|
break
|
|
@@ -1613,7 +1633,10 @@ class RunObject(RunTemplate):
|
|
|
1613
1633
|
)
|
|
1614
1634
|
if logs_enabled and not logs_interval:
|
|
1615
1635
|
self.logs(watch=False)
|
|
1616
|
-
if
|
|
1636
|
+
if (
|
|
1637
|
+
raise_on_failure
|
|
1638
|
+
and state != mlrun.common.runtimes.constants.RunStates.completed
|
|
1639
|
+
):
|
|
1617
1640
|
raise mlrun.errors.MLRunRuntimeError(
|
|
1618
1641
|
f"Task {self.metadata.name} did not complete (state={state})"
|
|
1619
1642
|
)
|
|
@@ -1629,9 +1652,12 @@ class RunObject(RunTemplate):
|
|
|
1629
1652
|
|
|
1630
1653
|
@staticmethod
|
|
1631
1654
|
def parse_uri(uri: str) -> tuple[str, str, str, str]:
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1655
|
+
"""Parse the run's uri
|
|
1656
|
+
|
|
1657
|
+
:param uri: run uri in the format of <project>@<uid>#<iteration>[:tag]
|
|
1658
|
+
:return: project, uid, iteration, tag
|
|
1659
|
+
"""
|
|
1660
|
+
uri_pattern = mlrun.utils.regex.run_uri_pattern
|
|
1635
1661
|
match = re.match(uri_pattern, uri)
|
|
1636
1662
|
if not match:
|
|
1637
1663
|
raise ValueError(
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
16
|
# for backwards compatibility
|
|
17
17
|
|
|
18
|
-
from .db import get_store_object
|
|
18
|
+
from .db import get_store_object, get_tsdb_connector
|
|
19
19
|
from .helpers import get_stream_path
|
|
20
20
|
from .model_endpoint import ModelEndpoint
|
|
21
21
|
from .tracking_policy import TrackingPolicy
|