<jupyter_start><jupyter_text>Oracle Cloud Infrastructure Data Science Sample NotebookCopyright (c) 2021 Oracle, Inc.  All rights reserved. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.  Deploying an XGBoost Model with Model Deployment In this tutorial we are going to prepare and save an xgboost model artifact using the `ADSModel` `prepare()` method and deploy the model as an HTTP endpoint.  Pre-requisites to Running this Notebook  * We recommend that you run this notebook in a notebook session using the **Data Science Conda Environment "General Machine Learning for CPU (v1.0)"** * You need access to the public internet* Upgrade the current version of the OCI Python SDK (`oci`):<jupyter_code>!pip install --upgrade oci
import oci
import ads
import json
import logging
import os
import tempfile
import warnings
from os import path
from ads.common.model import ADSModel
from ads.common.model_artifact import ModelArtifact
from ads.dataset.dataset_browser import DatasetBrowser
from xgboost import XGBRegressor
from xgboost import XGBClassifier
import time

logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.ERROR)
warnings.filterwarnings('ignore')
ads.set_documentation_mode(False)<jupyter_output><empty_output><jupyter_text>We're going to train a simple XGBoost classifier on the breast cancer dataset included in sklearn;<jupyter_code># Train xgboost model
breast_cancer = DatasetBrowser.sklearn().open('breast_cancer').set_target("target")
train, test = breast_cancer.train_test_split(test_size=0.15)
xgb_clf = XGBClassifier().fit(train.X.values, train.y)
xgb_bin_model = ADSModel.from_estimator(xgb_clf)<jupyter_output><empty_output><jupyter_text>Here we are using the "General Machine Learning for CPU" Data Science conda environment. Since we don't modify the conda environment we don't need to publish it. We can use "General Machine learning for CPU (v1.0)" for model deployment as well. Thus we'll set `data_science_env=True` when preparing the artifact with ADS. Here we are using the `prepare()` method on an `ADSModel` object.<jupyter_code># Prepare the model artifact template
path_to_model_artifacts = "xboost_artifacts"
model_artifact = xgb_bin_model.prepare(path_to_model_artifacts,
                                       force_overwrite=True,
                                       data_sample=test,
                                       fn_artifact_files_included=False,
                                       data_science_env=True)<jupyter_output><empty_output><jupyter_text>Let's take a look at the artifact template files that ADS generated.<jupyter_code># List the template files
print(f"Model Artifact Path: {path_to_model_artifacts}\n\nModel Artifact Files:")
for file in os.listdir(path_to_model_artifacts):
    if path.isdir(path.join(path_to_model_artifacts, file)):
        for file2 in os.listdir(path.join(path_to_model_artifacts, file)):
            print(path.join(file, file2))
    else:
        print(file)<jupyter_output><empty_output><jupyter_text>Let's test the artifact before saving it to the model catalog and verify that the predictions made on a sample data match what we expect<jupyter_code># Validate predicion
model_artifact.predict(data=test.X[:5], model=model_artifact.load_model())<jupyter_output><empty_output><jupyter_text>We can now save the model to the catalog:<jupyter_code>project_id = os.environ['PROJECT_OCID'] 
compartment_id = os.environ['NB_SESSION_COMPARTMENT_OCID']

mc_model = model_artifact.save(
    project_id=project_id, compartment_id=compartment_id, 
    display_name="XGB_model (Model Deployment Test)",
    description="Testing XGB_model Model Deployment",
    ignore_pending_changes=True)<jupyter_output><empty_output><jupyter_text>The model metadata, including its OCID value (`id`):<jupyter_code># Print published model information
