Consumir um modelo do Azure Machine Learning implementado como serviço Web

A implementação de um modelo do Azure Machine Learning como serviço Web cria um ponto final da API REST. Pode enviar dados para este ponto final e receber a predição devolvida pelo modelo. Neste documento, saiba como criar clientes para o serviço Web com C#, Go, Java e Python.

Cria um serviço Web quando implementa um modelo no seu ambiente local, Azure Container Instances, Azure Kubernetes Service ou matrizes de portas programáveis em campo (FPGA). Obtém o URI utilizado para aceder ao serviço Web com o SDK do Azure Machine Learning. Se a autenticação estiver ativada, também pode utilizar o SDK para obter as chaves ou tokens de autenticação.

O fluxo de trabalho geral para criar um cliente que utiliza um serviço Web de machine learning é:

  1. Utilize o SDK para obter as informações de ligação.
  2. Determine o tipo de dados de pedido utilizados pelo modelo.
  3. Crie uma aplicação que chame o serviço Web.

Dica

Os exemplos neste documento são criados manualmente sem a utilização de especificações do OpenAPI (Swagger). Se tiver ativado uma especificação OpenAPI para a sua implementação, pode utilizar ferramentas como swagger-codegen para criar bibliotecas de cliente para o seu serviço.

Importante

Alguns dos comandos da CLI do Azure neste artigo utilizam a extensão , ou v1, para o azure-cli-mlAzure Machine Learning. O suporte para a extensão v1 terminará a 30 de setembro de 2025. Poderá instalar e utilizar a extensão v1 até essa data.

Recomendamos que faça a transição para a mlextensão , ou v2, antes de 30 de setembro de 2025. Para obter mais informações sobre a extensão v2, veja Extensão da CLI do Azure ML e SDK Python v2.

Informações da ligação

Nota

Utilize o SDK do Azure Machine Learning para obter as informações do serviço Web. Este é um SDK Python. Pode utilizar qualquer idioma para criar um cliente para o serviço.

A classe azureml.core.Webservice fornece as informações necessárias para criar um cliente. As seguintes Webservice propriedades são úteis para criar uma aplicação cliente:

  • auth_enabled - Se a autenticação de chaves estiver ativada; Truecaso contrário, False.
  • token_auth_enabled - Se a autenticação de tokens estiver ativada; Truecaso contrário, False.
  • scoring_uri - O endereço da API REST.
  • swagger_uri - O endereço da especificação OpenAPI. Este URI está disponível se tiver ativado a geração automática de esquemas. Para obter mais informações, veja Implementar modelos com o Azure Machine Learning.

Existem várias formas de obter estas informações para serviços Web implementados:

APLICA-SE A:Python SDK azureml v1

  • Quando implementa um modelo, é devolvido um Webservice objeto com informações sobre o serviço:

    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)
    
  • Pode utilizar Webservice.list para obter uma lista de serviços Web implementados para modelos na sua área de trabalho. Pode adicionar filtros para restringir a lista de informações devolvidas. Para obter mais informações sobre o que pode ser filtrado, consulte a documentação de referência Webservice.list .

    services = Webservice.list(ws)
    print(services[0].scoring_uri)
    print(services[0].swagger_uri)
    
  • Se souber o nome do serviço implementado, pode criar uma nova instância de e fornecer a área de Webservicetrabalho e o nome do serviço como parâmetros. O novo objeto contém informações sobre o serviço implementado.

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

A tabela seguinte mostra o aspeto destes URIs:

Tipo de URI Exemplo
URI de Classificação 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

Dica

O endereço IP será diferente para a sua implementação. Cada cluster do AKS terá o seu próprio endereço IP que é partilhado por implementações nesse cluster.

Serviço Web protegido

Se tiver protegido o serviço Web implementado com um certificado TLS/SSL, pode utilizar HTTPS para ligar ao serviço com o URI de classificação ou swagger. O HTTPS ajuda a proteger as comunicações entre um cliente e um serviço Web ao encriptar as comunicações entre os dois. A encriptação utiliza o Transport Layer Security (TLS). Por vezes, o TLS ainda é referido como Secure Sockets Layer (SSL), que foi o antecessor do TLS.

Importante

Os serviços Web implementados pelo Azure Machine Learning só suportam a versão 1.2 do TLS. Ao criar uma aplicação cliente, certifique-se de que suporta esta versão.

Para obter mais informações, veja Utilizar o TLS para proteger um serviço Web através do Azure Machine Learning.

Autenticação para serviços

O Azure Machine Learning oferece duas formas de controlar o acesso aos serviços Web.

Método de autenticação ACI AKS
Chave Desativado por predefinição Ativado por predefinição
Token Não Disponível Desativado por predefinição

Ao enviar um pedido para um serviço protegido com uma chave ou token, utilize o cabeçalho Autorização para transmitir a chave ou token. A chave ou o token deve ser formatado como Bearer <key-or-token>, em que <key-or-token> é o valor da chave ou do token.

