mlrun 1.7.1rc10__py3-none-any.whl → 1.8.0rc11__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 (259) hide show
  1. mlrun/__init__.py +23 -21
  2. mlrun/__main__.py +3 -3
  3. mlrun/alerts/alert.py +148 -14
  4. mlrun/artifacts/__init__.py +2 -3
  5. mlrun/artifacts/base.py +55 -12
  6. mlrun/artifacts/dataset.py +16 -16
  7. mlrun/artifacts/document.py +378 -0
  8. mlrun/artifacts/manager.py +26 -17
  9. mlrun/artifacts/model.py +66 -53
  10. mlrun/common/constants.py +8 -0
  11. mlrun/common/formatters/__init__.py +1 -0
  12. mlrun/common/formatters/feature_set.py +1 -0
  13. mlrun/common/formatters/function.py +1 -0
  14. mlrun/{model_monitoring/db/stores/base/__init__.py → common/formatters/model_endpoint.py} +16 -1
  15. mlrun/common/formatters/pipeline.py +1 -2
  16. mlrun/common/formatters/project.py +9 -0
  17. mlrun/common/model_monitoring/__init__.py +0 -5
  18. mlrun/common/model_monitoring/helpers.py +1 -29
  19. mlrun/common/runtimes/constants.py +1 -2
  20. mlrun/common/schemas/__init__.py +6 -2
  21. mlrun/common/schemas/alert.py +111 -19
  22. mlrun/common/schemas/api_gateway.py +3 -3
  23. mlrun/common/schemas/artifact.py +11 -7
  24. mlrun/common/schemas/auth.py +6 -4
  25. mlrun/common/schemas/background_task.py +7 -7
  26. mlrun/common/schemas/client_spec.py +2 -3
  27. mlrun/common/schemas/clusterization_spec.py +2 -2
  28. mlrun/common/schemas/common.py +53 -3
  29. mlrun/common/schemas/constants.py +15 -0
  30. mlrun/common/schemas/datastore_profile.py +1 -1
  31. mlrun/common/schemas/feature_store.py +9 -9
  32. mlrun/common/schemas/frontend_spec.py +4 -4
  33. mlrun/common/schemas/function.py +10 -10
  34. mlrun/common/schemas/hub.py +1 -1
  35. mlrun/common/schemas/k8s.py +3 -3
  36. mlrun/common/schemas/memory_reports.py +3 -3
  37. mlrun/common/schemas/model_monitoring/__init__.py +2 -1
  38. mlrun/common/schemas/model_monitoring/constants.py +67 -14
  39. mlrun/common/schemas/model_monitoring/grafana.py +1 -1
  40. mlrun/common/schemas/model_monitoring/model_endpoints.py +92 -147
  41. mlrun/common/schemas/notification.py +24 -3
  42. mlrun/common/schemas/object.py +1 -1
  43. mlrun/common/schemas/pagination.py +4 -4
  44. mlrun/common/schemas/partition.py +137 -0
  45. mlrun/common/schemas/pipeline.py +2 -2
  46. mlrun/common/schemas/project.py +25 -17
  47. mlrun/common/schemas/runs.py +2 -2
  48. mlrun/common/schemas/runtime_resource.py +5 -5
  49. mlrun/common/schemas/schedule.py +1 -1
  50. mlrun/common/schemas/secret.py +1 -1
  51. mlrun/common/schemas/tag.py +3 -3
  52. mlrun/common/schemas/workflow.py +5 -5
  53. mlrun/config.py +68 -10
  54. mlrun/data_types/__init__.py +0 -2
  55. mlrun/data_types/data_types.py +1 -0
  56. mlrun/data_types/infer.py +3 -1
  57. mlrun/data_types/spark.py +5 -3
  58. mlrun/data_types/to_pandas.py +11 -2
  59. mlrun/datastore/__init__.py +2 -2
  60. mlrun/datastore/alibaba_oss.py +4 -1
  61. mlrun/datastore/azure_blob.py +4 -1
  62. mlrun/datastore/base.py +12 -4
  63. mlrun/datastore/datastore.py +9 -3
  64. mlrun/datastore/datastore_profile.py +79 -20
  65. mlrun/datastore/dbfs_store.py +4 -1
  66. mlrun/datastore/filestore.py +4 -1
  67. mlrun/datastore/google_cloud_storage.py +4 -1
  68. mlrun/datastore/hdfs.py +4 -1
  69. mlrun/datastore/inmem.py +4 -1
  70. mlrun/datastore/redis.py +4 -1
  71. mlrun/datastore/s3.py +4 -1
  72. mlrun/datastore/sources.py +52 -51
  73. mlrun/datastore/store_resources.py +7 -4
  74. mlrun/datastore/targets.py +23 -22
  75. mlrun/datastore/utils.py +2 -2
  76. mlrun/datastore/v3io.py +4 -1
  77. mlrun/datastore/vectorstore.py +229 -0
  78. mlrun/datastore/wasbfs/fs.py +13 -12
  79. mlrun/db/base.py +213 -83
  80. mlrun/db/factory.py +0 -3
  81. mlrun/db/httpdb.py +1265 -387
  82. mlrun/db/nopdb.py +205 -74
  83. mlrun/errors.py +2 -2
  84. mlrun/execution.py +136 -50
  85. mlrun/feature_store/__init__.py +0 -2
  86. mlrun/feature_store/api.py +41 -40
  87. mlrun/feature_store/common.py +9 -9
  88. mlrun/feature_store/feature_set.py +20 -18
  89. mlrun/feature_store/feature_vector.py +27 -24
  90. mlrun/feature_store/retrieval/base.py +14 -9
  91. mlrun/feature_store/retrieval/job.py +2 -1
  92. mlrun/feature_store/steps.py +2 -2
  93. mlrun/features.py +30 -13
  94. mlrun/frameworks/__init__.py +1 -2
  95. mlrun/frameworks/_common/__init__.py +1 -2
  96. mlrun/frameworks/_common/artifacts_library.py +2 -2
  97. mlrun/frameworks/_common/mlrun_interface.py +10 -6
  98. mlrun/frameworks/_common/model_handler.py +29 -27
  99. mlrun/frameworks/_common/producer.py +3 -1
  100. mlrun/frameworks/_dl_common/__init__.py +1 -2
  101. mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
  102. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
  103. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
  104. mlrun/frameworks/_ml_common/__init__.py +1 -2
  105. mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
  106. mlrun/frameworks/_ml_common/model_handler.py +21 -21
  107. mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
  108. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
  109. mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
  110. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
  111. mlrun/frameworks/auto_mlrun/__init__.py +1 -2
  112. mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
  113. mlrun/frameworks/huggingface/__init__.py +1 -2
  114. mlrun/frameworks/huggingface/model_server.py +9 -9
  115. mlrun/frameworks/lgbm/__init__.py +47 -44
  116. mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
  117. mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
  118. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
  119. mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
  120. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
  121. mlrun/frameworks/lgbm/model_handler.py +15 -11
  122. mlrun/frameworks/lgbm/model_server.py +11 -7
  123. mlrun/frameworks/lgbm/utils.py +2 -2
  124. mlrun/frameworks/onnx/__init__.py +1 -2
  125. mlrun/frameworks/onnx/dataset.py +3 -3
  126. mlrun/frameworks/onnx/mlrun_interface.py +2 -2
  127. mlrun/frameworks/onnx/model_handler.py +7 -5
  128. mlrun/frameworks/onnx/model_server.py +8 -6
  129. mlrun/frameworks/parallel_coordinates.py +11 -11
  130. mlrun/frameworks/pytorch/__init__.py +22 -23
  131. mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
  132. mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
  133. mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
  134. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
  135. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
  136. mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
  137. mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
  138. mlrun/frameworks/pytorch/model_handler.py +21 -17
  139. mlrun/frameworks/pytorch/model_server.py +13 -9
  140. mlrun/frameworks/sklearn/__init__.py +19 -18
  141. mlrun/frameworks/sklearn/estimator.py +2 -2
  142. mlrun/frameworks/sklearn/metric.py +3 -3
  143. mlrun/frameworks/sklearn/metrics_library.py +8 -6
  144. mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
  145. mlrun/frameworks/sklearn/model_handler.py +4 -3
  146. mlrun/frameworks/tf_keras/__init__.py +11 -12
  147. mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
  148. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
  149. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
  150. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
  151. mlrun/frameworks/tf_keras/model_handler.py +17 -13
  152. mlrun/frameworks/tf_keras/model_server.py +12 -8
  153. mlrun/frameworks/xgboost/__init__.py +19 -18
  154. mlrun/frameworks/xgboost/model_handler.py +13 -9
  155. mlrun/launcher/base.py +3 -4
  156. mlrun/launcher/local.py +1 -1
  157. mlrun/launcher/remote.py +1 -1
  158. mlrun/lists.py +4 -3
  159. mlrun/model.py +117 -46
  160. mlrun/model_monitoring/__init__.py +4 -4
  161. mlrun/model_monitoring/api.py +72 -59
  162. mlrun/model_monitoring/applications/_application_steps.py +17 -17
  163. mlrun/model_monitoring/applications/base.py +165 -6
  164. mlrun/model_monitoring/applications/context.py +88 -37
  165. mlrun/model_monitoring/applications/evidently_base.py +0 -1
  166. mlrun/model_monitoring/applications/histogram_data_drift.py +43 -21
  167. mlrun/model_monitoring/applications/results.py +55 -3
  168. mlrun/model_monitoring/controller.py +207 -239
  169. mlrun/model_monitoring/db/__init__.py +0 -2
  170. mlrun/model_monitoring/db/_schedules.py +156 -0
  171. mlrun/model_monitoring/db/_stats.py +189 -0
  172. mlrun/model_monitoring/db/tsdb/base.py +78 -25
  173. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +61 -6
  174. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
  175. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +255 -29
  176. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
  177. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +78 -17
  178. mlrun/model_monitoring/helpers.py +151 -49
  179. mlrun/model_monitoring/stream_processing.py +99 -283
  180. mlrun/model_monitoring/tracking_policy.py +10 -3
  181. mlrun/model_monitoring/writer.py +48 -36
  182. mlrun/package/__init__.py +3 -6
  183. mlrun/package/context_handler.py +1 -1
  184. mlrun/package/packager.py +12 -9
  185. mlrun/package/packagers/__init__.py +0 -2
  186. mlrun/package/packagers/default_packager.py +14 -11
  187. mlrun/package/packagers/numpy_packagers.py +16 -7
  188. mlrun/package/packagers/pandas_packagers.py +18 -18
  189. mlrun/package/packagers/python_standard_library_packagers.py +25 -11
  190. mlrun/package/packagers_manager.py +31 -14
  191. mlrun/package/utils/__init__.py +0 -3
  192. mlrun/package/utils/_pickler.py +6 -6
  193. mlrun/platforms/__init__.py +47 -16
  194. mlrun/platforms/iguazio.py +4 -1
  195. mlrun/projects/operations.py +27 -27
  196. mlrun/projects/pipelines.py +71 -36
  197. mlrun/projects/project.py +890 -220
  198. mlrun/run.py +53 -10
  199. mlrun/runtimes/__init__.py +1 -3
  200. mlrun/runtimes/base.py +15 -11
  201. mlrun/runtimes/daskjob.py +9 -9
  202. mlrun/runtimes/generators.py +2 -1
  203. mlrun/runtimes/kubejob.py +4 -5
  204. mlrun/runtimes/mounts.py +572 -0
  205. mlrun/runtimes/mpijob/__init__.py +0 -2
  206. mlrun/runtimes/mpijob/abstract.py +7 -6
  207. mlrun/runtimes/nuclio/api_gateway.py +7 -7
  208. mlrun/runtimes/nuclio/application/application.py +11 -11
  209. mlrun/runtimes/nuclio/function.py +19 -17
  210. mlrun/runtimes/nuclio/serving.py +18 -13
  211. mlrun/runtimes/pod.py +154 -45
  212. mlrun/runtimes/remotesparkjob.py +3 -2
  213. mlrun/runtimes/sparkjob/__init__.py +0 -2
  214. mlrun/runtimes/sparkjob/spark3job.py +21 -11
  215. mlrun/runtimes/utils.py +6 -5
  216. mlrun/serving/merger.py +6 -4
  217. mlrun/serving/remote.py +18 -17
  218. mlrun/serving/routers.py +185 -172
  219. mlrun/serving/server.py +7 -1
  220. mlrun/serving/states.py +97 -78
  221. mlrun/serving/utils.py +13 -2
  222. mlrun/serving/v1_serving.py +3 -2
  223. mlrun/serving/v2_serving.py +105 -72
  224. mlrun/track/__init__.py +1 -1
  225. mlrun/track/tracker.py +2 -2
  226. mlrun/track/trackers/mlflow_tracker.py +6 -5
  227. mlrun/utils/async_http.py +1 -1
  228. mlrun/utils/clones.py +1 -1
  229. mlrun/utils/helpers.py +63 -19
  230. mlrun/utils/logger.py +106 -4
  231. mlrun/utils/notifications/notification/__init__.py +22 -19
  232. mlrun/utils/notifications/notification/base.py +33 -14
  233. mlrun/utils/notifications/notification/console.py +6 -6
  234. mlrun/utils/notifications/notification/git.py +11 -11
  235. mlrun/utils/notifications/notification/ipython.py +10 -9
  236. mlrun/utils/notifications/notification/mail.py +176 -0
  237. mlrun/utils/notifications/notification/slack.py +6 -6
  238. mlrun/utils/notifications/notification/webhook.py +6 -6
  239. mlrun/utils/notifications/notification_pusher.py +86 -44
  240. mlrun/utils/regex.py +11 -2
  241. mlrun/utils/version/version.json +2 -2
  242. {mlrun-1.7.1rc10.dist-info → mlrun-1.8.0rc11.dist-info}/METADATA +29 -24
  243. mlrun-1.8.0rc11.dist-info/RECORD +347 -0
  244. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  245. mlrun/model_monitoring/db/stores/base/store.py +0 -213
  246. mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
  247. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -71
  248. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -190
  249. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -103
  250. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -40
  251. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -659
  252. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
  253. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -726
  254. mlrun/model_monitoring/model_endpoint.py +0 -118
  255. mlrun-1.7.1rc10.dist-info/RECORD +0 -351
  256. {mlrun-1.7.1rc10.dist-info → mlrun-1.8.0rc11.dist-info}/LICENSE +0 -0
  257. {mlrun-1.7.1rc10.dist-info → mlrun-1.8.0rc11.dist-info}/WHEEL +0 -0
  258. {mlrun-1.7.1rc10.dist-info → mlrun-1.8.0rc11.dist-info}/entry_points.txt +0 -0
  259. {mlrun-1.7.1rc10.dist-info → mlrun-1.8.0rc11.dist-info}/top_level.txt +0 -0
