mlrun 1.7.0rc14__py3-none-any.whl → 1.7.0rc16__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 (107) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +18 -109
  3. mlrun/{runtimes/mpijob/v1alpha1.py → alerts/__init__.py} +2 -16
  4. mlrun/alerts/alert.py +141 -0
  5. mlrun/artifacts/__init__.py +8 -3
  6. mlrun/artifacts/base.py +36 -253
  7. mlrun/artifacts/dataset.py +9 -190
  8. mlrun/artifacts/manager.py +20 -41
  9. mlrun/artifacts/model.py +8 -140
  10. mlrun/artifacts/plots.py +14 -375
  11. mlrun/common/schemas/__init__.py +4 -2
  12. mlrun/common/schemas/alert.py +46 -4
  13. mlrun/common/schemas/api_gateway.py +4 -0
  14. mlrun/common/schemas/artifact.py +15 -0
  15. mlrun/common/schemas/auth.py +2 -0
  16. mlrun/common/schemas/model_monitoring/__init__.py +8 -1
  17. mlrun/common/schemas/model_monitoring/constants.py +40 -4
  18. mlrun/common/schemas/model_monitoring/model_endpoints.py +73 -2
  19. mlrun/common/schemas/project.py +2 -0
  20. mlrun/config.py +7 -4
  21. mlrun/data_types/to_pandas.py +4 -4
  22. mlrun/datastore/base.py +41 -9
  23. mlrun/datastore/datastore_profile.py +54 -4
  24. mlrun/datastore/inmem.py +2 -2
  25. mlrun/datastore/sources.py +43 -2
  26. mlrun/datastore/store_resources.py +2 -6
  27. mlrun/datastore/targets.py +106 -39
  28. mlrun/db/base.py +23 -3
  29. mlrun/db/httpdb.py +101 -47
  30. mlrun/db/nopdb.py +20 -2
  31. mlrun/errors.py +5 -0
  32. mlrun/feature_store/__init__.py +0 -2
  33. mlrun/feature_store/api.py +12 -47
  34. mlrun/feature_store/feature_set.py +9 -0
  35. mlrun/feature_store/retrieval/base.py +9 -4
  36. mlrun/feature_store/retrieval/conversion.py +4 -4
  37. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  38. mlrun/feature_store/retrieval/job.py +2 -0
  39. mlrun/feature_store/retrieval/local_merger.py +2 -0
  40. mlrun/feature_store/retrieval/spark_merger.py +5 -0
  41. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +5 -10
  42. mlrun/launcher/base.py +4 -3
  43. mlrun/launcher/client.py +1 -1
  44. mlrun/lists.py +4 -2
  45. mlrun/model.py +25 -11
  46. mlrun/model_monitoring/__init__.py +1 -1
  47. mlrun/model_monitoring/api.py +41 -18
  48. mlrun/model_monitoring/application.py +5 -305
  49. mlrun/model_monitoring/applications/__init__.py +11 -0
  50. mlrun/model_monitoring/applications/_application_steps.py +157 -0
  51. mlrun/model_monitoring/applications/base.py +282 -0
  52. mlrun/model_monitoring/applications/context.py +214 -0
  53. mlrun/model_monitoring/applications/evidently_base.py +211 -0
  54. mlrun/model_monitoring/applications/histogram_data_drift.py +132 -91
  55. mlrun/model_monitoring/applications/results.py +99 -0
  56. mlrun/model_monitoring/controller.py +3 -1
  57. mlrun/model_monitoring/db/__init__.py +2 -0
  58. mlrun/model_monitoring/db/stores/base/store.py +9 -36
  59. mlrun/model_monitoring/db/stores/sqldb/models/base.py +7 -6
  60. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +63 -110
  61. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +104 -187
  62. mlrun/model_monitoring/db/tsdb/__init__.py +71 -0
  63. mlrun/model_monitoring/db/tsdb/base.py +135 -0
  64. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  65. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  66. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +404 -0
  67. mlrun/model_monitoring/db/v3io_tsdb_reader.py +134 -0
  68. mlrun/model_monitoring/evidently_application.py +6 -118
  69. mlrun/model_monitoring/helpers.py +1 -1
  70. mlrun/model_monitoring/model_endpoint.py +3 -2
  71. mlrun/model_monitoring/stream_processing.py +48 -213
  72. mlrun/model_monitoring/writer.py +101 -121
  73. mlrun/platforms/__init__.py +10 -9
  74. mlrun/platforms/iguazio.py +21 -202
  75. mlrun/projects/operations.py +11 -7
  76. mlrun/projects/pipelines.py +13 -76
  77. mlrun/projects/project.py +73 -45
  78. mlrun/render.py +11 -13
  79. mlrun/run.py +6 -41
  80. mlrun/runtimes/__init__.py +3 -3
  81. mlrun/runtimes/base.py +6 -6
  82. mlrun/runtimes/funcdoc.py +0 -28
  83. mlrun/runtimes/kubejob.py +2 -1
  84. mlrun/runtimes/local.py +1 -1
  85. mlrun/runtimes/mpijob/__init__.py +0 -20
  86. mlrun/runtimes/mpijob/v1.py +1 -1
  87. mlrun/runtimes/nuclio/api_gateway.py +75 -9
  88. mlrun/runtimes/nuclio/function.py +9 -35
  89. mlrun/runtimes/pod.py +16 -36
  90. mlrun/runtimes/remotesparkjob.py +1 -1
  91. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  92. mlrun/runtimes/utils.py +1 -39
  93. mlrun/utils/helpers.py +72 -71
  94. mlrun/utils/notifications/notification/base.py +1 -1
  95. mlrun/utils/notifications/notification/slack.py +12 -5
  96. mlrun/utils/notifications/notification/webhook.py +1 -1
  97. mlrun/utils/notifications/notification_pusher.py +134 -14
  98. mlrun/utils/version/version.json +2 -2
  99. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/METADATA +4 -3
  100. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/RECORD +105 -95
  101. mlrun/kfpops.py +0 -865
  102. mlrun/platforms/other.py +0 -305
  103. /mlrun/{runtimes → common/runtimes}/constants.py +0 -0
  104. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/LICENSE +0 -0
  105. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/WHEEL +0 -0
  106. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/entry_points.txt +0 -0
  107. {mlrun-1.7.0rc14.dist-info → mlrun-1.7.0rc16.dist-info}/top_level.txt +0 -0
