Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lordlinus/2bd08d0ff74f9919902376c37639bab7 to your computer and use it in GitHub Desktop.
Save lordlinus/2bd08d0ff74f9919902376c37639bab7 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{"cells":[{"cell_type":"markdown","source":["# Production deployment to AKS from Databricks using Azure ML SDK\n## Train, register model in Databricks, Azure ML, Deploy Azure ML model to AKS\n\nGoal of this notebook is to show the steps involved in deploying the model once it is built, although the example used is using scikit learn the same methodology can be applied to other machine learning models. This python notebook is tested on Databricks runtime 7.3 LTS ML | Spark 3.0.1 | Scala 2.12\n\n## Steps:\n* Train a model (In this notebook scikit learn using sample dataset)\n* Use MLflow to log the model in Databricks.\n* Download MLflow to the local Databricks environment.\n* Register MLflow model to Azure ML workspace\n* Deploy registered model to AKS. \n\n## Setup\n* If you are using a cluster running Databricks Runtime, you must install mlflow library from PyPI. See Cmd 3.\n* If you are using a cluster running Databricks Runtime ML, mlflow library is already installed.\n* Create Azure ML workspace"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"528c6d2b-3c5a-4236-ac61-fa8cc8d4d323"}}},{"cell_type":"markdown","source":["Install the mlflow library. \nThis is required for Databricks Runtime clusters only. If you are using a cluster running Databricks Runtime ML, skip to Cmd 4."],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"9596a0fc-f582-4e66-a457-f9549a700228"}}},{"cell_type":"code","source":["# If you are running Databricks Runtime version 7.1 or above, uncomment this line and run this cell:\n# %pip install mlflow\n# %pip install azureml-sdk[databricks]\n# %pip install azureml-mlflow\n\n# If you are running Databricks Runtime version 6.4 to 7.0, uncomment this line and run this cell:\n# dbutils.library.installPyPI(\"mlflow\")\n# dbutils.library.installPyPI(\"azureml-sdk[databricks]\")\n# dbutils.library.installPyPI(\"azureml-mlflow\")"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"4504cb32-8df6-4114-8e4c-a7ca5feb29ee"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["# %pip install msrest==0.6.21\n# Install this library if you see error/warnings during azureml-sdk import"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"0a7a8ca5-479a-459c-b00c-00341a3060d8"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Import the required libraries."],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"6b1f2b42-7670-4ac6-9f14-40e29cc9c122"}}},{"cell_type":"code","source":["import mlflow\nimport mlflow.sklearn\nfrom mlflow.tracking.client import MlflowClient\nfrom mlflow.entities import ViewType\n\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nfrom numpy import savetxt\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.datasets import load_diabetes\n\nfrom sklearn.ensemble import RandomForestRegressor\nfrom sklearn.metrics import mean_squared_error"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"cec61d6d-ea1a-4d2f-9ee6-625393a24aa5"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["* API reference: [Workspace Class](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.workspace.workspace?view=azure-ml-py)\n* NOTE: To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code received in the output cell to authenticate"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"c3077da7-b452-4f92-8f12-ada71fb3da3b"}}},{"cell_type":"code","source":["import azureml\nfrom azureml.core import Workspace\n\nsubscription_id = \"xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx\" #you should be owner or contributor\nresource_group = \"xxxxxx\" #you should be owner or contributor\nworkspace_name = \"xxxxx\" #your workspace name\nworkspace_region = \"southeastasia\" #your region (if workspace need to be created)\n\nworkspace = Workspace.create(name = workspace_name,\n location = workspace_region,\n resource_group = resource_group,\n subscription_id = subscription_id,\n exist_ok=True)\n# workspace.write_config()"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"d9c8a1be-ad97-4a1d-b0d5-79dafd93bc84"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Import the dataset from scikit-learn and create the training and test datasets.\n* Docs link [sklearn diabetes dataset](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_diabetes.html)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"b3b8e9ea-2046-48e0-bb26-d71c6669e66e"}}},{"cell_type":"code","source":["db = load_diabetes()\nX = db.data\ny = db.target\nX_train, X_test, y_train, y_test = train_test_split(X, y)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"e835da93-ac8c-4250-ab85-608ba2f280a8"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Create a random forest model and log parameters, metrics, and the model using `mlflow.sklearn.autolog()`.\n* Enable autolog() For details about what information is logged with `autolog()`, refer to the [MLflow documentation](https://mlflow.org/docs/latest/index.html)."],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"8123df40-67fa-43d0-97c1-6f608c9f7d61"}}},{"cell_type":"code","source":["mlflow.sklearn.autolog()\n\n# With autolog() enabled, all model parameters, a model score, and the fitted model are automatically logged. \nwith mlflow.start_run():\n \n # Set the model parameters. \n n_estimators = 100\n max_depth = 6\n max_features = 3\n \n # Create and train model.\n rf = RandomForestRegressor(n_estimators = n_estimators, max_depth = max_depth, max_features = max_features)\n rf.fit(X_train, y_train)\n \n # Use the model to make predictions on the test dataset.\n predictions = rf.predict(X_test)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"70fefb47-9af8-49c8-932d-49a0727c1428"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Get the current notebook path using scala dbutils api and pass it to widget. This widget value can then be retrived from python"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"6ffdee56-555e-4ec5-b131-3e439ce4fc90"}}},{"cell_type":"code","source":["%scala\nval notebookPath = dbutils.notebook.getContext.notebookPath.getOrElse(\"\")\ndbutils.widgets.text(\"Current_Notebook_Path\",notebookPath)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"9f643833-410b-4196-8c42-6af35c65d611"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["nb_path = dbutils.widgets.get(\"Current_Notebook_Path\")\nprint(nb_path)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"331b8781-ecee-4076-91aa-dd03a6185014"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["# Get current experiment ID, this is based on the notebook path\nnotebook_path = nb_path\nexp_id = mlflow.get_experiment_by_name(notebook_path).experiment_id\n\nbest_run = MlflowClient().search_runs(\n experiment_ids=exp_id,\n run_view_type=ViewType.ACTIVE_ONLY,\n max_results=1,\n order_by=[\"metrics.areaUnderROC DESC\"]\n)[0]"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"191c74ed-2492-4747-9e0f-66e0c855f049"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["best_run"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"167926ff-8fcc-491c-809f-186d9ceb3823"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["model_name = \"my-model-ss\" # Can be anything \nartifact_path = \"model\" # Folder where the model is saved, Recommended to keep it as model\nmodel_stage = 'Staging' # model stage, default is None, this example we are going to move the model to staging\nmodel_uri = f\"runs:/{best_run.info.run_id}/{artifact_path}\" # use the run_id from the best run\n# artifact_uri = best_run.info.artifact_uri\n# image_name = f\"{model_name}-image\""],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"38cdb950-5ff7-49c4-84cd-ea23cb5ae6d4"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["import mlflow.azureml\nfrom mlflow.azureml import mlflow_register_model\nfrom azureml.core.model import Model\nfrom mlflow.store.artifact.models_artifact_repo import ModelsArtifactRepository\nfrom mlflow.tracking.client import MlflowClient\nimport os\n\nclient = MlflowClient()\n\n# Register the model in Databricks, NOTE: It might take upto 300 sec for it to be register.\ndatabricks_mlflow_model = mlflow_register_model(name=model_name, model_uri=model_uri)\n\n# Moving the model to Staging in Databricks MLFlow\nclient.transition_model_version_stage(\n name=databricks_mlflow_model.name,\n version=databricks_mlflow_model.version,\n stage=model_stage,\n) \n\nmodel_path = f\"models:/{model_name}/{model_stage}\"\n\nos.makedirs(\"model\", exist_ok=True)\n\nlocal_path = ModelsArtifactRepository(model_path).download_artifacts(\"\",dst_path=\"model\") # Do not change the dst_path\n\nazureml_model =Model.register(workspace=workspace,\n model_path=local_path,\n model_name=model_name,\n description=\"Test model registry\")"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"282d8be4-0523-41c0-a1ef-e6be2776b88c"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Un-comment the below cell to create a new AKS cluster"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"71f86965-7822-4617-8c1c-293a132a45d3"}}},{"cell_type":"code","source":["# Create new AKS compute\n# from azureml.core.compute import AksCompute, ComputeTarget\n# prov_config = AksCompute.provisioning_configuration()\n# aks_name = 'aks-mlflow'\n\n# # Create the cluster\n# aks_target = ComputeTarget.create(workspace=workspace, \n# name=aks_name, \n# provisioning_configuration=prov_config)\n\n# aks_target.wait_for_completion(show_output = True)\n\n# print(aks_target.provisioning_state)\n# print(aks_target.provisioning_errors)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"56611ba7-d33f-4497-b9a5-96b276a769f3"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Use existing AKS cluster (NOTE: you need to add this AKS cluster as inference target in Azure ML)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"bbf3492a-d249-420f-8f93-cc49c7492af9"}}},{"cell_type":"code","source":["# Connect to existing AKS\nfrom azureml.core.compute import AksCompute, ComputeTarget\n\n# Give the cluster a local name\naks_compute_name = \"aks-mlflow\"\n\naks_target = AksCompute(workspace,aks_compute_name)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"9a054a6b-47a2-454e-86bc-619e6d4bec13"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Sample `score.py` script for the entry point to the container"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"58933c14-a3e8-4c79-b8ac-2299dde286b4"}}},{"cell_type":"code","source":["score_py = \"\"\"import joblib\nimport numpy as np\nimport os\n\nfrom inference_schema.schema_decorators import input_schema, output_schema\nfrom inference_schema.parameter_types.numpy_parameter_type import NumpyParameterType\n\n\n# The init() method is called once, when the web service starts up.\n#\n# Typically you would deserialize the model file, as shown here using joblib,\n# and store it in a global variable so your run() method can access it later.\ndef init():\n global model\n\n # The AZUREML_MODEL_DIR environment variable indicates\n # a directory containing the model file you registered.\n model_filename = 'model.pkl'\n model_path = os.path.join(os.environ['AZUREML_MODEL_DIR'],'model',model_filename)\n model = joblib.load(model_path)\n\n\n# The run() method is called each time a request is made to the scoring API.\n#\n# Shown here are the optional input_schema and output_schema decorators\n# from the inference-schema pip package. Using these decorators on your\n# run() method parses and validates the incoming payload against\n# the example input you provide here. This will also generate a Swagger\n# API document for your web service.\n@input_schema('data', NumpyParameterType(np.array([[0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0]])))\n@output_schema(NumpyParameterType(np.array([4429.929236457418])))\ndef run(data):\n # Use the model object loaded by init().\n result = model.predict(data)\n\n # You can return any JSON-serializable object.\n return result.tolist()\n\"\"\"\n\nwith open('score.py','w') as f:\n f.write(score_py)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"e7fa577c-8a93-403c-89df-1249d564b77c"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Deployment to AKS can take upto 10 min, if this step take longer than that troubleshoot using the api [link](https://aka.ms/debugimage#dockerlog) or from Azure ML deploymnet logs"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"948b2f94-d218-4342-b24b-1e0892ef454a"}}},{"cell_type":"code","source":["from azureml.core.model import InferenceConfig\nfrom azureml.core.webservice import Webservice, AksWebservice\nfrom azureml.core.environment import Environment,CondaDependencies\nfrom azureml.core.model import InferenceConfig, Model\nfrom azureml.core.webservice.aks import AksServiceDeploymentConfiguration\n\n# Choosing AzureML-Minimal and customizing as required ( see the last cell to display available environments)\nenv = Environment.get(workspace=workspace, name=\"AzureML-Minimal\")\ncurated_clone = env.clone(\"customize_curated\")\n\nconda_dep_pkgs=['joblib','scikit-learn']\npip_pkgs=['azureml-defaults', 'inference-schema']\nconda_dep = CondaDependencies()\n\n# Install additional packages as required\nfor conda_dep_pkg in conda_dep_pkgs:\n conda_dep.add_conda_package(conda_package=conda_dep_pkg)\n\nfor pip_pkg in pip_pkgs:\n conda_dep.add_pip_package(pip_package=pip_pkg)\n\ncurated_clone.python.conda_dependencies=conda_dep\n\nprod_webservice_name = \"diabetes-model-prod\"\nprod_webservice_deployment_config = AksWebservice.deploy_configuration()\n\n# NOTE: score.py is created in the previous cell and save to driver local path\ninference_config = InferenceConfig(entry_script='score.py', environment=curated_clone)\n\nservice = Model.deploy(workspace=workspace,\n name=prod_webservice_name,\n models=[azureml_model],\n inference_config=inference_config,\n deployment_config=prod_webservice_deployment_config,\n deployment_target = aks_target,\n overwrite=True)\n\nservice.wait_for_deployment(show_output=True)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"5347ca65-d6f6-4203-ae4b-d190e7daa5b7"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["print(service.get_logs())"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"5b8d22c6-7e27-4e68-b812-6ce804e3a60a"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"markdown","source":["Print the scoring url ( NOTE: This is also available from Azure ML studio under Endpoints section)"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"9918652f-3170-4ab6-ac41-3722674c5336"}}},{"cell_type":"code","source":["service.scoring_uri"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"a53aae37-c066-44c2-b411-bec3eb97220f"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["# envs = Environment.list(workspace=workspace)\n# # Print list of environments available in Azure ML\n# for env in envs:\n# if env.startswith(\"AzureML\"):\n# print(\"Name\",env)\n# print(\"packages\", envs[env].python.conda_dependencies.serialize_to_string())"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"d2aa93d9-228a-4484-9ea0-b5790eb52b25"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0},{"cell_type":"code","source":["# Remove the widgets\ndbutils.widgets.removeAll()"],"metadata":{"application/vnd.databricks.v1+cell":{"title":"","showTitle":false,"inputWidgets":{},"nuid":"cb6fe12a-f238-4a45-b52a-ca879b9b193d"}},"outputs":[{"output_type":"display_data","metadata":{"application/vnd.databricks.v1+output":{"data":"","errorSummary":"","metadata":{},"errorTraceType":null,"type":"ipynbError","arguments":{}}},"output_type":"display_data","data":{"text/html":["<style scoped>\n .ansiout {\n display: block;\n unicode-bidi: embed;\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n font-family: \"Source Code Pro\", \"Menlo\", monospace;;\n font-size: 13px;\n color: #555;\n margin-left: 4px;\n line-height: 19px;\n }\n</style>"]}}],"execution_count":0}],"metadata":{"application/vnd.databricks.v1+notebook":{"notebookName":"production-deployment-to-AKS-from-Databricks","dashboards":[],"notebookMetadata":{"pythonIndentUnit":2,"experimentId":"2379837548404309"},"language":"python","widgets":{},"notebookOrigID":2379837548404309}},"nbformat":4,"nbformat_minor":0}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment