Skip to content

Commit 9ec5009

Browse files
authored
Merge pull request #54 from microsoft/sudivate/scoringimage
Sudivate/scoringimage
2 parents c540a2f + 984399b commit 9ec5009

File tree

6 files changed

+130
-43
lines changed

6 files changed

+130
-43
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ AML_CLUSTER_MIN_NODES = ''
2222
AML_CLUSTER_PRIORITY = 'lowpriority'
2323
# Training Config
2424
MODEL_NAME = ''
25+
MODEL_VERSION = ''
2526
# AML Pipeline Config
2627
TRAINING_PIPELINE_NAME = ''
2728
PIPELINE_CONDA_PATH = 'aml_config/conda_dependencies.yml'

docs/getting_started.md

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Please make note of the following values after creating a service principal, we
2020
- Application Secret
2121

2222

23-
**Note:** You must have sufficient permissions to register an application with your Azure AD tenant, and assign the application to a role in your Azure subscription. Contact your subscription adminstator if you don't have the permissions. Normally a subscription admin can create a Service principal and can provide you the details.
23+
**Note:** You must have sufficient permissions to register an application with your Azure AD tenant, and assign the application to a role in your Azure subscription. Contact your subscription administrator if you don't have the permissions. Normally a subscription admin can create a Service principal and can provide you the details.
2424

2525

2626
### 4. Create a Variable Group
@@ -29,26 +29,26 @@ We make use of variable group inside Azure DevOps to store variables and their v
2929

3030
Please name your variable group **``devopsforai-aml-vg``** as we are using this name within our build yaml file.
3131

32-
The varibale group should contain the following variables:
33-
34-
| Variable Name | Suggested Value |
35-
| --- | --- |
36-
| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 |
37-
| AML_COMPUTE_CLUSTER_NAME | train-cluster |
38-
| AML_WORKSPACE_NAME | mlops-AML-WS |
39-
| BASE_NAME | mlops |
40-
| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py |
41-
| EXPERIMENT_NAME | mlopspython |
42-
| LOCATION | centralus |
43-
| MODEL_NAME | sklearn_regression_model.pkl |
44-
| REGISTER_SCRIPT_PATH | register/register_model.py |
45-
| RESOURCE_GROUP | mlops-AML-RG |
46-
| SOURCES_DIR_TRAIN | code |
47-
| SP_APP_ID | |
48-
| SP_APP_SECRET | |
49-
| SUBSCRIPTION_ID | |
50-
| TENANT_ID | |
51-
| TRAIN_SCRIPT_PATH | training/train.py |
32+
The variable group should contain the following variables:
33+
34+
| Variable Name | Suggested Value |
35+
| --------------------------- | ---------------------------- |
36+
| AML_COMPUTE_CLUSTER_CPU_SKU | STANDARD_DS2_V2 |
37+
| AML_COMPUTE_CLUSTER_NAME | train-cluster |
38+
| AML_WORKSPACE_NAME | mlops-AML-WS |
39+
| BASE_NAME | mlops |
40+
| EVALUATE_SCRIPT_PATH | evaluate/evaluate_model.py |
41+
| EXPERIMENT_NAME | mlopspython |
42+
| LOCATION | centralus |
43+
| MODEL_NAME | sklearn_regression_model.pkl |
44+
| REGISTER_SCRIPT_PATH | register/register_model.py |
45+
| RESOURCE_GROUP | mlops-AML-RG |
46+
| SOURCES_DIR_TRAIN | code |
47+
| SP_APP_ID | |
48+
| SP_APP_SECRET | |
49+
| SUBSCRIPTION_ID | |
50+
| TENANT_ID | |
51+
| TRAIN_SCRIPT_PATH | training/train.py |
5252

5353
Mark **SP_APP_SECRET** variable as a secret one.
5454

@@ -173,15 +173,15 @@ Create a stage **QA (ACI)** and add a single task to the job **Azure ML Model De
173173
Specify task parameters as it is shown in the table below:
174174

175175

176-
| Parameter | Value |
177-
| --- | --- |
178-
| Display Name | Azure ML Model Deploy |
179-
| Azure ML Workspace | mlops-AML-WS |
180-
| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` |
181-
| Model Deployment Target | Azure Container Instance |
182-
| Deployment Name | mlopspython-aci |
176+
| Parameter | Value |
177+
| ----------------------------- | ---------------------------------------------------------------------------------------------------- |
178+
| Display Name | Azure ML Model Deploy |
179+
| Azure ML Workspace | mlops-AML-WS |
180+
| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` |
181+
| Model Deployment Target | Azure Container Instance |
182+
| Deployment Name | mlopspython-aci |
183183
| Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aci.yml` |
184-
| Overwrite existing deployment | X |
184+
| Overwrite existing deployment | X |
185185

186186

187187
In a similar way create a stage **Prod (AKS** and add a single task to the job **Azure ML Model Deploy**:
@@ -190,25 +190,50 @@ In a similar way create a stage **Prod (AKS** and add a single task to the job *
190190

191191
Specify task parameters as it is shown in the table below:
192192

193-
| Parameter | Value |
194-
| --- | --- |
195-
| Display Name | Azure ML Model Deploy |
196-
| Azure ML Workspace | mlops-AML-WS |
197-
| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` |
198-
| Model Deployment Target | Azure Kubernetes Service |
199-
| Select AKS Cluster for Deployment | YOUR_DEPLOYMENT_K8S_CLUSTER |
200-
| Deployment Name | mlopspython-aks |
201-
| Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aks.yml` |
202-
| Overwrite existing deployment | X |
193+
| Parameter | Value |
194+
| --------------------------------- | ---------------------------------------------------------------------------------------------------- |
195+
| Display Name | Azure ML Model Deploy |
196+
| Azure ML Workspace | mlops-AML-WS |
197+
| Inference config Path | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/inference_config.yml` |
198+
| Model Deployment Target | Azure Kubernetes Service |
199+
| Select AKS Cluster for Deployment | YOUR_DEPLOYMENT_K8S_CLUSTER |
200+
| Deployment Name | mlopspython-aks |
201+
| Deployment Configuration file | `$(System.DefaultWorkingDirectory)/_ci-build/mlops-pipelines/code/scoring/deployment_config_aks.yml` |
202+
| Overwrite existing deployment | X |
203203

