mlrun 1.7.0rc14__py3-none-any.whl → 1.7.0rc21__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.

Files changed (152) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +23 -111
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/api/schemas/__init__.py +4 -3
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +36 -253
  8. mlrun/artifacts/dataset.py +9 -190
  9. mlrun/artifacts/manager.py +46 -42
  10. mlrun/artifacts/model.py +9 -141
  11. mlrun/artifacts/plots.py +14 -375
  12. mlrun/common/constants.py +65 -3
  13. mlrun/common/formatters/__init__.py +19 -0
  14. mlrun/{runtimes/mpijob/v1alpha1.py → common/formatters/artifact.py} +6 -14
  15. mlrun/common/formatters/base.py +113 -0
  16. mlrun/common/formatters/function.py +46 -0
  17. mlrun/common/formatters/pipeline.py +53 -0
  18. mlrun/common/formatters/project.py +51 -0
  19. mlrun/{runtimes → common/runtimes}/constants.py +32 -4
  20. mlrun/common/schemas/__init__.py +10 -5
  21. mlrun/common/schemas/alert.py +92 -11
  22. mlrun/common/schemas/api_gateway.py +56 -0
  23. mlrun/common/schemas/artifact.py +15 -5
  24. mlrun/common/schemas/auth.py +2 -0
  25. mlrun/common/schemas/client_spec.py +1 -0
  26. mlrun/common/schemas/frontend_spec.py +1 -0
  27. mlrun/common/schemas/function.py +4 -0
  28. mlrun/common/schemas/model_monitoring/__init__.py +15 -3
  29. mlrun/common/schemas/model_monitoring/constants.py +58 -7
  30. mlrun/common/schemas/model_monitoring/grafana.py +9 -5
  31. mlrun/common/schemas/model_monitoring/model_endpoints.py +86 -2
  32. mlrun/common/schemas/pipeline.py +0 -9
  33. mlrun/common/schemas/project.py +5 -11
  34. mlrun/common/types.py +1 -0
  35. mlrun/config.py +27 -9
  36. mlrun/data_types/to_pandas.py +9 -9
  37. mlrun/datastore/base.py +41 -9
  38. mlrun/datastore/datastore.py +6 -2
  39. mlrun/datastore/datastore_profile.py +56 -4
  40. mlrun/datastore/inmem.py +2 -2
  41. mlrun/datastore/redis.py +2 -2
  42. mlrun/datastore/s3.py +5 -0
  43. mlrun/datastore/sources.py +147 -7
  44. mlrun/datastore/store_resources.py +7 -7
  45. mlrun/datastore/targets.py +110 -42
  46. mlrun/datastore/utils.py +42 -0
  47. mlrun/db/base.py +54 -10
  48. mlrun/db/httpdb.py +282 -79
  49. mlrun/db/nopdb.py +52 -10
  50. mlrun/errors.py +11 -0
  51. mlrun/execution.py +24 -9
  52. mlrun/feature_store/__init__.py +0 -2
  53. mlrun/feature_store/api.py +12 -47
  54. mlrun/feature_store/feature_set.py +9 -0
  55. mlrun/feature_store/feature_vector.py +8 -0
  56. mlrun/feature_store/ingestion.py +7 -6
  57. mlrun/feature_store/retrieval/base.py +9 -4
  58. mlrun/feature_store/retrieval/conversion.py +9 -9
  59. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  60. mlrun/feature_store/retrieval/job.py +9 -3
  61. mlrun/feature_store/retrieval/local_merger.py +2 -0
  62. mlrun/feature_store/retrieval/spark_merger.py +16 -0
  63. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
  64. mlrun/frameworks/parallel_coordinates.py +2 -1
  65. mlrun/frameworks/tf_keras/__init__.py +4 -1
  66. mlrun/k8s_utils.py +10 -11
  67. mlrun/launcher/base.py +4 -3
  68. mlrun/launcher/client.py +5 -3
  69. mlrun/launcher/local.py +8 -2
  70. mlrun/launcher/remote.py +8 -2
  71. mlrun/lists.py +6 -2
  72. mlrun/model.py +45 -21
  73. mlrun/model_monitoring/__init__.py +1 -1
  74. mlrun/model_monitoring/api.py +41 -18
  75. mlrun/model_monitoring/application.py +5 -305
  76. mlrun/model_monitoring/applications/__init__.py +11 -0
  77. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  78. mlrun/model_monitoring/applications/base.py +280 -0
  79. mlrun/model_monitoring/applications/context.py +214 -0
  80. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  81. mlrun/model_monitoring/applications/histogram_data_drift.py +132 -91
  82. mlrun/model_monitoring/applications/results.py +99 -0
  83. mlrun/model_monitoring/controller.py +3 -1
  84. mlrun/model_monitoring/db/__init__.py +2 -0
  85. mlrun/model_monitoring/db/stores/__init__.py +0 -2
  86. mlrun/model_monitoring/db/stores/base/store.py +22 -37
  87. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +43 -21
  88. mlrun/model_monitoring/db/stores/sqldb/models/base.py +39 -8
  89. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +27 -7
  90. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +5 -0
  91. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +246 -224
  92. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +232 -216
  93. mlrun/model_monitoring/db/tsdb/__init__.py +100 -0
  94. mlrun/model_monitoring/db/tsdb/base.py +329 -0
  95. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  96. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  97. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +240 -0
  98. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +45 -0
  99. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +397 -0
  100. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  101. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  102. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +636 -0
  103. mlrun/model_monitoring/evidently_application.py +6 -118
  104. mlrun/model_monitoring/helpers.py +46 -1
  105. mlrun/model_monitoring/model_endpoint.py +3 -2
  106. mlrun/model_monitoring/stream_processing.py +57 -216
  107. mlrun/model_monitoring/writer.py +134 -124
  108. mlrun/package/utils/_formatter.py +2 -2
  109. mlrun/platforms/__init__.py +10 -9
  110. mlrun/platforms/iguazio.py +21 -202
  111. mlrun/projects/operations.py +19 -12
  112. mlrun/projects/pipelines.py +79 -102
  113. mlrun/projects/project.py +265 -103
  114. mlrun/render.py +15 -14
  115. mlrun/run.py +16 -46
  116. mlrun/runtimes/__init__.py +6 -3
  117. mlrun/runtimes/base.py +8 -7
  118. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  119. mlrun/runtimes/funcdoc.py +0 -28
  120. mlrun/runtimes/kubejob.py +2 -1
  121. mlrun/runtimes/local.py +5 -2
  122. mlrun/runtimes/mpijob/__init__.py +0 -20
  123. mlrun/runtimes/mpijob/v1.py +1 -1
  124. mlrun/runtimes/nuclio/api_gateway.py +194 -84
  125. mlrun/runtimes/nuclio/application/application.py +170 -8
  126. mlrun/runtimes/nuclio/function.py +39 -49
  127. mlrun/runtimes/pod.py +16 -36
  128. mlrun/runtimes/remotesparkjob.py +9 -3
  129. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  130. mlrun/runtimes/utils.py +6 -45
  131. mlrun/serving/server.py +2 -1
  132. mlrun/serving/v2_serving.py +5 -1
  133. mlrun/track/tracker.py +2 -1
  134. mlrun/utils/async_http.py +25 -5
  135. mlrun/utils/helpers.py +107 -75
  136. mlrun/utils/logger.py +39 -7
  137. mlrun/utils/notifications/notification/__init__.py +14 -9
  138. mlrun/utils/notifications/notification/base.py +1 -1
  139. mlrun/utils/notifications/notification/slack.py +34 -7
  140. mlrun/utils/notifications/notification/webhook.py +1 -1
  141. mlrun/utils/notifications/notification_pusher.py +147 -16
  142. mlrun/utils/regex.py +9 -0
  143. mlrun/utils/v3io_clients.py +0 -1
  144. mlrun/utils/version/version.json +2 -2
  145. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/METADATA +14 -6
  146. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/RECORD +150 -130
  147. mlrun/kfpops.py +0 -865
  148. mlrun/platforms/other.py +0 -305
  149. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/LICENSE +0 -0
  150. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/WHEEL +0 -0
  151. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.dist-info}/entry_points.txt +0 -0
  152. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc21.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
  import pathlib
