Skip to content

Commit

Permalink
Initial changes for function
Browse files Browse the repository at this point in the history
  • Loading branch information
axsaucedo committed Aug 1, 2019
1 parent 632a6a8 commit 88bea36
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 17 deletions.
31 changes: 20 additions & 11 deletions python/seldon_core/seldon_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
from seldon_core.user_model import *
from google.protobuf import json_format
from seldon_core.proto import prediction_pb2
from typing import Any
from typing import Any, Union, List, Dict

logger = logging.getLogger(__name__)


def predict(user_model: Any, request: prediction_pb2.SeldonMessage) -> prediction_pb2.SeldonMessage:
def predict(
user_model: Any,
request: Union[prediction_pb2.SeldonMessage, List, Dict]
) -> prediction_pb2.SeldonMessage:
"""
Call the user model to get a prediction and package the response
Expand All @@ -22,22 +25,28 @@ def predict(user_model: Any, request: prediction_pb2.SeldonMessage) -> predictio
-------
The prediction
"""
if hasattr(user_model, "predict_rest"):
is_proto = isinstance(request, prediction_pb2.SeldonMessage)

if hasattr(user_model, "predict_rest") and not is_proto:
logger.warning("predict_rest is deprecated. Please use predict_raw")
request_json = json_format.MessageToJson(request)
response_json = user_model.predict_rest(request_json)
return json_to_seldon_message(response_json)
elif hasattr(user_model, "predict_grpc"):
return user_model.predict_rest(request)
elif hasattr(user_model, "predict_grpc") and is_proto:
logger.warning("predict_grpc is deprecated. Please use predict_raw")
return user_model.predict_grpc(request)
else:
try:
return user_model.predict_raw(request)
except (NotImplementedError, AttributeError):
(features, meta, datadef, data_type) = extract_request_parts(request)
client_response = client_predict(user_model, features, datadef.names, meta=meta)

return construct_response(user_model, False, request, client_response)
logger.warning("ATTEMPTINGTORUN")
if is_proto:
(features, meta, datadef, data_type) = extract_request_parts(request)
client_response = client_predict(user_model, features, datadef.names, meta=meta)
return construct_response(user_model, False, request, client_response)
else:
(features, meta, datadef, data_type) = extract_request_parts_json(request)
client_response = client_predict(user_model, features, datadef.names, meta=meta)
print(client_response)
return construct_response_json(user_model, False, request, client_response)


def send_feedback(user_model: Any, request: prediction_pb2.Feedback,
Expand Down
60 changes: 59 additions & 1 deletion python/seldon_core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from google.protobuf.struct_pb2 import ListValue
from seldon_core.user_model import client_class_names, client_custom_metrics, client_custom_tags, client_feature_names, \
SeldonComponent
from typing import Tuple, Dict, Union, List, Optional, Iterable
from typing import Tuple, Dict, Union, List, Optional, Iterable, Any


def json_to_seldon_message(message_json: Dict) -> prediction_pb2.SeldonMessage:
Expand Down Expand Up @@ -301,6 +301,42 @@ def array_to_list_value(array: np.ndarray, lv: Optional[ListValue] = None) -> Li
array_to_list_value(sub_array, sub_lv)
return lv

def construct_response_json(user_model: SeldonComponent, is_request: bool, client_request_raw: Union[List, Dict],
client_raw_response: Union[np.ndarray, str, bytes, dict]) -> Union[List, Dict]:
"""
This class converts a raw REST response into a JSON object that has the same structure as
the SeldonMessage proto. This is necessary as the conversion using the SeldonMessage proto
changes the Numeric types of all ints in a JSON into Floats.
Parameters
----------
user_model
Client user class
is_request
Whether this is part of the request flow as opposed to the response flow
client_request
The request received
client_raw_response
The raw client response from their model
Returns
-------
A SeldonMessage JSON response
"""
client_request = json_to_seldon_message(client_request_raw)
data_type = client_request.WhichOneof("data_oneof")

sm = construct_response(user_model, is_request, client_request, client_raw_response)
sm_json = seldon_message_to_json(sm)

response_data_type = sm.WhichOneof("data_oneof")

if response_data_type == "jsonData":
sm_json["jsonData"] = client_raw_response

return sm_json


def construct_response(user_model: SeldonComponent, is_request: bool, client_request: prediction_pb2.SeldonMessage,
client_raw_response: Union[np.ndarray, str, bytes, dict]) -> prediction_pb2.SeldonMessage:
Expand Down Expand Up @@ -361,6 +397,28 @@ def construct_response(user_model: SeldonComponent, is_request: bool, client_req
raise SeldonMicroserviceException("Unknown data type returned as payload:" + client_raw_response)


def extract_request_parts_json(request_raw: Union[Dict, List]) -> Tuple[
Union[np.ndarray, str, bytes, dict], Dict, prediction_pb2.DefaultData, str]:
"""
Parameters
----------
request
Input request in JSON format
Returns
-------
Key parts of the request extracted
"""
request_proto = json_to_seldon_message(request_raw)
(features, meta, datadef, data_type) = extract_request_parts(request_proto)

if data_type == "jsonData":
features = request_raw["jsonData"]

return features, meta, datadef, data_type

def extract_request_parts(request: prediction_pb2.SeldonMessage) -> Tuple[
Union[np.ndarray, str, bytes, dict], Dict, prediction_pb2.DefaultData, str]:
"""
Expand Down
9 changes: 4 additions & 5 deletions python/seldon_core/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ def openAPI():
def Predict():
requestJson = get_request()
logger.debug("REST Request: %s", request)
requestProto = json_to_seldon_message(requestJson)
logger.debug("Proto Request: %s", requestProto)
responseProto = seldon_core.seldon_methods.predict(user_model, requestProto)
jsonDict = seldon_message_to_json(responseProto)
return jsonify(jsonDict)
response = seldon_core.seldon_methods.predict(user_model, requestJson)
logger.debug("REST Response: %s", response)
return jsonify(response)


@app.route("/send-feedback", methods=["GET", "POST"])
def SendFeedback():
Expand Down

0 comments on commit 88bea36

Please sign in to comment.