mlrun 1.10.0rc6__py3-none-any.whl → 1.10.0rc8__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 +3 -1
- mlrun/__main__.py +47 -4
- mlrun/artifacts/base.py +0 -27
- mlrun/artifacts/dataset.py +0 -8
- mlrun/artifacts/model.py +0 -7
- mlrun/artifacts/plots.py +0 -13
- mlrun/common/schemas/background_task.py +5 -0
- mlrun/common/schemas/model_monitoring/__init__.py +2 -0
- mlrun/common/schemas/model_monitoring/constants.py +16 -0
- mlrun/common/schemas/project.py +4 -0
- mlrun/common/schemas/serving.py +2 -0
- mlrun/config.py +11 -22
- mlrun/datastore/utils.py +3 -1
- mlrun/db/base.py +0 -19
- mlrun/db/httpdb.py +73 -65
- mlrun/db/nopdb.py +0 -12
- mlrun/frameworks/tf_keras/__init__.py +4 -4
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +23 -20
- mlrun/frameworks/tf_keras/model_handler.py +69 -9
- mlrun/frameworks/tf_keras/utils.py +12 -1
- mlrun/launcher/base.py +7 -0
- mlrun/launcher/client.py +2 -21
- mlrun/launcher/local.py +4 -0
- mlrun/model_monitoring/applications/_application_steps.py +23 -39
- mlrun/model_monitoring/applications/base.py +167 -32
- mlrun/model_monitoring/helpers.py +0 -3
- mlrun/projects/operations.py +11 -24
- mlrun/projects/pipelines.py +33 -3
- mlrun/projects/project.py +45 -89
- mlrun/run.py +37 -5
- mlrun/runtimes/daskjob.py +2 -0
- mlrun/runtimes/kubejob.py +5 -8
- mlrun/runtimes/mpijob/abstract.py +2 -0
- mlrun/runtimes/mpijob/v1.py +2 -0
- mlrun/runtimes/nuclio/function.py +2 -0
- mlrun/runtimes/nuclio/serving.py +60 -5
- mlrun/runtimes/pod.py +3 -0
- mlrun/runtimes/remotesparkjob.py +2 -0
- mlrun/runtimes/sparkjob/spark3job.py +2 -0
- mlrun/serving/__init__.py +2 -0
- mlrun/serving/server.py +253 -29
- mlrun/serving/states.py +215 -18
- mlrun/serving/system_steps.py +391 -0
- mlrun/serving/v2_serving.py +9 -8
- mlrun/utils/helpers.py +18 -4
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/METADATA +9 -9
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/RECORD +52 -51
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/WHEEL +0 -0
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc6.dist-info → mlrun-1.10.0rc8.dist-info}/top_level.txt +0 -0
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import collections
|
|
16
|
-
import json
|
|
17
16
|
import traceback
|
|
18
17
|
from collections import OrderedDict
|
|
19
18
|
from datetime import datetime
|
|
@@ -23,10 +22,12 @@ import mlrun.common.schemas
|
|
|
23
22
|
import mlrun.common.schemas.alert as alert_objects
|
|
24
23
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
25
24
|
import mlrun.model_monitoring.helpers
|
|
25
|
+
import mlrun.platforms.iguazio
|
|
26
26
|
from mlrun.serving import GraphContext
|
|
27
27
|
from mlrun.serving.utils import StepToDict
|
|
28
28
|
from mlrun.utils import logger
|
|
29
29
|
|
|
30
|
+
from .base import _serialize_context_and_result
|
|
30
31
|
from .context import MonitoringApplicationContext
|
|
31
32
|
from .results import (
|
|
32
33
|
ModelMonitoringApplicationMetric,
|
|
@@ -45,7 +46,7 @@ class _PushToMonitoringWriter(StepToDict):
|
|
|
45
46
|
:param project: Project name.
|
|
46
47
|
"""
|
|
47
48
|
self.project = project
|
|
48
|
-
self.
|
|
49
|
+
self._output_stream = None
|
|
49
50
|
|
|
50
51
|
def do(
|
|
51
52
|
self,
|
|
@@ -65,48 +66,31 @@ class _PushToMonitoringWriter(StepToDict):
|
|
|
65
66
|
|
|
66
67
|
:param event: Monitoring result(s) to push and the original event from the controller.
|
|
67
68
|
"""
|
|
68
|
-
self._lazy_init()
|
|
69
69
|
application_results, application_context = event
|
|
70
|
-
writer_event = {
|
|
71
|
-
mm_constants.WriterEvent.ENDPOINT_NAME: application_context.endpoint_name,
|
|
72
|
-
mm_constants.WriterEvent.APPLICATION_NAME: application_context.application_name,
|
|
73
|
-
mm_constants.WriterEvent.ENDPOINT_ID: application_context.endpoint_id,
|
|
74
|
-
mm_constants.WriterEvent.START_INFER_TIME: application_context.start_infer_time.isoformat(
|
|
75
|
-
sep=" ", timespec="microseconds"
|
|
76
|
-
),
|
|
77
|
-
mm_constants.WriterEvent.END_INFER_TIME: application_context.end_infer_time.isoformat(
|
|
78
|
-
sep=" ", timespec="microseconds"
|
|
79
|
-
),
|
|
80
|
-
}
|
|
81
|
-
for result in application_results:
|
|
82
|
-
data = result.to_dict()
|
|
83
|
-
if isinstance(result, ModelMonitoringApplicationResult):
|
|
84
|
-
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
85
|
-
mm_constants.WriterEventKind.RESULT
|
|
86
|
-
)
|
|
87
|
-
elif isinstance(result, _ModelMonitoringApplicationStats):
|
|
88
|
-
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
89
|
-
mm_constants.WriterEventKind.STATS
|
|
90
|
-
)
|
|
91
|
-
else:
|
|
92
|
-
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
93
|
-
mm_constants.WriterEventKind.METRIC
|
|
94
|
-
)
|
|
95
|
-
writer_event[mm_constants.WriterEvent.DATA] = json.dumps(data)
|
|
96
|
-
logger.debug(
|
|
97
|
-
"Pushing data to output stream", writer_event=str(writer_event)
|
|
98
|
-
)
|
|
99
|
-
self.output_stream.push(
|
|
100
|
-
[writer_event], partition_key=application_context.endpoint_id
|
|
101
|
-
)
|
|
102
|
-
logger.debug("Pushed data to output stream successfully")
|
|
103
70
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
71
|
+
writer_events = [
|
|
72
|
+
_serialize_context_and_result(context=application_context, result=result)
|
|
73
|
+
for result in application_results
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
logger.debug("Pushing data to output stream", writer_events=str(writer_events))
|
|
77
|
+
self.output_stream.push(
|
|
78
|
+
writer_events, partition_key=application_context.endpoint_id
|
|
79
|
+
)
|
|
80
|
+
logger.debug("Pushed data to output stream successfully")
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def output_stream(
|
|
84
|
+
self,
|
|
85
|
+
) -> Union[
|
|
86
|
+
mlrun.platforms.iguazio.OutputStream, mlrun.platforms.iguazio.KafkaOutputStream
|
|
87
|
+
]:
|
|
88
|
+
if self._output_stream is None:
|
|
89
|
+
self._output_stream = mlrun.model_monitoring.helpers.get_output_stream(
|
|
107
90
|
project=self.project,
|
|
108
91
|
function_name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
109
92
|
)
|
|
93
|
+
return self._output_stream
|
|
110
94
|
|
|
111
95
|
|
|
112
96
|
class _PrepareMonitoringEvent(StepToDict):
|
|
@@ -12,9 +12,12 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import json
|
|
15
16
|
import socket
|
|
16
17
|
from abc import ABC, abstractmethod
|
|
18
|
+
from collections import defaultdict
|
|
17
19
|
from collections.abc import Iterator
|
|
20
|
+
from contextlib import contextmanager
|
|
18
21
|
from datetime import datetime, timedelta
|
|
19
22
|
from typing import Any, Optional, Union, cast
|
|
20
23
|
|
|
@@ -23,14 +26,58 @@ import pandas as pd
|
|
|
23
26
|
import mlrun
|
|
24
27
|
import mlrun.common.constants as mlrun_constants
|
|
25
28
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
29
|
+
import mlrun.datastore.datastore_profile as ds_profile
|
|
26
30
|
import mlrun.errors
|
|
27
31
|
import mlrun.model_monitoring.api as mm_api
|
|
28
32
|
import mlrun.model_monitoring.applications.context as mm_context
|
|
29
33
|
import mlrun.model_monitoring.applications.results as mm_results
|
|
34
|
+
import mlrun.model_monitoring.helpers as mm_helpers
|
|
30
35
|
from mlrun.serving.utils import MonitoringApplicationToDict
|
|
31
36
|
from mlrun.utils import logger
|
|
32
37
|
|
|
33
38
|
|
|
39
|
+
def _serialize_context_and_result(
|
|
40
|
+
*,
|
|
41
|
+
context: mm_context.MonitoringApplicationContext,
|
|
42
|
+
result: Union[
|
|
43
|
+
mm_results.ModelMonitoringApplicationResult,
|
|
44
|
+
mm_results.ModelMonitoringApplicationMetric,
|
|
45
|
+
mm_results._ModelMonitoringApplicationStats,
|
|
46
|
+
],
|
|
47
|
+
) -> dict[mm_constants.WriterEvent, str]:
|
|
48
|
+
"""
|
|
49
|
+
Serialize the returned result from a model monitoring application and its context
|
|
50
|
+
for the writer.
|
|
51
|
+
"""
|
|
52
|
+
writer_event = {
|
|
53
|
+
mm_constants.WriterEvent.ENDPOINT_NAME: context.endpoint_name,
|
|
54
|
+
mm_constants.WriterEvent.APPLICATION_NAME: context.application_name,
|
|
55
|
+
mm_constants.WriterEvent.ENDPOINT_ID: context.endpoint_id,
|
|
56
|
+
mm_constants.WriterEvent.START_INFER_TIME: context.start_infer_time.isoformat(
|
|
57
|
+
sep=" ", timespec="microseconds"
|
|
58
|
+
),
|
|
59
|
+
mm_constants.WriterEvent.END_INFER_TIME: context.end_infer_time.isoformat(
|
|
60
|
+
sep=" ", timespec="microseconds"
|
|
61
|
+
),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if isinstance(result, mm_results.ModelMonitoringApplicationResult):
|
|
65
|
+
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
66
|
+
mm_constants.WriterEventKind.RESULT
|
|
67
|
+
)
|
|
68
|
+
elif isinstance(result, mm_results._ModelMonitoringApplicationStats):
|
|
69
|
+
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
70
|
+
mm_constants.WriterEventKind.STATS
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
|
|
74
|
+
mm_constants.WriterEventKind.METRIC
|
|
75
|
+
)
|
|
76
|
+
writer_event[mm_constants.WriterEvent.DATA] = json.dumps(result.to_dict())
|
|
77
|
+
|
|
78
|
+
return writer_event
|
|
79
|
+
|
|
80
|
+
|
|
34
81
|
class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
35
82
|
"""
|
|
36
83
|
The base class for a model monitoring application.
|
|
@@ -118,6 +165,43 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
118
165
|
]
|
|
119
166
|
return result
|
|
120
167
|
|
|
168
|
+
@staticmethod
|
|
169
|
+
@contextmanager
|
|
170
|
+
def _push_to_writer(
|
|
171
|
+
*,
|
|
172
|
+
write_output: bool,
|
|
173
|
+
stream_profile: Optional[ds_profile.DatastoreProfile],
|
|
174
|
+
) -> Iterator[dict[str, list[tuple]]]:
|
|
175
|
+
endpoints_output: dict[str, list[tuple]] = defaultdict(list)
|
|
176
|
+
try:
|
|
177
|
+
yield endpoints_output
|
|
178
|
+
finally:
|
|
179
|
+
if write_output:
|
|
180
|
+
logger.debug(
|
|
181
|
+
"Pushing model monitoring application job data to the writer stream",
|
|
182
|
+
passed_stream_profile=str(stream_profile),
|
|
183
|
+
)
|
|
184
|
+
project_name = (
|
|
185
|
+
mlrun.mlconf.active_project or mlrun.get_current_project().name
|
|
186
|
+
)
|
|
187
|
+
writer_stream = mm_helpers.get_output_stream(
|
|
188
|
+
project=project_name,
|
|
189
|
+
function_name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
190
|
+
profile=stream_profile,
|
|
191
|
+
)
|
|
192
|
+
for endpoint_id, outputs in endpoints_output.items():
|
|
193
|
+
writer_stream.push(
|
|
194
|
+
[
|
|
195
|
+
_serialize_context_and_result(context=ctx, result=res)
|
|
196
|
+
for ctx, res in outputs
|
|
197
|
+
],
|
|
198
|
+
partition_key=endpoint_id,
|
|
199
|
+
)
|
|
200
|
+
logger.debug(
|
|
201
|
+
"Pushed the data to all the relevant model endpoints successfully",
|
|
202
|
+
endpoints_output=endpoints_output,
|
|
203
|
+
)
|
|
204
|
+
|
|
121
205
|
def _handler(
|
|
122
206
|
self,
|
|
123
207
|
context: "mlrun.MLClientCtx",
|
|
@@ -127,6 +211,8 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
127
211
|
start: Optional[str] = None,
|
|
128
212
|
end: Optional[str] = None,
|
|
129
213
|
base_period: Optional[int] = None,
|
|
214
|
+
write_output: bool = False,
|
|
215
|
+
stream_profile: Optional[ds_profile.DatastoreProfile] = None,
|
|
130
216
|
):
|
|
131
217
|
"""
|
|
132
218
|
A custom handler that wraps the application's logic implemented in
|
|
@@ -134,46 +220,69 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
134
220
|
for an MLRun job.
|
|
135
221
|
This method should not be called directly.
|
|
136
222
|
"""
|
|
223
|
+
|
|
224
|
+
if write_output and (
|
|
225
|
+
not endpoints or sample_data is not None or reference_data is not None
|
|
226
|
+
):
|
|
227
|
+
raise mlrun.errors.MLRunValueError(
|
|
228
|
+
"Writing the results of an application to the TSDB is possible only when "
|
|
229
|
+
"working with endpoints, without any custom data-frame input"
|
|
230
|
+
)
|
|
231
|
+
|
|
137
232
|
feature_stats = (
|
|
138
233
|
mm_api.get_sample_set_statistics(reference_data)
|
|
139
234
|
if reference_data is not None
|
|
140
235
|
else None
|
|
141
236
|
)
|
|
142
237
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
for endpoint_name, endpoint_id in endpoints:
|
|
160
|
-
result = call_do_tracking(
|
|
161
|
-
event={
|
|
162
|
-
mm_constants.ApplicationEvent.ENDPOINT_NAME: endpoint_name,
|
|
163
|
-
mm_constants.ApplicationEvent.ENDPOINT_ID: endpoint_id,
|
|
164
|
-
mm_constants.ApplicationEvent.START_INFER_TIME: window_start,
|
|
165
|
-
mm_constants.ApplicationEvent.END_INFER_TIME: window_end,
|
|
166
|
-
}
|
|
167
|
-
)
|
|
168
|
-
result_key = (
|
|
169
|
-
f"{endpoint_name}-{endpoint_id}_{window_start.isoformat()}_{window_end.isoformat()}"
|
|
170
|
-
if window_start and window_end
|
|
171
|
-
else f"{endpoint_name}-{endpoint_id}"
|
|
238
|
+
with self._push_to_writer(
|
|
239
|
+
write_output=write_output, stream_profile=stream_profile
|
|
240
|
+
) as endpoints_output:
|
|
241
|
+
|
|
242
|
+
def call_do_tracking(event: Optional[dict] = None):
|
|
243
|
+
nonlocal endpoints_output
|
|
244
|
+
|
|
245
|
+
if event is None:
|
|
246
|
+
event = {}
|
|
247
|
+
monitoring_context = (
|
|
248
|
+
mm_context.MonitoringApplicationContext._from_ml_ctx(
|
|
249
|
+
event=event,
|
|
250
|
+
application_name=self.__class__.__name__,
|
|
251
|
+
context=context,
|
|
252
|
+
sample_df=sample_data,
|
|
253
|
+
feature_stats=feature_stats,
|
|
172
254
|
)
|
|
255
|
+
)
|
|
256
|
+
result = self.do_tracking(monitoring_context)
|
|
257
|
+
endpoints_output[monitoring_context.endpoint_id].append(
|
|
258
|
+
(monitoring_context, result)
|
|
259
|
+
)
|
|
260
|
+
return result
|
|
261
|
+
|
|
262
|
+
if endpoints is not None:
|
|
263
|
+
for window_start, window_end in self._window_generator(
|
|
264
|
+
start, end, base_period
|
|
265
|
+
):
|
|
266
|
+
for endpoint_name, endpoint_id in endpoints:
|
|
267
|
+
result = call_do_tracking(
|
|
268
|
+
event={
|
|
269
|
+
mm_constants.ApplicationEvent.ENDPOINT_NAME: endpoint_name,
|
|
270
|
+
mm_constants.ApplicationEvent.ENDPOINT_ID: endpoint_id,
|
|
271
|
+
mm_constants.ApplicationEvent.START_INFER_TIME: window_start,
|
|
272
|
+
mm_constants.ApplicationEvent.END_INFER_TIME: window_end,
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
result_key = (
|
|
276
|
+
f"{endpoint_name}-{endpoint_id}_{window_start.isoformat()}_{window_end.isoformat()}"
|
|
277
|
+
if window_start and window_end
|
|
278
|
+
else f"{endpoint_name}-{endpoint_id}"
|
|
279
|
+
)
|
|
173
280
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
281
|
+
context.log_result(
|
|
282
|
+
result_key, self._flatten_data_result(result)
|
|
283
|
+
)
|
|
284
|
+
else:
|
|
285
|
+
return self._flatten_data_result(call_do_tracking())
|
|
177
286
|
|
|
178
287
|
@staticmethod
|
|
179
288
|
def _handle_endpoints_type_evaluate(
|
|
@@ -338,6 +447,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
338
447
|
* ``start``, ``datetime``
|
|
339
448
|
* ``end``, ``datetime``
|
|
340
449
|
* ``base_period``, ``int``
|
|
450
|
+
* ``write_output``, ``bool``
|
|
341
451
|
|
|
342
452
|
For Git sources, add the source archive to the returned job and change the handler:
|
|
343
453
|
|
|
@@ -420,6 +530,8 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
420
530
|
start: Optional[datetime] = None,
|
|
421
531
|
end: Optional[datetime] = None,
|
|
422
532
|
base_period: Optional[int] = None,
|
|
533
|
+
write_output: bool = False,
|
|
534
|
+
stream_profile: Optional[ds_profile.DatastoreProfile] = None,
|
|
423
535
|
) -> "mlrun.RunObject":
|
|
424
536
|
"""
|
|
425
537
|
Call this function to run the application's
|
|
@@ -470,6 +582,14 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
470
582
|
..., (\\operatorname{start} +
|
|
471
583
|
m\\cdot\\operatorname{base\\_period}, \\operatorname{end}]`,
|
|
472
584
|
where :math:`m` is some positive integer.
|
|
585
|
+
:param write_output: Whether to write the results and metrics to the time-series DB. Can be ``True`` only
|
|
586
|
+
if ``endpoints`` are passed.
|
|
587
|
+
Note: the model monitoring infrastructure must be up for the writing to work.
|
|
588
|
+
:param stream_profile: The stream datastore profile. It should be provided only when running locally and
|
|
589
|
+
writing the outputs to the database (i.e., when both ``run_local`` and
|
|
590
|
+
``write_output`` are set to ``True``).
|
|
591
|
+
For more details on configuring the stream profile, see
|
|
592
|
+
:py:meth:`~mlrun.projects.MlrunProject.set_model_monitoring_credentials`.
|
|
473
593
|
|
|
474
594
|
:returns: The output of the
|
|
475
595
|
:py:meth:`~mlrun.model_monitoring.applications.ModelMonitoringApplicationBase.do_tracking`
|
|
@@ -507,10 +627,25 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
507
627
|
)
|
|
508
628
|
params["end"] = end.isoformat() if isinstance(end, datetime) else end
|
|
509
629
|
params["base_period"] = base_period
|
|
630
|
+
params["write_output"] = write_output
|
|
631
|
+
if stream_profile:
|
|
632
|
+
if not run_local:
|
|
633
|
+
raise mlrun.errors.MLRunValueError(
|
|
634
|
+
"Passing a `stream_profile` is relevant only when running locally"
|
|
635
|
+
)
|
|
636
|
+
if not write_output:
|
|
637
|
+
raise mlrun.errors.MLRunValueError(
|
|
638
|
+
"Passing a `stream_profile` is relevant only when writing the outputs"
|
|
639
|
+
)
|
|
640
|
+
params["stream_profile"] = stream_profile
|
|
510
641
|
elif start or end or base_period:
|
|
511
642
|
raise mlrun.errors.MLRunValueError(
|
|
512
643
|
"Custom `start` and `end` times or base_period are supported only with endpoints data"
|
|
513
644
|
)
|
|
645
|
+
elif write_output or stream_profile:
|
|
646
|
+
raise mlrun.errors.MLRunValueError(
|
|
647
|
+
"Writing the application output or passing `stream_profile` are supported only with endpoints data"
|
|
648
|
+
)
|
|
514
649
|
|
|
515
650
|
inputs: dict[str, str] = {}
|
|
516
651
|
for data, identifier in [
|
|
@@ -22,14 +22,11 @@ import numpy as np
|
|
|
22
22
|
import pandas as pd
|
|
23
23
|
|
|
24
24
|
import mlrun
|
|
25
|
-
import mlrun.artifacts
|
|
26
25
|
import mlrun.common.model_monitoring.helpers
|
|
27
26
|
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
28
27
|
import mlrun.data_types.infer
|
|
29
28
|
import mlrun.datastore.datastore_profile
|
|
30
|
-
import mlrun.model_monitoring
|
|
31
29
|
import mlrun.platforms.iguazio
|
|
32
|
-
import mlrun.utils.helpers
|
|
33
30
|
from mlrun.common.schemas import ModelEndpoint
|
|
34
31
|
from mlrun.common.schemas.model_monitoring.model_endpoints import (
|
|
35
32
|
ModelEndpointMonitoringMetric,
|
mlrun/projects/operations.py
CHANGED
|
@@ -281,7 +281,7 @@ def build_function(
|
|
|
281
281
|
mlrun_version_specifier=None,
|
|
282
282
|
builder_env: Optional[dict] = None,
|
|
283
283
|
project_object=None,
|
|
284
|
-
overwrite_build_params: bool =
|
|
284
|
+
overwrite_build_params: bool = True,
|
|
285
285
|
extra_args: Optional[str] = None,
|
|
286
286
|
force_build: bool = False,
|
|
287
287
|
) -> Union[BuildStatus, mlrun_pipelines.models.PipelineNodeWrapper]:
|
|
@@ -308,13 +308,6 @@ def build_function(
|
|
|
308
308
|
e.g. extra_args="--skip-tls-verify --build-arg A=val"
|
|
309
309
|
:param force_build: Force building the image, even when no changes were made
|
|
310
310
|
"""
|
|
311
|
-
if not overwrite_build_params:
|
|
312
|
-
# TODO: change overwrite_build_params default to True in 1.10.0
|
|
313
|
-
warnings.warn(
|
|
314
|
-
"The `overwrite_build_params` parameter default will change from 'False' to 'True' in 1.10.0.",
|
|
315
|
-
mlrun.utils.OverwriteBuildParamsWarning,
|
|
316
|
-
)
|
|
317
|
-
|
|
318
311
|
engine, function = _get_engine_and_function(function, project_object)
|
|
319
312
|
if function.kind in mlrun.runtimes.RuntimeKinds.nuclio_runtimes():
|
|
320
313
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
@@ -340,22 +333,16 @@ def build_function(
|
|
|
340
333
|
skip_deployed=skip_deployed,
|
|
341
334
|
)
|
|
342
335
|
else:
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
secret=secret_name,
|
|
354
|
-
requirements=requirements,
|
|
355
|
-
requirements_file=requirements_file,
|
|
356
|
-
overwrite=overwrite_build_params,
|
|
357
|
-
extra_args=extra_args,
|
|
358
|
-
)
|
|
336
|
+
function.build_config(
|
|
337
|
+
image=image,
|
|
338
|
+
base_image=base_image,
|
|
339
|
+
commands=commands,
|
|
340
|
+
secret=secret_name,
|
|
341
|
+
requirements=requirements,
|
|
342
|
+
requirements_file=requirements_file,
|
|
343
|
+
overwrite=overwrite_build_params,
|
|
344
|
+
extra_args=extra_args,
|
|
345
|
+
)
|
|
359
346
|
ready = function.deploy(
|
|
360
347
|
watch=True,
|
|
361
348
|
with_mlrun=with_mlrun,
|
mlrun/projects/pipelines.py
CHANGED
|
@@ -39,7 +39,12 @@ from mlrun.utils import (
|
|
|
39
39
|
|
|
40
40
|
from ..common.helpers import parse_versioned_object_uri
|
|
41
41
|
from ..config import config
|
|
42
|
-
from ..run import
|
|
42
|
+
from ..run import (
|
|
43
|
+
_run_pipeline,
|
|
44
|
+
retry_pipeline,
|
|
45
|
+
terminate_pipeline,
|
|
46
|
+
wait_for_pipeline_completion,
|
|
47
|
+
)
|
|
43
48
|
from ..runtimes.pod import AutoMountType
|
|
44
49
|
|
|
45
50
|
|
|
@@ -696,6 +701,24 @@ class _KFPRunner(_PipelineRunner):
|
|
|
696
701
|
)
|
|
697
702
|
return run_id
|
|
698
703
|
|
|
704
|
+
@classmethod
|
|
705
|
+
def terminate(
|
|
706
|
+
cls,
|
|
707
|
+
run: "_PipelineRunStatus",
|
|
708
|
+
project: typing.Optional["mlrun.projects.MlrunProject"] = None,
|
|
709
|
+
) -> str:
|
|
710
|
+
project_name = project.metadata.name if project else ""
|
|
711
|
+
logger.info(
|
|
712
|
+
"Terminating pipeline",
|
|
713
|
+
run_id=run.run_id,
|
|
714
|
+
project=project_name,
|
|
715
|
+
)
|
|
716
|
+
run_id = terminate_pipeline(
|
|
717
|
+
run.run_id,
|
|
718
|
+
project=project_name,
|
|
719
|
+
)
|
|
720
|
+
return run_id
|
|
721
|
+
|
|
699
722
|
@staticmethod
|
|
700
723
|
def wait_for_completion(
|
|
701
724
|
run: "_PipelineRunStatus",
|
|
@@ -1145,7 +1168,9 @@ def load_and_run_workflow(
|
|
|
1145
1168
|
notification.when = ["running"]
|
|
1146
1169
|
|
|
1147
1170
|
workflow_log_message = workflow_name or workflow_path
|
|
1148
|
-
context.logger.info(
|
|
1171
|
+
context.logger.info(
|
|
1172
|
+
"Running workflow from remote", workflow_log_message=workflow_log_message
|
|
1173
|
+
)
|
|
1149
1174
|
run = project.run(
|
|
1150
1175
|
name=workflow_name,
|
|
1151
1176
|
workflow_path=workflow_path,
|
|
@@ -1162,6 +1187,11 @@ def load_and_run_workflow(
|
|
|
1162
1187
|
notifications=start_notifications,
|
|
1163
1188
|
context=context,
|
|
1164
1189
|
)
|
|
1190
|
+
# Patch the current run object (the workflow-runner) with the workflow-id label
|
|
1191
|
+
context.logger.info(
|
|
1192
|
+
"Associating workflow-runner with workflow ID", run_id=run.run_id
|
|
1193
|
+
)
|
|
1194
|
+
context.set_label("workflow-id", run.run_id)
|
|
1165
1195
|
context.log_result(key="workflow_id", value=run.run_id)
|
|
1166
1196
|
context.log_result(key="engine", value=run._engine.engine, commit=True)
|
|
1167
1197
|
|
|
@@ -1321,4 +1351,4 @@ def import_remote_project(
|
|
|
1321
1351
|
sync_functions=True,
|
|
1322
1352
|
)
|
|
1323
1353
|
|
|
1324
|
-
context.logger.info(
|
|
1354
|
+
context.logger.info("Loaded project successfully", project_name=project.name)
|