mlrun 1.10.0rc36__py3-none-any.whl → 1.10.0rc38__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/config.py +1 -0
- mlrun/db/base.py +3 -1
- mlrun/db/httpdb.py +10 -3
- mlrun/db/nopdb.py +3 -1
- mlrun/model_monitoring/applications/base.py +85 -47
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +9 -2
- mlrun/run.py +19 -1
- mlrun/runtimes/nuclio/application/application.py +25 -11
- mlrun/runtimes/nuclio/function.py +11 -4
- mlrun/runtimes/nuclio/serving.py +7 -3
- mlrun/secrets.py +54 -13
- mlrun/serving/server.py +51 -9
- mlrun/serving/states.py +30 -5
- mlrun/serving/system_steps.py +7 -9
- mlrun/utils/helpers.py +9 -8
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/METADATA +1 -1
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/RECORD +22 -22
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/WHEEL +0 -0
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc36.dist-info → mlrun-1.10.0rc38.dist-info}/top_level.txt +0 -0
mlrun/config.py
CHANGED
|
@@ -304,6 +304,7 @@ default_config = {
|
|
|
304
304
|
"application": {
|
|
305
305
|
"default_sidecar_internal_port": 8050,
|
|
306
306
|
"default_authentication_mode": mlrun.common.schemas.APIGatewayAuthenticationMode.none,
|
|
307
|
+
"default_worker_number": 10000,
|
|
307
308
|
},
|
|
308
309
|
},
|
|
309
310
|
# TODO: function defaults should be moved to the function spec config above
|
mlrun/db/base.py
CHANGED
|
@@ -722,7 +722,9 @@ class RunDBInterface(ABC):
|
|
|
722
722
|
tsdb_metrics: bool = False,
|
|
723
723
|
metric_list: Optional[list[str]] = None,
|
|
724
724
|
top_level: bool = False,
|
|
725
|
-
modes: Optional[
|
|
725
|
+
modes: Optional[
|
|
726
|
+
Union[mm_constants.EndpointMode, list[mm_constants.EndpointMode]]
|
|
727
|
+
] = None,
|
|
726
728
|
uids: Optional[list[str]] = None,
|
|
727
729
|
latest_only: bool = False,
|
|
728
730
|
) -> mlrun.common.schemas.ModelEndpointList:
|
mlrun/db/httpdb.py
CHANGED
|
@@ -3771,7 +3771,9 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3771
3771
|
tsdb_metrics: bool = False,
|
|
3772
3772
|
metric_list: Optional[list[str]] = None,
|
|
3773
3773
|
top_level: bool = False,
|
|
3774
|
-
modes: Optional[
|
|
3774
|
+
modes: Optional[
|
|
3775
|
+
Union[mm_constants.EndpointMode, list[mm_constants.EndpointMode]]
|
|
3776
|
+
] = None,
|
|
3775
3777
|
uids: Optional[list[str]] = None,
|
|
3776
3778
|
latest_only: bool = False,
|
|
3777
3779
|
) -> mlrun.common.schemas.ModelEndpointList:
|
|
@@ -3802,8 +3804,13 @@ class HTTPRunDB(RunDBInterface):
|
|
|
3802
3804
|
labels = self._parse_labels(labels)
|
|
3803
3805
|
if names and isinstance(names, str):
|
|
3804
3806
|
names = [names]
|
|
3805
|
-
if
|
|
3806
|
-
modes
|
|
3807
|
+
if modes:
|
|
3808
|
+
# Ensure backward compatibility with Python 3.9 clients by converting IntEnum modes to integer values
|
|
3809
|
+
modes = (
|
|
3810
|
+
[modes.value]
|
|
3811
|
+
if isinstance(modes, mm_constants.EndpointMode)
|
|
3812
|
+
else [mode.value for mode in modes]
|
|
3813
|
+
)
|
|
3807
3814
|
response = self.api_call(
|
|
3808
3815
|
method=mlrun.common.types.HTTPMethod.GET,
|
|
3809
3816
|
path=path,
|
mlrun/db/nopdb.py
CHANGED
|
@@ -626,7 +626,9 @@ class NopDB(RunDBInterface):
|
|
|
626
626
|
tsdb_metrics: bool = False,
|
|
627
627
|
metric_list: Optional[list[str]] = None,
|
|
628
628
|
top_level: bool = False,
|
|
629
|
-
modes: Optional[
|
|
629
|
+
modes: Optional[
|
|
630
|
+
Union[mm_constants.EndpointMode, list[mm_constants.EndpointMode]]
|
|
631
|
+
] = None,
|
|
630
632
|
uids: Optional[list[str]] = None,
|
|
631
633
|
latest_only: bool = False,
|
|
632
634
|
) -> mlrun.common.schemas.ModelEndpointList:
|
|
@@ -233,7 +233,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
233
233
|
try:
|
|
234
234
|
yield endpoints_output, application_schedules.__enter__()
|
|
235
235
|
finally:
|
|
236
|
-
if write_output:
|
|
236
|
+
if write_output and any(endpoints_output.values()):
|
|
237
237
|
logger.debug(
|
|
238
238
|
"Pushing model monitoring application job data to the writer stream",
|
|
239
239
|
passed_stream_profile=str(stream_profile),
|
|
@@ -344,7 +344,7 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
344
344
|
return result
|
|
345
345
|
|
|
346
346
|
if endpoints is not None:
|
|
347
|
-
resolved_endpoints = self.
|
|
347
|
+
resolved_endpoints = self._normalize_and_validate_endpoints(
|
|
348
348
|
project=project, endpoints=endpoints
|
|
349
349
|
)
|
|
350
350
|
if (
|
|
@@ -390,6 +390,16 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
390
390
|
context.log_result(
|
|
391
391
|
result_key, self._flatten_data_result(result)
|
|
392
392
|
)
|
|
393
|
+
# Check if no result was produced for any endpoint (e.g., due to no data in all windows)
|
|
394
|
+
if not any(endpoints_output.values()):
|
|
395
|
+
context.logger.warning(
|
|
396
|
+
"No data was found for any of the specified endpoints. "
|
|
397
|
+
"No results were produced",
|
|
398
|
+
application_name=application_name,
|
|
399
|
+
endpoints=endpoints,
|
|
400
|
+
start=start,
|
|
401
|
+
end=end,
|
|
402
|
+
)
|
|
393
403
|
else:
|
|
394
404
|
result = call_do_tracking(
|
|
395
405
|
mm_context.MonitoringApplicationContext._from_ml_ctx(
|
|
@@ -421,69 +431,97 @@ class ModelMonitoringApplicationBase(MonitoringApplicationToDict, ABC):
|
|
|
421
431
|
)
|
|
422
432
|
|
|
423
433
|
@classmethod
|
|
424
|
-
def
|
|
434
|
+
def _normalize_and_validate_endpoints(
|
|
425
435
|
cls,
|
|
426
436
|
project: "mlrun.MlrunProject",
|
|
427
437
|
endpoints: Union[
|
|
428
438
|
list[tuple[str, str]], list[list[str]], list[str], Literal["all"]
|
|
429
439
|
],
|
|
430
|
-
) ->
|
|
431
|
-
if
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
440
|
+
) -> list[tuple[str, str]]:
|
|
441
|
+
if isinstance(endpoints, list):
|
|
442
|
+
if all(
|
|
443
|
+
isinstance(endpoint, (tuple, list)) and len(endpoint) == 2
|
|
444
|
+
for endpoint in endpoints
|
|
445
|
+
):
|
|
446
|
+
# A list of [(name, uid), ...] / [[name, uid], ...] tuples/lists
|
|
447
|
+
endpoint_uids_to_names = {
|
|
448
|
+
endpoint[1]: endpoint[0] for endpoint in endpoints
|
|
449
|
+
}
|
|
450
|
+
endpoints_list = project.list_model_endpoints(
|
|
451
|
+
uids=list(endpoint_uids_to_names.keys()), latest_only=True
|
|
452
|
+
).endpoints
|
|
453
|
+
|
|
454
|
+
# Check for missing endpoint uids or name/uid mismatches
|
|
455
|
+
for endpoint in endpoints_list:
|
|
456
|
+
if (
|
|
457
|
+
endpoint_uids_to_names[cast(str, endpoint.metadata.uid)]
|
|
458
|
+
!= endpoint.metadata.name
|
|
459
|
+
):
|
|
460
|
+
raise mlrun.errors.MLRunNotFoundError(
|
|
461
|
+
"Could not find model endpoint with name "
|
|
462
|
+
f"'{endpoint_uids_to_names[cast(str, endpoint.metadata.uid)]}' "
|
|
463
|
+
f"and uid '{endpoint.metadata.uid}'"
|
|
464
|
+
)
|
|
465
|
+
missing = set(endpoint_uids_to_names.keys()) - {
|
|
466
|
+
cast(str, endpoint.metadata.uid) for endpoint in endpoints_list
|
|
467
|
+
}
|
|
468
|
+
if missing:
|
|
469
|
+
raise mlrun.errors.MLRunNotFoundError(
|
|
470
|
+
"Could not find model endpoints with the following uids: "
|
|
471
|
+
f"{missing}"
|
|
447
472
|
)
|
|
448
|
-
else:
|
|
449
|
-
raise mlrun.errors.MLRunValueError(
|
|
450
|
-
f"Could not resolve endpoints as list of [(name, uid)], {endpoints=}"
|
|
451
|
-
)
|
|
452
473
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
names=endpoint_names, latest_only=True
|
|
460
|
-
).endpoints
|
|
474
|
+
elif all(isinstance(endpoint, str) for endpoint in endpoints):
|
|
475
|
+
# A list of [name, ...] strings
|
|
476
|
+
endpoint_names = cast(list[str], endpoints)
|
|
477
|
+
endpoints_list = project.list_model_endpoints(
|
|
478
|
+
names=endpoint_names, latest_only=True
|
|
479
|
+
).endpoints
|
|
461
480
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if endpoints_list:
|
|
465
|
-
list_endpoints_result = [
|
|
466
|
-
(endpoint.metadata.name, endpoint.metadata.uid)
|
|
467
|
-
for endpoint in endpoints_list
|
|
468
|
-
]
|
|
469
|
-
if endpoints != "all":
|
|
481
|
+
# Check for missing endpoint names
|
|
470
482
|
missing = set(endpoints) - {
|
|
471
|
-
endpoint
|
|
483
|
+
endpoint.metadata.name for endpoint in endpoints_list
|
|
472
484
|
}
|
|
473
485
|
if missing:
|
|
474
486
|
logger.warning(
|
|
475
487
|
"Could not list all the required endpoints",
|
|
476
|
-
|
|
477
|
-
|
|
488
|
+
missing_endpoints=missing,
|
|
489
|
+
endpoints_list=endpoints_list,
|
|
478
490
|
)
|
|
479
|
-
|
|
491
|
+
else:
|
|
492
|
+
raise mlrun.errors.MLRunValueError(
|
|
493
|
+
"Could not resolve the following list as a list of endpoints:\n"
|
|
494
|
+
f"{endpoints}\n"
|
|
495
|
+
"The list must be either a list of (name, uid) tuples/lists or a list of names."
|
|
496
|
+
)
|
|
497
|
+
elif endpoints == "all":
|
|
498
|
+
endpoints_list = project.list_model_endpoints(latest_only=True).endpoints
|
|
499
|
+
elif isinstance(endpoints, str):
|
|
500
|
+
raise mlrun.errors.MLRunValueError(
|
|
501
|
+
'A string input for `endpoints` can only be "all" for all the model endpoints in '
|
|
502
|
+
"the project. If you want to select a single model endpoint with the given name, "
|
|
503
|
+
f'use a list: `endpoints=["{endpoints}"]`.'
|
|
504
|
+
)
|
|
480
505
|
else:
|
|
481
|
-
|
|
482
|
-
|
|
506
|
+
raise mlrun.errors.MLRunValueError(
|
|
507
|
+
"Could not resolve the `endpoints` parameter. The parameter must be either:\n"
|
|
508
|
+
"- a list of (name, uid) tuples/lists\n"
|
|
509
|
+
"- a list of names\n"
|
|
510
|
+
'- the string "all" for all the model endpoints in the project.'
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
if not endpoints_list:
|
|
483
514
|
raise mlrun.errors.MLRunNotFoundError(
|
|
484
|
-
f"Did not find any model endpoints {
|
|
515
|
+
f"Did not find any model endpoints {endpoints=}"
|
|
485
516
|
)
|
|
486
517
|
|
|
518
|
+
cls._check_endpoints_first_request(endpoints_list)
|
|
519
|
+
|
|
520
|
+
return [
|
|
521
|
+
(endpoint.metadata.name, cast(str, endpoint.metadata.uid))
|
|
522
|
+
for endpoint in endpoints_list
|
|
523
|
+
]
|
|
524
|
+
|
|
487
525
|
@staticmethod
|
|
488
526
|
def _validate_and_get_window_length(
|
|
489
527
|
*, base_period: int, start_dt: datetime, end_dt: datetime
|
|
@@ -55,14 +55,12 @@ class TDEngineConnector(TSDBConnector):
|
|
|
55
55
|
"""
|
|
56
56
|
|
|
57
57
|
type: str = mm_schemas.TSDBTarget.TDEngine
|
|
58
|
-
database = f"{tdengine_schemas._MODEL_MONITORING_DATABASE}_{mlrun.mlconf.system_id}"
|
|
59
58
|
|
|
60
59
|
def __init__(
|
|
61
60
|
self,
|
|
62
61
|
project: str,
|
|
63
62
|
profile: DatastoreProfile,
|
|
64
63
|
timestamp_precision: TDEngineTimestampPrecision = TDEngineTimestampPrecision.MICROSECOND,
|
|
65
|
-
**kwargs,
|
|
66
64
|
):
|
|
67
65
|
super().__init__(project=project)
|
|
68
66
|
|
|
@@ -72,6 +70,15 @@ class TDEngineConnector(TSDBConnector):
|
|
|
72
70
|
timestamp_precision
|
|
73
71
|
)
|
|
74
72
|
|
|
73
|
+
if not mlrun.mlconf.system_id:
|
|
74
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
75
|
+
"system_id is not set in mlrun.mlconf. "
|
|
76
|
+
"TDEngineConnector requires system_id to be configured for database name construction. "
|
|
77
|
+
"Please ensure MLRun configuration is properly loaded before creating TDEngineConnector."
|
|
78
|
+
)
|
|
79
|
+
self.database = (
|
|
80
|
+
f"{tdengine_schemas._MODEL_MONITORING_DATABASE}_{mlrun.mlconf.system_id}"
|
|
81
|
+
)
|
|
75
82
|
self._init_super_tables()
|
|
76
83
|
|
|
77
84
|
@property
|
mlrun/run.py
CHANGED
|
@@ -118,7 +118,25 @@ def function_to_module(code="", workdir=None, secrets=None, silent=False):
|
|
|
118
118
|
raise ValueError("nothing to run, specify command or function")
|
|
119
119
|
|
|
120
120
|
command = os.path.join(workdir or "", command)
|
|
121
|
-
|
|
121
|
+
|
|
122
|
+
source_file_path_object, working_dir_path_object = (
|
|
123
|
+
mlrun.utils.helpers.get_source_and_working_dir_paths(command)
|
|
124
|
+
)
|
|
125
|
+
if source_file_path_object.is_relative_to(working_dir_path_object):
|
|
126
|
+
mod_name = mlrun.utils.helpers.get_relative_module_name_from_path(
|
|
127
|
+
source_file_path_object, working_dir_path_object
|
|
128
|
+
)
|
|
129
|
+
elif source_file_path_object.is_relative_to(
|
|
130
|
+
pathlib.Path(tempfile.gettempdir()).resolve()
|
|
131
|
+
):
|
|
132
|
+
mod_name = Path(command).stem
|
|
133
|
+
else:
|
|
134
|
+
raise mlrun.errors.MLRunRuntimeError(
|
|
135
|
+
f"Cannot run source file '{command}': it must be located either under the current working "
|
|
136
|
+
f"directory ('{working_dir_path_object}') or the system temporary directory ('{tempfile.gettempdir()}'). "
|
|
137
|
+
f"This is required when running with local=True."
|
|
138
|
+
)
|
|
139
|
+
|
|
122
140
|
spec = imputil.spec_from_file_location(mod_name, command)
|
|
123
141
|
if spec is None:
|
|
124
142
|
raise OSError(f"cannot import from {command!r}")
|
|
@@ -413,8 +413,7 @@ class ApplicationRuntime(RemoteRuntime):
|
|
|
413
413
|
show_on_failure=show_on_failure,
|
|
414
414
|
)
|
|
415
415
|
|
|
416
|
-
|
|
417
|
-
self._ensure_reverse_proxy_configurations(self)
|
|
416
|
+
self._ensure_reverse_proxy_configurations()
|
|
418
417
|
self._configure_application_sidecar()
|
|
419
418
|
|
|
420
419
|
# We only allow accessing the application via the API Gateway
|
|
@@ -799,27 +798,42 @@ class ApplicationRuntime(RemoteRuntime):
|
|
|
799
798
|
with_mlrun=with_mlrun,
|
|
800
799
|
)
|
|
801
800
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
801
|
+
def _ensure_reverse_proxy_configurations(self):
|
|
802
|
+
# If an HTTP trigger already exists in the spec,
|
|
803
|
+
# it means the user explicitly defined a custom configuration,
|
|
804
|
+
# so, skip automatic creation.
|
|
805
|
+
skip_http_trigger_creation = False
|
|
806
|
+
for key, value in self.spec.config.items():
|
|
807
|
+
if key.startswith("spec.triggers"):
|
|
808
|
+
if isinstance(value, dict):
|
|
809
|
+
if value.get("kind") == "http":
|
|
810
|
+
skip_http_trigger_creation = True
|
|
811
|
+
break
|
|
812
|
+
if not skip_http_trigger_creation:
|
|
813
|
+
self.with_http(
|
|
814
|
+
workers=mlrun.mlconf.function.application.default_worker_number,
|
|
815
|
+
trigger_name="application-http",
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
if self.spec.build.functionSourceCode or self.status.container_image:
|
|
805
819
|
return
|
|
806
820
|
|
|
807
821
|
filename, handler = ApplicationRuntime.get_filename_and_handler()
|
|
808
822
|
name, spec, code = nuclio.build_file(
|
|
809
823
|
filename,
|
|
810
|
-
name=
|
|
824
|
+
name=self.metadata.name,
|
|
811
825
|
handler=handler,
|
|
812
826
|
)
|
|
813
|
-
|
|
814
|
-
|
|
827
|
+
self.spec.function_handler = mlrun.utils.get_in(spec, "spec.handler")
|
|
828
|
+
self.spec.build.functionSourceCode = mlrun.utils.get_in(
|
|
815
829
|
spec, "spec.build.functionSourceCode"
|
|
816
830
|
)
|
|
817
|
-
|
|
831
|
+
self.spec.nuclio_runtime = mlrun.utils.get_in(spec, "spec.runtime")
|
|
818
832
|
|
|
819
833
|
# default the reverse proxy logger level to info
|
|
820
834
|
logger_sinks_key = "spec.loggerSinks"
|
|
821
|
-
if not
|
|
822
|
-
|
|
835
|
+
if not self.spec.config.get(logger_sinks_key):
|
|
836
|
+
self.set_config(
|
|
823
837
|
logger_sinks_key, [{"level": "info", "sink": "myStdoutLoggerSink"}]
|
|
824
838
|
)
|
|
825
839
|
|
|
@@ -1224,10 +1224,17 @@ class RemoteRuntime(KubeResource):
|
|
|
1224
1224
|
# try to infer the invocation url from the internal and if not exists, use external.
|
|
1225
1225
|
# $$$$ we do not want to use the external invocation url (e.g.: ingress, nodePort, etc.)
|
|
1226
1226
|
|
|
1227
|
-
#
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1227
|
+
# if none of urls is set, function was deployed with watch=False
|
|
1228
|
+
# and status wasn't fetched with Nuclio
|
|
1229
|
+
# _get_state fetches the state and updates url
|
|
1230
|
+
if (
|
|
1231
|
+
not self.status.address
|
|
1232
|
+
and not self.status.internal_invocation_urls
|
|
1233
|
+
and not self.status.external_invocation_urls
|
|
1234
|
+
):
|
|
1235
|
+
state, _, _ = self._get_state()
|
|
1236
|
+
if state not in ["ready", "scaledToZero"]:
|
|
1237
|
+
logger.warning(f"Function is in the {state} state")
|
|
1231
1238
|
|
|
1232
1239
|
# prefer internal invocation url if running inside k8s cluster
|
|
1233
1240
|
if (
|
mlrun/runtimes/nuclio/serving.py
CHANGED
|
@@ -679,9 +679,13 @@ class ServingRuntime(RemoteRuntime):
|
|
|
679
679
|
f"function {function} is used in steps and is not defined, "
|
|
680
680
|
"use the .add_child_function() to specify child function attributes"
|
|
681
681
|
)
|
|
682
|
-
if
|
|
683
|
-
isinstance(
|
|
684
|
-
|
|
682
|
+
if (
|
|
683
|
+
isinstance(self.spec.graph, RootFlowStep)
|
|
684
|
+
and any(
|
|
685
|
+
isinstance(step_type, mlrun.serving.states.ModelRunnerStep)
|
|
686
|
+
for step_type in self.spec.graph.steps.values()
|
|
687
|
+
)
|
|
688
|
+
and self.spec.build.functionSourceCode
|
|
685
689
|
):
|
|
686
690
|
# Add import for LLModel
|
|
687
691
|
decoded_code = b64decode(self.spec.build.functionSourceCode).decode("utf-8")
|
mlrun/secrets.py
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
14
|
+
import json
|
|
15
15
|
from ast import literal_eval
|
|
16
|
-
from os import environ
|
|
16
|
+
from os import environ
|
|
17
17
|
from typing import Callable, Optional, Union
|
|
18
18
|
|
|
19
19
|
from .utils import AzureVaultStore, list2dict
|
|
@@ -161,6 +161,9 @@ def get_secret_or_env(
|
|
|
161
161
|
4. An MLRun-generated env. variable, mounted from a project secret (to be used in MLRun runtimes)
|
|
162
162
|
5. The default value
|
|
163
163
|
|
|
164
|
+
Also supports discovering the value inside any environment variable that contains a JSON-encoded list
|
|
165
|
+
of dicts with fields: {'name': 'KEY', 'value': 'VAL', 'value_from': ...}. This fallback is applied
|
|
166
|
+
after checking normal environment variables and before returning the default.
|
|
164
167
|
Example::
|
|
165
168
|
|
|
166
169
|
secrets = {"KEY1": "VALUE1"}
|
|
@@ -187,18 +190,56 @@ def get_secret_or_env(
|
|
|
187
190
|
if prefix:
|
|
188
191
|
key = f"{prefix}_{key}"
|
|
189
192
|
|
|
190
|
-
value = None
|
|
191
193
|
if secret_provider:
|
|
192
194
|
if isinstance(secret_provider, (dict, SecretsStore)):
|
|
193
|
-
|
|
195
|
+
secret_value = secret_provider.get(key)
|
|
194
196
|
else:
|
|
195
|
-
|
|
196
|
-
if
|
|
197
|
-
return
|
|
197
|
+
secret_value = secret_provider(key)
|
|
198
|
+
if secret_value:
|
|
199
|
+
return secret_value
|
|
200
|
+
|
|
201
|
+
direct_environment_value = environ.get(key)
|
|
202
|
+
if direct_environment_value:
|
|
203
|
+
return direct_environment_value
|
|
204
|
+
|
|
205
|
+
json_list_value = _find_value_in_json_env_lists(key)
|
|
206
|
+
if json_list_value is not None:
|
|
207
|
+
return json_list_value
|
|
208
|
+
|
|
209
|
+
mlrun_env_key = SecretsStore.k8s_env_variable_name_for_secret(key)
|
|
210
|
+
mlrun_env_value = environ.get(mlrun_env_key)
|
|
211
|
+
if mlrun_env_value:
|
|
212
|
+
return mlrun_env_value
|
|
198
213
|
|
|
199
|
-
return
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
214
|
+
return default
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _find_value_in_json_env_lists(
|
|
218
|
+
secret_name: str,
|
|
219
|
+
) -> Optional[str]:
|
|
220
|
+
"""
|
|
221
|
+
Scan all environment variables. If any env var contains a JSON-encoded list
|
|
222
|
+
of dicts shaped like {'name': str, 'value': str|None, 'value_from': ...},
|
|
223
|
+
return the 'value' for the entry whose 'name' matches secret_name.
|
|
224
|
+
"""
|
|
225
|
+
for environment_variable_value in environ.values():
|
|
226
|
+
if not environment_variable_value or not isinstance(
|
|
227
|
+
environment_variable_value, str
|
|
228
|
+
):
|
|
229
|
+
continue
|
|
230
|
+
# Fast precheck to skip obvious non-JSON strings
|
|
231
|
+
first_char = environment_variable_value.lstrip()[:1]
|
|
232
|
+
if first_char not in ("[", "{"):
|
|
233
|
+
continue
|
|
234
|
+
try:
|
|
235
|
+
parsed_value = json.loads(environment_variable_value)
|
|
236
|
+
except ValueError:
|
|
237
|
+
continue
|
|
238
|
+
if isinstance(parsed_value, list):
|
|
239
|
+
for entry in parsed_value:
|
|
240
|
+
if isinstance(entry, dict) and entry.get("name") == secret_name:
|
|
241
|
+
value_in_entry = entry.get("value")
|
|
242
|
+
# Match original semantics: empty string is treated as "not found"
|
|
243
|
+
if value_in_entry:
|
|
244
|
+
return value_in_entry
|
|
245
|
+
return None
|
mlrun/serving/server.py
CHANGED
|
@@ -23,6 +23,7 @@ import os
|
|
|
23
23
|
import socket
|
|
24
24
|
import traceback
|
|
25
25
|
import uuid
|
|
26
|
+
from collections import defaultdict
|
|
26
27
|
from datetime import datetime, timezone
|
|
27
28
|
from typing import Any, Optional, Union
|
|
28
29
|
|
|
@@ -50,7 +51,7 @@ from ..datastore.store_resources import ResourceCache
|
|
|
50
51
|
from ..errors import MLRunInvalidArgumentError
|
|
51
52
|
from ..execution import MLClientCtx
|
|
52
53
|
from ..model import ModelObj
|
|
53
|
-
from ..utils import get_caller_globals,
|
|
54
|
+
from ..utils import get_caller_globals, get_relative_module_name_from_path
|
|
54
55
|
from .states import (
|
|
55
56
|
FlowStep,
|
|
56
57
|
MonitoredStep,
|
|
@@ -522,10 +523,6 @@ def add_system_steps_to_graph(
|
|
|
522
523
|
monitor_flow_step.after = [
|
|
523
524
|
step_name,
|
|
524
525
|
]
|
|
525
|
-
context.logger.info_with(
|
|
526
|
-
"Server graph after adding system steps",
|
|
527
|
-
graph=str(graph.steps),
|
|
528
|
-
)
|
|
529
526
|
return graph
|
|
530
527
|
|
|
531
528
|
|
|
@@ -583,7 +580,17 @@ async def async_execute_graph(
|
|
|
583
580
|
batch_size: Optional[int],
|
|
584
581
|
read_as_lists: bool,
|
|
585
582
|
nest_under_inputs: bool,
|
|
586
|
-
) ->
|
|
583
|
+
) -> None:
|
|
584
|
+
# Validate that data parameter is a DataItem and not passed via params
|
|
585
|
+
if not isinstance(data, DataItem):
|
|
586
|
+
raise MLRunInvalidArgumentError(
|
|
587
|
+
f"Parameter 'data' has type hint 'DataItem' but got {type(data).__name__} instead. "
|
|
588
|
+
f"Data files and artifacts must be passed via the 'inputs' parameter, not 'params'. "
|
|
589
|
+
f"The 'params' parameter is for simple configuration values (strings, numbers, booleans), "
|
|
590
|
+
f"while 'inputs' is for data files that need to be loaded. "
|
|
591
|
+
f"Example: run_function(..., inputs={{'data': 'path/to/data.csv'}}, params={{other_config: value}})"
|
|
592
|
+
)
|
|
593
|
+
run_call_count = 0
|
|
587
594
|
spec = mlrun.utils.get_serving_spec()
|
|
588
595
|
modname = None
|
|
589
596
|
code = os.getenv("MLRUN_EXEC_CODE")
|
|
@@ -597,7 +604,17 @@ async def async_execute_graph(
|
|
|
597
604
|
# gets set in local flow and not just in the remote pod
|
|
598
605
|
source_file_path = spec.get("filename", None)
|
|
599
606
|
if source_file_path:
|
|
600
|
-
|
|
607
|
+
source_file_path_object, working_dir_path_object = (
|
|
608
|
+
mlrun.utils.helpers.get_source_and_working_dir_paths(source_file_path)
|
|
609
|
+
)
|
|
610
|
+
if not source_file_path_object.is_relative_to(working_dir_path_object):
|
|
611
|
+
raise mlrun.errors.MLRunRuntimeError(
|
|
612
|
+
f"Source file path '{source_file_path}' is not under the current working directory "
|
|
613
|
+
f"(which is required when running with local=True)"
|
|
614
|
+
)
|
|
615
|
+
modname = get_relative_module_name_from_path(
|
|
616
|
+
source_file_path_object, working_dir_path_object
|
|
617
|
+
)
|
|
601
618
|
|
|
602
619
|
namespace = {}
|
|
603
620
|
if modname:
|
|
@@ -672,7 +689,6 @@ async def async_execute_graph(
|
|
|
672
689
|
|
|
673
690
|
if config.log_level.lower() == "debug":
|
|
674
691
|
server.verbose = True
|
|
675
|
-
context.logger.info_with("Initializing states", namespace=namespace)
|
|
676
692
|
kwargs = {}
|
|
677
693
|
if hasattr(context, "is_mock"):
|
|
678
694
|
kwargs["is_mock"] = context.is_mock
|
|
@@ -690,6 +706,7 @@ async def async_execute_graph(
|
|
|
690
706
|
context.logger.info(server.to_yaml())
|
|
691
707
|
|
|
692
708
|
async def run(body):
|
|
709
|
+
nonlocal run_call_count
|
|
693
710
|
event = storey.Event(id=index, body=body)
|
|
694
711
|
if timestamp_column:
|
|
695
712
|
if batching:
|
|
@@ -704,6 +721,7 @@ async def async_execute_graph(
|
|
|
704
721
|
f"Event body '{body}' did not contain timestamp column '{timestamp_column}'"
|
|
705
722
|
)
|
|
706
723
|
event._original_timestamp = body[timestamp_column]
|
|
724
|
+
run_call_count += 1
|
|
707
725
|
return await server.run(event, context)
|
|
708
726
|
|
|
709
727
|
if batching and not batch_size:
|
|
@@ -761,7 +779,31 @@ async def async_execute_graph(
|
|
|
761
779
|
model_endpoint_uids=model_endpoint_uids,
|
|
762
780
|
)
|
|
763
781
|
|
|
764
|
-
|
|
782
|
+
# log the results as artifacts
|
|
783
|
+
num_of_meps_in_the_graph = len(server.graph.model_endpoints_names)
|
|
784
|
+
artifact_path = None
|
|
785
|
+
if (
|
|
786
|
+
"{{run.uid}}" not in context.artifact_path
|
|
787
|
+
): # TODO: delete when IG-22841 is resolved
|
|
788
|
+
artifact_path = "+/{{run.uid}}" # will be concatenated to the context's path in extend_artifact_path
|
|
789
|
+
if num_of_meps_in_the_graph <= 1:
|
|
790
|
+
context.log_dataset(
|
|
791
|
+
"prediction", df=pd.DataFrame(responses), artifact_path=artifact_path
|
|
792
|
+
)
|
|
793
|
+
else:
|
|
794
|
+
# turn this list of samples into a dict of lists, one per model endpoint
|
|
795
|
+
grouped = defaultdict(list)
|
|
796
|
+
for sample in responses:
|
|
797
|
+
for model_name, features in sample.items():
|
|
798
|
+
grouped[model_name].append(features)
|
|
799
|
+
# create a dataframe per model endpoint and log it
|
|
800
|
+
for model_name, features in grouped.items():
|
|
801
|
+
context.log_dataset(
|
|
802
|
+
f"prediction_{model_name}",
|
|
803
|
+
df=pd.DataFrame(features),
|
|
804
|
+
artifact_path=artifact_path,
|
|
805
|
+
)
|
|
806
|
+
context.log_result("num_rows", run_call_count)
|
|
765
807
|
|
|
766
808
|
|
|
767
809
|
def _is_inside_asyncio_loop():
|
mlrun/serving/states.py
CHANGED
|
@@ -522,7 +522,9 @@ class BaseStep(ModelObj):
|
|
|
522
522
|
|
|
523
523
|
root = self._extract_root_step()
|
|
524
524
|
|
|
525
|
-
if not isinstance(root, RootFlowStep)
|
|
525
|
+
if not isinstance(root, RootFlowStep) or (
|
|
526
|
+
isinstance(root, RootFlowStep) and root.engine != "async"
|
|
527
|
+
):
|
|
526
528
|
raise GraphError(
|
|
527
529
|
"ModelRunnerStep can be added to 'Flow' topology graph only"
|
|
528
530
|
)
|
|
@@ -1148,6 +1150,7 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1148
1150
|
"artifact_uri",
|
|
1149
1151
|
"shared_runnable_name",
|
|
1150
1152
|
"shared_proxy_mapping",
|
|
1153
|
+
"execution_mechanism",
|
|
1151
1154
|
]
|
|
1152
1155
|
kind = "model"
|
|
1153
1156
|
|
|
@@ -1170,6 +1173,7 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1170
1173
|
self.model_artifact: Optional[ModelArtifact] = None
|
|
1171
1174
|
self.model_provider: Optional[ModelProvider] = None
|
|
1172
1175
|
self._artifact_were_loaded = False
|
|
1176
|
+
self._execution_mechanism = None
|
|
1173
1177
|
|
|
1174
1178
|
def __init_subclass__(cls):
|
|
1175
1179
|
super().__init_subclass__()
|
|
@@ -1189,6 +1193,20 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1189
1193
|
raise_missing_schema_exception=False,
|
|
1190
1194
|
)
|
|
1191
1195
|
|
|
1196
|
+
# Check if the relevant predict method is implemented when trying to initialize the model
|
|
1197
|
+
if self._execution_mechanism == storey.ParallelExecutionMechanisms.asyncio:
|
|
1198
|
+
if self.__class__.predict_async is Model.predict_async:
|
|
1199
|
+
raise mlrun.errors.ModelRunnerError(
|
|
1200
|
+
f"{self.name} is running with {self._execution_mechanism} execution_mechanism but predict_async() "
|
|
1201
|
+
f"is not implemented"
|
|
1202
|
+
)
|
|
1203
|
+
else:
|
|
1204
|
+
if self.__class__.predict is Model.predict:
|
|
1205
|
+
raise mlrun.errors.ModelRunnerError(
|
|
1206
|
+
f"{self.name} is running with {self._execution_mechanism} execution_mechanism but predict() "
|
|
1207
|
+
f"is not implemented"
|
|
1208
|
+
)
|
|
1209
|
+
|
|
1192
1210
|
def _load_artifacts(self) -> None:
|
|
1193
1211
|
if not self._artifact_were_loaded:
|
|
1194
1212
|
artifact = self._get_artifact_object()
|
|
@@ -1219,11 +1237,11 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1219
1237
|
|
|
1220
1238
|
def predict(self, body: Any, **kwargs) -> Any:
|
|
1221
1239
|
"""Override to implement prediction logic. If the logic requires asyncio, override predict_async() instead."""
|
|
1222
|
-
|
|
1240
|
+
raise NotImplementedError("predict() method not implemented")
|
|
1223
1241
|
|
|
1224
1242
|
async def predict_async(self, body: Any, **kwargs) -> Any:
|
|
1225
1243
|
"""Override to implement prediction logic if the logic requires asyncio."""
|
|
1226
|
-
|
|
1244
|
+
raise NotImplementedError("predict_async() method not implemented")
|
|
1227
1245
|
|
|
1228
1246
|
def run(self, body: Any, path: str, origin_name: Optional[str] = None) -> Any:
|
|
1229
1247
|
return self.predict(body)
|
|
@@ -1644,6 +1662,8 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1644
1662
|
Note when ModelRunnerStep is used in a graph, MLRun automatically imports
|
|
1645
1663
|
the default language model class (LLModel) during function deployment.
|
|
1646
1664
|
|
|
1665
|
+
Note ModelRunnerStep can only be added to a graph that has the flow topology and running with async engine.
|
|
1666
|
+
|
|
1647
1667
|
:param model_selector: ModelSelector instance whose select() method will be used to select models to run on each
|
|
1648
1668
|
event. Optional. If not passed, all models will be run.
|
|
1649
1669
|
:param raise_exception: If True, an error will be raised when model selection fails or if one of the models raised
|
|
@@ -2091,24 +2111,28 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
2091
2111
|
)
|
|
2092
2112
|
model_objects = []
|
|
2093
2113
|
for model, model_params in models.values():
|
|
2114
|
+
model_name = model_params.get("name")
|
|
2094
2115
|
model_params[schemas.MonitoringData.INPUT_PATH] = (
|
|
2095
2116
|
self.class_args.get(
|
|
2096
2117
|
mlrun.common.schemas.ModelRunnerStepData.MONITORING_DATA, {}
|
|
2097
2118
|
)
|
|
2098
|
-
.get(
|
|
2119
|
+
.get(model_name, {})
|
|
2099
2120
|
.get(schemas.MonitoringData.INPUT_PATH)
|
|
2100
2121
|
)
|
|
2101
2122
|
model_params[schemas.MonitoringData.RESULT_PATH] = (
|
|
2102
2123
|
self.class_args.get(
|
|
2103
2124
|
mlrun.common.schemas.ModelRunnerStepData.MONITORING_DATA, {}
|
|
2104
2125
|
)
|
|
2105
|
-
.get(
|
|
2126
|
+
.get(model_name, {})
|
|
2106
2127
|
.get(schemas.MonitoringData.RESULT_PATH)
|
|
2107
2128
|
)
|
|
2108
2129
|
model = get_class(model, namespace).from_dict(
|
|
2109
2130
|
model_params, init_with_params=True
|
|
2110
2131
|
)
|
|
2111
2132
|
model._raise_exception = False
|
|
2133
|
+
model._execution_mechanism = execution_mechanism_by_model_name.get(
|
|
2134
|
+
model_name
|
|
2135
|
+
)
|
|
2112
2136
|
model_objects.append(model)
|
|
2113
2137
|
self._async_object = ModelRunner(
|
|
2114
2138
|
model_selector=model_selector,
|
|
@@ -3018,6 +3042,7 @@ class RootFlowStep(FlowStep):
|
|
|
3018
3042
|
model_params, init_with_params=True
|
|
3019
3043
|
)
|
|
3020
3044
|
model._raise_exception = False
|
|
3045
|
+
model._execution_mechanism = self._shared_models_mechanism[model.name]
|
|
3021
3046
|
self.context.executor.add_runnable(
|
|
3022
3047
|
model, self._shared_models_mechanism[model.name]
|
|
3023
3048
|
)
|
mlrun/serving/system_steps.py
CHANGED
|
@@ -257,9 +257,10 @@ class MonitoringPreProcessor(storey.MapClass):
|
|
|
257
257
|
].get(
|
|
258
258
|
mlrun.common.schemas.MonitoringData.MODEL_ENDPOINT_UID
|
|
259
259
|
),
|
|
260
|
-
mm_schemas.StreamProcessingEvent.LABELS:
|
|
260
|
+
mm_schemas.StreamProcessingEvent.LABELS: event.body[
|
|
261
261
|
model
|
|
262
|
-
].get(
|
|
262
|
+
].get("labels")
|
|
263
|
+
or {},
|
|
263
264
|
mm_schemas.StreamProcessingEvent.FUNCTION_URI: self.server.function_uri
|
|
264
265
|
if self.server
|
|
265
266
|
else None,
|
|
@@ -301,19 +302,16 @@ class MonitoringPreProcessor(storey.MapClass):
|
|
|
301
302
|
mm_schemas.StreamProcessingEvent.ENDPOINT_ID: monitoring_data[
|
|
302
303
|
model
|
|
303
304
|
].get(mlrun.common.schemas.MonitoringData.MODEL_ENDPOINT_UID),
|
|
304
|
-
mm_schemas.StreamProcessingEvent.LABELS:
|
|
305
|
-
|
|
306
|
-
),
|
|
305
|
+
mm_schemas.StreamProcessingEvent.LABELS: event.body.get("labels")
|
|
306
|
+
or {},
|
|
307
307
|
mm_schemas.StreamProcessingEvent.FUNCTION_URI: self.server.function_uri
|
|
308
308
|
if self.server
|
|
309
309
|
else None,
|
|
310
310
|
mm_schemas.StreamProcessingEvent.REQUEST: request,
|
|
311
311
|
mm_schemas.StreamProcessingEvent.RESPONSE: resp,
|
|
312
|
-
mm_schemas.StreamProcessingEvent.ERROR: event.body
|
|
312
|
+
mm_schemas.StreamProcessingEvent.ERROR: event.body.get(
|
|
313
313
|
mm_schemas.StreamProcessingEvent.ERROR
|
|
314
|
-
|
|
315
|
-
if mm_schemas.StreamProcessingEvent.ERROR in event.body
|
|
316
|
-
else None,
|
|
314
|
+
),
|
|
317
315
|
mm_schemas.StreamProcessingEvent.METRICS: event.body[
|
|
318
316
|
mm_schemas.StreamProcessingEvent.METRICS
|
|
319
317
|
]
|
mlrun/utils/helpers.py
CHANGED
|
@@ -2464,15 +2464,16 @@ def merge_requirements(
|
|
|
2464
2464
|
return [str(req) for req in merged.values()]
|
|
2465
2465
|
|
|
2466
2466
|
|
|
2467
|
-
def
|
|
2467
|
+
def get_source_and_working_dir_paths(source_file_path) -> (pathlib.Path, pathlib.Path):
|
|
2468
2468
|
source_file_path_object = pathlib.Path(source_file_path).resolve()
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2469
|
+
working_dir_path_object = pathlib.Path(".").resolve()
|
|
2470
|
+
return source_file_path_object, working_dir_path_object
|
|
2471
|
+
|
|
2472
|
+
|
|
2473
|
+
def get_relative_module_name_from_path(
|
|
2474
|
+
source_file_path_object, working_dir_path_object
|
|
2475
|
+
) -> str:
|
|
2475
2476
|
relative_path_to_source_file = source_file_path_object.relative_to(
|
|
2476
|
-
|
|
2477
|
+
working_dir_path_object
|
|
2477
2478
|
)
|
|
2478
2479
|
return ".".join(relative_path_to_source_file.with_suffix("").parts)
|
mlrun/utils/version/version.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
mlrun/__init__.py,sha256=acM2jRv7RCvBROwucuC01Rf_HdvV3xUPtJlQtX_01MY,8076
|
|
2
2
|
mlrun/__main__.py,sha256=wQNaxW7QsqFBtWffnPkw-497fnpsrQzUnscBQQAP_UM,48364
|
|
3
|
-
mlrun/config.py,sha256=
|
|
3
|
+
mlrun/config.py,sha256=7t7F5jsPI1rO78-VzZv3q6QvzTIV6CZPZEQAJTmKwtM,73477
|
|
4
4
|
mlrun/errors.py,sha256=bAk0t_qmCxQSPNK0TugOAfA5R6f0G6OYvEvXUWSJ_5U,9062
|
|
5
5
|
mlrun/execution.py,sha256=Ozu8SjO-nQ6l5vHwqrTQjmP6koMpUqNQpp6qn6jvhVE,58802
|
|
6
6
|
mlrun/features.py,sha256=jMEXo6NB36A6iaxNEJWzdtYwUmglYD90OIKTIEeWhE8,15841
|
|
@@ -8,8 +8,8 @@ mlrun/k8s_utils.py,sha256=zIacVyvsXrXVO-DdxAoGQOGEDWOGJEFJzYPhPVnn3z8,24548
|
|
|
8
8
|
mlrun/lists.py,sha256=OlaV2QIFUzmenad9kxNJ3k4whlDyxI3zFbGwr6vpC5Y,8561
|
|
9
9
|
mlrun/model.py,sha256=JxYWYfMvRMloVEsxfghjH8gq5vsVCVk-OJmHGhbPJuU,88954
|
|
10
10
|
mlrun/render.py,sha256=5DlhD6JtzHgmj5RVlpaYiHGhX84Q7qdi4RCEUj2UMgw,13195
|
|
11
|
-
mlrun/run.py,sha256=
|
|
12
|
-
mlrun/secrets.py,sha256=
|
|
11
|
+
mlrun/run.py,sha256=DRlXYf9C4ZJeGeXdbQxgeCKhoV2892u0v0yIfsyDSkA,49730
|
|
12
|
+
mlrun/secrets.py,sha256=VFETVDJFZ0AGDivYjhYscO_YHnzeBnAebxlio7Svkq0,9633
|
|
13
13
|
mlrun/alerts/__init__.py,sha256=0gtG1BG0DXxFrXegIkjbM1XEN4sP9ODo0ucXrNld1hU,601
|
|
14
14
|
mlrun/alerts/alert.py,sha256=QQFZGydQbx9RvAaSiaH-ALQZVcDKQX5lgizqj_rXW2k,15948
|
|
15
15
|
mlrun/artifacts/__init__.py,sha256=ZrEUNto7tGdnBGteCp9zOyO8b78z7O3xgcpzUt9UHE4,1240
|
|
@@ -116,10 +116,10 @@ mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev
|
|
|
116
116
|
mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
|
|
117
117
|
mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
|
|
118
118
|
mlrun/db/auth_utils.py,sha256=hpg8D2r82oN0BWabuWN04BTNZ7jYMAF242YSUpK7LFM,5211
|
|
119
|
-
mlrun/db/base.py,sha256=
|
|
119
|
+
mlrun/db/base.py,sha256=8K0KlVfsGce1LgoB7pVOQCmQ2ceBnDz13PJlba1xuSw,32461
|
|
120
120
|
mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
|
|
121
|
-
mlrun/db/httpdb.py,sha256=
|
|
122
|
-
mlrun/db/nopdb.py,sha256=
|
|
121
|
+
mlrun/db/httpdb.py,sha256=QLQDhzALh6NQdpzTSw9H9XfQR9NFvnG1qct9N2dLtsk,239271
|
|
122
|
+
mlrun/db/nopdb.py,sha256=gi6O0ZSxC3PhRBeIjTTL1rIDVHp4GhJLlD1PM1I17Gs,28827
|
|
123
123
|
mlrun/feature_store/__init__.py,sha256=SlI845bWt6xX34SXunHHqhmFAR9-5v2ak8N-qpcAPGo,1328
|
|
124
124
|
mlrun/feature_store/api.py,sha256=qKj5Tk6prTab6XWatWhBuPRVp0eJEctoxRMN2wz48vA,32168
|
|
125
125
|
mlrun/feature_store/common.py,sha256=JlQA7XWkg9fLuw7cXFmWpUneQqM3NBhwv7DU_xlenWI,12819
|
|
@@ -236,7 +236,7 @@ mlrun/model_monitoring/stream_processing.py,sha256=bryYO3D0cC10MAQ-liHxUZ79MrL-V
|
|
|
236
236
|
mlrun/model_monitoring/writer.py,sha256=l2D_5Ms5Wq5jfyQRVJbGBBRTMLjMmIAxwPeHWmrc9Kg,16382
|
|
237
237
|
mlrun/model_monitoring/applications/__init__.py,sha256=BwlmRELlFJf2b2YMyv5kUSHNe8--OyqWhDgRlT8a_8g,779
|
|
238
238
|
mlrun/model_monitoring/applications/_application_steps.py,sha256=t9LDIqQUGE10cyjyhlg0QqN1yVx0apD1HpERYLJfm8U,7409
|
|
239
|
-
mlrun/model_monitoring/applications/base.py,sha256=
|
|
239
|
+
mlrun/model_monitoring/applications/base.py,sha256=f3WWMoXinsqzWtYebQnsMCGhi7M50E8LdeYmQl5QXjg,51339
|
|
240
240
|
mlrun/model_monitoring/applications/context.py,sha256=3W3AW4oyJgx_nW_5mDsV59Iy5D3frkfYMQSc6DgBc4c,17004
|
|
241
241
|
mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=2qgfFmrpHf-x0_EaHD-0T28piwSQzw-HH71aV1GwbZs,15389
|
|
242
242
|
mlrun/model_monitoring/applications/results.py,sha256=LfBQOmkpKGvVGNrcj5QiXsRIG2IRgcv_Xqe4QJBmauk,5699
|
|
@@ -252,7 +252,7 @@ mlrun/model_monitoring/db/tsdb/tdengine/__init__.py,sha256=vgBdsKaXUURKqIf3M0y4s
|
|
|
252
252
|
mlrun/model_monitoring/db/tsdb/tdengine/schemas.py,sha256=TuWuaCZw8sV1gSwN2BPmW8Gzwe3dsRN__KkJB9lum00,13116
|
|
253
253
|
mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py,sha256=Uadj0UvAmln2MxDWod-kAzau1uNlqZh981rPhbUH_5M,2857
|
|
254
254
|
mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py,sha256=dtkaHaWKWERPXylEWMECeetwrz3rWl0P43AADcTjlls,9330
|
|
255
|
-
mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=
|
|
255
|
+
mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=qq-2Slk9jHc18lUx00w4Oj5_EfnZXlmkvLXPDSbz1zY,54341
|
|
256
256
|
mlrun/model_monitoring/db/tsdb/tdengine/writer_graph_steps.py,sha256=zMof6hUr0dsyor73pnOWkJP62INAvslHU0nUklbT-3w,2053
|
|
257
257
|
mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
|
|
258
258
|
mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=sNQFj6qyJx5eSBKRC3gyTc1cfh1l2IkRpPtuZwtzCW0,6844
|
|
@@ -303,11 +303,11 @@ mlrun/runtimes/mpijob/abstract.py,sha256=QjAG4OZ6JEQ58w5-qYNd6hUGwvaW8ynLtlr9jNf
|
|
|
303
303
|
mlrun/runtimes/mpijob/v1.py,sha256=zSlRkiWHz4B3yht66sVf4mlfDs8YT9EnP9DfBLn5VNs,3372
|
|
304
304
|
mlrun/runtimes/nuclio/__init__.py,sha256=osOVMN9paIOuUoOTizmkxMb_OXRP-SlPwXHJSSYK_wk,834
|
|
305
305
|
mlrun/runtimes/nuclio/api_gateway.py,sha256=vH9ClKVP4Mb24rvA67xPuAvAhX-gAv6vVtjVxyplhdc,26969
|
|
306
|
-
mlrun/runtimes/nuclio/function.py,sha256=
|
|
306
|
+
mlrun/runtimes/nuclio/function.py,sha256=yL6PVyddDFEhXxY93g8YiywBERi-oqlpEw8IE3BVGmQ,56006
|
|
307
307
|
mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha6E,2942
|
|
308
|
-
mlrun/runtimes/nuclio/serving.py,sha256=
|
|
308
|
+
mlrun/runtimes/nuclio/serving.py,sha256=eXffwn6xTvEwC-HEk42DRxywOrin7RMUze3JWjeBxzA,36429
|
|
309
309
|
mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
|
|
310
|
-
mlrun/runtimes/nuclio/application/application.py,sha256=
|
|
310
|
+
mlrun/runtimes/nuclio/application/application.py,sha256=usovOWonpzHQ1B_El7l60y-jpUXyYwppjmrHlP5RMW8,33993
|
|
311
311
|
mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=lEHH74vr2PridIHp1Jkc_NjkrWb5b6zawRrNxHQhwGU,2913
|
|
312
312
|
mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
|
|
313
313
|
mlrun/runtimes/sparkjob/spark3job.py,sha256=3dW7RG2T58F2dsUw0TsRvE3SIFcekx3CerLdcaG1f50,41458
|
|
@@ -315,11 +315,11 @@ mlrun/serving/__init__.py,sha256=nriJAcVn5aatwU03T7SsE6ngJEGTxr3wIGt4WuvCCzY,139
|
|
|
315
315
|
mlrun/serving/merger.py,sha256=pfOQoozUyObCTpqXAMk94PmhZefn4bBrKufO3MKnkAc,6193
|
|
316
316
|
mlrun/serving/remote.py,sha256=p29CBtKwbW_l8BzmNg3Uy__0eMf7_OubTMzga_S3EOA,22089
|
|
317
317
|
mlrun/serving/routers.py,sha256=pu5jlSLI4Ml68YP_FMFDhhwPfLcT6lRu5yL5QDgXPHQ,52889
|
|
318
|
-
mlrun/serving/server.py,sha256=
|
|
318
|
+
mlrun/serving/server.py,sha256=UIQON9ytG_4VUa4cMWZ8AxxBzGjBrhFhkC-FrvAHa_o,42593
|
|
319
319
|
mlrun/serving/serving_wrapper.py,sha256=UL9hhWCfMPcTJO_XrkvNaFvck1U1E7oS8trTZyak0cA,835
|
|
320
|
-
mlrun/serving/states.py,sha256=
|
|
320
|
+
mlrun/serving/states.py,sha256=zSaELw7et0tAHa0nZ2_zKTPdxqnXo4WOCwclULkN6no,140363
|
|
321
321
|
mlrun/serving/steps.py,sha256=zbMgJnu-m4n7vhFRgZkCMMifIsCya-TzAj3Gjc-Fgnc,2193
|
|
322
|
-
mlrun/serving/system_steps.py,sha256=
|
|
322
|
+
mlrun/serving/system_steps.py,sha256=BDCJn73h7cUT5AoSSm25Fjg4WwzcEpMQp-ZjMw9ogEc,20025
|
|
323
323
|
mlrun/serving/utils.py,sha256=Zbfqm8TKNcTE8zRBezVBzpvR2WKeKeIRN7otNIaiYEc,4170
|
|
324
324
|
mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
|
|
325
325
|
mlrun/serving/v2_serving.py,sha256=FbN5QAurWL_KoKMUgRLV7b227PpnvntY5tPNE36J42E,25270
|
|
@@ -333,7 +333,7 @@ mlrun/utils/async_http.py,sha256=8Olx8TNNeXB07nEGwlqhEgFgnFAD71vBU_bqaA9JW-w,122
|
|
|
333
333
|
mlrun/utils/azure_vault.py,sha256=IEFizrDGDbAaoWwDr1WoA88S_EZ0T--vjYtY-i0cvYQ,3450
|
|
334
334
|
mlrun/utils/clones.py,sha256=qbAGyEbSvlewn3Tw_DpQZP9z6MGzFhSaZfI1CblX8Fg,7515
|
|
335
335
|
mlrun/utils/condition_evaluator.py,sha256=-nGfRmZzivn01rHTroiGY4rqEv8T1irMyhzxEei-sKc,1897
|
|
336
|
-
mlrun/utils/helpers.py,sha256=
|
|
336
|
+
mlrun/utils/helpers.py,sha256=zwaGatCEJphJEcTwvEOjiyGDWNSEDkzzYcR4IWsu378,84268
|
|
337
337
|
mlrun/utils/http.py,sha256=5ZU2VpokaUM_DT3HBSqTm8xjUqTPjZN5fKkSIvKlTl0,8704
|
|
338
338
|
mlrun/utils/logger.py,sha256=uaCgI_ezzaXf7nJDCy-1Nrjds8vSXqDbzmjmb3IyCQo,14864
|
|
339
339
|
mlrun/utils/regex.py,sha256=FcRwWD8x9X3HLhCCU2F0AVKTFah784Pr7ZAe3a02jw8,5199
|
|
@@ -352,11 +352,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
|
|
|
352
352
|
mlrun/utils/notifications/notification/slack.py,sha256=wSu_7W0EnGLBNwIgWCYEeTP8j9SPAMPDBnfUcPnVZYA,7299
|
|
353
353
|
mlrun/utils/notifications/notification/webhook.py,sha256=FM5-LQAKAVJKp37MRzR3SsejalcnpM6r_9Oe7znxZEA,5313
|
|
354
354
|
mlrun/utils/version/__init__.py,sha256=YnzE6tlf24uOQ8y7Z7l96QLAI6-QEii7-77g8ynmzy0,613
|
|
355
|
-
mlrun/utils/version/version.json,sha256=
|
|
355
|
+
mlrun/utils/version/version.json,sha256=hHIsu87_e3inXvZwxyAJBc1LtA2aFWqipBV_Mhx1n5o,90
|
|
356
356
|
mlrun/utils/version/version.py,sha256=M2hVhRrgkN3SxacZHs3ZqaOsqAA7B6a22ne324IQ1HE,1877
|
|
357
|
-
mlrun-1.10.
|
|
358
|
-
mlrun-1.10.
|
|
359
|
-
mlrun-1.10.
|
|
360
|
-
mlrun-1.10.
|
|
361
|
-
mlrun-1.10.
|
|
362
|
-
mlrun-1.10.
|
|
357
|
+
mlrun-1.10.0rc38.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
|
|
358
|
+
mlrun-1.10.0rc38.dist-info/METADATA,sha256=OGc4TY9eDtdLJ9NU5R8OsR_go-Wcm1VheehWzXs5yeE,26104
|
|
359
|
+
mlrun-1.10.0rc38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
360
|
+
mlrun-1.10.0rc38.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
|
|
361
|
+
mlrun-1.10.0rc38.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
|
|
362
|
+
mlrun-1.10.0rc38.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|