{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Prediction\n",
    "### Deploy ML model using KServe inference service"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import yaml\n",
    "import json\n",
    "\n",
    "def deploy_kserve_model(json_file_path):\n",
    "    try:\n",
    "        # Run kubectl apply command using subprocess\n",
    "        subprocess.run(['kubectl', 'apply', '-f', json_file_path], check=True)\n",
    "        print(\"Deployment successful!\")\n",
    "    except subprocess.CalledProcessError as e:\n",
    "        print(f\"Deployment failed. Error: {e}\")\n",
    "\n",
    "###################################################################################\n",
    "## update kserve-mlflow-deploy \n",
    "with open('kserve/kserve-mlflow-deploy.yaml', 'r') as file:\n",
    "    yaml_data = yaml.safe_load(file)\n",
    "\n",
    "## set model name - tutorial default logs model under experiment name\n",
    "model_name = 'bike-sharing-exp'\n",
    "with open('best-model-uri.txt','r') as f:\n",
    "    storage_uri = f.read()\n",
    "# Convert YAML to JSON\n",
    "json_data = json.dumps(yaml_data)\n",
    "data = json.loads(json_data)\n",
    "\n",
    "data[\"metadata\"][\"namespace\"] = os.environ['NOTEBOOK_NAMESPACE']\n",
    "data[\"metadata\"][\"name\"] = model_name\n",
    "data['spec']['predictor']['sklearn']['storageUri'] = f\"{storage_uri}/model.pkl\"\n",
    "\n",
    "# Save the JSON data to a file\n",
    "with open('kserve/kserve-mlflow-deploy.json', 'w') as file:\n",
    "    file.write(json.dumps(data))\n",
    "\n",
    "# Specify the path to your JSON file\n",
    "json_file_path = 'kserve/kserve-mlflow-deploy.json'\n",
    "\n",
    "# Call the function to deploy the Kubernetes resource to deploy ml model \n",
    "deploy_kserve_model(json_file_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Deployment of kserve will take few minutes to comes to ready state, so wait for few minutes before actually executing the below cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import requests\n",
    "\n",
    "DOMAIN_NAME = \"svc.cluster.local\" # change this to your domain for external access \n",
    "NAMESPACE = os.environ['NOTEBOOK_NAMESPACE']\n",
    "DEPLOYMENT_NAME = model_name\n",
    "MODEL_NAME = model_name\n",
    "if DOMAIN_NAME == \"svc.cluster.local\":\n",
    "    PROTO = \"http\"\n",
    "    SVC = f'{DEPLOYMENT_NAME}.{NAMESPACE}.{DOMAIN_NAME}'\n",
    "    VERIFY = False\n",
    "else:\n",
    "    PROTO = \"https\"\n",
    "    SVC = f'{DEPLOYMENT_NAME}.{NAMESPACE}.serving.{DOMAIN_NAME}'\n",
    "    VERIFY = os.environ['EZUA_DOMAIN_CA_CERT_PATH']\n",
    "URL = f\"{PROTO}://{SVC}/v2/models/{MODEL_NAME}/infer\"\n",
    "\n",
    "print(URL)\n",
    "\n",
    "names = ['season', 'year', 'month', 'hour_of_day', 'is_holiday', 'weekday', 'is_workingday', \n",
    "         'weather_situation', 'temperature', 'feels_like_temperature', 'humidity', 'windspeed']\n",
    "\n",
    "input_data = [\n",
    "    [1, 2, 1, 0, 0, 6, 0, 1, 0.24, 0.2879, 0.81, 0.0000],\n",
    "    [1, 5, 1, 0, 0, 6, 1, 1, 0.24, 0.2879, 0.81, 0.0000]\n",
    "]\n",
    "\n",
    "inputs = {\n",
    "  \"inputs\": [\n",
    "    {\n",
    "      \"name\": \"ndarray\",\n",
    "      \"shape\": [2, 12],\n",
    "      \"datatype\": \"FP32\",\n",
    "      \"data\": input_data\n",
    "    }\n",
    "  ]\n",
    "}\n",
    "\n",
    "%update_token\n",
    "\n",
    "headers = {\"Authorization\": f\"Bearer {os.environ['AUTH_TOKEN']}\"}\n",
    "\n",
    "response = requests.post(URL, json=inputs, headers=headers, verify=VERIFY)\n",
    "\n",
    "print(response.reason)\n",
    "\n",
    "output = response.json()['outputs'][0]['data']\n",
    "\n",
    "print(\"Rendted Bikes Per Hours:\\n\")\n",
    "for item, out in zip(input_data, output):\n",
    "    input_dict = dict(zip(names,item))\n",
    "    print(f\"Input Data: {input_dict} \\n\\nBike Per Hour: {out}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "### Accessing KServe API from an External Network\n",
    "\n",
    "#### Initializing Configuration Variables\n",
    "```bash\n",
    "DOMAIN=<hpe-example-ezaf.com>\n",
    "USERNAME=<examle-user01>\n",
    "PASSWORD=<example-password>\n",
    "KC_ADDR=<keycloak.$DOMAIN>\n",
    "```\n",
    "\n",
    "\n",
    "#### Acquiring Access and Refresh Tokens for Authentication\n",
    "\n",
    "```bash\n",
    "response_json=$(curl -k --data \"username=$USERNAME&password=$PASSWORD&grant_type=password&client_id=ua-grant\" \"https://$KC_ADDR/realms/UA/protocol/openid-connect/token\")\n",
    "\n",
    "REFRESH_TOKEN=$(echo \"$response_json\" | jq -r '.refresh_token')\n",
    "ACCESS_TOKEN=$(echo \"$response_json\" | jq -r '.access_token')\n",
    "```\n",
    "\n",
    "#### Configuring Variables for Model Inference\n",
    "\n",
    "```bash\n",
    "SVC=<service>\n",
    "MODEL_NAME=<model_name>\n",
    "NAMESPACE=<ns>\n",
    "```\n",
    "\n",
    "#### Executing Inference Request (Example: Bike Sharing Data)\n",
    "\n",
    "```bash\n",
    "curl --request POST \"https://$SVC.$NAMESPACE.$DOMAIN/v2/models/$MODEL_NAME/infer\" -k -H \"Authorization: Bearer $ACCESS_TOKEN\" --header 'Content-Type: application/json' --data-raw '{\"inputs\":[{\"name\":\"ndarray\",\"datatype\":\"FP32\",\"shape\":[2,12],\"data\":[[1, 2, 1, 0, 0, 6, 0, 1, 0.24, 0.2879, 0.81, 0.0000],[1, 5, 1, 0, 0, 6, 1, 1, 0.24, 0.2879, 0.81, 0.0000]]}]}'\n",
    "```\n",
    "\n",
    "#### Renewing Access Token Using Refresh Token (When Necessary)\n",
    "\n",
    "```bash\n",
    "response_json=$(curl -k --data \"grant_type=refresh_token&client_id=ua-grant&refresh_token=$REFRESH_TOKEN\" \"https://$KC_ADDR/realms/UA/protocol/openid-connect/token\")\n",
    "ACCESS_TOKEN=$(echo \"$response_json\" | jq -r '.access_token')\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
