使用部署為 Web 服務的 Azure Machine Learning 模型

將 Azure Machine Learning 模型部署為 Web 服務可建立 REST API 端點。 您可以將資料傳送至此端點,並接收模型傳回的預測。 在本文件中,了解如何使用 C#、Go、Java 和 Python 為Web 服務建立用戶端。

您會在將模型部署至本地環境、 Azure 容器執行個體、Azure Kubernetes Service 或可現場程式化閘道陣列 (FPGA) 時建立 Web 服務。 您可以使用 Azure Machine Learning SDK 擷取用來存取 Web 服務的 URI。 如果啟用驗證,您還可以使用 SDK 取得驗證金鑰或權杖。

建立使用機器學習 Web 服務的用戶端所適用的一般工作流程是:

  1. 使用 SDK 取得連線資訊。
  2. 判斷模型所使用之要求資料的類型。
  3. 建立一個呼叫 Web 服務的應用程式。

提示

本檔中的範例會以手動方式建立,而不需要使用 OpenAPI (Swagger) 規格。 如果您已為您的部署啟用 OpenAPI 規格,您可以使用像是 swagger-codegen \(英文\) 之類的工具來建立服務的用戶端程式庫。

重要

本文中的 Azure CLI 命令使用 azure-cli-ml 或 v1 (Azure Machine Learning 的擴充功能)。 v1 擴充功能的支援將於 2025 年 9 月 30 日終止。 您將能安裝並使用 v1 擴充功能,直到該日期為止。

建議您在 2025 年 9 月 30 日之前轉換至 ml 或 v2 擴充功能。 如需有關 v2 擴充功能的詳細資訊,請參閱 Azure ML CLI 擴充功能和 Python SDK v2

連線資訊

注意

使用 Azure Machine Learning SDK 來取得 Web 服務資訊。 這是 Python SDK。 您可以使用任何語言來建立服務的用戶端。

azureml.core.Webservice 類別可提供建立用戶端所需的資訊。 建立用戶端應用程式時,下列 Webservice 屬性很有用:

  • auth_enabled - 如果啟用金鑰驗證,則為 True;否則為 False
  • token_auth_enabled - 如果啟用權杖驗證,則為 True;否則為 False
  • scoring_uri - REST API 的位址。
  • swagger_uri - OpenAPI 規格的位址。 如果您已啟用自動產生架構,則可使用此 URI。 如需詳細資訊,請參閱使用 Azure Machine Learning 部署模型

針對部署的 Web 服務擷取這項資訊的方式有幾種:

適用於:Python SDK azureml v1

  • 部署模型時,將會傳回 Webservice 物件,其中包含服務的相關資訊:

    service = Model.deploy(ws, "myservice", [model], inference_config, deployment_config)
    service.wait_for_deployment(show_output = True)
    print(service.scoring_uri)
    print(service.swagger_uri)
    
  • 您可以使用 Webservice.list 擷取工作區中已針對模型部署的 Web 服務的清單。 您可以新增篩選來縮小傳回的資訊清單。 如需可篩選項目的詳細資訊,請參閱 Webservice.list 參考文件。

    services = Webservice.list(ws)
    print(services[0].scoring_uri)
    print(services[0].swagger_uri)
    
  • 如果您知道已部署服務的名稱,則可以建立 Webservice 的新執行個體,並將工作區和服務名稱作為參數提供。 新物件包含已部署服務的相關資訊。

    service = Webservice(workspace=ws, name='myservice')
    print(service.scoring_uri)
    print(service.swagger_uri)
    

下表顯示了這些 URI 看起來的樣子:

URI 類型 範例
評分 URI http://104.214.29.152:80/api/v1/service/<service-name>/score
Swagger URI http://104.214.29.152/api/v1/service/<service-name>/swagger.json

提示

您的部署中的 IP 位址將會不同。 每個 AKS 叢集都有自己的 IP 位址,且此位址與該叢集的部署共用。

安全的 Web 服務

