mlrun 1.5.0rc11__py3-none-any.whl → 1.5.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/__main__.py +31 -2
- mlrun/api/api/endpoints/functions.py +110 -52
- mlrun/api/api/endpoints/model_endpoints.py +0 -56
- mlrun/api/crud/model_monitoring/deployment.py +208 -38
- mlrun/api/crud/model_monitoring/helpers.py +19 -6
- mlrun/api/crud/model_monitoring/model_endpoints.py +14 -31
- mlrun/api/db/sqldb/db.py +3 -1
- mlrun/api/utils/builder.py +2 -4
- mlrun/common/model_monitoring/helpers.py +19 -5
- mlrun/common/schemas/model_monitoring/constants.py +69 -0
- mlrun/common/schemas/model_monitoring/model_endpoints.py +22 -1
- mlrun/config.py +30 -12
- mlrun/datastore/__init__.py +1 -0
- mlrun/datastore/datastore_profile.py +2 -2
- mlrun/datastore/sources.py +4 -30
- mlrun/datastore/targets.py +106 -55
- mlrun/db/httpdb.py +20 -6
- mlrun/feature_store/__init__.py +2 -0
- mlrun/feature_store/api.py +3 -31
- mlrun/feature_store/feature_vector.py +1 -1
- mlrun/feature_store/retrieval/base.py +8 -3
- mlrun/launcher/remote.py +3 -3
- mlrun/lists.py +11 -0
- mlrun/model_monitoring/__init__.py +0 -1
- mlrun/model_monitoring/api.py +1 -1
- mlrun/model_monitoring/application.py +313 -0
- mlrun/model_monitoring/batch_application.py +526 -0
- mlrun/model_monitoring/batch_application_handler.py +32 -0
- mlrun/model_monitoring/evidently_application.py +89 -0
- mlrun/model_monitoring/helpers.py +39 -3
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +38 -7
- mlrun/model_monitoring/tracking_policy.py +4 -4
- mlrun/model_monitoring/writer.py +37 -0
- mlrun/projects/pipelines.py +38 -4
- mlrun/projects/project.py +257 -43
- mlrun/run.py +5 -2
- mlrun/runtimes/__init__.py +2 -0
- mlrun/runtimes/function.py +2 -1
- mlrun/utils/helpers.py +12 -0
- mlrun/utils/http.py +3 -0
- mlrun/utils/notifications/notification_pusher.py +22 -8
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/METADATA +5 -5
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/RECORD +49 -44
- /mlrun/model_monitoring/{model_monitoring_batch.py → batch.py} +0 -0
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/LICENSE +0 -0
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/WHEEL +0 -0
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/entry_points.txt +0 -0
- {mlrun-1.5.0rc11.dist-info → mlrun-1.5.0rc13.dist-info}/top_level.txt +0 -0
|
@@ -25,21 +25,27 @@ import mlrun.api.utils.scheduler
|
|
|
25
25
|
import mlrun.api.utils.singletons.db
|
|
26
26
|
import mlrun.api.utils.singletons.k8s
|
|
27
27
|
import mlrun.common.schemas.model_monitoring
|
|
28
|
+
import mlrun.common.schemas.model_monitoring.constants as mm_constants
|
|
28
29
|
import mlrun.model_monitoring.stream_processing
|
|
29
30
|
import mlrun.model_monitoring.tracking_policy
|
|
30
31
|
from mlrun import feature_store as fstore
|
|
31
32
|
from mlrun.api.api import deps
|
|
32
33
|
from mlrun.api.crud.model_monitoring.helpers import Seconds, seconds2minutes
|
|
34
|
+
from mlrun.model_monitoring.writer import ModelMonitoringWriter
|
|
33
35
|
from mlrun.utils import logger
|
|
34
36
|
|
|
35
37
|
_MODEL_MONITORING_COMMON_PATH = pathlib.Path(__file__).parents[3] / "model_monitoring"
|
|
36
38
|
_STREAM_PROCESSING_FUNCTION_PATH = (
|
|
37
39
|
_MODEL_MONITORING_COMMON_PATH / "stream_processing.py"
|
|
38
40
|
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
_MONITORING_ORIGINAL_BATCH_FUNCTION_PATH = _MODEL_MONITORING_COMMON_PATH / "batch.py"
|
|
42
|
+
|
|
43
|
+
_MONITORING_APPLICATION_BATCH_FUNCTION_PATH = (
|
|
44
|
+
_MODEL_MONITORING_COMMON_PATH / "batch_application_handler.py"
|
|
41
45
|
)
|
|
42
46
|
|
|
47
|
+
_MONITORING_WRITER_FUNCTION_PATH = _MODEL_MONITORING_COMMON_PATH / "writer.py"
|
|
48
|
+
|
|
43
49
|
|
|
44
50
|
class MonitoringDeployment:
|
|
45
51
|
def __init__(
|
|
@@ -50,8 +56,11 @@ class MonitoringDeployment:
|
|
|
50
56
|
self._parquet_batching_max_events = parquet_batching_max_events
|
|
51
57
|
self._max_parquet_save_interval = max_parquet_save_interval
|
|
52
58
|
"""
|
|
53
|
-
Initialize a MonitoringDeployment object, which handles the deployment
|
|
54
|
-
|
|
59
|
+
Initialize a MonitoringDeployment object, which handles the deployment & scheduling of:
|
|
60
|
+
1. model monitoring stream
|
|
61
|
+
2. model monitoring batch
|
|
62
|
+
3. model monitoring batch application
|
|
63
|
+
4. model monitoring writer
|
|
55
64
|
|
|
56
65
|
:param parquet_batching_max_events: Maximum number of events that will be used for writing the monitoring
|
|
57
66
|
parquet by the monitoring stream function.
|
|
@@ -91,7 +100,25 @@ class MonitoringDeployment:
|
|
|
91
100
|
auth_info=auth_info,
|
|
92
101
|
tracking_policy=tracking_policy,
|
|
93
102
|
tracking_offset=Seconds(self._max_parquet_save_interval),
|
|
103
|
+
function_name=mm_constants.MonitoringFunctionNames.BATCH,
|
|
94
104
|
)
|
|
105
|
+
if tracking_policy.application_batch:
|
|
106
|
+
self.deploy_model_monitoring_batch_processing(
|
|
107
|
+
project=project,
|
|
108
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
109
|
+
db_session=db_session,
|
|
110
|
+
auth_info=auth_info,
|
|
111
|
+
tracking_policy=tracking_policy,
|
|
112
|
+
tracking_offset=Seconds(self._max_parquet_save_interval),
|
|
113
|
+
function_name=mm_constants.MonitoringFunctionNames.BATCH_APPLICATION,
|
|
114
|
+
)
|
|
115
|
+
self.deploy_model_monitoring_writer_application(
|
|
116
|
+
project=project,
|
|
117
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
118
|
+
db_session=db_session,
|
|
119
|
+
auth_info=auth_info,
|
|
120
|
+
tracking_policy=tracking_policy,
|
|
121
|
+
)
|
|
95
122
|
|
|
96
123
|
def deploy_model_monitoring_stream_processing(
|
|
97
124
|
self,
|
|
@@ -154,7 +181,9 @@ class MonitoringDeployment:
|
|
|
154
181
|
fn.metadata.labels = {"type": "model-monitoring-stream"}
|
|
155
182
|
|
|
156
183
|
mlrun.api.api.endpoints.functions._build_function(
|
|
157
|
-
db_session=db_session,
|
|
184
|
+
db_session=db_session,
|
|
185
|
+
auth_info=auth_info,
|
|
186
|
+
function=fn,
|
|
158
187
|
)
|
|
159
188
|
|
|
160
189
|
def deploy_model_monitoring_batch_processing(
|
|
@@ -167,12 +196,14 @@ class MonitoringDeployment:
|
|
|
167
196
|
with_schedule: bool = True,
|
|
168
197
|
overwrite: bool = False,
|
|
169
198
|
tracking_offset: Seconds = Seconds(0),
|
|
199
|
+
function_name: str = mm_constants.MonitoringFunctionNames.BATCH,
|
|
170
200
|
) -> typing.Union[mlrun.runtimes.kubejob.KubejobRuntime, None]:
|
|
171
201
|
"""
|
|
172
|
-
Deploying model monitoring batch job
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
202
|
+
Deploying model monitoring batch job or model monitoring batch application job.
|
|
203
|
+
The goal of this job is to identify drift in the data based on the latest batch of events. By default,
|
|
204
|
+
this job is executed on the hour every hour.
|
|
205
|
+
Note that if this job was already deployed then you will either have to pass overwrite=True or
|
|
206
|
+
to delete the old job before deploying a new one.
|
|
176
207
|
|
|
177
208
|
:param project: The name of the project.
|
|
178
209
|
:param model_monitoring_access_key: Access key to apply the model monitoring process.
|
|
@@ -182,14 +213,23 @@ class MonitoringDeployment:
|
|
|
182
213
|
:param with_schedule: If true, submit a scheduled batch drift job.
|
|
183
214
|
:param overwrite: If true, overwrite the existing model monitoring batch job.
|
|
184
215
|
:param tracking_offset: Offset for the tracking policy (for synchronization with the stream)
|
|
216
|
+
:param function_name: model-monitoring-batch or model-monitoring-application-batch
|
|
217
|
+
indicates witch one to deploy.
|
|
185
218
|
|
|
186
219
|
:return: Model monitoring batch job as a runtime function.
|
|
187
220
|
"""
|
|
188
|
-
|
|
221
|
+
job_valid_names = [
|
|
222
|
+
mm_constants.MonitoringFunctionNames.BATCH,
|
|
223
|
+
mm_constants.MonitoringFunctionNames.BATCH_APPLICATION,
|
|
224
|
+
]
|
|
225
|
+
if function_name not in job_valid_names:
|
|
226
|
+
raise mlrun.errors.MLRunRuntimeError(
|
|
227
|
+
f"Model Monitoring batch job can be only within {job_valid_names}"
|
|
228
|
+
)
|
|
189
229
|
fn = None
|
|
190
230
|
if not overwrite:
|
|
191
231
|
logger.info(
|
|
192
|
-
"Checking if
|
|
232
|
+
f"Checking if {function_name.replace('-',' ')} processing function is already deployed",
|
|
193
233
|
project=project,
|
|
194
234
|
)
|
|
195
235
|
|
|
@@ -198,17 +238,18 @@ class MonitoringDeployment:
|
|
|
198
238
|
try:
|
|
199
239
|
fn = mlrun.api.crud.Functions().get_function(
|
|
200
240
|
db_session=db_session,
|
|
201
|
-
name=
|
|
241
|
+
name=function_name,
|
|
202
242
|
project=project,
|
|
203
243
|
)
|
|
204
244
|
logger.info(
|
|
205
|
-
"Detected
|
|
245
|
+
f"Detected {function_name.replace('-',' ')} processing function already deployed",
|
|
206
246
|
project=project,
|
|
207
247
|
)
|
|
208
248
|
|
|
209
249
|
except mlrun.errors.MLRunNotFoundError:
|
|
210
250
|
logger.info(
|
|
211
|
-
"Deploying
|
|
251
|
+
f"Deploying {function_name.replace('-',' ')} processing function ",
|
|
252
|
+
project=project,
|
|
212
253
|
)
|
|
213
254
|
|
|
214
255
|
if not fn:
|
|
@@ -219,6 +260,7 @@ class MonitoringDeployment:
|
|
|
219
260
|
db_session=db_session,
|
|
220
261
|
auth_info=auth_info,
|
|
221
262
|
tracking_policy=tracking_policy,
|
|
263
|
+
function_name=function_name,
|
|
222
264
|
)
|
|
223
265
|
|
|
224
266
|
# Get the function uri
|
|
@@ -230,16 +272,16 @@ class MonitoringDeployment:
|
|
|
230
272
|
mlrun.api.utils.scheduler.Scheduler().get_schedule(
|
|
231
273
|
db_session=db_session,
|
|
232
274
|
project=project,
|
|
233
|
-
name=
|
|
275
|
+
name=function_name,
|
|
234
276
|
)
|
|
235
277
|
logger.info(
|
|
236
|
-
"Already deployed
|
|
278
|
+
f"Already deployed {function_name.replace('-',' ')} scheduled job function ",
|
|
237
279
|
project=project,
|
|
238
280
|
)
|
|
239
281
|
return
|
|
240
282
|
except mlrun.errors.MLRunNotFoundError:
|
|
241
283
|
logger.info(
|
|
242
|
-
"Deploying
|
|
284
|
+
f"Deploying {function_name.replace('-',' ')} scheduled job function ",
|
|
243
285
|
project=project,
|
|
244
286
|
)
|
|
245
287
|
# Submit batch scheduled job
|
|
@@ -250,9 +292,68 @@ class MonitoringDeployment:
|
|
|
250
292
|
auth_info=auth_info,
|
|
251
293
|
tracking_policy=tracking_policy,
|
|
252
294
|
tracking_offset=tracking_offset,
|
|
295
|
+
function_name=function_name,
|
|
253
296
|
)
|
|
254
297
|
return fn
|
|
255
298
|
|
|
299
|
+
def deploy_model_monitoring_writer_application(
|
|
300
|
+
self,
|
|
301
|
+
project,
|
|
302
|
+
model_monitoring_access_key,
|
|
303
|
+
db_session,
|
|
304
|
+
auth_info,
|
|
305
|
+
tracking_policy,
|
|
306
|
+
):
|
|
307
|
+
"""
|
|
308
|
+
Deploying model monitoring writer real time nuclio function. The goal of this real time function is
|
|
309
|
+
to write all the monitoring application result to the databases. It is triggered by those applications.
|
|
310
|
+
It processes and writes the result to the databases.
|
|
311
|
+
|
|
312
|
+
:param project: The name of the project.
|
|
313
|
+
:param model_monitoring_access_key: Access key to apply the model monitoring process.
|
|
314
|
+
:param db_session: A session that manages the current dialog with the database.
|
|
315
|
+
:param auth_info: The auth info of the request.
|
|
316
|
+
:param tracking_policy: Model monitoring configurations.
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
logger.info(
|
|
320
|
+
"Checking if model monitoring writer is already deployed",
|
|
321
|
+
project=project,
|
|
322
|
+
)
|
|
323
|
+
try:
|
|
324
|
+
# validate that the model monitoring stream has not yet been deployed
|
|
325
|
+
mlrun.runtimes.function.get_nuclio_deploy_status(
|
|
326
|
+
name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
327
|
+
project=project,
|
|
328
|
+
tag="",
|
|
329
|
+
auth_info=auth_info,
|
|
330
|
+
)
|
|
331
|
+
logger.info(
|
|
332
|
+
"Detected model monitoring writer processing function already deployed",
|
|
333
|
+
project=project,
|
|
334
|
+
)
|
|
335
|
+
return
|
|
336
|
+
except mlrun.errors.MLRunNotFoundError:
|
|
337
|
+
logger.info(
|
|
338
|
+
"Deploying model monitoring writer processing function", project=project
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
fn = self._initial_model_monitoring_writer_function(
|
|
342
|
+
project=project,
|
|
343
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
344
|
+
tracking_policy=tracking_policy,
|
|
345
|
+
auth_info=auth_info,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Adding label to the function - will be used to identify the stream pod
|
|
349
|
+
fn.metadata.labels = {"type": "model-monitoring-writer"}
|
|
350
|
+
|
|
351
|
+
mlrun.api.api.endpoints.functions._build_function(
|
|
352
|
+
db_session=db_session,
|
|
353
|
+
auth_info=auth_info,
|
|
354
|
+
function=fn,
|
|
355
|
+
)
|
|
356
|
+
|
|
256
357
|
def _initial_model_monitoring_stream_processing_function(
|
|
257
358
|
self,
|
|
258
359
|
project: str,
|
|
@@ -323,6 +424,7 @@ class MonitoringDeployment:
|
|
|
323
424
|
db_session: sqlalchemy.orm.Session,
|
|
324
425
|
auth_info: mlrun.common.schemas.AuthInfo,
|
|
325
426
|
tracking_policy: mlrun.model_monitoring.tracking_policy.TrackingPolicy,
|
|
427
|
+
function_name: str = "model-monitoring-batch",
|
|
326
428
|
):
|
|
327
429
|
"""
|
|
328
430
|
Initialize model monitoring batch function.
|
|
@@ -333,16 +435,21 @@ class MonitoringDeployment:
|
|
|
333
435
|
:param db_session: A session that manages the current dialog with the database.
|
|
334
436
|
:param auth_info: The auth info of the request.
|
|
335
437
|
:param tracking_policy: Model monitoring configurations.
|
|
336
|
-
|
|
438
|
+
:param function_name: model-monitoring-batch or model-monitoring-application-batch
|
|
439
|
+
indicates witch one to create.
|
|
337
440
|
:return: A function object from a mlrun runtime class
|
|
338
441
|
|
|
339
442
|
"""
|
|
340
|
-
|
|
443
|
+
filename = (
|
|
444
|
+
str(_MONITORING_ORIGINAL_BATCH_FUNCTION_PATH)
|
|
445
|
+
if function_name == "model-monitoring-batch"
|
|
446
|
+
else str(_MONITORING_APPLICATION_BATCH_FUNCTION_PATH)
|
|
447
|
+
)
|
|
341
448
|
# Create job function runtime for the model monitoring batch
|
|
342
449
|
function: mlrun.runtimes.KubejobRuntime = mlrun.code_to_function(
|
|
343
|
-
name=
|
|
450
|
+
name=function_name,
|
|
344
451
|
project=project,
|
|
345
|
-
filename=
|
|
452
|
+
filename=filename,
|
|
346
453
|
kind="job",
|
|
347
454
|
image=tracking_policy.default_batch_image,
|
|
348
455
|
handler="handler",
|
|
@@ -358,6 +465,7 @@ class MonitoringDeployment:
|
|
|
358
465
|
function=function,
|
|
359
466
|
model_monitoring_access_key=model_monitoring_access_key,
|
|
360
467
|
auth_info=auth_info,
|
|
468
|
+
function_name=function_name,
|
|
361
469
|
)
|
|
362
470
|
|
|
363
471
|
# Enrich runtime with the required configurations
|
|
@@ -375,6 +483,7 @@ class MonitoringDeployment:
|
|
|
375
483
|
auth_info: mlrun.common.schemas.AuthInfo,
|
|
376
484
|
tracking_policy: mlrun.model_monitoring.tracking_policy.TrackingPolicy,
|
|
377
485
|
tracking_offset: Seconds = Seconds(0),
|
|
486
|
+
function_name: str = "model-monitoring-batch",
|
|
378
487
|
):
|
|
379
488
|
"""
|
|
380
489
|
Create a new scheduled monitoring batch job analysis based on the model-monitoring-batch function that has
|
|
@@ -392,7 +501,7 @@ class MonitoringDeployment:
|
|
|
392
501
|
|
|
393
502
|
function_uri = function_uri.replace("db://", "")
|
|
394
503
|
|
|
395
|
-
task = mlrun.new_task(name=
|
|
504
|
+
task = mlrun.new_task(name=function_name, project=project)
|
|
396
505
|
task.spec.function = function_uri
|
|
397
506
|
|
|
398
507
|
# Apply batching interval params
|
|
@@ -423,7 +532,8 @@ class MonitoringDeployment:
|
|
|
423
532
|
}
|
|
424
533
|
|
|
425
534
|
logger.info(
|
|
426
|
-
"Deploying
|
|
535
|
+
f"Deploying {function_name.replace('-',' ')} processing function",
|
|
536
|
+
project=project,
|
|
427
537
|
)
|
|
428
538
|
|
|
429
539
|
# Add job schedule policy (every hour by default)
|
|
@@ -437,6 +547,7 @@ class MonitoringDeployment:
|
|
|
437
547
|
function: mlrun.runtimes.ServingRuntime,
|
|
438
548
|
model_monitoring_access_key: str = None,
|
|
439
549
|
auth_info: mlrun.common.schemas.AuthInfo = Depends(deps.authenticate_request),
|
|
550
|
+
function_name: str = None,
|
|
440
551
|
) -> mlrun.runtimes.ServingRuntime:
|
|
441
552
|
"""Adding stream source for the nuclio serving function. By default, the function has HTTP stream trigger along
|
|
442
553
|
with another supported stream source that can be either Kafka or V3IO, depends on the stream path schema that is
|
|
@@ -448,13 +559,17 @@ class MonitoringDeployment:
|
|
|
448
559
|
:param model_monitoring_access_key: Access key to apply the model monitoring stream function when the stream is
|
|
449
560
|
schema is V3IO.
|
|
450
561
|
:param auth_info: The auth info of the request.
|
|
562
|
+
:param function_name: the name of the function that be applied with the stream trigger,
|
|
563
|
+
None for model_monitoring_stream
|
|
451
564
|
|
|
452
565
|
:return: ServingRuntime object with stream trigger.
|
|
453
566
|
"""
|
|
454
567
|
|
|
455
568
|
# Get the stream path from the configuration
|
|
456
569
|
# stream_path = mlrun.mlconf.get_file_target_path(project=project, kind="stream", target="stream")
|
|
457
|
-
stream_path = mlrun.api.crud.model_monitoring.get_stream_path(
|
|
570
|
+
stream_path = mlrun.api.crud.model_monitoring.get_stream_path(
|
|
571
|
+
project=project, application_name=function_name
|
|
572
|
+
)
|
|
458
573
|
|
|
459
574
|
if stream_path.startswith("kafka://"):
|
|
460
575
|
topic, brokers = mlrun.datastore.utils.parse_kafka_url(url=stream_path)
|
|
@@ -471,11 +586,18 @@ class MonitoringDeployment:
|
|
|
471
586
|
function=function,
|
|
472
587
|
model_monitoring_access_key=model_monitoring_access_key,
|
|
473
588
|
auth_info=auth_info,
|
|
589
|
+
function_name=function_name,
|
|
474
590
|
)
|
|
475
591
|
if stream_path.startswith("v3io://"):
|
|
476
592
|
# Generate V3IO stream trigger
|
|
477
593
|
function.add_v3io_stream_trigger(
|
|
478
|
-
stream_path=stream_path,
|
|
594
|
+
stream_path=stream_path,
|
|
595
|
+
name="monitoring_stream_trigger"
|
|
596
|
+
if function_name is None
|
|
597
|
+
else f"monitoring_{function_name}_trigger",
|
|
598
|
+
access_key=model_monitoring_access_key
|
|
599
|
+
if function_name != mm_constants.MonitoringFunctionNames.STREAM
|
|
600
|
+
else None,
|
|
479
601
|
)
|
|
480
602
|
# Add the default HTTP source
|
|
481
603
|
http_source = mlrun.datastore.sources.HttpSource()
|
|
@@ -491,6 +613,7 @@ class MonitoringDeployment:
|
|
|
491
613
|
],
|
|
492
614
|
model_monitoring_access_key: str,
|
|
493
615
|
auth_info: mlrun.common.schemas.AuthInfo,
|
|
616
|
+
function_name: str = None,
|
|
494
617
|
) -> typing.Union[mlrun.runtimes.KubejobRuntime, mlrun.runtimes.ServingRuntime]:
|
|
495
618
|
"""Applying model monitoring access key on the provided function when using V3IO path. In addition, this method
|
|
496
619
|
mount the V3IO path for the provided function to configure the access to the system files.
|
|
@@ -505,23 +628,70 @@ class MonitoringDeployment:
|
|
|
505
628
|
:return: function runtime object with access key and access to system files.
|
|
506
629
|
"""
|
|
507
630
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_name(
|
|
512
|
-
project
|
|
513
|
-
),
|
|
514
|
-
mlrun.api.crud.secrets.Secrets().generate_client_project_secret_key(
|
|
515
|
-
mlrun.api.crud.secrets.SecretsClientType.model_monitoring,
|
|
631
|
+
if function_name in mm_constants.MonitoringFunctionNames.all():
|
|
632
|
+
# Set model monitoring access key for managing permissions
|
|
633
|
+
function.set_env_from_secret(
|
|
516
634
|
mlrun.common.schemas.model_monitoring.ProjectSecretKeys.ACCESS_KEY,
|
|
517
|
-
|
|
635
|
+
mlrun.api.utils.singletons.k8s.get_k8s_helper().get_project_secret_name(
|
|
636
|
+
project
|
|
637
|
+
),
|
|
638
|
+
mlrun.api.crud.secrets.Secrets().generate_client_project_secret_key(
|
|
639
|
+
mlrun.api.crud.secrets.SecretsClientType.model_monitoring,
|
|
640
|
+
mlrun.common.schemas.model_monitoring.ProjectSecretKeys.ACCESS_KEY,
|
|
641
|
+
),
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
function.metadata.credentials.access_key = model_monitoring_access_key
|
|
645
|
+
function.apply(mlrun.v3io_cred())
|
|
646
|
+
|
|
647
|
+
# Ensure that the auth env vars are set
|
|
648
|
+
mlrun.api.api.utils.ensure_function_has_auth_set(function, auth_info)
|
|
649
|
+
return function
|
|
650
|
+
|
|
651
|
+
def _initial_model_monitoring_writer_function(
|
|
652
|
+
self, project, model_monitoring_access_key, tracking_policy, auth_info
|
|
653
|
+
):
|
|
654
|
+
"""
|
|
655
|
+
Initialize model monitoring writer function.
|
|
656
|
+
|
|
657
|
+
:param project: Project name.
|
|
658
|
+
:param model_monitoring_access_key: Access key to apply the model monitoring process. Please note that in CE
|
|
659
|
+
deployments this parameter will be None.
|
|
660
|
+
:param tracking_policy: Model monitoring configurations.
|
|
661
|
+
:param auth_info: The auth info of the request.
|
|
662
|
+
|
|
663
|
+
:return: A function object from a mlrun runtime class
|
|
664
|
+
|
|
665
|
+
"""
|
|
666
|
+
|
|
667
|
+
# Create a new serving function for the streaming process
|
|
668
|
+
function = mlrun.code_to_function(
|
|
669
|
+
name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
670
|
+
project=project,
|
|
671
|
+
filename=str(_MONITORING_WRITER_FUNCTION_PATH),
|
|
672
|
+
kind="serving",
|
|
673
|
+
image=tracking_policy.stream_image,
|
|
518
674
|
)
|
|
519
675
|
|
|
520
|
-
|
|
521
|
-
function.
|
|
676
|
+
# Create writer monitoring serving graph
|
|
677
|
+
graph = function.set_topology("flow")
|
|
678
|
+
graph.to(ModelMonitoringWriter(name="king")).respond() # writer
|
|
679
|
+
|
|
680
|
+
# Set the project to the serving function
|
|
681
|
+
function.metadata.project = project
|
|
522
682
|
|
|
523
|
-
#
|
|
524
|
-
|
|
683
|
+
# Add stream triggers
|
|
684
|
+
function = self._apply_stream_trigger(
|
|
685
|
+
project=project,
|
|
686
|
+
function=function,
|
|
687
|
+
model_monitoring_access_key=model_monitoring_access_key,
|
|
688
|
+
auth_info=auth_info,
|
|
689
|
+
function_name=mm_constants.MonitoringFunctionNames.WRITER,
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
# Apply feature store run configurations on the serving function
|
|
693
|
+
run_config = fstore.RunConfig(function=function, local=False)
|
|
694
|
+
function.spec.parameters = run_config.parameters
|
|
525
695
|
|
|
526
696
|
return function
|
|
527
697
|
|
|
@@ -112,7 +112,9 @@ def get_access_key(auth_info: mlrun.common.schemas.AuthInfo):
|
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
def get_monitoring_parquet_path(
|
|
115
|
-
db_session: sqlalchemy.orm.Session,
|
|
115
|
+
db_session: sqlalchemy.orm.Session,
|
|
116
|
+
project: str,
|
|
117
|
+
kind: str = mlrun.common.schemas.model_monitoring.FileTargetKind.PARQUET,
|
|
116
118
|
) -> str:
|
|
117
119
|
"""Get model monitoring parquet target for the current project. The parquet target path is based on the
|
|
118
120
|
project artifact path. If project artifact path is not defined, the parquet target path will be based on MLRun
|
|
@@ -121,6 +123,7 @@ def get_monitoring_parquet_path(
|
|
|
121
123
|
:param db_session: A session that manages the current dialog with the database. Will be used in this function
|
|
122
124
|
to get the project record from DB.
|
|
123
125
|
:param project: Project name.
|
|
126
|
+
:param kind: indicate the kind of the parquet path, can be either stream_parquet or stream_controller_parquet
|
|
124
127
|
|
|
125
128
|
:return: Monitoring parquet target path.
|
|
126
129
|
"""
|
|
@@ -133,27 +136,37 @@ def get_monitoring_parquet_path(
|
|
|
133
136
|
# Generate monitoring parquet path value
|
|
134
137
|
parquet_path = mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
135
138
|
project=project,
|
|
136
|
-
kind=
|
|
139
|
+
kind=kind,
|
|
137
140
|
target="offline",
|
|
138
141
|
artifact_path=artifact_path,
|
|
139
142
|
)
|
|
140
143
|
return parquet_path
|
|
141
144
|
|
|
142
145
|
|
|
143
|
-
def get_stream_path(project: str = None):
|
|
144
|
-
"""
|
|
146
|
+
def get_stream_path(project: str = None, application_name: str = None):
|
|
147
|
+
"""
|
|
148
|
+
Get stream path from the project secret. If wasn't set, take it from the system configurations
|
|
149
|
+
|
|
150
|
+
:param project: Project name.
|
|
151
|
+
:param application_name: Application name, None for model_monitoring_stream.
|
|
152
|
+
|
|
153
|
+
:return: Monitoring stream path to the relevant application.
|
|
154
|
+
"""
|
|
145
155
|
|
|
146
156
|
stream_uri = mlrun.api.crud.secrets.Secrets().get_project_secret(
|
|
147
157
|
project=project,
|
|
148
158
|
provider=mlrun.common.schemas.secret.SecretProviderName.kubernetes,
|
|
149
159
|
allow_secrets_from_k8s=True,
|
|
150
|
-
secret_key=mlrun.common.schemas.model_monitoring.ProjectSecretKeys.STREAM_PATH
|
|
160
|
+
secret_key=mlrun.common.schemas.model_monitoring.ProjectSecretKeys.STREAM_PATH
|
|
161
|
+
if application_name is None
|
|
162
|
+
else "",
|
|
151
163
|
) or mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
152
164
|
project=project,
|
|
153
165
|
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.STREAM,
|
|
154
166
|
target="online",
|
|
167
|
+
application_name=application_name,
|
|
155
168
|
)
|
|
156
169
|
|
|
157
170
|
return mlrun.common.model_monitoring.helpers.parse_monitoring_stream_path(
|
|
158
|
-
stream_uri=stream_uri, project=project
|
|
171
|
+
stream_uri=stream_uri, project=project, application_name=application_name
|
|
159
172
|
)
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
import os
|
|
17
17
|
import typing
|
|
18
|
-
import warnings
|
|
19
18
|
|
|
20
19
|
import sqlalchemy.orm
|
|
21
20
|
|
|
@@ -36,35 +35,6 @@ from mlrun.utils import logger
|
|
|
36
35
|
class ModelEndpoints:
|
|
37
36
|
"""Provide different methods for handling model endpoints such as listing, writing and deleting"""
|
|
38
37
|
|
|
39
|
-
def create_or_patch(
|
|
40
|
-
self,
|
|
41
|
-
db_session: sqlalchemy.orm.Session,
|
|
42
|
-
access_key: str,
|
|
43
|
-
model_endpoint: mlrun.common.schemas.ModelEndpoint,
|
|
44
|
-
auth_info: mlrun.common.schemas.AuthInfo = mlrun.common.schemas.AuthInfo(),
|
|
45
|
-
) -> mlrun.common.schemas.ModelEndpoint:
|
|
46
|
-
# TODO: deprecated in 1.3.0, remove in 1.5.0.
|
|
47
|
-
warnings.warn(
|
|
48
|
-
"This is deprecated in 1.3.0, and will be removed in 1.5.0."
|
|
49
|
-
"Please use create_model_endpoint() for create or patch_model_endpoint() for update",
|
|
50
|
-
FutureWarning,
|
|
51
|
-
)
|
|
52
|
-
"""
|
|
53
|
-
Either create or updates the record of a given `ModelEndpoint` object.
|
|
54
|
-
Leaving here for backwards compatibility, remove in 1.5.0.
|
|
55
|
-
|
|
56
|
-
:param db_session: A session that manages the current dialog with the database
|
|
57
|
-
:param access_key: Access key with permission to write to KV table
|
|
58
|
-
:param model_endpoint: Model endpoint object to update
|
|
59
|
-
:param auth_info: The auth info of the request
|
|
60
|
-
|
|
61
|
-
:return: `ModelEndpoint` object.
|
|
62
|
-
"""
|
|
63
|
-
|
|
64
|
-
return self.create_model_endpoint(
|
|
65
|
-
db_session=db_session, model_endpoint=model_endpoint
|
|
66
|
-
)
|
|
67
|
-
|
|
68
38
|
@classmethod
|
|
69
39
|
def create_model_endpoint(
|
|
70
40
|
cls,
|
|
@@ -102,6 +72,12 @@ class ModelEndpoints:
|
|
|
102
72
|
)
|
|
103
73
|
)
|
|
104
74
|
|
|
75
|
+
mlrun.utils.helpers.verify_field_of_type(
|
|
76
|
+
field_name="model_endpoint.spec.model_uri",
|
|
77
|
+
field_value=model_obj,
|
|
78
|
+
expected_type=mlrun.artifacts.ModelArtifact,
|
|
79
|
+
)
|
|
80
|
+
|
|
105
81
|
# Get stats from model object if not found in model endpoint object
|
|
106
82
|
if not model_endpoint.status.feature_stats and hasattr(
|
|
107
83
|
model_obj, "feature_stats"
|
|
@@ -268,6 +244,12 @@ class ModelEndpoints:
|
|
|
268
244
|
name=feature.name, value_type=feature.value_type
|
|
269
245
|
)
|
|
270
246
|
)
|
|
247
|
+
for feature in model_obj.spec.outputs:
|
|
248
|
+
feature_set.add_feature(
|
|
249
|
+
mlrun.feature_store.Feature(
|
|
250
|
+
name=feature.name, value_type=feature.value_type
|
|
251
|
+
)
|
|
252
|
+
)
|
|
271
253
|
# Check if features can be found within the feature vector
|
|
272
254
|
elif model_obj.spec.feature_vector:
|
|
273
255
|
_, name, _, tag, _ = mlrun.utils.helpers.parse_artifact_uri(
|
|
@@ -297,7 +279,8 @@ class ModelEndpoints:
|
|
|
297
279
|
)
|
|
298
280
|
|
|
299
281
|
parquet_target = mlrun.datastore.targets.ParquetTarget(
|
|
300
|
-
mlrun.common.schemas.model_monitoring.FileTargetKind.PARQUET,
|
|
282
|
+
mlrun.common.schemas.model_monitoring.FileTargetKind.PARQUET,
|
|
283
|
+
parquet_path,
|
|
301
284
|
)
|
|
302
285
|
driver = mlrun.datastore.targets.get_target_driver(parquet_target, feature_set)
|
|
303
286
|
|
mlrun/api/db/sqldb/db.py
CHANGED
|
@@ -304,7 +304,9 @@ class SQLDB(DBInterface):
|
|
|
304
304
|
project = project or config.default_project
|
|
305
305
|
run = self._get_run(session, uid, project, iter)
|
|
306
306
|
if not run:
|
|
307
|
-
raise mlrun.errors.MLRunNotFoundError(
|
|
307
|
+
raise mlrun.errors.MLRunNotFoundError(
|
|
308
|
+
f"Run uid {uid} of project {project} not found"
|
|
309
|
+
)
|
|
308
310
|
return run.struct
|
|
309
311
|
|
|
310
312
|
def list_runs(
|
mlrun/api/utils/builder.py
CHANGED
|
@@ -673,10 +673,8 @@ def build_runtime(
|
|
|
673
673
|
base_image: str = (
|
|
674
674
|
build.base_image or runtime.spec.image or config.default_base_image
|
|
675
675
|
)
|
|
676
|
-
enriched_base_image =
|
|
677
|
-
base_image,
|
|
678
|
-
client_version,
|
|
679
|
-
client_python_version,
|
|
676
|
+
enriched_base_image = runtime.full_image_path(
|
|
677
|
+
base_image, client_version, client_python_version
|
|
680
678
|
)
|
|
681
679
|
mlrun.utils.logger.info(
|
|
682
680
|
"Building runtime image",
|
|
@@ -64,20 +64,34 @@ def parse_model_endpoint_store_prefix(store_prefix: str):
|
|
|
64
64
|
return endpoint, container, path
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def parse_monitoring_stream_path(
|
|
67
|
+
def parse_monitoring_stream_path(
|
|
68
|
+
stream_uri: str, project: str, application_name: str = None
|
|
69
|
+
):
|
|
68
70
|
if stream_uri.startswith("kafka://"):
|
|
69
71
|
if "?topic" in stream_uri:
|
|
70
72
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
71
73
|
"Custom kafka topic is not allowed"
|
|
72
74
|
)
|
|
73
75
|
# Add topic to stream kafka uri
|
|
74
|
-
|
|
76
|
+
if application_name is None:
|
|
77
|
+
stream_uri += f"?topic=monitoring_stream_{project}"
|
|
78
|
+
else:
|
|
79
|
+
stream_uri += f"?topic=monitoring_stream_{project}_{application_name}"
|
|
75
80
|
|
|
76
81
|
elif stream_uri.startswith("v3io://") and mlrun.mlconf.is_ce_mode():
|
|
77
82
|
# V3IO is not supported in CE mode, generating a default http stream path
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
if application_name is None:
|
|
84
|
+
stream_uri = (
|
|
85
|
+
mlrun.mlconf.model_endpoint_monitoring.default_http_sink.format(
|
|
86
|
+
project=project
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
stream_uri = (
|
|
91
|
+
mlrun.mlconf.model_endpoint_monitoring.default_http_sink_app.format(
|
|
92
|
+
project=project, application_name=application_name
|
|
93
|
+
)
|
|
94
|
+
)
|
|
81
95
|
return stream_uri
|
|
82
96
|
|
|
83
97
|
|