Skip to content

Commit

Permalink
feat(examples/pachyderm-cd4ml): New e2e CD demo using Pachyderm
Browse files Browse the repository at this point in the history
  • Loading branch information
philwinder authored and seldondev committed Jan 18, 2021
1 parent 2fb4716 commit cd19dc2
Show file tree
Hide file tree
Showing 21 changed files with 1,605 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/pachyderm-cd4ml/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.json
*.joblib
rbac.yaml
14 changes: 14 additions & 0 deletions examples/pachyderm-cd4ml/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
build:
make -C RSIServing build
make -C RSITraining build
make -C RSIDeployer build

push: build
make -C RSIServing push
make -C RSITraining push
make -C RSIDeployer push

kind_load: build
make -C RSIServing kind_load
make -C RSITraining kind_load
make -C RSIDeployer kind_load
4 changes: 4 additions & 0 deletions examples/pachyderm-cd4ml/RSIDeployer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM alpine/helm:3.4.2
ADD ./charts /charts
ADD ./deploy.sh /
ENTRYPOINT [ "ash" ]
12 changes: 12 additions & 0 deletions examples/pachyderm-cd4ml/RSIDeployer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
VERSION=0.1.0
IMAGE_BASE=seldonio/pachyderm-rsi-deployer
KIND_NAME ?= kind

build:
docker build . -t ${IMAGE_BASE}:${VERSION}

push: build
docker push ${IMAGE_BASE}:${VERSION}

kind_load: build
kind load -v 3 docker-image ${IMAGE_BASE}:${VERSION} --name ${KIND_NAME}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: seldon-deployment
description: A custom helm chart for this seldon deployment
type: application
version: 0.1.0
appVersion: 0.1.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Secret
metadata:
name: minio-credentials
type: Opaque
stringData:
AWS_ACCESS_KEY_ID: noauth
AWS_SECRET_ACCESS_KEY: noauth
AWS_ENDPOINT_URL: http://pachd.pachyderm.svc.cluster.local:600
USE_SSL: "false"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rsi-deployment-sa
secrets:
- name: minio-credentials
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: rsi-predictor
spec:
annotations:
seldon.io/executor: "true"
name: rsi-predictor
predictors:
- componentSpecs:
- spec:
containers:
- image: seldonio/pachyderm-rsi-server:0.1.0
imagePullPolicy: IfNotPresent
name: rsi-predictor
env:
- name: MODEL_URI
value: {{ .Values.model.uri }}
- name: MODEL_COMMIT_HASH
value: {{ .Values.model.version }}
- name: TEMP_DIR
value: /mnt/models
envFrom:
- secretRef:
name: minio-credentials
volumeMounts:
- name: model-storage
mountPath: /mnt/models
volumes:
- name: model-storage
emptyDir: {}
serviceAccountName: rsi-deployment-sa
graph:
children: []
endpoint:
type: REST
name: rsi-predictor
type: MODEL
name: default
replicas: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
model:
uri: "uri_to_model"
version: "commit_hash"
14 changes: 14 additions & 0 deletions examples/pachyderm-cd4ml/RSIDeployer/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/ash