mlrun/projects/project.py CHANGED
@@ -28,21 +28,20 @@ import warnings
28
28
  import zipfile
29
29
  from copy import deepcopy
30
30
  from os import environ, makedirs, path
31
- from typing import Callable, Optional, Union
31
+ from typing import Callable, Optional, Union, cast
32
32
 
33
33
  import dotenv
34
34
  import git
35
35
  import git.exc
36
- import mlrun_pipelines.common.models
37
- import mlrun_pipelines.mounts
38
36
  import nuclio.utils
39
37
  import requests
40
38
  import yaml
41
- from mlrun_pipelines.models import PipelineNodeWrapper
42
39
 
40
+ import mlrun.artifacts.model
43
41
  import mlrun.common.formatters
44
42
  import mlrun.common.helpers
45
43
  import mlrun.common.runtimes.constants
44
+ import mlrun.common.schemas.alert
46
45
  import mlrun.common.schemas.artifact
47
46
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
48
47
  import mlrun.db
@@ -51,18 +50,37 @@ import mlrun.k8s_utils
51
50
  import mlrun.lists
52
51
  import mlrun.model_monitoring.applications as mm_app
53
52
  import mlrun.runtimes
53
+ import mlrun.runtimes.mounts
54
54
  import mlrun.runtimes.nuclio.api_gateway
55
55
  import mlrun.runtimes.pod
56
56
  import mlrun.runtimes.utils
57
57
  import mlrun.serving
58
58
  import mlrun.utils
59
59
  import mlrun.utils.regex
60
+ import mlrun_pipelines.common.models
60
61
  from mlrun.alerts.alert import AlertConfig
61
- from mlrun.common.schemas.alert import AlertTemplate
62
- from mlrun.datastore.datastore_profile import DatastoreProfile, DatastoreProfile2Json
62
+ from mlrun.common.schemas import alert as alert_constants
63
+ from mlrun.datastore.datastore_profile import (
64
+ DatastoreProfile,
65
+ DatastoreProfile2Json,
66
+ datastore_profile_read,
67
+ )
68
+ from mlrun.datastore.vectorstore import VectorStoreCollection
69
+ from mlrun.model_monitoring.helpers import (
70
+ filter_results_by_regex,
71
+ get_result_instance_fqn,
72
+ )
63
73
  from mlrun.runtimes.nuclio.function import RemoteRuntime
74
+ from mlrun_pipelines.models import PipelineNodeWrapper
64
75
 
65
- from ..artifacts import Artifact, ArtifactProducer, DatasetArtifact, ModelArtifact
76
+ from ..artifacts import (
77
+ Artifact,
78
+ ArtifactProducer,
79
+ DatasetArtifact,
80
+ DocumentArtifact,
81
+ DocumentLoaderSpec,
82
+ ModelArtifact,
83
+ )
66
84
  from ..artifacts.manager import ArtifactManager, dict_to_artifact, extend_artifact_path
67
85
  from ..datastore import store_manager
68
86
  from ..features import Feature
@@ -126,15 +144,15 @@ def new_project(
126
144
  context: str = "./",
127
145
  init_git: bool = False,
128
146
  user_project: bool = False,
129
- remote: str = None,
130
- from_template: str = None,
131
- secrets: dict = None,
132
- description: str = None,
133
- subpath: str = None,
147
+ remote: Optional[str] = None,
148
+ from_template: Optional[str] = None,
149
+ secrets: Optional[dict] = None,
150
+ description: Optional[str] = None,
151
+ subpath: Optional[str] = None,
134
152
  save: bool = True,
135
153
  overwrite: bool = False,
136
- parameters: dict = None,
137
- default_function_node_selector: dict = None,
154
+ parameters: Optional[dict] = None,
155
+ default_function_node_selector: Optional[dict] = None,
138
156
  ) -> "MlrunProject":
139
157
  """Create a new MLRun project, optionally load it from a yaml/zip/git template
140
158
 
@@ -291,17 +309,17 @@ def new_project(
291
309
 
292
310
  def load_project(
293
311
  context: str = "./",
294
- url: str = None,
295
- name: str = None,
296
- secrets: dict = None,
312
+ url: Optional[str] = None,
313
+ name: Optional[str] = None,
314
+ secrets: Optional[dict] = None,
297
315
  init_git: bool = False,
298
- subpath: str = None,
316
+ subpath: Optional[str] = None,
299
317
  clone: bool = False,
300
318
  user_project: bool = False,
301
319
  save: bool = True,
302
320
  sync_functions: bool = False,
303
- parameters: dict = None,
304
- allow_cross_project: bool = None,
321
+ parameters: Optional[dict] = None,
322
+ allow_cross_project: Optional[bool] = None,
305
323
  ) -> "MlrunProject":
306
324
  """Load an MLRun project from git or tar or dir
307
325
 
