mlrun 1.8.0rc4__py3-none-any.whl → 1.8.0rc7__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 (75) hide show
  1. mlrun/__init__.py +5 -3
  2. mlrun/alerts/alert.py +129 -2
  3. mlrun/artifacts/__init__.py +1 -1
  4. mlrun/artifacts/base.py +12 -1
  5. mlrun/artifacts/document.py +59 -38
  6. mlrun/common/constants.py +1 -0
  7. mlrun/common/model_monitoring/__init__.py +0 -2
  8. mlrun/common/model_monitoring/helpers.py +0 -28
  9. mlrun/common/schemas/__init__.py +2 -4
  10. mlrun/common/schemas/alert.py +80 -1
  11. mlrun/common/schemas/artifact.py +4 -0
  12. mlrun/common/schemas/client_spec.py +0 -1
  13. mlrun/common/schemas/model_monitoring/__init__.py +0 -6
  14. mlrun/common/schemas/model_monitoring/constants.py +11 -9
  15. mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
  16. mlrun/common/schemas/notification.py +6 -0
  17. mlrun/common/schemas/project.py +3 -0
  18. mlrun/config.py +2 -3
  19. mlrun/datastore/datastore_profile.py +57 -17
  20. mlrun/datastore/sources.py +1 -2
  21. mlrun/datastore/vectorstore.py +67 -59
  22. mlrun/db/base.py +29 -19
  23. mlrun/db/factory.py +0 -3
  24. mlrun/db/httpdb.py +224 -161
  25. mlrun/db/nopdb.py +36 -17
  26. mlrun/execution.py +46 -32
  27. mlrun/feature_store/api.py +1 -0
  28. mlrun/model.py +7 -0
  29. mlrun/model_monitoring/__init__.py +3 -2
  30. mlrun/model_monitoring/api.py +55 -53
  31. mlrun/model_monitoring/applications/_application_steps.py +4 -2
  32. mlrun/model_monitoring/applications/base.py +165 -6
  33. mlrun/model_monitoring/applications/context.py +88 -37
  34. mlrun/model_monitoring/applications/evidently_base.py +0 -1
  35. mlrun/model_monitoring/applications/histogram_data_drift.py +3 -7
  36. mlrun/model_monitoring/controller.py +43 -37
  37. mlrun/model_monitoring/db/__init__.py +0 -2
  38. mlrun/model_monitoring/db/tsdb/base.py +2 -1
  39. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
  40. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
  41. mlrun/model_monitoring/helpers.py +79 -66
  42. mlrun/model_monitoring/stream_processing.py +83 -270
  43. mlrun/model_monitoring/writer.py +1 -10
  44. mlrun/projects/pipelines.py +37 -1
  45. mlrun/projects/project.py +171 -74
  46. mlrun/run.py +40 -0
  47. mlrun/runtimes/nuclio/function.py +7 -6
  48. mlrun/runtimes/nuclio/serving.py +9 -2
  49. mlrun/serving/routers.py +158 -145
  50. mlrun/serving/server.py +6 -0
  51. mlrun/serving/states.py +21 -7
  52. mlrun/serving/v2_serving.py +70 -61
  53. mlrun/utils/helpers.py +14 -30
  54. mlrun/utils/notifications/notification/mail.py +36 -9
  55. mlrun/utils/notifications/notification_pusher.py +43 -18
  56. mlrun/utils/version/version.json +2 -2
  57. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/METADATA +5 -4
  58. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/RECORD +62 -75
  59. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
  60. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  61. mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
  62. mlrun/model_monitoring/db/stores/base/store.py +0 -154
  63. mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
  64. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
  65. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
  66. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
  67. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
  68. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
  69. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
  70. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
  71. mlrun/model_monitoring/model_endpoint.py +0 -120
  72. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/LICENSE +0 -0
  73. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/WHEEL +0 -0
  74. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/entry_points.txt +0 -0
  75. {mlrun-1.8.0rc4.dist-info → mlrun-1.8.0rc7.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import inspect
16
- from importlib import import_module
16
+ from collections.abc import Iterable
17
17
  from typing import Union
18
18
 
19
19
  from mlrun.artifacts import DocumentArtifact
@@ -21,57 +21,27 @@ from mlrun.artifacts import DocumentArtifact
21
21
 
22
22
  class VectorStoreCollection:
23
23
  """
24
- VectorStoreCollection is a class that manages a collection of vector stores, providing methods to add and delete
25
- documents and artifacts, and to interact with an MLRun context.
26
-
27
- Attributes:
28
- _collection_impl (object): The underlying collection implementation.
29
- _mlrun_context (Union[MlrunProject, MLClientCtx]): The MLRun context associated with the collection.
30
- collection_name (str): The name of the collection.
31
- id (str): The unique identifier of the collection, composed of the datastore profile and collection name.
32
-
33
- Methods:
34
- add_documents(documents: list["Document"], **kwargs):
35
- Adds a list of documents to the collection and updates the MLRun artifacts associated with the documents
36
- if an MLRun context is present.
37
-
38
- add_artifacts(artifacts: list[DocumentArtifact], splitter=None, **kwargs):
39
- Adds a list of DocumentArtifact objects to the collection, optionally using a splitter to convert
40
- artifacts to documents.
41
-
42
- remove_itself_from_artifact(artifact: DocumentArtifact):
43
- Removes the current object from the given artifact's collection and updates the artifact.
44
-
45
- delete_artifacts(artifacts: list[DocumentArtifact]):
46
- Deletes a list of DocumentArtifact objects from the collection and updates the MLRun context.
47
- Raises NotImplementedError if the delete operation is not supported for the collection implementation.
24
+ A wrapper class for vector store collections with MLRun integration.
25
+
26
+ This class wraps a vector store implementation (like Milvus, Chroma) and provides
27
+ integration with MLRun context for document and artifact management. It delegates
28
+ most operations to the underlying vector store while handling MLRun-specific
29
+ functionality.
30
+
31
+ The class implements attribute delegation through __getattr__ and __setattr__,
32
+ allowing direct access to the underlying vector store's methods and attributes
33
+ while maintaining MLRun integration.
48
34
  """
49
35
 
50
36
  def __init__(
51
37
  self,
52
- vector_store_class: str,
53
38
  mlrun_context: Union["MlrunProject", "MLClientCtx"], # noqa: F821
54
- datastore_profile: str,
55
39
  collection_name: str,
56
- **kwargs,
40
+ vector_store: "VectorStore", # noqa: F821
57
41
  ):
58
- # Import the vector store class dynamically
59
- module_name, class_name = vector_store_class.rsplit(".", 1)
60
- module = import_module(module_name)
61
- vector_store_class = getattr(module, class_name)
62
-
63
- signature = inspect.signature(vector_store_class)
64
-
65
- # Create the vector store instance
66
- if "collection_name" in signature.parameters.keys():
67
- vector_store = vector_store_class(collection_name=collection_name, **kwargs)
68
- else:
69
- vector_store = vector_store_class(**kwargs)
70
-
71
42
  self._collection_impl = vector_store
72
43
  self._mlrun_context = mlrun_context
73
44
  self.collection_name = collection_name
74
- self.id = datastore_profile + "/" + collection_name
75
45
 
76
46
  def __getattr__(self, name):
77
47
  # This method is called when an attribute is not found in the usual places
@@ -112,40 +82,74 @@ class VectorStoreCollection:
112
82
  )