如果您使用了 TLS/SSL 憑證來保護已部署的 Web 服務,您可以通過計分或 Swagger URI 來使用 HTTPS,來連接至該服務。 HTTPS 可以加密用戶端與 Web 服務的通訊,藉此協助保護兩者之間的通訊安全。 加密方法使用的是傳輸層安全性 (TLS)。 TLS 有時仍被稱為 安全通訊端層 (SSL),也就是 TLS 的前身。

重要

Azure Machine Learning 部署的 Web 服務僅支援 TLS 1.2 版。 建立用戶端應用程式時,請確定它支援此版本。

如需詳細資訊,請參閱使用 TLS 來透過 Azure Machine Learning 保護 Web 服務 \(部分機器翻譯\)。

服務驗證

Azure Machine Learning 提供兩種方式來控制 Web 服務的存取權。

驗證方法 ACI AKS
Key 預設為停用 預設為啟用
Token 無法使用 預設為停用

將要求傳送至使用金鑰或權杖保護的服務時,請使用授權標頭來傳遞金鑰或權杖。 金鑰或權杖的格式必須是 Bearer <key-or-token>,其中 <key-or-token> 是您金鑰或權杖的值。

金鑰和權杖之間的主要差異在於 金鑰是靜態的,而且可以手動重新產生,而權杖則必須在 到期時重新整理。 Azure 容器實例和 Azure Kubernetes Service 部署的 Web 服務都支援金鑰型驗證,而權杖型驗證適用於 Azure Kubernetes Service 部署。 如需關於設定驗證方式的詳細資訊,請參閱為部署為 Web 服務的模型設定驗證

使用金鑰驗證

當您為部署啟用驗證時,您會自動建立驗證金鑰。

  • 部署至 Azure Kubernetes Service 後,預設會啟用驗證。
  • 部署至 Azure 容器執行個體後,預設會停用驗證。

若要控制驗證,在建立或更新部署時,請使用 auth_enabled 參數。

如果啟用驗證,則可以使用 get_keys 方法擷取主要和次要驗證金鑰:

primary, secondary = service.get_keys()
print(primary)

重要

如果您需要重新產生金鑰,請使用 service.regen_key

使用權杖驗證

當您為 Web 服務啟用權杖驗證時,使用者必須對 Web 服務提供 Azure Machine Learning 的 JWT 權杖才可存取。

  • 部署至 Azure Kubernetes Service 後,預設會停用權杖驗證。
  • 部署至 Azure 容器執行個體後,不支援權杖驗證。

若要控制權杖驗證,在建立或更新部署時,請使用 token_auth_enabled 參數。

如果已啟用權杖驗證,即可使用 get_token 方法來擷取持有人權杖,以及該權杖的到期時間:

token, refresh_by = service.get_token()
print(token)

如果您有 Azure CLI 和機器學習延伸模組,您可以使用下列命令來取得權杖:

適用於:Azure CLI ml 延伸模組 v1

az ml service get-access-token -n <service-name>

重要

目前取得權杖的唯一方法是使用 Azure Machine Learning SDK 或 Azure CLI Machine Learning 延伸模組。

您將必須在權杖的 refresh_by 時間之後要求新的權杖。

要求資料

REST API 預期是具有下列結構之 JSON 文件的要求主體:

{
    "data":
        [
            <model-specific-data-structure>
        ]
}

重要

資料結構需要與服務中預期的評分指令碼和模型相符。 評分指令碼可能會在將資料傳遞至模型之前修改資料。

二進位資料

如需如何在您的服務中啟用二進位資料支援的相關資訊,請參閱二進位資料

提示

針對已部署模型所使用的 score.py 檔案啟用對二進位資料的支援。 從用戶端,使用您程式設計語言的 HTTP 功能。 例如,下列程式碼片段會將 JPG 檔案的內容傳送至 Web 服務:

import requests
# Load image data
data = open('example.jpg', 'rb').read()
# Post raw data to scoring URI
res = request.post(url='<scoring-uri>', data=data, headers={'Content-Type': 'application/> octet-stream'})

跨原始來源資源分享 (CORS)

如需在您的服務中啟用 CORS 支援的相關資訊,請參閱跨原始資源分享

呼叫服務 (C#)

此範例示範如何使用 C# 呼叫從在筆記本內訓練範例建立的 Web 服務:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;

namespace MLWebServiceClient
{
    // The data structure expected by the service
    internal class InputData
    {
        [JsonProperty("data")]
        // The service used by this example expects an array containing
        //   one or more arrays of doubles
        internal double[,] data;
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Set the scoring URI and authentication key or token
            string scoringUri = "<your web service URI>";
            string authKey = "<your key or token>";

            // Set the data to be sent to the service.
            // In this case, we are sending two sets of data to be scored.
            InputData payload = new InputData();
            payload.data = new double[,] {
                {
                    0.0199132141783263,
                    0.0506801187398187,
                    0.104808689473925,
                    0.0700725447072635,
                    -0.0359677812752396,
                    -0.0266789028311707,
                    -0.0249926566315915,
                    -0.00259226199818282,
                    0.00371173823343597,
                    0.0403433716478807
                },
                {
                    -0.0127796318808497, 
                    -0.044641636506989, 
                    0.0606183944448076, 
                    0.0528581912385822, 
                    0.0479653430750293, 
                    0.0293746718291555, 
                    -0.0176293810234174, 
                    0.0343088588777263, 
                    0.0702112981933102, 
                    0.00720651632920303
                }
            };

            // Create the HTTP client
            HttpClient client = new HttpClient();
            // Set the auth header. Only needed if the web service requires authentication.
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authKey);

            // Make the request
            try {
                var request = new HttpRequestMessage(HttpMethod.Post, new Uri(scoringUri));
                request.Content = new StringContent(JsonConvert.SerializeObject(payload));
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var response = client.SendAsync(request).Result;
                // Display the response from the web service
                Console.WriteLine(response.Content.ReadAsStringAsync().Result);
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.Message);
            }
        }
    }
}

傳回的結果與下列 JSON 文件類似:

[217.67978776218715, 224.78937091757172]

呼叫服務 (Go)

此範例示範如何使用 Go 來呼叫從在筆記本內訓練範例建立的 Web 服務:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

// Features for this model are an array of decimal values
type Features []float64

// The web service input can accept multiple sets of values for scoring
type InputData struct {
    Data []Features `json:"data",omitempty`
}

// Define some example data
var exampleData = []Features{
    []float64{
        0.0199132141783263, 
        0.0506801187398187, 
        0.104808689473925, 
        0.0700725447072635, 
        -0.0359677812752396, 
        -0.0266789028311707, 
        -0.0249926566315915, 
        -0.00259226199818282, 
        0.00371173823343597, 
        0.0403433716478807,
    },
    []float64{
        -0.0127796318808497, 
        -0.044641636506989, 
        0.0606183944448076, 
        0.0528581912385822, 
        0.0479653430750293, 
        0.0293746718291555, 
        -0.0176293810234174, 
        0.0343088588777263, 
        0.0702112981933102, 
        0.00720651632920303,
    },
}

// Set to the URI for your service
var serviceUri string = "<your web service URI>"
// Set to the authentication key or token (if any) for your service
var authKey string = "<your key or token>"

func main() {
    // Create the input data from example data
    jsonData := InputData{
        Data: exampleData,
    }
    // Create JSON from it and create the body for the HTTP request
    jsonValue, _ := json.Marshal(jsonData)
    body := bytes.NewBuffer(jsonValue)

    // Create the HTTP request
    client := &http.Client{}
    request, err := http.NewRequest("POST", serviceUri, body)
    request.Header.Add("Content-Type", "application/json")

    // These next two are only needed if using an authentication key
    bearer := fmt.Sprintf("Bearer %v", authKey)
    request.Header.Add("Authorization", bearer)

    // Send the request to the web service
    resp, err := client.Do(request)
    if err != nil {
        fmt.Println("Failure: ", err)
    }

    // Display the response received
    respBody, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(respBody))
}

