mlrun 1.7.0rc20__py3-none-any.whl → 1.7.0rc28__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 (92) hide show
  1. mlrun/__main__.py +10 -8
  2. mlrun/alerts/alert.py +55 -18
  3. mlrun/api/schemas/__init__.py +3 -3
  4. mlrun/artifacts/manager.py +26 -0
  5. mlrun/common/constants.py +3 -2
  6. mlrun/common/formatters/__init__.py +1 -0
  7. mlrun/common/formatters/artifact.py +26 -3
  8. mlrun/common/formatters/base.py +44 -9
  9. mlrun/common/formatters/function.py +12 -7
  10. mlrun/common/formatters/run.py +26 -0
  11. mlrun/common/helpers.py +11 -0
  12. mlrun/common/schemas/__init__.py +4 -0
  13. mlrun/common/schemas/alert.py +5 -9
  14. mlrun/common/schemas/api_gateway.py +64 -16
  15. mlrun/common/schemas/artifact.py +11 -0
  16. mlrun/common/schemas/constants.py +3 -0
  17. mlrun/common/schemas/feature_store.py +58 -28
  18. mlrun/common/schemas/model_monitoring/constants.py +21 -12
  19. mlrun/common/schemas/model_monitoring/model_endpoints.py +0 -12
  20. mlrun/common/schemas/pipeline.py +16 -0
  21. mlrun/common/schemas/project.py +17 -0
  22. mlrun/common/schemas/runs.py +17 -0
  23. mlrun/common/schemas/schedule.py +1 -1
  24. mlrun/common/types.py +6 -0
  25. mlrun/config.py +17 -25
  26. mlrun/datastore/azure_blob.py +2 -1
  27. mlrun/datastore/datastore.py +3 -3
  28. mlrun/datastore/google_cloud_storage.py +6 -2
  29. mlrun/datastore/snowflake_utils.py +3 -1
  30. mlrun/datastore/sources.py +26 -11
  31. mlrun/datastore/store_resources.py +2 -0
  32. mlrun/datastore/targets.py +68 -16
  33. mlrun/db/base.py +83 -2
  34. mlrun/db/httpdb.py +280 -63
  35. mlrun/db/nopdb.py +60 -3
  36. mlrun/errors.py +5 -3
  37. mlrun/execution.py +28 -13
  38. mlrun/feature_store/feature_vector.py +8 -0
  39. mlrun/feature_store/retrieval/spark_merger.py +13 -2
  40. mlrun/launcher/local.py +4 -0
  41. mlrun/launcher/remote.py +1 -0
  42. mlrun/model.py +32 -3
  43. mlrun/model_monitoring/api.py +7 -52
  44. mlrun/model_monitoring/applications/base.py +5 -7
  45. mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
  46. mlrun/model_monitoring/db/stores/__init__.py +37 -24
  47. mlrun/model_monitoring/db/stores/base/store.py +40 -1
  48. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +42 -87
  49. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +27 -35
  50. mlrun/model_monitoring/db/tsdb/__init__.py +15 -15
  51. mlrun/model_monitoring/db/tsdb/base.py +1 -14
  52. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +22 -18
  53. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +86 -56
  54. mlrun/model_monitoring/helpers.py +34 -9
  55. mlrun/model_monitoring/stream_processing.py +12 -11
  56. mlrun/model_monitoring/writer.py +11 -11
  57. mlrun/projects/operations.py +5 -0
  58. mlrun/projects/pipelines.py +35 -21
  59. mlrun/projects/project.py +216 -107
  60. mlrun/render.py +10 -5
  61. mlrun/run.py +15 -5
  62. mlrun/runtimes/__init__.py +2 -0
  63. mlrun/runtimes/base.py +17 -4
  64. mlrun/runtimes/daskjob.py +8 -1
  65. mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
  66. mlrun/runtimes/local.py +23 -4
  67. mlrun/runtimes/nuclio/application/application.py +0 -2
  68. mlrun/runtimes/nuclio/function.py +31 -2
  69. mlrun/runtimes/nuclio/serving.py +9 -6
  70. mlrun/runtimes/pod.py +5 -29
  71. mlrun/runtimes/remotesparkjob.py +8 -2
  72. mlrun/serving/__init__.py +8 -1
  73. mlrun/serving/routers.py +75 -59
  74. mlrun/serving/server.py +11 -0
  75. mlrun/serving/states.py +80 -8
  76. mlrun/serving/utils.py +19 -11
  77. mlrun/serving/v2_serving.py +66 -39
  78. mlrun/utils/helpers.py +91 -11
  79. mlrun/utils/logger.py +36 -2
  80. mlrun/utils/notifications/notification/base.py +43 -7
  81. mlrun/utils/notifications/notification/git.py +21 -0
  82. mlrun/utils/notifications/notification/slack.py +9 -14
  83. mlrun/utils/notifications/notification/webhook.py +41 -1
  84. mlrun/utils/notifications/notification_pusher.py +3 -9
  85. mlrun/utils/regex.py +9 -0
  86. mlrun/utils/version/version.json +2 -2
  87. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/METADATA +16 -9
  88. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/RECORD +92 -91
  89. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/WHEEL +1 -1
  90. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/LICENSE +0 -0
  91. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/entry_points.txt +0 -0
  92. {mlrun-1.7.0rc20.dist-info → mlrun-1.7.0rc28.dist-info}/top_level.txt +0 -0