15
+ import re
15
16
  import typing
16
17
  from os.path import exists, isdir
17
18
  from urllib.parse import urlparse
18
19
 
20
+ import mlrun.common.schemas.artifact
19
21
  import mlrun.config
22
+ import mlrun.utils.regex
20
23
  from mlrun.utils.helpers import (
21
24
  get_local_file_schema,
22
25
  template_artifact_path,
@@ -24,7 +27,6 @@ from mlrun.utils.helpers import (
24
27
  )
25
28
 
26
29
  from ..utils import (
27
- is_legacy_artifact,
28
30
  is_relative_path,
29
31
  logger,
30
32
  validate_artifact_key_name,
@@ -33,56 +35,28 @@ from ..utils import (
33
35
  from .base import (
34
36
  Artifact,
35
37
  DirArtifact,
36
- LegacyArtifact,
37
- LegacyDirArtifact,
38
- LegacyLinkArtifact,
39
38
  LinkArtifact,
40
39
  )
41
40
  from .dataset import (
42
41
  DatasetArtifact,
43
- LegacyDatasetArtifact,
44
- LegacyTableArtifact,
45
42
  TableArtifact,
46
43
  )
47
- from .model import LegacyModelArtifact, ModelArtifact
44
+ from .model import ModelArtifact
48
45
  from .plots import (
49
- BokehArtifact,
50
- ChartArtifact,
51
- LegacyBokehArtifact,
52
- LegacyChartArtifact,
53
- LegacyPlotArtifact,
54
- LegacyPlotlyArtifact,
55
46
  PlotArtifact,
56
47
  PlotlyArtifact,
57
48
  )
58
49
 
59
- # TODO - Remove deprecated types when deleted in 1.7.0
60
50
  artifact_types = {
61
51
  "": Artifact,
62
52
  "artifact": Artifact,
63
53
  "dir": DirArtifact,
64
54
  "link": LinkArtifact,
65
55
  "plot": PlotArtifact,
66
- "chart": ChartArtifact,
67
56
  "table": TableArtifact,
68
57
  "model": ModelArtifact,
69
58
  "dataset": DatasetArtifact,
70
59
  "plotly": PlotlyArtifact,
71
- "bokeh": BokehArtifact,
72
- }
73
-
74
- # TODO - Remove this when legacy types are deleted in 1.7.0
75
- legacy_artifact_types = {
76
- "": LegacyArtifact,
77
- "dir": LegacyDirArtifact,
78
- "link": LegacyLinkArtifact,
79
- "plot": LegacyPlotArtifact,
80
- "chart": LegacyChartArtifact,
81
- "table": LegacyTableArtifact,
82
- "model": LegacyModelArtifact,
83
- "dataset": LegacyDatasetArtifact,
84
- "plotly": LegacyPlotlyArtifact,
85
- "bokeh": LegacyBokehArtifact,
86
60
  }
87
61
 
88
62
 
@@ -100,17 +74,33 @@ class ArtifactProducer:
100
74
  def get_meta(self) -> dict:
101
75
  return {"kind": self.kind, "name": self.name, "tag": self.tag}
102
76
 
77
+ @property
78
+ def uid(self):
79
+ return None
103
80
 
104
- def dict_to_artifact(struct: dict) -> Artifact:
105
- # Need to distinguish between LegacyArtifact classes and Artifact classes. Use existence of the "metadata"
106
- # property to make this distinction
107
- kind = struct.get("kind", "")
81
+ @staticmethod
82
+ def parse_uri(uri: str) -> tuple[str, str, str]:
83
+ """Parse artifact producer's uri
108
84
 
109
- if is_legacy_artifact(struct):
110
- return mlrun.artifacts.base.convert_legacy_artifact_to_new_format(struct)
85
+ :param uri: artifact producer's uri in the format <project>/<uid>[-<iteration>]
86
+ :returns: tuple of project, uid, iteration
87
+ """
88
+ uri_pattern = mlrun.utils.regex.artifact_producer_uri_pattern
89
+ match = re.match(uri_pattern, uri)
90
+ if not match:
91
+ return "", "", ""
92
+ group_dict = match.groupdict()
93
+
94
+ return (
95
+ group_dict["project"] or "",
96
+ group_dict["uid"] or "",
97
+ group_dict["iteration"] or "",
98
+ )
111
99
 
112
- artifact_class = artifact_types[kind]
113
100
 
101
+ def dict_to_artifact(struct: dict) -> Artifact:
102
+ kind = struct.get("kind", "")
103
+ artifact_class = artifact_types[kind]
114
104
  return artifact_class.from_dict(struct)
115
105
 
116
106
 
@@ -297,7 +287,7 @@ class ArtifactManager:
297
287
  if target_path and item.is_dir and not target_path.endswith("/"):
298
288
  target_path += "/"
299
289
  target_path = template_artifact_path(
300
- artifact_path=target_path, project=producer.project
290
+ artifact_path=target_path, project=producer.project, run_uid=producer.uid
301
291
  )
302
292
  item.target_path = target_path
303
293
 
@@ -308,10 +298,7 @@ class ArtifactManager:
308
298
  # before uploading the item, we want to ensure that its tags are valid,
309
299
  # so that we don't upload something that won't be stored later
310
300
  validate_tag_name(item.metadata.tag, "artifact.metadata.tag")
311
- if is_legacy_artifact(item):
312
- item.upload()
313
- else:
314
- item.upload(artifact_path=artifact_path)
301
+ item.upload(artifact_path=artifact_path)
315
302
 
316
303
  if db_key:
317
304
  self._log_to_db(db_key, project, producer.inputs, item)
@@ -382,6 +369,23 @@ class ArtifactManager:
382
369
  project=project,
383
370
  )
384
371
 
372
+ def delete_artifact(
373
+ self,
374
+ item: Artifact,
375
+ deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
376
+ mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
377
+ ),
378
+ secrets: dict = None,
379
+ ):
380
+ self.artifact_db.del_artifact(
381
+ key=item.db_key,
382
+ project=item.project,
383
+ tag=item.tag,
384
+ tree=item.tree,
385
+ deletion_strategy=deletion_strategy,
386
+ secrets=secrets,
387
+ )
388
+
385
389
 
386
390
  def extend_artifact_path(artifact_path: str, default_artifact_path: str):
387
391
  artifact_path = str(artifact_path or "")
mlrun/artifacts/model.py CHANGED
@@ -13,12 +13,12 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import tempfile
16
+ import warnings
16
17
  from os import path
17
18
  from typing import Any, Optional
18
19
 
19
20
  import pandas as pd
20
21
  import yaml
21
- from deprecated import deprecated
22
22
 
23
23
  import mlrun
24
24
  import mlrun.datastore
@@ -27,7 +27,7 @@ from ..data_types import InferOptions, get_infer_interface
27
27
  from ..features import Feature
28
28
  from ..model import ObjectList
29
29
  from ..utils import StorePrefix, is_relative_path
30
- from .base import Artifact, ArtifactSpec, LegacyArtifact, upload_extra_data
30
+ from .base import Artifact, ArtifactSpec, upload_extra_data
31
31
 
32
32
  model_spec_filename = "model_spec.yaml"
33
33
 
@@ -149,6 +149,12 @@ class ModelArtifact(Artifact):
149
149
  model_dir=None,
150
150
  **kwargs,
151
151
  ):
