This page was generated from examples/models/metadata/metadata.ipynb.
Simple Metadata Example¶
Prerequisites¶
A kubernetes cluster with kubectl configured
curl
grpcurl
pygmentize
Setup Seldon Core¶
Use the setup notebook to Setup Cluster to setup Seldon Core with an ingress.
[1]:
!kubectl create namespace seldon
Error from server (AlreadyExists): namespaces "seldon" already exists
[2]:
!kubectl config set-context $(kubectl config current-context) --namespace=seldon
Context "kind-kind" modified.
Example description¶
In this example we will define a following metadata
name: my-model-name
versions: [ my-model-version-01 ]
platform: seldon
inputs:
- messagetype: tensor
schema:
names: [a, b, c, d]
shape: [ 4 ]
outputs:
- messagetype: tensor
schema:
shape: [ 1 ]
which corresponds to model taking a tensor input with four columns named a
, b
, c
, and d
.
We will define the metadata
in two ways: directly in the model.py and in the deployment manifest.
When defining metadata
in deployment manifest we will use different names to indicate that metadata can be overwritten.
At the end we will see what happens if one misdefined the Metadata.
[3]:
import time
import requests
def getWithRetry(url, expected_code=requests.codes.ok):
for i in range(3):
r = requests.get(url)
if r.status_code == expected_code:
meta = r.json()
return meta
else:
print("Failed request with status code ", r.status_code)
time.sleep(3)
1. Directly define in model¶
Define Model¶
[4]:
%%writefile models/init-metadata/Model.py
import logging
class Model:
def predict(self, features, names=[], meta=[]):
logging.info(f"model features: {features}")
logging.info(f"model names: {names}")
logging.info(f"model meta: {meta}")
return features
def init_metadata(self):
logging.info("metadata method called")
meta = {
"name": "my-model-name",
"versions": ["my-model-version-01"],
"platform": "seldon",
"inputs": [
{
"messagetype": "tensor",
"schema": {"names": ["a", "b", "c", "d"], "shape": [4]},
}
],
"outputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
"custom": {
"author": "seldon-dev"
}
}
return meta
Overwriting models/init-metadata/Model.py
Build image¶
build image using provided Makefile
cd models/init-metadata
make build
If you are using kind
you can use kind_image_install
target to directly load your image into your local cluster.
Define deployment¶
[5]:
%%writefile model-metadata/init-metadata.yaml
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: seldon-model-init-metadata
spec:
name: test-deployment
predictors:
- componentSpecs:
- spec:
containers:
- image: seldonio/model-with-metadata:0.5
name: my-model
env:
- name: SELDON_LOG_LEVEL
value: DEBUG
graph:
children: []
name: my-model
type: MODEL
name: example
replicas: 1
Overwriting model-metadata/init-metadata.yaml
Deploy¶
[6]:
!kubectl apply -f model-metadata/init-metadata.yaml
seldondeployment.machinelearning.seldon.io/seldon-model-init-metadata created
[7]:
!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-model-init-metadata -o jsonpath='{.items[0].metadata.name}')
Waiting for deployment "seldon-model-init-metadata-example-0-my-model" rollout to finish: 0 of 1 updated replicas are available...
deployment "seldon-model-init-metadata-example-0-my-model" successfully rolled out
Model Metadata¶
[8]:
meta = getWithRetry(
"http://localhost:8003/seldon/seldon/seldon-model-init-metadata/api/v1.0/metadata/my-model"
)
assert meta == {
"name": "my-model-name",
"versions": ["my-model-version-01"],
"platform": "seldon",
"inputs": [
{
"messagetype": "tensor",
"schema": {"names": ["a", "b", "c", "d"], "shape": [4]},
}
],
"outputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
"custom": {"author": "seldon-dev"},
}
meta
[8]:
{'custom': {'author': 'seldon-dev'},
'inputs': [{'messagetype': 'tensor',
'schema': {'names': ['a', 'b', 'c', 'd'], 'shape': [4]}}],
'name': 'my-model-name',
'outputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}],
'platform': 'seldon',
'versions': ['my-model-version-01']}
Graph Metadata¶
[9]:
meta = getWithRetry(
"http://localhost:8003/seldon/seldon/seldon-model-init-metadata/api/v1.0/metadata"
)
assert meta == {
"name": "example",
"models": {
"my-model": {
"name": "my-model-name",
"platform": "seldon",
"versions": ["my-model-version-01"],
"inputs": [
{
"messagetype": "tensor",
"schema": {"names": ["a", "b", "c", "d"], "shape": [4]},
}
],
"outputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
"custom": {"author": "seldon-dev"},
}
},
"graphinputs": [
{
"messagetype": "tensor",
"schema": {"names": ["a", "b", "c", "d"], "shape": [4]},
}
],
"graphoutputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
}
meta
[9]:
{'name': 'example',
'models': {'my-model': {'name': 'my-model-name',
'platform': 'seldon',
'versions': ['my-model-version-01'],
'inputs': [{'messagetype': 'tensor',
'schema': {'names': ['a', 'b', 'c', 'd'], 'shape': [4]}}],
'outputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}],
'custom': {'author': 'seldon-dev'}}},
'graphinputs': [{'messagetype': 'tensor',
'schema': {'names': ['a', 'b', 'c', 'd'], 'shape': [4]}}],
'graphoutputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}]}
2. Via environmental variable¶
Metadata defined via environmental variables will overwrite top-level fields in metadata defined directly in the models.
You can use this approach to overwrite metadata defined in the model or to provide metadata if model does not define it.
[10]:
%%writefile model-metadata/environ-metadata.yaml
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: seldon-model-environ-metadata
spec:
name: test-deployment
predictors:
- componentSpecs:
- spec:
containers:
- image: seldonio/model-with-metadata:0.5
name: my-model
env:
- name: SELDON_LOG_LEVEL
value: DEBUG
- name: MODEL_METADATA
value: |
---
name: second-example-model-name
versions: [ my-model-version-01 ]
inputs:
- messagetype: tensor
schema:
names: [alpha, beta, gamma, delta]
shape: [4]
custom:
author: seldon-dev
purpose: tutorial
graph:
children: []
name: my-model
type: MODEL
name: example
replicas: 1
Overwriting model-metadata/environ-metadata.yaml
[11]:
!kubectl apply -f model-metadata/environ-metadata.yaml
seldondeployment.machinelearning.seldon.io/seldon-model-environ-metadata created
[12]:
!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-model-environ-metadata -o jsonpath='{.items[0].metadata.name}')
Waiting for deployment "seldon-model-environ-metadata-example-0-my-model" rollout to finish: 0 of 1 updated replicas are available...
deployment "seldon-model-environ-metadata-example-0-my-model" successfully rolled out
Model Metadata¶
[13]:
meta = getWithRetry(
"http://localhost:8003/seldon/seldon/seldon-model-environ-metadata/api/v1.0/metadata/my-model"
)
assert meta == {
"name": "second-example-model-name",
"versions": ["my-model-version-01"],
"platform": "seldon",
"inputs": [
{
"messagetype": "tensor",
"schema": {"names": ["alpha", "beta", "gamma", "delta"], "shape": [4]},
}
],
"outputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
"custom": {"author": "seldon-dev", "purpose": "tutorial"},
}
meta
[13]:
{'custom': {'author': 'seldon-dev', 'purpose': 'tutorial'},
'inputs': [{'messagetype': 'tensor',
'schema': {'names': ['alpha', 'beta', 'gamma', 'delta'], 'shape': [4]}}],
'name': 'second-example-model-name',
'outputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}],
'platform': 'seldon',
'versions': ['my-model-version-01']}
Graph Metadata¶
[14]:
meta = getWithRetry(
"http://localhost:8003/seldon/seldon/seldon-model-environ-metadata/api/v1.0/metadata"
)
assert meta == {
"name": "example",
"models": {
"my-model": {
"name": "second-example-model-name",
"platform": "seldon",
"versions": ["my-model-version-01"],
"inputs": [
{
"messagetype": "tensor",
"schema": {
"names": ["alpha", "beta", "gamma", "delta"],
"shape": [4],
},
}
],
"outputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
"custom": {"author": "seldon-dev", "purpose": "tutorial"},
}
},
"graphinputs": [
{
"messagetype": "tensor",
"schema": {"names": ["alpha", "beta", "gamma", "delta"], "shape": [4]},
}
],
"graphoutputs": [{"messagetype": "tensor", "schema": {"shape": [1]}}],
}
meta
[14]:
{'name': 'example',
'models': {'my-model': {'name': 'second-example-model-name',
'platform': 'seldon',
'versions': ['my-model-version-01'],
'inputs': [{'messagetype': 'tensor',
'schema': {'names': ['alpha', 'beta', 'gamma', 'delta'], 'shape': [4]}}],
'outputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}],
'custom': {'author': 'seldon-dev', 'purpose': 'tutorial'}}},
'graphinputs': [{'messagetype': 'tensor',
'schema': {'names': ['alpha', 'beta', 'gamma', 'delta'], 'shape': [4]}}],
'graphoutputs': [{'messagetype': 'tensor', 'schema': {'shape': [1]}}]}
3. Invalid metadata definition¶
Here we define metadata that is invalid (versions must be a list)
[15]:
%%writefile model-metadata/invalid-environ-metadata.yaml
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: seldon-model-invalid-environ-metadata
spec:
name: test-deployment
predictors:
- componentSpecs:
- spec:
containers:
- image: seldonio/model-with-metadata:0.5
name: my-model
env:
- name: SELDON_LOG_LEVEL
value: DEBUG
- name: MODEL_METADATA
value: |
---
name: my-model-name
versions: my-model-version-01
graph:
children: []
name: my-model
type: MODEL
name: example
replicas: 1
Overwriting model-metadata/invalid-environ-metadata.yaml
[16]:
!kubectl apply -f model-metadata/invalid-environ-metadata.yaml
seldondeployment.machinelearning.seldon.io/seldon-model-invalid-environ-metadata created
[17]:
!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=seldon-model-invalid-environ-metadata -o jsonpath='{.items[0].metadata.name}')
Waiting for deployment "seldon-model-invalid-environ-metadata-example-0-my-model" rollout to finish: 0 of 1 updated replicas are available...
deployment "seldon-model-invalid-environ-metadata-example-0-my-model" successfully rolled out
Requesting Metadata will lead to 500 error.
[18]:
meta = getWithRetry(
"http://localhost:8003/seldon/seldon/seldon-model-invalid-environ-metadata/api/v1.0/metadata/my-model",
500,
)
assert meta == {
"status": {
"code": -1,
"info": "Model metadata unavailable",
"reason": "MICROSERVICE_BAD_METADATA",
"status": 1,
}
}
meta
[18]:
{'status': {'code': -1,
'info': 'Model metadata unavailable',
'reason': 'MICROSERVICE_BAD_METADATA',
'status': 1}}
But Model will still be serving predictions
[19]:
%%bash
curl -s -H 'Content-Type: application/json' \
-d '{"data": {"names": ["input"], "ndarray": ["data"]}}' \
http://localhost:8003/seldon/seldon/seldon-model-invalid-environ-metadata/api/v1.0/predictions
{"data":{"names":[],"ndarray":["data"]},"meta":{}}
Cleanup resources¶
[20]:
%%bash
kubectl delete -f model-metadata/
seldondeployment.machinelearning.seldon.io "seldon-model-environ-metadata" deleted
seldondeployment.machinelearning.seldon.io "seldon-model-init-metadata" deleted
seldondeployment.machinelearning.seldon.io "seldon-model-invalid-environ-metadata" deleted
[ ]: