mlrun 1.8.0rc12__py3-none-any.whl → 1.8.0rc13__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/artifacts/document.py +32 -6
- mlrun/common/formatters/artifact.py +1 -1
- mlrun/common/schemas/partition.py +23 -18
- mlrun/datastore/vectorstore.py +69 -26
- mlrun/db/base.py +13 -1
- mlrun/db/httpdb.py +42 -7
- mlrun/db/nopdb.py +12 -1
- mlrun/execution.py +43 -11
- mlrun/model_monitoring/applications/_application_steps.py +1 -1
- mlrun/model_monitoring/applications/base.py +2 -3
- mlrun/model_monitoring/applications/context.py +94 -71
- mlrun/projects/pipelines.py +6 -3
- mlrun/projects/project.py +77 -1
- mlrun/runtimes/nuclio/function.py +2 -1
- mlrun/runtimes/nuclio/serving.py +10 -5
- mlrun/serving/routers.py +16 -7
- mlrun/serving/states.py +14 -6
- mlrun/serving/v2_serving.py +11 -6
- mlrun/utils/notifications/notification/base.py +1 -1
- mlrun/utils/notifications/notification/webhook.py +13 -12
- mlrun/utils/notifications/notification_pusher.py +18 -23
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/METADATA +2 -2
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/RECORD +28 -28
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/WHEEL +0 -0
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc12.dist-info → mlrun-1.8.0rc13.dist-info}/top_level.txt +0 -0
|
@@ -45,32 +45,6 @@ class _ArtifactsLogger(Protocol):
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class MonitoringApplicationContext:
|
|
48
|
-
"""
|
|
49
|
-
The monitoring context holds all the relevant information for the monitoring application,
|
|
50
|
-
and also it can be used for logging artifacts and results.
|
|
51
|
-
The monitoring context has the following attributes:
|
|
52
|
-
|
|
53
|
-
:param application_name: (str) The model monitoring application name.
|
|
54
|
-
:param project_name: (str) The project name.
|
|
55
|
-
:param project: (MlrunProject) The project object.
|
|
56
|
-
:param logger: (mlrun.utils.Logger) MLRun logger.
|
|
57
|
-
:param nuclio_logger: (nuclio.request.Logger) Nuclio logger.
|
|
58
|
-
:param sample_df_stats: (FeatureStats) The new sample distribution dictionary.
|
|
59
|
-
:param feature_stats: (FeatureStats) The train sample distribution dictionary.
|
|
60
|
-
:param sample_df: (pd.DataFrame) The new sample DataFrame.
|
|
61
|
-
:param start_infer_time: (pd.Timestamp) Start time of the monitoring schedule.
|
|
62
|
-
:param end_infer_time: (pd.Timestamp) End time of the monitoring schedule.
|
|
63
|
-
:param latest_request: (pd.Timestamp) Timestamp of the latest request on this endpoint_id.
|
|
64
|
-
:param endpoint_id: (str) ID of the monitored model endpoint
|
|
65
|
-
:param endpoint_name: (str) Name of the monitored model endpoint
|
|
66
|
-
:param output_stream_uri: (str) URI of the output stream for results
|
|
67
|
-
:param model_endpoint: (ModelEndpoint) The model endpoint object.
|
|
68
|
-
:param feature_names: (list[str]) List of models feature names.
|
|
69
|
-
:param label_names: (list[str]) List of models label names.
|
|
70
|
-
:param model: (tuple[str, ModelArtifact, dict]) The model file, model spec object,
|
|
71
|
-
and a list of extra data items.
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
48
|
_logger_name = "monitoring-application"
|
|
75
49
|
|
|
76
50
|
def __init__(
|
|
@@ -78,64 +52,51 @@ class MonitoringApplicationContext:
|
|
|
78
52
|
*,
|
|
79
53
|
application_name: str,
|
|
80
54
|
event: dict[str, Any],
|
|
55
|
+
project: "mlrun.MlrunProject",
|
|
56
|
+
artifacts_logger: _ArtifactsLogger,
|
|
57
|
+
logger: mlrun.utils.Logger,
|
|
58
|
+
nuclio_logger: nuclio.request.Logger,
|
|
81
59
|
model_endpoint_dict: Optional[dict[str, ModelEndpoint]] = None,
|
|
82
|
-
logger: Optional[mlrun.utils.Logger] = None,
|
|
83
|
-
graph_context: Optional[mlrun.serving.GraphContext] = None,
|
|
84
|
-
context: Optional["mlrun.MLClientCtx"] = None,
|
|
85
|
-
artifacts_logger: Optional[_ArtifactsLogger] = None,
|
|
86
60
|
sample_df: Optional[pd.DataFrame] = None,
|
|
87
61
|
feature_stats: Optional[FeatureStats] = None,
|
|
88
62
|
) -> None:
|
|
89
63
|
"""
|
|
90
|
-
The :code:`
|
|
91
|
-
and
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
:param application_name:
|
|
95
|
-
:param
|
|
96
|
-
:param
|
|
97
|
-
:param logger:
|
|
98
|
-
:param
|
|
99
|
-
:param
|
|
100
|
-
:param
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
:param
|
|
104
|
-
|
|
105
|
-
:param
|
|
106
|
-
|
|
64
|
+
The :code:`MonitoringApplicationContext` object holds all the relevant information for the
|
|
65
|
+
model monitoring application, and can be used for logging artifacts and messages.
|
|
66
|
+
The monitoring context has the following attributes:
|
|
67
|
+
|
|
68
|
+
:param application_name: (str) The model monitoring application name.
|
|
69
|
+
:param project: (:py:class:`~mlrun.projects.MlrunProject`) The current MLRun project object.
|
|
70
|
+
:param project_name: (str) The project name.
|
|
71
|
+
:param logger: (:py:class:`~mlrun.utils.Logger`) MLRun logger.
|
|
72
|
+
:param nuclio_logger: (nuclio.request.Logger) Nuclio logger.
|
|
73
|
+
:param sample_df_stats: (FeatureStats) The new sample distribution dictionary.
|
|
74
|
+
:param feature_stats: (FeatureStats) The train sample distribution dictionary.
|
|
75
|
+
:param sample_df: (pd.DataFrame) The new sample DataFrame.
|
|
76
|
+
:param start_infer_time: (pd.Timestamp) Start time of the monitoring schedule.
|
|
77
|
+
:param end_infer_time: (pd.Timestamp) End time of the monitoring schedule.
|
|
78
|
+
:param latest_request: (pd.Timestamp) Timestamp of the latest request on this endpoint_id.
|
|
79
|
+
:param endpoint_id: (str) ID of the monitored model endpoint
|
|
80
|
+
:param endpoint_name: (str) Name of the monitored model endpoint
|
|
81
|
+
:param output_stream_uri: (str) URI of the output stream for results
|
|
82
|
+
:param model_endpoint: (ModelEndpoint) The model endpoint object.
|
|
83
|
+
:param feature_names: (list[str]) List of models feature names.
|
|
84
|
+
:param label_names: (list[str]) List of models label names.
|
|
85
|
+
:param model: (tuple[str, ModelArtifact, dict]) The model file, model spec object,
|
|
86
|
+
and a list of extra data items.
|
|
107
87
|
"""
|
|
108
88
|
self.application_name = application_name
|
|
109
89
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
self.project = mlrun.load_project(url=self.project_name)
|
|
113
|
-
elif context:
|
|
114
|
-
potential_project = context.get_project_object()
|
|
115
|
-
if not potential_project:
|
|
116
|
-
raise mlrun.errors.MLRunValueError(
|
|
117
|
-
"Could not load project from context"
|
|
118
|
-
)
|
|
119
|
-
self.project = potential_project
|
|
120
|
-
self.project_name = self.project.name
|
|
90
|
+
self.project = project
|
|
91
|
+
self.project_name = project.name
|
|
121
92
|
|
|
122
|
-
self._artifacts_logger
|
|
93
|
+
self._artifacts_logger = artifacts_logger
|
|
123
94
|
|
|
124
95
|
# MLRun Logger
|
|
125
|
-
self.logger = logger
|
|
126
|
-
level=mlrun.mlconf.log_level,
|
|
127
|
-
formatter_kind=mlrun.mlconf.log_formatter,
|
|
128
|
-
name=self._logger_name,
|
|
129
|
-
)
|
|
96
|
+
self.logger = logger
|
|
130
97
|
# Nuclio logger - `nuclio.request.Logger`.
|
|
131
98
|
# Note: this logger accepts keyword arguments only in its `_with` methods, e.g. `info_with`.
|
|
132
|
-
self.nuclio_logger =
|
|
133
|
-
graph_context.logger
|
|
134
|
-
if graph_context
|
|
135
|
-
else nuclio.request.Logger(
|
|
136
|
-
level=mlrun.mlconf.log_level, name=self._logger_name
|
|
137
|
-
)
|
|
138
|
-
)
|
|
99
|
+
self.nuclio_logger = nuclio_logger
|
|
139
100
|
|
|
140
101
|
# event data
|
|
141
102
|
self.start_infer_time = pd.Timestamp(
|
|
@@ -166,6 +127,68 @@ class MonitoringApplicationContext:
|
|
|
166
127
|
model_endpoint_dict.get(self.endpoint_id) if model_endpoint_dict else None
|
|
167
128
|
)
|
|
168
129
|
|
|
130
|
+
@classmethod
|
|
131
|
+
def _from_ml_ctx(
|
|
132
|
+
cls,
|
|
133
|
+
context: "mlrun.MLClientCtx",
|
|
134
|
+
*,
|
|
135
|
+
application_name: str,
|
|
136
|
+
event: dict[str, Any],
|
|
137
|
+
model_endpoint_dict: Optional[dict[str, ModelEndpoint]] = None,
|
|
138
|
+
sample_df: Optional[pd.DataFrame] = None,
|
|
139
|
+
feature_stats: Optional[FeatureStats] = None,
|
|
140
|
+
) -> "MonitoringApplicationContext":
|
|
141
|
+
project = context.get_project_object()
|
|
142
|
+
if not project:
|
|
143
|
+
raise mlrun.errors.MLRunValueError("Could not load project from context")
|
|
144
|
+
logger = context.logger
|
|
145
|
+
artifacts_logger = context
|
|
146
|
+
nuclio_logger = nuclio.request.Logger(
|
|
147
|
+
level=mlrun.mlconf.log_level, name=cls._logger_name
|
|
148
|
+
)
|
|
149
|
+
return cls(
|
|
150
|
+
application_name=application_name,
|
|
151
|
+
event=event,
|
|
152
|
+
model_endpoint_dict=model_endpoint_dict,
|
|
153
|
+
project=project,
|
|
154
|
+
logger=logger,
|
|
155
|
+
nuclio_logger=nuclio_logger,
|
|
156
|
+
artifacts_logger=artifacts_logger,
|
|
157
|
+
sample_df=sample_df,
|
|
158
|
+
feature_stats=feature_stats,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
@classmethod
|
|
162
|
+
def _from_graph_ctx(
|
|
163
|
+
cls,
|
|
164
|
+
graph_context: mlrun.serving.GraphContext,
|
|
165
|
+
*,
|
|
166
|
+
application_name: str,
|
|
167
|
+
event: dict[str, Any],
|
|
168
|
+
model_endpoint_dict: Optional[dict[str, ModelEndpoint]] = None,
|
|
169
|
+
sample_df: Optional[pd.DataFrame] = None,
|
|
170
|
+
feature_stats: Optional[FeatureStats] = None,
|
|
171
|
+
) -> "MonitoringApplicationContext":
|
|
172
|
+
project = mlrun.load_project(url=graph_context.project)
|
|
173
|
+
nuclio_logger = graph_context.logger
|
|
174
|
+
artifacts_logger = project
|
|
175
|
+
logger = mlrun.utils.create_logger(
|
|
176
|
+
level=mlrun.mlconf.log_level,
|
|
177
|
+
formatter_kind=mlrun.mlconf.log_formatter,
|
|
178
|
+
name=cls._logger_name,
|
|
179
|
+
)
|
|
180
|
+
return cls(
|
|
181
|
+
application_name=application_name,
|
|
182
|
+
event=event,
|
|
183
|
+
project=project,
|
|
184
|
+
model_endpoint_dict=model_endpoint_dict,
|
|
185
|
+
logger=logger,
|
|
186
|
+
nuclio_logger=nuclio_logger,
|
|
187
|
+
artifacts_logger=artifacts_logger,
|
|
188
|
+
sample_df=sample_df,
|
|
189
|
+
feature_stats=feature_stats,
|
|
190
|
+
)
|
|
191
|
+
|
|
169
192
|
def _get_default_labels(self) -> dict[str, str]:
|
|
170
193
|
labels = {
|
|
171
194
|
mlrun_constants.MLRunInternalLabels.runner_pod: socket.gethostname(),
|
mlrun/projects/pipelines.py
CHANGED
|
@@ -471,6 +471,7 @@ class _PipelineRunner(abc.ABC):
|
|
|
471
471
|
namespace=None,
|
|
472
472
|
source=None,
|
|
473
473
|
notifications: typing.Optional[list[mlrun.model.Notification]] = None,
|
|
474
|
+
context: typing.Optional[mlrun.execution.MLClientCtx] = None,
|
|
474
475
|
) -> _PipelineRunStatus:
|
|
475
476
|
pass
|
|
476
477
|
|
|
@@ -595,6 +596,7 @@ class _KFPRunner(_PipelineRunner):
|
|
|
595
596
|
namespace=None,
|
|
596
597
|
source=None,
|
|
597
598
|
notifications: typing.Optional[list[mlrun.model.Notification]] = None,
|
|
599
|
+
context: typing.Optional[mlrun.execution.MLClientCtx] = None,
|
|
598
600
|
) -> _PipelineRunStatus:
|
|
599
601
|
pipeline_context.set(project, workflow_spec)
|
|
600
602
|
workflow_handler = _PipelineRunner._get_handler(
|
|
@@ -646,9 +648,7 @@ class _KFPRunner(_PipelineRunner):
|
|
|
646
648
|
)
|
|
647
649
|
project.notifiers.push_pipeline_start_message(
|
|
648
650
|
project.metadata.name,
|
|
649
|
-
|
|
650
|
-
run_id,
|
|
651
|
-
True,
|
|
651
|
+
context.uid,
|
|
652
652
|
)
|
|
653
653
|
pipeline_context.clear()
|
|
654
654
|
return _PipelineRunStatus(run_id, cls, project=project, workflow=workflow_spec)
|
|
@@ -722,6 +722,7 @@ class _LocalRunner(_PipelineRunner):
|
|
|
722
722
|
namespace=None,
|
|
723
723
|
source=None,
|
|
724
724
|
notifications: typing.Optional[list[mlrun.model.Notification]] = None,
|
|
725
|
+
context: typing.Optional[mlrun.execution.MLClientCtx] = None,
|
|
725
726
|
) -> _PipelineRunStatus:
|
|
726
727
|
pipeline_context.set(project, workflow_spec)
|
|
727
728
|
workflow_handler = _PipelineRunner._get_handler(
|
|
@@ -805,6 +806,7 @@ class _RemoteRunner(_PipelineRunner):
|
|
|
805
806
|
namespace: typing.Optional[str] = None,
|
|
806
807
|
source: typing.Optional[str] = None,
|
|
807
808
|
notifications: typing.Optional[list[mlrun.model.Notification]] = None,
|
|
809
|
+
context: typing.Optional[mlrun.execution.MLClientCtx] = None,
|
|
808
810
|
) -> typing.Optional[_PipelineRunStatus]:
|
|
809
811
|
workflow_name = normalize_workflow_name(name=name, project_name=project.name)
|
|
810
812
|
workflow_id = None
|
|
@@ -1127,6 +1129,7 @@ def load_and_run_workflow(
|
|
|
1127
1129
|
engine=engine,
|
|
1128
1130
|
local=local,
|
|
1129
1131
|
notifications=start_notifications,
|
|
1132
|
+
context=context,
|
|
1130
1133
|
)
|
|
1131
1134
|
context.log_result(key="workflow_id", value=run.run_id)
|
|
1132
1135
|
context.log_result(key="engine", value=run._engine.engine, commit=True)
|
mlrun/projects/project.py
CHANGED
|
@@ -1873,6 +1873,34 @@ class MlrunProject(ModelObj):
|
|
|
1873
1873
|
vector_store: "VectorStore", # noqa: F821
|
|
1874
1874
|
collection_name: Optional[str] = None,
|
|
1875
1875
|
) -> VectorStoreCollection:
|
|
1876
|
+
"""
|
|
1877
|
+
Create a VectorStoreCollection wrapper for a given vector store instance.
|
|
1878
|
+
|
|
1879
|
+
This method wraps a vector store implementation (like Milvus, Chroma) with MLRun
|
|
1880
|
+
integration capabilities. The wrapper provides access to the underlying vector
|
|
1881
|
+
store's functionality while adding MLRun-specific features like document and
|
|
1882
|
+
artifact management.
|
|
1883
|
+
|
|
1884
|
+
Args:
|
|
1885
|
+
vector_store: The vector store instance to wrap (e.g., Milvus, Chroma).
|
|
1886
|
+
This is the underlying implementation that will handle
|
|
1887
|
+
vector storage and retrieval.
|
|
1888
|
+
collection_name: Optional name for the collection. If not provided,
|
|
1889
|
+
will attempt to extract it from the vector_store object
|
|
1890
|
+
by looking for 'collection_name', '_collection_name',
|
|
1891
|
+
'index_name', or '_index_name' attributes.
|
|
1892
|
+
|
|
1893
|
+
Returns:
|
|
1894
|
+
VectorStoreCollection: A wrapped vector store instance with MLRun integration.
|
|
1895
|
+
This wrapper provides both access to the original vector
|
|
1896
|
+
store's capabilities and additional MLRun functionality.
|
|
1897
|
+
|
|
1898
|
+
Example:
|
|
1899
|
+
>>> vector_store = Chroma(embedding_function=embeddings)
|
|
1900
|
+
>>> collection = project.get_vector_store_collection(
|
|
1901
|
+
... vector_store, collection_name="my_collection"
|
|
1902
|
+
... )
|
|
1903
|
+
"""
|
|
1876
1904
|
return VectorStoreCollection(
|
|
1877
1905
|
self,
|
|
1878
1906
|
vector_store,
|
|
@@ -1899,12 +1927,39 @@ class MlrunProject(ModelObj):
|
|
|
1899
1927
|
:param local_path: path to the local file we upload, will also be use
|
|
1900
1928
|
as the destination subpath (under "artifact_path")
|
|
1901
1929
|
:param artifact_path: Target path for artifact storage
|
|
1902
|
-
:param document_loader_spec: Spec to use to load the artifact as langchain document
|
|
1930
|
+
:param document_loader_spec: Spec to use to load the artifact as langchain document.
|
|
1931
|
+
|
|
1932
|
+
By default, uses DocumentLoaderSpec() which initializes with:
|
|
1933
|
+
|
|
1934
|
+
* loader_class_name="langchain_community.document_loaders.TextLoader"
|
|
1935
|
+
* src_name="file_path"
|
|
1936
|
+
* kwargs=None
|
|
1937
|
+
|
|
1938
|
+
Can be customized for different document types, e.g.::
|
|
1939
|
+
|
|
1940
|
+
DocumentLoaderSpec(
|
|
1941
|
+
loader_class_name="langchain_community.document_loaders.PDFLoader",
|
|
1942
|
+
src_name="file_path",
|
|
1943
|
+
kwargs={"extract_images": True}
|
|
1944
|
+
)
|
|
1903
1945
|
:param upload: Whether to upload the artifact
|
|
1904
1946
|
:param labels: Key-value labels
|
|
1905
1947
|
:param target_path: Target file path
|
|
1906
1948
|
:param kwargs: Additional keyword arguments
|
|
1907
1949
|
:return: DocumentArtifact object
|
|
1950
|
+
|
|
1951
|
+
Example:
|
|
1952
|
+
>>> # Log a PDF document with custom loader
|
|
1953
|
+
>>> project.log_document(
|
|
1954
|
+
... key="my_doc",
|
|
1955
|
+
... local_path="path/to/doc.pdf",
|
|
1956
|
+
... document_loader=DocumentLoaderSpec(
|
|
1957
|
+
... loader_class_name="langchain_community.document_loaders.PDFLoader",
|
|
1958
|
+
... src_name="file_path",
|
|
1959
|
+
... kwargs={"extract_images": True},
|
|
1960
|
+
... ),
|
|
1961
|
+
... )
|
|
1962
|
+
|
|
1908
1963
|
"""
|
|
1909
1964
|
doc_artifact = DocumentArtifact(
|
|
1910
1965
|
key=key,
|
|
@@ -2586,6 +2641,24 @@ class MlrunProject(ModelObj):
|
|
|
2586
2641
|
self._set_function(resolved_function_name, tag, function_object, func)
|
|
2587
2642
|
return function_object
|
|
2588
2643
|
|
|
2644
|
+
def push_run_notifications(
|
|
2645
|
+
self,
|
|
2646
|
+
uid,
|
|
2647
|
+
timeout=45,
|
|
2648
|
+
):
|
|
2649
|
+
"""
|
|
2650
|
+
Push notifications for a run.
|
|
2651
|
+
|
|
2652
|
+
:param uid: Unique ID of the run.
|
|
2653
|
+
:returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
|
|
2654
|
+
"""
|
|
2655
|
+
db = mlrun.db.get_run_db(secrets=self._secrets)
|
|
2656
|
+
return db.push_run_notifications(
|
|
2657
|
+
project=self.name,
|
|
2658
|
+
uid=uid,
|
|
2659
|
+
timeout=timeout,
|
|
2660
|
+
)
|
|
2661
|
+
|
|
2589
2662
|
def _instantiate_function(
|
|
2590
2663
|
self,
|
|
2591
2664
|
func: typing.Union[str, mlrun.runtimes.BaseRuntime] = None,
|
|
@@ -3239,6 +3312,7 @@ class MlrunProject(ModelObj):
|
|
|
3239
3312
|
cleanup_ttl: Optional[int] = None,
|
|
3240
3313
|
notifications: Optional[list[mlrun.model.Notification]] = None,
|
|
3241
3314
|
workflow_runner_node_selector: typing.Optional[dict[str, str]] = None,
|
|
3315
|
+
context: typing.Optional[mlrun.execution.MLClientCtx] = None,
|
|
3242
3316
|
) -> _PipelineRunStatus:
|
|
3243
3317
|
"""Run a workflow using kubeflow pipelines
|
|
3244
3318
|
|
|
@@ -3281,6 +3355,7 @@ class MlrunProject(ModelObj):
|
|
|
3281
3355
|
This allows you to control and specify where the workflow runner pod will be scheduled.
|
|
3282
3356
|
This setting is only relevant when the engine is set to 'remote' or for scheduled workflows,
|
|
3283
3357
|
and it will be ignored if the workflow is not run on a remote engine.
|
|
3358
|
+
:param context: mlrun context.
|
|
3284
3359
|
:returns: ~py:class:`~mlrun.projects.pipelines._PipelineRunStatus` instance
|
|
3285
3360
|
"""
|
|
3286
3361
|
|
|
@@ -3367,6 +3442,7 @@ class MlrunProject(ModelObj):
|
|
|
3367
3442
|
namespace=namespace,
|
|
3368
3443
|
source=source,
|
|
3369
3444
|
notifications=notifications,
|
|
3445
|
+
context=context,
|
|
3370
3446
|
)
|
|
3371
3447
|
# run is None when scheduling
|
|
3372
3448
|
if run and run.state == mlrun_pipelines.common.models.RunStatuses.failed:
|
|
@@ -1036,9 +1036,10 @@ class RemoteRuntime(KubeResource):
|
|
|
1036
1036
|
if args and sidecar.get("command"):
|
|
1037
1037
|
sidecar["args"] = mlrun.utils.helpers.as_list(args)
|
|
1038
1038
|
|
|
1039
|
-
#
|
|
1039
|
+
# put the configured resources on the sidecar container instead of the reverse proxy container
|
|
1040
1040
|
if self.spec.resources:
|
|
1041
1041
|
sidecar["resources"] = self.spec.resources
|
|
1042
|
+
self.spec.resources = None
|
|
1042
1043
|
|
|
1043
1044
|
def _set_sidecar(self, name: str) -> dict:
|
|
1044
1045
|
self.spec.config.setdefault("spec.sidecars", [])
|
mlrun/runtimes/nuclio/serving.py
CHANGED
|
@@ -387,11 +387,16 @@ class ServingRuntime(RemoteRuntime):
|
|
|
387
387
|
:param router_step: router step name (to determine which router we add the model to in graphs
|
|
388
388
|
with multiple router steps)
|
|
389
389
|
:param child_function: child function name, when the model runs in a child function
|
|
390
|
-
:param creation_strategy:
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
390
|
+
:param creation_strategy: Strategy for creating or updating the model endpoint:
|
|
391
|
+
* **overwrite**:
|
|
392
|
+
1. If model endpoints with the same name exist, delete the `latest` one.
|
|
393
|
+
2. Create a new model endpoint entry and set it as `latest`.
|
|
394
|
+
* **inplace** (default):
|
|
395
|
+
1. If model endpoints with the same name exist, update the `latest` entry.
|
|
396
|
+
2. Otherwise, create a new entry.
|
|
397
|
+
* **archive**:
|
|
398
|
+
1. If model endpoints with the same name exist, preserve them.
|
|
399
|
+
2. Create a new model endpoint with the same name and set it to `latest`.
|
|
395
400
|
:param class_args: extra kwargs to pass to the model serving class __init__
|
|
396
401
|
(can be read in the model using .get_param(key) method)
|
|
397
402
|
"""
|
mlrun/serving/routers.py
CHANGED
|
@@ -619,7 +619,10 @@ class VotingEnsemble(ParallelRun):
|
|
|
619
619
|
|
|
620
620
|
if not self.context.is_mock or self.context.monitoring_mock:
|
|
621
621
|
self.model_endpoint_uid = _init_endpoint_record(
|
|
622
|
-
server,
|
|
622
|
+
server,
|
|
623
|
+
self,
|
|
624
|
+
creation_strategy=kwargs.get("creation_strategy"),
|
|
625
|
+
endpoint_type=kwargs.get("endpoint_type"),
|
|
623
626
|
)
|
|
624
627
|
|
|
625
628
|
self._update_weights(self.weights)
|
|
@@ -1004,7 +1007,7 @@ class VotingEnsemble(ParallelRun):
|
|
|
1004
1007
|
def _init_endpoint_record(
|
|
1005
1008
|
graph_server: GraphServer,
|
|
1006
1009
|
voting_ensemble: VotingEnsemble,
|
|
1007
|
-
creation_strategy:
|
|
1010
|
+
creation_strategy: mlrun.common.schemas.ModelEndpointCreationStrategy,
|
|
1008
1011
|
endpoint_type: mlrun.common.schemas.EndpointType,
|
|
1009
1012
|
) -> Union[str, None]:
|
|
1010
1013
|
"""
|
|
@@ -1015,11 +1018,17 @@ def _init_endpoint_record(
|
|
|
1015
1018
|
:param graph_server: A GraphServer object which will be used for getting the function uri.
|
|
1016
1019
|
:param voting_ensemble: Voting ensemble serving class. It contains important details for the model endpoint record
|
|
1017
1020
|
such as model name, model path, model version, and the ids of the children model endpoints.
|
|
1018
|
-
:param creation_strategy:
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1021
|
+
:param creation_strategy: Strategy for creating or updating the model endpoint:
|
|
1022
|
+
* **overwrite**:
|
|
1023
|
+
1. If model endpoints with the same name exist, delete the `latest` one.
|
|
1024
|
+
2. Create a new model endpoint entry and set it as `latest`.
|
|
1025
|
+
* **inplace** (default):
|
|
1026
|
+
1. If model endpoints with the same name exist, update the `latest` entry.
|
|
1027
|
+
2. Otherwise, create a new entry.
|
|
1028
|
+
* **archive**:
|
|
1029
|
+
1. If model endpoints with the same name exist, preserve them.
|
|
1030
|
+
2. Create a new model endpoint with the same name and set it to `latest`.
|
|
1031
|
+
|
|
1023
1032
|
:param endpoint_type: model endpoint type
|
|
1024
1033
|
:return: Model endpoint unique ID.
|
|
1025
1034
|
"""
|
mlrun/serving/states.py
CHANGED
|
@@ -755,11 +755,17 @@ class RouterStep(TaskStep):
|
|
|
755
755
|
:param class_args: class init arguments
|
|
756
756
|
:param handler: class handler to invoke on run/event
|
|
757
757
|
:param function: function this step should run in
|
|
758
|
-
:param creation_strategy:
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
758
|
+
:param creation_strategy: Strategy for creating or updating the model endpoint:
|
|
759
|
+
* **overwrite**:
|
|
760
|
+
1. If model endpoints with the same name exist, delete the `latest` one.
|
|
761
|
+
2. Create a new model endpoint entry and set it as `latest`.
|
|
762
|
+
* **inplace** (default):
|
|
763
|
+
1. If model endpoints with the same name exist, update the `latest` entry.
|
|
764
|
+
2. Otherwise, create a new entry.
|
|
765
|
+
* **archive**:
|
|
766
|
+
1. If model endpoints with the same name exist, preserve them.
|
|
767
|
+
2. Create a new model endpoint with the same name and set it to `latest`.
|
|
768
|
+
|
|
763
769
|
"""
|
|
764
770
|
|
|
765
771
|
if not route and not class_name and not handler:
|
|
@@ -770,7 +776,9 @@ class RouterStep(TaskStep):
|
|
|
770
776
|
class_args,
|
|
771
777
|
handler=handler,
|
|
772
778
|
model_endpoint_creation_strategy=creation_strategy,
|
|
773
|
-
endpoint_type=schemas.EndpointType.
|
|
779
|
+
endpoint_type=schemas.EndpointType.LEAF_EP
|
|
780
|
+
if self.class_name and "serving.VotingEnsemble" in self.class_name
|
|
781
|
+
else schemas.EndpointType.NODE_EP,
|
|
774
782
|
)
|
|
775
783
|
route.function = function or route.function
|
|
776
784
|
|
mlrun/serving/v2_serving.py
CHANGED
|
@@ -558,7 +558,7 @@ class _ModelLogPusher:
|
|
|
558
558
|
def _init_endpoint_record(
|
|
559
559
|
graph_server: GraphServer,
|
|
560
560
|
model: V2ModelServer,
|
|
561
|
-
creation_strategy:
|
|
561
|
+
creation_strategy: mlrun.common.schemas.ModelEndpointCreationStrategy,
|
|
562
562
|
endpoint_type: mlrun.common.schemas.EndpointType,
|
|
563
563
|
) -> Union[str, None]:
|
|
564
564
|
"""
|
|
@@ -569,11 +569,16 @@ def _init_endpoint_record(
|
|
|
569
569
|
:param graph_server: A GraphServer object which will be used for getting the function uri.
|
|
570
570
|
:param model: Base model serving class (v2). It contains important details for the model endpoint record
|
|
571
571
|
such as model name, model path, and model version.
|
|
572
|
-
:param creation_strategy:
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
572
|
+
:param creation_strategy: Strategy for creating or updating the model endpoint:
|
|
573
|
+
* **overwrite**:
|
|
574
|
+
1. If model endpoints with the same name exist, delete the `latest` one.
|
|
575
|
+
2. Create a new model endpoint entry and set it as `latest`.
|
|
576
|
+
* **inplace** (default):
|
|
577
|
+
1. If model endpoints with the same name exist, update the `latest` entry.
|
|
578
|
+
2. Otherwise, create a new entry.
|
|
579
|
+
* **archive**:
|
|
580
|
+
1. If model endpoints with the same name exist, preserve them.
|
|
581
|
+
2. Create a new model endpoint with the same name and set it to `latest`.
|
|
577
582
|
:param endpoint_type model endpoint type
|
|
578
583
|
|
|
579
584
|
:return: Model endpoint unique ID.
|
|
@@ -57,7 +57,7 @@ class NotificationBase:
|
|
|
57
57
|
typing.Union[mlrun.common.schemas.NotificationSeverity, str]
|
|
58
58
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
59
59
|
runs: typing.Optional[typing.Union[mlrun.lists.RunList, list]] = None,
|
|
60
|
-
custom_html: typing.Optional[
|
|
60
|
+
custom_html: typing.Optional[str] = None,
|
|
61
61
|
alert: typing.Optional[mlrun.common.schemas.AlertConfig] = None,
|
|
62
62
|
event_data: typing.Optional[mlrun.common.schemas.Event] = None,
|
|
63
63
|
):
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import re
|
|
15
16
|
import typing
|
|
16
17
|
|
|
17
18
|
import aiohttp
|
|
@@ -93,7 +94,6 @@ class WebhookNotification(NotificationBase):
|
|
|
93
94
|
|
|
94
95
|
@staticmethod
|
|
95
96
|
def _serialize_runs_in_request_body(override_body, runs):
|
|
96
|
-
str_parsed_runs = ""
|
|
97
97
|
runs = runs or []
|
|
98
98
|
|
|
99
99
|
def parse_runs():
|
|
@@ -105,22 +105,23 @@ class WebhookNotification(NotificationBase):
|
|
|
105
105
|
parsed_run = {
|
|
106
106
|
"project": run["metadata"]["project"],
|
|
107
107
|
"name": run["metadata"]["name"],
|
|
108
|
-
"host": run["metadata"]["labels"]["host"],
|
|
109
108
|
"status": {"state": run["status"]["state"]},
|
|
110
109
|
}
|
|
111
|
-
if run["
|
|
112
|
-
parsed_run["
|
|
113
|
-
|
|
114
|
-
parsed_run["status"]["
|
|
110
|
+
if host := run["metadata"].get("labels", {}).get("host", ""):
|
|
111
|
+
parsed_run["host"] = host
|
|
112
|
+
if error := run["status"].get("error"):
|
|
113
|
+
parsed_run["status"]["error"] = error
|
|
114
|
+
elif results := run["status"].get("results"):
|
|
115
|
+
parsed_run["status"]["results"] = results
|
|
115
116
|
parsed_runs.append(parsed_run)
|
|
116
117
|
return str(parsed_runs)
|
|
117
118
|
|
|
118
119
|
if isinstance(override_body, dict):
|
|
119
120
|
for key, value in override_body.items():
|
|
120
|
-
if "{{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
if re.search(r"{{\s*runs\s*}}", value):
|
|
122
|
+
str_parsed_runs = parse_runs()
|
|
123
|
+
override_body[key] = re.sub(
|
|
124
|
+
r"{{\s*runs\s*}}", str_parsed_runs, value
|
|
125
|
+
)
|
|
126
|
+
|
|
126
127
|
return override_body
|