204204
**Note:** Creating of a Kubernetes cluster on AKS is out of scope of this tutorial, so you should take care of it on your own.
205205

206-
Save the pipeline and craete a release to trigger it manually. Once the pipeline exection is finished, check out deployments in the **mlops-AML-WS** workspace.
206+
**Deploy trained model to Azure Web App for containers**
207+
208+
Note: This is an optional step and can be used only if you are deploying your scoring service on Azure Web Apps.
209+
210+
[Create Image Script](../ml_service/util/create_scoring_image.py)
211+
can be used to create a scoring image from the release pipeline. Image created by this script will be registered under Azure Container Registry(ACR) instance that belongs to Azure Machine Learning Service. Any dependencies that scoring file depends on can also be packaged with the container with Image config. To learn more on how to create a container with AML SDK click [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.image.image.image?view=azure-ml-py#create-workspace--name--models--image-config-).
212+
213+
Below is release pipeline with two tasks one to create an image using the above script and second is the deploy the image to Web App for containers
214+
![release_webapp](./images/release-webapp-pipeline.PNG)
215+
216+
Using bash script task to invoke [Create Image Script](../ml_service/util/create_scoring_image.py)
217+
![release_createimage](./images/release-task-createimage.PNG)
218+
219+
Specify task parameters as it is shown in the table below:
220+
221+
222+
| Parameter | Value |
223+
| ------------------ | --------------------------------------------------------------------------------------------------- |
224+
| Azure subscription | Subscription used to deploy Web App |
225+
| App name | Web App for Containers name |
226+
| Image name | Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' |
227+
228+
![release_webapp](./images/release-task-webappdeploy.PNG)
229+
230+
231+
Save the pipeline and create a release to trigger it manually. Once the pipeline execution is finished, check out deployments in the **mlops-AML-WS** workspace.
207232

208233

209234

210235
Congratulations! You have three pipelines set up end to end:
211-
- Build pipeline: triggered on code change to master branch on GitHub, performs linting, unit testing and publishing a trainig pipeline
212-
- Release Trigger pipeline: runs a published training pipeline to trian, evaluate and register a model
213-
- Release Deployment pipeline: deploys a model to QA (ACI) and Prod (AKS) environemts
236+
- Build pipeline: triggered on code change to master branch on GitHub, performs linting, unit testing and publishing a training pipeline
237+
- Release Trigger pipeline: runs a published training pipeline to train, evaluate and register a model
238+
- Release Deployment pipeline: deploys a model to QA (ACI) and Prod (AKS) environments
214239

26.2 KB
Loading
32.6 KB
Loading
10.1 KB
Loading
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import os
2+
from azureml.core import Workspace
3+
from azureml.core.image import ContainerImage, Image
4+
from azureml.core.model import Model
5+
from dotenv import load_dotenv
6+
from azureml.core.authentication import ServicePrincipalAuthentication
7+
8+
load_dotenv()
9+
10+
TENANT_ID = os.environ.get('TENANT_ID')
11+
APP_ID = os.environ.get('APP_ID')
12+
APP_SECRET = os.environ.get('APP_SECRET')
13+
WORKSPACE_NAME = os.environ.get('WORKSPACE_NAME')
14+
SUBSCRIPTION_ID = os.environ.get('SUBSCRIPTION_ID')
15+
RESOURCE_GROUP = os.environ.get('RESOURCE_GROUP')
16+
MODEL_NAME = os.environ.get('MODEL_NAME')
17+
MODEL_VERSION = os.environ.get('MODEL_VERSION')
18+
IMAGE_NAME = os.environ.get('IMAGE_NAME')
19+
20+
21+
SP_AUTH = ServicePrincipalAuthentication(
22+
tenant_id=TENANT_ID,
23+
service_principal_id=APP_ID,
24+
service_principal_password=APP_SECRET)
25+
26+
ws = Workspace.get(
27+
WORKSPACE_NAME,
28+
SP_AUTH,
29+
SUBSCRIPTION_ID,
30+
RESOURCE_GROUP
31+
)
32+
33+
34+
model = Model(ws, name=MODEL_NAME, version=MODEL_VERSION)
35+
os.chdir("./code/scoring")
36+
37+
image_config = ContainerImage.image_configuration(
38+
execution_script="score.py",
39+
runtime="python",
40+
conda_file="conda_dependencies.yml",
41+
description="Image with ridge regression model",
42+
tags={"area": "diabetes", "type": "regression"},
43+
)
44+
45+
image = Image.create(
46+
name=IMAGE_NAME, models=[model], image_config=image_config, workspace=ws
47+
)
48+
49+
image.wait_for_creation(show_output=True)
50+
51+
if image.creation_state != "Succeeded":
52+
raise Exception("Image creation status: {image.creation_state}")
53+
54+
print("{}(v.{} [{}]) stored at {} with build log {}".format(
55+
image.name,
56+
image.version,
57+
image.creation_state,
58+
image.image_location,
59+
image.image_build_log_uri,
60+
)
61+
)

0 commit comments

Comments
 (0)