From 645c6d43b3b836607e356abb4b81fe726894a47e Mon Sep 17 00:00:00 2001 From: Pavel Dmitriev Date: Fri, 6 Oct 2023 23:15:13 +0300 Subject: [PATCH] ***12 --- test01-images/Dockerfile | 13 +++++ test01-images/pipeline.py | 88 ++++++++++++++++++++++++++++ test01-images/requirements.txt | 10 ++++ test01/pipeline2.yaml | 101 +++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 test01-images/Dockerfile create mode 100644 test01-images/pipeline.py create mode 100644 test01-images/requirements.txt create mode 100644 test01/pipeline2.yaml diff --git a/test01-images/Dockerfile b/test01-images/Dockerfile new file mode 100644 index 0000000..2c5f038 --- /dev/null +++ b/test01-images/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.7-slim + +ENV APP_HOME /app +ENV WORKERS 1 +ENV THREADS 8 +ENV PREDICTIVE_UNIT_SERVICE_PORT 8080 +WORKDIR $APP_HOME +COPY pipeline.py requirements.txt ./ +ENV PYTHONUNBUFFERED=1 + +RUN pip install --no-cache-dir -r ./requirements.txt + +CMD ["sh","-c","gunicorn --bind 0.0.0.0:$PREDICTIVE_UNIT_SERVICE_PORT --workers $WORKERS --threads $THREADS pipeline"] \ No newline at end of file diff --git a/test01-images/pipeline.py b/test01-images/pipeline.py new file mode 100644 index 0000000..6a1cf03 --- /dev/null +++ b/test01-images/pipeline.py @@ -0,0 +1,88 @@ +from flask import Flask +from flask import request +from flask import make_response + +import random + +application=app = Flask(__name__) + +# Randomly route to either 1st or 2nd child +@application.route("/route", methods=['GET', 'POST']) +def route(): + if (request.method == 'GET'): + return "Healthy" + else: + payload = request.get_json() + print(f'Route message: {payload}') + child = random.randint(0, 1) + + response = make_response({"data":{"ndarray":[' + str(child) + ']}}) + response.headers['Content-Type'] = 'application/json' + return response + + +# Prediction is emulated by incrementing the input payload +# e.g {"data":"0"} -> {"data":"1"} +@application.route("/predict", methods=['GET', 'POST']) +def predict() -> str: + if (request.method == 'GET'): + return "Healthy" + else: + payload = request.get_json() + print(f'Input message: {payload}') + + data = int(payload['data']) + data = data + 1 + + response = make_response( '{"data":"' + str(data) + '"}') + response.headers['Content-Type'] = 'application/json' + return response + + +# Aggregate the output of two children by concatanating +# e.g. {"data":"101"},{"data":"101"} -> {"data":"101101"} +@application.route("/aggregate", methods=['GET', 'POST']) +def aggregate(): + if (request.method == 'GET'): + return "Healthy" + else: + payload = request.get_json() + print(f'Combine message: {payload}') + + combined_data = payload[0]['data'] + payload[1]['data'] + response = make_response('{"data":"' + str(combined_data) + '"}') + response.headers['Content-Type'] = 'application/json' + return response + + +# Tranform the input data by adding 100 to the payload +# e.g. {"data":"0"} -> {"data":"100"} +@application.route("/transform-input", methods=['GET', 'POST']) +def transform_input(): + if (request.method == 'GET'): + return "Healthy" + else: + payload = request.get_json() + print(f'Transform input message: {payload}') + + data = int(payload['data']) + data = data + 100 + + response = make_response( '{"data":"' + str(data) + '"}') + response.headers['Content-Type'] = 'application/json' + return response + + +# Put the output data into the "prediction" json +# e.g. {"data":"102"} -> {"prediction_result":"102"} +@application.route("/transform-output", methods=['GET', 'POST']) +def transform_output(): + if (request.method == 'GET'): + return "Healthy" + else: + payload = request.get_json() + print(f'Transform output message: {payload}') + + response = make_response('{"prediction_result":"' + payload['data'] + '"}') + response.headers['Content-Type'] = 'application/json' + return response diff --git a/test01-images/requirements.txt b/test01-images/requirements.txt new file mode 100644 index 0000000..6844ad9 --- /dev/null +++ b/test01-images/requirements.txt @@ -0,0 +1,10 @@ +Flask==2.2.5 +gunicorn==21.2.0 +importlib-metadata==6.7.0 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.3 +packaging==23.2 +typing_extensions==4.7.1 +Werkzeug==2.2.3 +zipp==3.15.0 \ No newline at end of file diff --git a/test01/pipeline2.yaml b/test01/pipeline2.yaml new file mode 100644 index 0000000..b845988 --- /dev/null +++ b/test01/pipeline2.yaml @@ -0,0 +1,101 @@ +apiVersion: machinelearning.seldon.io/v1alpha2 +kind: SeldonDeployment +metadata: + name: pipeline2 +spec: + name: pipeline-deployment2 + predictors: + - componentSpecs: + - spec: + containers: + - image: mxfox.ru/palkan/seldon1:latest + name: router + imagePullPolicy: Always + ports: + - containerPort: 8080 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: model-a + imagePullPolicy: Always + ports: + - containerPort: 8081 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: model-b + imagePullPolicy: Always + ports: + - containerPort: 8082 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: model-c + imagePullPolicy: Always + ports: + - containerPort: 8083 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: model-d + imagePullPolicy: Always + ports: + - containerPort: 8084 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: combiner + imagePullPolicy: Always + ports: + - containerPort: 8085 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: input-transformer + imagePullPolicy: Always + ports: + - containerPort: 8086 + name: http + - image: mxfox.ru/palkan/seldon1:latest + name: output-transformer + imagePullPolicy: Always + ports: + - containerPort: 8087 + name: http + graph: + name: output-transformer + type: OUTPUT_TRANSFORMER + endpoint: + type: REST + children: + - name: input-transformer + type: TRANSFORMER + endpoint: + type: REST + children: + - name: router + type: ROUTER + endpoint: + type: REST + children: + - name: model-a + endpoint: + type: REST + type: MODEL + children: + - name: model-b + endpoint: + type: REST + type: MODEL + children: [] + - name: combiner + endpoint: + type: REST + type: COMBINER + children: + - name: model-c + endpoint: + type: REST + type: MODEL + children: [] + - name: model-d + endpoint: + type: REST + type: MODEL + children: [] + name: pipeline-predictor2 + replicas: 1 \ No newline at end of file