@@ -437,16 +455,16 @@ def load_project(
437
455
  def get_or_create_project(
438
456
  name: str,
439
457
  context: str = "./",
440
- url: str = None,
441
- secrets: dict = None,
458
+ url: Optional[str] = None,
459
+ secrets: Optional[dict] = None,
442
460
  init_git=False,
443
- subpath: str = None,
461
+ subpath: Optional[str] = None,
444
462
  clone: bool = False,
445
463
  user_project: bool = False,
446
- from_template: str = None,
464
+ from_template: Optional[str] = None,
447
465
  save: bool = True,
448
- parameters: dict = None,
449
- allow_cross_project: bool = None,
466
+ parameters: Optional[dict] = None,
467
+ allow_cross_project: Optional[bool] = None,
450
468
  ) -> "MlrunProject":
451
469
  """Load a project from MLRun DB, or create/import if it does not exist
452
470
 
@@ -823,14 +841,14 @@ class ProjectSpec(ModelObj):
823
841
  origin_url=None,
824
842
  goals=None,
825
843
  load_source_on_run=None,
826
- default_requirements: typing.Union[str, list[str]] = None,
844
+ default_requirements: Optional[typing.Union[str, list[str]]] = None,
827
845
  desired_state=mlrun.common.schemas.ProjectState.online.value,
828
846
  owner=None,
829
847
  disable_auto_mount=None,
830
848
  workdir=None,
831
849
  default_image=None,
832
850
  build=None,
833
- custom_packagers: list[tuple[str, bool]] = None,
851
+ custom_packagers: Optional[list[tuple[str, bool]]] = None,
834
852
  default_function_node_selector=None,
835
853
  ):
836
854
  self.repo = None
@@ -1253,7 +1271,11 @@ class MlrunProject(ModelObj):
1253
1271
  raise exc
1254
1272
 
1255
1273
  def get_artifact_uri(
1256
- self, key: str, category: str = "artifact", tag: str = None, iter: int = None
1274
+ self,
1275
+ key: str,
1276
+ category: str = "artifact",
1277
+ tag: Optional[str] = None,
1278
+ iter: Optional[int] = None,
1257
1279
  ) -> str:
1258
1280
  """return the project artifact uri (store://..) from the artifact key
1259
1281
 
@@ -1353,7 +1375,7 @@ class MlrunProject(ModelObj):
1353
1375
  workflow_path: str,
1354
1376
  embed: bool = False,
1355
1377
  engine: Optional[str] = None,
1356
- args_schema: list[EntrypointParam] = None,
1378
+ args_schema: Optional[list[EntrypointParam]] = None,
1357
1379
  handler: Optional[str] = None,
1358
1380
  schedule: typing.Union[str, mlrun.common.schemas.ScheduleCronTrigger] = None,
1359
1381
  ttl: Optional[int] = None,
@@ -1425,8 +1447,8 @@ class MlrunProject(ModelObj):
1425
1447
  self,
1426
1448
  key,
1427
1449
  artifact: typing.Union[str, dict, Artifact] = None,
1428
- target_path: str = None,
1429
- tag: str = None,
1450
+ target_path: Optional[str] = None,
1451
+ tag: Optional[str] = None,
1430
1452
  ):
1431
1453
  """add/set an artifact in the project spec (will be registered on load)
1432
1454
 
@@ -1515,6 +1537,12 @@ class MlrunProject(ModelObj):
1515
1537
  is_retained_producer=is_retained_producer,
1516
1538
  )
1517
1539
 
1540
+ def update_artifact(self, artifact_object: Artifact):
1541
+ artifacts_manager = self._get_artifact_manager()
1542
+ project_tag = self._get_project_tag()
1543
+ producer, _ = self._resolve_artifact_producer(artifact_object, project_tag)
1544
+ artifacts_manager.update_artifact(producer, artifact_object)
1545
+
1518
1546
  def _get_artifact_manager(self):
1519
1547
  if self._artifact_manager:
1520
1548
  return self._artifact_manager
@@ -1646,7 +1674,7 @@ class MlrunProject(ModelObj):
1646
1674
  deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
1647
1675
  mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
1648
1676
  ),
1649
- secrets: dict = None,
1677
+ secrets: Optional[dict] = None,
1650
1678
  ):
1651
1679
  """Delete an artifact object in the DB and optionally delete the artifact data
1652
1680
 
@@ -1710,7 +1738,7 @@ class MlrunProject(ModelObj):
1710
1738
  :param upload: upload to datastore (default is True)
1711
1739
  :param labels: a set of key/value labels to tag the artifact with
1712
1740
 
1713
- :returns: artifact object
1741
+ :returns: dataset artifact object
1714
1742
  """
1715
1743
  ds = DatasetArtifact(
1716
1744
  key,
@@ -1723,14 +1751,17 @@ class MlrunProject(ModelObj):
1723
1751
  **kwargs,
1724
1752
  )
1725
1753
 
1726
- item = self.log_artifact(
1727
- ds,
1728
- local_path=local_path,
1729
- artifact_path=artifact_path,
1730
- target_path=target_path,
1731
- tag=tag,
1732
- upload=upload,
1733
- labels=labels,
1754
+ item = cast(
1755
+ DatasetArtifact,
1756
+ self.log_artifact(
1757
+ ds,
1758
+ local_path=local_path,
1759
+ artifact_path=artifact_path,
1760
+ target_path=target_path,
1761
+ tag=tag,
1762
+ upload=upload,
1763
+ labels=labels,
1764
+ ),
1734
1765
  )
1735
1766
  return item
1736
1767
 
@@ -1777,7 +1808,7 @@ class MlrunProject(ModelObj):
1777
1808
  :param key: artifact key or artifact class ()
1778
1809
  :param body: will use the body as the artifact content
1779
1810
  :param model_file: path to the local model file we upload (see also model_dir)
1780
- or to a model file data url (e.g. http://host/path/model.pkl)
1811
+ or to a model file data url (e.g. `http://host/path/model.pkl`)
1781
1812
  :param model_dir: path to the local dir holding the model file and extra files
1782
1813
  :param artifact_path: target artifact path (when not using the default)
1783
1814
  to define a subpath under the default location use:
@@ -1798,7 +1829,7 @@ class MlrunProject(ModelObj):
1798
1829
  :param extra_data: key/value list of extra files/charts to link with this dataset
1799
1830
  value can be absolute path | relative path (to model dir) | bytes | artifact object
1800
1831
 
1801
- :returns: artifact object
1832
+ :returns: model artifact object
1802
1833
  """
1803
1834
 
1804
1835
  if training_set is not None and inputs:
@@ -1825,14 +1856,73 @@ class MlrunProject(ModelObj):
1825
1856
  if training_set is not None:
1826
1857
  model.infer_from_df(training_set, label_column)
1827
1858
 
1828
- item = self.log_artifact(
1829
- model,
1830
- artifact_path=artifact_path,
1859
+ item = cast(
1860
+ ModelArtifact,
1861
+ self.log_artifact(
1862
+ model,
1863
+ artifact_path=artifact_path,
1864
+ tag=tag,
1865
+ upload=upload,
1866
+ labels=labels,
1867
+ ),
1868
+ )
1869
+ return item
1870
+
1871
+ def get_vector_store_collection(
1872
+ self,
1873
+ vector_store: "VectorStore", # noqa: F821
1874
+ collection_name: Optional[str] = None,
1875
+ ) -> VectorStoreCollection:
1876
+ return VectorStoreCollection(
1877
+ self,
1878
+ vector_store,
1879
+ collection_name,
1880
+ )
1881
+
1882
+ def log_document(
1883
+ self,
1884
+ key: str,
1885
+ tag: str = "",
1886
+ local_path: str = "",
1887
+ artifact_path: Optional[str] = None,
1888
+ document_loader_spec: Optional[DocumentLoaderSpec] = None,
1889
+ upload: Optional[bool] = False,
1890
+ labels: Optional[dict[str, str]] = None,
1891
+ target_path: Optional[str] = None,
1892
+ **kwargs,
1893
+ ) -> DocumentArtifact:
1894
+ """
1895
+ Log a document as an artifact.
1896
+
1897
+ :param key: Artifact key
1898
+ :param tag: Version tag
1899
+ :param local_path: path to the local file we upload, will also be use
1900
+ as the destination subpath (under "artifact_path")
1901
+ :param artifact_path: Target path for artifact storage
1902
+ :param document_loader_spec: Spec to use to load the artifact as langchain document
1903
+ :param upload: Whether to upload the artifact
1904
+ :param labels: Key-value labels
1905
+ :param target_path: Target file path
1906
+ :param kwargs: Additional keyword arguments
1907
+ :return: DocumentArtifact object
1908
+ """
1909
+ doc_artifact = DocumentArtifact(
1910
+ key=key,
1911
+ original_source=local_path or target_path,
1912
+ document_loader_spec=document_loader_spec
1913
+ if document_loader_spec
1914
+ else DocumentLoaderSpec(),
1915
+ **kwargs,
1916
+ )
1917
+ return self.log_artifact(
1918
+ item=doc_artifact,
1831
1919
  tag=tag,
1920
+ local_path=local_path,
1921
+ artifact_path=artifact_path,
1832
1922
  upload=upload,
1833
1923
  labels=labels,
1924
+ target_path=target_path,
1834
1925
  )
1835
- return item
1836
1926
 
1837
1927
  def import_artifact(
1838
1928
  self, item_path: str, new_key=None, artifact_path=None, tag=None
@@ -1946,22 +2036,100 @@ class MlrunProject(ModelObj):
1946
2036
  )
1947
2037
  return _run_project_setup(self, setup_file_path, save)
1948
2038
 
2039
+ def create_model_monitoring_alert_configs(
2040
+ self,
2041
+ name: str,
2042
+ summary: str,
2043
+ endpoints: mlrun.common.schemas.ModelEndpointList,
2044
+ events: Union[list[alert_constants.EventKind], alert_constants.EventKind],
2045
+ notifications: list[alert_constants.AlertNotification],
2046
+ result_names: Optional[
2047
+ list[str]
2048
+ ] = None, # can use wildcards - see below for explanation.
2049
+ severity: alert_constants.AlertSeverity = alert_constants.AlertSeverity.MEDIUM,
2050
+ criteria: alert_constants.AlertCriteria = alert_constants.AlertCriteria(
2051
+ count=1, period="10m"
2052
+ ),
2053
+ reset_policy: mlrun.common.schemas.alert.ResetPolicy = mlrun.common.schemas.alert.ResetPolicy.AUTO,
2054
+ ) -> list[mlrun.alerts.alert.AlertConfig]:
2055
+ """
2056
+ :param name: AlertConfig name.
2057
+ :param summary: Summary of the alert, will be sent in the generated notifications
2058
+ :param endpoints: The endpoints from which to retrieve the metrics that the
2059
+ alerts will be based on.
2060
+ :param events: AlertTrigger event types (EventKind).
2061
+ :param notifications: List of notifications to invoke once the alert is triggered
2062
+ :param result_names: Optional. Filters the result names used to create the alert configuration,
2063
+ constructed from the app and result_name regex.
2064
+
2065
+ For example:
2066
+ [`app1.result-*`, `*.result1`]
2067
+ will match "mep1.app1.result.result-1" and "mep1.app2.result.result1".
2068
+ :param severity: Severity of the alert.
2069
+ :param criteria: When the alert will be triggered based on the
2070
+ specified number of events within the defined time period.
2071
+ :param reset_policy: When to clear the alert. May be "manual" for manual reset of the alert,
2072
+ or "auto" if the criteria contains a time period.
2073
+ :returns: List of AlertConfig according to endpoints results,
2074
+ filtered by result_names.
2075
+ """
2076
+ db = mlrun.db.get_run_db(secrets=self._secrets)
2077
+ matching_results = []
2078
+ alerts = []
2079
+ # TODO: Refactor to use a single request to improve performance at scale, ML-8473
2080
+ for endpoint in endpoints.endpoints:
2081
+ results_by_endpoint = db.get_model_endpoint_monitoring_metrics(
2082
+ project=self.name, endpoint_id=endpoint.metadata.uid, type="results"
2083
+ )
2084
+ results_fqn_by_endpoint = [
2085
+ get_result_instance_fqn(
2086
+ model_endpoint_id=endpoint.metadata.uid,
2087
+ app_name=result.app,
2088
+ result_name=result.name,
2089
+ )
2090
+ for result in results_by_endpoint
2091
+ ]
2092
+ matching_results += filter_results_by_regex(
2093
+ existing_result_names=results_fqn_by_endpoint,
2094
+ result_name_filters=result_names,
2095
+ )
2096
+ for result_fqn in matching_results:
2097
+ alerts.append(
2098
+ mlrun.alerts.alert.AlertConfig(
2099
+ project=self.name,
2100
+ name=name,
2101
+ summary=summary,
2102
+ severity=severity,
2103
+ entities=alert_constants.EventEntities(
2104
+ kind=alert_constants.EventEntityKind.MODEL_ENDPOINT_RESULT,
2105
+ project=self.name,
2106
+ ids=[result_fqn],
2107
+ ),
2108
+ trigger=alert_constants.AlertTrigger(
2109
+ events=events if isinstance(events, list) else [events]
2110
+ ),
2111
+ criteria=criteria,
2112
+ notifications=notifications,
2113
+ reset_policy=reset_policy,
2114
+ )
2115
+ )
2116
+ return alerts
2117
+
1949
2118
  def set_model_monitoring_function(
1950
2119
  self,
1951
- func: typing.Union[str, mlrun.runtimes.BaseRuntime, None] = None,
2120
+ func: typing.Union[str, mlrun.runtimes.RemoteRuntime, None] = None,
1952
2121
  application_class: typing.Union[
1953
- str,
1954
- mm_app.ModelMonitoringApplicationBase,
2122
+ str, mm_app.ModelMonitoringApplicationBase, None
1955
2123
  ] = None,
1956
- name: str = None,
1957
- image: str = None,
2124
+ name: Optional[str] = None,
2125
+ image: Optional[str] = None,
1958
2126
  handler=None,
1959
- with_repo: bool = None,
1960
- tag: str = None,
1961
- requirements: typing.Union[str, list[str]] = None,
2127
+ with_repo: Optional[bool] = None,
2128
+ tag: Optional[str] = None,
2129
+ requirements: Optional[typing.Union[str, list[str]]] = None,
1962
2130
  requirements_file: str = "",
1963
2131
  **application_kwargs,
1964
- ) -> mlrun.runtimes.BaseRuntime:
2132
+ ) -> mlrun.runtimes.RemoteRuntime:
1965
2133
  """
1966
2134
  Update or add a monitoring function to the project.
1967
2135
  Note: to deploy the function after linking it to the project,
@@ -1973,7 +2141,8 @@ class MlrunProject(ModelObj):
1973
2141
  name="myApp", application_class="MyApp", image="mlrun/mlrun"
1974
2142
  )
1975
2143
 
1976
- :param func: Function object or spec/code url, None refers to current Notebook
2144
+ :param func: Remote function object or spec/code URL. :code:`None` refers to the current
2145
+ notebook.
1977
2146
  :param name: Name of the function (under the project), can be specified with a tag to support
1978
2147
  versions (e.g. myfunc:v1)
1979
2148
  Default: job
@@ -1989,9 +2158,8 @@ class MlrunProject(ModelObj):
1989
2158
  :param application_class: Name or an Instance of a class that implements the monitoring application.
1990
2159
  :param application_kwargs: Additional keyword arguments to be passed to the
1991
2160
  monitoring application's constructor.
2161
+ :returns: The model monitoring remote function object.
1992
2162
  """
1993
-
1994
- function_object: RemoteRuntime = None
1995
2163
  (
1996
2164
  resolved_function_name,
1997
2165
  function_object,
@@ -2015,20 +2183,20 @@ class MlrunProject(ModelObj):
2015
2183
 
2016
2184
  def create_model_monitoring_function(
2017
2185
  self,
2018
- func: str = None,
2186
+ func: Optional[str] = None,
2019
2187
  application_class: typing.Union[
2020
2188
  str,
2021
2189
  mm_app.ModelMonitoringApplicationBase,
2022
2190
  ] = None,
2023
- name: str = None,
2024
- image: str = None,
2025
- handler: str = None,
2026
- with_repo: bool = None,
2027
- tag: str = None,
2028
- requirements: typing.Union[str, list[str]] = None,
2191
+ name: Optional[str] = None,
2192
+ image: Optional[str] = None,
2193
+ handler: Optional[str] = None,
2194
+ with_repo: Optional[bool] = None,
2195
+ tag: Optional[str] = None,
2196
+ requirements: Optional[typing.Union[str, list[str]]] = None,
2029
2197
  requirements_file: str = "",
2030
2198
  **application_kwargs,
2031
- ) -> mlrun.runtimes.BaseRuntime:
2199
+ ) -> mlrun.runtimes.RemoteRuntime:
2032
2200
  """
2033
2201
  Create a monitoring function object without setting it to the project
2034
2202
 
@@ -2038,7 +2206,7 @@ class MlrunProject(ModelObj):
2038
2206
  application_class_name="MyApp", image="mlrun/mlrun", name="myApp"
2039
2207
  )
2040
2208
 
2041
- :param func: Code url, None refers to current Notebook
2209
+ :param func: The function's code URL. :code:`None` refers to the current notebook.
2042
2210
  :param name: Name of the function, can be specified with a tag to support
2043
2211
  versions (e.g. myfunc:v1)
2044
2212
  Default: job
@@ -2054,6 +2222,7 @@ class MlrunProject(ModelObj):
2054
2222
  :param application_class: Name or an Instance of a class that implementing the monitoring application.
2055
2223
  :param application_kwargs: Additional keyword arguments to be passed to the
2056
2224
  monitoring application's constructor.
2225
+ :returns: The model monitoring remote function object.
2057
2226
  """
2058
2227
 
2059
2228
  _, function_object, _ = self._instantiate_model_monitoring_function(
@@ -2086,10 +2255,9 @@ class MlrunProject(ModelObj):
2086
2255
  requirements: typing.Union[str, list[str], None] = None,
2087
2256
  requirements_file: str = "",
2088
2257
  **application_kwargs,
2089
- ) -> tuple[str, mlrun.runtimes.BaseRuntime, dict]:
2258
+ ) -> tuple[str, mlrun.runtimes.RemoteRuntime, dict]:
2090
2259
  import mlrun.model_monitoring.api