113
83
  if mlrun_uri:
114
84
  artifact = self._mlrun_context.get_store_resource(mlrun_uri)
115
- artifact.collection_add(self.id)
85
+ artifact.collection_add(self.collection_name)
116
86
  self._mlrun_context.update_artifact(artifact)
87
+
117
88
  return self._collection_impl.add_documents(documents, **kwargs)
118
89
 
119
90
  def add_artifacts(self, artifacts: list[DocumentArtifact], splitter=None, **kwargs):
120
91
  """
121
- Add a list of DocumentArtifact objects to the collection.
92
+ Add a list of DocumentArtifact objects to the vector store collection.
93
+
94
+ Converts artifacts to LangChain documents, adds them to the vector store, and
95
+ updates the MLRun context. If documents are split, the IDs are handled appropriately.
122
96
 
123
97
  Args:
124
- artifacts (list[DocumentArtifact]): A list of DocumentArtifact objects to be added.
125
- splitter (optional): An optional splitter to be used when converting artifacts to documents.
126
- **kwargs: Additional keyword arguments to be passed to the collection's add_documents method.
98
+ artifacts (list[DocumentArtifact]): List of DocumentArtifact objects to add
99
+ splitter (optional): Document splitter to break artifacts into smaller chunks.
100
+ If None, each artifact becomes a single document.
101
+ **kwargs: Additional arguments passed to the underlying add_documents method.
102
+ Special handling for 'ids' kwarg:
103
+ - If provided and document is split, IDs are generated as "{original_id}_{i}"
104
+ where i starts from 1 (e.g., "doc1_1", "doc1_2", etc.)
105
+ - If provided and document isn't split, original IDs are used as-is
127
106
 
128
107
  Returns:
129
- list: A list of IDs of the added documents.
108
+ list: List of IDs for all added documents. When no custom IDs are provided:
109
+ - Without splitting: Vector store generates IDs automatically
110
+ - With splitting: Vector store generates separate IDs for each chunk
111
+ When custom IDs are provided:
112
+ - Without splitting: Uses provided IDs directly
113
+ - With splitting: Generates sequential IDs as "{original_id}_{i}" for each chunk
130
114
  """
