mlrun 1.8.0rc5__py3-none-any.whl → 1.8.0rc9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +1 -0
- mlrun/artifacts/__init__.py +1 -1
- mlrun/artifacts/base.py +21 -1
- mlrun/artifacts/document.py +62 -39
- mlrun/artifacts/manager.py +12 -5
- mlrun/common/constants.py +1 -0
- mlrun/common/model_monitoring/__init__.py +0 -2
- mlrun/common/model_monitoring/helpers.py +0 -28
- mlrun/common/schemas/__init__.py +2 -4
- mlrun/common/schemas/alert.py +77 -1
- mlrun/common/schemas/client_spec.py +0 -1
- mlrun/common/schemas/model_monitoring/__init__.py +0 -6
- mlrun/common/schemas/model_monitoring/constants.py +11 -9
- mlrun/common/schemas/model_monitoring/model_endpoints.py +77 -149
- mlrun/common/schemas/notification.py +6 -0
- mlrun/common/schemas/project.py +3 -0
- mlrun/config.py +2 -3
- mlrun/datastore/datastore_profile.py +57 -17
- mlrun/datastore/sources.py +1 -2
- mlrun/datastore/store_resources.py +7 -2
- mlrun/datastore/vectorstore.py +99 -62
- mlrun/db/base.py +34 -20
- mlrun/db/httpdb.py +249 -163
- mlrun/db/nopdb.py +40 -17
- mlrun/execution.py +14 -7
- mlrun/feature_store/api.py +1 -0
- mlrun/model.py +3 -0
- mlrun/model_monitoring/__init__.py +3 -2
- mlrun/model_monitoring/api.py +64 -53
- mlrun/model_monitoring/applications/_application_steps.py +3 -1
- mlrun/model_monitoring/applications/base.py +115 -15
- mlrun/model_monitoring/applications/context.py +42 -24
- mlrun/model_monitoring/applications/histogram_data_drift.py +1 -1
- mlrun/model_monitoring/controller.py +43 -37
- mlrun/model_monitoring/db/__init__.py +0 -2
- mlrun/model_monitoring/db/tsdb/base.py +2 -1
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +2 -1
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +43 -0
- mlrun/model_monitoring/helpers.py +78 -66
- mlrun/model_monitoring/stream_processing.py +83 -270
- mlrun/model_monitoring/writer.py +1 -10
- mlrun/projects/pipelines.py +37 -1
- mlrun/projects/project.py +173 -70
- mlrun/run.py +40 -0
- mlrun/runtimes/nuclio/function.py +7 -6
- mlrun/runtimes/nuclio/serving.py +9 -4
- mlrun/serving/routers.py +158 -145
- mlrun/serving/server.py +6 -0
- mlrun/serving/states.py +21 -7
- mlrun/serving/v2_serving.py +94 -68
- mlrun/utils/helpers.py +23 -33
- mlrun/utils/notifications/notification/mail.py +17 -6
- mlrun/utils/notifications/notification_pusher.py +9 -5
- mlrun/utils/regex.py +8 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/METADATA +2 -2
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/RECORD +61 -74
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +0 -149
- mlrun/model_monitoring/db/stores/__init__.py +0 -136
- mlrun/model_monitoring/db/stores/base/__init__.py +0 -15
- mlrun/model_monitoring/db/stores/base/store.py +0 -154
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -46
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -93
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +0 -47
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +0 -408
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +0 -13
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +0 -464
- mlrun/model_monitoring/model_endpoint.py +0 -120
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/LICENSE +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/WHEEL +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/entry_points.txt +0 -0
- {mlrun-1.8.0rc5.dist-info → mlrun-1.8.0rc9.dist-info}/top_level.txt +0 -0
mlrun/serving/routers.py
CHANGED
|
@@ -28,10 +28,9 @@ import numpy as np
|
|
|
28
28
|
import mlrun
|
|
29
29
|
import mlrun.common.model_monitoring
|
|
30
30
|
import mlrun.common.schemas.model_monitoring
|
|
31
|
-
from mlrun.errors import err_to_str
|
|
32
31
|
from mlrun.utils import logger, now_date
|
|
33
32
|
|
|
34
|
-
from ..common.
|
|
33
|
+
from ..common.schemas.model_monitoring import ModelEndpointSchema
|
|
35
34
|
from .server import GraphServer
|
|
36
35
|
from .utils import RouterToDict, _extract_input_data, _update_result_body
|
|
37
36
|
from .v2_serving import _ModelLogPusher
|
|
@@ -814,7 +813,8 @@ class VotingEnsemble(ParallelRun):
|
|
|
814
813
|
return self.logic(flattened_predictions, np.array(weights))
|
|
815
814
|
|
|
816
815
|
def do_event(self, event, *args, **kwargs):
|
|
817
|
-
"""
|
|
816
|
+
"""
|
|
817
|
+
Handles incoming requests.
|
|
818
818
|
|
|
819
819
|
Parameters
|
|
820
820
|
----------
|
|
@@ -1016,116 +1016,124 @@ def _init_endpoint_record(
|
|
|
1016
1016
|
"""
|
|
1017
1017
|
|
|
1018
1018
|
logger.info("Initializing endpoint records")
|
|
1019
|
-
|
|
1020
|
-
# Generate required values for the model endpoint record
|
|
1021
|
-
try:
|
|
1022
|
-
# Getting project name from the function uri
|
|
1023
|
-
project, uri, tag, hash_key = parse_versioned_object_uri(
|
|
1024
|
-
graph_server.function_uri
|
|
1025
|
-
)
|
|
1026
|
-
except Exception as e:
|
|
1027
|
-
logger.error("Failed to parse function URI", exc=err_to_str(e))
|
|
1028
|
-
return None
|
|
1029
|
-
|
|
1030
|
-
# Generating version model value based on the model name and model version
|
|
1031
|
-
if voting_ensemble.version:
|
|
1032
|
-
versioned_model_name = f"{voting_ensemble.name}:{voting_ensemble.version}"
|
|
1033
|
-
else:
|
|
1034
|
-
versioned_model_name = f"{voting_ensemble.name}:latest"
|
|
1035
|
-
|
|
1036
|
-
# Generating model endpoint ID based on function uri and model version
|
|
1037
|
-
endpoint_uid = mlrun.common.model_monitoring.create_model_endpoint_uid(
|
|
1038
|
-
function_uri=graph_server.function_uri, versioned_model=versioned_model_name
|
|
1039
|
-
).uid
|
|
1040
|
-
|
|
1041
1019
|
try:
|
|
1042
|
-
|
|
1043
|
-
project=project,
|
|
1020
|
+
model_endpoint = mlrun.get_run_db().get_model_endpoint(
|
|
1021
|
+
project=graph_server.project,
|
|
1022
|
+
name=voting_ensemble.name,
|
|
1023
|
+
function_name=graph_server.function_name,
|
|
1024
|
+
function_tag=graph_server.function_tag or "latest",
|
|
1044
1025
|
)
|
|
1045
1026
|
except mlrun.errors.MLRunNotFoundError:
|
|
1046
|
-
|
|
1027
|
+
model_endpoint = None
|
|
1047
1028
|
except mlrun.errors.MLRunBadRequestError as err:
|
|
1048
|
-
logger.
|
|
1049
|
-
|
|
1029
|
+
logger.info(
|
|
1030
|
+
"Cannot get the model endpoints store", err=mlrun.errors.err_to_str(err)
|
|
1050
1031
|
)
|
|
1051
1032
|
return
|
|
1052
1033
|
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1034
|
+
function = mlrun.get_run_db().get_function(
|
|
1035
|
+
name=graph_server.function_name,
|
|
1036
|
+
project=graph_server.project,
|
|
1037
|
+
tag=graph_server.function_tag or "latest",
|
|
1038
|
+
)
|
|
1039
|
+
function_uid = function.get("metadata", {}).get("uid")
|
|
1040
|
+
# Get the children model endpoints ids
|
|
1041
|
+
children_uids = []
|
|
1042
|
+
children_names = []
|
|
1043
|
+
for _, c in voting_ensemble.routes.items():
|
|
1044
|
+
if hasattr(c, "endpoint_uid"):
|
|
1045
|
+
children_uids.append(c.endpoint_uid)
|
|
1046
|
+
children_names.append(c.name)
|
|
1047
|
+
if not model_endpoint and voting_ensemble.context.server.track_models:
|
|
1048
|
+
logger.info(
|
|
1049
|
+
"Creating a new model endpoint record",
|
|
1050
|
+
name=voting_ensemble.name,
|
|
1051
|
+
project=graph_server.project,
|
|
1052
|
+
function_name=graph_server.function_name,
|
|
1053
|
+
function_tag=graph_server.function_tag or "latest",
|
|
1054
|
+
function_uid=function_uid,
|
|
1055
|
+
model_class=voting_ensemble.__class__.__name__,
|
|
1056
|
+
)
|
|
1060
1057
|
model_endpoint = mlrun.common.schemas.ModelEndpoint(
|
|
1061
1058
|
metadata=mlrun.common.schemas.ModelEndpointMetadata(
|
|
1062
|
-
project=project,
|
|
1059
|
+
project=graph_server.project,
|
|
1060
|
+
name=voting_ensemble.name,
|
|
1061
|
+
endpoint_type=mlrun.common.schemas.model_monitoring.EndpointType.ROUTER,
|
|
1063
1062
|
),
|
|
1064
1063
|
spec=mlrun.common.schemas.ModelEndpointSpec(
|
|
1065
|
-
|
|
1066
|
-
|
|
1064
|
+
function_name=graph_server.function_name,
|
|
1065
|
+
function_uid=function_uid,
|
|
1066
|
+
function_tag=graph_server.function_tag or "latest",
|
|
1067
1067
|
model_class=voting_ensemble.__class__.__name__,
|
|
1068
|
-
|
|
1069
|
-
active=True,
|
|
1070
|
-
monitoring_mode=mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled,
|
|
1068
|
+
children_uids=list(voting_ensemble.routes.keys()),
|
|
1071
1069
|
),
|
|
1072
1070
|
status=mlrun.common.schemas.ModelEndpointStatus(
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1071
|
+
monitoring_mode=mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled
|
|
1072
|
+
if voting_ensemble.context.server.track_models
|
|
1073
|
+
else mlrun.common.schemas.model_monitoring.ModelMonitoringMode.disabled,
|
|
1076
1074
|
),
|
|
1077
1075
|
)
|
|
1078
|
-
|
|
1079
1076
|
db = mlrun.get_run_db()
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1077
|
+
db.create_model_endpoint(model_endpoint=model_endpoint)
|
|
1078
|
+
|
|
1079
|
+
elif model_endpoint:
|
|
1080
|
+
attributes = {}
|
|
1081
|
+
if function_uid != model_endpoint.spec.function_uid:
|
|
1082
|
+
attributes[ModelEndpointSchema.FUNCTION_UID] = function_uid
|
|
1083
|
+
if children_uids != model_endpoint.spec.children_uids:
|
|
1084
|
+
attributes[ModelEndpointSchema.CHILDREN_UIDS] = children_uids
|
|
1085
|
+
if (
|
|
1086
|
+
model_endpoint.status.monitoring_mode
|
|
1087
|
+
== mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled
|
|
1088
|
+
) != voting_ensemble.context.server.track_models:
|
|
1089
|
+
attributes[ModelEndpointSchema.MONITORING_MODE] = (
|
|
1090
|
+
mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled
|
|
1091
|
+
if voting_ensemble.context.server.track_models
|
|
1092
|
+
else mlrun.common.schemas.model_monitoring.ModelMonitoringMode.disabled
|
|
1091
1093
|
)
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
+
if attributes:
|
|
1095
|
+
db = mlrun.get_run_db()
|
|
1096
|
+
logger.info(
|
|
1097
|
+
"Updating model endpoint attributes",
|
|
1098
|
+
attributes=attributes,
|
|
1099
|
+
project=model_endpoint.metadata.project,
|
|
1100
|
+
name=model_endpoint.metadata.name,
|
|
1101
|
+
function_name=model_endpoint.spec.function_name,
|
|
1094
1102
|
)
|
|
1095
|
-
db.
|
|
1096
|
-
project=project,
|
|
1097
|
-
|
|
1098
|
-
model_endpoint
|
|
1103
|
+
model_endpoint = db.patch_model_endpoint(
|
|
1104
|
+
project=model_endpoint.metadata.project,
|
|
1105
|
+
name=model_endpoint.metadata.name,
|
|
1106
|
+
endpoint_id=model_endpoint.metadata.uid,
|
|
1107
|
+
attributes=attributes,
|
|
1099
1108
|
)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
model_ep.spec.monitoring_mode
|
|
1104
|
-
== mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled
|
|
1105
|
-
)
|
|
1106
|
-
!= voting_ensemble.context.server.track_models
|
|
1107
|
-
):
|
|
1108
|
-
monitoring_mode = (
|
|
1109
|
-
mlrun.common.schemas.model_monitoring.ModelMonitoringMode.enabled
|
|
1110
|
-
if voting_ensemble.context.server.track_models
|
|
1111
|
-
else mlrun.common.schemas.model_monitoring.ModelMonitoringMode.disabled
|
|
1112
|
-
)
|
|
1113
|
-
db = mlrun.get_run_db()
|
|
1114
|
-
db.patch_model_endpoint(
|
|
1115
|
-
project=project,
|
|
1116
|
-
endpoint_id=endpoint_uid,
|
|
1117
|
-
attributes={"monitoring_mode": monitoring_mode},
|
|
1118
|
-
)
|
|
1119
|
-
logger.debug(
|
|
1120
|
-
f"Updating model endpoint monitoring_mode to {monitoring_mode}",
|
|
1121
|
-
endpoint_id=endpoint_uid,
|
|
1109
|
+
else:
|
|
1110
|
+
logger.info(
|
|
1111
|
+
"Did not create a new model endpoint record, monitoring is disabled"
|
|
1122
1112
|
)
|
|
1113
|
+
return None
|
|
1123
1114
|
|
|
1124
|
-
|
|
1115
|
+
# Update model endpoint children type
|
|
1116
|
+
logger.info(
|
|
1117
|
+
"Updating children model endpoint type",
|
|
1118
|
+
children_uids=children_uids,
|
|
1119
|
+
children_names=children_names,
|
|
1120
|
+
)
|
|
1121
|
+
for uid, name in zip(children_uids, children_names):
|
|
1122
|
+
mlrun.get_run_db().patch_model_endpoint(
|
|
1123
|
+
name=name,
|
|
1124
|
+
project=graph_server.project,
|
|
1125
|
+
endpoint_id=uid,
|
|
1126
|
+
attributes={
|
|
1127
|
+
ModelEndpointSchema.ENDPOINT_TYPE: mlrun.common.schemas.model_monitoring.EndpointType.LEAF_EP
|
|
1128
|
+
},
|
|
1129
|
+
)
|
|
1130
|
+
return model_endpoint.metadata.uid
|
|
1125
1131
|
|
|
1126
1132
|
|
|
1127
1133
|
class EnrichmentModelRouter(ModelRouter):
|
|
1128
|
-
"""
|
|
1134
|
+
"""
|
|
1135
|
+
Model router with feature enrichment and imputing
|
|
1136
|
+
"""
|
|
1129
1137
|
|
|
1130
1138
|
def __init__(
|
|
1131
1139
|
self,
|
|
@@ -1139,7 +1147,8 @@ class EnrichmentModelRouter(ModelRouter):
|
|
|
1139
1147
|
impute_policy: typing.Optional[dict] = None,
|
|
1140
1148
|
**kwargs,
|
|
1141
1149
|
):
|
|
1142
|
-
"""
|
|
1150
|
+
"""
|
|
1151
|
+
Model router with feature enrichment (from the feature store)
|
|
1143
1152
|
|
|
1144
1153
|
The `EnrichmentModelRouter` class enrich the incoming event with real-time features
|
|
1145
1154
|
read from a feature vector (in MLRun feature store) and forwards the enriched event to the child models
|
|
@@ -1147,27 +1156,25 @@ class EnrichmentModelRouter(ModelRouter):
|
|
|
1147
1156
|
The feature vector is specified using the `feature_vector_uri`, in addition an imputing policy
|
|
1148
1157
|
can be specified to substitute None/NaN values with pre defines constant or stats.
|
|
1149
1158
|
|
|
1150
|
-
:param feature_vector_uri
|
|
1151
|
-
:param impute_policy
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
impute_policy={"*": "$mean", "age": 33}
|
|
1159
|
+
:param feature_vector_uri: feature vector uri in the form: [project/]name[:tag]
|
|
1160
|
+
:param impute_policy: value imputing (substitute NaN/Inf values with statistical or constant value),
|
|
1161
|
+
you can set the `impute_policy` parameter with the imputing policy, and specify which constant or
|
|
1162
|
+
statistical value will be used instead of NaN/Inf value, this can be defined per column or
|
|
1163
|
+
for all the columns ("*"). The replaced value can be fixed number for constants or $mean, $max, $min, $std,
|
|
1164
|
+
$count for statistical values.
|
|
1165
|
+
“*” is used to specify the default for all features, example: impute_policy={"*": "$mean", "age": 33}
|
|
1158
1166
|
:param context: for internal use (passed in init)
|
|
1159
1167
|
:param name: step name
|
|
1160
1168
|
:param routes: for internal use (routes passed in init)
|
|
1161
1169
|
:param protocol: serving API protocol (default "v2")
|
|
1162
1170
|
:param url_prefix: url prefix for the router (default /v2/models)
|
|
1163
1171
|
:param health_prefix: health api url prefix (default /v2/health)
|
|
1164
|
-
:param input_path: when specified selects the key/path in the event to use as body
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
:param result_path: selects the key/path in the event to write the results to
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
to event["y"] resulting in {"x": 5, "resp": <result>}
|
|
1172
|
+
:param input_path: when specified selects the key/path in the event to use as body this require that the
|
|
1173
|
+
event body will behave like a dict, example: event: {"data": {"a": 5, "b": 7}}, input_path="data.b"
|
|
1174
|
+
means request body will be 7.
|
|
1175
|
+
:param result_path: selects the key/path in the event to write the results to this require that the event body
|
|
1176
|
+
will behave like a dict, example: event: {"x": 5} , result_path="resp" means the returned response will be
|
|
1177
|
+
written to event["y"] resulting in {"x": 5, "resp": <result>}
|
|
1171
1178
|
:param kwargs: extra arguments
|
|
1172
1179
|
"""
|
|
1173
1180
|
super().__init__(
|
|
@@ -1206,7 +1213,9 @@ class EnrichmentModelRouter(ModelRouter):
|
|
|
1206
1213
|
|
|
1207
1214
|
|
|
1208
1215
|
class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
1209
|
-
"""
|
|
1216
|
+
"""
|
|
1217
|
+
Voting Ensemble with feature enrichment (from the feature store)
|
|
1218
|
+
"""
|
|
1210
1219
|
|
|
1211
1220
|
def __init__(
|
|
1212
1221
|
self,
|
|
@@ -1223,16 +1232,18 @@ class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
|
1223
1232
|
impute_policy: typing.Optional[dict] = None,
|
|
1224
1233
|
**kwargs,
|
|
1225
1234
|
):
|
|
1226
|
-
"""
|
|
1235
|
+
"""
|
|
1236
|
+
Voting Ensemble with feature enrichment (from the feature store)
|
|
1227
1237
|
|
|
1228
1238
|
The `EnrichmentVotingEnsemble` class enables to enrich the incoming event with real-time features
|
|
1229
1239
|
read from a feature vector (in MLRun feature store) and apply prediction logic on top of
|
|
1230
1240
|
the different added models.
|
|
1231
1241
|
|
|
1232
1242
|
You can use it by calling:
|
|
1233
|
-
|
|
1243
|
+
|
|
1244
|
+
- `<prefix>/<model>[/versions/<ver>]/operation`
|
|
1234
1245
|
Sends the event to the specific <model>[/versions/<ver>]
|
|
1235
|
-
-
|
|
1246
|
+
- `<prefix>/operation`
|
|
1236
1247
|
Sends the event to all models and applies `vote(self, event)`
|
|
1237
1248
|
|
|
1238
1249
|
The `VotingEnsemble` applies the following logic:
|
|
@@ -1243,7 +1254,7 @@ class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
|
1243
1254
|
The feature vector is specified using the `feature_vector_uri`, in addition an imputing policy
|
|
1244
1255
|
can be specified to substitute None/NaN values with pre defines constant or stats.
|
|
1245
1256
|
|
|
1246
|
-
|
|
1257
|
+
When enabling model tracking via `set_tracking()` the ensemble logic
|
|
1247
1258
|
predictions will appear with model name as the given VotingEnsemble name
|
|
1248
1259
|
or "VotingEnsemble" by default.
|
|
1249
1260
|
|
|
@@ -1251,17 +1262,20 @@ class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
|
1251
1262
|
|
|
1252
1263
|
# Define a serving function
|
|
1253
1264
|
# Note: You can point the function to a file containing you own Router or Classifier Model class
|
|
1254
|
-
#
|
|
1255
|
-
fn = mlrun.code_to_function(
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1265
|
+
# this basic class supports sklearn based models (with `<model>.predict()` api)
|
|
1266
|
+
fn = mlrun.code_to_function(
|
|
1267
|
+
name='ensemble',
|
|
1268
|
+
kind='serving',
|
|
1269
|
+
filename='model-server.py',
|
|
1270
|
+
image='mlrun/mlrun')
|
|
1271
|
+
|
|
1259
1272
|
|
|
1260
1273
|
# Set the router class
|
|
1261
1274
|
# You can set your own classes by simply changing the `class_name`
|
|
1262
|
-
fn.set_topology(
|
|
1263
|
-
|
|
1264
|
-
|
|
1275
|
+
fn.set_topology(
|
|
1276
|
+
class_name='mlrun.serving.routers.EnrichmentVotingEnsemble',
|
|
1277
|
+
feature_vector_uri="transactions-fraud",
|
|
1278
|
+
impute_policy={"*": "$mean"})
|
|
1265
1279
|
|
|
1266
1280
|
# Add models
|
|
1267
1281
|
fn.add_model(<model_name>, <model_path>, <model_class_name>)
|
|
@@ -1283,35 +1297,32 @@ class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
|
1283
1297
|
:param context: for internal use (passed in init)
|
|
1284
1298
|
:param name: step name
|
|
1285
1299
|
:param routes: for internal use (routes passed in init)
|
|
1286
|
-
:param protocol: serving API protocol (default
|
|
1287
|
-
:param url_prefix: url prefix for the router (default
|
|
1288
|
-
:param health_prefix: health api url prefix (default
|
|
1289
|
-
:param feature_vector_uri
|
|
1290
|
-
:param impute_policy
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
- float prediction type: regression
|
|
1307
|
-
- int prediction type: classification
|
|
1300
|
+
:param protocol: serving API protocol (default `v2`)
|
|
1301
|
+
:param url_prefix: url prefix for the router (default `/v2/models`)
|
|
1302
|
+
:param health_prefix: health api url prefix (default `/v2/health`)
|
|
1303
|
+
:param feature_vector_uri: feature vector uri in the form `[project/]name[:tag]`
|
|
1304
|
+
:param impute_policy: value imputing (substitute NaN/Inf values with statistical or constant value),
|
|
1305
|
+
you can set the `impute_policy` parameter with the imputing policy, and specify which constant or
|
|
1306
|
+
statistical value will be used instead of NaN/Inf value, this can be defined per column or for all
|
|
1307
|
+
the columns ("*"). The replaced value can be fixed number for constants or $mean, $max, $min, $std, $count
|
|
1308
|
+
for statistical values. “*” is used to specify the default for all features,
|
|
1309
|
+
example: impute_policy={"*": "$mean", "age": 33}
|
|
1310
|
+
:param input_path: when specified selects the key/path in the event to use as body this require that
|
|
1311
|
+
the event body will behave like a dict, example: event: {"data": {"a": 5, "b": 7}}, input_path="data.b"
|
|
1312
|
+
means request body will be 7.
|
|
1313
|
+
:param result_path: selects the key/path in the event to write the results to this require that the event body
|
|
1314
|
+
will behave like a dict, example: event: {"x": 5} , result_path="resp" means the returned response will be
|
|
1315
|
+
written to event["y"] resulting in {"x": 5, "resp": <result>}.
|
|
1316
|
+
:param vote_type: Voting type to be used (from `VotingTypes`). by default will try to self-deduct upon the
|
|
1317
|
+
first event:
|
|
1318
|
+
* float prediction type: regression
|
|
1319
|
+
* int prediction type: classification
|
|
1308
1320
|
:param executor_type: Parallelism mechanism, out of `ParallelRunnerModes`, by default `threads`
|
|
1309
1321
|
:param prediction_col_name: The dict key for the predictions column in the model's responses output.
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
:param kwargs: extra arguments
|
|
1322
|
+
Example:
|
|
1323
|
+
If the model returns `{id: <id>, model_name: <name>, outputs: {..., prediction: [<predictions>], ...}}`,
|
|
1324
|
+
the prediction_col_name should be `prediction`. By default, `prediction`.
|
|
1325
|
+
:param kwargs: extra arguments
|
|
1315
1326
|
"""
|
|
1316
1327
|
super().__init__(
|
|
1317
1328
|
context=context,
|
|
@@ -1342,7 +1353,9 @@ class EnrichmentVotingEnsemble(VotingEnsemble):
|
|
|
1342
1353
|
)
|
|
1343
1354
|
|
|
1344
1355
|
def preprocess(self, event):
|
|
1345
|
-
"""
|
|
1356
|
+
"""
|
|
1357
|
+
Turn an entity identifier (source) to a Feature Vector
|
|
1358
|
+
"""
|
|
1346
1359
|
if isinstance(event.body, (str, bytes)):
|
|
1347
1360
|
event.body = json.loads(event.body)
|
|
1348
1361
|
event.body["inputs"] = self._feature_service.get(
|
mlrun/serving/server.py
CHANGED
|
@@ -101,6 +101,9 @@ class GraphServer(ModelObj):
|
|
|
101
101
|
tracking_policy=None,
|
|
102
102
|
secret_sources=None,
|
|
103
103
|
default_content_type=None,
|
|
104
|
+
function_name=None,
|
|
105
|
+
function_tag=None,
|
|
106
|
+
project=None,
|
|
104
107
|
):
|
|
105
108
|
self._graph = None
|
|
106
109
|
self.graph: Union[RouterStep, RootFlowStep] = graph
|
|
@@ -123,6 +126,9 @@ class GraphServer(ModelObj):
|
|
|
123
126
|
self.resource_cache = None
|
|
124
127
|
self.default_content_type = default_content_type
|
|
125
128
|
self.http_trigger = True
|
|
129
|
+
self.function_name = function_name
|
|
130
|
+
self.function_tag = function_tag
|
|
131
|
+
self.project = project
|
|
126
132
|
|
|
127
133
|
def set_current_function(self, function):
|
|
128
134
|
"""set which child function this server is currently running on"""
|
mlrun/serving/states.py
CHANGED
|
@@ -557,6 +557,8 @@ class TaskStep(BaseStep):
|
|
|
557
557
|
self._object.post_init(mode)
|
|
558
558
|
if hasattr(self._object, "model_endpoint_uid"):
|
|
559
559
|
self.endpoint_uid = self._object.model_endpoint_uid
|
|
560
|
+
if hasattr(self._object, "name"):
|
|
561
|
+
self.endpoint_name = self._object.name
|
|
560
562
|
|
|
561
563
|
def respond(self):
|
|
562
564
|
"""mark this step as the responder.
|
|
@@ -1287,11 +1289,19 @@ class FlowStep(BaseStep):
|
|
|
1287
1289
|
if self._controller:
|
|
1288
1290
|
# async flow (using storey)
|
|
1289
1291
|
event._awaitable_result = None
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1292
|
+
if self.context.is_mock:
|
|
1293
|
+
resp = self._controller.emit(
|
|
1294
|
+
event, return_awaitable_result=self._wait_for_result
|
|
1295
|
+
)
|
|
1296
|
+
if self._wait_for_result and resp:
|
|
1297
|
+
return resp.await_result()
|
|
1298
|
+
else:
|
|
1299
|
+
resp_awaitable = self._controller.emit(
|
|
1300
|
+
event, await_result=self._wait_for_result
|
|
1301
|
+
)
|
|
1302
|
+
if self._wait_for_result:
|
|
1303
|
+
return resp_awaitable
|
|
1304
|
+
return self._await_and_return_id(resp_awaitable, event)
|
|
1295
1305
|
event = copy(event)
|
|
1296
1306
|
event.body = {"id": event.id}
|
|
1297
1307
|
return event
|
|
@@ -1708,8 +1718,12 @@ def _init_async_objects(context, steps):
|
|
|
1708
1718
|
is_explicit_ack_supported(context) and mlrun.mlconf.is_explicit_ack_enabled()
|
|
1709
1719
|
)
|
|
1710
1720
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1721
|
+
if context.is_mock:
|
|
1722
|
+
source_class = storey.SyncEmitSource
|
|
1723
|
+
else:
|
|
1724
|
+
source_class = storey.AsyncEmitSource
|
|
1725
|
+
|
|
1726
|
+
default_source = source_class(
|
|
1713
1727
|
context=context,
|
|
1714
1728
|
explicit_ack=explicit_ack,
|
|
1715
1729
|
**source_args,
|