diff --git a/Dockerfile b/Dockerfile index edfa59e..9a001dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,3 +17,19 @@ CMD streamlit run --server.address 0.0.0.0 --server.port 8080 src/serving/stream FROM builder AS app-fastapi CMD uvicorn --host 0.0.0.0 --port 8090 --workers 4 src.serving.fastapi:app + +FROM builder AS app-seldon +EXPOSE 5000 +EXPOSE 9000 +ENV MODEL_NAME SeldonAPI +ENV SERVICE_TYPE MODEL +COPY app/src/serving/seldon.py /app/SeldonAPI.py + +RUN chown -R 8888 /app +RUN mkdir /.cache +RUN chmod 777 /.cache +RUN mkdir /.config +RUN chmod 777 /.config + +CMD exec seldon-core-microservice $MODEL_NAME --service-type $SERVICE_TYPE + diff --git a/README.md b/README.md index ffa8dbe..750b013 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,11 @@ streamlit run src/serving/streamlit.py ![Alt text](assets/streamlit.png) +Deploy k8s: +``` +kubectl create -f deployment/app-ui.yml +kubectl port-forward --address 0.0.0.0 svc/app-ui.yml 8080:8080 +``` Deploy k8s: ``` @@ -54,6 +59,26 @@ kubectl create -f deployment/app-fasttext.yml kubectl port-forward --address 0.0.0.0 svc/app-fasttext 8090:8090 ``` + +### Seldon + +Instalation + +``` +kubectl apply -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-crds.yaml +kubectl apply -n ambassador -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-kind.yaml +kubectl wait --timeout=180s -n ambassador --for=condition=deployed ambassadorinstallations/ambassador + +kubectl create namespace seldon-system + +helm install seldon-core seldon-core-operator --version 1.15.1 --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --set ambassador.enabled=true --namespace seldon-system +``` + +Deploy k8s: +``` +kubectl create -f deployment/seldon-custom.yaml +``` +======= ### DVC Install DVC @@ -134,3 +159,4 @@ kubectl create -f deployment/minio.yml ``` + diff --git a/app/src/serving/seldon.py b/app/src/serving/seldon.py new file mode 100644 index 0000000..8afe399 --- /dev/null +++ b/app/src/serving/seldon.py @@ -0,0 +1,16 @@ +import logging + +from src.serving.model import BertPredictor + +logger = logging.getLogger() + + +class SeldonAPI: + def __init__(self): + self.predictor = BertPredictor.from_model_registry() + + def predict(self, text): + logger.info(text) + results = self.predictor.predict(text) + logger.info(results) + return results diff --git a/deployment/seldon.yml b/deployment/seldon.yml new file mode 100644 index 0000000..6b5e026 --- /dev/null +++ b/deployment/seldon.yml @@ -0,0 +1,32 @@ +apiVersion: machinelearning.seldon.io/v1 +kind: SeldonDeployment +metadata: + name: nlp-sample + namespace: default +spec: + annotations: + seldon.io/rest-timeout: "60" + seldon.io/grpc-timeout: "60" + protocol: seldon + predictors: + - componentSpecs: + - spec: + containers: + - image: yuriihavrylko/app-seldon:latest + name: classifier + env: + - name: GUNICORN_THREADS + value: '1' + - name: GUNICORN_WORKERS + value: '1' + - name: FLASK_SINGLE_THREADED + value: '1' + - name: SELDON_DEBUG + value: '1' + imagePullPolicy: Always + + graph: + name: classifier + type: MODEL + name: model + replicas: 1