A principal diferença entre chaves e tokens é que as chaves são estáticas e podem ser regeneradas manualmente e os tokens têm de ser atualizados após a expiração. A autenticação baseada em chaves é suportada para o Azure Container Instance e Azure Kubernetes Service serviços Web implementados e a autenticação baseada em tokens só está disponível para implementações Azure Kubernetes Service. Para obter mais informações sobre como configurar a autenticação, veja Configurar a autenticação para modelos implementados como serviços Web.

Autenticação com chaves

Quando ativa a autenticação para uma implementação, cria automaticamente chaves de autenticação.

  • A autenticação está ativada por predefinição quando está a implementar no Azure Kubernetes Service.
  • A autenticação está desativada por predefinição quando está a implementar no Azure Container Instances.

Para controlar a autenticação, utilize o auth_enabled parâmetro quando estiver a criar ou a atualizar uma implementação.

Se a autenticação estiver ativada, pode utilizar o get_keys método para obter uma chave de autenticação primária e secundária:

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

Importante

Se precisar de regenerar uma chave, utilize service.regen_key.

Autenticação com tokens

Quando ativa a autenticação de tokens para um serviço Web, um utilizador tem de fornecer um token JWT do Azure Machine Learning ao serviço Web para aceder ao mesmo.

  • A autenticação de tokens está desativada por predefinição quando está a implementar no Azure Kubernetes Service.
  • A autenticação de tokens não é suportada quando está a implementar no Azure Container Instances.

Para controlar a autenticação de tokens, utilize o token_auth_enabled parâmetro quando estiver a criar ou a atualizar uma implementação.

Se a autenticação de tokens estiver ativada, pode utilizar o get_token método para obter um token de portador e o tempo de expiração dos tokens:

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

Se tiver a CLI do Azure e a extensão de machine learning, pode utilizar o seguinte comando para obter um token:

APLICA-SE A:Extensão de ml da CLI do Azure v1

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

Importante

Atualmente, a única forma de obter o token é com o SDK do Azure Machine Learning ou a extensão de machine learning da CLI do Azure.

Precisará de pedir um novo token depois do prazo refresh_by do token.

Pedir dados

A API REST espera que o corpo do pedido seja um documento JSON com a seguinte estrutura:

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

Importante

A estrutura dos dados tem de corresponder ao que o script de classificação e o modelo no serviço esperam. O script de classificação pode modificar os dados antes de os transmitir ao modelo.

Dados binários

Para obter informações sobre como ativar o suporte para dados binários no seu serviço, veja Dados binários.

Dica

A ativação do suporte para dados binários ocorre no ficheiro de score.py utilizado pelo modelo implementado. No cliente, utilize a funcionalidade HTTP da sua linguagem de programação. Por exemplo, o fragmento seguinte envia o conteúdo de um ficheiro JPG para um serviço 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'})

Partilha de recursos transversais à origem (CORS)

Para obter informações sobre como ativar o suporte CORS no seu serviço, veja Partilha de recursos de várias origens.

Chamar o serviço (C#)

Este exemplo demonstra como utilizar o C# para chamar o serviço Web criado a partir do exemplo Preparar no bloco de notas:

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);
            }
        }
    }
}

Os resultados devolvidos são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Chamar o serviço (Go)

Este exemplo demonstra como utilizar o Go para chamar o serviço Web criado a partir do exemplo Preparar no bloco de notas:

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))
}

Os resultados devolvidos são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Chamar o serviço (Java)

Este exemplo demonstra como utilizar Java para chamar o serviço Web criado a partir do exemplo Preparar no bloco de notas:

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());
    }
}

Os resultados devolvidos são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Chamar o serviço (Python)

Este exemplo demonstra como utilizar o Python para chamar o serviço Web criado a partir do exemplo Preparar no bloco de notas:

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)

Os resultados devolvidos são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Esquema do serviço Web (especificação OpenAPI)

Se utilizou a geração automática de esquemas com a sua implementação, pode obter o endereço da especificação OpenAPI para o serviço com a propriedade swagger_uri. (Por exemplo, print(service.swagger_uri).) Utilize um pedido GET ou abra o URI num browser para obter a especificação.

O seguinte documento JSON é um exemplo de um esquema (especificação OpenAPI) gerado para uma implementação:

{
    "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"
                }
            }
        }
    }
}

Para obter mais informações, veja Especificação de OpenAPI.

Para um utilitário que pode criar bibliotecas de cliente a partir da especificação, veja swagger-codegen.

Dica

Pode obter o documento JSON de esquema depois de implementar o serviço. Utilize a propriedade swagger_uri do serviço Web implementado (por exemplo, service.swagger_uri) para obter o URI para o ficheiro Swagger do serviço Web local.

Consumir o serviço no Power BI

O Power BI suporta o consumo de serviços Web do Azure Machine Learning para melhorar os dados no Power BI com previsões.

Para gerar um serviço Web suportado para consumo no Power BI, o esquema tem de suportar o formato exigido pelo Power BI. Saiba como criar um esquema suportado pelo Power BI.

Assim que o serviço Web for implementado, poderá ser consumido nos fluxos de dados do Power BI. Saiba como consumir um serviço Web do Azure Machine Learning no Power BI.

Passos seguintes

Para ver uma arquitetura de referência para a classificação em tempo real do Python e dos modelos de aprendizagem profunda, aceda ao centro de arquitetura do Azure.