2091
2260
 
2092
- function_object: RemoteRuntime = None
2093
2261
  kind = None
2094
2262
  if (isinstance(func, str) or func is None) and application_class is not None:
2095
2263
  kind = mlrun.run.RuntimeKinds.serving
@@ -2128,9 +2296,6 @@ class MlrunProject(ModelObj):
2128
2296
  mm_constants.ModelMonitoringAppLabel.VAL,
2129
2297
  )
2130
2298
 
2131
- if not mlrun.mlconf.is_ce_mode():
2132
- function_object.apply(mlrun.mount_v3io())
2133
-
2134
2299
  return resolved_function_name, function_object, func
2135
2300
 
2136
2301
  def _wait_for_functions_deployment(self, function_names: list[str]) -> None:
@@ -2269,7 +2434,7 @@ class MlrunProject(ModelObj):
2269
2434
  delete_stream_function: bool = False,
2270
2435
  delete_histogram_data_drift_app: bool = True,
2271
2436
  delete_user_applications: bool = False,
2272
- user_application_list: list[str] = None,
2437
+ user_application_list: Optional[list[str]] = None,
2273
2438
  ) -> None:
2274
2439
  """
2275
2440
  Disable model monitoring application controller, writer, stream, histogram data drift application
@@ -2326,14 +2491,14 @@ class MlrunProject(ModelObj):
2326
2491
 
2327
2492
  def set_function(
2328
2493
  self,
2329
- func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
2494
+ func: typing.Union[str, mlrun.runtimes.BaseRuntime, None] = None,
2330
2495
  name: str = "",
2331
2496
  kind: str = "job",
2332
- image: str = None,
2333
- handler: str = None,
2334
- with_repo: bool = None,
2335
- tag: str = None,
2336
- requirements: typing.Union[str, list[str]] = None,
2497
+ image: Optional[str] = None,
2498
+ handler: Optional[str] = None,
2499
+ with_repo: Optional[bool] = None,
2500
+ tag: Optional[str] = None,
2501
+ requirements: Optional[typing.Union[str, list[str]]] = None,
2337
2502
  requirements_file: str = "",
2338
2503
  ) -> mlrun.runtimes.BaseRuntime:
2339
2504
  """
@@ -2427,11 +2592,11 @@ class MlrunProject(ModelObj):
2427
2592
  func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
2428
2593
  name: str = "",
2429
2594
  kind: str = "",
2430
- image: str = None,
2431
- handler: str = None,
2432
- with_repo: bool = None,
2433
- tag: str = None,
2434
- requirements: typing.Union[str, list[str]] = None,
2595
+ image: Optional[str] = None,
2596
+ handler: Optional[str] = None,
2597
+ with_repo: Optional[bool] = None,
2598
+ tag: Optional[str] = None,
2599
+ requirements: Optional[typing.Union[str, list[str]]] = None,
2435
2600
  requirements_file: str = "",
2436
2601
  ) -> tuple[str, str, mlrun.runtimes.BaseRuntime, dict]:
