{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# BentoML Example: Keras Fashion MNIST\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 notebook demonstrates how to use BentoML to turn a Keras model into a docker image containing a REST API server serving this model, how to use your ML service built with BentoML as a CLI tool, and how to distribute it a pypi package.\n", "\n", "![Impression](https://www.google-analytics.com/collect?v=1&tid=UA-112879361-3&cid=555&t=event&ec=keras&ea=keras-fashion-mnist&dt=keras-fashion-mnist)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: tensorflow==1.14.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (1.14.0)\n", "Requirement already satisfied: numpy in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (1.16.6)\n", "Requirement already satisfied: matplotlib in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (3.1.3)\n", "Requirement already satisfied: keras==2.3.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (2.3.1)\n", "Requirement already satisfied: pillow in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (7.2.0)\n", "Requirement already satisfied: grpcio>=1.8.6 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.27.2)\n", "Requirement already satisfied: six>=1.10.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.14.0)\n", "Requirement already satisfied: termcolor>=1.1.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.1.0)\n", "Requirement already satisfied: tensorflow-estimator<1.15.0rc0,>=1.14.0rc0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.14.0)\n", "Requirement already satisfied: absl-py>=0.7.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (0.9.0)\n", "Requirement already satisfied: wrapt>=1.11.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.12.1)\n", "Requirement already satisfied: wheel>=0.26 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (0.34.2)\n", "Requirement already satisfied: tensorboard<1.15.0,>=1.14.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.14.0)\n", "Requirement already satisfied: keras-applications>=1.0.6 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.0.8)\n", "Requirement already satisfied: keras-preprocessing>=1.0.5 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (1.1.0)\n", "Requirement already satisfied: google-pasta>=0.1.6 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (0.2.0)\n", "Requirement already satisfied: protobuf>=3.6.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (3.11.4)\n", "Requirement already satisfied: gast>=0.2.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (0.3.3)\n", "Requirement already satisfied: astor>=0.6.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorflow==1.14.0) (0.8.0)\n", "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from matplotlib) (2.4.7)\n", "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from matplotlib) (1.2.0)\n", "Requirement already satisfied: cycler>=0.10 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from matplotlib) (0.10.0)\n", "Requirement already satisfied: python-dateutil>=2.1 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from matplotlib) (2.8.0)\n", "Requirement already satisfied: pyyaml in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from keras==2.3.1) (5.3.1)\n", "Requirement already satisfied: scipy>=0.14 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from keras==2.3.1) (1.4.1)\n", "Requirement already satisfied: h5py in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from keras==2.3.1) (2.10.0)\n", "Requirement already satisfied: werkzeug>=0.11.15 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorboard<1.15.0,>=1.14.0->tensorflow==1.14.0) (1.0.1)\n", "Requirement already satisfied: setuptools>=41.0.0 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorboard<1.15.0,>=1.14.0->tensorflow==1.14.0) (46.2.0.post20200511)\n", "Requirement already satisfied: markdown>=2.6.8 in /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages (from tensorboard<1.15.0,>=1.14.0->tensorflow==1.14.0) (3.1.1)\n" ] } ], "source": [ "!pip install -q bentoml tensorflow==1.14.0 numpy matplotlib keras==2.3.1 pillow" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tensorflow Version: 1.14.0\n", "Keras Version: 2.3.1\n", "BentoML Version: 0.9.0.pre+7.g8af1c8b\n" ] } ], "source": [ "from __future__ import absolute_import, division, print_function\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "import tensorflow as tf\n", "print(\"Tensorflow Version: %s\" % tf.__version__)\n", "\n", "import keras\n", "print(\"Keras Version: %s\" % keras.__version__)\n", "\n", "import bentoml\n", "print(\"BentoML Version: %s\" % bentoml.__version__)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "yR0EdgrLCaWR" }, "source": [ "## Load Fashion MNIST dataset" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": {}, "colab_type": "code", "id": "7MqDQO0KCaWS" }, "outputs": [], "source": [ "fashion_mnist = keras.datasets.fashion_mnist\n", "\n", "(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each image is mapped to a single label. Since the class names are not included with the dataset, store them here to use later when plotting the images:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "colab": {}, "colab_type": "code", "id": "IjnLH5S2CaWx" }, "outputs": [], "source": [ "class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',\n", " 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "ES6uQoLKCaWr" }, "source": [ "## Preprocess the data\n", "\n", "The data must be preprocessed before training the network. If you inspect the first image in the training set, you will see that the pixel values fall in the range of 0 to 255:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": {}, "colab_type": "code", "id": "m4VEw8Ud9Quh", "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.imshow(train_images[0], cmap=plt.cm.binary)\n", "plt.colorbar()\n", "plt.grid(False)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Wz7l27Lz9S1P" }, "source": [ "We should scale these values to a range of 0 to 1 before feeding to the neural network model. For this, we divide the values by 255. It's important that the *training set* and the *testing set* are preprocessed in the same way:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": {}, "colab_type": "code", "id": "bW5WzIPlCaWv" }, "outputs": [], "source": [ "train_images = train_images / 255.0\n", "test_images = test_images / 255.0" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "Ee638AlnCaWz" }, "source": [ "Display the first 25 images from the training set and display the class name below each image. Verify that the data is in the correct format and we're ready to build and train the network." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": {}, "colab_type": "code", "id": "oZTImqg_CaW1" }, "outputs": [ { "data": { "image/png": "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kPV1079/fy/PmjUraGMTCau2Lax+53nKeo3ZtAGEayKPpo4YXHXeptewYeAMV9zme6sNFed7NYfA22r33I9lG3qdlprArg0O0c4jZ511VnB89tlne9mat9iMaTNqM2m/7zYNBO9zXhsrV64M+vHx+eefn/q5dYk0PUIIIYTIBXroEUIIIUQuqHFG5tpm++23jx4zO+64Y6lPR9QirAq1hevY7MSZY62ZiSNBspqqYoVEOYKPM89aVXvaOQDVN/U2FthEcuqppwZto0aN8nJFRYWXramDTSSxoro8bzyfXbt2DfqxGd2acPIOm5S32mqroI1NWBZe7xzxY82WHHl63333edmawfbdd9+iY9t9xfcLnstu3boF/fbee+/Uc88jnOXaZvhnbIFsZunSpUVft5mbed3wHrUmx6efftrL7IpSn+Tzri2EEEKI3KGHHiGEEELkAj30CCGEECIXlI1Pj2h4ZK2y3qdPHy/36NEjaOOKyjFfHbb7c9bQWPX0tHB4IPQjYR8CDse25NWHx8LX2Pp3DB48uOh7li1bFhyzjwBnY7fzucUWWxSVs4bDK80AcOutt3rZZszlfXXccccFbezfxv4Y7777btCP/YT69u2b6ZyOOuqo1LZjjjkm0xgihDMe25D1sWPHennmzJlethUTdt9996Jjn3vuucEx+/7wuuFqDOWK7uJCCCGEyAV66BFCCCFELnBpBRqLdnbuAwALSnc6oghbJknSZt3dqofmst7QfDYeNJeNi1qfT81lvZE6l9V66BFCCCGEaKjIvCWEEEKIXKCHHiGEEELkgrJ46HHOHeGcS5xz6bUnwv7znXOti7y+qlj/yDjV6h8Z53TnXId192zcOOdaOeemFP4tds69R8ffXsd7BznnHktpu8M5992Utgucc5uY137jnDvJOXd42vvEutF85hvn3NeFuZ7hnHvdOfcL51xZ/GbkGe3L9aNcFvAJAF4EcHx9n0gNOR1A7h96kiT5MEmSXkmS9AJwO4Abq46TJPliPcY9M0mSN+zrzrkNAVwAwBZbOgDASACHA2gwm7Hc0HzmntWFue4BYH8ABwP4X9vJOad8b3WI9uX6Ue8PPc65ZgB2B/A/oIeewhPpaOfcQ865N51z9zqTacw518Q595Rz7qwi417onJvgnJvqnLs88vnXO+cmO+eec861KbzWyzk3vvDe4c65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v387HUox77zzTvL6L39ZX+i1R48e7fa9b775ZvJ6m23W17bbbrvt2u17mUWLFmH58uVF1TJbTUf25bp166K92Wb18ZzNAfxmbX56C3niiSeWhxB6tvV+O2ts1sratWuT12+/HdeOxQcfrC/I7BMrtt9+ff2zjhpztdIVxqZYT3uMzXrpy7feeivaf/rTn6L9/vvvJ+14/PG43GKL9FGBx+Juu+3WZsfZVuT6skUPPf3798fMmZtW+qI1N5spU6Ykr1988cVo//3f//0mHU+Oa69Niz2PGDEi2occUkvR6E1nzJgx7bLftujLWnnvvfW1GvnBsTPhwe4HdHtiZq2tZJulPfuzJRmeRWP61VdfTV7fdttt0V65cmW0/cPREUccEe3cmCuaV/yxt+UDblcYm2I97TE266UvJ0yYEO377lu/Ms/y5cuTdjz++OHIOxcOPvjgaF9wQf3VJcz1ZX382S2EEEII0c7UTXFC/msPAE4++eTCbVtuuWW058yZE212xwGplMISC7v6PK+//nq0ly1LV63g/W299fo11x577LHC/YnUu/PXv/412cbnu3fv3tHOeRfYc7RmzZrCbStWrIh29+7dk3b9+vWD2HRynhP25vz85z9PtnF/9Oy53gvN4xRIva3PPfdctM86K11ZolYPTmfJmkK0BbWGCuy0007J61Wr1i89161bt2h7aerdd9evDfvhD3842gsXLkzaTZ48OdoXX3xxtP18zNTL2JOnRwghhBClQA89QgghhCgFeugRQgghRCno8JieIi3v/PPPT14/++yz0d5rr72SbZtvvnm0H3/88WjvscceSTtOdf/kJz8Z7enTpyftOOZk9erV0eZ0Wf+9zz//fLRvuOGGpN2ZZ54J0Txf/vKXk9d33XVXtHfcccdo+5ierbbaKtqcYeBjQPj64v737ZYuXdqSwy41fszyufTbbr311miPHz8+2j4ri+MROI5g5513TtoNGjQo2vfff3+0R48enbQbOXJks8dXLyUShGgLctfzCy+8EG0/3/F44XIRu+66a+H+OUaWY1iBNCZy0aJF0b7ooouSdpdffnm0ea7wx9eR41QzghBCCCFKgR56hBBCCFEKOjVlnV1cCxYsSLax+8xXRuYUV3bBcUorkKbcTZ06tbBdUXE673LjdOtevXpFm114gOStHPPmzUteF1Xz5KrbAPDa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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(10,10))\n", "for i in range(25):\n", " plt.subplot(5,5,i+1)\n", " plt.xticks([])\n", " plt.yticks([])\n", " plt.grid(False)\n", " plt.imshow(train_images[i], cmap=plt.cm.binary)\n", " plt.xlabel(class_names[train_labels[i]])\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": {}, "colab_type": "code", "id": "9ODch-OFCaW4" }, "outputs": [], "source": [ "# Reshaping the images so that our model can accept it\n", "train_images = train_images.reshape((60000, 28, 28, 1))\n", "test_images = test_images.reshape((10000, 28, 28, 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Build the model" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "WARNING:tensorflow:From /opt/conda/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "Model: \"sequential_1\"\n", "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "conv2d_1 (Conv2D) (None, 28, 28, 64) 320 \n", "_________________________________________________________________\n", "max_pooling2d_1 (MaxPooling2 (None, 14, 14, 64) 0 \n", "_________________________________________________________________\n", "dropout_1 (Dropout) (None, 14, 14, 64) 0 \n", "_________________________________________________________________\n", "conv2d_2 (Conv2D) (None, 14, 14, 32) 8224 \n", "_________________________________________________________________\n", "max_pooling2d_2 (MaxPooling2 (None, 7, 7, 32) 0 \n", "_________________________________________________________________\n", "dropout_2 (Dropout) (None, 7, 7, 32) 0 \n", "_________________________________________________________________\n", "flatten_1 (Flatten) (None, 1568) 0 \n", "_________________________________________________________________\n", "dense_1 (Dense) (None, 256) 401664 \n", "_________________________________________________________________\n", "dropout_3 (Dropout) (None, 256) 0 \n", "_________________________________________________________________\n", "dense_2 (Dense) (None, 10) 2570 \n", "=================================================================\n", "Total params: 412,778\n", "Trainable params: 412,778\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "model = keras.Sequential()\n", "# Must define the input shape in the first layer of the neural network\n", "model.add(keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu', input_shape=(28,28,1))) \n", "model.add(keras.layers.MaxPooling2D(pool_size=2))\n", "model.add(keras.layers.Dropout(0.3))\n", "model.add(keras.layers.Conv2D(filters=32, kernel_size=2, padding='same', activation='relu'))\n", "model.add(keras.layers.MaxPooling2D(pool_size=2))\n", "model.add(keras.layers.Dropout(0.3))\n", "model.add(keras.layers.Flatten())\n", "model.add(keras.layers.Dense(256, activation='relu'))\n", "model.add(keras.layers.Dropout(0.5))\n", "model.add(keras.layers.Dense(10, activation='softmax'))\n", "# Take a look at the model summary\n", "model.summary()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compile the model" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": {}, "colab_type": "code", "id": "Lhan11blCaW7" }, "outputs": [], "source": [ "model.compile(optimizer='adam',\n", " loss='sparse_categorical_crossentropy',\n", " metrics=['accuracy'])" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "qKF6uW-BCaW-" }, "source": [ "## Train the model" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": {}, "colab_type": "code", "id": "xvwvpA64CaW_" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "WARNING:tensorflow:From /opt/conda/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "Epoch 1/5\n", "60000/60000 [==============================] - 6s 101us/step - loss: 0.5853 - accuracy: 0.7847\n", "Epoch 2/5\n", "60000/60000 [==============================] - 5s 86us/step - loss: 0.4095 - accuracy: 0.8508\n", "Epoch 3/5\n", "60000/60000 [==============================] - 5s 86us/step - loss: 0.3620 - accuracy: 0.8662\n", "Epoch 4/5\n", "60000/60000 [==============================] - 5s 86us/step - loss: 0.3354 - accuracy: 0.8784\n", "Epoch 5/5\n", "60000/60000 [==============================] - 5s 85us/step - loss: 0.3190 - accuracy: 0.8843\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.fit(train_images, train_labels, batch_size=64, epochs=5)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "oEw4bZgGCaXB" }, "source": [ "## Evaluate model accuracy" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": {}, "colab_type": "code", "id": "VflXLEeECaXC" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10000/10000 [==============================] - 1s 52us/step\n", "Test accuracy: 0.899399995803833\n" ] } ], "source": [ "test_loss, test_acc = model.evaluate(test_images, test_labels)\n", "\n", "print('Test accuracy:', test_acc)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABC0AAAHUCAYAAAAeKdJ9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOzdeZgcVbk/8O/pnn2fJJN9I3sI+xZAVkH2TQUURBZBBcQrV38u96oUBeJ6VVyuVwUUFEQRXFBAEVlkC6uQAEmAhCRkz0wmM5NZe3l/f5xq0qfemulOMmEqyffzPDx6Tr9dVV2pU6fqVJ13jIiAiIiIiIiIiChuEkO9AUREREREREREUThoQURERERERESxxEELIiIiIiIiIoolDloQERERERERUSxx0IKIiIiIiIiIYomDFkREREREREQUSxy0KJLxzZPGN/sP0bq/Z3xz+VCsm3YtxjdifDNtaz8rsMyLjW+e2P6t2zbGNycY3/xpkJY1OdgPJVvzWRHLvdb45vbB2MYi1sXzBW2zYs8DxbQH45tvGN9cPbhbWNjWnJPy26bxzSjjm4XGN+U7dgtpZ8E+s+Cy2GcSDSLjm98b35w21NuxPYxvzjW+uXWwl7vVJ5KhYnxzPoDPApgFoAPASwBuEE+268RvfPMogNvFk5sHiDkdQId48u+8uhkAbgBwLIBSAMsB3ArgB+JJZju252IAl4knR+RVfwfAs8Y3vxBP+rZ12bTrCI7bfQGMFk96h3hzdgjjm2Ng2+b4AqFfB3BV6LsGwBIAPeLJnjtmC4cezxe7B+ObIwB8G8AcABkACwFcLZ48N6QbNgDjmyYAFwKYllf33wA+DqAJwCYAT4onHxqaLdTEk3XGN48A+ASAHw319tDgYZ/pYJ/JPnOXYXyzOa9YBaAXtp8EgE+KJ3e8+1u1bYKH47PEk78a33wVwBeDj0pg7zW7g/IS8WTfodjGIt0N4Hrjm5niyeLBWuhO8aaF8c1nAdwIe6IdBWAigJ8AOPNd2oTLAfw6b3umAngGwNsA9hZP6gGcA+AgALWDvXLxZA2ARQDOGOxl087H+GYygCMBCHbzY8L45mAA9eLJvNBHRwEYCWBKELPb4Pli12J8Uwfgr7A30cMAjAPgw16YxdnFAO4XT7oBwPjmIgAfBXC8eFID21/+c+g2r193APjkUG8EDR72mVuwz9TYZ+7cxJOa3H8AVgA4Pa9ODVhsy5s/g22AbbgcwO0AIJ5cn/e7rgLweN7vUgMWcfhdgN0O8SQL4C7YhxSDJhY/cCDGN/UArgNwiXjyh7yP/hL8h+BVzm8BODf47C4AXxRPeo1vGmEHHObC/t4nAVwunqw0vrkBtiM71PjmRgC3iifh0ecyAO+FexHjA3hKPPlsriIYSTo/73tnAPgG7AXmSwCuEE8WBp99CfYfciTswMeXxZM/Gt/MBvBTAKXByGFaPGkIFvkogFNhR69o93YhgHmwA2cXAfh97oPgdaxOAJNhL0JeA3C+eLIkvJDg6e2dAC4UTx4JfVYO+ybRuQDKAfwRwH/mbkAiGOObHwXbtgbAp8STfwbLGgt7XB8BYCOAb4knN+WtR7Vd2Lb6AIDyvFH0GeLJ6tB6TwbwWMT2XATgzwAqg///zhPp4Inb47Dteh8ATwf7qDliH30QwHcBnAZgc+izegDfA3AKgCyAXwLwBnjTqsL45ndB/Buw57SXg2XNBvB/APYDsArAf4kn9+at50fBb+0CcBPsAO5M8HyxO5gBAOLJnUG5G8CDuQ+DQfSbYJ8iC4C/w7a/TcHnywD8GLZtTgLwNwAXiSc9weefh32LUQB8JX/FxjenAvgagKkA2gDcIp5cW+R2nwzgF3nlgwH8PXcuEk/WAvh53rouAfAFAOMBbIA9T/ws+OwY2Au578OeHzIA/ls8+WXw+XDY9ncM7M3H30O/4wcAPgCgHrbtXS2ePN7Pdj8De+M2STxZXuRvpXhjn7kF+0z2mbsV45uvAZgOe8ydBuDTxje/hX178Zyg/ncAviSe9BnfXAbgAvHkmOD7JQBSAPYQT5YFUze+A9tXtQH4rnjy/SD2DADXw/a1r8Deb74SfLYSwA9g2/xMAGURm3sytrTtQr+rAvZ64EoA/y/YxlnGN0fD9pVTYd/K/HTurUzjm7UAzs7NUjC++SaAEeLJZcY31QBuAXAC7EsNiwGcJJ60Gt8Mg3154IRgPTcDuF48yQZTq84N1nU+bPv/Gmyb+nGwbYNiZ3jT4jAAFbAdQH++DOBQ2JPXvgAOwZaLrwTsiXES7Bsa3bA7EeLJl2FPxFcFI1dXQZsOICuerMyrOx4DnNiCqSN3Arga9jXY+wH8JRgAAewreEfCXkD5AG43vhkTDGpcDuDpYHsa8ha7MPhtRBfCPg28A8CJxjejQp+fB3tcNQJ4E/ZCymF8cyLsMfrB8MVX4FuwN0v7wb7ePQ7ANQNs01wASwGMAOAB+ENwkkOwnpUAxgI4G8DXjW+OCz6LbLviSSfsyXt13shy+OILAPaGPbHm/7aqYD25ffThvLaXcz6AS2AHDssQcVINbqK+Bftk+JWIdd8GIA27f/aHPZlfFhGXcybsxfIwAL8B8Cfjm1Ljm1LYAdgHg+35NIA7jG9mBt/7Eey5YgqAo2H//S/h+WK38TqAjPHNbcY3JwcD8fkM7AD5WACzAUwAcG0o5lwAJwHYA/am42IAML45CfbYfx9sX3d86HudsMdbA+wF/RXGN2cVud3htjkPwIXGN583vjnI+CYZil8Pe0FZB9s2v298c0De56Nh28E4AJcC+N+8ffG/AHoAjAHwseC/fM/BnmNybe/3wQWfIp6kYc+bbD+7DvaZW7DPZJ+5O3o/7DFUDztAcQ3s2377wB6L7wHwX0Uu65cALhVPaoPvPwa88xbTTbDH9HDYQfs/h9rSh2HbaX14ocFg2wSE2mcRTgNwIID9jW9GwraNbwbb8FMA9wfLLuQy2MHPcbDnpasA5KZL3QE7QDMF9pxzFuybkzlHwT6gHwE7aAHYNjXLDGKOqJ1h0GI4gObgQqI/HwFwnXiyXjzZANv5fBQAxJMW8eQe8aRLPOmA7YyO3or1N8Dm0Ahv05oBvvMhAPeJJ/8QT1IA/gd29PrwYJt+L56sFk+y4snvYEeQDymwHR3BttBuLHjSMwnAXeLJC7ADYOeHwv4gnjwbtJk7YC9u8p0D+4TzFPHk2Yh1GNg3gf5TPNkYtJuvw55s+7MewI3iSSo4phcDONX4ZgLs06Iviic94slLsCO0uZNdv223SFHt8wOwr84/CPtafQnsDVe+X4onrwdPwe6C3kdXA/g8gGPEkzfDKw0uek+GfWLbKZ6shx3ZHmgfvSCe3B2cE74HOxh7aPBfDYBviid94snDwXafF9zYfQj2KVKHeLIMtkMotI94vthFiCftsG1IYC+INhjf3Ju78RJP3gz6mt6gDX0Puo/7YdDnbIS9oMkd7+fCtoVXgpuea0PrflQ8WRD0VfNhb6aK7T+dtime3A57c3Ei7EXe+uCtw9zn94knS8QTEU8eg22/R+YtLwV7rkiJJ/fDPsWdGbSRDwK4JmiLr8DeHOX/jtuDa4G0ePJd2CfhM9E/tp9dBPtMhX1mNLb5XdsT4slfgr6sG7YdXSuebAiOxetQfDtKAdjT+KY2aO8vBvWfAPAT8eQ58SQjnuTeNMyfbvUD8WSlRL+BlTv+wu2zkBvEk03BMs8E8JJ4clfQ390KOwB6cpG/qwnA1OC7z4knncY3k2AHJT4b3EuvAfBDuG13qXhyU/C7c78t9zuKGTApSuynhwBoATAimCPT38DFWNhEmDnLg7rcCPL3YZ8y5Z7K1BrfJKW4hJmt0HkqWmCf6PTH2R6xr8+8DTt6BeObC2Ffx50chNTAjk4NpBY2cRnt3i4C8KBseS3zN0Hd9/Ni1ub9/y7Y4yvf1QB+JZ4s6GcdTbDJjF4wvsnVGQDhJ6P5VoknklfOtcGxAHIXcfmfHRT8/37bbpGi2udFsBeoaQBp45s/BHX5b2sV2kefh70wXIlok2CTIq3J20cJ2Ole/Xnns+CckHuSBgBvi50DmLMcW0a7y6D30bgB1gPwfLFLCZ4QXgwAxjezYKdK3Ah7kT4S9gLiSNh/9wRsu8gXPt5zx91YAC/kfeZMhzC+mQv7xGYv2OOwHHmv1heg2qbY+cV3BE9Kzwr+/7/Fk78b35wM+8R5RvAbqgDkn6NaQtcAuXbbBHstk9/2wr/jc7BPkcbCDv7UYeA+l+1n18E+08U+Mxrb/K4tfJyNwdYfIznvh33j6TvGNy/DDjA+A3uMf8T45j/zYstCyx3oeM8df7XQffhA8pcZPj8Axf+2W2DfaLzb+KYGwK8AfBX2d1XAPjDJxSZg30qL2oac3HmmrYh1F2VneNPiadjXPgd6JXU17E7NmRjUAcDnYJ+ozBVP6mBHiwDboQD2AmYgb8DOPcz/B38I9slOUdsTjMJPALAqGLG6Cfa1m+FiX097pYjtmQ3g5QLbSrsw45tK2CejRxvfrA3mpv0ngH2Nb7bmtcZzAJxl+v9ThM2w06jmiCcNwX/1YpMB9WdccJzn5NrgagDDjG9qQ5+tCv7/QG23UNsEgPkI5vwDgPHNeNh5txfk7aOzAZxifFNoYDDfCQC+EszPjfI27JOpEXn7qE48mTPAMifkbWcCdj5kbh9NCOpycvuoGXb0O7yPcvuP54vdjHiyCPYvVe0VVH0D9jjYJ+jjLsCW/qSQNcg7LmGPrXy/AXAvgAliE07/dCuW7bTNfMHT5d8HMXsFr4/eA/tW4qigX7y/yHVtgH3lPPJ3GN8cCTvn/1wAjcGy2/pbdjB/eRrYfnZ67DMjsc+Mxj5z1xb+d1+D/o+RTthByJzRzoI8eUY8OQN2atJfAfw2+OhtAH7e8d0gnlSJJ3cNsB35y22DHWCI7DcHkL/M8PkBKPK3BW9rXiOezIK9Vz4H9m2Kt2HfbGwMtd386ZtRv2s2gEUyiH+tKfaDFsE/4jWw81fPMr6pCua0nWx88+0g7E7Yk2VTcJK9BkH2VdiRnm4Am4L5gl5oFetg5+j0t/4U7CBF/iuxHoDDjW++Y3wzGgCMb6YZ39xufNMA++rcqcY3xwVPlD4He7J+CkA17D/uhuB7l2DLxWdue8ZHzCc8GjbJEu2+zoJNQLcn7KuZ+8GeFB6HnbNZrNUAjgPwH8Y3V4Y/DJ5e3AQ7p3wkABjfjAvm9PZnZLC8UuObc4Ltul88eRv2uP+G8U2F8c0+sPPRcxmdB2q76wAMLzAX7364bfOjsDkAZmLLPpoB+3rceQMsJ+xV2Lez/tfYxEqO4PW4BwF81/imzvgmYXwz1dgESP050PjmA8FN0dWw54RccrhOAF8I9t8xAE4H8NvgbbC7ANxgfFMbDHp+Fu4+4vliF2Z8M8v45nPBzQWC18fPgz12ANvHbYbt48bBPvEs1l0ALja+2TN4KzHcP9bCPvXtMb45BPq1+oE4bdP45mLjm1OD4zgRvFkxB/b4z73FsQH2Se/JsDdBBQVt5A8Arg2uD/aEfUqc/xvSwbJLjG+ugX3Toj+HAFgmTMK5K2CfqbHPZJ9Jth1dY3wzwtg/z/1VbDlGXgawj/HN3sHA5zv9ovFNpfHN+cY3dcH9YQe2/HnVnwP4lPHNwcY3xvimxvjmdGMTXBYr3D631r2wuS3ONr4pMfbN/omwCbgBm3fivOCzQ5H3VziNb44PrgUSANph+82MePIWbLv7dl7/Pd3YqXcDGfQ2FftBCwAQT74He9L5CuyFx9uwbyr8KQj5GoDnYUeQFwB4MagD7Cu0lbCjr/Ow5R8u5wcAzja+aTW++WE/m/Az5M11EptV+jDY6R2vGt+0wT4leh5Ah9i/JHIBbDKgZtiT6enB3LvXYOfXPQ178twb9i+a5DwMe/Jfa3zTDADGN2NgO90/gXZnF8HOK10hnqzN/QebWPYjZiv+3JF4sgL2IuyLxmZKDvsi7Ktf84xv2mEH7gaaA/4MbCK/Zti8MWeLJy3BZ+fBtpXVsK+beuLJP4LP+m27wRPlOwEsNb7ZZGxG9fDveBFAm7GvsQN2H/0kf/8E++incG9kChKbpfw0ADcFN1FhF8LebL0G+yrf3Rh42tifYefatsKeTz4QPHHug/1TayfD7r+fwGanXxR879OwF2hLATwB+/Q7N1eS54tdXwds0r5njG86YfuxV2AHwwE7p/0A2LcH7oO9gS+KePIAbB/5MGx7fzgUciWA64xvOmBvju5C8X4F+7S2Mii3A/hv2D9Jtwk2c/sV4skTwavw/xEsvxV2cOTerVjXVbCvq6+FfQvll3mf/R32wul12KdYPRj4Fd2PwJ4vaOfHPlP/DvaZ7DPJ9psvw7ah+bDt8RsAENynfR32r18sBvCv0HcvArA8aOeXYksOxWcAXAH7V21aYfucC7Zyu36+Dd95h3iyDrZtfBk2lcFVAE6T4K+JwfbBe8P2wf+FLW+JAHYKyZ9hrzlegR1AyfX558Hm3FgE+xeNfgcgnND4Hca+RfYh5P2FsMFgRPp9U4XyGN88AftnY/49BOv+LoAl4slP3u11E8Wd8c0JAK4UT4r9qwa7NJ4vKC6Mb74OYL14cuNQb0sxgqfkjwHYX4I/CUu0q2Gf6WKfSXFifHMXbA6dvw71tmyr4O2x08WTrXmjrfByOWhBRERERERERHG0U0wPISIiIiIiIqLdDwctiIiIiIiIiCiWOGhBRERERERERLFUdOZkACgz5VKBrfnLLTuPvrHu75KSiFwfyYi6jPun3ks79J9+T7R2bte2xUUHWptFpGmot4O0XbltUmFsm/HEdrl7Y7uML7bN3RvbZnztDG3TlIX/Yi7QMN2912tPV+jvhW4RkyarYjb3lau64RXuslPZpIopCS2rpUfvw7Kl3aoubgZqm1s1aFGBasw1xw3OVsXM8isOc8q9IzMqJlGdUnXZzlKnPO4hPWhRffcz27l1WyHcIgBgkJKtPiR38+/Wx9Su3DapMLbNeGK73L2xXcYX2+bujW0zvnaGtlkybqKqO/Oe553yQy2z9fdCAwu1pfqPVM1bPVnVXTDtWae8qrdRxYwo3eyU71h8sIqZeM4CVRc3A7VNTg8hIiIiIiIioljioAURERERERERxRIHLYiIiIiIiIgolrYqp8WQi8jXYJJuMhJJpwsu5rdvP6XqqhLPOeWV6V4VUxqRLiI86jPq9EoVc9zHz3bKlSe+VXAbTYn+p5GMzrOh8lUMUv4KIiIiIiIi2mLJJeNV3Sfq73XKSegkm6NLNznlcck2FTOzSufCSIl7r9tY0qViyhNu3sWbD7xNxVyHA1TdzoRvWhARERERERFRLHHQgoiIiIiIiIhiiYMWRERERERERBRLO1dOi4h8DcXksOg5/RCnXG6eVTHfadnbKa/trVcxnZkyVTeizP27uDVJnQvjuml/dsrfPPA8FSMvvOqWi/hdAHSeD+a0ICIiIiIiGnR9w3WOwa5sn1N+uXOCilmUGOOUx5W3qphwbgoAWNdb55Q70+UqJiXufeueFatUTHL6FKeceWOpiokzvmlBRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLHHQgoiIiIiIiIhiaedKxBmh6/1znXLq4y0q5uRxTzjlhTrHCQ6qesspf3XFmSqmqXqzqlvXXeuUPzxGJ/lclW50ymf9+lEVc9vyQ52y3N6kYurvmKfqmHiTiIiIaDeUSOq6rE4SGLbkO4epurJ2N7H7sNf0chJp95oz2auvQcv+9lzB9ZuD9tLL7nYvzjOvLi64HKKhMHHGOlXXK+4fUBhe2qliUuK219pEj4ppTtequrCShG6bJXDrKoy+2W3bf6RTrmEiTiIiIiIiIiKi7cdBCyIiIiIiIiKKJQ5aEBEREREREVEsDU1OC2N0XSg3gzlwjgrp/abOKXHIMHfu3KqeBhXzXOskp7yyp1HFXD3qIad8zNg3VMySzSNU3ejKDqe8qHusinmtfYxTnli9UcV8aOILTrntC1UqZsHletkbr5/slEsffF7FEBEREdGuxZTqy3jpdee2J0eNVDEXn/iIqlvf586lr/lAr4qZVbnaKY8s6VAx76vsdsr3dOprbuAtVZMV9znqE+0zVMzzGyY45fan9W+bcP1TTtmURNzqROS2IyrWCaMXqrqneoc55da0vo+rSbptqitbrmIyot8nqEi4B+ymVKWKWddd55SfKZ2mYjpHu8uuURHxxjctiIiIiIiIiCiWOGhBRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLA1NIs5Q0s0oG67VWXJmV7epuuea3SSbfZmkiulNuT/zyOFvqpi72w50ysfVvaZiGksmq7r5HeOc8uVNj6qYaztOd8oH1CxXMU+3T3XKr2wco2JmNGxQdWXeEqfc8qAKISIiIqLd0Mb3TVF1KVml4/qqnXK2VD/XXJNyk2qmRN9G3NTnJq3/9kOnqZj3HTpf1Y0ub3fXD520/9NT3QSi/svnqpgwJuKkwTa2rFXVLetrcspZ0cdvStx71K5smYqZUr5e1W3KuEk9N4SS5gK6vSzvGaZievXfqtip8E0LIiIiIiIiIoolDloQERERERERUSxx0IKIiIiIiIiIYmloclpESOw72ykfM3axivnXmmmqrrwkXXDZnd3unKGbF7xHxUwe1eKUH10/XcX8bc+7Vd0PE+76H+/S33t5xXin/KlxD6uYmzYe4ZT70vqfpq2vQtUdNfwNp/zXY9+rYpKPvKjqiEhLH3egqlt3ULlboacpItmr66pXZ51y43Nr9fqWLtuazSMiInqH9EZ0PiHZ81pUXUb0M8uEcfuskkRGxRxUtdQpr03rSfJTS0Jz8uv0dfqqLv29o+pfd8qtqSoVE57bX7EhokMOyfb0FIwh2hp7l69UdU+F7v8WtI5VMZNrNxZc9tyqJaquIuEmYfm3TFQxy1vdfDNrOupUTOX6wjkl44xvWhARERERERFRLHHQgoiIiIiIiIhiiYMWRERERERERBRLHLQgIiIiIiIioliKTSLOdYe7SXnGpytVzLDKLlXXm3F/Ql25TriTyrhjM1095SqmttT93rquWhXzx80jVd1b3U1OeX6LTrxy/IxFTvmZTp1QtK3L/b2Th+lkLU0Vm1VdV8b9LSuP1b9t0iOqimiXl2xy2+bC6/dQMbed8HOnvKBHJyzbnHET4DanalRMwujkRptSbpvuSOlEuuu63WRKS5fpc8zMK+Y7ZUn1qRgiItr1mXL3Gi8qEWfJ+HFOee/ha1TMqh6dCDMZ6sf2q16hYoYnQtfhRdxFnDLnFVX3zLpJqm56mZusen5ygopJSdIpd8xKqZgxhTeJaLtUGJ2kdmGXe+QtW96kYiqnusfruIpNKuaQiPvYdZl2p/yg2UvFbH6r3ilnIxLgDtfNZafCNy2IiIiIiIiIKJY4aEFEREREREREscRBCyIiIiIiIiKKJQ5aEBEREREREVEsxSYR56Y5WadcmtBJTspLdFIRE0octKqtXsUkE+6yp4/coGJGV3Y45azo8Zy71h2k6sqS7nZGJQJt7atyyo8t04k4k0l3G4eVd6qYKCt7G51y72i9j4h2agk38Ray+tyw7GuHqTr/nN865aaSh1XMi92TnfKqUHsCdJLNTakqFdOR1glwW3qqnXJWjIoJ23/GclX31sfd887InzxVcDlEg8mUDN6lgqSHto/qPvMQp9xXo/v6+jvmFV6QCbVn0cl4ibZL+BgDgGzh4+zNy90Ez4dUPqZilnSNUHUTK1ud8uTSZhWzIu32kUmTVTFhn2rS2eCXbj5b1d2z6WCnvEe5vlZf2TfMKV95uO7XH4JOpE80mDZkqlXd0o7hTjmxWfeb3elSpxx1Pbnvvz6h6l47+hb3e336j1Uke93zRdUw/ccrMpU6Ae/OhG9aEBEREREREVEscdCCiIiIiIiIiGKJgxZEREREREREFEuxyWkxa87bTnlzukzF9GWSqm5YuTtnp6NCzy1Phb63vFXPWw8LzzsCgHRWj/HUlvU65a6U3u66MjfPxX7jVqmY8Pz3htJuFdOb1f9cmdA8+VP3n69i3lA1RDEVOYdX57AIS8zcrOrWpt38Nm/2jlIxpcZddjh/BQDUJt32+1ZquIqZUbNe1R3asNQp/3a5zomzabM7L7G9qkLF1Kwt/PuJtlk4ZwwAiDtPfajzUCQbdK6qJf9vT6d81fvvVzHLenRbTcm/nfLSzXpuf/Z5N+9UZvGbKsaUuX299PaqGKLtYvQ1p6T6Cn7tuBPdY7wrq69Lm3tqVF04p0UGuj+uMCmnnII+fyTh9qNdoq9dTx75qqq7b91eTvmoiYtUTFvGzQFQYfS5qe8kNzdG2d+eUzFE2+OlnomqbmQoN+LiGn1sDq9w8xWu7NI5Jhr+ofNVlB7jtrO+rG53mQq33WUy+vzRsGrnvp7kmxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHFEgctiIiIiIiIiCiWYpOI84xRLzvlv23YS8Vs7tNJNiuSbqKTpspOFbOizU10EpVsb2O3m9xnbE2bitmjukXVre+tHXA5gE7g2RWRZLS+zE28WZlMqZjmXp04qTz0+2fXvq1i3oBO9EIURyapkwuFkwCacn0eGD9sk6rryrhxGdFjtF0Zty3uUb5BxXRk3eSYRw97XcVEufGl45xyskQnQDphiptorDujzw3zq91kgvoMQ4TIhJqmVHfx4TaW7epSMWHJmdNUXddUN6F1ukq3r/onl6u69Jq1TjmcNA8Amj/p9uNfnXOfinmh0+2jU6J//x8X7K/q0OYm2TbDdALNEYe4bb4hIhEn0Y6WqNSJmbOdbtvIHq2P8doSNxHn8q5hKqaqRCf0rC9xzwWpiASaCbhJesNJN6P0RCznEw26Td27dh+nvDQiefZele417oZ0nYpZdZH72/b4W8FNJNoqf1s3R9XNqAslZI/IKx9O2v508x4qZvhL7QXXH3UfKwm3rrxUJwKte3G1Ux7aFNtbj29aEBEREREREVEscdCCiIiIiIiIiGKJgxZEREREREREFEuxyWkRVk6qAf0AACAASURBVBfK8QAAjeV67u2GHjfPw/pOnfchlXHnug6v1svJijv5qC+jd82LGycU/F5NmZ4fu7LDzSmx74hVKqYz7c6/H1Om5+g/2zxJ1YX3yegSnYsDzGlBcRWahx/OXxGl+YIDVN0Hmh4u+L1So3NKjCjvcMo9Uqpiwt9Lhub0AsCtyw5TdXPGrXHKHxv7uIq5u/kgp9zeV6lizHmhPBu/ViG0OzKhCbNZfXxLb0RduCIiF8a6q+Y65b56vfqRL7p5lzpH6eWsun68qps8ye3rPjnxbhUztrTVKX/s6UtUTLbVzf9SPioiN0ciYt5vudt+Rw7vUDFte7jtMKoHNaH9X3hmP9HWCeeviPLmR3W7OyLh5nSIyqM2plJfK44tda87N2UKZ1CqSuhr3rpEj1N+rnuKinmgvVbVzR2+zCl//58nqZjrT9Tni7DP7OteD9yL4f1EEm2bxW+MVXXHHh7Kd5bS7wVMrmh2yr9dc5CKmf7yy6oubEO3vtdNpNw+qapc561JL9d5D3cmfNOCiIiIiIiIiGKJgxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHF0pAk4kxUVKi6hqSbRKsnoxPibU6Vq7pM1h13qa/oUTHVZW4ykrKETk62psNNCtTcUa1iEhFJvbq73ARHwxp04qSGSjep6PBSHbN88zCn3BSRHGx9u068UjnMTYZWm9QJTJPD3WVnWjaqGKIdzZTo041KvBmRFDA5e5pT3v8T81XMiFLdXlrTbhueVNasYhb3jHHKK3saVUxnKInZW+3DVMzYGp3U7IOjXnTK316ik4qVJNykgOmsHkfu6HbPexE5EWlXE0ryaJK6XRSTtLb9vENVXess9xjrHamXM/5Bt48sX5BSMRv2c/vxzrG6f6xYqRMApu8f7ZRvXXGqipnx08VOubFe95kdpe52//WQ/1Mxx//jalW39+wVTrmlWycbnPxnNxGoTr1b3P4n2irh/i8iuW7Y/jOWq7r2tNs2wwnjAWBsue6zGpJuO+vI6MTQmdCzzqhknQ9u2tsp379wjopBVm/TSXNedcqlo/T17MOts53yAXX6988pd5Pd33P8CXr9/yic0JOoPzVL9D3qtGPXOWWT1sd4XcI9pktW6vvaYtq9RLTpTLXbU22MuI/Vd5E7F75pQURERERERESxxEELIiIiIiIiIoolDloQERERERERUSwNSU6L9NzZqq5P3nTKLT16Lk5pRC6KpsrNTnlJ23AV07LJncWTSOoZqlUVbt6L8gq9rkn1OhfE6y1NTjmcvwIAZtatd8oruvWc+I4+d17TuJJWFVMSsd3NXe5+qjZ9KiY72Z23D+a0oMEWkYsC4h6vUXPAkyPc9tp56FQVs/Ywd9nHVj+vYh7dOFPVTa5qccpvyigVs6HPzWXT0qvn567saHDKh4xcoWLeP0xv001rj3bKvWl9up07xj3vPbNhsooJ59JJNjWpGKzXVRRTobZiSiNyvfT2uuWItpOods/9i27cU8WMGKPP9b2r3awoh815U8U8WzfZKZeU6vXXPuD2WSPm676nfI3ONbP6uBFOuXmvOhWz9raDnfLYDyxTMZnQnHhv1WkqZsJf9HOZzAJ3vn/N0qUqJiqHhRLOM8IcF7SdEhVum8p2damYtZ853Cl/qOGfKmZRp9vXTazW15PTKtapup6sm4OmJaNnwG/OuO1nfagPBYBlne41rjE6382lBzyp6s6se8kpf3j4PBXzkzXvddfVM0LFlBr3+n3TdJ1bB//QVUTFGjFf53k6vGK1W1ET0W+G8g4OX6DbRjHKk3rZlSPc80V3i85Js7PjmxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHFEgctiIiIiIiIiCiWhiQRZ9dInRRnTarRKa9t08l9Dh+/TNVVl7gJyxb0jlExlZVugrCe3lIVU1/Z45RXtdSrmLZKndSktsJdf/NmnUC0sdxNZtTWq5fTVNnplBNGpwJLpXWyw0zWHXfalNWJBHub3LqIlES0u4pKoBliQgnnJKUT7iGrE9eGlYzWiTCXfcxNvNn4ul5O9d5uMsG2tD7Ga0t7VF1jqdumXmibVHAb+7L6lJhMuG3x+IZXVcySPv3b2vvchGW9Ee334ZUznHJHZ4WKOXbqG0555biI38FEnDuPUFuR3sJtJ7GvTl69+hi3z9zj97pdlj22XNVVnbCvU346O13FzLj8Waecfu+BKmbNYW4izOajVAhmT96s6vYqdw/WA+p0YtsM3GVXGJ107MaXT3bKG85YrGIq8ayqG6x0meFkqURbJaLvjUq8GXbSxU855ZaUvuYMq07qY3V0ySZVlxK3/6tN6MTy1Ql3WVUJfd6ZW7vEKZ84ba2KKYX+/WsyoQSaGd3XT6h0k4omIpJ87lfhnvd6G4yKIdoeVS+/repWZ0J3VxHHZkOiq1BIUUqT+rohnXbvB6vf0ve6Ozu+aUFEREREREREscRBCyIiIiIiIiKKJQ5aEBEREREREVEscdCCiIiIiIiIiGJpSBJxpqr1WElHxk1A19Ol00Wu69HJOS8as8ApL6gZq2I6+9xldXfrZbd0ugl/Dp20TMWURiTHnLfKTYpXXqrTfE2qchMJviXDVUxZwk2qMi6pE5glk3r9lWUpp9yT1YlX+mrd/c1EnLsJE0o+JREZf4pIoClFxJgD56i6FSe7yWy7J6RUTNWINndzluo23ljlJgPbq3KlilmaGKnqXm6f4JSfeW2qikHG3UcmrRN2mZRb5/39QhUjEcO/vY3u/i7t1MvumOyeL0ZN3KhierNuwrLekTo5Ge08ErXuMW7K9RlZxruJXTfuoxNDN77ptqdVR+tz//6eTtL3ywnfc8pXvPVBFaPT72n3feLbTnlBn26Db6d0X9eVdX/vulSdiukNJcRNQvd9n37f39z1zxuvYpZ26PUvX+PWlb5drmJKNrttNZTTFwAw+ql2pyzPv6KDiPpTRL/aculhqq7UPOGUm1M1KmZYWeGEnuGkmwDQkqkpGDO1zE2kO7ayQ8X0iNtn/XnzBBXz1+Z9VV1J6Bq7JKH30VWj/+mUu7K6/W7IuOfYxGBl3yUKpNfo5LLLUiOc8vjRrSqm2rj9dvmmwucBAMiI2zbKIg7qTMptd8MW7noHPt+0ICIiIiIiIqJY4qAFEREREREREcUSBy2IiIiIiIiIKJaGJqdFlZ7bPaNijVOuqOpTMR19eu7an1v2c8qjIubXvdnrzjPKZPRYTTrtzgVq76tUMZ1pPfc4FZpDlEjovAFretz5yGs69Rzeg5tWOOU/d+yjYmoqelVdb8r9J6xK6JhwTgva9ZhEAolKN9dBtqvwvNZkQ2iu/MgRKmbznu4c8NVH6uMpO0K3V9PqzsFreFnPue851l1WIqXbz8ZQvpn5XXp+7Py2caru1cXuHPfk5qSKCW93SZmeX1hR6ca0V+q8G8k6/ftrq3uccltbRC6KLrf9bny5SYU8Uevu/+ntxWQcoLiqfcDtR6ZVb1AxvVl3LmxJQud0+GDDc055dbpRxdy3Uc8bv37d8U758nGPqpiXF0x0yo0lD6iYF3vd/FE/fftoFdO8WefUMMZt42Ulus1lsu55IRnx+4dVjnbKc+rXqJgTJy1Qda+OdM8LiX0jcv2EjCjV1xUvfcTdRyvmFlwM7aZMub52lV59rRZ2xJXPqbrNGXdZUXkfykPz3SsSOp/Ugh6dAybsgMplqm5aqZvL5eGuySrmtpWHO+VURve954x/UdVNL3fzBNQmdF/XkXXz370W8Tt6Qrk4KloKt3Gi7TW11O3LE0Yfdy1Z9zqwckWbionKcpGFu6ymCp33sK7ObS+lm3e9e79d7xcRERERERER0S6BgxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHF0pAk4kxH5KPrETc5WVNtp4qJSmqyrstNajmqql3FdPW6yzY6DyjGNbrJULLQQRu7dHLOcOLN0qROoZIVd1llETHTK9c55UdaZqqYUVU68cqidSPdZRu97FRNxA+mXYpkswUTby799mGqrmamm/AvfKwCQEe7m9SrtDytYkoi2mZvt3t66R6lx0iv2/dep/w/952vYszf3ASDdx5ysIpBX8T4a+i3ZOoi0hv1uAnC0hG/v67RTcK3195rVUx7qkLVhfdlRZlOhiahmCl7t6iYMRXuuemV2/dSMRRPmWHVaD/5UKduv+p5TnlNbygZLoD6UjehVlRi6J+tO9Ypp0S3gVKjE1j2Ztx2+UjHbBUTTtz39PopKqYs6Z4HJla3qpiouqjEgWHhRIJRfX9YSnSyv0fb9G9r7nWTg5ZE7KOw51KTVN2oCve8kD1yf/3Ff91dcNm0kwldQJoSnWDaVLjJMrMdOpFrlDd+6GZznZ59ScV0Ztzr2XB7BoBs6FwQ1a9HtcMLRzzprr9UJ8L8zoYjnfKrbWNUzAfG/tspX1a/VMV8fMVxqu7Mca865Xk9OsH2pozbflf0DlMxx9QtdMp1y3WibKLBtj5T45TTWd0nTyhx71Fl2cqilv2rdrctLN+sj/tN690k8SM7Cyf73dnwTQsiIiIiIiIiiiUOWhARERERERFRLHHQgoiIiIiIiIhiaUhyWmT09Fy0pt15anvU6bndCeh5rY+/NdUp7zdLzw8aUePmx1iX0WM16zvcuUj1lT0qZvqwZlX30ip3ntH4+jYVE1ZbpucZTSh1f++K9kYVM61Brz+TdufxdmbLVUzEVF/axaSbqrH+3MOduvYZ7lztpud1+0m82OCUexr13NeaKrdu8x56Lmz1OD1n99SDn3fKf3jhQBXTk3XnAz/79f9TMXvc93GnPG6MnicfNeN99Wp3zl/jCL2Np0x8zSkfVvOGikmGlr4po5PyVCV0m06G5sqHlwMAPeL+/umlG1TMH9tDc+XnzVcxFE/pSqB5H7f9HFW7yCnfl95Pfa8v63bNUXPSw3Pb+zL6RN8RkWslfFwu2jRSxdSXu/1fVUnhOeGjynU+qRmVOv9LhdG5XVRMKKdGe0b/jpSEcnO0ziq4XACoDv2WqJwAYVE5NRpK3RxCb9br3Aa0czGlbpuSdMSxKu6xICndNqLqwpo/oXNMnXSYmwuiN6uPzUzoXBA+ngGgM+3+jq5QGQA+P+EBVXdo6PLxS+uOUDELNo11yhePe0rFfLjW7aNPHKvzUPWcrtvrxJ/9yyn/OdWgYorRk3V/b/ma4nKKEBUrUaH7pAkl7v3flHp9z7aor8kpF8pFl/OTN49yymdMfEXFtPW629Syt+7bh89TVTsVvmlBRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLHHQgoiIiIiIiIhiaUgScaaqdVKr5pSbCDOcbAgA9qxdreoeX7a3U66f061iypNpd9lpPVbTnXGTaI2s3axietI60VZvq5v4ZMpUnXjl9XY3GUpdmU7yOTWUiHNjW7WKmTBWJwl8udxNitSSqVEx6YjEp7RrSfYJ6t52j/OqM9xj8fCj3lLfm9/qJpJdu3CciqlZ6ib4m367bmOJrqyqe+zgue5yhus2/dN/nu2U/+9inYhy9rRVTnnxqlEq5rAp+rd9e8bdTnlZqknF/Ktthvudqy9UMRsvdc8FN+z1JxWzsEfvt/JQMsFUREbc5lStU07U6P14y/NuMrQZeF7FUDyVtQsmPugmyvvOASc55b0a16jvndCwwCmH+wcA6AkdT1GJXjPQbS4cV2r0MRcWlQR7Wqmbte/MY85RMS+8ofvaZF2dU5aMTuwrfW7biUps2HKpm8jw+et1El9vwxxVd0Ktu29LjV5/eB/d1vIeFfPdMS865bnD5qoY2rkUk0CzGOZA97hbfKW+CDtwhr6eC1/3hq9LAaA84fbzbRHJdktCbfrKcQ+rmL0iEsJ/ZvUxTnl1d52KuXLCI075W0tOUjG/PGmpqgvbsI++/Xi1z722iOozE0Wcr8IJrk17Zz+RRNum73DdtzzT4x73e1Tpfvu+1n1DNfp6OkrXCyOc8tF7LlIx7SPdc8FfJ0Yk4ixqbfHFNy2IiIiIiIiIKJY4aEFEREREREREscRBCyIiIiIiIiKKpSHJaSElen5se9qdi9OVLlMxTSUdqq4hNK2n6gw9T88Yd3011TqnRPtmd85hdYme21gVUTdjmjsfeUVnY8HvReXGaEq68/SSS/QcyOYpOl9FIqH3ZVi6snAM7dxMWxcq/vKsW/kXt/jqzGnqe2+f6855Gz5X52SZur9bN+WjOuajjfNU3f9uONYpz6xaq2Ke3DTVKUe1jUMalznlj4x9RsX8bu3Bqu4TN13llMd/4ykVE55PWIFnVcTmM91ln1jVpmLKIubFNyXd81VUfoHwnN0pJV0qZuIfOba8szIdXSh5+AWnriQ0vVzPbAfegJtrJdmo+xWMdGenZut0n5Gq0/1opsw9nrLl+rgMp7DIluqY7mHucka88bReToRMe3tRcYUMv8Vd36xJV6iY0g693X9fc6RTrmjVbbdso9tnJ7tTKuaUNe6/ScO64n4/xVdin1lOeemHdLtLjXevMceM2qRihle6c9lLn95DxXRM1rkoRle4fUZa9Lk/nXHbdDqrY05setUpz63Qbe66dTpPSziHxYVj9DF99d8/6pSnX6X742KI7upVnp6erA4qDeX0iBL+XrZV/xsRbY+2KbpvnVK2vuD35jWHzwUri1pfSSjN4oQS3aanV65zyn3jBydHT5zwapiIiIiIiIiIYomDFkREREREREQUSxy0ICIiIiIiIqJY4qAFEREREREREcXSkCTijDK8tNMpd2d0Ap7ObLmqGzbfTUYSnQhljlPq6dPLTpjCySrLkzoB0JqOWqc8vj6rYpq7qp3y2BqdQKU+4SZ1GTNPr6vhFJ2kr67STSranKpVMelqJuIkILP4TVU34XpdF9YaKr88bryKefSIz6q6zePdMdGH6vVxmKpz66pX6HHUtevdxEWNf5ivYrJdOsnneOi6bTHtV25bnJX5lIqpWaJPpelQXsSoBMThPGtlbTpx4Ni/RCUQpd1JpjXcCgFE1YVEdfCD1elXFw55V026ZsclwtS9Ou3sTHk5kpPdRNAbv+me65sSbmI7AFizod4pN78wSsXUf8tNhLlHuz4237zxUFU3/lA3YeSGbp18vbHcvQ48d9TzKuacGjcR6I82zVYxSzY3qbqPjX3cKX/moQtUzIxiEm8m3ISayOpkt6la3ao6sm5y0nCiagBIivu9rOg+c2PGPTtlOztVDNH2MBGdQjLUU4wu0Unbw/eMY4pcXxH5Z1GbDP2RiYi2sbPjmxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHFEgctiIiIiIiIiCiWhiQRp0SstT2Uta40IstJW7pK1SXXNBdcX0/aTbyZSBROTLl8U6OqKxmmkwl1bHATJWVqO1TM/k0rnXJnWicUzYi7TRVrddLN7myZqitNuPupIpFSMRyaosGUXrVa1dX+LqJuB63/3U6Kl3j83055xuP9BBIR0U6hZ0QJ3rh0pFN3xLBXnHIqqxNBTql3rznTU3TMe97/llNe1jNCxZS2L1d1r7W6ST33qNuoYj4x+jF3e0p1Yvdb2mc45UebZ6qYT49/SNV9/a1TnfKMK55VMUWJSLypQsr1dXiPuNfqWehEgl2h6+BMxAVu1L0C0WCqWl/4GC81Ontmz6KGbVpf4xvuvd2miPvB0SVuIt/S9fqPTuzseDtLRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLA1JTotEn56ntqLLzSExubpFxTy2Ybpe2Fo3X8ShFRsKrr80qecilVa5dSNqOlVMX1bvroaRbg6L3oyOSYfmRY4o36xiHumpc8qmV2/ja62jVV1NWa9TXtw1SsVIaeEcHkRERES7g/LqPkw9eIVTN7nSve5c2aNzm5Un3HnqiYj8a1E5LMJOGzlf1e1X4W7P2JJuFRN+0vjXzTpfxb9a3ZwWHx/3mIpZm9Zz60uOX6HqwkyJe40raT1vvxgSkVsunNOiJ6vn5IfztpWaiGvl9vC1cuH7AqKtUb2kVdWF86tUmz4V0/Titt2PVT2z1ClvylaqmNpEj1OuX7xNq4o1vmlBRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLHHQgoiIiIiIiIhiaUgScWYqdOKiYixZp5MbTYWbiDNqFObgEcud8sa+ahVTknCT+WRFL6kyGZFUJZRUs6G0S8WMLHOTdY4qbVMxp1a5CVR++MoiFZNMTFR1FclwUqJt27dEREREu4U1pUhf7yYu/9sXKpzypDqdbG9a3Xqn3Fiik7Yn4V6HhRNMAjqhJAC81ONe482L+F5r2r1+TUAn9vvUmH865XCCQAD44bRZqk4xOmn+tibeVJJ6u6uMm1g+vB8BnZwznBgVALrSZdu5cUQDyyx8Q9WtTdc75Rml61VM+Ubd7osh3e49YjKi3YfPMyNe0Oevnf0OkW9aEBEREREREVEscdCCiIiIiIiIiGKJgxZEREREREREFEtDktMi2V14rCRqnlqmvfA8tY/ueZKq23T6HKfcW6fn6XWPcut6mzIqpnyUzleBV2udYkKnvUDSnaaHyg16LtJvf/NcqEb//rebG1Rd/dhup5xFxBzEiLmDRERERLulji4kH3nRqap7xA3RM8KBR/Y/xF3MtBoVs+EA9xrXTNF5L46YtFTVjSpvd8pjynT+s5pk4bntH/3rFU55+n88o2KKIhHXjuE8F9sYY9L6PuDt1HCn3JXV1/z1Je41bzjHBQCsbq9zymOwSm8j0SB7tXu8U47KaZHs0feWxUg0uvd/FUbnxpjfO8EpZ1/ReTd2dnzTgoiIiIiIiIhiiYMWRERERERERBRLHLQgIiIiIiIioljioAURERERERERxdKQJOIs26STRR7SuMwpz65YrWLu6Z1bcNnZjg5VV/ebecVv3EDCyYWA6CRE26CYpaRaK1TdcfsscsrViV4V82DH/tu6WUREREQEQP79qlOu+beOqfl94eWsjKwLP0dsLHq78k3HNibeLEYx17xFxEz/lN7GuzA6VKMT0gM68WbYGCwsGEM02BZ2uMfvF4fre8Zkr5uIs+g7yIz7vWmlPSpkSSp0/5fdtqSfccY3LYiIiIiIiIgoljhoQURERERERESxxEELIiIiIiIiIoqlIclpMenni1TdHeXvdcqpaj3TZ+btm1RdNlyRSKoYk3DnFUk2YhaRhJYUNSevmLl8UXkvTBFjQ0XMPZr5i25V94PW05xyulbtEcy8rdVdVeGtISIiIiIiogJevW+mUz7isBEqZuRLi7dp2ek1a53ywfdfrWJKW9xb+j3w9DatK874pgURERERERERxRIHLYiIiIiIiIgoljhoQURERERERESxxEELIiIiIiIiIoolI8Ukl8wFG7MBwPIdtzkUc5NEpGmoN4I0ts3dHttmDLFd7vbYLmOKbXO3x7YZU2ybu71+2+ZWDVoQEREREREREb1bOD2EiIiIiIiIiGKJgxZEREREREREFEsctCAiIiIiIiKiWOKgBRERERERERHFEgctiIiIiIiIiCiWOGhBRERERERERLHEQQsiIiIiIiIiiiUOWhARERERERFRLHHQgoiIiIiIiIhiaWgHLYy5GMY8McDnD8CYiwZhPZ+EMTdu93LcZZbAGIExk/v5/CIY88CgrnN7GfNDGHPZUG8GxYfxzRPGNxf389kU45vN7/ImbTXjm72Nb57ZAcudZ3xzQT+fzTC+2TTY69wexjfnGt/cOtTbQZRjfHOC8c2f3qV1fc/45vJ3Y11EO4rxzcXG7/+62PjmAeNv/3Wx8c0njV/cdbHxza3GN18b4PPNxjdTtnL9zxrfzNma7xDtDoxvnjS+2X+I1h3rfrRkh6/BmCMAfBvAHAAZAAsBXA2R5wp+V+TkAsu+GMBlEDligJgyAF8BcCiMORJAbiDBAKgC0JkXvSdEVhTcrmKI3AbgtgG2qwRACsAeEFkW+uwa2H+bfwG4GSKTB2Wb7L/DUzDmVoikB2mZ9C4LDSRUAeiFbVsA8Enx5I7BWI94shRATYFteQLAzeLJraH6owB8DcB7ERzn4oWO88HzNQDfMb5JAmjLqw/vm0vFk98NxgrFk9cBNAwUY3wzD8CPxZPbQ/XvhT0nnQKgG8AE8WTlIGzW3QCuN76ZKZ4sHoTl0S7G+GYZgFGwbSIF4CkAl4snb++gVX4dwFV56xcAXQAEQA+AfwC4QjwZjAHA7wB41vjmF+JJ3yAsj2iHMH70dbF4ha+LxRv4ujh4CHGZeP1fFxs/77p4S92lAD4PYBxsG30ewIfFk44itqnQdcKtAFaKJ1/Jq/4fANcB+GCh5RO9m4xvzgfwWQCzAHQAeAnADeJJ/w/Zi1vuowBuF09uHiDmdAAd4sm/8+pmALgBwLEASgEsB3ArgB+IJ5mo5RS5PRdDnyti3Y/u2DctjKkD8FcAPwIwDPZk6MPeSGzvsosdcDkTwCKIrILI4xCpgUgNbGcBAA3v1A3WgEUhhbf9FAD3D/p6RVYCWALgtEFfNr1rxJOa3H8AVgA4Pa9uUAYsCjG+SRjfDHT+2DHHsN6O8QCOAPAX8SQT2jerAZycVzcoAxZFbNOQ7BvxJAvgLgAfH+xl0y7l9KB9jAGwDrZ/HnTGNwcDqBdP5oU+2jdY/xQAjQCuHYz1iSdrACwCcMZgLI9oRzD+jrsuNv7WXReLJ6uC7x0NO8B4nnhSC2A2bF+y3YKHCVHuBXCs8c2YwVgP0WAwvvksgBth28MoABMB/AS2zbwbLgfw67ztmQrgGQBvA9hbPKkHcA6AgwDUDvbK496P7ug3LWYAAETuDMrdAB5UUcb8D4BLAWwCcCVEHgjqHwVwO0RuDt6q+DiAZwFcBOARAKcCKIUxAtsKNgAAIABJREFUmwGkIRL15PNkAI9t8y8wZgaAmwHsC/tk6kGInJ8XcSKM+TyA4QB+DZH/CL53GYALIHJM3lsVn4IdvQOA9cH/vgpjBMBFELkHxowAsAfsyPtaAOXB7wPsRV477Aj9OQCyAH4H4EsQ6YMxxwfb+gsAnwli/wsiv83b3kdh99u78souDT3jmyrY4+JEAEkArwM4RTxpDkL2ML55CsDeAJ4EcL54stH4ZhqAN8QTEyznCdh2dzyA/WAvOg4DcJDxzY9h37i4OljmKQAugH1bCABeDZ6yXiSe3BO8fvb/YG9aHod92romuOhKAfgP2LZSG2z7fwc35WEnAHhOPNmmCz7jm2oAtwTLSQBYDOAk8aQ1CJkavDGxJ4AnAHxEPGk1vpkF4BXxpCRYzjzYc9uJsOeKOwAcDOBm45ufAviZePK5vH1zdt6+WRzsmwvEkz8Z3+TOEw2w564rxJN1xjcVsOfQTwf7rhrAzwF8RTyRYFmPAvhx8DlRv8STHuObu2Ev0AAAxjenwr65NBX2raVbxJNr8z6/EMD1sG9g3Qjbb18mnjwUsYoB+17xpN345l4AZ+Ut/xIAXwAwHsAGAN8ST36W9/kXAPwn7Jsa1wC4CcB08eTNIORR2P7t7qJ2AtG7bwYAiDfwdbHx3eti8ex1cf7T2uBJaeR1cfBGZlq8oq6LDwbwdO7prniyEfpN4Ubjm/sAHAXgNdjrhCXBNgmCdhi8VdENYBKAo2Hb60cAiPHN1QAeEU9OD84/L8D2vf2/lUz0LjG+qYd9++cS8eQPeR/9JfgPxjflAL4F4Nzgs7sAfFE86TW+aYQdcJgLe3/9JOybjCuNb24AcCSAQ4NpWbeKJ1flrSP3BtR7AXwyr9oH8JR4krt3RPAm7fl53zsDwDdgB0Bfgr1mXBh89iXYc8RI2IGPL4snfzS+mQ3gp4g+VzyKmPajOzqnxesAMjDmNhhzMoxpjIiZC3ujMAL2ZvwWGGP6Wd5cAEthd/4FsCNSTwdvSfT3qvbewfK31Q0A7oO9uRoP4H9Dn58C4EAA+wO4IBg46M8ZsJ3D3rAnfgCYE2z/PUH5JNiBkTYApwNYkfcmyHrYC7WDAOwTrPM9AP4rbx3jYW/0xsJ2eL+AMdPyPl8Ie1NFu49LYKdKjIcdXLsS9tXsnPNhL3hGwd4Ifza8gDwfBfAxAHWwFyJPw56Ua3IDFsHbDw3iyXzkHedBzD3GNyfAdgxnw55kV8Pe5Oc7E8ABsMf62QAu7Gd7trd9XwbbuYyDPQddBSD/lbjzg985BnYQ4TMDLOuCYDtrYTud52Bv6GpyAxbGN5MBVIonr2HLvpkZxPzJ+OYUAF8F8P5gm5oBONNLYM8L+wE4BMB5wfblLAQwK+hYifoVDGZ+CED+mxCdsMdwA+xFyxXGN2cF8XvCPnHKtYd62GO0PwO2zeAC76zQ+tfDvglYB3ve+r7xzQFB/Emw56bjAUyDvSEKY/9Gcfc6gIzxzW3GNycH7SBMXRcbf+uui4M+pdjr4mcAnGh84xvfvKef/uM82BuoRgBvwl4b9+f84PNaAL+C7d+/HWzT6XlxbK8UJ4cBqADwxwFivgw7rWo/2GP3ENipVoC9p/4l7IDdRNjBux8DgHjyZdgHdFcF7eAqaNMBZEPThY/HAIMHwdSROwFcDaAJ9i3evwQDIIB9u/5I2P7aB3C78c2YYFCjv3NFbNvljh20EGmHfXVbYJ+IbIAx98KYUXlRyyFyE0QysKOtY2BvnqKshsiPIJKGSHeRW9EAOydpW6UATAYwBiI9EHky9Pk3INIW5KV4FPZA7s/XIdJaYNtPxcCvjn8EwLUQ2RAMYlwHeyOZkwXgQaQXIg8D+BvsWxk5HSgwF592OSnYi59pwRSK58WT/LwYt4gnb4gnXQB+j4GP4V+IJwvFk5R4/eZFORVbcsdE+QjsWxkviSc9AL4E4OhgsCPnm+JJa5AH44ewF0xRBqN9NwGYKp6kxZPnxJP8PDc3iSdLgrq7MfC+uVk8WVzEvinUvn8unswP9s0XABxnfDM6L+Yb4skm8eQt2A4xf9/k9kX9AOug3dufgiSy7QDeBzuHFQAgnjwqniwQT7LBoOOd2DI4cDbsNKwngrmu18D27f3pr22+GKy/GfbC7p03KcST+4L2JuLJY7BPoI8MPj4XwC/Fk1eDc5UfsWz2bxRr4unrYuObe43vXheLJzcF89ULXheLJz8K+q9tui4WTx4H8AHYBwX3AWgJEvLlT+34g3jybNC33YGB+8I/iydPBueRngHi2F4pToYDaB7g+g2w12jXiSfrxZMNsP3QRwFAPGkRT+4RT7rE5oK5AdGD6/2J6jOHA1gzwHc+BOA+8eQf4kkKNldMJYDDg236vXiyOmiLvwPwBuxAy0Bi2y53fCJOkYUALgYAGDML9qnhjdhyob02L7YLdjC5v6Q+25IsrBXFzvsx5hjYuYYAsAQi+wL4HOzrsM/DmGYA/xMk2cxZm/f/uzBw4sKBt9+YJIDjYKeR9GcMbBKWnOVwn3a1QKQr9PnYvHIt7OuGtAuKSEY5AzZhz1gAdwXzaX8NO6Ugd2IevGPYOgV2ilJ/xsImAATwzmvirbDHcW5b8tcTPobzFd2+g6dHLXlVU2CnhowGcLfxTQ3sU6GvypbkRjti3/xkgM/HAng4VxBPNhnftMPum1y7HWjf5PZF/jFAlO8s8eSh4FxxJoDHjG/2FE/WGt/MBfBNAHsBKANQDjuQCdjj7J1jTzzpMr5pQf/6a5sHBK+Rl8K+9fV4sP4e45uTAXiw560E7BtiC/LW/3zecqLaG/s3ir3gKefFABBMNez3ujhoZ8AOvi4Opp88EORjOha23S/GlkHFwe4LAbZXipcWACOMb0oGGLgYC30PNhZ45+3F78O+MZ97g6rW+CYpxSXMjOozW2Dv+/rjbI94kjW+eRvBfWEwpfOzsA/fAdtuRxTYjti2y3f3T56KLIK9gdprW5dQoBxlPnK5NQouXR7Nm4qxb1C3BiKXQWQM7GDCz2HMHluxzf1tb9S2HwrgdYhsHCBmDeyrRzkTAazKKw+HMZWhz1fnlWcDeLnoLaadioSSUQYjrH3iybXiyWzYJzzvhzulYKtWMVA5GBh4D4CH+okH7PE4Ke87tbAn+PzjeELe/w8fw/mKbt/iSW9o36wP6q4RT2bBTtc4B8CHi1le1CoGKgc5KQ7FlkGJYvZNPeyr8sXum9mwCda2P9kx7dKCc8UfYP96QS57+G9gc9VMEJvw66ewf2kLsH3PO29DGd9Uwj4F6s+AbTN4KnQzbA6nvYJzxz2wT4pGBa+r3t/f+uG2gxz2b7RTES9e18XBE9l/wvZTO3qb2F4pTp6GnTp91gAxzjUa3GuwzwGYCWCueFKHLVOAc31Yobb5BgBjfJP/IPohDPwXdsLXjAa2b1xlfDMJ9m2uqwAMD/rUV4rYnti2yx3910NmwZjPwQSvfRszAXYkOZxNfFutAzA++LOm/bkfW/d6jsuYc2HeOYA2wf4jb/OfmHmHnQ7TAvu0Nyf86vg6ACNgTP7I250AroExI2BME+z89/w57wkA18KYsuDNkZPhzoc6GgO/uk+7GOOb9xrf7BU8QWmHnRKx/cewtQ7uMXw0gBdzUyyC0eXwcX4ngEuNb/YJblS+AeDx0Dy+LxjfNBjfTIRNytnfX/54EMDBefP3torxzfHGN3vm7Zs0dty+eS+AZ3Kv8AYDC23Q++bjwb9XBWzCp4fFk/ynXF80vqkP8mNcBXffsH1TUYxvjPHNmbADhguD6loAG4O3Hg5BXrIv2H7kdOObw4P25mPLxU+UAfve4E2PS2Dn/S7Fljc7NgBIB29dnJD3lbsAXGJ8Mzt4onVNxGJ5/FOsGd/MMr75XG46pPF3zHVxgT7RaZvGN2ca33zY+KYxOC8cEnw+mNuU38/lHnAcCPtnj+n/s3ffYZJVZf7Av6dy556e6Qk9eRhmyEkBAVcQFQRBMMvCmkBX3TWsuOtvTWW5rrqL4uKac8aEAbOLCoLMMGQY0gyTc+zcXV3hnt8ftxr6Pe+ZrpqeDneY7+d5fB7Pmbdu3W7q1Ll1+p5v0ZSzWduNcF75vMmZy03O1JucSVayZ/67UnYjgA+anGk3OTOjUj/8GawJ4XzWZXKmDeFdgyOpceA8fxHhIsXIeTML4GyTM9cNbxM2ObPU5Mz3TM60IpwXX2Jy5gWVuxevRfhNRHcizKizCOfU4aDrkQuRB3qviOw8OtF3WvQiDAm6C8b0I3wDXI3wlzoe/gzgEQA7K1s3fH4F4BgYc6Dby6s5E8DdlfP/GYB/GsevRs0C+AGM6YIxL4f7VYjWrkb4l6eNlZqZCC8UH0R4y+xDCAOUPjHimFsRhqntQLgX8hpYuxYAKosvR6OSgktHjA6Er90ehOPlFoRvvOPhfwBcYXKmy+TM9fB/nWcWwA8qNS+3Wft7hFksP0f4Ol0AfefHrxCmIN9fqfuW78lt1m5HGG50qe/fazAXwC8Rvletrpz7uHzVG8LbBF9ncqazMuH5fjcfBvCTyu/mpTZrf41wPN+McAV9NmRmDRDuOX4Q4a3yP0FlwqyssL8G4TeKEB3Irypp4T0I99y+3mbtI5V/ezuAj5qc6UX42nxqLFRq3gHghwjHbS/C4EzvXT02a+8D0F3ZcjLSg5Xn70QYAPwym7X7K3uA31l5zk6ECyY3jzje7xDm2/wFYRDgiso/DQGACb868Tjwm7Eo2p66Lja5ib0uNrnRr4tN7qnr4k6E3zCwFuH7wvcAXGfH7yvUvw7guMo8Nzw+Xwrg1socThQJNmuvR7id4oMIP+xvQfjHoeHX7ccQXns9hPBz2H2VPiC8Hq5DmNe0EmGm4Eg3AHhl5Zrwswc4hS9jxDWfDb+h5yyE2zseMTnTjfBz4T0Aem34TSJXIfwK5b0Ir4Uvrdxh/SiATyOcK3fh6W8IHKbeK6I+jxpra7mT7DBnzFsAHAf71NcxRk+4qLIK1s6rWnvgY4RfeWrtogP8+w0AHoG1/FBDE8LkzBoAl9isXTPGxw9/5eniSghnLY85EWFg5nPG8pyTxeTMOgAvslm7foyPH/7K0/nOXSnD//4qhJPVgb5phWjcVDJguhB+1eGGA9RcgPDrGke73Xasz38swg97aZu1JZMznwawzmbtaJkxRATA5MLrYpudmutikzN3AbjaZu3qqXh+oqgyOXMHgHfYylcQT/JzR3oePTIWLQ4HYUjpybD2QLfB13KM0RctiCZQ5UP1u2zW/tchHOOgFy0OB5Xb2f/JZu11VYsPfIxRFy2IJprJmUsB/AnhtpBPI/yL8Wk2OzkXEiZnXobwTqMGhHcSBhOxIEJERETRMvHfHkK1CUNKH5/q0yAaq8pXm415weKZrPIVjWNesCCKiMsQfvuQQXh76msna8Gi4h8RbhUrA7gN4XYWIiIieobjnRZEREREREREFEmT+5WnREREREREREQ1OqjtISmTthk0TNS5PDPUZ1RXqSEu2mVdglSPvOPFdA+M62mNh1507rXWtk/1eZB2OIxNk9bfwFZsTop2sk9/26gdzE/YOZXb5O/MxnVNsqcoa4YKE3Y+Y8WxGU2Hw7gcL4UldaqvIaXHSn63nADj+/sn7JymGsdldE312DR1+kLQxpxvEO4fnKSzOQjulxz7btZ2akw6rUps3vulQ5OGYzO6pnpsTqSh+fLnMvqSFzbhGVSjfbl4RXpTDZ8bjXOgCO62GG1sHtSiRQYNONO8YHzOaizcXzYQuV+4Of4E1bf72U2i3X2MPud5fwpEO/OrVeN7YuPgFvvTTVN9DuR3OIzN+EL99dQ7XzhLtGet6FY1wQOPHtq5jaLnxfILR/LT9M1nHb+X38hWWr9RH2iK35s4NqNpysflWI3hwmbjJ09SfafP198Ovu5zx4h28w9WHty5HUgErw84LqNrqsdmbNkxqq/cID/cmxUPTtbp1Mwk5McGWypVrYkdpef+8qNj+oKxccOxGV1TPTa93PnFeDYqBM4KREz/FezJa08X7VS3Pk5+th5TiDtzmdFz27Jr7tGPc5ik/OOhLUbvj3CjjU1uDyEiIiIiIiKiSOKiBRERERERERFFEhctiIiIiIiIiCiSDirTYsrVsj/Vs691203HifZgvw4EtJ2yb/0rv6xqLn7iYtX32PoO0U5v1cdu2CbPu92z7Wj3afI/RWL52aqm41N36gcSHSZsgw4em/GgDA56700/UjXvevC1ol1+oEXVeLb3YXCJDPp6+Un3q5ozm24U7W+/+PmqptDRKtqx9fq5iA5X7h5XQO9zHbrodFWz6RVy0C38lp57H5t/rOp714d/Itr/cdKrVM2S/7fioM+R6HDSfVyr7lss/464cK8nC2LtxE1AteRV1CJ/4ami3bksqWo61uu8myA/caHbRD7uax44wOve/fxpPQmajuD/OlTfmmO+INqPF3Ug7bridNW3KLlftJcm9D0HZ7zv3aI997/0Z8aa5k1fPlQtJiFDindaEBEREREREVEkcdGCiIiIiIiIiCKJixZEREREREREFEnRzbQY43eur/nGaapvSfMe0d6FJlVT39Yn2h/bq79D+7HH5qm+9lXye3htTJ+jCWR7qFWvFTVukY/rWqZKsP6/z1J9S/5thS4kiiDTr/erxtfKr2N+y81vVjXrXvMl0f7bKYGqKVr9VrYw0SNroN9TLv7JtaK9dLMOnIlPaxDtid+1RzR5atnjeuvXv6r6Luw4perj0p6+739FzqOn3rFG1XSfcaJo21UPq5rD4fvmiQ6keV2/6iunGkV7z3NnqZqZfTIHqrRjp6qpJZuilr38tdTEj9a5G4PT5eOmrSmqGuZXUBSMNbdl00f157HPX/kV0e4P9Nx2Q+dS0d6Y1/kVO/PNqu/4ph2i3RTX4+dj13xHtL/y4uepmr4b5Pxb94tVqqambIpYXPfVkPNxqHinBRERERERERFFEhctiIiIiIiIiCiSuGhBRERERERERJHERQsiIiIiIiIiiqToBnHWaOglp4t2sm5I1azfNFO0Tz16k6p5aIsMJ/nlTc9XNQv26JCRgXbZLmV02F+6RwYHDk3TNT1LZfDJnDt0EMpZ79eBKXc7P3/6N3erGqJISOjgHnvMItE+5tNbVM0lp14k2q+cfa+q6S3Xqb6/lGSoWWexXtUc/a0u0TbLj1I1QayGtd1agouIosANufa8dtddJ0PGTlp1rKqZg8fkYZ1gTAAwGR3FGfT2ivamr+jU6YF/7xbtjpepEpikEzbIIE46jAQJPa8UmuTYbNqqQwJ3XLZYtOf8Uh/bF87pqiVk0xdSmJgzW7R3navDQus918pEk84XFhlUf23u/IWe7645+k7RPi7zFVWzsSA/EA4Eev6b4QTEL2zeq2rujS9SffNS+0W7IaY/6+5zrnnfOf9Pqqbp+kHR/smHzlA1t35L9836X/nze3+PNVxbHCreaUFEREREREREkcRFCyIiIiIiIiKKJC5aEBEREREREVEkRTfTosa9MJsulXtoYjv1vvV0t1ybub+4WNW0r5R7n2Il/fz9s/T+KCPjKhDobb2qptigj92wSO7hNX9tVjW/+flZqq94rjzWkt/o5yeacDWM13JTRvUZ52E2n1c1hewC0b7hPeermqaM3t+3v1++F7R9u0HVNO5cJ9rBwtmqxuoIGqLDVw1j9ZLzZTbSH27We1zVYX2ZErHqg6duj943v2/QM5E6goEB2eHupwWYNUORldjb6+mVc5TvOrR5ixwv21++RNXM+aOc+8pr16uawDPXqnNcvFD17XpBh2i3bNDjvtgor5Xj+UDVEI03N6fFl8niZi+dvEq/fl/Q9FPVt2pA5p39vvskVVMfl8fqK+lMi3SsRbTPaNRjc0+hSfUtq5M5NTtLLarm4V6ZzTgn061qMrGiaJ/WsFHVvOnaO1Tfq//uzaK98NUPq5rJmG95pwURERERERERRRIXLYiIiIiIiIgokrhoQURERERERESRxEULIiIiIiIiIoqkyARx1hKgEjv5WNXXOqdHtIdWtenHlWW7aZUO1Cw7uV/WEyAWeH5b+elOEGjZU9Mm14aCjA4lOqFdhqysaWtVNY1bdMjJvpNkX2Juh6opbduuT4pokpWadLheale/aPuCMJMPbRTtmZd3qZpYvQ7gbSjLwWgyOhQpOEoGF5myHmPlOiekl4F/dLiI6bkOgWeScrxpugziemjFKWN6LlvU87ir4fHdqi+dbqz+fOrJOAbp8GadIWQ8QZyulo1F1bfplXIenb1qmqqJD+ixueMcGQTaul6/V7jBm74501VLDVDb5wCiA7Hl6nPbmutPFe33t3xZ1fxw33NU36xUj+pzucGbg55vZugqymvVrjp97XrLg8epvtgp8nNjvyfk8+gGOZcW3TcUjw1DM2vq++gpN4v2N5t0EGnQ6wsXHl+804KIiIiIiIiIIomLFkREREREREQUSVy0ICIiIiIiIqJIikymRS1719a9Vuc84FHZrPdsqXHzKoqNek+6cWImypmqp1Opc/bqFfSxB2Y5uRP9uqYtNVD1HGMF1YX6nbJu94UL9bG/wUwLmnzxaXIfbSGp10htuvqeu2CpzJ2IFeeoGlPUexmDjHx7K6f0212sJAe+hc6bCVLyHFML5qma0qYtqo/ocLDzXWervtaYzLSoe0i/vt0Z23hyoGrZY1zasEn1NdUtlcc5R2dqmL89UPXYRFFl6/R+9xq2oMMm5Djz5V7MWZEX7b65+rl2PU/Px/UbZTuze0jVBM6cbUp6zkz2VR/3PsywoENSQ67RrKV7RXtnqUXVtKf0B8kBJ59iyBNyOOh+2KxBzHPNefLyzarvhAb5OS5v9fNvyctMx8DqMd6alJ81MzGdiZMPkvpxMfm4/vN1xmTdL1epvvHGOy2IiIiIiIiIKJK4aEFEREREREREkcRFCyIiIiIiIiKKJC5aEBEREREREVEkTUkQp0nop3UDeOLHLVM1pQ4dCtR0v0zM9AVougGWnmwS9bhyWtf4Hucu+xRadKhKqlsWqfBOANsHmz0Hd4/teXon76hpsyetk2gKlI5ZINqJPh344zJlT5CSG+bnCVuyxhOuOyQfF/cd2zmWKeggMDeSqDi3TdUYBnFSFAXVA/F6n5VXfVtK9fIw/QOqxuUN3awhGM0nHpPz6LpX6Yl96d/GdGiiSCg169d0yb0OzeiLznjeCY9O6LkPzqVyqk9fl8ab9Hyc7qz+kSBwg0DL+hzdGnjOsYbMUaJx95K5j4j21sJ0VTMt0a/6NuZniLYv5HIokK/qgiessyEuP6PtLenPfs2pQdXnBoHOSXaqmjXl2aOeDwDUOc9f7/mGh6TRc3nK6dt6vv75j/6l6hp3vNOCiIiIiIiIiCKJixZEREREREREFElctCAiIiIiIiKiSOKiBRERERERERFF0pQEcXoDuxwDi3XqpC1VD/UyOkcPbhaK0ZlEcPNK4joHBYOzPSGbnXLdp7RAh5oNJWSqZ9DkOUlHvl3/rMleHWbUcd0K2THG4DOi8TY4W6aK1e3SYwMxOX68Ybc1sJ4sMht3DuapiQ3JsRikdThakJJvDv1zdU1T9VMk8ot5IumsM9fU8r7uCaOt5XHHzN+p+n7R9SzRDnp7qz//OM49Xf11on3+WQ+rms01HMckU6rPFp3gMd/vTT2I8yqNr6Hp+rXpKqf0a7NUJy9oE4P6unSwXcZH27g+ji3rvrp98lgDc3QivRv+XmrQ719uoHbfHF0zs4ZAfqJDkVi0QPUdm7lVtB/Ld3hqtqu+bUPTRLvX860PfUU5XnxBnDHIsdFdrlM1JU+A5g7nmxh+vuVkVXNa+1bV5ypaeexkTI+5INDvDXkr31NaFnVVfa6JwDstiIiIiIiIiCiSuGhBRERERERERJHERQsiIiIiIiIiiqQpybSoZX9oot+Te1H07A9ytuOUq28T9GZajKXGp/FevT/Jntcp2sm4/tnyZblfKFbQe4rmfvLOsZ0U0RRo2Nwn2vtOblY19bvlWEgM6rERK8nBaIp6cLq5E7UqZ+R7SjntWcd1uuIF7m+ncRRUz3jy5i6YGv7mYKsf+9hmnWlx+86jRLsFT1Z/rlqyOXw81wMDuxpE+w2n3q5qPj7/paJd2qL38xo31wYAbPXLnlpyt4gOhS/noW6PHAu+TAuXL6/C5TvOR8+4WfV97MnXiPaMh6uPg2Kd7/llX36Grok16SSocmen6iMaq33n6LyK1ni/aHeX9Ge2htiQ6kua6mPB/RwX+MLWHEVPfkVbakD1zU3LsXF8m87UcA065xMe2/3561XNvNR+1dcfyLyOc+fpa4LHqp7RoeOdFkREREREREQUSVy0ICIiIiIiIqJI4qIFEREREREREUUSFy2IiIiIiIiIKJKmJoizBvkZOkAkNqBDTewYll3KnvwS9zhFnRGE+u36yXqXF0W79S86VGXX+hbRXnTSdlVz9dw7RPur/7lbn6M+JR3QVkPIKdFkiG3dI9r2VB3EWc7I168p+4LznOOW9Wvc+F73njpXUC/fAn1BoKUGOaZTPSVVQzRW8aWLVV/5yQ2yw/f6riFksxbzMzp0q7v/eNFuURUetQSK1mjmCjnmzrlcvy/suGS+aLd/UQdxBvn8uJ0T0XgKvCGb1ecsN1TTFwzthnN2Xtyvaj604nLVl3bavpDNTJcc54En7LbQKPtiRVUCOzioO4nG0Z4X60DNohPEPC2hQy9nx3tUX2NcHmur58NnKibHRsETsjlQkt8WkYzpefOh/Z4A0VnyPHtL7mgFEs6x9g/pkM2GhPw5jm3YoZ8rrn8nO0vyKuBdM25VNW/Fc1XfeOOdFkREREREREQUSVy0ICIiIiIiIqJI4qIFEREREREREUVSZDMtOo/We4FS3dUfZwLd52xhQqDjMgDncUHKt7dQ7+/mZmxOAAAgAElEQVSL98rz7F6s14GmPSqPtT4zW9V8PS73AtmSzr0wCf2fy5bHbx8x0Xgq75K5LOluvXc/MSgHnrsX18cm9BizMc/jnLcQE3iyMEqyL1bQ4ylokeOufnOnquEopLHafZ6eD/a9t120l73tblWT6Jgj2taT31Dep/MqEnPlftnZiU2qZmh7g/9kR2GSKd3pG5fOOLTFgipJ98gR1R3o/e9dZ8rHtX9RP1W8VadxlHv6nPPRo7f/lWeK9pJrH1M1u87S+56JalX2DBd9jVk948KXadE7T05+xX79ZM3Tdc5FrzNFZ+6p/nfN5IC+6B5q4d9Daeot6dir+rrKMuehLdGnalo8ISwZp68xoectN68i5vlAOi0l57KYZ4zPqNPn1JaQ43VmWteknXM8vkXnVQwF8no2Y/TP2p7Qc9umwgzR7kjoTA2Tln12SGeKHCq+sxARERERERFRJHHRgoiIiIiIiIgiiYsWRERERERERBRJXLQgIiIiIiIiokiKbBBnvl0HmNRv12ssTqYIrGcZppysXqPiwjyBnqU63ZfqlAcLPOFK5Yw8et02/Wvft3KhaLdCB3HaUkkf3FQPLiSaCm5wrDcscyzHLXkGpyec01gZcBTEq6/R2mT1GjM4/uFCdORqWa8DvV78z6tE+4fff5aqCUrytWoH9LyS3qX7CjNk8OTqwS2q5qgTton2po+epWpg5Xgu1etAsbj+0RAryMcVWvV4DjKy73s9y1TN0fN3ifbaz56pas4941HVN1iW4ZwPbJural5+9ArR/uVPnqtq5uFO1Ud0KIyTCVtLMHWspMddoVm243X62nHg8VbVZ1vcUFp97HJavu/Eh/T4dce9+3MBQOAJDiYaT5fPeUD17SzJ9//ZCf0ND0nPsNtfkuHUPcWMqik4H0hTMc9nNkfg+YKH01r1nOyGbC6s0yGjj/fJcO5TmvRxVnQtEe1kgx6cTTE9NutjclDHPPc8xJoaRbvMIE4iIiIiIiIiOlJw0YKIiIiIiIiIIomLFkREREREREQUSZHJtIhPb6takxjQfaV62bY1/ERBQu/Tcx/n7rsFgLJnz256n6wb6ND7+xq2yRo7XR/bBPrYNbFjfBzRBHMzLeIFz2vVGS5BRo8Nm3D6ymPMxqjhYdaTEaP2Gff1je35iTziQ3pP6UXND4r2zfUnqJqBfrmn1ub13yCaN+gx1+XktjzZ365qNt4zT7QTnjFXzshj1+/0DDDfkHczpjzzcfMT8r3jbyctVTU7e5tE2zdnr9q2QJ+AI5HQc/bqng7Rnv8Hve+ZMy8dipgn58HGZTuI6xr3cW7GBAA0bpOvzlK9DmSLD+nx0vKkfMJy2pMf5fA9v57rmb1Gk+/49DbV90Bezgn1MZ27MCder/panA+g6ViLqmlOVs9pSTgDOOkJfMm7kySATidTo7Ooz3HPkMyUKDbqN5D59Z2i7fsdxT2zW9F9c/IIFs6WHXv3VX3MweKdFkREREREREQUSVy0ICIiIiIiIqJI4qIFEREREREREUUSFy2IiIiIiIiIKJIiE8TZf7YM2koM+gL59OPcvJIgVf25TOAJ2yvIdqykH1fyHFsFeBb1sYfaZF+pToeclDwBhESHtaQcnL6w2SBlqtaYstPntgHYlF5/tU74V5DUNe7zqecCECvJvnKXDuUjGqvuJTok7y1f+2fRPvuyB1XNA3vminZDe6eq2Vqco/piRdl+Udujqub+0nLRrt+hx0X/3OpzVrHJ0+k8rG6HDvhKd8nnm5npVTX7m2UQ2ZZ901RNodys+krT5OQ+d4EOC9uwXwaDd9z7iKohOhTxwerzoTf7zg3iTOlxmO52wv769MWzJ+sP6W4ZvOk7tjtH2ngtNfq5iCba0mSP6rt7UL4YU54gzMATRJkxct4oWn092Zbql8fx1KSdCdhtH0jMOaeZKT0ndqXlnLjfCe8EgFIgz6nFE0Ra9NzP0BiXIaOBm6IPYKhdPn8NH8cPGu+0ICIiIiIiIqJI4qIFEREREREREUUSFy2IiIiIiIiIKJK4aEFEREREREREkRSZIM69J8hTiQ/omlK97nNzTsoZT0ifmxPkWapxs1i8YZ2ecM6ik3NSv0M/rm+BE25UrwNMGj1BZ/oEPMFntobHEU0Bk5YxPEFSv37j+eqBXWUnZNMXllnT+XhCPlWNZzyV6uXzp5M6XsgWC6qPqBa7z9JBYItulq/DN1xzu6r5cO/lol0s68Ez+8Rdqm/b5umi/T/ffLmqadrnjEvPlULKyTgrp3WNJ+MMcXeoeIblUKt8r/j9r89QNe5cX3+mDiI9aprue/TuRaJdl9RBaD3/N1ufFNE48gVYugLPuFPjp4ZjD03TgyzZp5+/VCfnunjBcz1dw3nHPONe1WQyqi/I5z2VRGPTGvME0DofGtvifaomBj2XJp0PgCc2bVM1d3UuFu1MXH9onJORA9gX1nlq/UbVd//AItHemp+uahLOwNtTaFQ1s9Ny4l6S1Im8TxT1AE45P3/Zc61cbJA/C4M4iYiIiIiIiOiIwUULIiIiIiIiIookLloQERERERERUSRFJtMicDa/eLb5IN6v+6yzj7bUpPMibEzuvYkVqq/VxAp6316qV/flZzh7f2OefftDsq+stxnBlJhNQc8sJi0Hp8qWARAvyPEa+PbLOsM1SOnx6x0/5uBrrCc3Jj4ozzE+fZqqKe3U2QFEtZi5Uu+frbv3SdG+e3CJqtndKyeSoSE9ncdi+jXf2C4nUjtDv+a78nKfa7BXB1bEB9z976rEuyd/qE2eU1Cn5+x4izxYzOifY3qL/Dm6V83UNS/eqvpe+8K/yecy+vn/b+tc1Uc0nnz5Tb4+V+DU1PAQeF7iKNXrMeUe23gOXktehZs75cu2ibXP0M+/RY9Xolol5sn37bTReQ0DzofNvNU1vsvQoi/YyTEzI/Mx2pL6Q2tLQgY21sf0xPlEvkP1JZ1B5Dt2T0nmxKRjOlPDPU7R6sGZ8QzYGOSbSJ/VWVD5NnlN0KAqDh3vtCAiIiIiIiKiSOKiBRERERERERFFEhctiIiIiIiIiCiSuGhBRERERERERJEUmSDO+JBsD87WyUGpbr3G4gZ22oQnbM85VNDgCRnplYlDhem6xsb08ye7ZWJLoUU/fcMW2S506GP3zpfhMNP1YWDiOhXJlnTQClEU2IY60U4M6rFZdkI13QAvAIjn5QC2vpQk7wk4bd/DnBpfkG7MOSfb5IkX2lnbKRG54kOecbFnj2jf17NA1TynY5Nor9y+UNUUi3rOCAL5Gi+VdE0sJsdcrD2vz7Esx25poMbLCffHjeuf3zrnGEvpObM1Myja3cf3qprNH1im+v76BvmzXX3ynaomXmAwNk0+N//Ok6OnuOGZAJBw5yzPnyfLjZ7Q+rgs9IVu+p6vGu9xpnkS6bfoLqKxCtwPfwBa4nLeSMGXLKtf5E3O44ol/fodLMtQz8GYL+RThmXG1YQI7C3qYyedQbQjrz9sFp2BXhfXYZluOGdXoN9kyp43jJTz5pT0XFCX0zVemx8C3mlBRERERERERJHERQsiIiIiIiIiiiQuWhARERERERFRJEUn08LZMhtk9F6kWtZYTEnvqbFJ51hFT03K2VfkefpCu977VLdF/gpLdXp/UnLA6SiNba3Iln17r4iiqTRd7sszVo+NICHHorunF4DaA29Knv3m47SVLlbWA7+YlmPcplOqhmjManjtrrjteNV33Su+K9r37pqnagYH9Ws1Hg9GbQOAtfKkfFNPIik7TaveG2tq+NkSCU9+lPP8bg4HAGza1ybas1p0psX6K2aovta7ZNZO5lS977f5/h2izeQoGm9lzzSS7JNzm2+PuJv7FCt7cpicOTIxqGtKnuvZctrZy9+n51o3n8KXceHmTsU9eVb9i5tVX91D+lhEtXJz1Mqea86yM+G67QOJOR8Ki1a/8BviBdFuTAypmrSpPpssyuxVfbuLcrzMSPepGjdTI/BkU2Ricr7zRdQ0xfQ1Qdn5/L0n8Pxu056DjTPeaUFEREREREREkcRFCyIiIiIiIiKKJC5aEBEREREREVEkcdGCiIiIiIiIiCIpMkGc+XYZ6mHqdFhJvFD9dL1BnE7YH5I6QMQ6aX9mUK/nmII+dn6WTCWK+Wra5LGSTTqcpe2RguojOmx4EvfyM6un8iT75PhxA7wAIEjJ8WM8AUBuOFl4MKfG8zgbk89nPT9HfEiGEhVmNqiayLyR0mGnbo8Ogoy3toj27Lt0MNa5V+4W7ZQn0LIWxnjGjqrxzKvOw2KeP4H4ju2GapZKOgrMDedMJvTPH3OO3TlQp2qmzdThnIMzpov2zdtPUjXpjRtVH9FYxZqaVJ8nxw9x59Kw0OqpGZRtXxCmyxdwHUvpzoKTjVm3Tz/OfT43mNNXk+r1zL2euZ7oUNikvBIbsvpz5ICTFukGTAJAZ9n99gSguyyv+5KeQTUUyOcve4Iwi070ZQZ6/u8u67nMPZYbugnoOdFzyYuYc2G83/MG0u4J5+4tZ0Q76V5gAyjV6+cbb7zTgoiIiIiIiIgiiYsWRERERERERBRJXLQgIiIiIiIiokiKzFbsQofMdIjF9H6ZWMHX5+xJT1Tfn+vlbOHxHceXl+GKD+oaZysQTpm3TdX0Pig3KuodRYCJ671HtqT3bBFNtvjMdtVXrJdroukevQfQ3dcaJD1jzB0MMc/+ek+fyrDwbfmv4e0iVpAPDNJ6HManTVN95c7O6genI17iT/eqvj1vOku021b3qZoHC43yMfs9++bLelwMDMr9siZefRDYoi+wQj6u5Jt7PZkWtTxfuSSfz1rPvOqcky15ztEzZ8eb5BvKrjs6VM0CbKx6jkS1MpmM6vNsd1c5F768ipSTe1GuHh2FclqPuboGnaNWTsn3Bt/zu3N22VPjbvf351eM8VqdqEYxTxaTK+75tJW3uq8MeSw34wEA6uJyTPlyL4rOIM8HOpsibvTzu48reUJxEs5FbjpWPS9jS0kH57TH96u+vJXnuSfQbzxDbb5PruOLd1oQERERERERUSRx0YKIiIiIiIiIIomLFkREREREREQUSVy0ICIiIiIiIqJImpIgTpPQT9va1i/aff065CQ5oIN7BhIyHCU2zRMuVKi+NmOc4E9b8KQL1RDE6clUQUnmnuD+zfNVzZKBB6oe25Z9SYJEEdCiQwDjRTmmyinPOAxkcE+Q8ARqui976wnw8uX/OOGcvrDOWKGG4CAnRMwbKjZ7hu5jECeNUftdMghr77PbVM3DeTmPfPrMn6ia3aVm1dcQk0l+rfF+VZMxMsDLFyiWckK/3KAuQIeXAUDcCeCL1RA65j4GAPptSrS7yg2q5q/dy1TfqY2bRfuz379M1Sgxz/VAwPmYatSug5o9OXoIargijzkvu5JnPvLNo66TZm1XfXfXyfcL97kAoJjSfa6YM+59gZ6Dbfp6oL76oYkOyAzJz38DnvfojBNOWa7xb/dNsbxod0LPNzFP8LQ6Tlwepz6mP7PmrX4jcB835HmzSMfkFzO4PysAdBblKCv43og83GsC35zsuUwYd7zTgoiIiIiIiIgiiYsWRERERERERBRJXLQgIiIiIiIiokjiogURERERERERRdKUBHHG53Wovt4+mVbZ1DjoeaQO5wwSTqhXXCeBuEErsYQO/goGnF+F1UFGNuUJHnHCOcv1+th2vgxaCfanVU1NfAGERBFQmtGo+twhFKQ8QZhFJ0i3oF/j5Tp3bdUTMuYZGvFC9ZBPd93WBL5wISek1xPoadOeBF6iMSo/8oRo973sbFXTlugT7XMzu1XNnwf13yXu7V8k2hc0r1Y1bqhm0RMMlnfSb32hX7X8VSTuS9F1hpgbAgYAbWZAtI9O7lM1SVNSfdPj8vfWuq6GMF6iQxDUOD+4Ic9xndGHYg1ple5xYp4Q+XOmPan6VsWPqX5w9Vy6zzjzuBvMCQBDTdXDQokORdLo15gbKu2bW3yPe3xwTg3PJ48d94RM7y3Ka+V6zyCfltDh2LuLMvizp6Q/D5ecxNvAM+7q4vLn3V/W1+7AHk+f5AZhA0C5aeKTOHmnBRERERERERFFEhctiIiIiIiIiCiSuGhBRERERERERJE0JZkW2y+ep/oydd2i3dev9+s0d+v9QZl98kfomVk9LyLZoPcQFQK598f261+NadD7Y2N75L6eRL9eB0rMk8+X3zHGTAuiiLLJ6uufsbInL8LJafHlXriZEt5jl2qo8eRluHx5Fep8PLkXpRY9prkiTONl/sfuVH1PvmqWaH+vpPemvq7lcdXn5jy4+RUA0FWWG+d7gjpVsygp9736sil8WRhlZ5+t7/ndvcC9gb4e6A/kmAtsbSPuzLTcL9z0w5XVHxRM/F5deuYqN9SaaeE8Tm8bR8yTc1H1+dN6zhoK9DkFdXLcDU7XgRWpXnmsoudytpxyszl8WVGejKuMHOdBPq8PTnQAple+t/vSigYCOaiKnlCW9SU98Db0Txft+oQeiLPSvaLt5lcAQDqmP0e6+sp6vosZOYYa40OqZsjIMe3LtNg7JLMxdmVaVM2Wkn5vaIrLsej7vU3GRS+vq4mIiIiIiIgokrhoQURERERERESRxEULIiIiIiIiIookLloQERERERERUSRNSRBn2+M6QKTroqJonzZni6p54Oq5VY/dEOh1mP49MlRsqFuHnMAJBUr06ZCRkmeJp9wkA7piRU+4UEzGwbTfp4+jmOqBgAAAWz1ckGgq1JA3BOPk29XysveFdcIT9GXjsi7mGStullCsWEugp453CuL6zYErwjSR3JCt5entquanvYtV3+l1G0X7tv7lqubo9E7RPrdOz8cDzlBZW5yuatzQTx83dBPQAZ5x6HGZMfKaYcDqREA3UBQAPt95YtVzIhpP+RoC4sdTfEiOKRvTs1F3WYfr2rgcZyVdglSv7tPHcdt6zg48IaNIOgGADOKkgxD0Dxz0YzKeOerxwhzV95Y5t4n26vz8qsf+xbaTVV9Ho/zSiUtnPKhqfPOmOyfu9wRvuyGjZU849bUzbxHtX/aepGp8ylaO4V5POHd928H//g8Wr6uJiIiIiIiIKJK4aEFEREREREREkcRFCyIiIiIiIiKKpCnJtEj8+V7VN+PPsn3Xf56lapLH9qi+Wc1yg11LalDVlKbLDXZbulpVTdf+BvkYvV0IiS5PzsWsgminlutzTMblxv1pD+xXNWXV48H8CjqMuPtaPVvXUU47uRMlT+6EE3Th7tcFAOMZGm6Xez6AzrCID+mRWE7LBwYpvdab6CuqPqKJtHKvzKt4Vv0GVTMQ6L30W0py/ju9bn3V57qxR+97XZ6RGRrPz+i576GCHnQx540g8Oy7zcTk3tik783D0W/15UxHXOdnXfKpfxPtWbhTHyzmnHdQ0wxN5FVo1K/xZL+uSzhBMWVPfpObD+Gb1/RjqtcAQGxQnmdmn55Yi05MjC9jys2riHsyp1JdvJ6l8WWXLRDtL+4/XdX0leWcWIZ+/V6/5gWqb/rHZYbDhpfpvCQ3oy3Zo4+9DzIv4/5GnSkVK3iyEeVHTSQ8cS+Zvc6Y8sS/3f7AqaK954xpqubs969VffvL8kPxhqGZqiYerz5PHyreaUFEREREREREkcRFCyIiIiIiIiKKJC5aEBEREREREVEkcdGCiIiIiIiIiCJpSoI4YTzpIE7I5KIPrKjpUIULny3aq89LqpqmE/aJ9uJp+1RNR4cMMauLF1SNz33754t2Q1I/bs+ADPk0vTocTGHoJh1Gio36rcTNzjNl/ZpODMoiG/O8N7gpm56lVut9mBOymdchQUFSHqxYr3+OmHPeQVw/WaElpfp0BCLR+Fl3/zzRfqh9gap5tHeO6rupXwZxzajrUzWpmEwUCzyJXr3ljGhfUPewqulI6GBs923AF92VryE50A1Qm+8J3bzbExY267Oe4E2XnfhAMTpyBJ6Xcymj+4oN8jVdaNFzZnq/Z7Jz9M+U81i5TQdF59ofUX3fqTtHnqNnPiw6IfWBvuRGzHm6Up0+52Kj/tlmLJ4rOx56XB+c6AB2ndki2sfWbVM1a/JyTjwuqUOWX7HwQdV32woZxLmkto+okePObLHT9JdenJ7W43VzqVO0O5Kdqubty7pF++doP/gTrIJ3WhARERERERFRJHHRgoiIiIiIiIgiiYsWRERERERERBRJU5Np4clrMAl5KrZUqulQqT/cI9qL/1D9Mf2evg3z5f7goaP0XtjuJXqXes9Rsl1elFc19Q2yr2X31uonSXQY8eVFxIpynJdTeo3UzbBIDOpxHyTk49wcilofB09MTDyv9zOqY9eSQePBVBqaSEe9d6Vor1hyjKrZfZ7OtBiYLcfc1ul67JYbZF+iWWc19X6gSbQv2aBzXQ5bzJSicTR9tc6Nqdtfp/qsJy9JPW6HvsZ0JbpllkzD7hZVc+zmt6u+hffIMIrM7l5VU07LgA7rzrMATCmoWuP9Wdds1H1ENZq1qke033fbq1VNrF++fr8RO1fV1G/XITRzUUMWUsx53FizkczY7icwbiZcXP8cdkhez85YsUfVHPPdf1J9LWtlOz9Dj9/GbfLnbcFKVXOoeKcFEREREREREUUSFy2IiIiIiIiIKJK4aEFEREREREREkcRFCyIiIiIiIiKKJGMPInDKGLMHwKaJOx2KuIXW2vapPgnSODaPeBybEcRxecTjuIwojs0jHsdmRHFsHvEOODYPatGCiIiIiIiIiGiycHsIEREREREREUUSFy2IiIiIiIiIKJK4aEFEREREREREkcRFCyIiIiIiIiKKJC5aEBEREREREVEkcdGCiIiIiIiIiCKJixZEREREREREFElctCAiIiIiIiKiSDryFi2MuQDG/GICjrsVxpx3gH87D8Y8Mu7PeSiMeQ+M+dhUnwZNLZMzd5icecMB/m2JyZm+ST6lg2Zy5kSTM3dNwHFXmpy56gD/tszkTNd4P+ehMDnzapMz35rq86DDh8mZjSZnXjiBx7/A5CZgvj3487AmZ5aO07GuNznz1vE4FtEh4fVsiNezNEk4Z47pWOM2ZybG4yCKMRsBzAJQAlAG8CiA7wD4CqwNJuQ5a/dxAP8MYxYgPK9hDQAGANhK+yJYe/u4PKO1twI4ftQaY7YCuKpSO7L/dQBeCOCjANbCWjMu5wR8CcBaGPMZWLtvnI5Jk8BZSKgHMIRwnAHAP9qs/f54PI/N2vUAGqucyx0Avmaz9ltO//MAfAzA+QCKABbbrN04Hufl8TEA15mciQPoHtHv/m6utln7o/F4Qpu1awC0jlZjcmYlgM/ZrP2e038+gA8CuBjAIID5Nmu3jsNp/RTAf5icWW6z9olxOB5NEpMzzwXw3wjniTKAxwC822bt3VN6YocunG8rTM5cBiAHYAmAAoAHEY7LjVNydmNzHYBVJme+YbO2MNUnQxOM17MSr2cpAjhnHplz5sQsWoQuhbW3wJgWAOcCuAHAmQDe6K02Jg5ry95/Gy/GnA6gBdaurPQ0jvg3C+BkWPvkhJ6DPqcErC2NUnExgPFfdbN2AMb8EcA/APifcT8+TRibtU+9bk3ObARwjc3aWybzHEzOVLtL62IAv52E85gH4LkAXm2ztowRY9rkwgsnm3UunCb+nKbkd2OzNjA582MAbwbw3vE+Pk0MkzPNAH4N4G0AfgwgBeDvEC64HRZMziRsVs5jJhfOtzYbzreVv9p8B8DLAfwZ4Vi9AMBUf/CrmcmZuM3aHSZnHgfwUoQLhfTMx+vZ2s6J17M04ThnHrlz5kQuWoSs7QZwM4zZCWAljPk0rF0NY76F8K+MCxFOApfBmNsB/CeAVwNIA/g5gH+BtYMwZgaAbyH8gBIAeATAubA2gDHvA/BOAM0AtgN4O6z9k+dsLgJw25h/FmNmVs7h7Mo5rIa1zxtRcRqM+V8ACxB+KHkDrB2CMS8E8DVYu6hynK0IJ73XAVgOY24C0AHgdzCmDODDsPZ6GBNH+Jfqt1V+XsA89Vf25wO4F+FfbK8GUFd5znfC2h4YsxTAWgBvQbhKBwDXwdrPjDjfWwFcBb7JP6OZnKkH8DUAFwKIA1gD4GKbtXsrJYtNztwJ4EQAfwPw9zZr91feMNfabPjXkMpdFX9B+JeSUwDcDOAsAM82OfM5hHdcvLtyzIsRvrb+Wmk/YnLGAni9zdqbKreKvRfANAC3A3hb5Y0tgfDOjHcCeA+Apsq5v99mvX/VugDA3TZrxzRZmZxpAPD1ynFiAJ4A8GKbtZ2VkqMqd0wcB+AOAFfarO00OXMMgNU2axOV46wE8EeEv+OTAXwfwOkAvmZy5ksAvmyz9toRv5tXjvjdPFH53Vxls/YXJmf+qfKztyJ8v3qbzdpdJmcyCN8z31H53TUA+AqAD9qsHf6L2q0APgcuWhxOlgGAzdobK+1BhK8lAEBl+9Y1AFYifK/vAvB2m7W/q/x7C4DrEb6uAgDfBJC1WVs2OXMUgK8ifE1aAH8A8E82a9XWpspr+ncA/t1m7Q9NznQA+F8AzwPQB+AzNms/W6n9CIATAOQRXoi8B+E4Hcmdb08BsMFmn5qbewHcNOL5P4JwnOUBvAzAZoTvF/dU/n208zkD4Zx6bOX3dxOA9/j+qlP5C92NAF5ns/YvlZ/7fwE8C8AeAB+yWfvjSu234F6nALcgHGcvARctjiy8nuX1LEUB50wcmXPm5GVaWLsKwFaEq2HD/h7hm3oTwg8E/4XwxXgKgKUA5gL4cKX22srj2xHeqvd+ABbGLEd4K83psLYJ4YeGjQc4ixMRfigZq38FsL5yDrMBfMj591cDeBHC23iehXDV90Bei/AF2gJrr0A4OV0Eaxth7fWVmrMAPAFrOxG+6FD590ZYezfCQXkVgPMAHIXwA+ANzvM8D+Hv8iIAH3T2KT6GcGDSM9sbEW6VmAdgOoC3I3yTG/b3AJ1r1Z0AACAASURBVF6PcFw1IHwzPZB/APAmhBdUVwJYAeCtNmsbhxcsKnc/tNqsfQjDr1vg+ErNTSZnLkB4e+grEY7x7Qg/5I90GYDTADy7Uve6A5zPoY7paxAu3s4FMAPhe8nIN+2/r/yccxAuIrxrlGNdVTnPJgD/COBuhHfBNA4vWJicWQSgzmbto3j6d7O8UvMLkzMXI3xfeVnlnPYCENtLAFyK8D3yDABXVM5v2GMAjjE5k67x56eptwZA2eTMt03OXGRyZpqn5kyEr/MZCG+J/brJmeFbq7+N8Nb1pQBORbgAd03l3wyATyD8EHEsgPkAPuIe3OTMaQgv+t5RufiKAfgVwltR5wJ4AYB3m5y5cMTDLkN4AdIKPX4BPTbvQ/ja/IzJmeebnPFtPXspgB9WjnkzwgU41HA+ZQD/Uvn9nFX597d7fs4LEV58vaJy8dUA4P8A/ADATITj6QsmZ0be/u5epwCcO49svJ518XqWJhPnzKcdUXPmxN9pIW0H0Dai/UtY+zcAgDFDCG9rPgnW7q/0fRzhL+bfEf71dQ6AhZVb3m6v1JQRrmIfB2P2wI66z6cV4UrVWBURvpkugLXroFe5/wfW7qyc168RTlYHcgNs1X3sL8Hot5FfCeBTsHZD5TnfD+A+GHP1iJocrB0A8CCM+TbCF9itlX/rRZV9+fSMUET4xrTUZu3DAO5x/v3rNmvXAoDJmZ8gfAM/kG/YrH1suGFy3i2pL0G4+nwgVyK8K+OByjH+H4DOymLHzkrNJyt3O3SanPkswtfttzzHagWwbZTnqqaI8KLtKJu1qxEuNIz0VZu16yrn+VM8vdDg87WRWRKj/G6qjemvVBZ8YHLm3wDsNzkzG+FfCwDgE5VV/67KHS5X4OmFjeH3txYAu0d5HooIm7U9lb9kvA/hX3hmm5z5LYA326zdVSnbZLP2qwBgcubbAL4AYFblDp2LEC4SDgLoNznzGYR/kfyyzdonAQzfIr7H5Mz1ALLOKfwdwr9G/YPN2r9U+k4H0G6z9qOV9nqTM19F+OHkD5W+FTZrh2/1HvT8aGK+tVm73uTMeQgXRX8MoMnkzA8B/LPN2uG/uN5hs/a3lZ/zuwCG79wa9Xxs1t474nk3mpz5MsK/8oz8q+urALwV4V1mD1f6LgGw0WbtNyvt+0zO3IRwoXQ4bPCXNlu5Tnl6sZdzJ/F69mm8nqVJwznzyJ0zJ3vRYi6A/SPaW0b8/3aEfw2+F08thsEgvJ0dCIM8PgLgj5V//wqs/SSsfRLGvLvyb8fDmD8AeA+s3e55/k6EKz/VGbMEwEOVVgnWtgL4JMJb0/5UmVy+BGuvG/GonSP+/wDkhObaMsq/DbsYB/4LMxCuBG4a0d6EcG9X+wGeZxPCW/uHNeHpD0L0DGB0GOUyhB/2OwD8uLIX8LsItxQM76dzX7ejhW/W+rr9xij/3gHgzuFGZQLqRPj+MHwu7uu24wDHqnlMV+4+GBnStQTh1pDZAH5aWcX+DsJb3Yb3I0/E7+YLo/x7B8K9iwAAm7VdJmd6EP5uhsfqaL+b4d/FyNcARVxlIfANwFO3nH4P4cXDFZWSnSNqByoLYo0I55gkgB0jFsliqLxGTM7MBPBZhBdZTZV/G976NOytAG4bcfEFhLd2dhj5DTlxDH+4ClV7vauxWdmr++rKuZ0O4EcAPoDwg5z4ORGOt0xly9io52NyZhnC232fjfA6IoHwdvOR3g3gOyMuvoZ/zjOd4yYQvkeO9nNy7iRezz6N17M0qThnHplz5uQtWoShQXPx9K0iwNPJxkB4G/QggONhrf7LqbW9CG+puxbGHA/gLzDmblj7J1j7AwA/gDHNAL6M8LY8361sD6GyF6oq6/nmBGt7EN5O8y8w5sTKOayCtWPZV2hHbRszF0AbrH3wAPVAuNK/cER7AcJb2/fg6Rf+fDy9arig8phhxyK8dYieIdwwyhE+AuAjJmcWA/g9wlu1vj2WpxitXVkYOAfh7WG+esB53ZqcaUJ4K+jIcT8fT98m575uR3oIwGtqOvEw98L3u/kwgA+bnFmCcEX8Efhv3av6FKO1K5kUz0G4Iu2rB/TvpgXhVhz3d7Ou8v99Y/rxsWZ80NSzWft4ZV/oP9ZQvgVh+NgMN9Sr4hMIX2cn2azdZ3LmclRuHx3hrQDeZ3LmMzZr/2XEcTfYrD16tFOtcm6jzrc2a+82OfMzhPt8q6l2Pl8EcD+AK2zW9pqceTeeHmfDXoXwFuFtNmuH/5q0BeHF54tGeW7fz8m580jG61n1DKO2eT1LE4hzptczcs6c+EwLY5phzCUI99x8D1as2Dwt/OqorwL4TCUgKHyjM5X9N8ZcAmOWwhgDoAfhfpwyjFkOY86HMWmEt6EM4umvOHT9FuHtL2P9WS6FMUdVzqH7qXMYH7sQ/uV3mHuL/W6Eex5H1twI4D0wZhGMaUK4h+hG52u4PgRj6iqT0usRrtINOxej38ZPzwAmZ843OXNCZY9bD8LbQifqdXsugPts1vYDTy2i7HNqbgRwtcmZkyqLHJ8AcLuVX/v5byZnWk3OLEAYSnagryr9I4DTTc6kxnLyJmdeaHLmuBG/m+GvtRsP7u/mfAB3VW5JHF5E6Yb+3by58t8rg/CC9c82a0eupr/P5ExLJR/jn8ExfVgzOXOMyZlrK9ujYHJmPsK/Fq0c/ZGAzdodCMfAp03ONJuciZmcOcrkzPA814QwgKvL5MxchPvYXb0AXgzgeSZnPlnpWwWgx+TM+0zO1JmciVdek6cfxI8m5luTM881OfPmyl+yhv869tJafs4azqcJ4fjtqxz3bZ5jbEe4b/edJmeG9+7+GsAykzP/YHImWfnf6SZnjq1yPhxnRyJez9aK17M0YThnHrlz5kQuWvwKxvQiXJX5AMLbUPxfD/W09yFcRV0JY3oQJo4ur/zb0ZV2H8Lwvy9UvgM6jfA2t70Ib5OZiTDUSLP2PgDdMObMMf5MyxHeut2H8FsWboC1d4z+kJp9HEAOxnRVbg+UX4sYrsx/AsBdlZpnI5wUf4Twdp/1CAeSGxR4R+Xf/gjgE7A2vPXcmDqEg+4743T+FF0dAH6G8A3qEYTj6MZRH1G7/wFwhcmZLhPu/fN9nWcWwA8qNS+3Wft7hEGcPwewA+FfTK50HvMrAA8gXAn+Ofx5FrBZux3h6//SMZ7/XAC/RDh2VlfO/cdjPJbrMwBeZ3Km0+TMf8P/u/kwgJ9UfjcvtVn7a4Tj/GaEE8Zs6L+y/QbhivU9AH6CSp6FCUOmXoPwG0Xo8NGLMDTsLpMz/QgvSFYj/EtsLV6H8DbqRxHeXvpThPvlgfD279MQfij5DcL3AaWSkfIiABeZnPmPymLjcODrBoTz69cQZqXUxGbD+dbknppvuxBecD1scqYP4R1fP0cYklbtWNXO570I7+7qxdPzou84mxFehL3P5Mw1Nmt7EWb4vBbheNuJcKHwgEG2JmfmIExsH/+vbqSo4vXsweH1LE0kzpnVj/WMnDONtdXuVnmGMeYChF8hdflUn8oBGZNC+GJYBPtU2MrBHiP8iihrvWmAMOZfALTDWv+ESDQGJmfWALjEZu2aMT5++CtPF9vsqCFkIx9zIsLAzOeM5Tkni8mZdQBeZLN2/RgfP/yVp/Odu1KG//1VAC61WTvavmGiSWPCbwp6u81GeL49SCZnPg1gnc3a0bJpiCYer2eH/53Xs/SMwDmzyrGOuEWLw4ExswFcBmu/fAjHGP1NnmicVT5Uv8tm7X8dwjEOetHicGByph7hd31fV7X4wMcYddGCiIgoUng9S0TjZLK/PYRqEX7N1Njf4ImmgM3aPMLbxMhhs3YAYWI8ERHRkYHXs0Q0TninBRERERERERFF0sR/ewgRERERERER0Rgc1PaQlEnbDBom6lzGxCTlj1Bs1QGmNu526OMk+wPRNsXavvnJJuXBiw2edSBnF16sqEvi+/prer6p1IvOvdba9qk+D9ImdWz6dpWO0w1bJpnUh14s20NDusbE9QnYQJ5oXbqgazbIGlvwDM7DAMdmNEVxzqTJw3EZXYfD2DQJfYlemCGvcQP3+hZAXE91Sqyk+9xjWc8nhEBPv0rSiduMdw2omqm+y5tjM7oOh7FJE2e0sXlQixYZNOBM84LxOatxkpgxS7R3XrZE1QxNkx9MjGc9Ys6d8k01uaOrpucvzmmVz/+celVTTsl2/U79Zt32zRU1Pd9UusX+dNNUnwP5TebY9F1I2cBzAWIDp139IiUxq0P1lb4kFwLXbJytalKN+iqtOCivrk5arLMri1fJmtKWGvItY56rRPdnBQATq14zThduHJvRFMU5kyYPx2V0HQ5jM96mr9s3velo0S606jmkcZNzzeuZn+v36vko3yLnrMFZ+i8Ug3PkBbQp65rZf5PP1/yrB1VNkM+rvsnEsRldh8PYpIkz2tjk9hAiIiIiIiIiiiQuWhARERERERFRJHHRgoiIiIiIiIgi6aAyLaLo6N/sE+26AR1Yce9jMskvVqcTiPY8V+6vWzxNB2O+dKbel/fIwFzR3rjmRFXT1izzMl6x4H59jtcsFO3Oc/arGqJxZ5z9qDVkLNiSJ8FrrE+flqFi5vv6+T+84GbR3jm/VdUkjT6nwFmTvbS+R9Vc+p1LZMfzD3iqIw5cW0gvrKyLZTL6UENDzmP4FdREREei8nmnifbWdwypmlRCXhtePP8JVfNEr8x6KwX675Ont+lt4/sKjaLd7wayAZiT7hbtn609WdXseYW8rth52bGqZulV+jqYiGg0vNOCiIiIiIiIiCKJixZEREREREREFElctCAiIiIiIiKiSDrsMy3+cPMZol1cNqhq6tpkX2FTo6rpT8jvrF796FJV82DmKNUXK8q9e/Xb9HdWd54t20mj98Svul9+9/bRuEvVEI27ccpQGLrodNW36VXy2Nmzb1Y1b2jeLdqL/3C1qrlzhhwbL2p4VNV8d/9Zqu+Ts+8W7bv19mCs3TFTtP+0+ceq5lO7ZdDFH373bFUz97aC6kvecq9oT/X30hMRUXTlZyRFO5UYUDXdnQ2ifU/9AlVzfOtO0b5/31xV82DXPNWXSRRFe2a6V9X8bvNxoj3UqbOaYvUyYyroT6oaIqKDxTstiIiIiIiIiCiSuGhBRERERERERJHERQsiIiIiIiIiiiQuWhARERERERFRJB32QZzlOhn2t3j2XlVTLMdFe8tMHQpUKsqaWEoHFFrPEk/g1BUbdRBnqSCPfUx6h6qJDdawfmT0sccrSJHoQPa8VYZcvuWdOlDz3PobVF/KyHDbbWUdgPvHATkWrzx1laopBvJt6oObLtc15+kxldzujGlTVDXLO3aJ9u/7l6maN02/Q7Sv+YfbVU1wlR6bX9xznmhveaMOTCs/8oTqIyKiI085KeeRwOp5xcTlvLpxU7uqmVUvAzRfO/9eVZOO6flwdb8M7Lx373xV07WrSfXpk5TNmq5viYiq4DsJEREREREREUUSFy2IiIiIiIiIKJK4aEFEREREREREkXTYZ1qU6uX+vkWN+1XNxr420U6kyvo4Tu6EZyshbJ1+XMNauSd/cKbOmLj8uAdFO2lKqia93/OERJOs9zXPUX03v/860X6y2KxqHi7MqXrslNHjx/XKlntU34y43Hv7wqbVquaN73+X6hsIZD7G/rLei/uxhb8Q7TXFmarmkUKHaBdtXNX0B2nV94o2+bPs/9njqua7550p2qUdO1UNERE98/XNk39HTBh9PWncPzV6/vR41+qjRPuRmbNVjfVc5PZ31smOoj64ych53BZ0jS3LY9tMoGqIiA4W77QgIiIiIiIiokjiogURERERERERRRIXLYiIiIiIiIgokrhoQURERERERESRdNgHccbzct2lv5RSNfv660W70JlRNRec9rBo32KO0U82pAP4+o6SoZo/vfBzqua2fnmsR/PzVE2xRQcuEU22Sz7wF9XXG8gxtrPUomrqY0Oqzw3eLEMHfxWtfAtaV2xXNY8UZNjtxfVbVM2HXn+j6ru5f5ZoZ2JFVbNycIloH53WQZhd5QbRzgdJVTM93qf61hZk+NmJGX3eHb/oFe3NZ6oSIiI6AvQtkdeT7QkdXm2dS8WYJ1gezmVwf3edLtmkw6PNQjmPm7SeM23J+VtnXF+7WifAM96sj0NEdLB4pwURERERERERRRIXLYiIiIiIiIgokrhoQURERERERESRdNhnWpQa5X6+mZleVbMh2Vb1OPftni/azU2DqqZ+RkH1lZ39/v+x+VJV056R+93bUv2qJqYPTTTpFqb3qr5d5UbRbk/0qJr+QO+PLVidAeOKIRBtX+5E3MqaJ4r6uTYVZqi+E+pkhkQ+0Hk3bQk5Nn15M25Na3xA1eStzrnIGPmzPD7UoWq+MO+von357ItVTWnnLtVHRETPLIkWeSGYinvyKpwICVvWf3s0cTlnphv0BWYQ1/NhU6uc23r2N6ga99gwOqsKZdk3rcVzzdvUpM+pV1+/ExEN450WRERERERERBRJXLQgIiIiIiIiokjiogURERERERERRRIXLYiIiIiIiIgokg77IM66bfJHuHvPAlVTn5SBeMuXbVM1W7taRXtOiw4bnJbWAXwXz3hYtO/pXaxqduZl4FDMBKom0e8JMyKaYKXznyXaR6fuVjVFJ1Cz7Amd7A3qVN/0uAywLEO/xotWjt+CVSUqrNPnu2vPUH03nLxetPcFjarG9fUvv0T1zb58k2h/ZNHNqubm7lNV3zF120W7wehQtT8OyqCzLX9/lKqZcz2DOImInunq64dE2zMdIpUpiXa5rOfVWEw+Mt+jw6uTnqv/3m45jyec5wKAwHk+q7OzAef59+5uViXtZqfngUREB8Y7LYiIiIiIiIgokrhoQURERERERESRxEULIiIiIiIiIookLloQERERERERUSQd9kGcjdtk4M+cBh2guXdQBvDNqdc1nzz1Z6J968ByVfPtz1+s+h64ulu0u4o6kLApKcOV2lN9qqZ+ly9yyWE8a0xWh/sR1Wr3s2VA1/TYkKpZV5wm2jPj+vUbT+jX776yHHdxTwBt0jihYla/xgNnbbUnyKiaL5zyfdXXVa5Xfa7WuAzXvena/1Y1W0oyROz2gWWq5oLm1arPDdzd7vweASDuRK1lXrBHn+T1uouIiJ5ZZn5KzscXfGmVqrll17GiXQjiqqZvSB6nMKjDs4vTdMhmMiWvJzumd6uaYiDn4z1dOuC60QkUrftuq6op9+jrcKLIMjV8WYKV13MmoT9i27Lzmc3W8NnPY9c7z1Z99bvkNWfTj1aqGvecbEm/D4yVSaacY3tSesf48w7jnRZEREREREREFElctCAiIiIiIiKiSOKiBRERERERERFFUnQzLXz7hzx7Ydoelvvi9uUbqh76bw8frfpak4OifUHrw6qmZaPen/PHDceI9pnzNqmaDT3TRfuF0x5VNSu2FPwnO4KJ6d+J1TEBRDUbnClfQPuCtKppjuVFuy2ux8G+QOdHLEruFe11xXZV0xST4y4Pvfc2DnmOeatr9hSbVZ97bDe/AgAGnJ/3//p1lo37fB3JLlVz474zVd+1s24RbV/GxuNDc0S7WNL7k4nGlTu3HuIe09HE2/WY33y1nH9jz+lUNXM/KM8pWP24qpnIvbmT+TsiGha/+zHR9s01l8yW16YP9c1TNet75TXnYJOeM1tnDaq+zn6ZyVaf1NeljU5G29xGnXuxva9FtFtu36hqxnG0Ek28GuYAlelQrP65zie+7CjVt+bNM0X7TRf+SdW8f8YTon3hj05RNTXNkzF9Hep+/vQdZ6w/78HgnRZEREREREREFElctCAiIiIiIiKiSOKiBRERERERERFFEhctiIiIiIiIiCiSIhzE6VlPsWXVVZgug4N2dOrHnbvoSdHuOEEHB/3ub6eK9qqjF6ia/Vfq4JFZjTLcr2x1WGZrWgceuVJ7+kXbl69pA4aB0fha9sm1ov2PG96larrPlEGctk+/bUy/Twf33PPRL4r2w0M65HNmvFe0M0aHfBat83xGj47p8T7V5ypDj836mAwVy8T08z+Rl2GZp2c2q5qvv+Nlqu+l58j3lPR+fU7zfrpRtGdu04GDRONqnEIl3ZDNtdcuVTVXXXSb6tu8TgaKHde+S9Xc94H5or34Cv38NQWK1RjoPaYaonFmh+R89NfuZaqmIy2vX3flm1TNxp0yiPOsJRtUzRtn3a76smsvE+0122epmrZWOdfObuxVNft6ZSB+wy79/ETPNCqI0hNoGZxzkmgnd+iw3aC5TvU1bpZz2ZkNT6qaVUPy+nXddWepmqP+dYXq0yegP2vX8qUPe98in69wkf6s3fEy/UUUB4N3WhARERERERFRJHHRgoiIiIiIiIgiiYsWRERERERERBRJ0c20qGUDDYChVvkjpFP9qmZTX5tonzxtm6p5YK9cv9k7Te8TfP0pK1XfY32zRfu5rXqfUeDkXMQ9iRVDsxtFO/mQKoGJ6f25Nf6aiLzKe/eJ9szP36lqZn6++nHsWSdXrWmND6i+pHH2pbv5FQDKzngpQ+8T9OVVlG31Ndm4k4+RgS9TQz5fu2ccFhv0OS3M6t+lq4Zd+USTLn78ctHu/JR+pb5xkdwb+4udSVXz7Qeeo/pMXOZF3L91nqp54dInRPuWG/X7y+IrHlR9yhizKeLTpol25w/aVM3iZhlSs++czjE9F9HBmJOSe+AXNTSomtRCOV5XbdYZbQ/vfrXqK5XlnHnCvO2qJnDm2uVNOpOmZygjO5gRQ1Hlyz3yqeE1XLjw2aK98XJ9DTp7kbzmnvY6ncdW/w3d950FXxNt93MloK+Dn7zyi6pmzavlZ+SXfflfVc30R/V8v+sKmW1361lfUDW/7d8p2p/7/MtVjcr58ORnjIZ3WhARERERERFRJHHRgoiIiIiIiIgiiYsWRERERERERBRJXLQgIiIiIiIiokiKcBBnbcE9A+1y3WVGow7i3LBnumjPqe9RNcdduEa0EzGdcLli32LV54b93bj1dFVz4jQZZnRu8xOqxg0U1ZFmgA0YZkTj7BBDcYYld+gQuocKeaenUdW4ClYHWqrngj7HAZvWdU7Ipy+Ysz+Qj5ub0D+HG8TZ70m/NTWMTZPQb7e2LH8WE9c/vy0xrvOIU0s42BjD7cypx4v2+lc1q5orX3Lb/2/v3mPkOss7jr/nzH1mvff1eje+xZdN7FxsYqdx7RADSRonoiI0IAXErS2NWkTUUorSIhWJv0pLqVBpSQlCqrgIKtIqCU25FBChTdKYuLET23F8wff4uuu9eHdndmbO6R9UtM/7O/ZsDCFn4+/nv+fVM2fOrOfMe/b1vL819bePr5aev3jiraauzNe5d6B/VMcqdv6difS62H3OBlzff/2PpKe+014rj/7pbdLTtvOkjFWX9Zn64Pukxd2w/LCph8qHpac3Z8PSnix26oGmdQi4IO+6f1/vk9LyvYnrTB0lzGv+NdXToddmo6lzTca7782GOtceGbchtcWMhldv7t9n6mfWrZWeeNsuGQNmzb93TZL0lwoC73q5xHve+m+sl7Gwbufknm16joXHbKjzv+34Z+nZW9fr9SObbHDutd/SPyjx8T4bjv3l8V7p+c2KDcTf9WEN1Ezy6ZHlpr73Q38sPcV/3Wrq+U7D6P2Q6+a5VxZgzTctAAAAAABAKrFoAQAAAAAAUolFCwAAAAAAkErpzbSYpel+u4dovFqUnjiy+wS3Hl8sPR+75t9N/bl9b5Keh679qox96ewtpv7O1jXSs3TdiH3+yWXSM91jzzFx93/S/izgFzGL/XxBLm/quD6jTXXNXZiI7OOSMiV8meDS3uNhwrWRcd6e/4RjR5E9p3qsH4m5wP6Mds90SU/l0IQeO/FMPV4uAfkVcM5dUl5FOG+ejO35zNUydv/GH5j6keM6Z31l502mzuX1fblgybCp2/L6uVDK6n73pAwL38I2m4Xx3TOaqXFjl82ZeOKhh6Tn3QffLGONqr0yP9y/W3qO1Oy+Y/8zwDnnztbtLB0sGpQet1eHgAupbbH75DcVn5Oex8Zs4tmqysvSU8rYa/Ho6FXSMzZalrGeHpvT0pXXUJaJor3HPj2lnzt39Ni8isfXam5OzzYZAmbvErMoXNz6cbW7NJuw8O1nTV16UfOSBh+2+Qz+deicc5/sf8Ib0evw/iWbZGz67itM/Zf9j0vPNybsHHR7+ZD07Jix12I5rEnPsqye9/evtdd50W2VnuBGm7fzO197THq+eHSRqcNbybQAAAAAAACvAyxaAAAAAACAVGLRAgAAAAAApBKLFgAAAAAAIJXmfBBnbPMrXSUhDGy6YIOL5pWq0nNsxgZvje3tlp7jV3fK2C3tL5l663NvkJ4P3mmDV74+/OvSM3aVDV7rkw53SeFswC8sDFr3NDXcqOmtieaC1iGTEp7pnGu61s8/mwDPnGsdwDQZ52WsI2PDyHZUNcg3OKKhTCKT0TGCNy8/gX0/h4WCtERVO0eNv3uD9Jz+NVtnB6akp71wXsa+sOtmU+dyel30dtlg2WL20t6njUj/XyTyJ+0E1dDemoSBfi5sG7XX4b3nF0jPqYSQwCMn7dweuWukZ23XMVMfntL7gaG206auD3ZID0GceCVObLLv+2ZCwHRvzl6bSSGxaytHTD0+oAH13x/XkN4b5h9teY5L59kA3ueHEwJoPeMrdKyn5aOAC8teoe+7gx9Yaur5mzWkdm2P/Wz/7MCz0rO99oyM/fZnPmLqd973A+n5eK/9ffAtH/ig9Lzx94dMXchpWHVvwsTx48/boOlHJvXPNawunDD1VMKvjFflxk1dTejpzeixD37K/t6aG9N5fNf9n9eDeeoLnzL1l92iC3Qm45sWAAAAAAAglVi0AAAAAAAAqcSiBQAAAAAASCUWLQAAAAAAQCrN+SDO7GobKjJY6qVlkgAAELtJREFUGZOeQsaGiN3W/6L03NG2y9QHNmkUZj3WH9c/HN5s6vHleo5+8OaCgp5jecm4jAFzRTw1LWOjzbKp8wmBYX5YZ5gUqBm37qnGORnzRQlrtH6I2USzJD0dmUlT7xxfKT3N0dGWz58UVorXtyATukxbuxmLvfdBUNQgTucFcY79lgZqruiy77kTExo6OVPXOatctGHV9aYGxNa8x03P6PWVz9rXUUgI66yHeuxcxj6ulNUgMj+sMx/qsfNh6+upvzwhY8tW2iDBWqQ/oxfHbahnOasB3+XQ+zlW5vztFF5jG2/baerjTQ3X9eeseqzX2JmG/SxYUND7y/Z2nbNLGXstnq1pIF/Ou+78zwrnnHvu/BJTz3/DKekBXok/2Lff1HdXtktPLbbv32qcMCd54bZnE6aRaqzBtffc90NT+6Gbzjl3553vMnU8oGGVOzd8zdR3DK6Vnuabb9CTcvb13l3Re4LnvWlqT71XejpD+5kyL9S57fkZ/WMVu977d6bOBfq5c6Jhz2kgq58fV2TPeSMEcQIAAAAAgNcBFi0AAAAAAEAqsWgBAAAAAABSac5vwlw13+6Ve3r3CulZsHDE1LvPD0rPWMPuv99zbr70dOf02G/u32vq+p0HpOfrL6w39cfWfU96KgXdVwSkQhS3bGmO657Zl+tdpr6ueFQf562bRrGuo/oZFnmnmxCT8mYyge6V1x577IlI9zLOC+3+vjNV3afnYt0fLC2z+DnidSabdUFvtxkKavazPm7ovltf71fKMrZ3ix0r9up78Nale2Ws7l1ji4r+HlPnOjL2WCdmOvSccnb/andW99jOJFyXvnygr7/pnWNfVj9fKmGt5bH9/f/OJX/G6OPsOf3jmTdKj7+n+QfVm1seF7iYAS/vbF9dr7uMaz2P+O/7aqSZNGOj+pkyPWD7GgnXStXLsCjk9Pp95pTNtLiyc1h6NNkN+JkgCFxYtPdiH338Pabeuvkpedzvdtux/kxCplNoj5uUzdCrQ25DcY+pvzyueRHRDpuXOHrzRj2Q588OPC9jf7VBMxXvWLjO1Iuf1nvVLy560tTX5zWbQr+roMeZjWMNne+/eO4mU39jzzrpCfbY++clTv8dL4ZvWgAAAAAAgFRi0QIAAAAAAKQSixYAAAAAACCVWLQAAAAAAACpNKeCOINCQcaOjNuwv/n/oS9p/G02aGSP05DNO5fbMJRHq9dJz/Fqp4zd0LvD1H+z91bpKZZt8NrZxjzpGeo6bepT0gG8RuKodU8CPxwzKRSvHtkeP3RztkKnj/PHooQ12nJgw/xGnYaTyWOyGvA52fJRuCwFgYtz9j0edVRsT8J/HWS6bQBf6dGt0jP0aOunP1DUkK1wwM5/x4J+fWDshf3N6Hs+Gp8wdRAEepimXvOxd6ykHhf5Ywu0xxNkE25ngoRg35L3M8m1vg2KxjV07K7SLabOjm9reRzgYoZKJ019aEYD+Qph64DpqShv6ummBnFW2jWkr5Sxx55s6D23H+rZV9bZb99pe97DxYr0ZJ2GcwLOORe3lVz9xtVmbMUf/ZeptyVMnDuW2bDOk7cNSM/oKju3LbrmpPSs7DgjYyvK9ne0B3r2Sc+mw4dM/aEl0uK2fMH+YYa/PfCE9Hz22Udk7MPv+pCpj9y0Q3o2v/U+U58f1ETRjkP2Gi/tPys98dkRGUsK229lqdOQ0eyV9ocS9+vv407/SX6Ob1oAAAAAAIBUYtECAAAAAACkEosWAAAAAAAgleZUpsX07WtkrNEcsz1X6r7aVX12L9L255ZLzzPz7diti/dKz8iM7nf/6z23m3r9gqPS49s9ofusqk37T+Hv+3HOucbBwy2PDaSFn09RTMi0mPLqTEI2RavjOudcZhZjUdx6jTYpG8M/Tn9B9/bpDsgEl5gNgrkrrtZc86X9Ziys2P3dwYDu6YzbSrbeqHNfZtzmsQRndB9qNDIqY7+0eSTU/bKzEYTBRWvnnHM53UsvIi93I+H6ihu6/785YceCfF56Qi8/Kyjq+QRdNnckGFqs5/iTh3UMcM5lFy2UsWZsN3OPNDULYjBnr+mkOdMf68r5M61zpbxeG372RS7UObstZz93GgnzajZrH1dr6K8aha4uGWueOydjuAw1I5f15rexd28wdftP9T0d7z9u6t6HDklP7yye/kjimL0Wf+jWSo8/t2f69HfG5hl7t3j/kk2zOCPncgM26TBePSQ9pe9uN3WxPiM9fjZk7Gc8OedcQn5kZsj+jhyXdN6Ms/azYKanJD2nV9rHDfzTS/r8F8E3LQAAAAAAQCqxaAEAAAAAAFKJRQsAAAAAAJBKLFoAAAAAAIBUmlNBnCOr9HS7CjZoZHL1een51JJHTH3X1o9Kz3Rkw0GGyiel57H/3CJjhcFJexwvyMg559pzVVO/cFqDOP3gzx9vWSE9fQ8SxIlfvdgPvJuleeG0qesJgV1NZ0P49OqZnYzTc6zH9vOiHNakZyqygUOVUIOLqpE9q2Uljd3c6Xpan2SQsEYca9AZXt+iSTtnuP0HWz4mzGnoVdDdaQd6OqUnbG9rfULZhEDNhve+jFt/BgQJnxNxUsimPFB7gmbr0Fo5dsJxXJhwzfmvdzavLen5/frZnS2PA/xcpO/xqwsvm3pPbVB6Jr05qyej97xN7/8jw4T5cWmHBveO1W1wXj5sSI8fznm+pqF9HSV7zzs8oYGi7UmJiARxwjnnpqou3rbLDHUd6jZ1tOwKedj0+mWmbhb1jy6EdXsthDW9DoOEKSE7aYNrM2PT2uTNN/VuDeJs3GD/yEKjovNvM68zjn/eiVZ54bZJU6J3nIR8/MS5PDdhPwuS5uhwxh6stP+s9BS32SD75rB+Dl0M37QAAAAAAACpxKIFAAAAAABIJRYtAAAAAABAKs2pTIuZdt1n016we+euWnpaer40sskOxLrRZ23bEVMvzem+9dVrNFNiQ3fr/chn63ZfcaOhe5gWF+y+nvGbq9LT92DLpwJ+6QJv73jceru5c07zIeqxvu/9LAp/L26SnNNNeKHTk6rGNouiO6hrj5eiUUzItKg37T5fP6tjtvyfo3Oz/1ni8hbX9X3ZPOXNdX4NILVGNy6SsWvzNnfpZGNKejKBnTT8jIsk5YzmOYUJG/cbkZ1/FxT1+Udm7D79mUjn9TbvdZyodUhPMDEpY8CFSPZBQhaCJD+FCfecPTYbIyhoXlRSPlKz176Ho7I+LsrbX6mzCbkXWS+2JahrbkxQ1es1nrTXYnNkVHpc9NpmpPmfKPrKfnF80wIAAAAAAKQSixYAAAAAACCVWLQAAAAAAACpxKIFAAAAAABIpTkVxNlcpuGUw9M2FGhpRcNZvrljnakzmj/kvvmy7bl38CfSkxS6uef8AlPnQg1C2dz5kqkfnVgrPRPNoqnfdvUO6dkpI8CvQHBpa5t+qGUYaOpkzovqyQV6/USxfX4/vPNnz6Uhm1NNG1DmH8c5DTVL6vHPKel1AAAwW6MrkoKpbQCgPz8lySSEUOcDO68WA43Ey4c61ohsuGBXVoM4/bFTU+3SU8jaY1+36GXpqWfn1K8fmIsSgimbZ/SPLMzK0WMtW/z4Tu4Uf/n4pgUAAAAAAEglFi0AAAAAAEAqsWgBAAAAAABSiUULAAAAAACQSulNwgk1pOgT674lY0+OrzT1znMD0rNx6ICpn85cKT3Hz3WY+vHcddIzWBqXsa8u/ZGp33PoTdKzLH/a1MG0vrZTMzbMaEvn89Kz0w3JGPCqC/14IRUkhGoVAw3H9CUFb+rT2zijpCDOvEsIXEoI1byU5y96r382xwUA4EKmFmkQZjW281HSHFqNc6buzGhY5mjTBtRPBgXpSQqdbkT23jQp4Loa2efvKExLz1itZOrBypj0nOhbLGPu2HEdA4D/xd03AAAAAABIJRYtAAAAAABAKrFoAQAAAAAAUim1mRbn33GjjB2s6d65U9M2C2K8qnv3zmTaWj7fp9b8i6kf2H6P9BQHdQ/i3fvuMPX6rsPSUwlmTN2xUPf3DRZGW57j5Dtu0mM//EzLxwGvtqBUkjE/LyJpD62vnLCHNoq9TAmnGRt+7sXPnr/RssfFmi/j8zMsvjN6fUJXteVxAABwzrnKgkkZq8ea1+QrBzVT+xkXzjnXnMX/R5YyOteer9v756koLz1tGTvXFROOM+bs/cBEXe/La/1lGdNnA4D/wzctAAAAAABAKrFoAQAAAAAAUolFCwAAAAAAkEosWgAAAAAAgFRKbRDn2TUatvej0ytlbE33cVMfGOmRnlWdJ019ZrIiPZXQhhst7j4nPU+/tFzG8i/bEKQD1+jzN5fZtaHOsgaKnp6ZZ+qJggYbTr5XAzwrD8sQkAp5Z4M4k4IwM84Gj+Wc9kSB91mQEOjpH8c55zLe801FGgY24wVx5r3w0CTzsoRuAgAuXdJ94AszXS0fF83i/xoz3jyaFII9Vi+2PE45nGk51l+YkJ5TUzYgPwx0fh5dpgGi81ueEYDLGd+0AAAAAAAAqcSiBQAAAAAASCUWLQAAAAAAQCqlNtNipq8hY59c/qiM/cmL7zT1os5R6Tl03uZMFHJ67E8f3mLqg2e6pee2a16Usemr7b683Wf7pWe4bjM0RibL0hN22z1/bykdlp4/P9YhY+wBRCo0NQui6WwWRTUhU6LsZcmcifTa8PfnVmPdC5uUaTHcaLPHTlij7cuOmzpp7+9EpPkyAABcqvV9R2SsMzNl6tGmzodTsc6jrSTlSVWbOo/WGvZXgmqkPUk5F3Kcpj3OWE3n0PNLdc7mfhbAxfBNCwAAAAAAkEosWgAAAAAAgFRi0QIAAAAAAKQSixYAAAAAACCVUhvEuerjP5Wx97vfk7EX7vqcqXfOaHDQU1MrTf32pc9Lz756l6mri/Q4UwlBgvMy06a+YmBMeo43bYDm5vaXpGe4aUMD//DI26Rn5f3Pyhjwqos0MMsXJwRxHq3bANy3t52Wnqmobur2MNP6dJwGgYVe6KdzzkXFUy2P5T9uOJqWnolo2NT1WM9xuxts+VwAADjn3GM7r5exD9zypKmvy5+TnpHIzj/zQp17D3kh1CvzOhdW+msydqpu71Uf6NknPT+u2npRflh6Rus2QHSoclJ6HixfIWMAcDF80wIAAAAAAKQSixYAAAAAACCVWLQAAAAAAACplNpMi+ZZ3Sc3dJ+O3eM2mDpYd4307L+33dR/P7BZehb0ahaFb6qWl7Hx8ZKpwxNF6SkM233zC7+vzxVv2+WN6GsFXgtxXTMkpKem+2O/cqe9zj7xwQHpqfc17EBG8zMyBbtnN8zoHt5AIy1cveZ9vE1oTk1Qsw8snEtYx41s2b1Hn7/intHHeZJyPwAAl5+V7/9vGXsg3Gjq8/esl56za+wcFS+fkp7BHnuPeXJ0nvQ06nr7X9pu72e/Ft0uPXXvULkJaXELnpo09ZGnJ6Vn5SzmTAD4//imBQAAAAAASCUWLQAAAAAAQCqxaAEAAAAAAFKJRQsAAAAAAJBKQRxr8N0Fm4PgjHPu8Kt3Oki5JXEc973WJwHFtXnZ49pMIa7Lyx7XZUpxbV72uDZTimvzsnfBa/MVLVoAAAAAAAD8qrA9BAAAAAAApBKLFgAAAAAAIJVYtAAAAAAAAKnEogUAAAAAAEglFi0AAAAAAEAqsWgBAAAAAABSiUULAAAAAACQSixaAAAAAACAVGLRAgAAAAAApNL/AGcRTmOdal/QAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "y_hat = model.predict_classes(test_images)\n", "\n", "# Plot a random sample of 10 test images, their predicted labels and ground truth\n", "figure = plt.figure(figsize=(20, 8))\n", "for i, index in enumerate(np.random.choice(test_images.shape[0], size=15, replace=False)):\n", " ax = figure.add_subplot(3, 5, i + 1, xticks=[], yticks=[])\n", " # Display each image\n", " ax.imshow(np.squeeze(test_images[index]))\n", " predict_index = y_hat[index]\n", " true_index = test_labels[index]\n", " # Set the title for each image\n", " ax.set_title(\"{} ({})\".format(class_names[predict_index], \n", " class_names[true_index]),\n", " color=(\"green\" if predict_index == true_index else \"red\"))" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "xsoS7CPDCaXH" }, "source": [ "## Predict on a single image" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's first see the test image and and its label:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Class: Ankle boot\n" ] } ], "source": [ "plt.imshow(test_images[0].squeeze(-1), cmap=plt.cm.binary)\n", "plt.show()\n", "print('Class:', class_names[test_labels[0]])" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": {}, "colab_type": "code", "id": "Gl91RPhdCaXI" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Prediction: Ankle boot\n" ] } ], "source": [ "pred_idx = model.predict_classes(np.expand_dims(test_images[0], 0))[0]\n", "print('Prediction:', class_names[pred_idx])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define BentoService for model serving" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting keras_fashion_mnist.py\n" ] } ], "source": [ "%%writefile keras_fashion_mnist.py\n", "from typing import List\n", "\n", "import numpy as np\n", "from PIL import Image\n", "from bentoml import api, artifacts, env, BentoService\n", "from bentoml.frameworks.keras import KerasModelArtifact\n", "from bentoml.adapters import ImageInput\n", "\n", "class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',\n", " 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']\n", "\n", "@env(pip_packages=['keras==2.3.1', 'tensorflow==1.14.0', 'pillow', 'numpy'])\n", "@artifacts([KerasModelArtifact('classifier')])\n", "class KerasFashionMnistService(BentoService):\n", " \n", " @api(input=ImageInput(pilmode='L'), batch=True)\n", " def predict(self, imgs: List[np.ndarray]) -> List[str]:\n", " inputs = []\n", " for img in imgs:\n", " img = Image.fromarray(img).resize((28, 28))\n", " img = np.array(img.getdata()).reshape((28, 28, 1))\n", " inputs.append(img)\n", " inputs = np.stack(inputs)\n", " class_idxs = self.artifacts.classifier.predict_classes(inputs)\n", " return [class_names[class_idx] for class_idx in class_idxs]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Save BentoService to file archive" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 13:23:49,677] 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-23 13:23:49,704] WARNING - pip package requirement tensorflow already exist\n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 13:23:51,430] INFO - Detected non-PyPI-released BentoML installed, copying local BentoML modulefiles to target saved bundle path..\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/conda/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/setuptools/dist.py:452: UserWarning: Normalizing '0.9.0.pre+7.g8af1c8b' to '0.9.0rc0+7.g8af1c8b'\n", " warnings.warn(tmpl.format(**locals()))\n", "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", "warning: no directories found matching 'bentoml/yatai/web/dist'\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+7.g8af1c8b/bentoml/_version.py\n", "set BentoML-0.9.0rc0+7.g8af1c8b/bentoml/_version.py to '0.9.0.pre+7.g8af1c8b'\n", "[2020-09-23 13:23:52,274] INFO - BentoService bundle 'KerasFashionMnistService:20200923132350_974EEA' saved to: /home/bentoml/bentoml/repository/KerasFashionMnistService/20200923132350_974EEA\n" ] } ], "source": [ "# 1) import the custom BentoService defined above\n", "from keras_fashion_mnist import KerasFashionMnistService\n", "\n", "# 2) `pack` it with required artifacts\n", "mnist_svc = KerasFashionMnistService()\n", "mnist_svc.pack('classifier', model)\n", "\n", "# 3) save your BentoSerivce to file archive\n", "saved_path = mnist_svc.save()" ] }, { "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": 20, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 13:23:59,176] 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+7.g8af1c8b\n", "[2020-09-23 13:23:59,178] WARNING - Module `keras_fashion_mnist` already loaded, using existing imported module.\n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "[2020-09-23 13:24:00,085] WARNING - pip package requirement imageio already exist\n", "[2020-09-23 13:24:00,086] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 13:24:00,087] WARNING - pip package requirement keras already exist\n" ] }, { "data": { "text/plain": [ "['Ankle boot']" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svc = bentoml.load(saved_path)\n", "svc.predict([test_images[0].squeeze(-1)])" ] }, { "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": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 13:24:35,370] INFO - Getting latest version KerasFashionMnistService:20200923132350_974EEA\n", "[2020-09-23 13:24:36,401] 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-23 13:24:36,419] 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+7.g8af1c8b\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "Using TensorFlow backend.\n", "2020-09-23 13:24:37.559712: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcuda.so.1\n", "2020-09-23 13:24:37.574229: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.574603: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1640] Found device 0 with properties: \n", "name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705\n", "pciBusID: 0000:01:00.0\n", "2020-09-23 13:24:37.574778: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:37.576014: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcublas.so.10\n", "2020-09-23 13:24:37.577344: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcufft.so.10\n", "2020-09-23 13:24:37.577571: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcurand.so.10\n", "2020-09-23 13:24:37.579057: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusolver.so.10\n", "2020-09-23 13:24:37.579956: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusparse.so.10\n", "2020-09-23 13:24:37.583071: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudnn.so.7\n", "2020-09-23 13:24:37.583207: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.583615: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.583945: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1763] Adding visible gpu devices: 0\n", "2020-09-23 13:24:37.584206: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA\n", "2020-09-23 13:24:37.728318: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.728789: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5557595e9bd0 executing computations on platform CUDA. Devices:\n", "2020-09-23 13:24:37.728809: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): GeForce GTX 1060, Compute Capability 6.1\n", "2020-09-23 13:24:37.728961: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.729290: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1640] Found device 0 with properties: \n", "name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705\n", "pciBusID: 0000:01:00.0\n", "2020-09-23 13:24:37.729326: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:37.729340: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcublas.so.10\n", "2020-09-23 13:24:37.729352: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcufft.so.10\n", "2020-09-23 13:24:37.729363: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcurand.so.10\n", "2020-09-23 13:24:37.729376: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusolver.so.10\n", "2020-09-23 13:24:37.729388: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusparse.so.10\n", "2020-09-23 13:24:37.729400: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudnn.so.7\n", "2020-09-23 13:24:37.729447: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.729796: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.730123: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1763] Adding visible gpu devices: 0\n", "2020-09-23 13:24:37.730164: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:37.730641: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1181] Device interconnect StreamExecutor with strength 1 edge matrix:\n", "2020-09-23 13:24:37.730654: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1187] 0 \n", "2020-09-23 13:24:37.730662: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1200] 0: N \n", "2020-09-23 13:24:37.730760: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.731141: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:37.731496: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1326] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5683 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060, pci bus id: 0000:01:00.0, compute capability: 6.1)\n", "2020-09-23 13:24:37.756994: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2699905000 Hz\n", "2020-09-23 13:24:37.757349: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x55575c5d4840 executing computations on platform Host. Devices:\n", "2020-09-23 13:24:37.757417: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): , \n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "WARNING:tensorflow:From /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "WARNING:tensorflow:From /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 13:24:38,862] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 13:24:38,862] WARNING - pip package requirement keras already exist\n", "2020-09-23 13:24:39.961990: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcublas.so.10\n", "2020-09-23 13:24:40.109036: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudnn.so.7\n", "[2020-09-23 13:24:40,664] INFO - {'service_name': 'KerasFashionMnistService', 'service_version': '20200923132350_974EEA', 'api': 'predict', 'task': {'data': {'uri': 'file:///home/bentoml/lab/gallery/legacy-keras/fashion-mnist/sample_image.png', 'name': 'sample_image.png'}, 'task_id': 'f350fdaa-9523-469b-8d73-8facb0945bb7', 'cli_args': ('--input-file', 'sample_image.png')}, 'result': {'data': '\"Ankle boot\"', 'http_status': 200, 'http_headers': (('Content-Type', 'application/json'),)}, 'request_id': 'f350fdaa-9523-469b-8d73-8facb0945bb7'}\n", "\"Ankle boot\"\n" ] } ], "source": [ "!bentoml run KerasFashionMnistService:latest predict --input-file sample_image.png" ] }, { "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": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 13:24:48,477] INFO - Getting latest version KerasFashionMnistService:20200923132350_974EEA\n", "[2020-09-23 13:24:48,477] INFO - Starting BentoML API server in development mode..\n", "[2020-09-23 13:24:49,637] 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-23 13:24:49,654] 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+7.g8af1c8b\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "Using TensorFlow backend.\n", "2020-09-23 13:24:50.754920: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcuda.so.1\n", "2020-09-23 13:24:50.769561: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.769934: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1640] Found device 0 with properties: \n", "name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705\n", "pciBusID: 0000:01:00.0\n", "2020-09-23 13:24:50.770104: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:50.771331: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcublas.so.10\n", "2020-09-23 13:24:50.772609: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcufft.so.10\n", "2020-09-23 13:24:50.772876: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcurand.so.10\n", "2020-09-23 13:24:50.774317: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusolver.so.10\n", "2020-09-23 13:24:50.775157: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusparse.so.10\n", "2020-09-23 13:24:50.778709: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudnn.so.7\n", "2020-09-23 13:24:50.778855: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.779265: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.779583: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1763] Adding visible gpu devices: 0\n", "2020-09-23 13:24:50.779837: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA\n", "2020-09-23 13:24:50.950505: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.950963: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5597103fd600 executing computations on platform CUDA. Devices:\n", "2020-09-23 13:24:50.950987: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): GeForce GTX 1060, Compute Capability 6.1\n", "2020-09-23 13:24:50.951170: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.951547: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1640] Found device 0 with properties: \n", "name: GeForce GTX 1060 major: 6 minor: 1 memoryClockRate(GHz): 1.6705\n", "pciBusID: 0000:01:00.0\n", "2020-09-23 13:24:50.951582: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:50.951612: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcublas.so.10\n", "2020-09-23 13:24:50.951638: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcufft.so.10\n", "2020-09-23 13:24:50.951665: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcurand.so.10\n", "2020-09-23 13:24:50.951679: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusolver.so.10\n", "2020-09-23 13:24:50.951692: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcusparse.so.10\n", "2020-09-23 13:24:50.951731: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudnn.so.7\n", "2020-09-23 13:24:50.951794: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.952186: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.952530: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1763] Adding visible gpu devices: 0\n", "2020-09-23 13:24:50.952558: I tensorflow/stream_executor/platform/default/dso_loader.cc:42] Successfully opened dynamic library libcudart.so.10.1\n", "2020-09-23 13:24:50.953034: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1181] Device interconnect StreamExecutor with strength 1 edge matrix:\n", "2020-09-23 13:24:50.953047: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1187] 0 \n", "2020-09-23 13:24:50.953053: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1200] 0: N \n", "2020-09-23 13:24:50.953157: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.953528: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:1005] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero\n", "2020-09-23 13:24:50.953875: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1326] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 5683 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1060, pci bus id: 0000:01:00.0, compute capability: 6.1)\n", "2020-09-23 13:24:50.972930: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2699905000 Hz\n", "2020-09-23 13:24:50.973274: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5597135723e0 executing computations on platform Host. Devices:\n", "2020-09-23 13:24:50.973362: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): , \n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "WARNING:tensorflow:From /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "WARNING:tensorflow:From /opt/anaconda3/envs/bentoml-py3_6-tf1_4/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "WARNING:tensorflow:From /home/bentoml/BentoML/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 13:24:52,198] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 13:24:52,198] WARNING - pip package requirement keras already exist\n", "[2020-09-23 13:24:53,251] 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+7.g8af1c8b\n", "[2020-09-23 13:24:53,253] INFO - Micro batch enabled for API `predict`\n", "[2020-09-23 13:24:53,253] INFO - Your system nofile limit is 10000, which means each instance of microbatch service is able to hold this number of connections at same time. You can increase the number of file descriptors for the server process, or launch more microbatch instances to accept more concurrent connection.\n", "[2020-09-23 13:24:53,267] INFO - Running micro batch service on :5000\n", " * Serving Flask app \"KerasFashionMnistService\" (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:48301/ (Press CTRL+C to quit)\n", "======== Running on http://0.0.0.0:5000 ========\n", "(Press CTRL+C to quit)\n", "^C\n" ] } ], "source": [ "!bentoml serve KerasFashionMnistService:latest --enable-microbatch" ] }, { "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 KerasFashionMnistService:latest --run-with-ngrok" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Test sending request to API Server from terminal:\n", "\n", "```bash\n", "curl -X POST \"http://127.0.0.1:5000/predict\" -F image=@sample_image.png\n", "```\n", "\n", "or:\n", "\n", "```bash\n", "curl -X POST \"http://127.0.0.1:5000/predict\" -H \"Content-Type: image/png\" --data-binary @sample_image.png\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": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 13:25:09,964] INFO - Getting latest version KerasFashionMnistService:20200923132350_974EEA\n", "\u001b[39mFound Bento: /home/bentoml/bentoml/repository/KerasFashionMnistService/20200923132350_974EEA\u001b[0m\n", "[2020-09-23 13:25:09,983] 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-23 13:25:09,999] 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+7.g8af1c8b\n", "Building Docker image kerasfashionmnistservice:latest from KerasFashionMnistService:latest \n", "-\u001b[39mStep 1/15 : FROM bentoml/model-server:0.9.0.pre-py36\u001b[0m\n", "\u001b[39m ---> 4aac43d10e50\u001b[0m\n", "\u001b[39mStep 2/15 : ARG EXTRA_PIP_INSTALL_ARGS=\u001b[0m\n", "\u001b[39m ---> Using cache\u001b[0m\n", "\u001b[39m ---> 790054f5ad85\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 ---> 85b0a1b40542\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 ---> 8729a1f5c821\u001b[0m\n", "\u001b[39mStep 5/15 : WORKDIR /bento\u001b[0m\n", "\u001b[39m ---> Running in 60907eb65c99\u001b[0m\n", "\b\\\u001b[39m ---> 6df2fc7b9f5b\u001b[0m\n", "\u001b[39mStep 6/15 : RUN chmod +x /bento/bentoml-init.sh\u001b[0m\n", "\u001b[39m ---> Running in 5623e9822b02\u001b[0m\n", "\b|\u001b[39m ---> 4c3fa98dc1df\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 050ae928ea3d\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", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m+ '[' -f ./setup.sh ']'\n", "+ '[' -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.6.10\n", "+ DESIRED_PY_VERSION=3.6\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m++ python -c 'import sys; print(f\"{sys.version_info.major}.{sys.version_info.minor}\")'\n", "\u001b[0m\u001b[0m\n", "\u001b[39m\u001b[91m+ CURRENT_PY_VERSION=3.6\n", "+ [[ 3.6 == \\3\\.\\6 ]]\n", "+ echo 'Python Version in docker base image 3.6 matches requirement python=3.6. Skipping.'\n", "\u001b[0m\u001b[0m\n", "\u001b[39mPython Version in docker base image 3.6 matches requirement python=3.6. Skipping.\u001b[0m\n", "\u001b[39m\u001b[91m+ command -v conda\n", "+ echo 'Updating conda base environment with environment.yml'\n", "+ conda env update -n base -f ./environment.yml\n", "\u001b[0m\u001b[0m\n", "\u001b[39mUpdating conda base environment with environment.yml\u001b[0m\n", "\b|\u001b[39mCollecting package metadata (repodata.json): ...working... \u001b[0m\n", "\b|\u001b[39mdone\n", "Solving environment: ...working... \u001b[0m\n", "\b-\u001b[39mdone\u001b[0m\n", "\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 | 3% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | 4 | 4% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | 5 | 6% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | 7 | 7% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #3 | 13% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #9 | 19% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ##7 | 27% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ##9 | 29% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ###3 | 34% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ###6 | 36% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #### | 41% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ####1 | 42% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ####6 | 46% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ####8 | 49% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ##### | 51% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #####2 | 52% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #####5 | 55% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ###### | 60% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #######2 | 73% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ######## | 80% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########1 | 82% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########6 | 87% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########9 | 89% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #########1 | 91% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #########5 | 96% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | #########7 | 98% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########## | 100% \u001b[0m\n", "openssl-1.1.1h | 2.1 MB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "ca-certificates-2020 | 145 KB | | 0% \u001b[0m\n", "ca-certificates-2020 | 145 KB | #1 | 11% \u001b[0m\n", "ca-certificates-2020 | 145 KB | ##2 | 22% \u001b[0m\n", "ca-certificates-2020 | 145 KB | ###3 | 33% \u001b[0m\n", "ca-certificates-2020 | 145 KB | ######6 | 66% \u001b[0m\n", "ca-certificates-2020 | 145 KB | ########## | 100% \u001b[0m\n", "\u001b[39m\n", "python_abi-3.6 | 4 KB | | 0% \u001b[0m\n", "python_abi-3.6 | 4 KB | ########## | 100% \u001b[0m\n", "python_abi-3.6 | 4 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 | 1 | 1% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | 5 | 6% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | 8 | 9% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | #8 | 19% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ##7 | 28% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ###6 | 37% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | #####2 | 53% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | #####8 | 58% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ######2 | 63% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ######## | 80% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ########4 | 85% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | ######### | 91% \u001b[0m\n", "pip-20.2.3 | 1.1 MB | #########3 | 94% \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", "certifi-2020.6.20 | 151 KB | | 0% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | # | 11% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | ##1 | 21% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | ####2 | 42% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | #####3 | 53% \u001b[0m\n", "certifi-2020.6.20 | 151 KB | ########4 | 85% \u001b[0m\n", "certifi-2020.6.20 | 151 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.6/site-packages (from -r ./requirements.txt (line 1)) (0.9.0rc0)\u001b[0m\n", "\b|\u001b[39mCollecting keras==2.3.1\u001b[0m\n", "\b-\u001b[39m Downloading Keras-2.3.1-py2.py3-none-any.whl (377 kB)\u001b[0m\n", "\b/\u001b[39mCollecting tensorflow==1.14.0\u001b[0m\n", "\b|\u001b[39m Downloading tensorflow-1.14.0-cp36-cp36m-manylinux1_x86_64.whl (109.2 MB)\u001b[0m\n", "\b-\u001b[39mCollecting pillow==7.2.0\u001b[0m\n", "\b/\u001b[39m Downloading Pillow-7.2.0-cp36-cp36m-manylinux1_x86_64.whl (2.2 MB)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied: numpy==1.19.2 in /opt/conda/lib/python3.6/site-packages (from -r ./requirements.txt (line 5)) (1.19.2)\u001b[0m\n", "\b\\\u001b[39mCollecting imageio==2.9.0\u001b[0m\n", "\b/\u001b[39m Downloading imageio-2.9.0-py3-none-any.whl (3.3 MB)\u001b[0m\n", "\b-\u001b[39mRequirement already satisfied: tabulate in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.8.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: requests in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.24.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: cerberus in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.3.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: click>=7.0 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (7.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: py-zipkin in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.20.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: prometheus-client in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.8.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: docker in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (4.3.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: certifi in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2020.6.20)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-json-logger in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.1.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied: alembic in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: boto3 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.15.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: protobuf>=3.6.0 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.13.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-dateutil<3.0.0,>=2.7.3 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.8.1)\u001b[0m\n", "\b/\u001b[39mRequirement already satisfied: ruamel.yaml>=0.15.0 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.15.87)\u001b[0m\n", "\u001b[39mRequirement already satisfied: sqlalchemy-utils<0.36.8 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.36.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: humanfriendly in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (8.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: psutil in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (5.7.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: dataclasses; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: packaging in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: aiohttp in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.6.2)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied: contextvars; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: grpcio<=1.27.2 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.27.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied: multidict in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (4.7.6)\u001b[0m\n", "\u001b[39mRequirement already satisfied: sqlalchemy>=1.3.0 in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.3.19)\u001b[0m\n", "\u001b[39mRequirement already satisfied: gunicorn in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: configparser in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (5.0.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: flask in /opt/conda/lib/python3.6/site-packages (from bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.2)\u001b[0m\n", "\b-\u001b[39mCollecting keras-preprocessing>=1.0.5\u001b[0m\n", "\b/\u001b[39m Downloading Keras_Preprocessing-1.1.2-py2.py3-none-any.whl (42 kB)\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied: six>=1.9.0 in /opt/conda/lib/python3.6/site-packages (from keras==2.3.1->-r ./requirements.txt (line 2)) (1.15.0)\u001b[0m\n", "\b-\u001b[39mCollecting scipy>=0.14\u001b[0m\n", "\b/\u001b[39m Downloading scipy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl (25.9 MB)\u001b[0m\n", "\b-\u001b[39mCollecting pyyaml\u001b[0m\n", "\b|\u001b[39m Downloading PyYAML-5.3.1.tar.gz (269 kB)\u001b[0m\n", "\b/\u001b[39mCollecting keras-applications>=1.0.6\u001b[0m\n", "\b|\u001b[39m Downloading Keras_Applications-1.0.8-py3-none-any.whl (50 kB)\u001b[0m\n", "\b|\u001b[39mCollecting h5py\u001b[0m\n", "\b\\\u001b[39m Downloading h5py-2.10.0-cp36-cp36m-manylinux1_x86_64.whl (2.9 MB)\u001b[0m\n", "\b|\u001b[39mCollecting tensorflow-estimator<1.15.0rc0,>=1.14.0rc0\u001b[0m\n", "\b\\\u001b[39m Downloading tensorflow_estimator-1.14.0-py2.py3-none-any.whl (488 kB)\u001b[0m\n", "\b/\u001b[39mCollecting astor>=0.6.0\u001b[0m\n", "\b\\\u001b[39m Downloading astor-0.8.1-py2.py3-none-any.whl (27 kB)\u001b[0m\n", "\u001b[39mRequirement already satisfied: wheel>=0.26 in /opt/conda/lib/python3.6/site-packages (from tensorflow==1.14.0->-r ./requirements.txt (line 3)) (0.35.1)\u001b[0m\n", "\b/\u001b[39mCollecting absl-py>=0.7.0\u001b[0m\n", "\b|\u001b[39m Downloading absl_py-0.10.0-py3-none-any.whl (127 kB)\u001b[0m\n", "\b|\u001b[39mCollecting tensorboard<1.15.0,>=1.14.0\u001b[0m\n", "\b-\u001b[39m Downloading tensorboard-1.14.0-py3-none-any.whl (3.1 MB)\u001b[0m\n", "\b-\u001b[39mCollecting wrapt>=1.11.1\u001b[0m\n", "\b/\u001b[39m Downloading wrapt-1.12.1.tar.gz (27 kB)\u001b[0m\n", "\b|\u001b[39mCollecting google-pasta>=0.1.6\u001b[0m\n", "\b\\\u001b[39m Downloading google_pasta-0.2.0-py3-none-any.whl (57 kB)\u001b[0m\n", "\b/\u001b[39mCollecting termcolor>=1.1.0\u001b[0m\n", "\b\\\u001b[39m Downloading termcolor-1.1.0.tar.gz (3.9 kB)\u001b[0m\n", "\b\\\u001b[39mCollecting gast>=0.2.0\u001b[0m\n", "\b-\u001b[39m Downloading gast-0.4.0-py3-none-any.whl (9.8 kB)\u001b[0m\n", "\u001b[39mRequirement already satisfied: chardet<4,>=3.0.2 in /opt/conda/lib/python3.6/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.6/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.6/site-packages (from requests->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.25.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied: setuptools in /opt/conda/lib/python3.6/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: thriftpy2>=0.4.0 in /opt/conda/lib/python3.6/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: websocket-client>=0.32.0 in /opt/conda/lib/python3.6/site-packages (from docker->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.57.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: python-editor>=0.3 in /opt/conda/lib/python3.6/site-packages (from alembic->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Mako in /opt/conda/lib/python3.6/site-packages (from alembic->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: botocore<1.19.0,>=1.18.2 in /opt/conda/lib/python3.6/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.18.2)\u001b[0m\n", "\b/\u001b[39mRequirement already satisfied: jmespath<1.0.0,>=0.7.1 in /opt/conda/lib/python3.6/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.10.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: s3transfer<0.4.0,>=0.3.0 in /opt/conda/lib/python3.6/site-packages (from boto3->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.3.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: pyparsing>=2.0.2 in /opt/conda/lib/python3.6/site-packages (from packaging->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.4.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (20.2.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: typing-extensions>=3.6.5; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.7.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.5.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: idna-ssl>=1.0; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: async-timeout<4.0,>=3.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (3.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: immutables>=0.9 in /opt/conda/lib/python3.6/site-packages (from contextvars; python_version < \"3.7\"->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (0.14)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Werkzeug>=0.15 in /opt/conda/lib/python3.6/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied: itsdangerous>=0.24 in /opt/conda/lib/python3.6/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied: Jinja2>=2.10.1 in /opt/conda/lib/python3.6/site-packages (from flask->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (2.11.2)\u001b[0m\n", "\b\\\u001b[39mCollecting markdown>=2.6.8\u001b[0m\n", "\b-\u001b[39m Downloading Markdown-3.2.2-py3-none-any.whl (88 kB)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied: ply<4.0,>=3.4 in /opt/conda/lib/python3.6/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: MarkupSafe>=0.9.2 in /opt/conda/lib/python3.6/site-packages (from Mako->alembic->bentoml==0.9.0.pre->-r ./requirements.txt (line 1)) (1.1.1)\u001b[0m\n", "\b/\u001b[39mCollecting importlib-metadata; python_version < \"3.8\"\u001b[0m\n", "\b|\u001b[39m Downloading importlib_metadata-2.0.0-py2.py3-none-any.whl (31 kB)\u001b[0m\n", "\b-\u001b[39mCollecting zipp>=0.5\u001b[0m\n", "\b|\u001b[39m Downloading zipp-3.2.0-py3-none-any.whl (5.1 kB)\u001b[0m\n", "\u001b[39mBuilding wheels for collected packages: pyyaml, wrapt, termcolor\u001b[0m\n", "\u001b[39m Building wheel for pyyaml (setup.py): started\u001b[0m\n", "\b|\u001b[39m Building wheel for pyyaml (setup.py): finished with status 'done'\u001b[0m\n", "\u001b[39m Created wheel for pyyaml: filename=PyYAML-5.3.1-cp36-cp36m-linux_x86_64.whl size=44619 sha256=bc3a34861f160832e54226e9dfc5886ed6a1f193d13bc07bd8cc6c07e9252140\u001b[0m\n", "\u001b[39m Stored in directory: /tmp/pip-ephem-wheel-cache-n4qcgfhc/wheels/e5/9d/ad/2ee53cf262cba1ffd8afe1487eef788ea3f260b7e6232a80fc\u001b[0m\n", "\u001b[39m Building wheel for wrapt (setup.py): started\u001b[0m\n", "\b|\u001b[39m Building wheel for wrapt (setup.py): finished with status 'done'\u001b[0m\n", "\u001b[39m Created wheel for wrapt: filename=wrapt-1.12.1-cp36-cp36m-linux_x86_64.whl size=75206 sha256=3e1a885724afaa51a425c64bc576f9bcac3f850636e59c10ee14160a0d4d9340\u001b[0m\n", "\u001b[39m Stored in directory: /tmp/pip-ephem-wheel-cache-n4qcgfhc/wheels/32/42/7f/23cae9ff6ef66798d00dc5d659088e57dbba01566f6c60db63\u001b[0m\n", "\u001b[39m Building wheel for termcolor (setup.py): started\u001b[0m\n", "\b/\u001b[39m Building wheel for termcolor (setup.py): finished with status 'done'\u001b[0m\n", "\u001b[39m Created wheel for termcolor: filename=termcolor-1.1.0-py3-none-any.whl size=4830 sha256=66929de748b95c287b1919fc0cbd3c4337b4897dbc42ebcda4be7c6cbdc707fa\u001b[0m\n", "\u001b[39m Stored in directory: /tmp/pip-ephem-wheel-cache-n4qcgfhc/wheels/93/2a/eb/e58dbcbc963549ee4f065ff80a59f274cc7210b6eab962acdc\u001b[0m\n", "\u001b[39mSuccessfully built pyyaml wrapt termcolor\u001b[0m\n", "\b\\\u001b[39mInstalling collected packages: keras-preprocessing, scipy, pyyaml, h5py, keras-applications, keras, tensorflow-estimator, astor, absl-py, zipp, importlib-metadata, markdown, tensorboard, wrapt, google-pasta, termcolor, gast, tensorflow, pillow, imageio\u001b[0m\n", "\b/\u001b[39mSuccessfully installed absl-py-0.10.0 astor-0.8.1 gast-0.4.0 google-pasta-0.2.0 h5py-2.10.0 imageio-2.9.0 importlib-metadata-2.0.0 keras-2.3.1 keras-applications-1.0.8 keras-preprocessing-1.1.2 markdown-3.2.2 pillow-7.2.0 pyyaml-5.3.1 scipy-1.5.2 tensorboard-1.14.0 tensorflow-1.14.0 tensorflow-estimator-1.14.0 termcolor-1.1.0 wrapt-1.12.1 zipp-3.2.0\u001b[0m\n", "\b|\u001b[39m ---> f67cf901ef18\u001b[0m\n", "\u001b[39mStep 8/15 : COPY . /bento\u001b[0m\n", "\b/\u001b[39m ---> 4a58550a0fad\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 98757f1e8214\u001b[0m\n", "\b-\u001b[39mProcessing ./bundled_pip_dependencies/BentoML-0.9.0rc0+7.g8af1c8b.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: grpcio<=1.27.2 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.27.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: boto3 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.15.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: numpy in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.19.2)\u001b[0m\n", "\b-\u001b[39mRequirement already satisfied, skipping upgrade: prometheus-client in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.8.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: sqlalchemy-utils<0.36.8 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.36.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: gunicorn in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (20.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: requests in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (2.24.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: psutil in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (5.7.2)\u001b[0m\n", "\b/\u001b[39mRequirement already satisfied, skipping upgrade: packaging in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (20.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: contextvars; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (2.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: docker in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (4.3.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: aiohttp in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (3.6.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: dataclasses; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: humanfriendly in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (8.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: tabulate in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.8.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: ruamel.yaml>=0.15.0 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.15.87)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: py-zipkin in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.20.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.7.3 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (2.8.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: certifi in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (2020.6.20)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: multidict in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (4.7.6)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: protobuf>=3.6.0 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (3.13.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: flask in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: alembic in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: cerberus in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.3.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-json-logger in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (0.1.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: click>=7.0 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (7.1.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: sqlalchemy>=1.3.0 in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (1.3.19)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: configparser in /opt/conda/lib/python3.6/site-packages (from BentoML==0.9.0rc0+7.g8af1c8b) (5.0.0)\u001b[0m\n", "\b|\u001b[39mRequirement already satisfied, skipping upgrade: six>=1.5.2 in /opt/conda/lib/python3.6/site-packages (from grpcio<=1.27.2->BentoML==0.9.0rc0+7.g8af1c8b) (1.15.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: s3transfer<0.4.0,>=0.3.0 in /opt/conda/lib/python3.6/site-packages (from boto3->BentoML==0.9.0rc0+7.g8af1c8b) (0.3.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /opt/conda/lib/python3.6/site-packages (from boto3->BentoML==0.9.0rc0+7.g8af1c8b) (0.10.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: botocore<1.19.0,>=1.18.2 in /opt/conda/lib/python3.6/site-packages (from boto3->BentoML==0.9.0rc0+7.g8af1c8b) (1.18.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: setuptools>=3.0 in /opt/conda/lib/python3.6/site-packages (from gunicorn->BentoML==0.9.0rc0+7.g8af1c8b) (49.6.0.post20200814)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: idna<3,>=2.5 in /opt/conda/lib/python3.6/site-packages (from requests->BentoML==0.9.0rc0+7.g8af1c8b) (2.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: chardet<4,>=3.0.2 in /opt/conda/lib/python3.6/site-packages (from requests->BentoML==0.9.0rc0+7.g8af1c8b) (3.0.4)\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.6/site-packages (from requests->BentoML==0.9.0rc0+7.g8af1c8b) (1.25.10)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: pyparsing>=2.0.2 in /opt/conda/lib/python3.6/site-packages (from packaging->BentoML==0.9.0rc0+7.g8af1c8b) (2.4.7)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: immutables>=0.9 in /opt/conda/lib/python3.6/site-packages (from contextvars; python_version < \"3.7\"->BentoML==0.9.0rc0+7.g8af1c8b) (0.14)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: websocket-client>=0.32.0 in /opt/conda/lib/python3.6/site-packages (from docker->BentoML==0.9.0rc0+7.g8af1c8b) (0.57.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: async-timeout<4.0,>=3.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->BentoML==0.9.0rc0+7.g8af1c8b) (3.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: typing-extensions>=3.6.5; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from aiohttp->BentoML==0.9.0rc0+7.g8af1c8b) (3.7.4.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: attrs>=17.3.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->BentoML==0.9.0rc0+7.g8af1c8b) (20.2.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: yarl<2.0,>=1.0 in /opt/conda/lib/python3.6/site-packages (from aiohttp->BentoML==0.9.0rc0+7.g8af1c8b) (1.5.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: idna-ssl>=1.0; python_version < \"3.7\" in /opt/conda/lib/python3.6/site-packages (from aiohttp->BentoML==0.9.0rc0+7.g8af1c8b) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: thriftpy2>=0.4.0 in /opt/conda/lib/python3.6/site-packages (from py-zipkin->BentoML==0.9.0rc0+7.g8af1c8b) (0.4.11)\u001b[0m\n", "\b\\\u001b[39mRequirement already satisfied, skipping upgrade: Werkzeug>=0.15 in /opt/conda/lib/python3.6/site-packages (from flask->BentoML==0.9.0rc0+7.g8af1c8b) (1.0.1)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: Jinja2>=2.10.1 in /opt/conda/lib/python3.6/site-packages (from flask->BentoML==0.9.0rc0+7.g8af1c8b) (2.11.2)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: itsdangerous>=0.24 in /opt/conda/lib/python3.6/site-packages (from flask->BentoML==0.9.0rc0+7.g8af1c8b) (1.1.0)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: python-editor>=0.3 in /opt/conda/lib/python3.6/site-packages (from alembic->BentoML==0.9.0rc0+7.g8af1c8b) (1.0.4)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: Mako in /opt/conda/lib/python3.6/site-packages (from alembic->BentoML==0.9.0rc0+7.g8af1c8b) (1.1.3)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: ply<4.0,>=3.4 in /opt/conda/lib/python3.6/site-packages (from thriftpy2>=0.4.0->py-zipkin->BentoML==0.9.0rc0+7.g8af1c8b) (3.11)\u001b[0m\n", "\u001b[39mRequirement already satisfied, skipping upgrade: MarkupSafe>=0.23 in /opt/conda/lib/python3.6/site-packages (from Jinja2>=2.10.1->flask->BentoML==0.9.0rc0+7.g8af1c8b) (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+7.g8af1c8b-py3-none-any.whl size=620483 sha256=c0a193a2b7442065fb7abec76df7be020511af5c5a8ea34107d58bc21b9760e1\u001b[0m\n", "\u001b[39m Stored in directory: /root/.cache/pip/wheels/0f/c2/e2/64640eb406a012df3abf685e4e5fa441b87b3e609903d041b6\u001b[0m\n", "\u001b[39mSuccessfully built BentoML\u001b[0m\n", "\b|\u001b[39mInstalling collected packages: BentoML\u001b[0m\n", "\u001b[39m 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+7.g8af1c8b\u001b[0m\n", "\b\\\u001b[39m ---> 40090207374a\u001b[0m\n", "\u001b[39mStep 10/15 : ENV PORT 5000\u001b[0m\n", "\b-\u001b[39m ---> Running in bef4344724f5\u001b[0m\n", "\b|\u001b[39m ---> b336b939b877\u001b[0m\n", "\u001b[39mStep 11/15 : EXPOSE $PORT\u001b[0m\n", "\u001b[39m ---> Running in 94b0d4042e8c\u001b[0m\n", "\b-\u001b[39m ---> 6dbdacacc9ee\u001b[0m\n", "\u001b[39mStep 12/15 : COPY docker-entrypoint.sh /usr/local/bin/\u001b[0m\n", "\b|\u001b[39m ---> 08f3c0134892\u001b[0m\n", "\u001b[39mStep 13/15 : RUN chmod +x /usr/local/bin/docker-entrypoint.sh\u001b[0m\n", "\b\\\u001b[39m ---> Running in 919280fa3744\u001b[0m\n", "\b|\u001b[39m ---> 0c8922f41ad5\u001b[0m\n", "\u001b[39mStep 14/15 : ENTRYPOINT [ \"docker-entrypoint.sh\" ]\u001b[0m\n", "\b\\\u001b[39m ---> Running in cf1a37e5f312\u001b[0m\n", "\b/\u001b[39m ---> 084525a4fb10\u001b[0m\n", "\u001b[39mStep 15/15 : CMD [\"bentoml\", \"serve-gunicorn\", \"/bento\"]\u001b[0m\n", "\b|\u001b[39m ---> Running in ae9aab696766\u001b[0m\n", "\b-\u001b[39m ---> df4a2b1bf7e6\u001b[0m\n", "\u001b[39mSuccessfully built df4a2b1bf7e6\u001b[0m\n", "\u001b[39mSuccessfully tagged kerasfashionmnistservice:latest\u001b[0m\n", "\u001b[32mFinished building kerasfashionmnistservice:latest from KerasFashionMnistService:latest\u001b[0m\n" ] } ], "source": [ "!bentoml containerize KerasFashionMnistService:latest -t kerasfashionmnistservice:latest" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2020-09-23 05:35:06,581] INFO - Starting BentoML API server in production mode..\n", "[2020-09-23 05:35:06,806] INFO - get_gunicorn_num_of_workers: 3, calculated by cpu count\n", "[2020-09-23 05:35:06 +0000] [1] [INFO] Starting gunicorn 20.0.4\n", "[2020-09-23 05:35:06 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)\n", "[2020-09-23 05:35:06 +0000] [1] [INFO] Using worker: sync\n", "[2020-09-23 05:35:06 +0000] [13] [INFO] Booting worker with pid: 13\n", "[2020-09-23 05:35:06 +0000] [14] [INFO] Booting worker with pid: 14\n", "[2020-09-23 05:35:06 +0000] [15] [INFO] Booting worker with pid: 15\n", "[2020-09-23 05:35:07,826] 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-23 05:35:07,847] 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+7.g8af1c8b\n", "[2020-09-23 05:35:07,847] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.6.10, but current environment version is 3.6.12.\n", "[2020-09-23 05:35:07,855] 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-23 05:35:07,868] 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-23 05:35:07,877] 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+7.g8af1c8b\n", "[2020-09-23 05:35:07,877] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.6.10, but current environment version is 3.6.12.\n", "[2020-09-23 05:35:07,900] 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+7.g8af1c8b\n", "[2020-09-23 05:35:07,900] WARNING - Saved BentoService Python version mismatch: loading BentoService bundle created with Python version 3.6.10, but current environment version is 3.6.12.\n", "2020-09-23 05:35:09.265543: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA\n", "2020-09-23 05:35:09.288840: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2699905000 Hz\n", "2020-09-23 05:35:09.289083: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5637744043a0 executing computations on platform Host. Devices:\n", "2020-09-23 05:35:09.289103: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): , \n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "Using TensorFlow backend.\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "2020-09-23 05:35:09.320438: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA\n", "2020-09-23 05:35:09.328772: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2699905000 Hz\n", "2020-09-23 05:35:09.328969: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x563774404be0 executing computations on platform Host. Devices:\n", "2020-09-23 05:35:09.328987: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): , \n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "Using TensorFlow backend.\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "2020-09-23 05:35:09.378158: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA\n", "2020-09-23 05:35:09.388984: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2699905000 Hz\n", "2020-09-23 05:35:09.389196: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x563774403ae0 executing computations on platform Host. Devices:\n", "2020-09-23 05:35:09.389212: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): , \n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n", "/opt/conda/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n", " np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n", "Using TensorFlow backend.\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:137: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n", "\n", "2020-09-23 05:35:09.477116: W tensorflow/compiler/jit/mark_for_compilation_pass.cc:1412] (One-time warning): Not using XLA:CPU for cluster because envvar TF_XLA_FLAGS=--tf_xla_cpu_global_jit was not set. If you want XLA:CPU, either set that envvar, or use experimental_jit_scope to enable XLA:CPU. To confirm that XLA is active, pass --vmodule=xla_compilation_cache=1 (as a proper command-line flag, not via TF_XLA_FLAGS) or set the envvar XLA_FLAGS=--xla_hlo_profile.\n", "2020-09-23 05:35:09.535995: W tensorflow/compiler/jit/mark_for_compilation_pass.cc:1412] (One-time warning): Not using XLA:CPU for cluster because envvar TF_XLA_FLAGS=--tf_xla_cpu_global_jit was not set. If you want XLA:CPU, either set that envvar, or use experimental_jit_scope to enable XLA:CPU. To confirm that XLA is active, pass --vmodule=xla_compilation_cache=1 (as a proper command-line flag, not via TF_XLA_FLAGS) or set the envvar XLA_FLAGS=--xla_hlo_profile.\n", "2020-09-23 05:35:09.582936: W tensorflow/compiler/jit/mark_for_compilation_pass.cc:1412] (One-time warning): Not using XLA:CPU for cluster because envvar TF_XLA_FLAGS=--tf_xla_cpu_global_jit was not set. If you want XLA:CPU, either set that envvar, or use experimental_jit_scope to enable XLA:CPU. To confirm that XLA is active, pass --vmodule=xla_compilation_cache=1 (as a proper command-line flag, not via TF_XLA_FLAGS) or set the envvar XLA_FLAGS=--xla_hlo_profile.\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n", "\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 05:35:10,507] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 05:35:10,508] WARNING - pip package requirement keras already exist\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 05:35:10,525] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 05:35:10,525] WARNING - pip package requirement keras already exist\n", "WARNING:tensorflow:From /opt/conda/lib/python3.6/site-packages/bentoml/frameworks/keras.py:123: The name tf.keras.backend.get_session is deprecated. Please use tf.compat.v1.keras.backend.get_session instead.\n", "\n", "[2020-09-23 05:35:10,615] WARNING - pip package requirement tensorflow already exist\n", "[2020-09-23 05:35:10,616] WARNING - pip package requirement keras already exist\n", "[2020-09-23 05:35:55,479] ERROR - Exception on /predict [POST]\n", "Traceback (most recent call last):\n", " File \"/opt/conda/lib/python3.6/site-packages/bentoml/server/api_server.py\", line 288, in api_func\n", " response = api.handle_request(request)\n", " File \"/opt/conda/lib/python3.6/site-packages/bentoml/service/inference_api.py\", line 281, in handle_request\n", " results = self.infer((inf_task,))\n", " File \"/opt/conda/lib/python3.6/site-packages/bentoml/service/inference_api.py\", line 222, in infer\n", " user_args = self.input_adapter.extract_user_func_args(inf_tasks)\n", " File \"/opt/conda/lib/python3.6/site-packages/bentoml/adapters/image_input.py\", line 134, in extract_user_func_args\n", " img_array = imageio.imread(task.data, pilmode=self.pilmode)\n", " File \"/opt/conda/lib/python3.6/site-packages/imageio/core/functions.py\", line 265, in imread\n", " reader = read(uri, format, \"i\", **kwargs)\n", " File \"/opt/conda/lib/python3.6/site-packages/imageio/core/functions.py\", line 172, in get_reader\n", " request = Request(uri, \"r\" + mode, **kwargs)\n", " File \"/opt/conda/lib/python3.6/site-packages/imageio/core/request.py\", line 124, in __init__\n", " self._parse_uri(uri)\n", " File \"/opt/conda/lib/python3.6/site-packages/imageio/core/request.py\", line 222, in _parse_uri\n", " raise IOError(\"Cannot understand given URI: %s.\" % uri_r)\n", "OSError: Cannot understand given URI: None.\n", "[2020-09-23 05:36:09,200] INFO - {'service_name': 'KerasFashionMnistService', 'service_version': '20200923132350_974EEA', 'api': 'predict', 'task': {'data': {'name': 'sample_image.png'}, 'task_id': '895a16b1-c689-490f-b30e-c5601984093a', 'http_headers': (('Host', '127.0.0.1:5000'), ('User-Agent', 'curl/7.72.0'), ('Content-Length', '133877'), ('Accept', '*/*'), ('Content-Type', 'multipart/form-data; boundary=------------------------4f19d0a72380315e'))}, 'result': {'data': '\"Ankle boot\"', 'http_status': 200, 'http_headers': (('Content-Type', 'application/json'),)}, 'request_id': '895a16b1-c689-490f-b30e-c5601984093a'}\n", "^C\n", "[2020-09-23 05:36:20 +0000] [1] [INFO] Handling signal: int\n", "[2020-09-23 05:36:20 +0000] [13] [INFO] Worker exiting (pid: 13)\n", "[2020-09-23 05:36:20 +0000] [14] [INFO] Worker exiting (pid: 14)\n", "[2020-09-23 05:36:20 +0000] [15] [INFO] Worker exiting (pid: 15)\n" ] } ], "source": [ "!docker run -p 5000:5000 kerasfashionmnistservice" ] }, { "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": { "colab": { "collapsed_sections": [], "name": "basic_classification.ipynb", "private_outputs": true, "provenance": [], "toc_visible": true, "version": "0.3.2" }, "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.7.3" } }, "nbformat": 4, "nbformat_minor": 4 }