@@ -30,6 +30,27 @@ class GitNotification(NotificationBase):
30
30
  API/Client notification for setting a rich run statuses git issue comment (github/gitlab)
31
31
  """
32
32
 
33
+ @classmethod
34
+ def validate_params(cls, params):
35
+ git_repo = params.get("repo", None)
36
+ git_issue = params.get("issue", None)
37
+ git_merge_request = params.get("merge_request", None)
38
+ token = (
39
+ params.get("token", None)
40
+ or params.get("GIT_TOKEN", None)
41
+ or params.get("GITHUB_TOKEN", None)
42
+ )
43
+ if not git_repo:
44
+ raise ValueError("Parameter 'repo' is required for GitNotification")
45
+
46
+ if not token:
47
+ raise ValueError("Parameter 'token' is required for GitNotification")
48
+
49
+ if not git_issue and not git_merge_request:
50
+ raise ValueError(
51
+ "At least one of 'issue' or 'merge_request' is required for GitNotification"
52
+ )
53
+
33
54
  async def push(
34
55
  self,
35
56
  message: str,
@@ -35,6 +35,14 @@ class SlackNotification(NotificationBase):
35
35
  "skipped": ":zzz:",
36
36
  }
37
37
 
38
+ @classmethod
39
+ def validate_params(cls, params):
40
+ webhook = params.get("webhook", None) or mlrun.get_secret_or_env(
41
+ "SLACK_WEBHOOK"
42
+ )
43
+ if not webhook:
44
+ raise ValueError("Parameter 'webhook' is required for SlackNotification")
45
+
38
46
  async def push(
39
47
  self,
40
48
  message: str,
@@ -153,20 +161,7 @@ class SlackNotification(NotificationBase):
153
161
  data_text = "\n".join(data_lines)
154
162
  line.append(self._get_slack_row(f"*Event data:*\n{data_text}"))
155
163
 
156
- if (
157
- event_data.entity.kind == mlrun.common.schemas.alert.EventEntityKind.JOB
158
- ): # JOB entity
159
- uid = event_data.value_dict.get("uid")
160
- url = mlrun.utils.helpers.get_ui_url(alert.project, uid)
161
- overview_type = "Job overview"
162
- else: # MODEL entity
163
- model_name = event_data.value_dict.get("model")
164
- model_endpoint_id = event_data.value_dict.get("model_endpoint_id")
165
- url = mlrun.utils.helpers.get_model_endpoint_url(
166
- alert.project, model_name, model_endpoint_id
167
- )
168
- overview_type = "Model endpoint"
169
-
164
+ overview_type, url = self._get_overview_type_and_url(alert, event_data)
170
165
  line.append(self._get_slack_row(f"*Overview:*\n<{url}|*{overview_type}*>"))
171
166
 
172
167
  return line
@@ -28,6 +28,12 @@ class WebhookNotification(NotificationBase):
28
28
  API/Client notification for sending run statuses in a http request
29
29
  """
30
30
 
