{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Models and Pipelines are Core SDK Abstractions\n",
    "\n",
    "This notebook demonstrates how models can be deployed as steps in pipelines implictly and explicitly. Older concepts such as Deployment, PipelineVariant, and PipelineConfigBuilder are no longer necessary. We simply deploy and undeploy pipelines.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "import os\n",
    "\n",
    "import wallaroo\n",
    "from wallaroo.pipeline   import Pipeline\n",
    "\n",
    "\n",
    "model_path = \"keras_ccfraud.onnx\"\n",
    "data_path = \"dev_smoke_test.json\"\n",
    "with open(data_path, \"rb\") as f:data = json.load(f)\n",
    "    \n",
    "wl = wallaroo.Client()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Convenience Style - single model\n",
    "\n",
    "Lets create and deploy a pipeline with a single model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ..... ok\n"
     ]
    }
   ],
   "source": [
    "pipeline = wl.upload_model(name=\"ccfraud2\", path=model_path).deploy(\"single-model\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can easily undeploy it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'single-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 9, 11, 19234, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's redeploy it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ...... ok\n"
     ]
    },
    {
     "data": {
      "text/plain": [
        "{'name': 'single-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 10, 11, 32734, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[InferenceResult({'check_failures': [],\n",
       "  'elapsed': 103147,\n",
       "  'model_name': 'ccfraud2',\n",
       "  'model_version': 'b75496c3-5e00-461d-b921-feaf3ae7dec8',\n",
       "  'original_data': {'tensor': [[1.0678324729342086,\n",
       "                                0.21778102664937624,\n",
       "                                -1.7115145261843976,\n",
       "                                0.6822857209662413,\n",
       "                                1.0138553066742804,\n",
       "                                -0.43350000129006655,\n",
       "                                0.7395859436561657,\n",
       "                                -0.28828395953577357,\n",
       "                                -0.44726268795990787,\n",
       "                                0.5146124987725894,\n",
       "                                0.3791316964287545,\n",
       "                                0.5190619748123175,\n",
       "                                -0.4904593221655364,\n",
       "                                1.1656456468728569,\n",
       "                                -0.9776307444180006,\n",
       "                                -0.6322198962519854,\n",
       "                                -0.6891477694494687,\n",
       "                                0.17833178574255615,\n",
       "                                0.1397992467197424,\n",
       "                                -0.35542206494183326,\n",
       "                                0.4394217876939808,\n",
       "                                1.4588397511627804,\n",
       "                                -0.3886829614721505,\n",
       "                                0.4353492889350186,\n",
       "                                1.7420053483337177,\n",
       "                                -0.4434654615252943,\n",
       "                                -0.15157478906219238,\n",
       "                                -0.26684517248765616,\n",
       "                                -1.454961775612449]]},\n",
       "  'outputs': [{'Float': {'data': [0.001497417688369751],\n",
       "                         'dim': [1, 1],\n",
       "                         'v': 1}}],\n",
       "  'pipeline_name': 'single-model',\n",
       "  'time': 1644014192840})]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.infer(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'single-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 11, 11, 65536, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Convenience Style - chain a second model on the end\n",
    "\n",
    "Lets create a pipeline, deploy it, add another model step to the end and redeploy it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ...... ok\n"
     ]
    }
   ],
   "source": [
    "pipeline = wl.upload_model(name=\"ccfraud\", path=model_path).deploy(\"chained-model\")\n",
    "model2 = wl.upload_model(name=\"ccfraud2\", path=model_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'chained-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 12, 11, 65536, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.add_model_step(model2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " ok\n"
     ]
    },
    {
     "data": {
      "text/plain": [
        "{'name': 'chained-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 12, 42, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'chained-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 13, 17, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Convenience Style - replace a model\n",
    "\n",
    "We can replace a model model by clearing the steps and adding a new step with the new model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ...... ok\n"
     ]
    }
   ],
   "source": [
    "pipeline = wl.upload_model(name=\"ccfraud\", path=model_path).deploy(\"replaced-model\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " ok\n"
     ]
    },
    {
     "data": {
      "text/plain": [
        "{'name': 'replaced-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 14, 17, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.clear().add_model_step(model2).deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'replaced-model', 'create_time': datetime.datetime(2021, 5, 22, 4, 14, 51, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replace a model in the middle of a pipeline\n",
    "\n",
    "Each \"add_\\<step\\>\" method has an equivalent \"replace_with_\\<step\\>\" method. See the pipeline documentation for details\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "model1 = wl.upload_model(\"preprocess\", \"./test_resources/pre_process.py\").configure('python')\n",
    "model2 = wl.upload_model(\"noopfloats\", \"./test_resources/no-op-floats.onnx\").configure('onnx')\n",
    "model3 = wl.upload_model(\"postprocess\", \"./test_resources/post_process.py\").configure('python')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets create a pipeline with three model steps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ........ ok\n"
     ]
    }
   ],
   "source": [
    "python_pipeline = (wl.build_pipeline(\"pythonpipeline\")\n",
    "        .add_model_step(model1)\n",
    "        .add_model_step(model2)\n",
    "        .add_model_step(model3)).deploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll replace the step at index 1 (second step in the pipeline) with a different model step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "model2_replacement = wl.upload_model(\"some-other-model\", \"./test_resources/no-op-floats.onnx\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " ok\n"
     ]
    },
    {
     "data": {
      "text/plain": [
        "{'name': 'pythonpipeline', 'create_time': datetime.datetime(2021, 5, 22, 4, 15, 2, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "python_pipeline.replace_with_model_step(1, model2_replacement).deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'pythonpipeline', 'create_time': datetime.datetime(2021, 5, 22, 4, 15, 38, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Explicit Style with all options\n",
    "\n",
    "Now will create a pipeline with models that have configuration options set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "model1 = wl.upload_model(name=\"ccfraud\", path=model_path).configure(filter_threshold=0.123)\n",
    "model2 = wl.upload_model(name=\"ccfraud2\", path=model_path).configure()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for deployment - this will take up to 45s ...... ok\n"
     ]
    },
    {
     "data": {
      "text/plain": [
        "{'name': 'all-options', 'create_time': datetime.datetime(2021, 5, 22, 4, 14, 17, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline = wl.build_pipeline(\"all-options\")\n",
    "pipeline.add_model_step(model1)\n",
    "pipeline.add_model_step(model2)\n",
    "pipeline.deploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
        "{'name': 'all-options', 'create_time': datetime.datetime(2021, 5, 22, 4, 14, 19, 86529, tzinfo=tzutc()), 'definition': \"[{'ModelInference': {'models': [{'name': 'ccfraud2', 'version': '76cacac7-1dc7-41fc-8b7a-1e5dc17a093c', 'sha': '4dc88d159249ccce83942ada69b919cb91455d5fd0e4bfc287de3f21d1aafb1b'}]}}]\"}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline.undeploy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
