Skip to content

Commit

Permalink
Fix missing alibi key in explainers configmap (kubeflow#439)
Browse files Browse the repository at this point in the history
* Fix missing alibi key in configmap

* Remove hardcode alibi image name

* Add alibi explainer default test

* Add validation/default tests for explainer

* Add alibi explainer container creation test

* Fix format

* Fix alibiexplainer image registry
  • Loading branch information
yuzisun authored and k8s-ci-robot committed Oct 13, 2019
1 parent a2efe33 commit 9a38524
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 74 deletions.
14 changes: 8 additions & 6 deletions config/default/configmap/inferenceservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,17 @@ data:
}
explainers: |-
{
"image" : "docker.io/seldonio/alibiexplainer",
"defaultImageVersion": "0.2.3",
"allowedImageVersions": [
"0.2.3"
]
"alibi": {
"image" : "gcr.io/kfserving/alibi-explainer",
"defaultImageVersion": "0.2.0",
"allowedImageVersions": [
"0.2.0"
]
}
}
storageInitializer: |-
{
"image" : "gcr.io/kfserving/storage-initializer:latest"
"image" : "gcr.io/kfserving/storage-initializer:0.2.0"
}
credentials: |-
{
Expand Down
12 changes: 7 additions & 5 deletions install/0.2.0/kfserving.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -756,11 +756,13 @@ data:
}
explainers: |-
{
"image" : "docker.io/seldonio/alibiexplainer",
"defaultImageVersion": "0.2.3",
"allowedImageVersions": [
"0.2.3"
]
"alibi": {
"image" : "gcr.io/kfserving/alibi-explainer",
"defaultImageVersion": "0.2.0",
"allowedImageVersions": [
"0.2.0"
]
}
}
ingress: |-
{
Expand Down
8 changes: 1 addition & 7 deletions pkg/apis/serving/v1alpha2/explainer_alibi.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
)

var (
AlibiImageName = "docker.io/seldonio/alibiexplainer"
InvalidAlibiRuntimeVersionError = "RuntimeVersion must be one of %s"
)

Expand All @@ -18,11 +17,6 @@ func (s *AlibiExplainerSpec) GetStorageUri() string {
}

