mlrun 1.8.0rc5__py3-none-any.whl → 1.8.0rc9__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 (74) hide show
  1. mlrun/__init__.py +1 -0
  2. mlrun/artifacts/__init__.py +1 -1
  3. mlrun/artifacts/base.py +21 -1
  4. mlrun/artifacts/document.py +62 -39
  5. mlrun/artifacts/manager.py +12 -5
  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 +77 -1
  11. mlrun/common/schemas/client_spec.py +0 -1
  12. mlrun/common/schemas/model_monitoring/__init__.py +0 -6
  13. mlrun/common/schemas/model_monitoring/constants.py +11 -9
  14. mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
  15. mlrun/common/schemas/notification.py +6 -0
  16. mlrun/common/schemas/project.py +3 -0
  17. mlrun/config.py +2 -3
  18. mlrun/datastore/datastore_profile.py +57 -17
  19. mlrun/datastore/sources.py +1 -2
  20. mlrun/datastore/store_resources.py +7 -2
  21. mlrun/datastore/vectorstore.py +99 -62
  22. mlrun/db/base.py +34 -20
  23. mlrun/db/httpdb.py +249 -163
  24. mlrun/db/nopdb.py +40 -17
  25. mlrun/execution.py +14 -7
  26. mlrun/feature_store/api.py +1 -0
  27. mlrun/model.py +3 -0
  28. mlrun/model_monitoring/__init__.py +3 -2
  29. mlrun/model_monitoring/api.py +64 -53
  30. mlrun/model_monitoring/applications/_application_steps.py +3 -1
  31. mlrun/model_monitoring/applications/base.py +115 -15
  32. mlrun/model_monitoring/applications/context.py +42 -24
  33. mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
  34. mlrun/model_monitoring/controller.py +43 -37
  35. mlrun/model_monitoring/db/__init__.py +0 -2
  36. mlrun/model_monitoring/db/tsdb/base.py +2 -1
  37. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
  38. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
  39. mlrun/model_monitoring/helpers.py +78 -66
  40. mlrun/model_monitoring/stream_processing.py +83 -270
  41. mlrun/model_monitoring/writer.py +1 -10
  42. mlrun/projects/pipelines.py +37 -1
  43. mlrun/projects/project.py +173 -70
  44. mlrun/run.py +40 -0
  45. mlrun/runtimes/nuclio/function.py +7 -6
  46. mlrun/runtimes/nuclio/serving.py +9 -4
  47. mlrun/serving/routers.py +158 -145
  48. mlrun/serving/server.py +6 -0
  49. mlrun/serving/states.py +21 -7
  50. mlrun/serving/v2_serving.py +94 -68
  51. mlrun/utils/helpers.py +23 -33
  52. mlrun/utils/notifications/notification/mail.py +17 -6
  53. mlrun/utils/notifications/notification_pusher.py +9 -5
  54. mlrun/utils/regex.py +8 -1
  55. mlrun/utils/version/version.json +2 -2
  56. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/METADATA +2 -2
  57. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/RECORD +61 -74
  58. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
  59. mlrun/model_monitoring/db/stores/__init__.py +0 -136
  60. mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
  61. mlrun/model_monitoring/db/stores/base/store.py +0 -154
  62. mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
  63. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
  64. mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
  65. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
  66. mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
  67. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
  68. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
  69. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
  70. mlrun/model_monitoring/model_endpoint.py +0 -120
  71. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/LICENSE +0 -0
  72. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/WHEEL +0 -0
  73. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/entry_points.txt +0 -0
  74. {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/top_level.txt +0 -0
@@ -13,65 +13,61 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import inspect
16
- from importlib import import_module
17
- from typing import Union
16
+ from collections.abc import Iterable
17
+ from typing import Optional, Union
18
18
 
19
19
  from mlrun.artifacts import DocumentArtifact
20
20
 
21
21
 
22
+ def _extract_collection_name(vectorstore: "VectorStore") -> str: # noqa: F821
23
+ # List of possible attribute names for collection name
24
+ possible_attributes = ["collection_name", "_collection_name"]
25
+
26
+ for attr in possible_attributes:
27
+ if hasattr(vectorstore, attr):
28
+ collection_name = getattr(vectorstore, attr)
29
+ if collection_name:
30
+ return collection_name
31
+
32
+ store_class = vectorstore.__class__.__name__.lower()
33
+ if store_class == "mongodbatlasvectorsearch":
34
+ return vectorstore.collection.name
35
+
36
+ # If we get here, we couldn't find a valid collection name
37
+ raise ValueError(
38
+ "Failed to extract collection name from the vector store. "
39
+ "Please provide the collection name explicitly. "
40
+ )
41
+
42
+
22
43
  class VectorStoreCollection:
23
44
  """
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.
45
+ A wrapper class for vector store collections with MLRun integration.
46
+
47
+ This class wraps a vector store implementation (like Milvus, Chroma) and provides
48
+ integration with MLRun context for document and artifact management. It delegates
49
+ most operations to the underlying vector store while handling MLRun-specific
50
+ functionality.
51
+
52
+ The class implements attribute delegation through __getattr__ and __setattr__,
53
+ allowing direct access to the underlying vector store's methods and attributes
54
+ while maintaining MLRun integration.
48
55
  """
49
56
 
50
57
  def __init__(
51
58
  self,
52
- vector_store_class: str,
53
59
  mlrun_context: Union["MlrunProject", "MLClientCtx"], # noqa: F821
54
- datastore_profile: str,
55
- collection_name: str,
56
- **kwargs,
60
+ vector_store: "VectorStore", # noqa: F821
61
+ collection_name: Optional[str] = None,
57
62
  ):
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
63
  self._collection_impl = vector_store
72
64
  self._mlrun_context = mlrun_context
73
- self.collection_name = collection_name
74
- self.id = datastore_profile + "/" + collection_name
65
+ self.collection_name = collection_name or _extract_collection_name(vector_store)
66
+
67
+ @property
68
+ def __class__(self):
69
+ # Make isinstance() check the wrapped object's class
70
+ return self._collection_impl.__class__
75
71
 
76
72
  def __getattr__(self, name):
77
73
  # This method is called when an attribute is not found in the usual places
@@ -86,6 +82,9 @@ class VectorStoreCollection:
86
82
  # Forward the attribute setting to _collection_impl
87
83
  setattr(self._collection_impl, name, value)
88
84
 
85
+ def delete(self, *args, **kwargs):
86
+ self._collection_impl.delete(*args, **kwargs)
87
+
89
88
  def add_documents(
90
89
  self,
91
90
  documents: list["Document"], # noqa: F821
@@ -112,40 +111,74 @@ class VectorStoreCollection:
112
111
  )
113
112
  if mlrun_uri:
114
113
  artifact = self._mlrun_context.get_store_resource(mlrun_uri)
115
- artifact.collection_add(self.id)
114
+ artifact.collection_add(self.collection_name)
116
115
  self._mlrun_context.update_artifact(artifact)
116
+
117
117
  return self._collection_impl.add_documents(documents, **kwargs)
118
118
 
119
119
  def add_artifacts(self, artifacts: list[DocumentArtifact], splitter=None, **kwargs):
120
120
  """
121
- Add a list of DocumentArtifact objects to the collection.
121
+ Add a list of DocumentArtifact objects to the vector store collection.
122
+
123
+ Converts artifacts to LangChain documents, adds them to the vector store, and
124
+ updates the MLRun context. If documents are split, the IDs are handled appropriately.
122
125
 
123
126
  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.
127
+ artifacts (list[DocumentArtifact]): List of DocumentArtifact objects to add
128
+ splitter (optional): Document splitter to break artifacts into smaller chunks.
129
+ If None, each artifact becomes a single document.
130
+ **kwargs: Additional arguments passed to the underlying add_documents method.
131
+ Special handling for 'ids' kwarg:
132
+ - If provided and document is split, IDs are generated as "{original_id}_{i}"
133
+ where i starts from 1 (e.g., "doc1_1", "doc1_2", etc.)
134
+ - If provided and document isn't split, original IDs are used as-is
127
135
 
128
136
  Returns:
129
- list: A list of IDs of the added documents.
137
+ list: List of IDs for all added documents. When no custom IDs are provided:
138
+ - Without splitting: Vector store generates IDs automatically
139
+ - With splitting: Vector store generates separate IDs for each chunk
140
+ When custom IDs are provided:
141
+ - Without splitting: Uses provided IDs directly
142
+ - With splitting: Generates sequential IDs as "{original_id}_{i}" for each chunk
130
143
  """
131
144
  all_ids = []
132
- for artifact in artifacts:
145
+ user_ids = kwargs.pop("ids", None)
146
+
147
+ if user_ids:
148
+ if not isinstance(user_ids, Iterable):
149
+ raise ValueError("IDs must be an iterable collection")
150
+ if len(user_ids) != len(artifacts):
151
+ raise ValueError(
152
+ "The number of IDs should match the number of artifacts"
153
+ )
154
+ for index, artifact in enumerate(artifacts):
133
155
  documents = artifact.to_langchain_documents(splitter)
134
- artifact.collection_add(self.id)
135
- self._mlrun_context.update_artifact(artifact)
156
+ artifact.collection_add(self.collection_name)
157
+ if self._mlrun_context:
158
+ self._mlrun_context.update_artifact(artifact)
159
+ if user_ids:
160
+ num_of_documents = len(documents)
161
+ if num_of_documents > 1:
162
+ ids_to_pass = [
163
+ f"{user_ids[index]}_{i}" for i in range(1, num_of_documents + 1)
164
+ ]
165
+ else:
166
+ ids_to_pass = [user_ids[index]]
167
+ kwargs["ids"] = ids_to_pass
136
168
  ids = self._collection_impl.add_documents(documents, **kwargs)
137
169
  all_ids.extend(ids)
138
170
  return all_ids
139
171
 
140
- def remove_itself_from_artifact(self, artifact: DocumentArtifact):
172
+ def remove_from_artifact(self, artifact: DocumentArtifact):
141
173
  """
142
174
  Remove the current object from the given artifact's collection and update the artifact.
143
175
 
144
176
  Args:
145
177
  artifact (DocumentArtifact): The artifact from which the current object should be removed.
146
178
  """
147
- artifact.collection_remove(self.id)
148
- self._mlrun_context.update_artifact(artifact)
179
+ artifact.collection_remove(self.collection_name)
180
+ if self._mlrun_context:
181
+ self._mlrun_context.update_artifact(artifact)
149
182
 
150
183
  def delete_artifacts(self, artifacts: list[DocumentArtifact]):
151
184
  """
@@ -162,13 +195,15 @@ class VectorStoreCollection:
162
195
  """
163
196
  store_class = self._collection_impl.__class__.__name__.lower()
164
197
  for artifact in artifacts:
165
- artifact.collection_remove(self.id)
166
- self._mlrun_context.update_artifact(artifact)
198
+ artifact.collection_remove(self.collection_name)
199
+ if self._mlrun_context:
200
+ self._mlrun_context.update_artifact(artifact)
201
+
167
202
  if store_class == "milvus":
168
- expr = f"{DocumentArtifact.METADATA_SOURCE_KEY} == '{artifact.source}'"
203
+ expr = f"{DocumentArtifact.METADATA_SOURCE_KEY} == '{artifact.get_source()}'"
169
204
  return self._collection_impl.delete(expr=expr)
170
205
  elif store_class == "chroma":
171
- where = {DocumentArtifact.METADATA_SOURCE_KEY: artifact.source}
206
+ where = {DocumentArtifact.METADATA_SOURCE_KEY: artifact.get_source()}
172
207
  return self._collection_impl.delete(where=where)
173
208
 
174
209
  elif (
@@ -177,7 +212,9 @@ class VectorStoreCollection:
177
212
  in inspect.signature(self._collection_impl.delete).parameters
178
213
  ):
179
214
  filter = {
180
- "metadata": {DocumentArtifact.METADATA_SOURCE_KEY: artifact.source}
215
+ "metadata": {
216
+ DocumentArtifact.METADATA_SOURCE_KEY: artifact.get_source()
217
+ }
181
218
  }
182
219
  return self._collection_impl.delete(filter=filter)
183
220
  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,17 +665,18 @@ 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,
676
- endpoint_id: str,
677
+ function_name: Optional[str] = None,
678
+ function_tag: Optional[str] = None,
679
+ endpoint_id: Optional[str] = None,
677
680
  ):