2437
2602
  if (
@@ -2654,8 +2819,8 @@ class MlrunProject(ModelObj):
2654
2819
 
2655
2820
  def pull(
2656
2821
  self,
2657
- branch: str = None,
2658
- remote: str = None,
2822
+ branch: Optional[str] = None,
2823
+ remote: Optional[str] = None,
2659
2824
  secrets: Union[SecretsStore, dict] = None,
2660
2825
  ):
2661
2826
  """pull/update sources from git or tar into the context dir
@@ -2768,10 +2933,10 @@ class MlrunProject(ModelObj):
2768
2933
  branch,
2769
2934
  message=None,
2770
2935
  update=True,
2771
- remote: str = None,
2772
- add: list = None,
2773
- author_name: str = None,
2774
- author_email: str = None,
2936
+ remote: Optional[str] = None,
2937
+ add: Optional[list] = None,
2938
+ author_name: Optional[str] = None,
2939
+ author_email: Optional[str] = None,
2775
2940
  secrets: Union[SecretsStore, dict] = None,
2776
2941
  ):
2777
2942
  """update spec and push updates to remote git repo
@@ -2834,7 +2999,7 @@ class MlrunProject(ModelObj):
2834
2999
 
2835
3000
  def sync_functions(
2836
3001
  self,
2837
- names: list = None,
3002
+ names: Optional[list] = None,
2838
3003
  always: bool = True,
2839
3004
  save: bool = False,
2840
3005
  silent: bool = False,
@@ -2978,8 +3143,8 @@ class MlrunProject(ModelObj):
2978
3143
 
2979
3144
  def set_secrets(
2980
3145
  self,
2981
- secrets: dict = None,
2982
- file_path: str = None,
3146
+ secrets: Optional[dict] = None,
3147
+ file_path: Optional[str] = None,
2983
3148
  provider: typing.Union[str, mlrun.common.schemas.SecretProviderName] = None,
2984
3149
  ):
2985
3150
  """
@@ -3056,24 +3221,24 @@ class MlrunProject(ModelObj):
3056
3221
 
3057
3222
  def run(
3058
3223
  self,
3059
- name: str = None,
3060
- workflow_path: str = None,
3061
- arguments: dict[str, typing.Any] = None,
3062
- artifact_path: str = None,
3063
- workflow_handler: typing.Union[str, typing.Callable] = None,
3064
- namespace: str = None,
3224
+ name: Optional[str] = None,
3225
+ workflow_path: Optional[str] = None,
3226
+ arguments: Optional[dict[str, typing.Any]] = None,
3227
+ artifact_path: Optional[str] = None,
3228
+ workflow_handler: Optional[typing.Union[str, typing.Callable]] = None,
3229
+ namespace: Optional[str] = None,
3065
3230
  sync: bool = False,
3066
3231
  watch: bool = False,
3067
3232
  dirty: bool = False,
3068
- engine: str = None,
3069
- local: bool = None,
3233
+ engine: Optional[str] = None,
3234
+ local: Optional[bool] = None,
3070
3235
  schedule: typing.Union[
3071
3236
  str, mlrun.common.schemas.ScheduleCronTrigger, bool
3072
3237
  ] = None,
3073
- timeout: int = None,
3074
- source: str = None,
3075
- cleanup_ttl: int = None,
3076
- notifications: list[mlrun.model.Notification] = None,
3238
+ timeout: Optional[int] = None,
3239
+ source: Optional[str] = None,
3240
+ cleanup_ttl: Optional[int] = None,
3241
+ notifications: Optional[list[mlrun.model.Notification]] = None,
3077
3242
  workflow_runner_node_selector: typing.Optional[dict[str, str]] = None,
3078
3243
  ) -> _PipelineRunStatus:
3079
3244
  """Run a workflow using kubeflow pipelines
@@ -3280,7 +3445,7 @@ class MlrunProject(ModelObj):
3280
3445
 
3281
3446
  return db.create_project(self.to_dict())
3282
3447
 
3283
- def export(self, filepath=None, include_files: str = None):
3448
+ def export(self, filepath=None, include_files: Optional[str] = None):
3284
3449
  """save the project object into a yaml file or zip archive (default to project.yaml)
3285
3450
 
3286
3451
  By default, the project object is exported to a yaml file, when the filepath suffix is '.zip'
@@ -3325,7 +3490,6 @@ class MlrunProject(ModelObj):
3325
3490
  def set_model_monitoring_credentials(
3326
3491
  self,
3327
3492
  access_key: Optional[str] = None,
3328
- endpoint_store_connection: Optional[str] = None,
3329
3493
  stream_path: Optional[str] = None,
3330
3494
  tsdb_connection: Optional[str] = None,
3331
3495
  replace_creds: bool = False,
@@ -3336,7 +3500,6 @@ class MlrunProject(ModelObj):
3336
3500
  model monitoring or serving function.
3337
3501
 
3338
3502
  :param access_key: Model monitoring access key for managing user permissions.
3339
- :param endpoint_store_connection: Endpoint store connection string. By default, None. Options:
3340
3503
 
3341
3504
  * None - will be set from the system configuration.
3342
3505
  * v3io - for v3io endpoint store, pass `v3io` and the system will generate the
@@ -3369,7 +3532,6 @@ class MlrunProject(ModelObj):
3369
3532
  project=self.name,
3370
3533
  credentials={
3371
3534
  "access_key": access_key,
3372
- "endpoint_store_connection": endpoint_store_connection,
3373
3535
  "stream_path": stream_path,
3374
3536
  "tsdb_connection": tsdb_connection,
3375
3537
  },
@@ -3385,30 +3547,92 @@ class MlrunProject(ModelObj):
3385
3547
  "and set `rebuild_images=True`"
3386
3548
  )
3387
3549
 
3550
+ def list_model_endpoints(
3551
+ self,
3552
+ name: Optional[str] = None,
3553
+ model_name: Optional[str] = None,
3554
+ function_name: Optional[str] = None,
3555
+ function_tag: Optional[str] = None,
3556
+ labels: Optional[list[str]] = None,
3557
+ start: Optional[datetime.datetime] = None,
3558
+ end: Optional[datetime.datetime] = None,
3559
+ top_level: bool = False,
3560
+ uids: Optional[list[str]] = None,
3561
+ latest_only: bool = False,
3562
+ ) -> mlrun.common.schemas.ModelEndpointList:
3563
+ """
3564
+ Returns a list of `ModelEndpoint` objects. Each `ModelEndpoint` object represents the current state of a
3565
+ model endpoint. This functions supports filtering by the following parameters:
3566
+ 1) name
3567
+ 2) model_name
3568
+ 3) function_name
3569
+ 4) function_tag
3570
+ 5) labels
3571
+ 6) top level
3572
+ 7) uids
3573
+ 8) start and end time, corresponding to the `created` field.
3574
+ By default, when no filters are applied, all available endpoints for the given project will be listed.
3575
+
3576
+ In addition, this functions provides a facade for listing endpoint related metrics. This facade is time-based
3577
+ and depends on the 'start' and 'end' parameters.
3578
+
3579
+ :param name: The name of the model to filter by
3580
+ :param model_name: The name of the model to filter by
3581
+ :param function_name: The name of the function to filter by
3582
+ :param function_tag: The tag of the function to filter by
3583
+ :param labels: Filter model endpoints by label key-value pairs or key existence. This can be provided as:
3584
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
3585
+ or `{"label": None}` to check for key existence.
3586
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
3587
+ or just `"label"` for key existence.
3588
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
3589
+ the specified key-value pairs or key existence.
3590
+ :param start: The start time to filter by.Corresponding to the `created` field.
3591
+ :param end: The end time to filter by. Corresponding to the `created` field.
3592
+ :param top_level: if true will return only routers and endpoint that are NOT children of any router
3593
+ :param uids: if passed will return a list `ModelEndpoint` object with uid in uids
3594
+
3595
+ :returns: Returns a list of `ModelEndpoint` objects.
3596
+ """
3597
+ db = mlrun.db.get_run_db(secrets=self._secrets)
3598
+ return db.list_model_endpoints(
3599
+ project=self.name,
3600
+ name=name,
3601
+ model_name=model_name,
3602
+ function_name=function_name,
3603
+ function_tag=function_tag,
3604
+ labels=labels,
3605
+ start=start,
3606
+ end=end,
3607
+ top_level=top_level,
3608
+ uids=uids,
3609
+ latest_only=latest_only,
3610
+ )
3611
+
3388
3612
  def run_function(
3389
3613
  self,
3390
3614
  function: typing.Union[str, mlrun.runtimes.BaseRuntime],
3391
- handler: str = None,
3615
+ handler: Optional[str] = None,
3392
3616
  name: str = "",
3393
- params: dict = None,
3394
- hyperparams: dict = None,
3617
+ params: Optional[dict] = None,
3618
+ hyperparams: Optional[dict] = None,
3395
3619
  hyper_param_options: mlrun.model.HyperParamOptions = None,
3396
- inputs: dict = None,
3397
- outputs: list[str] = None,
3620
+ inputs: Optional[dict] = None,
3621
+ outputs: Optional[list[str]] = None,
3398
3622
  workdir: str = "",
3399
- labels: dict = None,
3623
+ labels: Optional[dict] = None,
3400
3624
  base_task: mlrun.model.RunTemplate = None,
3401
3625
  watch: bool = True,
3402
- local: bool = None,
3403
- verbose: bool = None,
3404
- selector: str = None,
3405
- auto_build: bool = None,
3626
+ local: Optional[bool] = None,
3627
+ verbose: Optional[bool] = None,
3628
+ selector: Optional[str] = None,
3629
+ auto_build: Optional[bool] = None,
3406
3630
  schedule: typing.Union[str, mlrun.common.schemas.ScheduleCronTrigger] = None,
3407
- artifact_path: str = None,
3408
- notifications: list[mlrun.model.Notification] = None,
3631
+ artifact_path: Optional[str] = None,
3632
+ notifications: Optional[list[mlrun.model.Notification]] = None,
3409
3633
  returns: Optional[list[Union[str, dict[str, str]]]] = None,
3410
3634
  builder_env: Optional[dict] = None,
3411
- reset_on_run: bool = None,
3635
+ reset_on_run: Optional[bool] = None,
3412
3636
  ) -> typing.Union[mlrun.model.RunObject, PipelineNodeWrapper]:
3413
3637
  """Run a local or remote task as part of a local/kubeflow pipeline
3414
3638
 
@@ -3501,18 +3725,18 @@ class MlrunProject(ModelObj):
3501
3725
  def build_function(
3502
3726
  self,
3503
3727
  function: typing.Union[str, mlrun.runtimes.BaseRuntime],
3504
- with_mlrun: bool = None,
3728
+ with_mlrun: Optional[bool] = None,
3505
3729
  skip_deployed: bool = False,
3506
- image: str = None,
3507
- base_image: str = None,
3508
- commands: list = None,
3509
- secret_name: str = None,
3510
- requirements: typing.Union[str, list[str]] = None,
3511
- mlrun_version_specifier: str = None,
3512
- builder_env: dict = None,
3730
+ image: Optional[str] = None,
3731
+ base_image: Optional[str] = None,
3732
+ commands: Optional[list] = None,
3733
+ secret_name: Optional[str] = None,
3734
+ requirements: Optional[typing.Union[str, list[str]]] = None,
3735
+ mlrun_version_specifier: Optional[str] = None,
3736
+ builder_env: Optional[dict] = None,
3513
3737
  overwrite_build_params: bool = False,
3514
- requirements_file: str = None,
3515
- extra_args: str = None,
3738
+ requirements_file: Optional[str] = None,
3739
+ extra_args: Optional[str] = None,
3516
3740
  force_build: bool = False,
3517
3741
  ) -> typing.Union[BuildStatus, PipelineNodeWrapper]:
3518
3742
  """deploy ML function, build container with its dependencies
@@ -3557,18 +3781,18 @@ class MlrunProject(ModelObj):
3557
3781
 
3558
3782
  def build_config(
3559
3783
  self,
3560
- image: str = None,
3784
+ image: Optional[str] = None,
3561
3785
  set_as_default: bool = False,
3562
- with_mlrun: bool = None,
3563
- base_image: str = None,
3564
- commands: list = None,
3565
- secret_name: str = None,
3566
- requirements: typing.Union[str, list[str]] = None,
3786
+ with_mlrun: Optional[bool] = None,
3787
+ base_image: Optional[str] = None,
3788
+ commands: Optional[list] = None,
3789
+ secret_name: Optional[str] = None,
3790
+ requirements: Optional[typing.Union[str, list[str]]] = None,
3567
3791
  overwrite_build_params: bool = False,
3568
- requirements_file: str = None,
3569
- builder_env: dict = None,
3570
- extra_args: str = None,
3571
- source_code_target_dir: str = None,
3792
+ requirements_file: Optional[str] = None,
3793
+ builder_env: Optional[dict] = None,
3794
+ extra_args: Optional[str] = None,
3795
+ source_code_target_dir: Optional[str] = None,
3572
3796
  ):
3573
3797
  """specify builder configuration for the project
3574
3798
 
@@ -3622,19 +3846,19 @@ class MlrunProject(ModelObj):
3622
3846
 
3623
3847
  def build_image(
3624
3848
  self,
3625
- image: str = None,
3849
+ image: Optional[str] = None,
3626
3850
  set_as_default: bool = True,
3627
- with_mlrun: bool = None,
3628
- base_image: str = None,
3629
- commands: list = None,
3630
- secret_name: str = None,
3631
- requirements: typing.Union[str, list[str]] = None,
3632
- mlrun_version_specifier: str = None,
3633
- builder_env: dict = None,
3851
+ with_mlrun: Optional[bool] = None,
3852
+ base_image: Optional[str] = None,
3853
+ commands: Optional[list] = None,
3854
+ secret_name: Optional[str] = None,
3855
+ requirements: Optional[typing.Union[str, list[str]]] = None,
3856
+ mlrun_version_specifier: Optional[str] = None,
3857
+ builder_env: Optional[dict] = None,
3634
3858
  overwrite_build_params: bool = False,
3635
- requirements_file: str = None,
3636
- extra_args: str = None,
3637
- target_dir: str = None,
3859
+ requirements_file: Optional[str] = None,
3860
+ extra_args: Optional[str] = None,
3861
+ target_dir: Optional[str] = None,
3638
3862
  ) -> typing.Union[BuildStatus, PipelineNodeWrapper]:
3639
3863
  """Builder docker image for the project, based on the project's build config. Parameters allow to override
3640
3864
  the build config.
@@ -3740,12 +3964,12 @@ class MlrunProject(ModelObj):
3740
3964
  def deploy_function(
3741
3965
  self,
3742
3966
  function: typing.Union[str, mlrun.runtimes.BaseRuntime],
3743
- models: list = None,
3744
- env: dict = None,
3745
- tag: str = None,
3746
- verbose: bool = None,
3747
- builder_env: dict = None,
3748
- mock: bool = None,
3967
+ models: Optional[list] = None,
3968
+ env: Optional[dict] = None,
3969
+ tag: Optional[str] = None,
3970
+ verbose: Optional[bool] = None,
3971
+ builder_env: Optional[dict] = None,
3972
+ mock: Optional[bool] = None,
3749
3973
  ) -> typing.Union[DeployStatus, PipelineNodeWrapper]:
3750
3974
  """deploy real-time (nuclio based) functions
3751
3975
 
@@ -3768,18 +3992,21 @@ class MlrunProject(ModelObj):
3768
3992
  mock=mock,
3769
3993
  )
3770
3994
 
3771
- def get_artifact(self, key, tag=None, iter=None, tree=None):
3995
+ def get_artifact(
3996
+ self, key, tag=None, iter=None, tree=None, uid=None
3997
+ ) -> typing.Optional[Artifact]:
3772
3998
  """Return an artifact object
3773
3999
 
3774
- :param key: artifact key
3775
- :param tag: version tag
3776
- :param iter: iteration number (for hyper-param tasks)
3777
- :param tree: the producer id (tree)
4000
+ :param key: Artifact key
4001
+ :param tag: Version tag
4002
+ :param iter: Iteration number (for hyper-param tasks)
4003
+ :param tree: The producer id (tree)
4004
+ :param uid: The artifact uid
3778
4005
  :return: Artifact object
3779
4006
  """