131
115
  all_ids = []
132
- for artifact in artifacts:
116
+ user_ids = kwargs.pop("ids", None)
117
+
118
+ if user_ids:
119
+ if not isinstance(user_ids, Iterable):
120
+ raise ValueError("IDs must be an iterable collection")
121
+ if len(user_ids) != len(artifacts):
122
+ raise ValueError(
123
+ "The number of IDs should match the number of artifacts"
124
+ )
125
+ for index, artifact in enumerate(artifacts):
133
126
  documents = artifact.to_langchain_documents(splitter)
134
- artifact.collection_add(self.id)
135
- self._mlrun_context.update_artifact(artifact)
127
+ artifact.collection_add(self.collection_name)
128
+ if self._mlrun_context:
129
+ self._mlrun_context.update_artifact(artifact)
130
+ if user_ids:
131
+ num_of_documents = len(documents)
132
+ if num_of_documents > 1:
133
+ ids_to_pass = [
134
+ f"{user_ids[index]}_{i}" for i in range(1, num_of_documents + 1)
135
+ ]
136
+ else:
137
+ ids_to_pass = [user_ids[index]]
138
+ kwargs["ids"] = ids_to_pass
136
139
  ids = self._collection_impl.add_documents(documents, **kwargs)
137
140
  all_ids.extend(ids)
138
141
  return all_ids
139
142
 
140
- def remove_itself_from_artifact(self, artifact: DocumentArtifact):
143
+ def remove_from_artifact(self, artifact: DocumentArtifact):
141
144
  """
142
145
  Remove the current object from the given artifact's collection and update the artifact.
143
146
 
144
147
  Args:
145
148
  artifact (DocumentArtifact): The artifact from which the current object should be removed.
146
149
  """
147
- artifact.collection_remove(self.id)
148
- self._mlrun_context.update_artifact(artifact)
150
+ artifact.collection_remove(self.collection_name)
151
+ if self._mlrun_context:
152
+ self._mlrun_context.update_artifact(artifact)
149
153
 
150
154
  def delete_artifacts(self, artifacts: list[DocumentArtifact]):
151
155
  """
@@ -162,13 +166,15 @@ class VectorStoreCollection:
162
166
  """
163
167
  store_class = self._collection_impl.__class__.__name__.lower()
164
168
  for artifact in artifacts:
165
- artifact.collection_remove(self.id)
166
- self._mlrun_context.update_artifact(artifact)
169
+ artifact.collection_remove(self.collection_name)
170
+ if self._mlrun_context:
171
+ self._mlrun_context.update_artifact(artifact)
172
+
167
173
  if store_class == "milvus":
168
- expr = f"{DocumentArtifact.METADATA_SOURCE_KEY} == '{artifact.source}'"
174
+ expr = f"{DocumentArtifact.METADATA_SOURCE_KEY} == '{artifact.get_source()}'"
169
175
  return self._collection_impl.delete(expr=expr)
170
176
  elif store_class == "chroma":
171
- where = {DocumentArtifact.METADATA_SOURCE_KEY: artifact.source}
177
+ where = {DocumentArtifact.METADATA_SOURCE_KEY: artifact.get_source()}
172
178
  return self._collection_impl.delete(where=where)
173
179
 
174
180
  elif (
@@ -177,7 +183,9 @@ class VectorStoreCollection:
177
183
  in inspect.signature(self._collection_impl.delete).parameters
178
184
  ):
179
185
  filter = {
180
- "metadata": {DocumentArtifact.METADATA_SOURCE_KEY: artifact.source}
186
+ "metadata": {
187
+ DocumentArtifact.METADATA_SOURCE_KEY: artifact.get_source()
188
+ }
181
189
  }
