Skip to content

Commit

Permalink
Update kserve sdk examples with renamed classes (kubeflow#1966)
Browse files Browse the repository at this point in the history
* Update kserve sdk examples

Signed-off-by: Mark Winter <mark.winter@navercorp.com>

* Better var names

Signed-off-by: Mark Winter <mark.winter@navercorp.com>

* Update READMEs

Signed-off-by: Mark Winter <mark.winter@navercorp.com>
  • Loading branch information
markwinter authored Dec 28, 2021
1 parent 8fe28b9 commit 340df7a
Show file tree
Hide file tree
Showing 44 changed files with 124 additions and 124 deletions.
4 changes: 2 additions & 2 deletions docs/samples/explanation/aif/germancredit/server/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from aif360.algorithms.preprocessing.optim_preproc_helpers.data_preproc_functions import load_preproc_data_german


class KServeSampleModel(kserve.KFModel):
class KServeSampleModel(kserve.Model):
def __init__(self, name: str):
super().__init__(name)
self.name = name
Expand Down Expand Up @@ -39,4 +39,4 @@ def predict(self, request: Dict) -> Dict:
if __name__ == "__main__":
model = KServeSampleModel("german-credit")
model.load()
kserve.KFServer(workers=1).start([model])
kserve.ModelServer(workers=1).start([model])
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

DEFAULT_MODEL_NAME = "rfserver"

parser = argparse.ArgumentParser(parents=[kserve.kfserver.parser])
parser = argparse.ArgumentParser(parents=[kserve.model_server.parser])
parser.add_argument('--model_name', default=DEFAULT_MODEL_NAME,
help='The name that the model is served under.')
args, _ = parser.parse_known_args()

if __name__ == "__main__":
model = RFModel(args.model_name)
model.load()
kserve.KFServer().start([model])
kserve.ModelServer().start([model])
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def transform(self, X):
return self._step_func(X)


class RFModel(kserve.KFModel): # pylint:disable=c-extension-no-member
class RFModel(kserve.Model): # pylint:disable=c-extension-no-member
def __init__(self, name: str):
super().__init__(name)
self.name = name
Expand Down
2 changes: 1 addition & 1 deletion docs/samples/explanation/aix/mnist/rfserver/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
license='https://github.com/kserve/kserve/LICENSE',
url='https://github.com/kserve/kserve/python/rfserver',
description='Model Server implementation for AI eXplainability using LIME. \
Not intended for use outside KFServing Frameworks Images',
Not intended for use outside KServe Frameworks Images',
long_description=open('README.md').read(),
python_requires='>3.4',
packages=find_packages("rfserver"),
Expand Down
2 changes: 1 addition & 1 deletion docs/samples/explanation/art/mnist/sklearnserver/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
license='https://github.com/kserve/kserve/LICENSE',
url='https://github.com/kserve/kserve/python/sklearnserver',
description='Model Server implementation for scikit-learn. \
Not intended for use outside KFServing Frameworks Images',
Not intended for use outside KServe Frameworks Images',
long_description=open('README.md').read(),
python_requires='>3.4',
packages=find_packages("sklearnserver"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
import sys

import kserve
from .kfserver import KFServer
from .kfserver import ModelServer
from sklearnserver import SKLearnModel, SKLearnModelRepository

DEFAULT_MODEL_NAME = "model"
DEFAULT_LOCAL_MODEL_DIR = "/tmp/model"

parser = argparse.ArgumentParser(parents=[kserve.kfserver.parser])
parser = argparse.ArgumentParser(parents=[kserve.model_server.parser])
parser.add_argument('--model_dir', required=True,
help='A URI pointer to the model binary')
parser.add_argument('--model_name', default=DEFAULT_MODEL_NAME,
Expand All @@ -38,4 +38,4 @@
logging.error(f"fail to load model {args.model_name} from dir {args.model_dir}. "
f"exception type {ex_type}, exception msg: {ex_value}")
model.ready = False
KFServer(registered_models=SKLearnModelRepository(args.model_dir)).start([model] if model.ready else [])
ModelServer(registered_models=SKLearnModelRepository(args.model_dir)).start([model] if model.ready else [])
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
import tornado.web
import json
from http import HTTPStatus
from .kfmodel_repository import KFModelRepository
from .model_repository import ModelRepository


class HTTPHandler(tornado.web.RequestHandler):
def initialize(self, models: KFModelRepository):
def initialize(self, models: ModelRepository):
self.models = models # pylint:disable=attribute-defined-outside-init

def get_model(self, name: str):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
# limitations under the License.

from typing import List, Optional
from kserve import KFModel
from kserve import Model

MODEL_MOUNT_DIRS = "/mnt/models"


class KFModelRepository:
class ModelRepository:
"""
Model repository interface, follows NVIDIA Triton's `model-repository`
extension.
Expand All @@ -30,17 +30,17 @@ def __init__(self, models_dir: str = MODEL_MOUNT_DIRS):
def set_models_dir(self, models_dir): # used for unit tests
self.models_dir = models_dir

def get_model(self, name: str) -> Optional[KFModel]:
def get_model(self, name: str) -> Optional[Model]:
return self.models.get(name, None)

def get_models(self) -> List[KFModel]:
def get_models(self) -> List[Model]:
return list(self.models.values())

def is_model_ready(self, name: str):
model = self.get_model(name)
return False if model is None else model.ready

def update(self, model: KFModel):
def update(self, model: Model):
self.models[model.name] = model

def load(self, name: str) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import tornado.log

from .http import PredictHandler, ExplainHandler
from kserve import KFModel
from .kfmodel_repository import KFModelRepository
from kserve import Model
from .model_repository import ModelRepository

DEFAULT_HTTP_PORT = 8080
DEFAULT_GRPC_PORT = 8081
Expand All @@ -44,12 +44,12 @@
tornado.log.enable_pretty_logging()


class KFServer:
class ModelServer:
def __init__(self, http_port: int = args.http_port,
grpc_port: int = args.grpc_port,
max_buffer_size: int = args.max_buffer_size,
workers: int = args.workers,
registered_models: KFModelRepository = KFModelRepository()):
registered_models: ModelRepository = ModelRepository()):
self.registered_models = registered_models
self.http_port = http_port
self.grpc_port = grpc_port
Expand Down Expand Up @@ -85,7 +85,7 @@ def create_application(self):
UnloadHandler, dict(models=self.registered_models)),
])

def start(self, models: List[KFModel], nest_asyncio: bool = False):
def start(self, models: List[Model], nest_asyncio: bool = False):
for model in models:
self.register_model(model)

Expand All @@ -106,7 +106,7 @@ def start(self, models: List[KFModel], nest_asyncio: bool = False):

tornado.ioloop.IOLoop.current().start()

def register_model(self, model: KFModel):
def register_model(self, model: Model):
if not model.name:
raise Exception(
"Failed to register model, model.name must be provided.")
Expand All @@ -120,7 +120,7 @@ def get(self):


class HealthHandler(tornado.web.RequestHandler):
def initialize(self, models: KFModelRepository):
def initialize(self, models: ModelRepository):
self.models = models # pylint:disable=attribute-defined-outside-init

def get(self, name: str):
Expand All @@ -144,15 +144,15 @@ def get(self, name: str):


class ListHandler(tornado.web.RequestHandler):
def initialize(self, models: KFModelRepository):
def initialize(self, models: ModelRepository):
self.models = models # pylint:disable=attribute-defined-outside-init

def get(self):
self.write(json.dumps([ob.name for ob in self.models.get_models()]))


class LoadHandler(tornado.web.RequestHandler):
def initialize(self, models: KFModelRepository): # pylint:disable=attribute-defined-outside-init
def initialize(self, models: ModelRepository): # pylint:disable=attribute-defined-outside-init
self.models = models

async def post(self, name: str):
Expand All @@ -178,7 +178,7 @@ async def post(self, name: str):


class UnloadHandler(tornado.web.RequestHandler):
def initialize(self, models: KFModelRepository): # pylint:disable=attribute-defined-outside-init
def initialize(self, models: ModelRepository): # pylint:disable=attribute-defined-outside-init
self.models = models

def post(self, name: str):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
MODEL_EXTENSIONS = [".joblib", ".pkl", ".pickle"]


class SKLearnModel(kserve.KFModel): # pylint:disable=c-extension-no-member
class SKLearnModel(kserve.Model): # pylint:disable=c-extension-no-member
def __init__(self, name: str, model_dir: str):
super().__init__(name)
self.name = name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
# limitations under the License.

import os
from .kfmodel_repository import KFModelRepository, MODEL_MOUNT_DIRS
from .model_repository import ModelRepository, MODEL_MOUNT_DIRS
from sklearnserver import SKLearnModel


class SKLearnModelRepository(KFModelRepository):
class SKLearnModelRepository(ModelRepository):

def __init__(self, model_dir: str = MODEL_MOUNT_DIRS):
super().__init__(model_dir)
Expand Down
6 changes: 3 additions & 3 deletions docs/samples/kafka/image_transformer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

DEFAULT_MODEL_NAME = "model"

parser = argparse.ArgumentParser(parents=[kserve.kfserver.parser])
parser = argparse.ArgumentParser(parents=[kserve.model_server.parser])
parser.add_argument('--model_name', default=DEFAULT_MODEL_NAME,
help='The name that the model is served under.')
parser.add_argument('--predictor_host', help='The URL for the model predict function', required=True)
Expand All @@ -26,5 +26,5 @@

if __name__ == "__main__":
transformer = ImageTransformer(args.model_name, predictor_host=args.predictor_host)
kfserver = kserve.KFServer()
kfserver.start(models=[transformer])
server = kserve.ModelServer()
server.start(models=[transformer])
2 changes: 1 addition & 1 deletion docs/samples/kafka/image_transformer/image_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def image_transform(image):
return g.tolist()


class ImageTransformer(kserve.KFModel):
class ImageTransformer(kserve.Model):
def __init__(self, name: str, predictor_host: str):
super().__init__(name)
self.predictor_host = predictor_host
Expand Down
26 changes: 13 additions & 13 deletions docs/samples/v1beta1/custom/custom_model/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# Deploy Custom Python Model with KFServer API
When out of the box model server does not fit your need, you can build your own model server using KFServer API and use the
following source to serving workflow to deploy your custom models to KFServing.
following source to serving workflow to deploy your custom models to KServe.

## Setup
1. Your ~/.kube/config should point to a cluster with [KFServing installed](https://github.com/kubeflow/kfserving/#install-kfserving).
1. Your ~/.kube/config should point to a cluster with [KServe installed](https://github.com/kserve/kserve#installation).
2. Your cluster's Istio Ingress gateway must be [network accessible](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/).
3. Install [pack CLI](https://buildpacks.io/docs/tools/pack/) to build your custom model server image.

## Create your custom Model Server by extending KFModel
`KFServing.KFModel` base class mainly defines three handlers `preprocess`, `predict` and `postprocess`, these handlers are executed
## Create your custom Model Server by extending Model
`KServe.Model` base class mainly defines three handlers `preprocess`, `predict` and `postprocess`, these handlers are executed
in sequence, the output of the `preprocess` is passed to `predict` as the input, the `predictor` handler should execute the
inference for your model, the `postprocess` handler then turns the raw prediction result into user-friendly inference response. There
is an additional `load` handler which is used for writing custom code to load your model into the memory from local file system or
remote model storage, a general good practice is to call the `load` handler in the model server class `__init__` function, so your model
is loaded on startup and ready to serve when user is making the prediction calls.

```python
import kfserving
import kserve
from typing import Dict

class AlexNetModel(kfserving.KFModel):
class AlexNetModel(kserve.Model):
def __init__(self, name: str):
super().__init__(name)
self.name = name
Expand All @@ -33,11 +33,11 @@ class AlexNetModel(kfserving.KFModel):

if __name__ == "__main__":
model = AlexNetModel("custom-model")
kfserving.KFServer().start([model])
kserve.ModelServer().start([model])
```

## Build the custom image with Buildpacks
[Buildpacks](https://buildpacks.io/) allows you to transform your inference code into images that can be deployed on KFServing without
[Buildpacks](https://buildpacks.io/) allows you to transform your inference code into images that can be deployed on KServe without
needing to define the `Dockerfile`. Buildpacks automatically determines the python application and then install the dependencies from the
`requirements.txt` file, it looks at the `Procfile` to determine how to start the model server. Here we are showing how to build the serving
image manually with `pack`, you can also choose to use [kpack](https://github.com/pivotal/kpack)
Expand All @@ -52,16 +52,16 @@ docker push ${DOCKER_USER}/custom-model:v1
## Parallel Inference
By default the model is loaded and inference is ran in the same process as tornado http server, if you are hosting multiple models
the inference can only be run for one model at a time which limits the concurrency when you share the container for the models.
KFServing integrates [RayServe](https://docs.ray.io/en/master/serve/index.html) which provides a programmable API to deploy models
KServe integrates [RayServe](https://docs.ray.io/en/master/serve/index.html) which provides a programmable API to deploy models
as separate python workers so the inference can be ran in parallel.

```python
import kfserving
import kserve
from typing import Dict
from ray import serve

@serve.deployment(name="custom-model", config={"num_replicas": 2})
class AlexNetModel(kfserving.KFModel):
class AlexNetModel(kserve.Model):
def __init__(self):
self.name = "custom-model"
super().__init__(self.name)
Expand All @@ -74,7 +74,7 @@ class AlexNetModel(kfserving.KFModel):
pass

if __name__ == "__main__":
kfserving.KFServer().start({"custom-model": AlexNetModel})
kserve.ModelServer().start({"custom-model": AlexNetModel})
```

Modify the `Procfile` to `web: python -m model_remote` and then run the above `pack` command, it builds the serving image which launches
Expand All @@ -96,7 +96,7 @@ curl localhost:8080/v1/models/custom-model:predict -d @./input.json
{"predictions": [[14.861763000488281, 13.94291877746582, 13.924378395080566, 12.182709693908691, 12.00634765625]]}
```

## Deploy to KFServing
## Deploy to KServe
### Create the InferenceService

In the `custom.yaml` file edit the container image and replace {username} with your Docker Hub username.
Expand Down
4 changes: 2 additions & 2 deletions docs/samples/v1beta1/custom/torchserve/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ In this example we use torchserve as custom server to serve an mnist model. The

## Setup

1. Your ~/.kube/config should point to a cluster with [KFServing installed](https://github.com/kubeflow/kfserving/#install-kfserving).
1. Your ~/.kube/config should point to a cluster with [KServe installed](https://github.com/kserve/kserve#installation).
2. Your cluster's Istio Ingress gateway must be [network accessible](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/).

### This example requires v1beta1/KFS 0.5

## Build and push the sample Docker Image

The custom torchserve image is wrapped with model inside the container and serves it with KFServing.
The custom torchserve image is wrapped with model inside the container and serves it with KServe.

In this example we build a torchserve image with marfile and config.properties into a container. To build and push with Docker Hub, run these commands replacing {username} with your Docker Hub username:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ torch-model-archiver --model-name BERTSeqClassification --version 1.0 --serializ

## Build and push the sample Docker Image

The custom torchserve image is wrapped with model inside the container and serves it with KFServing.
The custom torchserve image is wrapped with model inside the container and serves it with KServe.

In this example we use Docker to build the torchserve image with marfile and config.properties into a container.

Expand Down
2 changes: 1 addition & 1 deletion docs/samples/v1beta1/custom/torchserve/docs/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This adds prometheus and granfana to the cluster with some default metrics.

## Setup

1. Your ~/.kube/config should point to a cluster with [KFServing installed](https://github.com/kubeflow/kfserving/#install-kfserving).
1. Your ~/.kube/config should point to a cluster with [KServe installed](https://github.com/kserve/kserve#installation).
2. Your cluster's Istio Ingress gateway must be [network accessible](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/).

## Enable request metrics
Expand Down
6 changes: 3 additions & 3 deletions docs/samples/v1beta1/lightgbm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ print(res.text)
## Predict on a InferenceService using LightGBM Server

## Setup
1. Your ~/.kube/config should point to a cluster with [KFServing installed](https://github.com/kubeflow/kfserving/#install-kfserving).
1. Your ~/.kube/config should point to a cluster with [KServe installed](https://github.com/kserve/kserve#installation).
2. Your cluster's Istio Ingress gateway must be [network accessible](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/).

## Create the InferenceService
Expand Down Expand Up @@ -99,11 +99,11 @@ Expected Output
```

## Run LightGBM InferenceService with your own image
Since the KFServing LightGBM image is built from a specific version of `lightgbm` pip package, sometimes it might not be compatible with the pickled model
Since the KServe LightGBM image is built from a specific version of `lightgbm` pip package, sometimes it might not be compatible with the pickled model
you saved from your training environment, however you can build your own lgbserver image following [this instruction](../../../python/lgbserver/README.md#building-your-own-ligthgbm-server-docker-image).

To use your lgbserver image:
- Add the image to the KFServing [configmap](../../../../config/configmap/inferenceservice.yaml)
- Add the image to the KServe [configmap](../../../../config/configmap/inferenceservice.yaml)
```yaml
"lightgbm": {
"image": "<your-dockerhub-id>/kfserving/lgbserver",
Expand Down
Loading

0 comments on commit 340df7a

Please sign in to comment.