3780
4007
  db = mlrun.db.get_run_db(secrets=self._secrets)
3781
4008
  artifact = db.read_artifact(
3782
- key, tag, iter=iter, project=self.metadata.name, tree=tree
4009
+ key, tag, iter=iter, project=self.metadata.name, tree=tree, uid=uid
3783
4010
  )
3784
4011
 
3785
4012
  # in tests, if an artifact is not found, the db returns None
@@ -3792,18 +4019,28 @@ class MlrunProject(ModelObj):
3792
4019
  self,
3793
4020
  name=None,
3794
4021
  tag=None,
3795
- labels: Optional[Union[dict[str, str], list[str]]] = None,
4022
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
3796
4023
  since=None,
3797
4024
  until=None,
3798
- iter: int = None,
4025
+ iter: Optional[int] = None,
3799
4026
  best_iteration: bool = False,
3800
- kind: str = None,
4027
+ kind: Optional[str] = None,
3801
4028
  category: typing.Union[str, mlrun.common.schemas.ArtifactCategories] = None,
3802
- tree: str = None,
3803
- limit: int = None,
4029
+ tree: Optional[str] = None,
4030
+ limit: Optional[int] = None,
3804
4031
  format_: Optional[
3805
4032
  mlrun.common.formatters.ArtifactFormat
3806
4033
  ] = mlrun.common.formatters.ArtifactFormat.full,
4034
+ partition_by: Optional[
4035
+ Union[mlrun.common.schemas.ArtifactPartitionByField, str]
4036
+ ] = None,
4037
+ rows_per_partition: int = 1,
4038
+ partition_sort_by: Optional[
4039
+ Union[mlrun.common.schemas.SortField, str]
4040
+ ] = mlrun.common.schemas.SortField.updated,
4041
+ partition_order: Union[
4042
+ mlrun.common.schemas.OrderType, str
4043
+ ] = mlrun.common.schemas.OrderType.desc,
3807
4044
  ) -> mlrun.lists.ArtifactList:
3808
4045
  """List artifacts filtered by various parameters.
3809
4046
 
@@ -3813,7 +4050,7 @@ class MlrunProject(ModelObj):
3813
4050
  Examples::
3814
4051
 
3815
4052
  # Get latest version of all artifacts in project
3816
- latest_artifacts = project.list_artifacts("", tag="latest")
4053
+ latest_artifacts = project.list_artifacts(tag="latest")
3817
4054
  # check different artifact versions for a specific artifact, return as objects list
3818
4055
  result_versions = project.list_artifacts("results", tag="*").to_objects()
3819
4056
 
@@ -3821,8 +4058,13 @@ class MlrunProject(ModelObj):
3821
4058
  case-sensitive. This means that querying for ``~name`` may return artifacts named
3822
4059
  ``my_Name_1`` or ``surname``.
3823
4060
  :param tag: Return artifacts assigned this tag.
3824
- :param labels: Return artifacts that have these labels. Labels can either be a dictionary {"label": "value"} or
3825
- a list of "label=value" (match label key and value) or "label" (match just label key) strings.
4061
+ :param labels: Filter artifacts by label key-value pairs or key existence. This can be provided as:
4062
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
4063
+ or `{"label": None}` to check for key existence.
4064
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
4065
+ or just `"label"` for key existence.
4066
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
4067
+ the specified key-value pairs or key existence.
3826
4068
  :param since: Not in use in :py:class:`HTTPRunDB`.
3827
4069
  :param until: Not in use in :py:class:`HTTPRunDB`.
3828
4070
  :param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
@@ -3835,6 +4077,13 @@ class MlrunProject(ModelObj):
3835
4077
  :param tree: Return artifacts of the requested tree.
3836
4078
  :param limit: Maximum number of artifacts to return.
3837
4079
  :param format_: The format in which to return the artifacts. Default is 'full'.
4080
+ :param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
4081
+ parameter must be provided as well.
4082
+ :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
4083
+ to return per group. Default value is 1.
4084
+ :param partition_sort_by: What field to sort the results by, within each partition defined by `partition_by`.
4085
+ Currently the only allowed values are `created` and `updated`.
4086
+ :param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
3838
4087
  """
3839
4088
  db = mlrun.db.get_run_db(secrets=self._secrets)
3840
4089
  return db.list_artifacts(
@@ -3851,19 +4100,86 @@ class MlrunProject(ModelObj):
3851
4100
  tree=tree,
3852
4101
  format_=format_,
3853
4102
  limit=limit,
4103
+ partition_by=partition_by,
4104
+ rows_per_partition=rows_per_partition,
4105
+ partition_sort_by=partition_sort_by,
4106
+ partition_order=partition_order,
4107
+ )
4108
+
4109
+ def paginated_list_artifacts(
4110
+ self,
4111
+ *args,
4112
+ page: Optional[int] = None,
4113
+ page_size: Optional[int] = None,
4114
+ page_token: Optional[str] = None,
4115
+ **kwargs,
4116
+ ) -> tuple[mlrun.lists.ArtifactList, Optional[str]]:
4117
+ """List artifacts with support for pagination and various filtering options.
4118
+
4119
+ This method retrieves a paginated list of artifacts based on the specified filter parameters.
4120
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4121
+ will return a list of artifacts that match the filtering criteria provided.
4122
+
4123
+ The returned result is an `ArtifactList` (list of dict), use `.to_objects()` to convert it to a list of
4124
+ RunObjects, `.show()` to view graphically in Jupyter, and `.to_df()` to convert to a DataFrame.
4125
+
4126
+ For detailed information about the parameters, refer to the list_artifacts method:
4127
+ See :py:func:`~list_artifacts` for more details.
4128
+
4129
+ Examples::
4130
+
4131
+ # Fetch first page of artifacts with page size of 5
4132
+ artifacts, token = project.paginated_list_artifacts("results", page_size=5)
4133
+ # Fetch next page using the pagination token from the previous response
4134
+ artifacts, token = project.paginated_list_artifacts("results", page_token=token)
4135
+ # Fetch artifacts for a specific page (e.g., page 3)
4136
+ artifacts, token = project.paginated_list_artifacts(
4137
+ "results", page=3, page_size=5
4138
+ )
4139
+
4140
+ # Automatically iterate over all pages without explicitly specifying the page number
4141
+ artifacts = []
4142
+ token = None
4143
+ while True:
4144
+ page_artifacts, token = project.paginated_list_artifacts(
4145
+ page_token=token, page_size=5
4146
+ )
4147
+ artifacts.extend(page_artifacts)
4148
+
4149
+ # If token is None and page_artifacts is empty, we've reached the end (no more artifacts).
4150
+ # If token is None and page_artifacts is not empty, we've fetched the last page of artifacts.
4151
+ if not token:
4152
+ break
4153
+ print(f"Total artifacts retrieved: {len(artifacts)}")
4154
+
4155
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4156
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4157
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4158
+ for the first request.
4159
+
4160
+ :returns: A tuple containing the list of artifacts and an optional `page_token` for pagination.
4161
+ """
4162
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4163
+ return db.paginated_list_artifacts(
4164
+ *args,
4165
+ project=self.metadata.name,
4166
+ page=page,
4167
+ page_size=page_size,
4168
+ page_token=page_token,
4169
+ **kwargs,
3854
4170
  )
3855
4171
 
3856
4172
  def list_models(
3857
4173
  self,
3858
4174
  name=None,
3859
4175
  tag=None,
3860
- labels: Optional[Union[dict[str, str], list[str]]] = None,
4176
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
3861
4177
  since=None,
3862
4178
  until=None,
3863
- iter: int = None,
4179
+ iter: Optional[int] = None,
3864
4180
  best_iteration: bool = False,
3865
- tree: str = None,
3866
- limit: int = None,
4181
+ tree: Optional[str] = None,
4182
+ limit: Optional[int] = None,
3867
4183
  format_: Optional[
3868
4184
  mlrun.common.formatters.ArtifactFormat
3869
4185
  ] = mlrun.common.formatters.ArtifactFormat.full,
@@ -3873,15 +4189,20 @@ class MlrunProject(ModelObj):
3873
4189
  Examples::
3874
4190
 
3875
4191
  # Get latest version of all models in project
3876
- latest_models = project.list_models("", tag="latest")
4192
+ latest_models = project.list_models(tag="latest")
3877
4193
 
3878
4194
 
3879
4195
  :param name: Name of artifacts to retrieve. Name with '~' prefix is used as a like query, and is not
3880
4196
  case-sensitive. This means that querying for ``~name`` may return artifacts named
3881
4197
  ``my_Name_1`` or ``surname``.
3882
4198
  :param tag: Return artifacts assigned this tag.
3883
- :param labels: Return artifacts that have these labels. Labels can either be a dictionary {"label": "value"} or
3884
- a list of "label=value" (match label key and value) or "label" (match just label key) strings.
4199
+ :param labels: Filter model artifacts by label key-value pairs or key existence. This can be provided as:
4200
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
4201
+ or `{"label": None}` to check for key existence.
4202
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
4203
+ or just `"label"` for key existence.
4204
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
4205
+ the specified key-value pairs or key existence.
3885
4206
  :param since: Not in use in :py:class:`HTTPRunDB`.
3886
4207
  :param until: Not in use in :py:class:`HTTPRunDB`.
3887
4208
  :param iter: Return artifacts from a specific iteration (where ``iter=0`` means the root iteration). If
@@ -3903,13 +4224,79 @@ class MlrunProject(ModelObj):
3903
4224
  until=until,
3904
4225
  iter=iter,
3905
4226
  best_iteration=best_iteration,
3906
- kind="model",
4227
+ kind=mlrun.artifacts.model.ModelArtifact.kind,
3907
4228
  tree=tree,
3908
4229
  limit=limit,
3909
4230
  format_=format_,
3910
4231
  ).to_objects()
3911
4232
 
3912
- def list_functions(self, name=None, tag=None, labels=None):
4233
+ def paginated_list_models(
4234
+ self,
4235
+ *args,
4236
+ page: Optional[int] = None,
4237
+ page_size: Optional[int] = None,
4238
+ page_token: Optional[str] = None,
4239
+ **kwargs,
4240
+ ) -> tuple[mlrun.lists.ArtifactList, Optional[str]]:
4241
+ """List models in project with support for pagination and various filtering options.
4242
+
4243
+ This method retrieves a paginated list of artifacts based on the specified filter parameters.
4244
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4245
+ will return a list of artifacts that match the filtering criteria provided.
4246
+
4247
+ For detailed information about the parameters, refer to the list_models method:
4248
+ See :py:func:`~list_models` for more details.
4249
+
4250
+ Examples::
4251
+
4252
+ # Fetch first page of artifacts with page size of 5
4253
+ artifacts, token = project.paginated_list_models("results", page_size=5)
4254
+ # Fetch next page using the pagination token from the previous response
4255
+ artifacts, token = project.paginated_list_models("results", page_token=token)
4256
+ # Fetch artifacts for a specific page (e.g., page 3)
4257
+ artifacts, token = project.paginated_list_models("results", page=3, page_size=5)
4258
+
4259
+ # Automatically iterate over all pages without explicitly specifying the page number
4260
+ artifacts = []
4261
+ token = None
4262
+ while True:
4263
+ page_artifacts, token = project.paginated_list_models(
4264
+ page_token=token, page_size=5
4265
+ )
4266
+ artifacts.extend(page_artifacts)
4267
+
4268
+ # If token is None and page_artifacts is empty, we've reached the end (no more artifacts).
4269
+ # If token is None and page_artifacts is not empty, we've fetched the last page of artifacts.
4270
+ if not token:
4271
+ break
4272
+ print(f"Total artifacts retrieved: {len(artifacts)}")
4273
+
4274
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4275
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4276
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4277
+ for the first request.
4278
+
4279
+ :returns: A tuple containing the list of artifacts and an optional `page_token` for pagination.
4280
+ """
4281
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4282
+ return db.paginated_list_artifacts(
4283
+ *args,
4284
+ project=self.metadata.name,
4285
+ kind=mlrun.artifacts.model.ModelArtifact.kind,
4286
+ page=page,
4287
+ page_size=page_size,
4288
+ page_token=page_token,
4289
+ **kwargs,
4290
+ )
4291
+
4292
+ def list_functions(
4293
+ self,
4294
+ name: Optional[str] = None,
4295
+ tag: Optional[str] = None,
4296
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
4297
+ kind: Optional[str] = None,
4298
+ format_: Optional[str] = None,
4299
+ ):
3913
4300
  """Retrieve a list of functions, filtered by specific criteria.
3914
4301
 
3915
4302
  example::
@@ -3919,20 +4306,95 @@ class MlrunProject(ModelObj):
3919
4306
 
3920
4307
  :param name: Return only functions with a specific name.
3921
4308
  :param tag: Return function versions with specific tags. To return only tagged functions, set tag to ``"*"``.
3922
- :param labels: Return functions that have specific labels assigned to them.
4309
+ :param labels: Filter functions by label key-value pairs or key existence. This can be provided as:
4310
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
4311
+ or `{"label": None}` to check for key existence.
4312
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
4313
+ or just `"label"` for key existence.
4314
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
4315
+ the specified key-value pairs or key existence.
4316
+ :param kind: Return functions of the specified kind. If not provided, all function kinds will be returned.
4317
+ :param format_: The format in which to return the functions. Default is 'full'.
3923
4318
  :returns: List of function objects.
3924
4319
  """
3925
4320
  db = mlrun.db.get_run_db(secrets=self._secrets)
3926
- functions = db.list_functions(name, self.metadata.name, tag=tag, labels=labels)
4321
+ functions = db.list_functions(
4322
+ name,
4323
+ project=self.metadata.name,
4324
+ tag=tag,
4325
+ kind=kind,
4326
+ labels=labels,
4327
+ format_=format_,
4328
+ )
3927
4329
  if functions:
3928
4330
  # convert dict to function objects
3929
4331
  return [mlrun.new_function(runtime=func) for func in functions]
3930
4332
 
4333
+ def paginated_list_functions(
4334
+ self,
4335
+ *args,
4336
+ page: Optional[int] = None,
4337
+ page_size: Optional[int] = None,
4338
+ page_token: Optional[str] = None,
4339
+ **kwargs,
4340
+ ) -> tuple[list, Optional[str]]:
4341
+ """List functions with support for pagination and various filtering options.
4342
+
4343
+ This method retrieves a paginated list of functions based on the specified filter parameters.
4344
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4345
+ will return a list of functions that match the filtering criteria provided.
4346
+
4347
+ For detailed information about the parameters, refer to the list_functions method:
4348
+ See :py:func:`~list_functions` for more details.
4349
+
4350
+ Examples::
4351
+
4352
+ # Fetch first page of functions with page size of 5
4353
+ functions, token = project.paginated_list_functions(page_size=5)
4354
+ # Fetch next page using the pagination token from the previous response
4355
+ functions, token = project.paginated_list_functions(page_token=token)
4356
+ # Fetch functions for a specific page (e.g., page 3)
4357
+ functions, token = project.paginated_list_functions(page=3, page_size=5)
4358
+
4359
+ # Automatically iterate over all pages without explicitly specifying the page number
4360
+ functions = []
4361
+ token = None
4362
+ while True:
4363
+ page_functions, token = project.paginated_list_functions(
4364
+ page_token=token, page_size=5
4365
+ )
4366
+ functions.extend(page_functions)
4367
+
4368
+ # If token is None and page_functions is empty, we've reached the end (no more functions).
4369
+ # If token is None and page_functions is not empty, we've fetched the last page of functions.
4370
+ if not token:
4371
+ break
4372
+ print(f"Total functions retrieved: {len(functions)}")
4373
+
4374
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4375
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4376
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4377
+ for the first request.
4378
+
4379
+ :returns: A tuple containing the list of functions and an optional `page_token` for pagination.
4380
+ """
4381
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4382
+ functions, token = db.paginated_list_functions(
4383
+ *args,
4384
+ project=self.metadata.name,
4385
+ page=page,
4386
+ page_size=page_size,
4387
+ page_token=page_token,
4388
+ **kwargs,
4389
+ )
4390
+ # convert dict to function objects
4391
+ return [mlrun.new_function(runtime=func) for func in functions], token
4392
+
3931
4393
  def list_model_monitoring_functions(
3932
4394
  self,
3933
4395
  name: Optional[str] = None,
3934
4396
  tag: Optional[str] = None,
3935
- labels: Optional[list[str]] = None,
4397
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
3936
4398
  ) -> Optional[list]:
3937
4399
  """
3938
4400
  Retrieve a list of all the model monitoring functions.
@@ -3942,8 +4404,13 @@ class MlrunProject(ModelObj):
3942
4404
 
3943
4405
  :param name: Return only functions with a specific name.
3944
4406
  :param tag: Return function versions with specific tags.
3945
- :param labels: Return functions that have specific labels assigned to them.
3946
-
4407
+ :param labels: Filter functions by label key-value pairs or key existence. This can be provided as:
4408
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
4409
+ or `{"label": None}` to check for key existence.
4410
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
4411
+ or just `"label"` for key existence.
4412
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
4413
+ the specified key-value pairs or key existence.
3947
4414
  :returns: List of function objects.
3948
4415
  """
3949
4416
 
@@ -3960,7 +4427,7 @@ class MlrunProject(ModelObj):
3960
4427
  self,
3961
4428
  name: Optional[str] = None,
3962
4429
  uid: Optional[Union[str, list[str]]] = None,
3963
- labels: Optional[Union[str, list[str]]] = None,
4430
+ labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
3964
4431
  state: Optional[
3965
4432
  mlrun.common.runtimes.constants.RunStates
3966
4433
  ] = None, # Backward compatibility
@@ -3995,9 +4462,13 @@ class MlrunProject(ModelObj):
3995
4462
 
3996
4463
  :param name: Name of the run to retrieve.
3997
4464
  :param uid: Unique ID of the run.
3998
- :param labels: A list of labels to filter by. Label filters work by either filtering a specific value
3999
- of a label (i.e. list("key=value")) or by looking for the existence of a given
4000
- key (i.e. "key").
4465
+ :param labels: Filter runs by label key-value pairs or key existence. This can be provided as:
4466
+ - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
4467
+ or `{"label": None}` to check for key existence.
4468
+ - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
4469
+ or just `"label"` for key existence.
4470
+ - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
4471
+ the specified key-value pairs or key existence.
4001
4472
  :param state: Deprecated - List only runs whose state is specified.
4002
4473
  :param states: List only runs whose state is one of the provided states.
4003
4474
  :param sort: Whether to sort the result according to their start time. Otherwise, results will be
@@ -4023,9 +4494,11 @@ class MlrunProject(ModelObj):
4023
4494
  uid,
4024
4495
  self.metadata.name,
4025
4496
  labels=labels,
4026
- states=mlrun.utils.helpers.as_list(state)
4027
- if state is not None
4028
- else states or None,
4497
+ states=(
4498
+ mlrun.utils.helpers.as_list(state)
4499
+ if state is not None
4500
+ else states or None
4501
+ ),
4029
4502
  sort=sort,
4030
4503
  last=last,
4031
4504
  iter=iter,
@@ -4036,6 +4509,68 @@ class MlrunProject(ModelObj):
4036
4509
  **kwargs,
4037
4510
  )
4038
4511
 
4512
+ def paginated_list_runs(
4513
+ self,
4514
+ *args,
4515
+ page: Optional[int] = None,
4516
+ page_size: Optional[int] = None,
4517
+ page_token: Optional[str] = None,
4518
+ **kwargs,
4519
+ ) -> tuple[mlrun.lists.RunList, Optional[str]]:
4520
+ """List runs with support for pagination and various filtering options.
4521
+
4522
+ This method retrieves a paginated list of runs based on the specified filter parameters.
4523
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4524
+ will return a list of runs that match the filtering criteria provided.
4525
+
4526
+ The returned result is a `` (list of dict), use `.to_objects()` to convert it to a list of RunObjects,
4527
+ `.show()` to view graphically in Jupyter, `.to_df()` to convert to a DataFrame, and `compare()` to
4528
+ generate comparison table and PCP plot.
4529
+
4530
+ For detailed information about the parameters, refer to the list_runs method:
4531
+ See :py:func:`~list_runs` for more details.
4532
+
4533
+ Examples::
4534
+
4535
+ # Fetch first page of runs with page size of 5
4536
+ runs, token = project.paginated_list_runs(page_size=5)
4537
+ # Fetch next page using the pagination token from the previous response
4538
+ runs, token = project.paginated_list_runs(page_token=token)
4539
+ # Fetch runs for a specific page (e.g., page 3)
4540
+ runs, token = project.paginated_list_runs(page=3, page_size=5)
4541
+
4542
+ # Automatically iterate over all pages without explicitly specifying the page number
4543
+ runs = []
4544
+ token = None
4545
+ while True:
4546
+ page_runs, token = project.paginated_list_runs(
4547
+ page_token=token, page_size=5
4548
+ )
4549
+ runs.extend(page_runs)
4550
+
4551
+ # If token is None and page_runs is empty, we've reached the end (no more runs).
4552
+ # If token is None and page_runs is not empty, we've fetched the last page of runs.
4553
+ if not token:
4554
+ break
4555
+ print(f"Total runs retrieved: {len(runs)}")
4556
+
4557
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4558
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4559
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4560
+ for the first request.
4561
+
4562
+ :returns: A tuple containing the list of runs and an optional `page_token` for pagination.
4563
+ """
4564
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4565
+ return db.paginated_list_runs(
4566
+ *args,
4567
+ project=self.metadata.name,
4568
+ page=page,
4569
+ page_size=page_size,
4570
+ page_token=page_token,
4571
+ **kwargs,
4572
+ )
4573
+
4039
4574
  def register_datastore_profile(self, profile: DatastoreProfile):
4040
4575
  private_body = DatastoreProfile2Json.get_json_private(profile)
4041
4576
  public_body = DatastoreProfile2Json.get_json_public(profile)
@@ -4051,6 +4586,25 @@ class MlrunProject(ModelObj):
4051
4586
  profile, self.name
4052
4587
  )
4053
4588
 