if [ $# -eq 0 ]
then
echo "USAGE: deploy.sh NAMESPACE MODEL_URI MODEL_VERSION"
fi

echo "namespace=${1} model.uri=${2} model.version=${3}"

if helm --namespace=${1} status rsi ; then
helm --namespace=${1} upgrade rsi /charts/seldon-deployment --set model.uri=${2} --set model.version=${3}
else
helm --namespace=${1} install rsi /charts/seldon-deployment --set model.uri=${2} --set model.version=${3}
fi
6 changes: 6 additions & 0 deletions examples/pachyderm-cd4ml/RSIServing/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM python:3.8-slim
RUN pip install pandas==1.1.4 statsmodels==0.12.1 seldon-core==1.5.0 joblib==1.0.0 minio==7.0.0
WORKDIR /app
ADD RSIModel.py /app/RSIModel.py
EXPOSE 5000
CMD exec seldon-core-microservice RSIModel --service-type MODEL --persistence 0
12 changes: 12 additions & 0 deletions examples/pachyderm-cd4ml/RSIServing/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
VERSION=0.1.0
IMAGE_BASE=seldonio/pachyderm-rsi-server
KIND_NAME ?= kind

build:
docker build . -t ${IMAGE_BASE}:${VERSION}

push: build
docker push ${IMAGE_BASE}:${VERSION}

kind_load: build
kind load -v 3 docker-image ${IMAGE_BASE}:${VERSION} --name ${KIND_NAME}
90 changes: 90 additions & 0 deletions examples/pachyderm-cd4ml/RSIServing/RSIModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import logging
import os
from urllib.parse import urlparse

import joblib
from minio import Minio

MODEL_URI = os.getenv("MODEL_URI", "")
MODEL_COMMIT_HASH = os.getenv("MODEL_COMMIT_HASH", "")
TEMP_DIR = os.getenv("TEMP_DIR", "/mnt/models")
_S3_PREFIX = "s3://"

logger = logging.getLogger(__name__)


class RSIModel(object):
def __init__(self):
super().__init__()
self.ready = False
logger.info(f"Model uri: {MODEL_URI} @ ${MODEL_COMMIT_HASH}")
model_file = self._download_s3()
logger.info(f"model file: {model_file}")
self._model = joblib.load(model_file)

def predict(self, X, features_names):
"""Predict!
The return type is important. It has to fit into one of three types:
https://docs.seldon.io/projects/seldon-core/en/v1.1.0/python/python_component.html
The statsmodel model returns a pandas Series. I want to return the index, so I reset
it to move it into a column, then use the to_numpy method to convert it to a valid
seldon return type.
Args:
X (int): A scalar representing the number of periods to forecast.
Returns:
np.ndarray: The forecast [timestamps x predictions]
"""
return self._model.forecast(X).reset_index().to_numpy()

def init_metadata(self):
meta = {
"name": "RSIModel",
"versions": [f"{MODEL_URI}@{MODEL_COMMIT_HASH}"],
"platform": "seldon",
"inputs": [
{
"messagetype": "ndarray",
"schema": {"names": ["periods"], "shape": [1]},
}
],
"outputs": [{"messagetype": "ndarray", "schema": {"shape": [2]}}],
"custom": {"MODEL_URI": MODEL_URI, "MODEL_COMMIT_HASH": MODEL_COMMIT_HASH},
}
return meta

# Inspired by https://github.com/SeldonIO/kfserving/blob/master/python/kfserving/kfserving/storage.py
def _download_s3(self) -> str:
client = RSIModel._create_minio_client()
bucket_args = MODEL_URI.replace(_S3_PREFIX, "", 1).split("/", 1)
bucket_name = bucket_args[0]
bucket_path = bucket_args[1] if len(bucket_args) > 1 else ""
file_name = bucket_path.split("/")[-1]
local_file = os.path.join(TEMP_DIR, file_name)
logger.info(f"Downloading {bucket_path} from {bucket_name} to {local_file}.")
try:
client.fget_object(
bucket_name, bucket_path, local_file, version_id=MODEL_COMMIT_HASH
)
except Exception as e:
raise RuntimeError(f"Failed to fetch model {MODEL_URI}.\n{e}")
return local_file

@staticmethod
def _create_minio_client():
# Remove possible http scheme for Minio
url = urlparse(os.getenv("AWS_ENDPOINT_URL", "s3.amazonaws.com"))
use_ssl = (
url.scheme == "https"
if url.scheme
else bool(os.getenv("S3_USE_HTTPS", "true"))
)
return Minio(
url.netloc,
access_key=os.getenv("AWS_ACCESS_KEY_ID", ""),
secret_key=os.getenv("AWS_SECRET_ACCESS_KEY", ""),
secure=use_ssl,
)
4 changes: 4 additions & 0 deletions examples/pachyderm-cd4ml/RSITraining/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM python:3.8-slim
RUN pip install pandas==1.1.4 statsmodels==0.12.1 joblib==1.0.0
WORKDIR /code
ADD RSITrain.py /code/RSITrain.py
14 changes: 14 additions & 0 deletions examples/pachyderm-cd4ml/RSITraining/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
VERSION=0.1.0
IMAGE_BASE=seldonio/pachyderm-rsi-trainer

KIND_NAME ?= kind


build:
docker build . -t ${IMAGE_BASE}:${VERSION}

push:
docker push ${IMAGE_BASE}:${VERSION}

kind_load:
kind load -v 3 docker-image ${IMAGE_BASE}:${VERSION} --name ${KIND_NAME}
21 changes: 21 additions & 0 deletions examples/pachyderm-cd4ml/RSITraining/RSITrain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import argparse

import joblib
import pandas as pd
from statsmodels.tsa.holtwinters import ExponentialSmoothing

parser = argparse.ArgumentParser(description='Train a model for iris classification.')
parser.add_argument('data_file_path', type=str, help='Path to csv file containing training set')
parser.add_argument('model_path', type=str, help='Path to output joblib file')
args = parser.parse_args()

print(f"Loading data set from {args.data_file_path}")
rsi = pd.read_csv(args.data_file_path, index_col="Date", parse_dates=True)

print("Training model...")
model = ExponentialSmoothing(rsi,trend='add').fit()
print("Model trained!")

print(f"Saving model in {args.model_path}")
joblib.dump(model, args.model_path)
print("Model saved!")
83 changes: 83 additions & 0 deletions examples/pachyderm-cd4ml/data/rsi_after.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"Date","RSI"
"2014 JAN",86.0
"2014 FEB",86.4
"2014 MAR",87.5
"2014 APR",87.2
"2014 MAY",87.3
"2014 JUN",88.0
"2014 JUL",87.8
"2014 AUG",87.7
"2014 SEP",87.0
"2014 OCT",87.4
"2014 NOV",87.8
"2014 DEC",89.0
"2015 JAN",87.2
"2015 FEB",87.7
"2015 MAR",88.0
"2015 APR",88.5
"2015 MAY",88.5
"2015 JUN",88.9
"2015 JUL",88.7
"2015 AUG",87.6
"2015 SEP",89.2
"2015 OCT",87.9
"2015 NOV",88.4
"2015 DEC",88.3
"2016 JAN",89.8
"2016 FEB",89.1
"2016 MAR",88.8
"2016 APR",89.4
"2016 MAY",90.7
"2016 JUN",90.0
"2016 JUL",91.7
"2016 AUG",91.3
"2016 SEP",92.1
"2016 OCT",93.9
"2016 NOV",93.6
"2016 DEC",93.2
"2017 JAN",93.2
"2017 FEB",94.3
"2017 MAR",94.0
"2017 APR",95.5
"2017 MAY",94.4
"2017 JUN",94.7
"2017 JUL",95.1
"2017 AUG",96.1
"2017 SEP",96.4
"2017 OCT",96.8
"2017 NOV",97.7
"2017 DEC",97.7
"2018 JAN",97.8
"2018 FEB",98.4
"2018 MAR",97.0
"2018 APR",98.2
"2018 MAY",100.4
"2018 JUN",100.0
"2018 JUL",100.7
"2018 AUG",101.4
"2018 SEP",101.0
"2018 OCT",100.7
"2018 NOV",102.5
"2018 DEC",101.9
"2019 JAN",102.5
"2019 FEB",103.1
"2019 MAR",104.2
"2019 APR",103.4
"2019 MAY",103.2
"2019 JUN",104.4
"2019 JUL",105.1
"2019 AUG",104.5
"2019 SEP",104.0
"2019 OCT",104.0
"2019 NOV",103.4
"2019 DEC",103.1
"2020 JAN",104.5
"2020 FEB",103.6
"2020 MAR",97.4
"2020 APR",79.4
"2020 MAY",88.7
"2020 JUN",100.9
"2020 JUL",105.3
"2020 AUG",106.2
"2020 SEP",107.5
"2020 OCT",109.0
Loading

0 comments on commit cd19dc2

Please sign in to comment.