Skip to content
Permalink
Browse files

Update quick-start guide for coming release & MISC (#295)

* move things around

* update links in readme

* renaming cli command 'docs' to 'open-api-spec'

* nit

* fix _get_bento_service_metadata_pb

* include more metadata in cli command 'info' output

* fix error message

* update DeploymentOperator cli option and update proto

* fix unit test

* update track_cli event name after renaming

* Update bentoml-quick-start-guide.ipynb

* auto formatting

* ignore guides directory in black auto formatting script

* fixing ALL linter errors 😆
  • Loading branch information...
parano committed Sep 17, 2019
1 parent bdf4139 commit c4482a0c0747c79efcbdae900be09acc76ccfd8b
Showing with 243 additions and 298 deletions.
  1. +5 −5 README.md
  2. +0 −1 bentoml/__init__.py
  3. +3 −0 bentoml/archive/config.py
  4. +4 −6 bentoml/archive/loader.py
  5. +16 −18 bentoml/cli/__init__.py
  6. +2 −2 bentoml/cli/click_utils.py
  7. +2 −1 bentoml/cli/config.py
  8. +22 −17 bentoml/cli/deployment.py
  9. +15 −22 bentoml/cli/deployment_utils.py
  10. +16 −7 bentoml/configuration/__init__.py
  11. +17 −7 bentoml/deployment/clipper/__init__.py
  12. +1 −1 bentoml/deployment/sagemaker/__init__.py
  13. +1 −1 bentoml/deployment/store.py
  14. +2 −2 bentoml/handlers/fastai_image_handler.py
  15. +58 −65 bentoml/proto/deployment_pb2.py
  16. +4 −5 bentoml/repository/metadata_store.py
  17. +2 −2 bentoml/server/bento_api_server.py
  18. +4 −4 bentoml/service.py
  19. +1 −1 bentoml/utils/usage_stats.py
  20. +2 −2 bentoml/utils/validator/__init__.py
  21. +3 −4 bentoml/yatai/python_api.py
  22. +3 −2 bentoml/yatai/yatai_service_impl.py
  23. +0 −1 examples/deploy-with-sagemaker/output.json
  24. +0 −1 examples/local-dependencies/.gitignore
  25. +0 −3 examples/local-dependencies/main.sh
  26. +0 −3 examples/local-dependencies/mymodule/__init__.py
  27. 0 examples/local-dependencies/mymodule/scripts/__init__.py
  28. +0 −51 examples/local-dependencies/mymodule/scripts/main.py
  29. +0 −3 examples/local-dependencies/mymodule/submodule/__init__.py
  30. +0 −3 examples/local-dependencies/mymodule/submodule/submodule2.py
  31. +0 −3 examples/local-dependencies/mymodule/submodule1.py
  32. +0 −1 examples/local-dependencies/mymodule/unused_module.py
  33. +0 −2 examples/use-with-python-script/requirements.txt
  34. 0 {examples → guides/deployment}/deploy-with-clipper/deploy-iris-classifier-to-clipper.ipynb
  35. 0 {examples → guides/deployment}/deploy-with-clipper/fastai-pet-classifier-on-clipper.ipynb
  36. 0 {examples → guides/deployment}/deploy-with-kubernetes/README.md
  37. 0 {examples → guides/deployment}/deploy-with-kubernetes/deploy-with-kubernetes.ipynb
  38. 0 {examples → guides/deployment}/deploy-with-kubernetes/deployment.yaml
  39. 0 {examples → guides/deployment}/deploy-with-kubernetes/service-with-ingress.yaml
  40. 0 {examples → guides/deployment}/deploy-with-kubernetes/service-without-ingress.yaml
  41. 0 {examples → guides/deployment}/deploy-with-sagemaker/.gitignore
  42. 0 {examples → guides/deployment}/deploy-with-sagemaker/README.md
  43. BIN {examples → guides/deployment}/deploy-with-sagemaker/aws-ecr.png
  44. BIN {examples → guides/deployment}/deploy-with-sagemaker/aws-endpoint-config.png
  45. BIN {examples → guides/deployment}/deploy-with-sagemaker/aws-endpoint.png
  46. BIN {examples → guides/deployment}/deploy-with-sagemaker/aws-model.png
  47. 0 {examples → guides/deployment}/deploy-with-sagemaker/deploy-with-sagemaker.ipynb
  48. BIN {examples → guides/deployment}/deploy-with-sagemaker/docker-image.png
  49. BIN {examples → guides/deployment}/deploy-with-sagemaker/file-struc.png
  50. 0 {examples → guides/deployment}/deploy-with-sagemaker/sentiment_lr_model.py
  51. BIN {examples → guides/deployment}/deploy-with-sagemaker/test-prediction.png
  52. 0 {examples → guides/deployment}/deploy-with-serverless/.gitignore
  53. 0 {examples → guides/deployment}/deploy-with-serverless/README.md
  54. BIN {examples → guides/deployment}/deploy-with-serverless/cloud-formation.png
  55. 0 {examples → guides/deployment}/deploy-with-serverless/deploy-with-serverless.ipynb
  56. BIN {examples → guides/deployment}/deploy-with-serverless/file-structures.png
  57. BIN {examples → guides/deployment}/deploy-with-serverless/lambda-dash.png
  58. BIN {examples → guides/deployment}/deploy-with-serverless/make-prediction-curl.png
  59. 0 {examples → guides/deployment}/deploy-with-serverless/requirements.txt
  60. 0 {examples → guides/deployment}/deploy-with-serverless/sentiment_lr_model.py
  61. 0 {examples → guides}/quick-start/.gitignore
  62. +36 −32 {examples → guides}/quick-start/bentoml-quick-start-guide.ipynb
  63. 0 {examples → guides}/quick-start/iris_classifier.py
  64. 0 {examples → guides/quick-start}/use-with-python-script/main.py
  65. 0 {examples/local-dependencies → guides/quick-start/use-with-python-script}/requirements.txt
  66. +15 −15 protos/deployment.proto
  67. +1 −0 pyproject.toml
  68. +4 −0 tests/conftest.py
  69. +2 −2 tests/test_pip_install_bento_archive.py
  70. +0 −1 tests/test_save_and_load.py
  71. +2 −2 tests/utils/test_utils.py
@@ -168,7 +168,7 @@ Try out the full getting started notebook
* League of Legend win Prediction - [Google Colab](https://colab.research.google.com/github/bentoml/gallery/blob/master/xgboost/league-of-legend-win-prediction/xgboost-league-of-legend-win-prediction.ipynb) | [nbviewer](https://nbviewer.jupyter.org/github/bentoml/gallery/blob/master/xgboost/league-of-legend-win-prediction/xgboost-league-of-legend-win-prediction.ipynb) | [source](https://github.com/bentoml/gallery/blob/master/xgboost/league-of-legend-win-prediction/xgboost-league-of-legend-win-prediction.ipynb)


#### H2o
#### H2O

* Loan Default Prediction - [Google Colab](https://colab.research.google.com/github/bentoml/gallery/blob/master/h2o/loan-prediction/h2o-loan-prediction.ipynb) | [nbviewer](https://nbviewer.jupyter.org/github/bentoml/gallery/blob/master/h2o/loan-prediction/h2o-loan-prediction.ipynb) | [source](https://github.com/bentoml/gallery/blob/master/h2o/loan-prediction/h2o-loan-prediction.ipynb)
* Prostate Cancer Prediction - [Google Colab](https://colab.research.google.com/github/bentoml/gallery/blob/master/h2o/prostate-cancer-classification/h2o-prostate-cancer-classification.ipynb) | [nbviewer](https://nbviewer.jupyter.org/github/bentoml/gallery/blob/master/h2o/prostate-cancer-classification/h2o-prostate-cancer-classification.ipynb) | [source](https://github.com/bentoml/gallery/blob/master/h2o/prostate-cancer-classification/h2o-prostate-cancer-classification.ipynb)
@@ -179,10 +179,10 @@ Try out the full getting started notebook

### Deployment guides:

- [Serverless deployment with AWS Lambda](https://github.com/bentoml/BentoML/blob/master/examples/deploy-with-serverless)
- [API server deployment with AWS SageMaker](https://github.com/bentoml/BentoML/blob/master/examples/deploy-with-sagemaker)
- [API server deployment with Clipper](https://github.com/bentoml/BentoML/blob/master/example/deploy-with-clipper/deploy-iris-classifier-to-clipper.ipynb)
- [API server deployment on Kubernetes](https://github.com/bentoml/BentoML/tree/master/examples/deploy-with-kubernetes)
- [Serverless deployment with AWS Lambda](https://github.com/bentoml/BentoML/blob/master/guides/deployment/deploy-with-serverless)
- [API server deployment with AWS SageMaker](https://github.com/bentoml/BentoML/blob/master/guides/deployment/deploy-with-sagemaker)
- [API server deployment with Clipper](https://github.com/bentoml/BentoML/blob/master/guides/deployment/deploy-with-clipper/deploy-iris-classifier-to-clipper.ipynb)
- [API server deployment on Kubernetes](https://github.com/bentoml/BentoML/tree/master/guides/deployment/deploy-with-kubernetes)


## Feature Highlights
@@ -32,7 +32,6 @@
ver_decorator as ver,
)
from bentoml.server import metrics
from bentoml.utils.log import configure_logging
from bentoml.yatai.python_api import upload_bento_service

save = upload_bento_service
@@ -83,3 +83,6 @@ def __getitem__(self, item):

def __setitem__(self, key, value):
self.config[key] = value

def __contains__(self, item):
return item in self.config
@@ -19,7 +19,7 @@
import os
import sys
import logging
import datetime


from bentoml.utils import dump_to_yaml_str
from bentoml.utils.usage_stats import track_load_finish, track_load_start
@@ -46,9 +46,7 @@ def load_bento_service_metadata(archive_path):
bento_service_metadata = BentoServiceMetadata()
bento_service_metadata.name = config["metadata"]["service_name"]
bento_service_metadata.version = config["metadata"]["service_version"]

created_at_dt = datetime.datetime.fromisoformat(config["metadata"]["created_at"])
bento_service_metadata.created_at.FromDatetime(created_at_dt)
bento_service_metadata.created_at.FromDatetime(config["metadata"]["created_at"])

if "env" in config:
if "setup_sh" in config["env"]:
@@ -73,7 +71,7 @@ def load_bento_service_metadata(archive_path):
api_metadata.handler_type = api_config["handler_type"]
if "docs" in api_config:
api_metadata.docs = api_config["docs"]
bento_service_metadata.apis.append(api_metadata)
bento_service_metadata.apis.extend([api_metadata])

if "artifacts" in config:
for artifact_config in config["artifacts"]:
@@ -82,7 +80,7 @@ def load_bento_service_metadata(archive_path):
artifact_metadata.name = artifact_config["name"]
if "artifact_type" in artifact_config:
artifact_metadata.artifact_type = artifact_config["artifact_type"]
bento_service_metadata.artifacts.append(artifact_metadata)
bento_service_metadata.artifacts.extend([artifact_metadata])

return bento_service_metadata

@@ -25,8 +25,14 @@
import subprocess

from ruamel.yaml import YAML

from bentoml.archive import load, load_service_api, load_bentoml_config
from google.protobuf.json_format import MessageToDict

from bentoml.archive import (
load,
load_service_api,
load_bentoml_config,
load_bento_service_metadata,
)
from bentoml.server import BentoAPIServer, get_docs
from bentoml.server.gunicorn_server import GunicornBentoServer
from bentoml.cli.click_utils import BentoMLCommandGroup, conditional_argument, _echo
@@ -145,27 +151,19 @@ def info(archive_path=archive_path):
List all APIs defined in the BentoService loaded from archive
"""
track_cli('info')
bento_service = load(archive_path)

service_apis = bento_service.get_service_apis()
output = json.dumps(
dict(
name=bento_service.name,
version=bento_service.version,
apis=[api.name for api in service_apis],
),
indent=2,
)
bento_service_metadata_pb = load_bento_service_metadata(archive_path)
output = json.dumps(MessageToDict(bento_service_metadata_pb), indent=2)
_echo(output)

# Example usage: bentoml docs /SAVED_ARCHIVE_PATH
# Example usage: bentoml open-api-spec /SAVED_ARCHIVE_PATH
@bentoml_cli.command(
help="Display API documents in Open API format",
short_help="Display OpenAPI docs",
name="open-api-spec",
help="Display API specification JSON in Open-API format",
short_help="Display OpenAPI/Swagger JSON specs",
)
@conditional_argument(archive_path is None, "archive-path", type=click.STRING)
def docs(archive_path=archive_path):
track_cli('docs')
def open_api_spec(archive_path=archive_path):
track_cli('open-api-spec')
bento_service = load(archive_path)

_echo(json.dumps(get_docs(bento_service), indent=2))
@@ -116,7 +116,7 @@ def decorator(f):
return decorator


def parse_bento_tag_callback(ctx, param, value):
def parse_bento_tag_callback(ctx, param, value): # pylint: disable=unused-argument
if re.match(r"^[A-Za-z_][A-Za-z_0-9]*:[A-Za-z0-9.+-_]*$", value) is None:
raise click.BadParameter(
"Bad formatting. Please present in BentoName:Version, for example "
@@ -126,7 +126,7 @@ def parse_bento_tag_callback(ctx, param, value):
return value


def parse_yaml_file_callback(ctx, param, value):
def parse_yaml_file_callback(ctx, param, value): # pylint: disable=unused-argument
yaml = YAML()
yml_content = value.read()
try:
@@ -73,11 +73,12 @@ def view_effective():
return

@config.command(
name="set",
context_settings=dict(ignore_unknown_options=True, allow_extra_args=True),
help="Set value to BentoML configuration",
)
@click.argument("updates", nargs=-1)
def set(updates):
def set_command(updates):
track_cli('config-set')
local_config = ConfigParser()
local_config_file = get_local_config_file()
@@ -38,7 +38,6 @@
ListDeploymentsRequest,
Deployment,
DeploymentSpec,
DeploymentOperator,
DeploymentState,
)
from bentoml.proto.status_pb2 import Status
@@ -48,8 +47,6 @@
from bentoml.deployment.store import ALL_NAMESPACE_TAG
from bentoml import config

SERVERLESS_PLATFORMS = ['aws-lambda', 'aws-lambda-py2', 'gcp-function']

# pylint: disable=unused-variable

logger = logging.getLogger(__name__)
@@ -108,13 +105,14 @@ def deployment():
type=click.STRING,
required=True,
callback=parse_bento_tag_callback,
help='Deployed bento archive, in format of name:version. For example, '
help='Deployed bento archive, in format of name:version. For example, '
'iris_classifier:v1.2.0',
)
@click.option(
'--platform',
type=click.Choice(
['aws_lambda', 'gcp_function', 'aws_sagemaker', 'kubernetes', 'custom']
['aws-lambda', 'gcp-function', 'aws-sagemaker', 'kubernetes', 'custom'],
case_sensitive=False,
),
required=True,
help='Target platform that Bento archive is going to deployed to',
@@ -128,22 +126,22 @@ def deployment():
@click.option('--annotations', type=click.STRING)
@click.option(
'--region',
help='Name of the deployed region. For platforms: AWS_Lambda, AWS_SageMaker, '
'GCP_Function',
help='Name of the deployed region. For platforms: AWS Lambda, AWS SageMaker, '
'GCP Function',
)
@click.option(
'--instance-type',
help='Type of instance will be used for inference. For platform: AWS_SageMaker',
help='Type of instance will be used for inference. For platform: AWS SageMaker',
)
@click.option(
'--instance-count',
help='Number of instance will be used. For platform: AWS_SageMaker',
help='Number of instance will be used. For platform: AWS SageMaker',
type=click.INT,
)
@click.option(
'--api-name',
help='User defined API function will be used for inference. For platform: '
'AWS_SageMaker',
'AWS SageMaker',
)
@click.option(
'--kube-namespace',
@@ -177,9 +175,16 @@ def create(
service_type,
wait,
):
# converting platform parameter to DeploymentOperator name in proto
# e.g. 'aws-lambda' to 'AWS_LAMBDA'
platform = platform.replace('-', '_').upper()
operator = DeploymentSpec.DeploymentOperator.Value(platform)

track_cli('deploy-create', platform)

yatai_service = get_yatai_service()

# Make sure there is no active deployment with the same deployment name
get_deployment = yatai_service.GetDeployment(
GetDeploymentRequest(deployment_name=name, namespace=namespace)
)
@@ -189,7 +194,7 @@ def create(
' instead'.format(name=name)
)

if platform == 'aws_sagemaker':
if operator == DeploymentSpec.AWS_SAGEMAKER:
if not api_name:
raise click.BadParameter(
'api-name is required for Sagemaker deployment'
@@ -204,19 +209,19 @@ def create(
api_name=api_name,
)
spec = DeploymentSpec(sagemaker_operator_config=sagemaker_operator_config)
elif platform == 'aws_lambda':
elif operator == DeploymentSpec.AWS_LAMBDA:
aws_lambda_operator_config = DeploymentSpec.AwsLambdaOperatorConfig(
region=region or config().get('aws', 'default_region')
)
spec = DeploymentSpec(aws_lambda_operator_config=aws_lambda_operator_config)
elif platform == 'gcp_function':
elif operator == DeploymentSpec.GCP_FUNCTION:
gcp_function_operator_config = DeploymentSpec.GcpFunctionOperatorConfig(
region=region or config().get('google-cloud', 'default_region')
)
spec = DeploymentSpec(
gcp_function_operator_config=gcp_function_operator_config
)
elif platform == 'kubernetes':
elif operator == DeploymentSpec.KUBERNETES:
kubernetes_operator_config = DeploymentSpec.KubernetesOperatorConfig(
kube_namespace=kube_namespace,
replicas=replicas,
@@ -232,7 +237,7 @@ def create(
bento_name, bento_version = bento.split(':')
spec.bento_name = bento_name
spec.bento_version = bento_version
spec.operator = DeploymentOperator.Value(platform.upper())
spec.operator = operator

result = yatai_service.ApplyDeployment(
ApplyDeploymentRequest(
@@ -397,7 +402,7 @@ def describe(name, output, namespace):
deployment_pb.state.CopyFrom(result.state)
display_deployment_info(deployment_pb, output)

@deployment.command(help='List deployments')
@deployment.command(name="list", help='List deployments')
@click.option('--namespace', type=click.STRING)
@click.option('--all-namespace', type=click.BOOL, default=False)
@click.option(
@@ -412,7 +417,7 @@ def describe(name, output, namespace):
'--labels', type=click.STRING, help='List deployments with the giving labels'
)
@click.option('--output', type=click.Choice(['json', 'yaml']), default='json')
def list(output, limit, filters, labels, namespace, all_namespace):
def list_deployments(output, limit, filters, labels, namespace, all_namespace):
track_cli('deploy-list')

if all_namespace:
@@ -19,7 +19,7 @@

import logging

from bentoml.proto.deployment_pb2 import Deployment, DeploymentOperator
from bentoml.proto.deployment_pb2 import Deployment, DeploymentSpec
from bentoml.exceptions import BentoMLException

logger = logging.getLogger(__name__)
@@ -40,28 +40,27 @@ def deployment_yaml_to_pb(deployment_yaml):
spec_yaml = deployment_yaml.get('spec')
platform = spec_yaml.get('operator')
if platform is not None:
deployment_pb.spec.operator = DeploymentOperator.Value(platform.upper())
deployment_pb.spec.operator = DeploymentSpec.DeploymentOperator.Value(
platform.replace('-', '_').upper()
)
if spec_yaml.get('bento_name'):
deployment_pb.spec.bento_name = spec_yaml.get('bento_name')
if spec_yaml.get('bento_version'):
deployment_pb.spec.bento_version = spec_yaml.get('bento_version')

if platform == 'aws_sagemaker':
sagemaker_config = spec_yaml.get('sagemaker_operator_config')
sagemaker_operator_config_pb = deployment_pb.spec.sagemaker_operator_config
if sagemaker_config.get('api_name'):
deployment_pb.spec.sagemaker_operator_config.api_name = sagemaker_config.get(
'api_name'
)
sagemaker_operator_config_pb.api_name = sagemaker_config.get('api_name')
if sagemaker_config.get('region'):
deployment_pb.spec.sagemaker_operator_config.region = sagemaker_config.get(
'region'
)
sagemaker_operator_config_pb.region = sagemaker_config.get('region')
if sagemaker_config.get('instance_count'):
deployment_pb.spec.sagemaker_operator_config.instance_count = sagemaker_config.get(
sagemaker_operator_config_pb.instance_count = sagemaker_config.get(
'instance_count'
)
if sagemaker_config.get('instance_type'):
deployment_pb.spec.sagemaker_operator_config.instance_type = sagemaker_config.get(
sagemaker_operator_config_pb.instance_type = sagemaker_config.get(
'instance_type'
)
elif platform == 'aws_lambda':
@@ -76,22 +75,16 @@ def deployment_yaml_to_pb(deployment_yaml):
)
elif platform == 'kubernetes':
k8s_config = spec_yaml.get('kubernetes_operator_config')
k8s_operator_config_pb = deployment_pb.spec.kubernetes_operator_config

if k8s_config.get('kube_namespace'):
deployment_pb.spec.kubernetes_operator_config.kube_namespace = k8s_config.get(
'kube_namespace'
)
k8s_operator_config_pb.kube_namespace = k8s_config.get('kube_namespace')
if k8s_config.get('replicas'):
deployment_pb.spec.kubernetes_operator_config.replicas = k8s_config.get(
'replicas'
)
k8s_operator_config_pb.replicas = k8s_config.get('replicas')
if k8s_config.get('service_name'):
deployment_pb.spec.kubernetes_operator_config.service_name = k8s_config.get(
'service_name'
)
k8s_operator_config_pb.service_name = k8s_config.get('service_name')
if k8s_config.get('service_type'):
deployment_pb.spec.kubernetes_operator_config.service_type = k8s_config.get(
'service_type'
)
k8s_operator_config_pb.service_type = k8s_config.get('service_type')
else:
raise BentoMLException(
'Custom deployment is not supported in the current version of BentoML'

0 comments on commit c4482a0

Please sign in to comment.
You can’t perform that action at this time.