{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### BentoML Example\n", "\n", "# XGBoost League of legend Win prediction \n", "\n", "**BentoML makes moving trained ML models to production easy:**\n", "\n", "* Package models trained with **any ML framework** and reproduce them for model serving in production\n", "* **Deploy anywhere** for online API serving or offline batch serving\n", "* High-Performance API model server with *adaptive micro-batching* support\n", "* Central hub for managing models and deployment process via Web UI and APIs\n", "* Modular and flexible design making it *adaptable to your infrastrcuture*\n", "\n", "BentoML is a framework for serving, managing, and deploying machine learning models. It is aiming to bridge the gap between Data Science and DevOps, and enable teams to deliver prediction services in a fast, repeatable, and scalable way.\n", "\n", "Before reading this example project, be sure to check out the [Getting started guide](https://github.com/bentoml/BentoML/blob/master/guides/quick-start/bentoml-quick-start-guide.ipynb) to learn about the basic concepts in BentoML.\n", "\n", "This is a BentoML Demo Project demonstrating how to train a League of Legend win prdiction model, and use BentoML to package and serve the model for building applictions.\n", "\n", "\n", "Example notebook built based on https://slundberg.github.io/shap/notebooks/League%20of%20Legends%20Win%20Prediction%20with%20XGBoost.html\n", "\n", "![Impression](https://www.google-analytics.com/collect?v=1&tid=UA-112879361-3&cid=555&t=event&ec=xgboost&ea=xgboost-league-of-legend-win-prediction&dt=xgboost-league-of-legend-win-prediction)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline\n", "\n", "import warnings\n", "warnings.filterwarnings(\"ignore\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: bentoml in /opt/anaconda3/lib/python3.7/site-packages (0.8.1+27.g8e155f5.dirty)\n", "Requirement already satisfied: requests in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (2.24.0)\n", "Requirement already satisfied: click>=7.0 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (7.1.2)\n", "Requirement already satisfied: alembic in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.4.0)\n", "Requirement already satisfied: cerberus in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.3.2)\n", "Requirement already satisfied: prometheus-client in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.8.0)\n", "Requirement already satisfied: protobuf>=3.6.0 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (3.11.3)\n", "Requirement already satisfied: aiohttp in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (3.6.2)\n", "Requirement already satisfied: sqlalchemy-utils in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.36.6)\n", "Requirement already satisfied: ruamel.yaml>=0.15.0 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.16.10)\n", "Requirement already satisfied: tabulate in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.8.6)\n", "Requirement already satisfied: humanfriendly in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (7.1.1)\n", "Requirement already satisfied: numpy in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.18.5)\n", "Requirement already satisfied: packaging in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (20.4)\n", "Requirement already satisfied: psutil in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (5.7.0)\n", "Requirement already satisfied: configparser in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (4.0.2)\n", "Requirement already satisfied: certifi in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (2020.6.20)\n", "Requirement already satisfied: grpcio<=1.27.2 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.27.2)\n", "Requirement already satisfied: flask in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.1.1)\n", "Requirement already satisfied: sqlalchemy>=1.3.0 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.3.9)\n", "Requirement already satisfied: python-json-logger in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.1.11)\n", "Requirement already satisfied: py-zipkin in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (0.18.7)\n", "Requirement already satisfied: python-dateutil<2.8.1,>=2.1 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (2.8.0)\n", "Requirement already satisfied: gunicorn in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (20.0.4)\n", "Requirement already satisfied: docker in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (4.2.0)\n", "Requirement already satisfied: boto3 in /opt/anaconda3/lib/python3.7/site-packages (from bentoml) (1.12.9)\n", "Requirement already satisfied: chardet<4,>=3.0.2 in /opt/anaconda3/lib/python3.7/site-packages (from requests->bentoml) (3.0.4)\n", "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /opt/anaconda3/lib/python3.7/site-packages (from requests->bentoml) (1.24.3)\n", "Requirement already satisfied: idna<3,>=2.5 in /opt/anaconda3/lib/python3.7/site-packages (from requests->bentoml) (2.10)\n", "Requirement already satisfied: python-editor>=0.3 in /opt/anaconda3/lib/python3.7/site-packages (from alembic->bentoml) (1.0.4)\n", "Requirement already satisfied: Mako in /opt/anaconda3/lib/python3.7/site-packages (from alembic->bentoml) (1.1.1)\n", "Requirement already satisfied: setuptools in /opt/anaconda3/lib/python3.7/site-packages (from cerberus->bentoml) (49.1.0.post20200710)\n", "Requirement already satisfied: six>=1.9 in /opt/anaconda3/lib/python3.7/site-packages (from protobuf>=3.6.0->bentoml) (1.15.0)\n", "Requirement already satisfied: attrs>=17.3.0 in /opt/anaconda3/lib/python3.7/site-packages (from aiohttp->bentoml) (19.3.0)\n", "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/anaconda3/lib/python3.7/site-packages (from aiohttp->bentoml) (1.4.2)\n", "Requirement already satisfied: multidict<5.0,>=4.5 in /opt/anaconda3/lib/python3.7/site-packages (from aiohttp->bentoml) (4.7.5)\n", "Requirement already satisfied: async-timeout<4.0,>=3.0 in /opt/anaconda3/lib/python3.7/site-packages (from aiohttp->bentoml) (3.0.1)\n", "Requirement already satisfied: ruamel.yaml.clib>=0.1.2; platform_python_implementation == \"CPython\" and python_version < \"3.9\" in /opt/anaconda3/lib/python3.7/site-packages (from ruamel.yaml>=0.15.0->bentoml) (0.2.0)\n", "Requirement already satisfied: pyparsing>=2.0.2 in /opt/anaconda3/lib/python3.7/site-packages (from packaging->bentoml) (2.4.7)\n", "Requirement already satisfied: Jinja2>=2.10.1 in /opt/anaconda3/lib/python3.7/site-packages (from flask->bentoml) (2.11.2)\n", "Requirement already satisfied: Werkzeug>=0.15 in /opt/anaconda3/lib/python3.7/site-packages (from flask->bentoml) (0.16.0)\n", "Requirement already satisfied: itsdangerous>=0.24 in /opt/anaconda3/lib/python3.7/site-packages (from flask->bentoml) (1.1.0)\n", "Requirement already satisfied: thriftpy2>=0.4.0 in /opt/anaconda3/lib/python3.7/site-packages (from py-zipkin->bentoml) (0.4.10)\n", "Requirement already satisfied: websocket-client>=0.32.0 in /opt/anaconda3/lib/python3.7/site-packages (from docker->bentoml) (0.57.0)\n", "Requirement already satisfied: s3transfer<0.4.0,>=0.3.0 in /opt/anaconda3/lib/python3.7/site-packages (from boto3->bentoml) (0.3.3)\n", "Requirement already satisfied: jmespath<1.0.0,>=0.7.1 in /opt/anaconda3/lib/python3.7/site-packages (from boto3->bentoml) (0.9.5)\n", "Requirement already satisfied: botocore<1.16.0,>=1.15.9 in /opt/anaconda3/lib/python3.7/site-packages (from boto3->bentoml) (1.15.9)\n", "Requirement already satisfied: MarkupSafe>=0.9.2 in /opt/anaconda3/lib/python3.7/site-packages (from Mako->alembic->bentoml) (1.1.1)\n", "Requirement already satisfied: ply<4.0,>=3.4 in /opt/anaconda3/lib/python3.7/site-packages (from thriftpy2>=0.4.0->py-zipkin->bentoml) (3.11)\n", "Requirement already satisfied: docutils<0.16,>=0.10 in /opt/anaconda3/lib/python3.7/site-packages (from botocore<1.16.0,>=1.15.9->boto3->bentoml) (0.15.2)\n", "Requirement already satisfied: numpy in /opt/anaconda3/lib/python3.7/site-packages (1.18.5)\n", "Requirement already satisfied: xgboost in /opt/anaconda3/lib/python3.7/site-packages (0.90)\n", "Requirement already satisfied: sklearn in /opt/anaconda3/lib/python3.7/site-packages (0.0)\n", "Requirement already satisfied: matplotlib in /opt/anaconda3/lib/python3.7/site-packages (3.2.2)\n", "Requirement already satisfied: kaggle in /opt/anaconda3/lib/python3.7/site-packages (1.5.6)\n", "Requirement already satisfied: scipy in /opt/anaconda3/lib/python3.7/site-packages (from xgboost) (1.3.1)\n", "Requirement already satisfied: scikit-learn in /opt/anaconda3/lib/python3.7/site-packages (from sklearn) (0.21.3)\n", "Requirement already satisfied: cycler>=0.10 in /opt/anaconda3/lib/python3.7/site-packages (from matplotlib) (0.10.0)\n", "Requirement already satisfied: python-dateutil>=2.1 in /opt/anaconda3/lib/python3.7/site-packages (from matplotlib) (2.8.0)\n", "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/anaconda3/lib/python3.7/site-packages (from matplotlib) (1.1.0)\n", "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /opt/anaconda3/lib/python3.7/site-packages (from matplotlib) (2.4.7)\n", "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /opt/anaconda3/lib/python3.7/site-packages (from kaggle) (1.24.3)\n", "Requirement already satisfied: requests in /opt/anaconda3/lib/python3.7/site-packages (from kaggle) (2.24.0)\n", "Requirement already satisfied: six>=1.10 in /opt/anaconda3/lib/python3.7/site-packages (from kaggle) (1.15.0)\n", "Requirement already satisfied: python-slugify in /opt/anaconda3/lib/python3.7/site-packages (from kaggle) (4.0.1)\n", "Requirement already satisfied: tqdm in /home/bentoml/.local/lib/python3.7/site-packages (from kaggle) (4.45.0)\n", "Requirement already satisfied: certifi in /opt/anaconda3/lib/python3.7/site-packages (from kaggle) (2020.6.20)\n", "Requirement already satisfied: joblib>=0.11 in /opt/anaconda3/lib/python3.7/site-packages (from scikit-learn->sklearn) (0.13.2)\n", "Requirement already satisfied: setuptools in /opt/anaconda3/lib/python3.7/site-packages (from kiwisolver>=1.0.1->matplotlib) (49.1.0.post20200710)\n", "Requirement already satisfied: idna<3,>=2.5 in /opt/anaconda3/lib/python3.7/site-packages (from requests->kaggle) (2.10)\n", "Requirement already satisfied: chardet<4,>=3.0.2 in /opt/anaconda3/lib/python3.7/site-packages (from requests->kaggle) (3.0.4)\n", "Requirement already satisfied: text-unidecode>=1.3 in /opt/anaconda3/lib/python3.7/site-packages (from python-slugify->kaggle) (1.3)\n" ] } ], "source": [ "!pip install -q bentoml \"numpy>=1.18.5\" \"xgboost==0.90\" \"scikit-learn>=0.23.0\" \"matplotlib>=3.2.2\" \"kaggle==1.5.6\"" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "import xgboost as xgb\n", "import matplotlib.pyplot as pl\n", "from sklearn.model_selection import train_test_split" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Download Data\n", "\n", "This notebook uses data from kaggle [paololol/league-of-legends-ranked-matches](https://www.kaggle.com/paololol/league-of-legends-ranked-matches)\n", "\n", "You can set your Kaggle credential below and download the dataset automatically. The kaggle key can be created by going to the 'Account' tab of your user profile (https://www.kaggle.com//account) and select 'Create API Token'. This will trigger the download of kaggle.json, a file containing your API credentials, and fill it in the cell below.\n", "\n", "Alternativelly, you can download it manually from [here](https://www.kaggle.com/paololol/league-of-legends-ranked-matches) and place unzip'd data in this folder." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%bash\n", "export KAGGLE_USERNAME=\n", "export KAGGLE_KEY=\n", "\n", "if [ ! -f ./league-of-legends-ranked-matches.zip ]; then\n", " kaggle datasets download paololol/league-of-legends-ranked-matches\n", " unzip -n league-of-legends-ranked-matches.zip\n", "fi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load data" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# read in the data\n", "matches = pd.read_csv(\"matches.csv\")\n", "participants = pd.read_csv(\"participants.csv\")\n", "stats1 = pd.read_csv(\"stats1.csv\", low_memory=False)\n", "stats2 = pd.read_csv(\"stats2.csv\", low_memory=False)\n", "stats = pd.concat([stats1,stats2])\n", "\n", "# merge into a single DataFrame\n", "a = pd.merge(participants, matches, left_on=\"matchid\", right_on=\"id\")\n", "allstats_orig = pd.merge(a, stats, left_on=\"matchid\", right_on=\"id\")\n", "allstats = allstats_orig.copy()\n", "\n", "# drop games that lasted less than 10 minutes\n", "allstats = allstats.loc[allstats[\"duration\"] >= 10*60,:]\n", "\n", "# Convert string-based categories to numeric values\n", "cat_cols = [\"role\", \"position\", \"version\", \"platformid\"]\n", "for c in cat_cols:\n", " allstats[c] = allstats[c].astype('category')\n", " allstats[c] = allstats[c].cat.codes\n", "allstats[\"wardsbought\"] = allstats[\"wardsbought\"].astype(np.int32)\n", "\n", "X = allstats.drop([\"win\"], axis=1)\n", "y = allstats[\"win\"]\n", "\n", "# convert all features we want to consider as rates\n", "rate_features = [\n", " \"kills\", \"deaths\", \"assists\", \"killingsprees\", \"doublekills\",\n", " \"triplekills\", \"quadrakills\", \"pentakills\", \"legendarykills\",\n", " \"totdmgdealt\", \"magicdmgdealt\", \"physicaldmgdealt\", \"truedmgdealt\",\n", " \"totdmgtochamp\", \"magicdmgtochamp\", \"physdmgtochamp\", \"truedmgtochamp\",\n", " \"totheal\", \"totunitshealed\", \"dmgtoobj\", \"timecc\", \"totdmgtaken\",\n", " \"magicdmgtaken\" , \"physdmgtaken\", \"truedmgtaken\", \"goldearned\", \"goldspent\",\n", " \"totminionskilled\", \"neutralminionskilled\", \"ownjunglekills\",\n", " \"enemyjunglekills\", \"totcctimedealt\", \"pinksbought\", \"wardsbought\",\n", " \"wardsplaced\", \"wardskilled\"\n", "]\n", "for feature_name in rate_features:\n", " X[feature_name] /= X[\"duration\"] / 60 # per minute rate\n", "\n", "# convert to fraction of game\n", "X[\"longesttimespentliving\"] /= X[\"duration\"]\n", "\n", "# define friendly names for the features\n", "full_names = {\n", " \"kills\": \"Kills per min.\",\n", " \"deaths\": \"Deaths per min.\",\n", " \"assists\": \"Assists per min.\",\n", " \"killingsprees\": \"Killing sprees per min.\",\n", " \"longesttimespentliving\": \"Longest time living as % of game\",\n", " \"doublekills\": \"Double kills per min.\",\n", " \"triplekills\": \"Triple kills per min.\",\n", " \"quadrakills\": \"Quadra kills per min.\",\n", " \"pentakills\": \"Penta kills per min.\",\n", " \"legendarykills\": \"Legendary kills per min.\",\n", " \"totdmgdealt\": \"Total damage dealt per min.\",\n", " \"magicdmgdealt\": \"Magic damage dealt per min.\",\n", " \"physicaldmgdealt\": \"Physical damage dealt per min.\",\n", " \"truedmgdealt\": \"True damage dealt per min.\",\n", " \"totdmgtochamp\": \"Total damage to champions per min.\",\n", " \"magicdmgtochamp\": \"Magic damage to champions per min.\",\n", " \"physdmgtochamp\": \"Physical damage to champions per min.\",\n", " \"truedmgtochamp\": \"True damage to champions per min.\",\n", " \"totheal\": \"Total healing per min.\",\n", " \"totunitshealed\": \"Total units healed per min.\",\n", " \"dmgtoobj\": \"Damage to objects per min.\",\n", " \"timecc\": \"Time spent with crown control per min.\",\n", " \"totdmgtaken\": \"Total damage taken per min.\",\n", " \"magicdmgtaken\": \"Magic damage taken per min.\",\n", " \"physdmgtaken\": \"Physical damage taken per min.\",\n", " \"truedmgtaken\": \"True damage taken per min.\",\n", " \"goldearned\": \"Gold earned per min.\",\n", " \"goldspent\": \"Gold spent per min.\",\n", " \"totminionskilled\": \"Total minions killed per min.\",\n", " \"neutralminionskilled\": \"Neutral minions killed per min.\",\n", " \"ownjunglekills\": \"Own jungle kills per min.\",\n", " \"enemyjunglekills\": \"Enemy jungle kills per min.\",\n", " \"totcctimedealt\": \"Total crown control time dealt per min.\",\n", " \"pinksbought\": \"Pink wards bought per min.\",\n", " \"wardsbought\": \"Wards bought per min.\",\n", " \"wardsplaced\": \"Wards placed per min.\",\n", " \"turretkills\": \"# of turret kills\",\n", " \"inhibkills\": \"# of inhibitor kills\",\n", " \"dmgtoturrets\": \"Damage to turrets\"\n", "}\n", "feature_names = [full_names.get(n, n) for n in X.columns]\n", "X.columns = feature_names\n", "\n", "# create train/validation split\n", "Xt, Xv, yt, yv = train_test_split(X,y, test_size=0.2, random_state=10)\n", "dt = xgb.DMatrix(Xt, label=yt.values)\n", "dv = xgb.DMatrix(Xv, label=yv.values)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Train the XGBoost model\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[15:31:01] WARNING: /Users/travis/build/dmlc/xgboost/src/learner.cc:516: \n", "Parameters: { silent } might not be used.\n", "\n", " This may not be accurate due to some parameters are only used in language bindings but\n", " passed down to XGBoost core. Or some parameters are not used but slip through this\n", " verification. Please open an issue if you find above cases.\n", "\n", "\n", "[0]\ttrain-logloss:0.54119\tvalid-logloss:0.54137\n", "Multiple eval metrics have been passed: 'valid-logloss' will be used for early stopping.\n", "\n", "Will train until valid-logloss hasn't improved in 5 rounds.\n", "[10]\ttrain-logloss:0.34090\tvalid-logloss:0.34078\n", "[20]\ttrain-logloss:0.29880\tvalid-logloss:0.29892\n", "[30]\ttrain-logloss:0.27532\tvalid-logloss:0.27589\n", "[40]\ttrain-logloss:0.26305\tvalid-logloss:0.26410\n", "[50]\ttrain-logloss:0.25208\tvalid-logloss:0.25362\n", "[60]\ttrain-logloss:0.24394\tvalid-logloss:0.24587\n", "[70]\ttrain-logloss:0.23717\tvalid-logloss:0.23933\n", "[80]\ttrain-logloss:0.23103\tvalid-logloss:0.23352\n", "[90]\ttrain-logloss:0.22614\tvalid-logloss:0.22881\n", "[99]\ttrain-logloss:0.22185\tvalid-logloss:0.22484\n" ] } ], "source": [ "params = {\n", " \"eta\": 0.5,\n", " \"max_depth\": 4,\n", " \"objective\": \"binary:logistic\",\n", " \"silent\": 1,\n", " \"base_score\": np.mean(yt),\n", " \"eval_metric\": \"logloss\"\n", "}\n", "model = xgb.train(params, dt, 100, [(dt, \"train\"),(dv, \"valid\")], early_stopping_rounds=5, verbose_eval=10)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
id_xmatchidplayerchampionidss1ss2rolepositionid_ygameid...Neutral minions killed per min.Own jungle kills per min.Enemy jungle kills per min.Total crown control time dealt per min.champlvlPink wards bought per min.Wards bought per min.Wards placed per min.wardskilledfirstblood
121555515010341509331059411221509333162804935...0.0230860.0230860.0000007.572143180.0692570.00.8310890.2539440
142783517136141723576351114311723573186087472...0.0282620.0282620.00000010.937353160.0000000.00.1978330.0000000
12041181489597149786334414421497863193266242...0.8828170.6936420.18917511.192853180.0630580.00.5675250.1891750
\n", "

3 rows × 71 columns

\n", "
" ], "text/plain": [ " id_x matchid player championid ss1 ss2 role position \\\n", "1215555 1501034 150933 10 59 4 11 2 2 \n", "1427835 1713614 172357 6 35 11 14 3 1 \n", "1204118 1489597 149786 3 34 4 14 4 2 \n", "\n", " id_y gameid ... Neutral minions killed per min. \\\n", "1215555 150933 3162804935 ... 0.023086 \n", "1427835 172357 3186087472 ... 0.028262 \n", "1204118 149786 3193266242 ... 0.882817 \n", "\n", " Own jungle kills per min. Enemy jungle kills per min. \\\n", "1215555 0.023086 0.000000 \n", "1427835 0.028262 0.000000 \n", "1204118 0.693642 0.189175 \n", "\n", " Total crown control time dealt per min. champlvl \\\n", "1215555 7.572143 18 \n", "1427835 10.937353 16 \n", "1204118 11.192853 18 \n", "\n", " Pink wards bought per min. Wards bought per min. \\\n", "1215555 0.069257 0.0 \n", "1427835 0.000000 0.0 \n", "1204118 0.063058 0.0 \n", "\n", " Wards placed per min. wardskilled firstblood \n", "1215555 0.831089 0.253944 0 \n", "1427835 0.197833 0.000000 0 \n", "1204118 0.567525 0.189175 0 \n", "\n", "[3 rows x 71 columns]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Xt[:3]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.35312122, 0.06715239, 0.04428952], dtype=float32)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.predict(xgb.DMatrix(Xt[:3]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create ML service with BentoML" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting lol_win_predictions.py\n" ] } ], "source": [ "%%writefile lol_win_predictions.py\n", "\n", "from bentoml import api, env, BentoService, artifacts\n", "from bentoml.frameworks.xgboost import XgboostModelArtifact\n", "from bentoml.adapters import DataframeInput\n", "\n", "import xgboost as xgb\n", "\n", "@env(pip_packages=['xgboost'])\n", "@artifacts([XgboostModelArtifact('model')])\n", "class LeagueWinPrediction(BentoService):\n", " \n", " @api(input=DataframeInput(), batch=True)\n", " def predict(self, df):\n", " dmatrix = xgb.DMatrix(df)\n", " return self.artifacts.model.predict(dmatrix)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-22 15:36:13,398] WARNING - Using BentoML installed in `editable` model, the local BentoML repository including all code changes will be packaged together with saved bundle created, under the './bundled_pip_dependencies' directory of the saved bundle.\n", "[2020-09-22 15:36:13,853] INFO - Using default docker base image: `None` specified inBentoML config file or env var. User must make sure that the docker base image either has Python 3.7 or conda installed.\n", "[2020-09-22 15:36:13,856] WARNING - pip package requirement xgboost already exist\n", "[2020-09-22 15:36:14,960] INFO - Detected non-PyPI-released BentoML installed, copying local BentoML modulefiles to target saved bundle path..\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "warning: no previously-included files matching '*~' found anywhere in distribution\n", "warning: no previously-included files matching '*.pyo' found anywhere in distribution\n", "warning: no previously-included files matching '.git' found anywhere in distribution\n", "warning: no previously-included files matching '.ipynb_checkpoints' found anywhere in distribution\n", "warning: no previously-included files matching '__pycache__' found anywhere in distribution\n", "no previously-included directories found matching 'e2e_tests'\n", "no previously-included directories found matching 'tests'\n", "no previously-included directories found matching 'benchmark'\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "UPDATING BentoML-0.9.0rc0+3.gcebf2015/bentoml/_version.py\n", "set BentoML-0.9.0rc0+3.gcebf2015/bentoml/_version.py to '0.9.0.pre+3.gcebf2015'\n", "[2020-09-22 15:36:19,116] INFO - BentoService bundle 'LeagueWinPrediction:20200922153614_15BE7D' saved to: /Users/bozhaoyu/bentoml/repository/LeagueWinPrediction/20200922153614_15BE7D\n" ] } ], "source": [ "# 1) import the custom BentoService defined above\n", "from lol_win_predictions import LeagueWinPrediction\n", "\n", "# 2) `pack` it with required artifacts\n", "bento_svc = LeagueWinPrediction()\n", "bento_svc.pack('model', model)\n", "\n", "# 3) save your BentoSerivce\n", "saved_path = bento_svc.save()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## REST API Model Serving\n", "\n", "\n", "To start a REST API model server with the BentoService saved above, use the bentoml serve command:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-22 15:36:38,016] INFO - Getting latest version LeagueWinPrediction:20200922153614_15BE7D\n", "[2020-09-22 15:36:38,017] INFO - Starting BentoML API server in development mode..\n", "[2020-09-22 15:36:38,363] WARNING - Using BentoML installed in `editable` model, the local BentoML repository including all code changes will be packaged together with saved bundle created, under the './bundled_pip_dependencies' directory of the saved bundle.\n", "[2020-09-22 15:36:38,379] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "[2020-09-22 15:36:40,823] INFO - Using default docker base image: `None` specified inBentoML config file or env var. User must make sure that the docker base image either has Python 3.7 or conda installed.\n", "[2020-09-22 15:36:40,825] WARNING - pip package requirement xgboost already exist\n", " * Serving Flask app \"LeagueWinPrediction\" (lazy loading)\n", " * Environment: production\n", "\u001b[31m WARNING: This is a development server. Do not use it in a production deployment.\u001b[0m\n", "\u001b[2m Use a production WSGI server instead.\u001b[0m\n", " * Debug mode: off\n", " * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n", "127.0.0.1 - - [22/Sep/2020 15:37:09] \"\u001b[1m\u001b[31mPOST /predict HTTP/1.1\u001b[0m\" 400 -\n", "WARNING: Logging before flag parsing goes to stderr.\n", "I0922 15:37:09.624686 4628762048 _internal.py:122] 127.0.0.1 - - [22/Sep/2020 15:37:09] \"\u001b[1m\u001b[31mPOST /predict HTTP/1.1\u001b[0m\" 400 -\n", "^C\n" ] } ], "source": [ "!bentoml serve LeagueWinPrediction:latest" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you are running this notebook from Google Colab, you can start the dev server with `--run-with-ngrok` option, to gain acccess to the API endpoint via a public endpoint managed by [ngrok](https://ngrok.com/):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!bentoml serve LeagueWinPrediction:latest --run-with-ngrok" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Make requeset to the REST server\n", "\n", "*After navigate to the location of this notebook, copy and paste the following code to your terminal and run it to make request*\n", "\n", "```bash\n", "curl -i \\\n", "--request POST \\\n", "--header \"Content-Type: text/csv\" \\\n", "-d @test.csv \\\n", "localhost:5000/predict\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Containerize model server with Docker\n", "\n", "\n", "One common way of distributing this model API server for production deployment, is via Docker containers. And BentoML provides a convenient way to do that.\n", "\n", "Note that docker is **not available in Google Colab**. You will need to download and run this notebook locally to try out this containerization with docker feature.\n", "\n", "If you already have docker configured, simply run the follow command to product a docker container serving the IrisClassifier prediction service created above:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-22 15:38:10,877] INFO - Getting latest version LeagueWinPrediction:20200922153614_15BE7D\n", "\u001b[39mFound Bento: /Users/bozhaoyu/bentoml/repository/LeagueWinPrediction/20200922153614_15BE7D\u001b[0m\n", "[2020-09-22 15:38:10,922] WARNING - Using BentoML installed in `editable` model, the local BentoML repository including all code changes will be packaged together with saved bundle created, under the './bundled_pip_dependencies' directory of the saved bundle.\n", "[2020-09-22 15:38:10,939] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "\u001b[39mTag not specified, using tag parsed from BentoService: 'leaguewinprediction:20200922153614_15BE7D'\u001b[0m\n", "Building Docker image leaguewinprediction:20200922153614_15BE7D from LeagueWinPrediction:latest \n", "-we in here\n", "processed docker file\n", "(None, None)\n", "root in create archive /Users/bozhaoyu/bentoml/repository/LeagueWinPrediction/20200922153614_15BE7D ['Dockerfile', 'LeagueWinPrediction', 'LeagueWinPrediction/__init__.py', 'LeagueWinPrediction/__pycache__', 'LeagueWinPrediction/__pycache__/lol_win_predictions.cpython-37.pyc', 'LeagueWinPrediction/artifacts', 'LeagueWinPrediction/artifacts/__init__.py', 'LeagueWinPrediction/artifacts/model.model', 'LeagueWinPrediction/bentoml.yml', 'LeagueWinPrediction/lol_win_predictions.py', 'MANIFEST.in', 'README.md', 'bentoml-init.sh', 'bentoml.yml', 'bundled_pip_dependencies', 'bundled_pip_dependencies/BentoML-0.9.0rc0+3.gcebf2015.tar.gz', 'docker-entrypoint.sh', 'environment.yml', 'python_version', 'requirements.txt', 'setup.py']\n", "about to build\n", "about to upgrade params\n", "check each param and update\n", "if use config proxy\n", "if buildargs\n", "if shmsize\n", "if labels\n", "if cache from\n", "if target\n", "if network_mode\n", "if squash\n", "if extra hosts is not None\n", "if platform is not None\n", "if isolcation is not None\n", "if context is not None\n", "setting auth {'Content-Type': 'application/tar'}\n", "\b\\docker build {'t': 'leaguewinprediction:20200922153614_15BE7D', 'remote': None, 'q': False, 'nocache': False, 'rm': False, 'forcerm': False, 'pull': False, 'dockerfile': (None, None)}\n", "\b|docker response \n", "context closes\n", "print responses\n", "\u001b[39mStep 1/15 : FROM bentoml/model-server:0.9.0.pre\u001b[0m\n", "\u001b[39m ---> a25066aa8b0e\u001b[0m\n", "\u001b[39mStep 2/15 : ARG EXTRA_PIP_INSTALL_ARGS=\u001b[0m\n", "\u001b[39m ---> Using cache\u001b[0m\n", "\u001b[39m ---> fc6e47d06522\u001b[0m\n", "\u001b[39mStep 3/15 : ENV EXTRA_PIP_INSTALL_ARGS $EXTRA_PIP_INSTALL_ARGS\u001b[0m\n", "\u001b[39m ---> Using cache\u001b[0m\n", "\u001b[39m ---> db8172e98571\u001b[0m\n", "\u001b[39mStep 4/15 : COPY environment.yml requirements.txt setup.sh* bentoml-init.sh python_version* /bento/\u001b[0m\n", "\b\\\u001b[39m ---> 0d7364cd570c\u001b[0m\n", "\u001b[39mStep 5/15 : WORKDIR /bento\u001b[0m\n", "\u001b[39m ---> Running in f8b49e247b4b\u001b[0m\n", "\b-\u001b[39m ---> c7e443ac083a\u001b[0m\n", "\u001b[39mStep 6/15 : RUN chmod +x /bento/bentoml-init.sh\u001b[0m\n", "\b/\u001b[39m ---> Running in 7a86e0af06b7\u001b[0m\n", "\b\\\u001b[39m ---> a555c7d51ca7\u001b[0m\n", "\u001b[39mStep 7/15 : RUN if [ -f /bento/bentoml-init.sh ]; then bash -c /bento/bentoml-init.sh; fi\u001b[0m\n", "\u001b[39m ---> Running in ccd57d484032\u001b[0m\n", "\b|\u001b[39m\u001b[91m+++ dirname /bento/bentoml-init.sh\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m++ cd /bento\n", "++ pwd -P\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m+ SAVED_BUNDLE_PATH=/bento\n", "+ cd /bento\n", "+ '[' -f ./setup.sh ']'\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m+ '[' -f ./python_version ']'\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m++ cat ./python_version\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m+ PY_VERSION_SAVED=3.7.3\n", "+ DESIRED_PY_VERSION=3.7\n", "++ python -c 'import sys; print(f\"{sys.version_info.major}.{sys.version_info.minor}\")'\n", "\u001b[0m\u001b[0m\n", "\b-\u001b[39mPython Version in docker base image 3.7 matches requirement python=3.7. Skipping.\u001b[0m\n", "\u001b[39m\u001b[91m+ CURRENT_PY_VERSION=3.7\n", "+ [[ 3.7 == \\3\\.\\7 ]]\n", "+ echo 'Python Version in docker base image 3.7 matches requirement python=3.7. Skipping.'\n", "+ command -v conda\n", "\u001b[0m\u001b[0m\n", "\u001b[39mUpdating conda base environment with environment.yml\u001b[0m\n", "\u001b[39m\u001b[91m+ echo 'Updating conda base environment with environment.yml'\n", "+ conda env update -n base -f ./environment.yml\n", "\u001b[0m\u001b[0m\n", "\b|\u001b[39mCollecting package metadata (repodata.json): ...working... \u001b[0m\n", "\b-\u001b[39mdone\u001b[0m\n", "\u001b[39mSolving environment: \u001b[0m\n", "\u001b[39m...working... \u001b[0m\n", "\b\\\u001b[39mdone\u001b[0m\n", "\b-\u001b[39m\n", "Downloading and Extracting Packages\n", "openssl-1.1.1h | 2.1 MB | | 0% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | | 1% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ####2 | 43% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########3 | 84% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "certifi-2020.6.20 | 151 KB | | 0% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "python-3.7.9 | 45.3 MB | | 0% \u001b[0m\n", "python-3.7.9 | 45.3 MB | | 0% \u001b[0m\n", "python-3.7.9 | 45.3 MB | 1 | 2% \u001b[0m\n", "python-3.7.9 | 45.3 MB | 3 | 3% \u001b[0m\n", "python-3.7.9 | 45.3 MB | 6 | 6% \u001b[0m\n", "python-3.7.9 | 45.3 MB | # | 11% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #5 | 15% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #9 | 19% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ##2 | 23% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ##6 | 26% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ### | 30% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ###5 | 35% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #### | 40% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ####5 | 45% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ##### | 50% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #####5 | 55% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ###### | 61% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ######6 | 66% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #######1 | 71% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #######5 | 76% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ########1 | 81% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ########6 | 86% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ######### | 91% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #########5 | 95% \u001b[0m\n", "python-3.7.9 | 45.3 MB | #########9 | 100% \u001b[0m\n", "python-3.7.9 | 45.3 MB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "python_abi-3.7 | 4 KB | | 0% \u001b[0m\n", "python_abi-3.7 | 4 KB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "readline-8.0 | 281 KB | | 0% \u001b[0m\n", "readline-8.0 | 281 KB | ######8 | 68% \u001b[0m\n", "readline-8.0 | 281 KB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "pip-20.2.3 | 1.1 MB | | 0% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ##6 | 26% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ########## | 100% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "ca-certificates-2020 | 145 KB | | 0% \u001b[0m\n", "ca-certificates-2020 | 145 KB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "Preparing transaction: ...working... \u001b[0m\n", "\b-\u001b[39mdone\u001b[0m\n", "\u001b[39mVerifying transaction: ...working... \u001b[0m\n", "\b\\\u001b[39mdone\u001b[0m\n", "\u001b[39mExecuting transaction: ...working... \u001b[0m\n", "\b-\u001b[39mdone\u001b[0m\n", "\b\\\u001b[39m#\n", "# To activate this environment, use\n", "#\n", "# $ conda activate base\n", "#\n", "# To deactivate an active environment, use\n", "#\n", "# $ conda deactivate\u001b[0m\n", "\b|\u001b[39m\u001b[91m+ pip install -r ./requirements.txt --no-cache-dir\n", "\u001b[0m\u001b[0m\n", "\b-\u001b[39mRequirement already satisfied: bentoml==0.9.0.pre in /opt/conda/lib/python3.7/site-packages (from -r ./requirements.txt (line 1)) (0.9.0rc0)\u001b[0m\n", "\b-\u001b[39mCollecting xgboost==1.2.0\u001b[0m\n", "\b/\u001b[39m Downloading xgboost-1.2.0-py3-none-manylinux2010_x86_64.whl (148.9 MB)\u001b[0m\n", "\b|\u001b[39mCollecting pandas==0.24.2\u001b[0m\n", "\u001b[39m Downloading pandas-0.24.2-cp37-cp37m-manylinux1_x86_64.whl (10.1 MB)\u001b[0m\n", "\b-\u001b[39mRequirement already satisfied: certifi in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2020.6.20)\u001b[0m\n", "\u001b[39mRequirement already satisfied: flask in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: tabulate in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.8.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: py-zipkin in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.20.0)\u001b[0m\n", "\b/\u001b[39mRequirement already satisfied: multidict in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (4.7.6)\u001b[0m\n", "\u001b[39mRequirement already satisfied: cerberus in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.3.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: protobuf>=3.6.0 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.13.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: click>=7.0 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (7.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: alembic in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: ruamel.yaml>=0.15.0 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.15.87)\u001b[0m\n", "\u001b[39mRequirement already satisfied: humanfriendly in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (8.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-dateutil<3.0.0,>=2.7.3 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.8.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: requests in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.24.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: boto3 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.15.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: prometheus-client in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.8.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: sqlalchemy>=1.3.0 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.3.19)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-json-logger in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.1.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied: gunicorn in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: numpy in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.19.2)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied: grpcio<=1.27.2 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.27.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: docker in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (4.3.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: packaging in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: psutil in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (5.7.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: sqlalchemy-utils<0.36.8 in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.36.7)\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied: configparser in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (5.0.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: aiohttp in /opt/conda/lib/python3.7/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.6.2)\u001b[0m\n", "\b|\u001b[39mCollecting scipy\u001b[0m\n", "\b\u001b[39m Downloading scipy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl (25.9 MB)\u001b[0m\n", "/\u001b[39mCollecting pytz>=2011k\u001b[0m\n", "\u001b[39m Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied: itsdangerous>=0.24 in /opt/conda/lib/python3.7/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Werkzeug>=0.15 in /opt/conda/lib/python3.7/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Jinja2>=2.10.1 in /opt/conda/lib/python3.7/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.11.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: thriftpy2>=0.4.0 in /opt/conda/lib/python3.7/site-packages (from py-zipkin->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.4.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied: six in /opt/conda/lib/python3.7/site-packages (from py-zipkin->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.15.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: setuptools in /opt/conda/lib/python3.7/site-packages (from cerberus->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (49.6.0.post20200814)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Mako in /opt/conda/lib/python3.7/site-packages (from alembic->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-editor>=0.3 in /opt/conda/lib/python3.7/site-packages (from alembic->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: chardet<4,>=3.0.2 in /opt/conda/lib/python3.7/site-packages (from requests->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: idna<3,>=2.5 in /opt/conda/lib/python3.7/site-packages (from requests->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /opt/conda/lib/python3.7/site-packages (from requests->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.25.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied: botocore<1.19.0,>=1.18.2 in /opt/conda/lib/python3.7/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.18.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: s3transfer<0.4.0,>=0.3.0 in /opt/conda/lib/python3.7/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.3.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: jmespath<1.0.0,>=0.7.1 in /opt/conda/lib/python3.7/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.10.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: websocket-client>=0.32.0 in /opt/conda/lib/python3.7/site-packages (from docker->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.57.0)\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied: pyparsing>=2.0.2 in /opt/conda/lib/python3.7/site-packages (from packaging->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.4.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.5.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: async-timeout<4.0,>=3.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.2.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: MarkupSafe>=0.23 in /opt/conda/lib/python3.7/site-packages (from Jinja2>=2.10.1->flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: ply<4.0,>=3.4 in /opt/conda/lib/python3.7/site-packages (from thriftpy2>=0.4.0->py-zipkin->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied: typing-extensions>=3.7.4; python_version < \"3.8\" in /opt/conda/lib/python3.7/site-packages (from yarl<2.0,>=1.0->aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.7.4.3)\u001b[0m\n", "\b-\u001b[39mInstalling collected packages: scipy, xgboost, pytz, pandas\u001b[0m\n", "\b/\u001b[39mSuccessfully installed pandas-0.24.2 pytz-2020.1 scipy-1.5.2 xgboost-1.2.0\u001b[0m\n", "\b-\u001b[39m ---> cf3711f3c835\u001b[0m\n", "\u001b[39mStep 8/15 : COPY . /bento\u001b[0m\n", "\b|\u001b[39m ---> 3c517e745ea8\u001b[0m\n", "\u001b[39mStep 9/15 : RUN if [ -d /bento/bundled_pip_dependencies ]; then pip install -U bundled_pip_dependencies/* ;fi\u001b[0m\n", "\b\\\u001b[39m ---> Running in 3a7dd6434563\u001b[0m\n", "\b|\u001b[39mProcessing ./bundled_pip_dependencies/BentoML-0.9.0rc0+3.gcebf2015.tar.gz\u001b[0m\n", "\b|\u001b[39m Installing build dependencies: started\u001b[0m\n", "\b|\u001b[39m Installing build dependencies: finished with status 'done'\u001b[0m\n", "\u001b[39m Getting requirements to build wheel: started\u001b[0m\n", "\b\\\u001b[39m Getting requirements to build wheel: finished with status 'done'\u001b[0m\n", "\u001b[39m Preparing wheel metadata: started\u001b[0m\n", "\b/\u001b[39m Preparing wheel metadata: finished with status 'done'\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied, skipping upgrade: prometheus-client in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.8.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: aiohttp in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (3.6.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: docker in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (4.3.1)\u001b[0m\n", "\b-\u001b[39mRequirement already satisfied, skipping upgrade: py-zipkin in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.20.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: packaging in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (20.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: boto3 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.15.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: flask in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: requests in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (2.24.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: numpy in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.19.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: certifi in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (2020.6.20)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: ruamel.yaml>=0.15.0 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.15.87)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-json-logger in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.1.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: multidict in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (4.7.6)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: sqlalchemy>=1.3.0 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.3.19)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: click>=7.0 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (7.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.7.3 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (2.8.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: humanfriendly in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (8.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: protobuf>=3.6.0 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (3.13.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: alembic in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: tabulate in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.8.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: cerberus in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.3.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: grpcio<=1.27.2 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (1.27.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: sqlalchemy-utils<0.36.8 in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (0.36.7)\u001b[0m\n", "\b/\u001b[39mRequirement already satisfied, skipping upgrade: gunicorn in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (20.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: psutil in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (5.7.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: configparser in /opt/conda/lib/python3.7/site-packages (from BentoML==0.9.0rc0+3.gcebf2015) (5.0.0)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied, skipping upgrade: yarl<2.0,>=1.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->BentoML==0.9.0rc0+3.gcebf2015) (1.5.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: async-timeout<4.0,>=3.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->BentoML==0.9.0rc0+3.gcebf2015) (3.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: chardet<4.0,>=2.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->BentoML==0.9.0rc0+3.gcebf2015) (3.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: attrs>=17.3.0 in /opt/conda/lib/python3.7/site-packages (from aiohttp->BentoML==0.9.0rc0+3.gcebf2015) (20.2.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: websocket-client>=0.32.0 in /opt/conda/lib/python3.7/site-packages (from docker->BentoML==0.9.0rc0+3.gcebf2015) (0.57.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: six>=1.4.0 in /opt/conda/lib/python3.7/site-packages (from docker->BentoML==0.9.0rc0+3.gcebf2015) (1.15.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: thriftpy2>=0.4.0 in /opt/conda/lib/python3.7/site-packages (from py-zipkin->BentoML==0.9.0rc0+3.gcebf2015) (0.4.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: pyparsing>=2.0.2 in /opt/conda/lib/python3.7/site-packages (from packaging->BentoML==0.9.0rc0+3.gcebf2015) (2.4.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: s3transfer<0.4.0,>=0.3.0 in /opt/conda/lib/python3.7/site-packages (from boto3->BentoML==0.9.0rc0+3.gcebf2015) (0.3.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /opt/conda/lib/python3.7/site-packages (from boto3->BentoML==0.9.0rc0+3.gcebf2015) (0.10.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: botocore<1.19.0,>=1.18.2 in /opt/conda/lib/python3.7/site-packages (from boto3->BentoML==0.9.0rc0+3.gcebf2015) (1.18.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: itsdangerous>=0.24 in /opt/conda/lib/python3.7/site-packages (from flask->BentoML==0.9.0rc0+3.gcebf2015) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: Werkzeug>=0.15 in /opt/conda/lib/python3.7/site-packages (from flask->BentoML==0.9.0rc0+3.gcebf2015) (1.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: Jinja2>=2.10.1 in /opt/conda/lib/python3.7/site-packages (from flask->BentoML==0.9.0rc0+3.gcebf2015) (2.11.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /opt/conda/lib/python3.7/site-packages (from requests->BentoML==0.9.0rc0+3.gcebf2015) (1.25.10)\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied, skipping upgrade: idna<3,>=2.5 in /opt/conda/lib/python3.7/site-packages (from requests->BentoML==0.9.0rc0+3.gcebf2015) (2.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: setuptools in /opt/conda/lib/python3.7/site-packages (from protobuf>=3.6.0->BentoML==0.9.0rc0+3.gcebf2015) (49.6.0.post20200814)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-editor>=0.3 in /opt/conda/lib/python3.7/site-packages (from alembic->BentoML==0.9.0rc0+3.gcebf2015) (1.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: Mako in /opt/conda/lib/python3.7/site-packages (from alembic->BentoML==0.9.0rc0+3.gcebf2015) (1.1.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: typing-extensions>=3.7.4; python_version < \"3.8\" in /opt/conda/lib/python3.7/site-packages (from yarl<2.0,>=1.0->aiohttp->BentoML==0.9.0rc0+3.gcebf2015) (3.7.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: ply<4.0,>=3.4 in /opt/conda/lib/python3.7/site-packages (from thriftpy2>=0.4.0->py-zipkin->BentoML==0.9.0rc0+3.gcebf2015) (3.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: MarkupSafe>=0.23 in /opt/conda/lib/python3.7/site-packages (from Jinja2>=2.10.1->flask->BentoML==0.9.0rc0+3.gcebf2015) (1.1.1)\u001b[0m\n", "\u001b[39mBuilding wheels for collected packages: BentoML\u001b[0m\n", "\u001b[39m Building wheel for BentoML (PEP 517): started\u001b[0m\n", "\b-\u001b[39m Building wheel for BentoML (PEP 517): finished with status 'done'\u001b[0m\n", "\u001b[39m Created wheel for BentoML: filename=BentoML-0.9.0rc0+3.gcebf2015-py3-none-any.whl size=3064091 sha256=8e787b2d7d257f7106558876f09d73902ba33b332788f147eefffacab48ccf04\n", " Stored in directory: /root/.cache/pip/wheels/a0/45/41/62152db705af4ff47e7a3d6abf6247986eef4aa1b94a58d3b9\u001b[0m\n", "\u001b[39mSuccessfully built BentoML\u001b[0m\n", "\b-\u001b[39mInstalling collected packages: BentoML\n", " Attempting uninstall: BentoML\u001b[0m\n", "\u001b[39m Found existing installation: BentoML 0.9.0rc0\u001b[0m\n", "\b|\u001b[39m Uninstalling BentoML-0.9.0rc0:\u001b[0m\n", "\b/\u001b[39m Successfully uninstalled BentoML-0.9.0rc0\u001b[0m\n", "\b|\u001b[39mSuccessfully installed BentoML-0.9.0rc0+3.gcebf2015\u001b[0m\n", "\b\\\u001b[39m ---> e42b40e1aa88\u001b[0m\n", "\u001b[39mStep 10/15 : ENV PORT 5000\u001b[0m\n", "\b-\u001b[39m ---> Running in 5f759f6f786b\u001b[0m\n", "\b/\u001b[39m ---> 000eb066d01b\u001b[0m\n", "\u001b[39mStep 11/15 : EXPOSE $PORT\u001b[0m\n", "\u001b[39m ---> Running in e1f3cbec65d9\u001b[0m\n", "\b|\u001b[39m ---> be9e430ba73f\u001b[0m\n", "\u001b[39mStep 12/15 : COPY docker-entrypoint.sh /usr/local/bin/\u001b[0m\n", "\b-\u001b[39m ---> 286540998c4c\u001b[0m\n", "\u001b[39mStep 13/15 : RUN chmod +x /usr/local/bin/docker-entrypoint.sh\u001b[0m\n", "\u001b[39m ---> Running in 5af2837f2622\u001b[0m\n", "\b|\u001b[39m ---> 80d32914bfce\u001b[0m\n", "\u001b[39mStep 14/15 : ENTRYPOINT [ \"docker-entrypoint.sh\" ]\u001b[0m\n", "\b\\\u001b[39m ---> Running in 22ccfd449e4c\u001b[0m\n", "\b-\u001b[39m ---> 83b5dbe3de6f\u001b[0m\n", "\u001b[39mStep 15/15 : CMD [\"bentoml\", \"serve-gunicorn\", \"/bento\"]\u001b[0m\n", "\u001b[39m ---> Running in 81b057cf8222\u001b[0m\n", "\b/\u001b[39m ---> aba92d537770\u001b[0m\n", "\u001b[39mSuccessfully built aba92d537770\u001b[0m\n", "\u001b[39mSuccessfully tagged leaguewinprediction:20200922153614_15BE7D\u001b[0m\n", "\u001b[32mFinished building leaguewinprediction:20200922153614_15BE7D from LeagueWinPrediction:latest\u001b[0m\n" ] } ], "source": [ "!bentoml containerize LeagueWinPrediction:latest" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-22 22:40:28,656] INFO - Starting BentoML API server in production mode..\n", "[2020-09-22 22:40:29,076] INFO - get_gunicorn_num_of_workers: 3, calculated by cpu count\n", "[2020-09-22 22:40:29 +0000] [1] [INFO] Starting gunicorn 20.0.4\n", "[2020-09-22 22:40:29 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)\n", "[2020-09-22 22:40:29 +0000] [1] [INFO] Using worker: sync\n", "[2020-09-22 22:40:29 +0000] [12] [INFO] Booting worker with pid: 12\n", "[2020-09-22 22:40:29 +0000] [13] [INFO] Booting worker with pid: 13\n", "[2020-09-22 22:40:29 +0000] [14] [INFO] Booting worker with pid: 14\n", "[2020-09-22 22:40:29,370] WARNING - Using BentoML not from official PyPI release. In order to find the same version of BentoML when deploying your BentoService, you must set the 'core/bentoml_deploy_version' config to a http/git location of your BentoML fork, e.g.: 'bentoml_deploy_version = git+https://github.com/{username}/bentoml.git@{branch}'\n", "[2020-09-22 22:40:29,370] WARNING - Using BentoML not from official PyPI release. In order to find the same version of BentoML when deploying your BentoService, you must set the 'core/bentoml_deploy_version' config to a http/git location of your BentoML fork, e.g.: 'bentoml_deploy_version = git+https://github.com/{username}/bentoml.git@{branch}'\n", "[2020-09-22 22:40:29,390] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "[2020-09-22 22:40:29,390] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.7.3, but current environment version is 3.7.9.\n", "[2020-09-22 22:40:29,391] WARNING - Using BentoML not from official PyPI release. In order to find the same version of BentoML when deploying your BentoService, you must set the 'core/bentoml_deploy_version' config to a http/git location of your BentoML fork, e.g.: 'bentoml_deploy_version = git+https://github.com/{username}/bentoml.git@{branch}'\n", "[2020-09-22 22:40:29,391] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "[2020-09-22 22:40:29,393] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.7.3, but current environment version is 3.7.9.\n", "[2020-09-22 22:40:29,414] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "[2020-09-22 22:40:29,414] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.7.3, but current environment version is 3.7.9.\n", "[2020-09-22 22:40:30,144] WARNING - pip package requirement xgboost already exist\n", "[2020-09-22 22:40:30,145] WARNING - pip package requirement xgboost already exist\n", "[2020-09-22 22:40:30,146] WARNING - pip package requirement xgboost already exist\n", "^C\n", "[2020-09-22 22:40:38 +0000] [1] [INFO] Handling signal: int\n", "[2020-09-22 22:40:38 +0000] [14] [INFO] Worker exiting (pid: 14)\n", "[2020-09-22 22:40:38 +0000] [13] [INFO] Worker exiting (pid: 13)\n", "[2020-09-22 22:40:38 +0000] [12] [INFO] Worker exiting (pid: 12)\n" ] } ], "source": [ "!docker run --rm -p 5000:5000 leaguewinprediction:20200922153614_15BE7D" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load saved BentoService\n", "\n", "bentoml.load is the API for loading a BentoML packaged model in python: " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-22 15:40:44,389] WARNING - Saved BentoService bundle version mismatch: loading BentoService bundle create with BentoML version 0.9.0.pre, but loading from BentoML version 0.9.0.pre+3.gcebf2015\n", "[2020-09-22 15:40:44,391] WARNING - Module `lol_win_predictions` already loaded, using existing imported module.\n", "[2020-09-22 15:40:44,396] WARNING - pip package requirement pandas already exist\n", "[2020-09-22 15:40:44,397] WARNING - pip package requirement xgboost already exist\n", "[0.35312122 0.06715239 0.04428952]\n" ] } ], "source": [ "from bentoml import load\n", "\n", "svc = load(saved_path)\n", "\n", "print(svc.predict(Xt[:3]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Launch inference job from CLI\n", "\n", "BentoML cli supports loading and running a packaged model from CLI. With the DataframeInput adapter, the CLI command supports reading input Dataframe data from CLI argument or local csv or json files:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Xt[:3].to_csv('test.csv')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!bentoml run LeagueWinPrediction:latest predict --input-file test.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Deployment Options\n", "\n", "If you are at a small team with limited engineering or DevOps resources, try out automated deployment with BentoML CLI, currently supporting AWS Lambda, AWS SageMaker, and Azure Functions:\n", "- [AWS Lambda Deployment Guide](https://docs.bentoml.org/en/latest/deployment/aws_lambda.html)\n", "- [AWS SageMaker Deployment Guide](https://docs.bentoml.org/en/latest/deployment/aws_sagemaker.html)\n", "- [Azure Functions Deployment Guide](https://docs.bentoml.org/en/latest/deployment/azure_functions.html)\n", "\n", "If the cloud platform you are working with is not on the list above, try out these step-by-step guide on manually deploying BentoML packaged model to cloud platforms:\n", "- [AWS ECS Deployment](https://docs.bentoml.org/en/latest/deployment/aws_ecs.html)\n", "- [Google Cloud Run Deployment](https://docs.bentoml.org/en/latest/deployment/google_cloud_run.html)\n", "- [Azure container instance Deployment](https://docs.bentoml.org/en/latest/deployment/azure_container_instance.html)\n", "- [Heroku Deployment](https://docs.bentoml.org/en/latest/deployment/heroku.html)\n", "\n", "Lastly, if you have a DevOps or ML Engineering team who's operating a Kubernetes or OpenShift cluster, use the following guides as references for implementating your deployment strategy:\n", "- [Kubernetes Deployment](https://docs.bentoml.org/en/latest/deployment/kubernetes.html)\n", "- [Knative Deployment](https://docs.bentoml.org/en/latest/deployment/knative.html)\n", "- [Kubeflow Deployment](https://docs.bentoml.org/en/latest/deployment/kubeflow.html)\n", "- [KFServing Deployment](https://docs.bentoml.org/en/latest/deployment/kfserving.html)\n", "- [Clipper.ai Deployment Guide](https://docs.bentoml.org/en/latest/deployment/clipper.html)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.6" } }, "nbformat": 4, "nbformat_minor": 4 }