mlrun/__init__.py CHANGED
@@ -22,11 +22,16 @@ __all__ = [
22
22
  "handler",
23
23
  "ArtifactType",
24
24
  "get_secret_or_env",
25
+ "mount_v3io",
26
+ "v3io_cred",
27
+ "auto_mount",
28
+ "VolumeMount",
25
29
  ]
26
30
 
27
31
  from os import environ, path
28
32
 
29
33
  import dotenv
34
+ import mlrun_pipelines
30
35
 
31
36
  from .config import config as mlconf
32
37
  from .datastore import DataItem, store_manager
@@ -35,7 +40,6 @@ from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
35
40
  from .execution import MLClientCtx
36
41
  from .model import RunObject, RunTemplate, new_task
37
42
  from .package import ArtifactType, DefaultPackager, Packager, handler
38
- from .platforms import VolumeMount, auto_mount, mount_v3io, v3io_cred
39
43
  from .projects import (
40
44
  ProjectMetadata,
41
45
  build_function,
@@ -65,6 +69,11 @@ from .utils.version import Version
65
69
 
66
70
  __version__ = Version().get()["version"]
67
71
 
72
+ VolumeMount = mlrun_pipelines.common.mounts.VolumeMount
73
+ mount_v3io = mlrun_pipelines.mounts.mount_v3io
74
+ v3io_cred = mlrun_pipelines.mounts.v3io_cred
75
+ auto_mount = mlrun_pipelines.mounts.auto_mount
76
+
68
77
 
69
78
  def get_version():
70
79
  """get current mlrun version"""
mlrun/__main__.py CHANGED
@@ -22,14 +22,12 @@ from ast import literal_eval
22
22
  from base64 import b64decode, b64encode
23
23
  from os import environ, path, remove
24
24
  from pprint import pprint
25
- from subprocess import Popen
26
- from sys import executable
27
- from urllib.parse import urlparse
28
25
 
29
26
  import click
30
27
  import dotenv
31
28
  import pandas as pd
32
29
  import yaml
30
+ from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
33
31
  from tabulate import tabulate
34
32
 
35
33
  import mlrun
@@ -40,7 +38,6 @@ from .config import config as mlconf
40
38
  from .db import get_run_db
41
39
  from .errors import err_to_str
42
40
  from .model import RunTemplate
43
- from .platforms import auto_mount as auto_mount_modifier
44
41
  from .projects import load_project
45
42
  from .run import (
46
43
  get_object,
@@ -469,6 +466,17 @@ def run(
469
466
  is_flag=True,
470
467
  help="ensure the project exists, if not, create project",
471
468
  )
469
+ @click.option(
470
+ "--state-file-path", default="/tmp/state", help="path to file with state data"
471
+ )
472
+ @click.option(
473
+ "--image-file-path", default="/tmp/image", help="path to file with image data"
474
+ )
475
+ @click.option(
476
+ "--full-image-file-path",
477
+ default="/tmp/fullimage",
478
+ help="path to file with full image data",
479
+ )
472
480
  def build(
473
481
  func_url,
474
482
  name,
@@ -488,6 +496,9 @@ def build(
488
496
  skip,
489
497
  env_file,
490
498
  ensure_project,
499
+ state_file_path,
500
+ image_file_path,
501
+ full_image_file_path,
491
502
  ):
492
503
  """Build a container image from code and requirements."""
493
504
 
@@ -577,12 +588,12 @@ def build(
577
588
  state = func.status.state
578
589
  image = func.spec.image
579
590
  if kfp:
580
- with open("/tmp/state", "w") as fp:
591
+ with open(state_file_path, "w") as fp:
581
592
  fp.write(state or "none")
582
593
  full_image = func.full_image_path(image) or ""
583
- with open("/tmp/image", "w") as fp:
594
+ with open(image_file_path, "w") as fp:
584
595
  fp.write(image)
585
- with open("/tmp/fullimage", "w") as fp:
596
+ with open(full_image_file_path, "w") as fp:
586
597
  fp.write(full_image)
587
598
  print("Full image path = ", full_image)
588
599
 
@@ -827,108 +838,6 @@ def get(kind, name, selector, namespace, uid, project, tag, db, extra_args):
827
838
  )
828
839
 
829
840
 
830
- @main.command(deprecated=True)
831
- @click.option("--port", "-p", help="port to listen on", type=int)
832
- @click.option("--dirpath", "-d", help="database directory (dirpath)")
833
- @click.option("--dsn", "-s", help="database dsn, e.g. sqlite:///db/mlrun.db")
834
- @click.option("--logs-path", "-l", help="logs directory path")
835
- @click.option("--data-volume", "-v", help="path prefix to the location of artifacts")
836
- @click.option("--verbose", is_flag=True, help="verbose log")
837
- @click.option("--background", "-b", is_flag=True, help="run in background process")
838
- @click.option("--artifact-path", "-a", help="default artifact path")
839
- @click.option(
840
- "--update-env",
841
- default="",
842
- is_flag=False,
843
- flag_value=mlrun.config.default_env_file,
844
- help=f"update the specified mlrun .env file (if TEXT not provided defaults to {mlrun.config.default_env_file})",
845
- )
846
- def db(
847
- port,
848
- dirpath,
849
- dsn,
850
- logs_path,
851
- data_volume,
852
- verbose,
853
- background,
854
- artifact_path,
855
- update_env,
856
- ):
857
- """Run HTTP api/database server"""
858
- warnings.warn(
859
- "The `mlrun db` command is deprecated in 1.5.0 and will be removed in 1.7.0, it is for internal use only.",
860
- FutureWarning,
861
- )
862
- env = environ.copy()
863
- # ignore client side .env file (so import mlrun in server will not try to connect to local/remote DB)
864
- env["MLRUN_IGNORE_ENV_FILE"] = "true"
865
- env["MLRUN_DBPATH"] = ""
866
-
867
- if port is not None:
868
- env["MLRUN_HTTPDB__PORT"] = str(port)
869
- if dirpath is not None:
870
- env["MLRUN_HTTPDB__DIRPATH"] = dirpath
871
- if dsn is not None:
872
- if dsn.startswith("sqlite://") and "check_same_thread=" not in dsn:
873
- dsn += "?check_same_thread=false"
874
- env["MLRUN_HTTPDB__DSN"] = dsn
875
- if logs_path is not None:
876
- env["MLRUN_HTTPDB__LOGS_PATH"] = logs_path
877
- if data_volume is not None:
878
- env["MLRUN_HTTPDB__DATA_VOLUME"] = data_volume
879
- if verbose:
880
- env["MLRUN_LOG_LEVEL"] = "DEBUG"
881
- if artifact_path or "MLRUN_ARTIFACT_PATH" not in env:
882
- if not artifact_path:
883
- artifact_path = (
884
- env.get("MLRUN_HTTPDB__DATA_VOLUME", "./artifacts").rstrip("/")
885
- + "/{{project}}"
886
- )
887
- env["MLRUN_ARTIFACT_PATH"] = path.realpath(path.expanduser(artifact_path))
888
-
889
- env["MLRUN_IS_API_SERVER"] = "true"
890
-
891
- # create the DB dir if needed
892
- dsn = dsn or mlconf.httpdb.dsn
893
- if dsn and dsn.startswith("sqlite:///"):
894
- parsed = urlparse(dsn)
895
- p = pathlib.Path(parsed.path[1:]).parent
896
- p.mkdir(parents=True, exist_ok=True)
897
-
898
- cmd = [executable, "-m", "server.api.main"]
899
- pid = None
900
- if background:
901
- print("Starting MLRun API service in the background...")
902
- child = Popen(
903
- cmd,
904
- env=env,
905
- stdout=open("mlrun-stdout.log", "w"),
906
- stderr=open("mlrun-stderr.log", "w"),
907
- start_new_session=True,
908
- )
909
- pid = child.pid
910
- print(
911
- f"Background pid: {pid}, logs written to mlrun-stdout.log and mlrun-stderr.log, use:\n"
912
- f"`kill {pid}` (linux/mac) or `taskkill /pid {pid} /t /f` (windows), to kill the mlrun service process"
913
- )
914
- else:
915
- child = Popen(cmd, env=env)
916
- returncode = child.wait()
917
- if returncode != 0:
918
- raise SystemExit(returncode)
919
- if update_env:
920
- # update mlrun client env file with the API path, so client will use the new DB
921
- # update and PID, allow killing the correct process in a config script
922
- filename = path.expanduser(update_env)
923
- dotenv.set_key(
924
- filename, "MLRUN_DBPATH", f"http://localhost:{port or 8080}", quote_mode=""
925
- )
926
- dotenv.set_key(filename, "MLRUN_MOCK_NUCLIO_DEPLOYMENT", "auto", quote_mode="")
927
- if pid:
928
- dotenv.set_key(filename, "MLRUN_SERVICE_PID", str(pid), quote_mode="")
929
- print(f"Updated configuration in {update_env} .env file")
930
-
931
-
932
841
  @main.command()
933
842
  def version():
934
843
  """get mlrun version"""
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2024 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -11,19 +11,5 @@
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
- from deprecated import deprecated
15
14
 
16
- from mlrun.runtimes.constants import MPIJobCRDVersions
17
- from mlrun.runtimes.mpijob.abstract import AbstractMPIJobRuntime
18
-
19
-
20
- # TODO: Remove in 1.7.0
21
- @deprecated(
22
- version="1.5.0",
23
- reason="v1alpha1 mpi will be removed in 1.7.0, use v1 instead",
24
- category=FutureWarning,
25
- )
26
- class MpiRuntimeV1Alpha1(AbstractMPIJobRuntime):
27
- crd_group = "kubeflow.org"
28
- crd_version = MPIJobCRDVersions.v1alpha1
29
- crd_plural = "mpijobs"
15
+ from .alert import AlertConfig
mlrun/alerts/alert.py ADDED
@@ -0,0 +1,141 @@
1
+ # Copyright 2024 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Union
16
+
17
+ import mlrun
18
+ import mlrun.common.schemas.alert as alert_constants
19
+ from mlrun.common.schemas.notification import Notification
20
+ from mlrun.model import ModelObj
21
+
22
+
23
+ class AlertConfig(ModelObj):
24
+ _dict_fields = [
25
+ "project",
26
+ "name",
27
+ "description",
28
+ "summary",
29
+ "severity",
30
+ "criteria",
31
+ "reset_policy",
32
+ "state",
33
+ ]
34
+
35
+ def __init__(
36
+ self,
37
+ project: str = None,
38
+ name: str = None,
39
+ template: Union[alert_constants.AlertTemplate, str] = None,
40
+ description: str = None,
41
+ summary: str = None,
42
+ severity: alert_constants.AlertSeverity = None,
43
+ trigger: alert_constants.AlertTrigger = None,
44
+ criteria: alert_constants.AlertCriteria = None,
45
+ reset_policy: alert_constants.ResetPolicy = None,
46
+ notifications: list[Notification] = None,
47
+ entities: alert_constants.EventEntities = None,
48
+ id: int = None,
49
+ state: alert_constants.AlertActiveState = None,
50
+ created: str = None,
51
+ count: int = None,
52
+ ):
53
+ self.project = project
54
+ self.name = name
55
+ self.description = description
56
+ self.summary = summary
57
+ self.severity = severity
58
+ self.trigger = trigger
59
+ self.criteria = criteria
60
+ self.reset_policy = reset_policy
61
+ self.notifications = notifications or []
62
+ self.entities = entities
63
+ self.id = id
64
+ self.state = state
65
+ self.created = created
66
+ self.count = count
67
+
68
+ if template:
69
+ self._apply_template(template)
70
+
71
+ def validate_required_fields(self):
72
+ if not self.project or not self.name:
73
+ raise mlrun.errors.MLRunBadRequestError("Project and name must be provided")
74
+
75
+ def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
76
+ data = super().to_dict(self._dict_fields)
77
+
78
+ data["entities"] = (
79
+ self.entities.dict()
80
+ if not isinstance(self.entities, dict)
81
+ else self.entities
82
+ )
83
+ data["notifications"] = [
84
+ notification.dict() if not isinstance(notification, dict) else notification
85
+ for notification in self.notifications
86
+ ]
87
+ data["trigger"] = (
88
+ self.trigger.dict() if not isinstance(self.trigger, dict) else self.trigger
89
+ )
90
+ return data
91
+
92
+ @classmethod
93
+ def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
94
+ new_obj = super().from_dict(struct, fields=fields)
95
+
96
+ entity_data = struct.get("entities")
97
+ if entity_data:
98
+ entity_obj = alert_constants.EventEntities.parse_obj(entity_data)
99
+ new_obj.entities = entity_obj
100
+
101
+ notifications_data = struct.get("notifications")
102
+ if notifications_data:
103
+ notifications_objs = [
104
+ Notification.parse_obj(notification_data)
105
+ for notification_data in notifications_data
106
+ ]
107
+ new_obj.notifications = notifications_objs
108
+
109
+ trigger_data = struct.get("trigger")
110
+ if trigger_data:
111
+ trigger_obj = alert_constants.AlertTrigger.parse_obj(trigger_data)
112
+ new_obj.trigger = trigger_obj
113
+
114
+ return new_obj
115
+
116
+ def with_notifications(self, notifications: list[Notification]):
117
+ if not isinstance(notifications, list) or not all(
118
+ isinstance(item, Notification) for item in notifications
119
+ ):
120
+ raise ValueError("Notifications parameter must be a list of notifications")
121
+ for notification in notifications:
122
+ self.notifications.append(notification)
123
+ return self
124
+
125
+ def with_entities(self, entities: alert_constants.EventEntities):
126
+ if not isinstance(entities, alert_constants.EventEntities):
127
+ raise ValueError("Entities parameter must be of type: EventEntities")
128
+ self.entities = entities
129
+ return self
130
+
131
+ def _apply_template(self, template):
132
+ if isinstance(template, str):
133
+ db = mlrun.get_run_db()
134
+ template = db.get_alert_template(template)
135
+
136
+ # Extract parameters from the template and apply them to the AlertConfig object
137
+ self.description = template.description
138
+ self.severity = template.severity
139
+ self.criteria = template.criteria
140
+ self.trigger = template.trigger
141
+ self.reset_policy = template.reset_policy
@@ -17,14 +17,19 @@
17
17
  # Don't remove this, used by sphinx documentation
18
18
  __all__ = ["get_model", "update_model"]
19
19
 
20
- from .base import Artifact, ArtifactMetadata, ArtifactSpec, get_artifact_meta
20
+ from .base import (
21
+ Artifact,
22
+ ArtifactMetadata,
23
+ ArtifactSpec,
24
+ DirArtifact,
25
+ get_artifact_meta,
26
+ )
21
27
  from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
22
28
  from .manager import (
23
29
  ArtifactManager,
24
30
  ArtifactProducer,
25
31
  artifact_types,
26
32
  dict_to_artifact,
27
- legacy_artifact_types,
28
33
  )
29
34
  from .model import ModelArtifact, get_model, update_model
30
- from .plots import BokehArtifact, ChartArtifact, PlotArtifact, PlotlyArtifact
35
+ from .plots import PlotArtifact, PlotlyArtifact