Skip to content

Commit a4cdc9f

Browse files
author
Adrian Gonzalez-Martin
authored
Add helpers to build custom MLServer images (#371)
1 parent db34354 commit a4cdc9f

File tree

44 files changed

+5650
-106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+5650
-106
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ bin
1818
*.swp
1919
*.swo
2020
*~
21+
.env
2122

2223
# Python dev
2324
.mypy_cache

Dockerfile

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ FROM python:3.8-slim AS wheel-builder
22
SHELL ["/bin/bash", "-c"]
33

44
COPY ./hack/build-wheels.sh ./hack/build-wheels.sh
5-
6-
COPY setup.py .
7-
COPY README.md .
8-
COPY ./mlserver/ ./mlserver/
9-
COPY ./runtimes/ ./runtimes/
5+
COPY ./mlserver ./mlserver
6+
COPY ./runtimes ./runtimes
7+
COPY \
8+
setup.py \
9+
README.md \
10+
.
1011

1112
# This will build the wheels and place will place them in the
1213
# /opt/mlserver/dist folder
@@ -53,11 +54,15 @@ COPY requirements/docker.txt requirements/docker.txt
5354
RUN pip install -r requirements/docker.txt
5455

5556
COPY ./licenses/license.txt .
56-
57-
COPY ./hack/activate-env.sh ./hack/activate-env.sh
57+
COPY \
58+
./hack/build-env.sh \
59+
./hack/generate_dotenv.py \
60+
./hack/activate-env.sh \
61+
./hack/
5862

5963
USER 1000
6064

61-
# Need to source `activate-env.sh` so that env changes get persisted
62-
CMD . ./hack/activate-env.sh $MLSERVER_ENV_TARBALL \
63-
&& mlserver start $MLSERVER_MODELS_DIR
65+
# We need to build and activate the "hot-loaded" environment before MLServer
66+
# starts
67+
CMD source ./hack/activate-env.sh $MLSERVER_ENV_TARBALL . && \
68+
mlserver start $MLSERVER_MODELS_DIR

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ Out of the box, MLServer comes with a set of pre-packaged runtimes which let
6464
you interact with a subset of common frameworks.
6565
This allows you to start serving models saved in these frameworks straight
6666
away.
67+
However, it's also possible to **write [custom
68+
runtimes](./docs/runtimes/custom)**.
6769

6870
Out of the box, MLServer provides support for:
6971

docs/conf.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
project = "MLServer"
2222
copyright = "2021, Seldon Technologies"
23-
html_title = "MLServer"
23+
html_title = "MLServer Documentation"
2424
author = "Seldon Technologies"
2525

2626
# The full version, including alpha/beta/rc tags
27-
release = "0.6.0.dev2"
27+
release = "0.6.0.dev3"
2828

2929

3030
# -- General configuration ---------------------------------------------------
@@ -37,6 +37,7 @@
3737
"sphinx_search.extension",
3838
"sphinxcontrib.bibtex",
3939
"sphinxcontrib.autodoc_pydantic",
40+
"sphinx_click",
4041
]
4142

4243
# Add any paths that contain templates here, relative to this directory.
@@ -122,6 +123,7 @@
122123
html_theme_path = sphinx_material.html_theme_path()
123124
html_context = sphinx_material.get_html_context()
124125

126+
html_favicon = "favicon.ico"
125127
html_sidebars = {
126128
"**": ["logo-text.html", "globaltoc.html", "localtoc.html", "searchbox.html"]
127129
}

docs/examples/custom/README.ipynb

Lines changed: 4687 additions & 12 deletions
Large diffs are not rendered by default.

docs/examples/custom/README.md

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ The next step will be to create 2 configuration files:
200200
"name": "numpyro-divorce",
201201
"implementation": "models.NumpyroModel",
202202
"parameters": {
203-
"uri": "./numpyro-divorce.json",
204-
"version": "v0.1.0",
203+
"uri": "./numpyro-divorce.json"
205204
}
206205
}
207206
```
@@ -240,13 +239,104 @@ inference_request = {
240239
]
241240
}
242241

243-
endpoint = "http://localhost:8080/v2/models/numpyro-divorce/versions/v0.1.0/infer"
242+
endpoint = "http://localhost:8080/v2/models/numpyro-divorce/infer"
244243
response = requests.post(endpoint, json=inference_request)
245244

246245
response.json()
247246
```
248247