182
190
  return self._collection_impl.delete(filter=filter)
183
191
  else:
mlrun/db/base.py CHANGED
@@ -370,7 +370,9 @@ class RunDBInterface(ABC):
370
370
  pass
371
371
 
372
372
  @abstractmethod
373
- def get_project(self, name: str) -> mlrun.common.schemas.Project:
373
+ def get_project(
374
+ self, name: str
375
+ ) -> Union[mlrun.common.schemas.Project, "mlrun.MlrunProject"]:
374
376
  pass
375
377
 
376
378
  @abstractmethod
@@ -663,16 +665,16 @@ class RunDBInterface(ABC):
663
665
  @abstractmethod
664
666
  def create_model_endpoint(
665
667
  self,
666
- project: str,
667
- endpoint_id: str,
668
- model_endpoint: Union[mlrun.model_monitoring.ModelEndpoint, dict],
669
- ):
668
+ model_endpoint: mlrun.common.schemas.ModelEndpoint,
669
+ ) -> mlrun.common.schemas.ModelEndpoint:
670
670
  pass
671
671
 
672
672
  @abstractmethod
673
673
  def delete_model_endpoint(
674
674
  self,
675
+ name: str,
675
676
  project: str,
677
+ function_name: str,
676
678
  endpoint_id: str,
677
679
  ):
678
680
  pass
@@ -681,36 +683,40 @@ class RunDBInterface(ABC):
681
683
  def list_model_endpoints(
682
684
  self,
683
685
  project: str,
684
- model: Optional[str] = None,
685
- function: Optional[str] = None,
686
+ name: Optional[str] = None,
687
+ function_name: Optional[str] = None,
688
+ model_name: Optional[str] = None,
686
689
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
687
- start: str = "now-1h",
688
- end: str = "now",
689
- metrics: Optional[list[str]] = None,
690
+ start: Optional[datetime.datetime] = None,
691
+ end: Optional[datetime.datetime] = None,
692
+ tsdb_metrics: bool = True,
690
693
  top_level: bool = False,
691
694
  uids: Optional[list[str]] = None,
692
- ) -> list[mlrun.model_monitoring.model_endpoint.ModelEndpoint]:
695
+ latest_only: bool = False,
696
+ ) -> mlrun.common.schemas.ModelEndpointList:
693
697
  pass
694
698
 
695
699
  @abstractmethod
696
700
  def get_model_endpoint(
697
701
  self,
702
+ name: str,
698
703
  project: str,
699
- endpoint_id: str,
700
- start: Optional[str] = None,
701
- end: Optional[str] = None,
702
- metrics: Optional[list[str]] = None,
703
- features: bool = False,
704
- ) -> mlrun.model_monitoring.ModelEndpoint:
704
+ function_name: Optional[str] = None,
705
+ endpoint_id: Optional[str] = None,
706
+ tsdb_metrics: bool = True,
707
+ feature_analysis: bool = False,
708
+ ) -> mlrun.common.schemas.ModelEndpoint:
705
709
  pass
706
710
 
707
711
  @abstractmethod
708
712
  def patch_model_endpoint(
709
713
  self,
714
+ name: str,
710
715
  project: str,
711
- endpoint_id: str,
712
716
  attributes: dict,
713
- ):
717
+ function_name: Optional[str] = None,
718
+ endpoint_id: Optional[str] = None,
719
+ ) -> mlrun.common.schemas.ModelEndpoint:
714
720
  pass
715
721
 
716
722
  @abstractmethod
@@ -1051,3 +1057,7 @@ class RunDBInterface(ABC):
1051
1057
  replace_creds: bool,
1052
1058
  ) -> None:
1053
1059
  pass
1060
+
1061
+ @abstractmethod
1062
+ def get_project_summary(self, project: str) -> mlrun.common.schemas.ProjectSummary:
1063
+ pass
mlrun/db/factory.py CHANGED
@@ -54,9 +54,6 @@ class RunDBFactory(
54
54
  self._run_db = self._rundb_container.nop(url)
55
55
 
56
56
  else:
57
- # TODO: this practically makes the SQLRunDB a singleton, which mean that its session is shared, needs
58
- # to be refreshed frequently and cannot be used concurrently.
59
- # The SQLRunDB should always get its session from the FastAPI dependency injection.
60
57
  self._run_db = self._rundb_container.run_db(url)
61
58
 
62
59
  self._run_db.connect(secrets=secrets)