傳回的結果與下列 JSON 文件類似:

[217.67978776218715, 224.78937091757172]

呼叫服務 (Java)

此範例示範如何使用 Java 來呼叫從在筆記本內訓練範例建立的 Web 服務:

import java.io.IOException;
import org.apache.http.client.fluent.*;
import org.apache.http.entity.ContentType;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class App {
    // Handle making the request
    public static void sendRequest(String data) {
        // Replace with the scoring_uri of your service
        String uri = "<your web service URI>";
        // If using authentication, replace with the auth key or token
        String key = "<your key or token>";
        try {
            // Create the request
            Content content = Request.Post(uri)
            .addHeader("Content-Type", "application/json")
            // Only needed if using authentication
            .addHeader("Authorization", "Bearer " + key)
            // Set the JSON data as the body
            .bodyString(data, ContentType.APPLICATION_JSON)
            // Make the request and display the response.
            .execute().returnContent();
            System.out.println(content);
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }
    public static void main(String[] args) {
        // Create the data to send to the service
        JSONObject obj = new JSONObject();
        // In this case, it's an array of arrays
        JSONArray dataItems = new JSONArray();
        // Inner array has 10 elements
        JSONArray item1 = new JSONArray();
        item1.add(0.0199132141783263);
        item1.add(0.0506801187398187);
        item1.add(0.104808689473925);
        item1.add(0.0700725447072635);
        item1.add(-0.0359677812752396);
        item1.add(-0.0266789028311707);
        item1.add(-0.0249926566315915);
        item1.add(-0.00259226199818282);
        item1.add(0.00371173823343597);
        item1.add(0.0403433716478807);
        // Add the first set of data to be scored
        dataItems.add(item1);
        // Create and add the second set
        JSONArray item2 = new JSONArray();
        item2.add(-0.0127796318808497);
        item2.add(-0.044641636506989);
        item2.add(0.0606183944448076);
        item2.add(0.0528581912385822);
        item2.add(0.0479653430750293);
        item2.add(0.0293746718291555);
        item2.add(-0.0176293810234174);
        item2.add(0.0343088588777263);
        item2.add(0.0702112981933102);
        item2.add(0.00720651632920303);
        dataItems.add(item2);
        obj.put("data", dataItems);

        // Make the request using the JSON document string
        sendRequest(obj.toJSONString());
    }
}

傳回的結果與下列 JSON 文件類似:

[217.67978776218715, 224.78937091757172]

呼叫服務 (Python)

此範例示範如何使用 Python 來呼叫從在筆記本內訓練範例建立的 Web 服務:

import requests
import json

# URL for the web service
scoring_uri = '<your web service URI>'
# If the service is authenticated, set the key or token
key = '<your key or token>'

# Two sets of data to score, so we get two results back
data = {"data":
        [
            [
                0.0199132141783263,
                0.0506801187398187,
                0.104808689473925,
                0.0700725447072635,
                -0.0359677812752396,
                -0.0266789028311707,
                -0.0249926566315915,
                -0.00259226199818282,
                0.00371173823343597,
                0.0403433716478807
            ],
            [
                -0.0127796318808497,
                -0.044641636506989,
                0.0606183944448076,
                0.0528581912385822,
                0.0479653430750293,
                0.0293746718291555,
                -0.0176293810234174,
                0.0343088588777263,
                0.0702112981933102,
                0.00720651632920303]
        ]
        }
# Convert to JSON string
input_data = json.dumps(data)

# Set the content type
headers = {'Content-Type': 'application/json'}
# If authentication is enabled, set the authorization header
headers['Authorization'] = f'Bearer {key}'

# Make the request and display the response
resp = requests.post(scoring_uri, input_data, headers=headers)
print(resp.text)

傳回的結果與下列 JSON 文件類似:

[217.67978776218715, 224.78937091757172]

Web 服務架構 (OpenAPI 規格)

如果您在部署中使用了自動產生架構,您可以藉由使用 swagger_uri 屬性 來取得服務 OpenAPI 規格的位址。 (例如,print(service.swagger_uri))。使用 GET 要求或在瀏覽器中開啟 URI 以取得規格。

下列 JSON 文件為針對部署所產生的架構 (OpenAPI 規格) 範例:

{
    "swagger": "2.0",
    "info": {
        "title": "myservice",
        "description": "API specification for Azure Machine Learning myservice",
        "version": "1.0"
    },
    "schemes": [
        "https"
    ],
    "consumes": [
        "application/json"
    ],
    "produces": [
        "application/json"
    ],
    "securityDefinitions": {
        "Bearer": {
            "type": "apiKey",
            "name": "Authorization",
            "in": "header",
            "description": "For example: Bearer abc123"
        }
    },
    "paths": {
        "/": {
            "get": {
                "operationId": "ServiceHealthCheck",
                "description": "Simple health check endpoint to ensure the service is up at any given point.",
                "responses": {
                    "200": {
                        "description": "If service is up and running, this response will be returned with the content 'Healthy'",
                        "schema": {
                            "type": "string"
                        },
                        "examples": {
                            "application/json": "Healthy"
                        }
                    },
                    "default": {
                        "description": "The service failed to execute due to an error.",
                        "schema": {
                            "$ref": "#/definitions/ErrorResponse"
                        }
                    }
                }
            }
        },
        "/score": {
            "post": {
                "operationId": "RunMLService",
                "description": "Run web service's model and get the prediction output",
                "security": [
                    {
                        "Bearer": []
                    }
                ],
                "parameters": [
                    {
                        "name": "serviceInputPayload",
                        "in": "body",
                        "description": "The input payload for executing the real-time machine learning service.",
                        "schema": {
                            "$ref": "#/definitions/ServiceInput"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The service processed the input correctly and provided a result prediction, if applicable.",
                        "schema": {
                            "$ref": "#/definitions/ServiceOutput"
                        }
                    },
                    "default": {
                        "description": "The service failed to execute due to an error.",
                        "schema": {
                            "$ref": "#/definitions/ErrorResponse"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "ServiceInput": {
            "type": "object",
            "properties": {
                "data": {
                    "type": "array",
                    "items": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "format": "int64"
                        }
                    }
                }
            },
            "example": {
                "data": [
                    [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
                ]
            }
        },
        "ServiceOutput": {
            "type": "array",
            "items": {
                "type": "number",
                "format": "double"
            },
            "example": [
                3726.995
            ]
        },
        "ErrorResponse": {
            "type": "object",
            "properties": {
                "status_code": {
                    "type": "integer",
                    "format": "int32"
                },
                "message": {
                    "type": "string"
                }
            }
        }
    }
}

如需詳細資訊,請參閱 OpenAPI 規格 \(英文\)。

如需可從規格建立用戶端程式庫的公用程式,請參閱 swagger-codegen \(英文\)。

提示

您可以在部署服務之後取得架構 JSON 文件。 從已部署的 Web 服務 (例如 service.swagger_uri) 使用 swagger_uri 屬性 來取得本機 Web 服務 Swagger 檔案的 URI。

使用來自 Power BI 的服務

Power BI 支援耗用 Azure Machine Learning Web 服務來利用預測來擴充 Power BI 中的資料。

若要在 Power BI 中建立一個支援耗用的 Web 服務,架構必須支援 Power BI 所需的格式。 瞭解如何建立支援 Power BI 的架構

一旦部署 Web 服務之後,就可從 Power BI 資料流程中取用。 了解如何從 Power BI 使用 Azure Machine Learning Web 服務

下一步

若要查看適用於 Python 和深度學習模型的即時評分參考架構,請前往 Azure 架構中心