4589
+ def get_config_profile_attributes(self, name: str) -> dict:
4590
+ """
4591
+ Get the merged attributes from a named configuration profile.
4592
+
4593
+ Retrieves a profile from the datastore using the provided name and returns its
4594
+ merged public and private attributes as a dictionary.
4595
+
4596
+ Args:
4597
+ name (str): Name of the configuration profile to retrieve. Will be prefixed
4598
+ with "ds://" to form the full profile path.
4599
+
4600
+ Returns:
4601
+ dict: The merged attributes dictionary containing both public and private
4602
+ configuration settings from the profile. Returns nested dictionaries if
4603
+ the profile contains nested configurations.
4604
+ """
4605
+ profile = datastore_profile_read(f"ds://{name}", self.name)
4606
+ return profile.attributes()
4607
+
4054
4608
  def delete_datastore_profile(self, profile: str):
4055
4609
  mlrun.db.get_run_db(secrets=self._secrets).delete_datastore_profile(
4056
4610
  profile, self.name
@@ -4188,13 +4742,17 @@ class MlrunProject(ModelObj):
4188
4742
  mlrun.db.get_run_db().delete_api_gateway(name=name, project=self.name)
4189
4743
 
4190
4744
  def store_alert_config(
4191
- self, alert_data: AlertConfig, alert_name: typing.Optional[str] = None
4745
+ self,
4746
+ alert_data: AlertConfig,
4747
+ alert_name: typing.Optional[str] = None,
4748
+ force_reset: bool = False,
4192
4749
  ) -> AlertConfig:
4193
4750
  """
4194
4751
  Create/modify an alert.
4195
4752
 
4196
4753
  :param alert_data: The data of the alert.
4197
4754
  :param alert_name: The name of the alert.
4755
+ :param force_reset: If True and the alert already exists, the alert would be reset.
4198
4756
  :return: the created/modified alert.
4199
4757
  """
4200
4758
  if not alert_data:
@@ -4208,7 +4766,9 @@ class MlrunProject(ModelObj):
4208
4766
  project=alert_data.project,
4209
4767
  )
4210
4768
  alert_data.project = self.metadata.name
4211
- return db.store_alert_config(alert_name, alert_data, project=self.metadata.name)
4769
+ return db.store_alert_config(
4770
+ alert_name, alert_data, project=self.metadata.name, force_reset=force_reset
4771
+ )
4212
4772
 
4213
4773
  def get_alert_config(self, alert_name: str) -> AlertConfig:
4214
4774
  """
@@ -4230,7 +4790,7 @@ class MlrunProject(ModelObj):
4230
4790
  return db.list_alerts_configs(self.metadata.name)
4231
4791
 
4232
4792
  def delete_alert_config(
4233
- self, alert_data: AlertConfig = None, alert_name: str = None
4793
+ self, alert_data: AlertConfig = None, alert_name: Optional[str] = None
4234
4794
  ):
4235
4795
  """
4236
4796
  Delete an alert.
@@ -4250,7 +4810,7 @@ class MlrunProject(ModelObj):
4250
4810
  db.delete_alert_config(alert_name, self.metadata.name)
4251
4811
 
4252
4812
  def reset_alert_config(
4253
- self, alert_data: AlertConfig = None, alert_name: str = None
4813
+ self, alert_data: AlertConfig = None, alert_name: Optional[str] = None
4254
4814
  ):
4255
4815
  """
4256
4816
  Reset an alert.
@@ -4269,7 +4829,9 @@ class MlrunProject(ModelObj):
4269
4829
  alert_name = alert_data.name
4270
4830
  db.reset_alert_config(alert_name, self.metadata.name)
4271
4831
 
4272
- def get_alert_template(self, template_name: str) -> AlertTemplate:
4832
+ def get_alert_template(
4833
+ self, template_name: str
4834
+ ) -> mlrun.common.schemas.alert.AlertTemplate:
4273
4835
  """
4274
4836
  Retrieve a specific alert template.
4275
4837
 
@@ -4279,7 +4841,7 @@ class MlrunProject(ModelObj):
4279
4841
  db = mlrun.db.get_run_db(secrets=self._secrets)
4280
4842
  return db.get_alert_template(template_name)
4281
4843
 
4282
- def list_alert_templates(self) -> list[AlertTemplate]:
4844
+ def list_alert_templates(self) -> list[mlrun.common.schemas.alert.AlertTemplate]:
4283
4845
  """
4284
4846
  Retrieve list of all alert templates.
4285
4847
 
@@ -4288,12 +4850,114 @@ class MlrunProject(ModelObj):
4288
4850
  db = mlrun.db.get_run_db(secrets=self._secrets)
4289
4851
  return db.list_alert_templates()
4290
4852
 
4853
+ def list_alert_activations(
4854
+ self,
4855
+ name: Optional[str] = None,
4856
+ since: Optional[datetime.datetime] = None,
4857
+ until: Optional[datetime.datetime] = None,
4858
+ entity: Optional[str] = None,
4859
+ severity: Optional[
4860
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
4861
+ ] = None,
4862
+ entity_kind: Optional[
4863
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
4864
+ ] = None,
4865
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
4866
+ ) -> list[mlrun.common.schemas.alert.AlertActivation]:
4867
+ """
4868
+ Retrieve a list of alert activations for a project.
4869
+
4870
+ :param name: The alert name to filter by. Supports exact matching or partial matching if prefixed with `~`.
4871
+ :param since: Filters for alert activations occurring after this timestamp.
4872
+ :param until: Filters for alert activations occurring before this timestamp.
4873
+ :param entity: The entity ID to filter by. Supports wildcard matching if prefixed with `~`.
4874
+ :param severity: A list of severity levels to filter by (e.g., ["high", "low"]).
4875
+ :param entity_kind: The kind of entity (e.g., "job", "endpoint") to filter by.
4876
+ :param event_kind: The kind of event (e.g., ""data-drift-detected"", "failed") to filter by.
4877
+
4878
+ :returns: A list of alert activations matching the provided filters.
4879
+ """
4880
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4881
+ return db.list_alert_activations(
4882
+ project=self.metadata.name,
4883
+ name=name,
4884
+ since=since,
4885
+ until=until,
4886
+ entity=entity,
4887
+ severity=severity,
4888
+ entity_kind=entity_kind,
4889
+ event_kind=event_kind,
4890
+ )
4891
+
4892
+ def paginated_list_alert_activations(
4893
+ self,
4894
+ *args,
4895
+ page: Optional[int] = None,
4896
+ page_size: Optional[int] = None,
4897
+ page_token: Optional[str] = None,
4898
+ **kwargs,
4899
+ ) -> tuple[mlrun.common.schemas.alert.AlertActivation, Optional[str]]:
4900
+ """
4901
+ List alerts activations with support for pagination and various filtering options.
4902
+
4903
+ This method retrieves a paginated list of alert activations based on the specified filter parameters.
4904
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4905
+ will return a list of alert activations that match the filtering criteria provided.
4906
+
4907
+ For detailed information about the parameters, refer to the list_alert_activations method:
4908
+ See :py:func:`~list_alert_activations` for more details.
4909
+
4910
+ Examples::
4911
+
4912
+ # Fetch first page of alert activations with page size of 5
4913
+ alert_activations, token = project.paginated_list_alert_activations(page_size=5)
4914
+ # Fetch next page using the pagination token from the previous response
4915
+ alert_activations, token = project.paginated_list_alert_activations(
4916
+ page_token=token
4917
+ )
4918
+ # Fetch alert activations for a specific page (e.g., page 3)
4919
+ alert_activations, token = project.paginated_list_alert_activations(
4920
+ page=3, page_size=5
4921
+ )
4922
+
4923
+ # Automatically iterate over all pages without explicitly specifying the page number
4924
+ alert_activations = []
4925
+ token = None
4926
+ while True:
4927
+ page_alert_activations, token = project.paginated_list_alert_activations(
4928
+ page_token=token, page_size=5
4929
+ )
4930
+ alert_activations.extend(page_alert_activations)
4931
+
4932
+ # If token is None and page_alert_activations is empty, we've reached the end (no more activations).
4933
+ # If token is None and page_alert_activations is not empty, we've fetched the last page of activations.
4934
+ if not token:
4935
+ break
4936
+ print(f"Total alert activations retrieved: {len(alert_activations)}")
4937
+
4938
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4939
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4940
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4941
+ for the first request.
4942
+
4943
+ :returns: A tuple containing the list of alert activations and an optional `page_token` for pagination.
4944
+ """
4945
+ db = mlrun.db.get_run_db(secrets=self._secrets)
4946
+ return db.paginated_list_alert_activations(
4947
+ *args,
4948
+ project=self.metadata.name,
4949
+ page=page,
4950
+ page_size=page_size,
4951
+ page_token=page_token,
4952
+ **kwargs,
4953
+ )
4954
+
4291
4955
  def _run_authenticated_git_action(
4292
4956
  self,
4293
4957
  action: Callable,
4294
4958
  remote: str,
4295
- args: list = None,
4296
- kwargs: dict = None,
4959
+ args: Optional[list] = None,
4960
+ kwargs: Optional[dict] = None,
4297
4961
  secrets: Union[SecretsStore, dict] = None,
4298
4962
  ):
4299
4963
  """Run an arbitrary Git routine while the remote is enriched with secrets
@@ -4370,7 +5034,7 @@ class MlrunProject(ModelObj):
4370
5034
  def _resolve_artifact_producer(
4371
5035
  self,
4372
5036
  artifact: typing.Union[str, Artifact],
4373
- project_producer_tag: str = None,
5037
+ project_producer_tag: Optional[str] = None,
4374
5038
  ) -> tuple[ArtifactProducer, bool]:
4375
5039
  """
4376
5040
  Resolve the artifact producer of the given artifact.
@@ -4400,28 +5064,34 @@ class MlrunProject(ModelObj):
4400
5064
  )
4401
5065
 
4402
5066
  if producer_dict.get("kind", "") == "run":
4403
- return ArtifactProducer(
4404
- name=producer_dict.get("name", ""),
4405
- kind=producer_dict.get("kind", ""),
4406
- project=producer_project,
4407
- tag=producer_tag,
4408
- owner=producer_dict.get("owner", ""),
4409
- ), True
5067
+ return (
5068
+ ArtifactProducer(
5069
+ name=producer_dict.get("name", ""),
5070
+ kind=producer_dict.get("kind", ""),
5071
+ project=producer_project,
5072
+ tag=producer_tag,
5073
+ owner=producer_dict.get("owner", ""),
5074
+ ),
5075
+ True,
5076
+ )
4410
5077
 
4411
5078
  # do not retain the artifact's producer, replace it with the project as the producer
4412
5079
  project_producer_tag = project_producer_tag or self._get_project_tag()
4413
- return ArtifactProducer(
4414
- kind="project",
4415
- name=self.metadata.name,
4416
- project=self.metadata.name,
4417
- tag=project_producer_tag,
4418
- owner=self._resolve_artifact_owner(),
4419
- ), False
5080
+ return (
5081
+ ArtifactProducer(
5082
+ kind="project",
5083
+ name=self.metadata.name,
5084
+ project=self.metadata.name,
5085
+ tag=project_producer_tag,
5086
+ owner=self._resolve_artifact_owner(),
5087
+ ),
5088
+ False,
5089
+ )
4420
5090
 
4421
5091
  def _resolve_existing_artifact(
4422
5092
  self,
4423
5093
  item: typing.Union[str, Artifact],
4424
- tag: str = None,
5094
+ tag: Optional[str] = None,
4425
5095
  ) -> typing.Optional[Artifact]:
4426
5096
  """
4427
5097
  Check if there is and existing artifact with the given item and tag.