678
681
  pass
679
682
 
@@ -681,36 +684,43 @@ class RunDBInterface(ABC):
681
684
  def list_model_endpoints(
682
685
  self,
683
686
  project: str,
684
- model: Optional[str] = None,
685
- function: Optional[str] = None,
687
+ name: Optional[str] = None,
688
+ function_name: Optional[str] = None,
689
+ function_tag: Optional[str] = None,
690
+ model_name: Optional[str] = None,
686
691
  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,
692
+ start: Optional[datetime.datetime] = None,
693
+ end: Optional[datetime.datetime] = None,
694
+ tsdb_metrics: bool = True,
690
695
  top_level: bool = False,
691
696
  uids: Optional[list[str]] = None,
692
- ) -> list[mlrun.model_monitoring.model_endpoint.ModelEndpoint]:
697
+ latest_only: bool = False,
698
+ ) -> mlrun.common.schemas.ModelEndpointList:
693
699
  pass
694
700
 
695
701
  @abstractmethod
696
702
  def get_model_endpoint(
697
703
  self,
704
+ name: str,
698
705
  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:
706
+ function_name: Optional[str] = None,
707
+ function_tag: Optional[str] = None,
708
+ endpoint_id: Optional[str] = None,
709
+ tsdb_metrics: bool = True,
710
+ feature_analysis: bool = False,
711
+ ) -> mlrun.common.schemas.ModelEndpoint:
705
712
  pass
706
713
 
707
714
  @abstractmethod
708
715
  def patch_model_endpoint(
709
716
  self,
717
+ name: str,
710
718
  project: str,
711
- endpoint_id: str,
712
719
  attributes: dict,
713
- ):
720
+ function_name: Optional[str] = None,
721
+ function_tag: Optional[str] = None,
722
+ endpoint_id: Optional[str] = None,
723
+ ) -> mlrun.common.schemas.ModelEndpoint:
714
724
  pass
715
725
 
716
726
  @abstractmethod
@@ -1051,3 +1061,7 @@ class RunDBInterface(ABC):
1051
1061
  replace_creds: bool,
1052
1062
  ) -> None:
1053
1063
  pass
1064
+
1065
+ @abstractmethod
1066
+ def get_project_summary(self, project: str) -> mlrun.common.schemas.ProjectSummary:
1067
+ pass