mc_model<jupyter_output><empty_output><jupyter_text>Deploying the model with Model DeploymentWe are ready to deploy `mc_model`. We are using the user principal (config+key) method of authentication. Alternatively you can use resource principal.<jupyter_code># Getting OCI config information
oci_config = oci.config.from_file("~/.oci/config", "DEFAULT")
# Setting up DataScience instance
data_science = oci.data_science.DataScienceClient(oci_config)
# Setting up data science composite client to unlock wait_for_state operations
data_science_composite = oci.data_science.DataScienceClientCompositeOperations(data_science)<jupyter_output><empty_output><jupyter_text>The model deployment configuration object:<jupyter_code># Prepareing model deployment data
model_deployment_details = {
    "displayName": "XGB model test - ONNX",
    "projectId": mc_model.project_id,
    "compartmentId": mc_model.compartment_id,
    "modelDeploymentConfigurationDetails": {
        "deploymentType": "SINGLE_MODEL",
        "modelConfigurationDetails": {
            "modelId": mc_model.id,
            "instanceConfiguration": {
                "instanceShapeName": "VM.Standard2.4"
            },
            "scalingPolicy": {
                "policyType": "FIXED_SIZE",
                "instanceCount": 2
            },
            "bandwidthMbps": 10
        }
    },
    "categoryLogDetails": None
}<jupyter_output><empty_output><jupyter_text>We are now ready to deploy. This takes a few minutes to complete.<jupyter_code>%%time

model_deployment = data_science_composite.create_model_deployment_and_wait_for_state(model_deployment_details,
                                                                                     wait_for_states=["SUCCEEDED",
                                                                                                      "FAILED"])<jupyter_output><empty_output><jupyter_text>Let's make sure our deployment was successful:<jupyter_code>print("Grabbing the model deployment ocid...")
model_deployment_data = json.loads(str(model_deployment.data))
model_deployment_id = model_deployment_data['resources'][0]['identifier']
print(f"Model deployment ocid: {model_deployment_id}")

# check if the model deployment was successful: 
assert model_deployment.status == 200, f"Model deployment issued an HTTP error code: {model_deployment.status}"<jupyter_output><empty_output><jupyter_text>If the model deployment was unsuccessful, we recommend that you follow the Troubleshooting guide in our service documentation.   Invoking the Model Deployment `/predict` Endpoint  Lastly we want to invoke the `/predict` endpoint of the deployed model and make inferences on a batch of<jupyter_code>import requests
import oci
from oci.signer import Signer<jupyter_output><empty_output><jupyter_text>Before you can execute the cell below, copy and paste the URI of your model deployment. You can find that value in the OCI console under the detail page of your model deployment. In the **Resources** menu of the detail page, click on **"Invoking Your Model"**. You will find the HTTP endpoint of the model.<jupyter_code>uri = f"<replace-with-your-model-deployment-uri>"
print(uri)
using_rps = False

# payload: 
input_data = train.X[:5].to_json()

if using_rps: # using resource principal:     
    auth = oci.auth.signers.get_resource_principals_signer()
else: # using config + key: 
    config = oci.config.from_file("~/.oci/config") # replace with the location of your oci config file
    auth = Signer(
        tenancy=config['tenancy'],
        user=config['user'],
        fingerprint=config['fingerprint'],
        private_key_file_location=config['key_file'],
        pass_phrase=config['pass_phrase'])
%%time
    
# submit request to model endpoint: 
response = requests.post(uri, json=input_data, auth=auth)<jupyter_output><empty_output><jupyter_text>Let's take a look at the status code:<jupyter_code>response.status_code<jupyter_output><empty_output><jupyter_text>and the model predictions:<jupyter_code>print(json.loads(response.content))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08414848256834713, 'fraction_numerical': 0.0032605969400551793, 'mean_word_length': 4.481099656357388, 'pattern_counts': {'":': 14, '<': 62, '<?xml version=': 0, '>': 62, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '571120', 'license': 'UPL-1.0', 'n_tokens_mistral': 2362, 'n_tokens_neox': 2284, 'n_words': 654, 'path': 'model_catalog_examples/notebook_examples/xgboost_onnx.ipynb', 'repo_name': 'jrgauthier01/oci-data-science-ai-samples', 'size': '7974'}