From f917ee38dab8c509a87aa422834f30a0f8e29641 Mon Sep 17 00:00:00 2001 From: Clive Cox Date: Sat, 25 Aug 2018 15:39:56 +0100 Subject: [PATCH 1/2] add flatbuffers numpy update and make async tornado python 2 compatible --- wrappers/python/model_microservice.py | 12 ++++++------ wrappers/python/seldon_flatbuffers.py | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/wrappers/python/model_microservice.py b/wrappers/python/model_microservice.py index 5e5c895b8e..a3ce74c7f7 100644 --- a/wrappers/python/model_microservice.py +++ b/wrappers/python/model_microservice.py @@ -134,23 +134,23 @@ def __init__(self,user_model): super(SeldonFlatbuffersServer, self).__init__() self.user_model = user_model - async def handle_stream(self, stream, address): + @gen.coroutine + def handle_stream(self, stream, address): while True: try: - data = await stream.read_bytes(4) + data = yield stream.read_bytes(4) obj = struct.unpack('1: - print(predictions.shape) class_names = get_class_names(self.user_model, predictions.shape[1]) else: class_names = [] outData = NumpyArrayToSeldonRPC(predictions,class_names) - await stream.write(outData) + yield stream.write(outData) except StreamClosedError: print("Stream closed during processing:",address) break @@ -158,7 +158,7 @@ async def handle_stream(self, stream, address): tb = traceback.format_exc() print("Caught exception during processing:",address,tb) outData = CreateErrorMsg(tb) - await stream.write(outData) + yield stream.write(outData) stream.close() break; except StreamClosedError: diff --git a/wrappers/python/seldon_flatbuffers.py b/wrappers/python/seldon_flatbuffers.py index c2057bf44a..14c40e9ff2 100644 --- a/wrappers/python/seldon_flatbuffers.py +++ b/wrappers/python/seldon_flatbuffers.py @@ -38,7 +38,6 @@ def SeldonRPCToNumpyArray(data): shape = [] for i in range(tensor.ShapeLength()): shape.append(tensor.Shape(i)) - print(shape) values = tensor.ValuesAsNumpy() values = values.reshape(shape) return (values,names) @@ -130,7 +129,7 @@ def CreateNumpyVector(builder, x): if not isinstance(x, np.ndarray): raise TypeError("non-numpy-ndarray passed to CreateNumpyVector") - if x.data.ndim > 1: + if x.ndim > 1: raise TypeError("multidimensional-ndarray passed to CreateNumpyVector") builder.StartVector(x.itemsize, x.size, x.dtype.alignment) @@ -139,7 +138,7 @@ def CreateNumpyVector(builder, x): if x.dtype.str[0] == "<": x_lend = x else: - x_lend = x.byteswap() + x_lend = x.byteswap(inplace=False) # Calculate total length l = UOffsetTFlags.py_type(x_lend.itemsize * x_lend.size) From adfe6e6797ce912440080cfa9fe52b82c8555c09 Mon Sep 17 00:00:00 2001 From: Clive Cox Date: Sat, 25 Aug 2018 16:11:58 +0100 Subject: [PATCH 2/2] add simple fbs test in s2i folder --- wrappers/s2i/python/build_python2.sh | 1 + wrappers/s2i/python/test_fbs/.s2i/environment | 4 ++ wrappers/s2i/python/test_fbs/READNE.txt | 1 + wrappers/s2i/python/test_fbs/Test.py | 23 +++++++++++ wrappers/s2i/python/test_fbs/contract.json | 39 +++++++++++++++++++ wrappers/s2i/python/test_fbs/requirements.txt | 1 + wrappers/s2i/python/test_fbs/run_test_python2 | 6 +++ wrappers/s2i/python/test_fbs/run_test_python3 | 6 +++ wrappers/testing/tester_flatbuffers.py | 1 - 9 files changed, 81 insertions(+), 1 deletion(-) create mode 100755 wrappers/s2i/python/build_python2.sh create mode 100644 wrappers/s2i/python/test_fbs/.s2i/environment create mode 100644 wrappers/s2i/python/test_fbs/READNE.txt create mode 100644 wrappers/s2i/python/test_fbs/Test.py create mode 100644 wrappers/s2i/python/test_fbs/contract.json create mode 100644 wrappers/s2i/python/test_fbs/requirements.txt create mode 100755 wrappers/s2i/python/test_fbs/run_test_python2 create mode 100755 wrappers/s2i/python/test_fbs/run_test_python3 diff --git a/wrappers/s2i/python/build_python2.sh b/wrappers/s2i/python/build_python2.sh new file mode 100755 index 0000000000..3af55d4f7a --- /dev/null +++ b/wrappers/s2i/python/build_python2.sh @@ -0,0 +1 @@ +make build diff --git a/wrappers/s2i/python/test_fbs/.s2i/environment b/wrappers/s2i/python/test_fbs/.s2i/environment new file mode 100644 index 0000000000..d183138877 --- /dev/null +++ b/wrappers/s2i/python/test_fbs/.s2i/environment @@ -0,0 +1,4 @@ +MODEL_NAME=Test +API_TYPE=FBS +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/wrappers/s2i/python/test_fbs/READNE.txt b/wrappers/s2i/python/test_fbs/READNE.txt new file mode 100644 index 0000000000..4b5da1fc55 --- /dev/null +++ b/wrappers/s2i/python/test_fbs/READNE.txt @@ -0,0 +1 @@ +A simple dummy model to test wrapping. diff --git a/wrappers/s2i/python/test_fbs/Test.py b/wrappers/s2i/python/test_fbs/Test.py new file mode 100644 index 0000000000..7427a12d77 --- /dev/null +++ b/wrappers/s2i/python/test_fbs/Test.py @@ -0,0 +1,23 @@ +class Test(object): + """ + Model template. You can load your model parameters in __init__ from a location accessible at runtime + """ + + def __init__(self): + """ + Add any initialization parameters. These will be passed at runtime from the graph definition parameters defined in your seldondeployment kubernetes resource manifest. + """ + print("Initializing") + + def predict(self,X,features_names): + """ + Return a prediction. + + Parameters + ---------- + X : array-like + feature_names : array of feature names (optional) + """ + print("Predict called - will run identity function") + print(X) + return X diff --git a/wrappers/s2i/python/test_fbs/contract.json b/wrappers/s2i/python/test_fbs/contract.json new file mode 100644 index 0000000000..ab7102d7e5 --- /dev/null +++ b/wrappers/s2i/python/test_fbs/contract.json @@ -0,0 +1,39 @@ +{ + "features":[ + { + "name":"sepal_length", + "dtype":"FLOAT", + "ftype":"continuous", + "range":[4,8] + }, + { + "name":"sepal_width", + "dtype":"FLOAT", + "ftype":"continuous", + "range":[2,5] + }, + { + "name":"petal_length", + "dtype":"FLOAT", + "ftype":"continuous", + "range":[1,10] + }, + { + "name":"petal_width", + "dtype":"FLOAT", + "ftype":"continuous", + "range":[0,3] + } + ], + "targets":[ + { + "name":"class", + "dtype":"FLOAT", + "ftype":"continuous", + "range":[0,1], + "repeat":3 + } + ] +} + + diff --git a/wrappers/s2i/python/test_fbs/requirements.txt b/wrappers/s2i/python/test_fbs/requirements.txt new file mode 100644 index 0000000000..24ce15ab7e --- /dev/null +++ b/wrappers/s2i/python/test_fbs/requirements.txt @@ -0,0 +1 @@ +numpy diff --git a/wrappers/s2i/python/test_fbs/run_test_python2 b/wrappers/s2i/python/test_fbs/run_test_python2 new file mode 100755 index 0000000000..06aad3e209 --- /dev/null +++ b/wrappers/s2i/python/test_fbs/run_test_python2 @@ -0,0 +1,6 @@ + +s2i build . seldonio/seldon-core-s2i-python2:0.2-SNAPSHOT test-wrapper-py2:0.1 +docker run --name "test_predictor" --rm -d -p 5000:5000 test-wrapper-py2:0.1 +sleep 2 +python ../../../testing/tester.py contract.json 0.0.0.0 5000 -p --fbs +docker rm -f test_predictor diff --git a/wrappers/s2i/python/test_fbs/run_test_python3 b/wrappers/s2i/python/test_fbs/run_test_python3 new file mode 100755 index 0000000000..1493e8ab6b --- /dev/null +++ b/wrappers/s2i/python/test_fbs/run_test_python3 @@ -0,0 +1,6 @@ + +s2i build . seldonio/seldon-core-s2i-python3:0.2-SNAPSHOT test-wrapper-py3:0.1 +docker run --name "test_predictor" --rm -d -p 5000:5000 test-wrapper-py3:0.1 +sleep 2 +python ../../../testing/tester.py contract.json 0.0.0.0 5000 -p --fbs +docker rm -f test_predictor diff --git a/wrappers/testing/tester_flatbuffers.py b/wrappers/testing/tester_flatbuffers.py index 58d07d838a..71863d87d7 100644 --- a/wrappers/testing/tester_flatbuffers.py +++ b/wrappers/testing/tester_flatbuffers.py @@ -74,7 +74,6 @@ def SeldonRPCToNumpyArray(data): shape = [] for i in range(tensor.ShapeLength()): shape.append(tensor.Shape(i)) - print(shape) values = tensor.ValuesAsNumpy() values = values.reshape(shape) return (values,names)