Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

include rclone in adserver #3172

Merged
merged 16 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion components/alibi-detect-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# TODO: Add to release script
# TODO: Add to release script
FROM docker.io/seldonio/seldon-core-s2i-python37-ubi8:1.8.0-dev
LABEL name="Seldon Alibi Detect Server" \
vendor="Seldon Technologies" \
Expand All @@ -7,6 +7,13 @@ LABEL name="Seldon Alibi Detect Server" \
summary="Alibi Detect Server for Seldon Core" \
description="The Alibi Detect Server provides outlier, drift and adversarial detection services for Seldon Core"

# Install Rclone Binary to be present in the image
RUN yum install -y unzip
RUN wget https://downloads.rclone.org/v1.55.1/rclone-v1.55.1-linux-amd64.zip && \
unzip rclone-v1.55.1-linux-amd64.zip && \
mv rclone-v1.55.1-linux-amd64/rclone /usr/bin/rclone && \
rm -rf rclone-v1.55.1-linux-amd64.zip rclone-v1.55.1-linux-amd64

ADD requirements_server.txt .

RUN pip install pip -U
Expand Down
4 changes: 2 additions & 2 deletions components/alibi-detect-server/adserver/ad_model.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import json
from typing import List, Dict, Optional
import logging
import kfserving
import numpy as np
from adserver.constants import HEADER_RETURN_INSTANCE_SCORE
from .numpy_encoder import NumpyEncoder
from alibi_detect.utils.saving import load_detector, Data
from adserver.base import CEModel
from adserver.base.storage import download_model


class AlibiDetectAdversarialDetectionModel(
Expand Down Expand Up @@ -34,7 +34,7 @@ def load(self):
Load the model from storage

"""
model_folder = kfserving.Storage.download(self.storage_uri)
model_folder = download_model(self.storage_uri)
self.model: Data = load_detector(model_folder)
self.ready = True

Expand Down
4 changes: 2 additions & 2 deletions components/alibi-detect-server/adserver/base/alibi_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import kfserving
from typing import Optional
from adserver.base.model import CEModel
from adserver.base.storage import download_model
from alibi_detect.utils.saving import load_detector, Data


Expand All @@ -27,6 +27,6 @@ def load(self):
Load the model from storage

"""
model_folder = kfserving.Storage.download(self.storage_uri)
model_folder = download_model(self.storage_uri)
self.model: Data = load_detector(model_folder)
self.ready = True
63 changes: 63 additions & 0 deletions components/alibi-detect-server/adserver/base/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os
import sys
import kfserving
import logging
import tempfile
from distutils.util import strtobool


logger = logging.getLogger(__name__)

try:
from sh import rclone
except ImportError:
logger.warning(
"rclone-based storage funcionality not available without rclone binary"
)
rclone = None


def _rclone_enabled():
# IF RCLONE_ENABLED variable set explicitly we read from it
enabled = os.environ.get("RCLONE_ENABLED", None)
if enabled is not None:
return strtobool(enabled)

# Otherwise we determine if Rclone config is provided
for key in os.environ.keys():
if "RCLONE_CONFIG" in key:
return True
else:
return False


RCLONE_ENABLED = _rclone_enabled()


class Rclone:
def __init__(self, cfg_file: str = None):
self.cfg_file = cfg_file

def copy(self, src: str, dest: str = None):
if rclone is None:
raise RuntimeError(
"rclone binary not found - rclone-based storage funcionality disabled"
)

if dest is None:
dest = tempfile.mkdtemp()

args = ["-v"]
kwargs = {}
if self.cfg_file is not None:
kwargs["config"] = os.path.abspath(os.path.expanduser(self.cfg_file))

rclone.copy(src, dest, *args, **kwargs, _out=sys.stdout, _err_to_out=True)
return dest


def download_model(storage_uri) -> str:
if RCLONE_ENABLED:
return Rclone().copy(storage_uri)
else:
return kfserving.Storage.download(storage_uri)
1 change: 0 additions & 1 deletion components/alibi-detect-server/adserver/cd_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from alibi_detect.utils.saving import load_detector, Data
from adserver.base import AlibiDetectModel
from seldon_core.user_model import SeldonResponse
import kfserving
import tensorflow as tf
from transformers import AutoTokenizer

Expand Down
4 changes: 2 additions & 2 deletions components/alibi-detect-server/adserver/cm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import logging
import numpy as np
from enum import Enum
import kfserving
import importlib
import pickle
import os
Expand All @@ -14,6 +13,7 @@
)
from .numpy_encoder import NumpyEncoder
from adserver.base import CEModel
from adserver.base.storage import download_model
from seldon_core.user_model import SeldonResponse
from seldon_core.flask_utils import SeldonMicroserviceException
from seldon_core.metrics import DEFAULT_LABELS, NONIMPLEMENTED_MSG
Expand Down Expand Up @@ -73,7 +73,7 @@ def load(self):

"""
if "/" in self.storage_uri:
model_folder = kfserving.Storage.download(self.storage_uri)
model_folder = download_model(self.storage_uri)
self.model = pickle.load(
open(os.path.join(model_folder, "meta.pickle"), "rb")
)
Expand Down
5 changes: 3 additions & 2 deletions components/alibi-detect-server/adserver/od_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from typing import List, Dict, Optional, Union
import os
import logging
import kfserving
import numpy as np
from .numpy_encoder import NumpyEncoder
from adserver.base import CEModel
from adserver.base.storage import download_model
from alibi_detect.utils.saving import load_detector, Data
from seldon_core.user_model import SeldonResponse
from adserver.base.storage import download_model
from adserver.constants import (
HEADER_RETURN_INSTANCE_SCORE,
HEADER_RETURN_FEATURE_SCORE,
Expand Down Expand Up @@ -62,7 +63,7 @@ def load(self):
Load the model from storage

"""
model_folder = kfserving.Storage.download(self.storage_uri)
model_folder = download_model(self.storage_uri)
self.model: Data = load_detector(model_folder)
self.ready = True

Expand Down
1 change: 1 addition & 0 deletions components/alibi-detect-server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"numpy >= 1.8.2",
"cloudevents == 1.2.0",
"elasticsearch==7.9.1",
"sh<2.0.0",
# Fixes #2533
"google-cloud-core==1.4.1",
"google-cloud-storage==1.31.2",
Expand Down
Loading