152
+ if key or body or format or target_path:
153
+ warnings.warn(
154
+ "Artifact constructor parameters are deprecated and will be removed in 1.9.0. "
155
+ "Use the metadata and spec parameters instead.",
156
+ DeprecationWarning,
157
+ )
152
158
  super().__init__(key, body, format=format, target_path=target_path, **kwargs)
153
159
  model_file = str(model_file or "")
154
160
  if model_file and "/" in model_file:
@@ -397,144 +403,6 @@ class ModelArtifact(Artifact):
397
403
  return mlrun.get_dataitem(target_model_path).get()
398
404
 
399
405
 
400
- # TODO: remove in 1.7.0
401
- @deprecated(
402
- version="1.3.0",
403
- reason="'LegacyModelArtifact' will be removed in 1.7.0, use 'ModelArtifact' instead",
404
- category=FutureWarning,
405
- )
406
- class LegacyModelArtifact(LegacyArtifact):
407
- """ML Model artifact
408
-
409
- Store link to ML model file(s) along with the model metrics, parameters, schema, and stats
410
- """
411
-
412
- _dict_fields = LegacyArtifact._dict_fields + [
413
- "model_file",
414
- "metrics",
415
- "parameters",
416
- "inputs",
417
- "outputs",
418
- "framework",
419
- "algorithm",
420
- "extra_data",
421
- "feature_vector",
422
- "feature_weights",
423
- "feature_stats",
424
- "model_target_file",
425
- ]
426
- kind = "model"
427
- _store_prefix = StorePrefix.Model
428
-
429
- def __init__(
430
- self,
431
- key=None,
432
- body=None,
433
- format=None,
434
- model_file=None,
435
- metrics=None,
436
- target_path=None,
437
- parameters=None,
438
- inputs=None,
439
- outputs=None,
440
- framework=None,
441
- algorithm=None,
442
- feature_vector=None,
443
- feature_weights=None,
444
- extra_data=None,
445
- model_target_file=None,
446
- **kwargs,
447
- ):
448
- super().__init__(key, body, format=format, target_path=target_path, **kwargs)
449
- self._inputs: Optional[ObjectList] = None
450
- self._outputs: Optional[ObjectList] = None
451
-
452
- self.model_file = model_file
453
- self.parameters = parameters or {}
454
- self.metrics = metrics or {}
455
- self.inputs = inputs or []
456
- self.outputs = outputs or []
457
- self.extra_data = extra_data or {}
458
- self.framework = framework
459
- self.algorithm = algorithm
460
- self.feature_vector = feature_vector
461
- self.feature_weights = feature_weights
462
- self.feature_stats = None
463
- self.model_target_file = model_target_file
464
-
465
- @property
466
- def inputs(self) -> Optional[ObjectList]:
467
- """input feature list"""
468
- return self._inputs
469
-
470
- @inputs.setter
471
- def inputs(self, inputs: list[Feature]) -> None:
472
- self._inputs = ObjectList.from_list(Feature, inputs)
473
-
474
- @property
475
- def outputs(self) -> Optional[ObjectList]:
476
- """output feature list"""
477
- return self._outputs
478
-
479
- @outputs.setter
480
- def outputs(self, outputs: list[Feature]) -> None:
481
- self._outputs = ObjectList.from_list(Feature, outputs)
482
-
483
- def infer_from_df(self, df, label_columns=None, with_stats=True, num_bins=None):
484
- """infer inputs, outputs, and stats from provided df (training set)
485
-
486
- :param df: dataframe to infer from
487
- :param label_columns: name of the label (target) column
488
- :param with_stats: infer statistics (min, max, .. histogram)
489
- :param num_bins: number of bins for histogram
490
- """
491
- subset = df
492
- inferer = get_infer_interface(subset)
493
- if label_columns:
494
- if not isinstance(label_columns, list):
495
- label_columns = [label_columns]
496
- subset = df.drop(columns=label_columns)
497
- inferer.infer_schema(subset, self.inputs, {}, options=InferOptions.Features)
498
- if label_columns:
499
- inferer.infer_schema(
500
- df[label_columns], self.outputs, {}, options=InferOptions.Features
501
- )
502
- if with_stats:
503
- self.feature_stats = inferer.get_stats(
504
- df, options=InferOptions.Histogram, num_bins=num_bins
505
- )
506
-
507
- @property
508
- def is_dir(self):
509
- return True
510
-
511
- def before_log(self):
512
- if not self.model_file:
513
- raise ValueError("model_file attr must be specified")
514
-
515
- super().before_log()
516
-
517
- if self.framework:
518
- self.labels = self.labels or {}
519
- self.labels["framework"] = self.framework
520
-
521
- def upload(self):
522
- target_model_path = path.join(self.target_path, self.model_file)
523
- body = self.get_body()
524
- if body:
525
- self._upload_body(body, target=target_model_path)
526
- else:
527
- src_model_path = _get_src_path(self, self.model_file)
528
- if not path.isfile(src_model_path):
529
- raise ValueError(f"model file {src_model_path} not found")
530
- self._upload_file(src_model_path, target=target_model_path)
531
-
532
- upload_extra_data(self, self.extra_data)
533
-
534
- spec_path = path.join(self.target_path, model_spec_filename)
535
- mlrun.datastore.store_manager.object(url=spec_path).put(self.to_yaml())
536
-
537
-
538
406
  def _get_src_path(model_spec: ModelArtifact, filename):
539
407
  if model_spec.src_path:
540
408
  return path.join(model_spec.src_path, filename)
@@ -641,7 +509,7 @@ def _get_extra(target, extra_data, is_dir=False):
641
509
  def _remove_tag_from_spec_yaml(model_spec):
642
510
  spec_dict = model_spec.to_dict()
643
511
  spec_dict["metadata"].pop("tag", None)
644
- return yaml.dump(spec_dict)
512
+ return yaml.safe_dump(spec_dict)
645
513
 
646
514
 
647
515
  def update_model(