{
  "metadata": {
    "hide_input": false,
    "kernelspec": {
      "name": "py-dku-venv-py_39_mlflow_in_dku",
      "display_name": "Python (env py_39_mlflow_in_dku)",
      "language": "python"
    },
    "language_info": {
      "name": "python",
      "version": "3.9.20",
      "mimetype": "text/x-python",
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "pygments_lexer": "ipython3",
      "nbconvert_exporter": "python",
      "file_extension": ".py"
    },
    "createdOn": 1638796031687,
    "tags": [
      "recipe-editor"
    ],
    "customFields": {},
    "associatedRecipe": "recipe_from_notebook_import_mlflow_models",
    "creator": "admin",
    "modifiedBy": "camille.cochener"
  },
  "nbformat": 4,
  "nbformat_minor": 1,
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Importing MLflow models in DSS\n\nIn this notebook we show through a simple example how to import a machine learning model trained *entirely out of DSS* into a SavedModel in a project\u0027s Flow. We use the [Catboost]() framework to perform a binary classification task on the [UCI Bank dataset]()."
      ]
    },
    {
      "execution_count": 0,
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import dataiku\nimport dataikuapi\nimport os\n\nfrom dataikuapi.dss.ml import DSSPredictionMLTaskSettings"
      ],
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Step 1: train your model outside of DSS\n\nTo replicate the training of the model, perform the following actions *outside of DSS*:\n* Create a virtual environment using Python \u003e\u003d 3.9 and install the packages listed in `requirement.txt` (can be found in the model folder in the managed folder `MLflow model`).\n* Activate the newly-created virtual environment\n* Go to `src/` and train the model by running `python train_catboost.py`. The resulting model artifact will be stored in the `dist/` directory, its name should be of the form `catboost-uci-bank-xxxxxxxx-xxxxxx`.\n\n\u003e **WARNING**: Any pre-processing step applied to the training data **MUST** also be applied to the evaluation data."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Step 2: create the code env in DSS\n\nIn the *Administration \u003e Code envs* section of DSS, create a new code environment and add the packages listed in the archive\u0027s `requirement.txt` file (minus `pandas`), then build the code-env.\n\n\u003e **This notebook should be running using that code env ! **\n\nWrite down the name of that code env, you will need it to call `import_mlflow_version_from_path()`."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Step 3: get a handle on a SavedModel"
      ]
    },
    {
      "execution_count": 0,
      "cell_type": "code",
      "metadata": {},
      "source": [
        "client \u003d dataiku.api_client()\nproject \u003d client.get_default_project()\n\n# Get or create SavedModel\nsm_name \u003d \"catboost-uci-bank\"\nsm_id \u003d None\nfor sm in project.list_saved_models():\n    if sm_name !\u003d sm[\"name\"]:\n        continue\n    else:\n        sm_id \u003d sm[\"id\"]\n        print(\"Found SavedModel {} with id {}\".format(sm_name, sm_id))\n        break\nif sm_id:\n    sm \u003d project.get_saved_model(sm_id)\nelse:\n    sm \u003d project.create_mlflow_pyfunc_model(name\u003dsm_name,\n                                            prediction_type\u003dDSSPredictionMLTaskSettings.PredictionTypes.BINARY)\n    sm_id \u003d sm.id\n    print(\"SavedModel not found, created new one with id {}\".format(sm_id))"
      ],
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Step 4: import the evaluation dataset\n\nCreate a new Dataset in your DSS project by uploading `data/uci-bank-marketing/eval_data.csv`. Call this Dataset `eval_data`.\n\n\u003e **WARNING**: The evaluation Dataset **MUST** already be preprocessed using the exact same steps as in step 1 !"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Step 5: import mlflow model into a SavedModel version"
      ]
    },
    {
      "execution_count": 0,
      "cell_type": "code",
      "metadata": {},
      "source": [
        "folder \u003d dataiku.Folder(\"M8tpkIby\")\nfolder_path \u003d folder.get_path()\n\n# Change the following values to match your setup !\nMLFLOW_DIST_DIR \u003d folder_path + \"/mlflow-model-import/dist/\"\nCATBOOST_MODEL_DIR \u003d \"catboost-uci-bank-20211213-162747\"\n\nversion_id \u003d \"v32\" # Change this to iterate to a new version\nmodel_dir \u003d os.path.join(MLFLOW_DIST_DIR, CATBOOST_MODEL_DIR)\n\n# Create version in SavedModel\nfor v in sm.list_versions():\n    if v[\"id\"] \u003d\u003d version_id:\n        raise Exception(\"SavedModel version already exists! Choose a new version name.\")\n\nsm_version \u003d sm.import_mlflow_version_from_path(version_id\u003dversion_id,\n                                                path\u003dmodel_dir,\n                                                code_env_name\u003d\"py_39_mlflow_in_dku\")\n\n# Evaluate the version using the previously created Dataset\nsm_version.set_core_metadata(target_column_name\u003d\"y\",\n                             class_labels\u003d[\"no\", \"yes\"],\n                             get_features_from_dataset\u003d\"eval_data\")\nsm_version.evaluate(\"eval_data\")"
      ],
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If you go to the SavedModel\u0027s version screen, you should now be able to see properly all the \"Performance\" visualizations."
      ]
    }
  ]
}