31
+ @classmethod
32
+ def validate_params(cls, params):
33
+ url = params.get("url", None)
34
+ if not url:
35
+ raise ValueError("Parameter 'url' is required for WebhookNotification")
36
+
31
37
  async def push(
32
38
  self,
33
39
  message: str,
@@ -63,7 +69,7 @@ class WebhookNotification(NotificationBase):
63
69
  request_body["custom_html"] = custom_html
64
70
 
65
71
  if override_body:
66
- request_body = override_body
72
+ request_body = self._serialize_runs_in_request_body(override_body, runs)
67
73
 
68
74
  # Specify the `verify_ssl` parameter value only for HTTPS urls.
69
75
  # The `ClientSession` allows using `ssl=None` for the default SSL check,
@@ -77,3 +83,37 @@ class WebhookNotification(NotificationBase):
77
83
  url, headers=headers, json=request_body, ssl=verify_ssl
78
84
  )
79
85
  response.raise_for_status()
86
+
87
+ @staticmethod
88
+ def _serialize_runs_in_request_body(override_body, runs):
89
+ str_parsed_runs = ""
90
+ runs = runs or []
91
+
92
+ def parse_runs():
93
+ parsed_runs = []
94
+ for run in runs:
95
+ if hasattr(run, "to_dict"):
96
+ run = run.to_dict()
97
+ if isinstance(run, dict):
98
+ parsed_run = {
99
+ "project": run["metadata"]["project"],
100
+ "name": run["metadata"]["name"],
101
+ "host": run["metadata"]["labels"]["host"],
102
+ "status": {"state": run["status"]["state"]},
103
+ }
104
+ if run["status"].get("error", None):
105
+ parsed_run["status"]["error"] = run["status"]["error"]
106
+ elif run["status"].get("results", None):
107
+ parsed_run["status"]["results"] = run["status"]["results"]
108
+ parsed_runs.append(parsed_run)
109
+ return str(parsed_runs)
110
+
111
+ if isinstance(override_body, dict):
112
+ for key, value in override_body.items():
113
+ if "{{ runs }}" or "{{runs}}" in value:
114
+ if not str_parsed_runs:
115
+ str_parsed_runs = parse_runs()
116
+ override_body[key] = value.replace(
117
+ "{{ runs }}", str_parsed_runs
118
+ ).replace("{{runs}}", str_parsed_runs)
119
+ return override_body
@@ -20,9 +20,9 @@ import traceback
20
20
  import typing
21
21
  from concurrent.futures import ThreadPoolExecutor
22
22
 
23
- import kfp
24
23
  import mlrun_pipelines.common.ops
25
24
  import mlrun_pipelines.models
25
+ import mlrun_pipelines.utils
26
26
 
27
27
  import mlrun.common.constants as mlrun_constants
28
28
  import mlrun.common.runtimes.constants
@@ -397,7 +397,7 @@ class NotificationPusher(_NotificationPusherBase):
397
397
  try:
398
398
  _run = db.list_runs(
399
399
  project=run.metadata.project,
400
- labels=f"mlrun_constants.MLRunInternalLabels.runner_pod={_step.node_name}",
400
+ labels=f"{mlrun_constants.MLRunInternalLabels.runner_pod}={_step.node_name}",
401
401
  )[0]
402
402
  except IndexError:
403
403
  _run = {
@@ -484,13 +484,7 @@ class NotificationPusher(_NotificationPusherBase):
484
484
  def _get_workflow_manifest(
485
485
  workflow_id: str,
486
486
  ) -> typing.Optional[mlrun_pipelines.models.PipelineManifest]:
487
- kfp_url = mlrun.mlconf.resolve_kfp_url(mlrun.mlconf.namespace)
488
- if not kfp_url:
489
- raise mlrun.errors.MLRunNotFoundError(
490
- "KubeFlow Pipelines is not configured"
491
- )
492
-
493
- kfp_client = kfp.Client(host=kfp_url)
487
+ kfp_client = mlrun_pipelines.utils.get_client(mlrun.mlconf)
494
488
 
495
489
  # arbitrary timeout of 5 seconds, the workflow should be done by now
496
490
  kfp_run = kfp_client.wait_for_run_completion(workflow_id, 5)
mlrun/utils/regex.py CHANGED
@@ -92,3 +92,12 @@ artifact_key = [r"[^\/\\]+$"]
92
92
  # must be alphanumeric or _
93
93
  # max 256 length
94
94
  v3io_stream_consumer_group = [r"^(?!_)[a-zA-Z0-9_]{1,256}$"]
95
+
96
+ # URI patterns
97
+ run_uri_pattern = r"^(?P<project>.*)@(?P<uid>.*)\#(?P<iteration>.*?)(:(?P<tag>.*))?$"
98
+
99
+ artifact_uri_pattern = r"^((?P<project>.*)/)?(?P<key>.*?)(\#(?P<iteration>.*?))?(:(?P<tag>.*?))?(@(?P<tree>.*))?$"
100
+
101
+ artifact_producer_uri_pattern = (
102
+ r"^((?P<project>.*)/)?(?P<uid>.*?)(\-(?P<iteration>.*?))?$"
103
+ )
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "f869a5513ea7c9f4ccdaddad6589274eec39f0a4",
3
- "version": "1.7.0-rc20"
2
+ "git_commit": "71818c39b83a7e8c396aa2c37f1cd4f3e192dd2f",
3
+ "version": "1.7.0-rc28"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mlrun
3
- Version: 1.7.0rc20
3
+ Version: 1.7.0rc28
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -28,30 +28,30 @@ Requires-Dist: aiohttp-retry ~=2.8
28
28
  Requires-Dist: click ~=8.1
29
29
  Requires-Dist: nest-asyncio ~=1.0
30
30
  Requires-Dist: ipython ~=8.10
31
- Requires-Dist: nuclio-jupyter ~=0.9.17
31
+ Requires-Dist: nuclio-jupyter ~=0.10.0
32
32
  Requires-Dist: numpy <1.27.0,>=1.16.5
33
33
  Requires-Dist: pandas <2.2,>=1.2
34
34
  Requires-Dist: pyarrow <15,>=10.0
35
- Requires-Dist: pyyaml ~=5.1
35
+ Requires-Dist: pyyaml <7,>=5.4.1
36
36
  Requires-Dist: requests ~=2.31
37
37
  Requires-Dist: tabulate ~=0.8.6
38
38
  Requires-Dist: v3io ~=0.6.4
39
39
  Requires-Dist: pydantic <1.10.15,>=1.10.8
40
40
  Requires-Dist: mergedeep ~=1.3
41
- Requires-Dist: v3io-frames ~=0.10.12
41
+ Requires-Dist: v3io-frames ~=0.10.14
42
42
  Requires-Dist: semver ~=3.0
43
43
  Requires-Dist: dependency-injector ~=4.41
44
44
  Requires-Dist: fsspec <2024.4,>=2023.9.2
45
45
  Requires-Dist: v3iofs ~=0.1.17
46
- Requires-Dist: storey ~=1.7.17
46
+ Requires-Dist: storey ~=1.7.20
47
47
  Requires-Dist: inflection ~=0.5.0
48
48
  Requires-Dist: python-dotenv ~=0.17.0
49
49
  Requires-Dist: setuptools ~=69.1
50
50
  Requires-Dist: deprecated ~=1.2
51
51
  Requires-Dist: jinja2 >=3.1.3,~=3.1
52
52
  Requires-Dist: orjson <4,>=3.9.15
53
- Requires-Dist: mlrun-pipelines-kfp-common ~=0.1.0
54
- Requires-Dist: mlrun-pipelines-kfp-v1-8 ~=0.1.0
53
+ Requires-Dist: mlrun-pipelines-kfp-common ~=0.1.2
54
+ Requires-Dist: mlrun-pipelines-kfp-v1-8 ~=0.1.2
55
55
  Provides-Extra: alibaba-oss
56
56
  Requires-Dist: ossfs ==2023.12.0 ; extra == 'alibaba-oss'
57
57
  Requires-Dist: oss2 ==2.18.1 ; extra == 'alibaba-oss'
@@ -81,6 +81,7 @@ Requires-Dist: plotly <5.12.0,~=5.4 ; extra == 'all'
81
81
  Requires-Dist: pyopenssl >=23 ; extra == 'all'
82
82
  Requires-Dist: redis ~=4.3 ; extra == 'all'
83
83
  Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'all'
84
+ Requires-Dist: snowflake-connector-python ~=3.7 ; extra == 'all'
84
85
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'all'
85
86
  Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'all'
86
87
  Provides-Extra: api
@@ -88,13 +89,14 @@ Requires-Dist: uvicorn ~=0.27.1 ; extra == 'api'
88
89
  Requires-Dist: dask-kubernetes ~=0.11.0 ; extra == 'api'
89
90
  Requires-Dist: apscheduler <4,>=3.10.3 ; extra == 'api'
90
91
  Requires-Dist: objgraph ~=3.6 ; extra == 'api'
91
- Requires-Dist: igz-mgmt ~=0.1.3 ; extra == 'api'
92
+ Requires-Dist: igz-mgmt ~=0.2.0 ; extra == 'api'
92
93
  Requires-Dist: humanfriendly ~=10.0 ; extra == 'api'
93
94
  Requires-Dist: fastapi ~=0.110.0 ; extra == 'api'
94
95
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'api'
95
96
  Requires-Dist: pymysql ~=1.0 ; extra == 'api'
96
97
  Requires-Dist: alembic ~=1.9 ; extra == 'api'
97
98
  Requires-Dist: timelength ~=1.1 ; extra == 'api'
99
+ Requires-Dist: memray ~=1.12 ; extra == 'api'
98
100
  Provides-Extra: azure-blob-storage
99
101
  Requires-Dist: msrest ~=0.6.21 ; extra == 'azure-blob-storage'
100
102
  Requires-Dist: azure-core ~=1.24 ; extra == 'azure-blob-storage'
@@ -129,6 +131,7 @@ Requires-Dist: plotly <5.12.0,~=5.4 ; extra == 'complete'
129
131
  Requires-Dist: pyopenssl >=23 ; extra == 'complete'
130
132
  Requires-Dist: redis ~=4.3 ; extra == 'complete'
131
133
  Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'complete'
134
+ Requires-Dist: snowflake-connector-python ~=3.7 ; extra == 'complete'
132
135
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'complete'
133
136
  Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'complete'
134
137
  Provides-Extra: complete-api
@@ -150,8 +153,9 @@ Requires-Dist: gcsfs <2024.4,>=2023.9.2 ; extra == 'complete-api'
150
153
  Requires-Dist: google-cloud-bigquery[bqstorage,pandas] ==3.14.1 ; extra == 'complete-api'
151
154
  Requires-Dist: graphviz ~=0.20.0 ; extra == 'complete-api'
152
155
  Requires-Dist: humanfriendly ~=10.0 ; extra == 'complete-api'
153
- Requires-Dist: igz-mgmt ~=0.1.3 ; extra == 'complete-api'
156
+ Requires-Dist: igz-mgmt ~=0.2.0 ; extra == 'complete-api'
154
157
  Requires-Dist: kafka-python ~=2.0 ; extra == 'complete-api'
158
+ Requires-Dist: memray ~=1.12 ; extra == 'complete-api'
155
159
  Requires-Dist: mlflow ~=2.8 ; extra == 'complete-api'
156
160
  Requires-Dist: msrest ~=0.6.21 ; extra == 'complete-api'
157
161
  Requires-Dist: objgraph ~=3.6 ; extra == 'complete-api'
@@ -162,6 +166,7 @@ Requires-Dist: pymysql ~=1.0 ; extra == 'complete-api'
162
166
  Requires-Dist: pyopenssl >=23 ; extra == 'complete-api'
163
167
  Requires-Dist: redis ~=4.3 ; extra == 'complete-api'
164
168
  Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 'complete-api'
169
+ Requires-Dist: snowflake-connector-python ~=3.7 ; extra == 'complete-api'
165
170
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'complete-api'
166
171
  Requires-Dist: taos-ws-py ~=0.3.2 ; extra == 'complete-api'
167
172
  Requires-Dist: timelength ~=1.1 ; extra == 'complete-api'
@@ -194,6 +199,8 @@ Provides-Extra: s3
194
199
  Requires-Dist: boto3 <1.29.0,>=1.28.0 ; extra == 's3'
195
200
  Requires-Dist: aiobotocore <2.8,>=2.5.0 ; extra == 's3'
196
201
  Requires-Dist: s3fs <2024.4,>=2023.9.2 ; extra == 's3'
202
+ Provides-Extra: snowflake
203
+ Requires-Dist: snowflake-connector-python ~=3.7 ; extra == 'snowflake'
197
204
  Provides-Extra: sqlalchemy
198
205
  Requires-Dist: sqlalchemy ~=1.4 ; extra == 'sqlalchemy'
199
206
  Provides-Extra: tdengine