248+
## Deployment
249+
250+
Now that we have written and tested our custom model, the next step is to deploy it.
251+
With that goal in mind, the rough outline of steps will be to first build a custom image containing our code, and then deploy it.
252+
253+
254+
### Building a custom image
255+
256+
```{note}
257+
This section expects that Docker is available and running in the background.
258+
```
259+
260+
MLServer offers helpers to build a custom Docker image containing your code.
261+
In this example, we will use the `mlserver build` subcommand to create an image, which we'll be able to deploy later.
262+
263+
264+
Note that this section expects that Docker is available and running in the background, as well as a functional cluster with Seldon Core installed and some familiarity with `kubectl`.
265+
266+
267+
```bash
268+
%%bash
269+
mlserver build . -t 'my-custom-numpyro-server'
270+
```
271+
272+
To ensure that the image is fully functional, we can spin up a container and then send a test request. To start the container, you can run something along the following lines in a separate terminal:
273+
274+
```bash
275+
docker run -it --rm -p 8080:8080 my-custom-numpyro-server
276+
```
277+
249278

250279
```python
280+
import requests
251281

282+
x_0 = [28.0]
283+
inference_request = {
284+
"inputs": [
285+
{
286+
"name": "marriage",
287+
"shape": [1],
288+
"datatype": "FP32",
289+
"data": x_0
290+
}
291+
]
292+
}
293+
294+
endpoint = "http://localhost:8080/v2/models/numpyro-divorce/infer"
295+
response = requests.post(endpoint, json=inference_request)
296+
297+
response.json()
298+
```
299+
300+
As we should be able to see, the server running within our Docker image responds as expected.
301+
302+
### Deploying our custom image
303+
304+
```{note}
305+
This section expects access to a functional Kubernetes cluster with Seldon Core installed and some familiarity with `kubectl`.
306+
```
307+
308+
Now that we've built a custom image and verified that it works as expected, we can move to the next step and deploy it.
309+
There is a large number of tools out there to deploy images.
310+
However, for our example, we will focus on deploying it to a cluster running [Seldon Core](https://docs.seldon.io/projects/seldon-core/en/latest/).
311+
312+
For that, we will need to create a `SeldonDeployment` resource which instructs Seldon Core to deploy a model embedded within our custom image and compliant with the [V2 Inference Protocol](https://github.com/kserve/kserve/tree/master/docs/predict-api/v2).
313+
This can be achieved by _applying_ (i.e. `kubectl apply`) a `SeldonDeployment` manifest to the cluster, similar to the one below:
314+
315+
316+
```python
317+
%%writefile seldondeployment.yaml
318+
apiVersion: machinelearning.seldon.io/v1
319+
kind: SeldonDeployment
320+
metadata:
321+
name: numpyro-model
322+
spec:
323+
predictors:
324+
- name: default
325+
annotations:
326+
seldon.io/no-engine: "true"
327+
graph:
328+
name: mlflow-model
329+
type: MODEL
330+
componentSpecs:
331+
- spec:
332+
containers:
333+
- name: mlflow-model
334+
image: my-custom-numpyro-server
335+
ports:
336+
- containerPort: 8080
337+
name: http
338+
protocol: TCP
339+
- containerPort: 8081
340+
name: grpc
341+
protocol: TCP
252342
```

docs/examples/custom/model-settings.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"name": "numpyro-divorce",
33
"implementation": "models.NumpyroModel",
44
"parameters": {
5-
"uri": "./numpyro-divorce.json",
6-
"version": "v0.1.0",
5+
"uri": "./numpyro-divorce.json"
76
}
87
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
numpy==1.18.5
2+
numpyro==0.8.0
3+
jax==0.2.24
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: machinelearning.seldon.io/v1
2+
kind: SeldonDeployment
3+
metadata:
4+
name: numpyro-model
5+
spec:
6+
predictors:
7+
- name: default
8+
annotations:
9+
seldon.io/no-engine: "true"
10+
graph:
11+
name: mlflow-model
12+
type: MODEL
13+
componentSpecs:
14+
- spec:
15+
containers:
16+
- name: mlflow-model
17+
image: my-custom-numpyro-server
18+
ports:
19+
- containerPort: 8080
20+
name: http
21+
protocol: TCP
22+
- containerPort: 8081
23+
name: grpc
24+
protocol: TCP

docs/favicon.ico

4.19 KB
Binary file not shown.

0 commit comments

Comments
 (0)