func (s *AlibiExplainerSpec) CreateExplainerContainer(modelName string, predictorHost string, config *InferenceServicesConfig) *v1.Container {
imageName := AlibiImageName
if config.Explainers.AlibiExplainer.ContainerImage != "" {
imageName = config.Explainers.AlibiExplainer.ContainerImage
}

var args = []string{
constants.ArgumentModelName, modelName,
constants.ArgumentPredictorHost, predictorHost,
Expand All @@ -40,7 +34,7 @@ func (s *AlibiExplainerSpec) CreateExplainerContainer(modelName string, predicto
}

return &v1.Container{
Image: imageName + ":" + s.RuntimeVersion,
Image: config.Explainers.AlibiExplainer.ContainerImage + ":" + s.RuntimeVersion,
Resources: s.Resources,
Args: args,
}
Expand Down
99 changes: 99 additions & 0 deletions pkg/apis/serving/v1alpha2/explainer_alibi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package v1alpha2

import (
"fmt"
"github.com/onsi/gomega"
"github.com/onsi/gomega/types"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"strings"
"testing"
)

func TestAlibiExplainer(t *testing.T) {
g := gomega.NewGomegaWithT(t)
allowedAlibiImageVersionsArray := []string{
DefaultAlibiExplainerRuntimeVersion,
}
allowedAlibiImageVersions := strings.Join(allowedAlibiImageVersionsArray, ", ")

scenarios := map[string]struct {
spec AlibiExplainerSpec
matcher types.GomegaMatcher
}{
"AcceptGoodRuntimeVersion": {
spec: AlibiExplainerSpec{
RuntimeVersion: DefaultAlibiExplainerRuntimeVersion,
},
matcher: gomega.Succeed(),
},
"RejectBadRuntimeVersion": {
spec: AlibiExplainerSpec{
RuntimeVersion: "",
},
matcher: gomega.MatchError(fmt.Sprintf(InvalidAlibiRuntimeVersionError, allowedAlibiImageVersions)),
},
}

for name, scenario := range scenarios {
config := &InferenceServicesConfig{
Explainers: &ExplainersConfig{
AlibiExplainer: ExplainerConfig{
ContainerImage: "seldon.io/alibi",
DefaultImageVersion: "latest",
AllowedImageVersions: allowedAlibiImageVersionsArray,
},
},
}
g.Expect(scenario.spec.Validate(config)).Should(scenario.matcher, fmt.Sprintf("Testing %s", name))
}
}

func TestCreateAlibiExplainerContainer(t *testing.T) {

var requestedResource = v1.ResourceRequirements{
Limits: v1.ResourceList{
"cpu": resource.Quantity{
Format: "100",
},
},
Requests: v1.ResourceList{
"cpu": resource.Quantity{
Format: "90",
},
},
}
config := &InferenceServicesConfig{
Explainers: &ExplainersConfig{
AlibiExplainer: ExplainerConfig{
ContainerImage: "seldon.io/alibi",
DefaultImageVersion: "latest",
},
},
}
var spec = AlibiExplainerSpec{
Type: "Anchor",
StorageURI: "gs://someUri",
Resources: requestedResource,
RuntimeVersion: "0.1.0",
}
g := gomega.NewGomegaWithT(t)

expectedContainer := &v1.Container{
Image: "seldon.io/alibi:0.1.0",
Resources: requestedResource,
Args: []string{
"--model_name",
"someName",
"--predictor_host",
"predictor.svc.cluster.local",
"--storage_uri",
"/mnt/models",
"Anchor",
},
}

// Test Create with config
container := spec.CreateExplainerContainer("someName", "predictor.svc.cluster.local", config)
g.Expect(container).To(gomega.Equal(expectedContainer))
}
37 changes: 37 additions & 0 deletions pkg/apis/serving/v1alpha2/inferenceservice_defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,40 @@ func TestTensorRTDefaults(t *testing.T) {
g.Expect(isvc.Spec.Canary.Predictor.TensorRT.Resources.Requests[v1.ResourceCPU]).To(gomega.Equal(DefaultCPU))
g.Expect(isvc.Spec.Canary.Predictor.TensorRT.Resources.Requests[v1.ResourceMemory]).To(gomega.Equal(resource.MustParse("3Gi")))
}

func TestAlibiExplainerDefaults(t *testing.T) {
g := gomega.NewGomegaWithT(t)
isvc := InferenceService{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: InferenceServiceSpec{
Default: EndpointSpec{
Predictor: PredictorSpec{
Tensorflow: &TensorflowSpec{
StorageURI: "gs://testbucket/testmodel",
},
},
Explainer: &ExplainerSpec{
Alibi: &AlibiExplainerSpec{
StorageURI: "gs://testbucket/testmodel",
},
},
},
},
}
isvc.Spec.Canary = isvc.Spec.Default.DeepCopy()
isvc.Spec.Canary.Explainer.Alibi.RuntimeVersion = "0.2.4"
isvc.Spec.Canary.Explainer.Alibi.Resources.Requests = v1.ResourceList{v1.ResourceMemory: resource.MustParse("3Gi")}
isvc.Default(c)

g.Expect(isvc.Spec.Default.Explainer.Alibi.RuntimeVersion).To(gomega.Equal(DefaultAlibiExplainerRuntimeVersion))
g.Expect(isvc.Spec.Default.Explainer.Alibi.Resources.Requests[v1.ResourceCPU]).To(gomega.Equal(DefaultCPU))
g.Expect(isvc.Spec.Default.Explainer.Alibi.Resources.Requests[v1.ResourceMemory]).To(gomega.Equal(DefaultMemory))
g.Expect(isvc.Spec.Default.Explainer.Alibi.Resources.Limits[v1.ResourceCPU]).To(gomega.Equal(DefaultCPU))
g.Expect(isvc.Spec.Default.Explainer.Alibi.Resources.Limits[v1.ResourceMemory]).To(gomega.Equal(DefaultMemory))
g.Expect(isvc.Spec.Canary.Explainer.Alibi.RuntimeVersion).To(gomega.Equal("0.2.4"))
g.Expect(isvc.Spec.Canary.Explainer.Alibi.Resources.Requests[v1.ResourceCPU]).To(gomega.Equal(DefaultCPU))
g.Expect(isvc.Spec.Canary.Explainer.Alibi.Resources.Requests[v1.ResourceMemory]).To(gomega.Equal(resource.MustParse("3Gi")))
}
12 changes: 12 additions & 0 deletions pkg/apis/serving/v1alpha2/inferenceservice_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,15 @@ func TestRejectBadExplainer(t *testing.T) {
isvc.Spec.Default.Explainer = &ExplainerSpec{}
g.Expect(isvc.ValidateCreate(c)).Should(gomega.MatchError(ExactlyOneExplainerViolatedError))
}

func TestGoodExplainer(t *testing.T) {
g := gomega.NewGomegaWithT(t)
isvc := makeTestInferenceService()
isvc.Spec.Default.Explainer = &ExplainerSpec{
Alibi: &AlibiExplainerSpec{
StorageURI: "gs://testbucket/testmodel",
},
}
isvc.Default(c)
g.Expect(isvc.ValidateCreate(c)).Should(gomega.Succeed())
}
122 changes: 66 additions & 56 deletions pkg/apis/serving/v1alpha2/v1alpha2_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ var cfg *rest.Config
var c client.Client

const (
DefaultTensorflowRuntimeVersion = "latest"
DefaultTensorflowRuntimeVersionGPU = "latest-gpu"
DefaultSKLearnRuntimeVersion = "0.1.0"
DefaultPyTorchRuntimeVersion = "0.1.0"
DefaultXGBoostRuntimeVersion = "0.1.0"
DefaultTensorRTRuntimeVersion = "19.05-py3"
DefaultONNXRuntimeVersion = "v0.5.0"
DefaultTensorflowRuntimeVersion = "latest"
DefaultTensorflowRuntimeVersionGPU = "latest-gpu"
DefaultSKLearnRuntimeVersion = "0.1.0"
DefaultPyTorchRuntimeVersion = "0.1.0"
DefaultXGBoostRuntimeVersion = "0.1.0"
DefaultTensorRTRuntimeVersion = "19.05-py3"
DefaultONNXRuntimeVersion = "v0.5.0"
DefaultAlibiExplainerRuntimeVersion = "0.2.3"
)

func TestMain(m *testing.M) {
Expand All @@ -67,55 +68,64 @@ func TestMain(m *testing.M) {
// Create configmap
configs := map[string]string{
"predictors": `{
"tensorflow" : {
"image" : "tensorflow/serving",
"defaultImageVersion": "latest",
"defaultGPUImageVersion": "latest-gpu",
"allowedImageVersions": [
"latest",
"latest-gpu"
]
},
"sklearn" : {
"image" : "kfserving/sklearnserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"xgboost" : {
"image" : "kfserving/xgbserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"pytorch" : {
"image" : "kfserving/pytorchserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"onnx" : {
"image" : "onnxruntime/server",
"defaultImageVersion": "v0.5.0",
"allowedImageVersions": [
"latest",
"v0.5.0"
]
},
"tensorrt" : {
"image" : "nvcr.io/nvidia/tensorrtserver",
"defaultImageVersion": "19.05-py3",
"allowedImageVersions": [
"19.05-py3"
]
}
}`,
"tensorflow" : {
"image" : "tensorflow/serving",
"defaultImageVersion": "latest",
"defaultGPUImageVersion": "latest-gpu",
"allowedImageVersions": [
"latest",
"latest-gpu"
]
},
"sklearn" : {
"image" : "kfserving/sklearnserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"xgboost" : {
"image" : "kfserving/xgbserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"pytorch" : {
"image" : "kfserving/pytorchserver",
"defaultImageVersion": "0.1.0",
"allowedImageVersions": [
"latest",
"0.1.0"
]
},
"onnx" : {
"image" : "onnxruntime/server",
"defaultImageVersion": "v0.5.0",
"allowedImageVersions": [
"latest",
"v0.5.0"
]
},
"tensorrt" : {
"image" : "nvcr.io/nvidia/tensorrtserver",
"defaultImageVersion": "19.05-py3",
"allowedImageVersions": [
"19.05-py3"
]
}
}`,
"explainers": `{
"alibi" : {
"image" : "docker.io/seldonio/alibiexplainer",
"defaultImageVersion": "0.2.3",
"allowedImageVersions": [
"0.2.3"
]
}
}`,
}
var configMap = &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand Down

0 comments on commit 9a38524

Please sign in to comment.