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.
- mlrun/__init__.py +1 -0
- mlrun/artifacts/__init__.py +1 -1
- mlrun/artifacts/base.py +21 -1
- mlrun/artifacts/document.py +62 -39
- mlrun/artifacts/manager.py +12 -5
- mlrun/common/constants.py +1 -0
- mlrun/common/model_monitoring/__init__.py +0 -2
- mlrun/common/model_monitoring/helpers.py +0 -28
- mlrun/common/schemas/__init__.py +2 -4
- mlrun/common/schemas/alert.py +77 -1
- mlrun/common/schemas/client_spec.py +0 -1
- mlrun/common/schemas/model_monitoring/__init__.py +0 -6
- mlrun/common/schemas/model_monitoring/constants.py +11 -9
- mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
- mlrun/common/schemas/notification.py +6 -0
- mlrun/common/schemas/project.py +3 -0
- mlrun/config.py +2 -3
- mlrun/datastore/datastore_profile.py +57 -17
- mlrun/datastore/sources.py +1 -2
- mlrun/datastore/store_resources.py +7 -2
- mlrun/datastore/vectorstore.py +99 -62
- mlrun/db/base.py +34 -20
- mlrun/db/httpdb.py +249 -163
- mlrun/db/nopdb.py +40 -17
- mlrun/execution.py +14 -7
- mlrun/feature_store/api.py +1 -0
- mlrun/model.py +3 -0
- mlrun/model_monitoring/__init__.py +3 -2
- mlrun/model_monitoring/api.py +64 -53
- mlrun/model_monitoring/applications/_application_steps.py +3 -1
- mlrun/model_monitoring/applications/base.py +115 -15
- mlrun/model_monitoring/applications/context.py +42 -24
- mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
- mlrun/model_monitoring/controller.py +43 -37
- mlrun/model_monitoring/db/__init__.py +0 -2
- mlrun/model_monitoring/db/tsdb/base.py +2 -1
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
- mlrun/model_monitoring/helpers.py +78 -66
- mlrun/model_monitoring/stream_processing.py +83 -270
- mlrun/model_monitoring/writer.py +1 -10
- mlrun/projects/pipelines.py +37 -1
- mlrun/projects/project.py +173 -70
- mlrun/run.py +40 -0
- mlrun/runtimes/nuclio/function.py +7 -6
- mlrun/runtimes/nuclio/serving.py +9 -4
- mlrun/serving/routers.py +158 -145
- mlrun/serving/server.py +6 -0
- mlrun/serving/states.py +21 -7
- mlrun/serving/v2_serving.py +94 -68
- mlrun/utils/helpers.py +23 -33
- mlrun/utils/notifications/notification/mail.py +17 -6
- mlrun/utils/notifications/notification_pusher.py +9 -5
- mlrun/utils/regex.py +8 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/METADATA +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/RECORD +61 -74
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
- mlrun/model_monitoring/db/stores/__init__.py +0 -136
- mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
- mlrun/model_monitoring/db/stores/base/store.py +0 -154
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
- mlrun/model_monitoring/model_endpoint.py +0 -120
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/WHEEL +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/top_level.txt +0 -0
mlrun/datastore/vectorstore.py
CHANGED
|
@@ -13,65 +13,61 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import inspect
|
|
16
|
-
from
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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]):
|
|
125
|
-
splitter (optional):
|
|
126
|
-
|
|
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:
|
|
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
|
-
|
|
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.
|
|
135
|
-
self._mlrun_context
|
|
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
|
|
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.
|
|
148
|
-
self._mlrun_context
|
|
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.
|
|
166
|
-
self._mlrun_context
|
|
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.
|
|
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.
|
|
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": {
|
|
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(
|
|
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
|
-
|
|
667
|
-
|
|
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
|
-
|
|
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
|
-
|
|
685
|
-
|
|
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:
|
|
688
|
-
end:
|
|
689
|
-
|
|
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
|
-
|
|
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
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
) -> mlrun.
|
|
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
|