Consumir um modelo de Azure Machine Learning implantado como um serviço web

A implantação de um modelo do Azure Machine Learning como um serviço Web cria um ponto de extremidade da API REST. Você pode enviar dados para esse ponto de extremidade e receber a previsão retornada pelo modelo. Neste documento, saiba como criar clientes para o serviço da Web usando C#, Go, Java e Python.

Você cria um serviço Web ao implantar um modelo em seu ambiente local, Instâncias de Contêiner do Azure, Serviço de Kubernetes do Azure ou FPGA (matrizes de porta programáveis em campo). Você recupera o URI usado para acessar um serviço Web usando o SDK do Azure Machine Learning. Se a autenticação estiver ativada, você também poderá usar o SDK para obter os tokens ou chaves de autenticação.

O fluxo de trabalho geral para a criação de um cliente que usa um serviço web machine learning é:

  1. Use o SDK para obter as informações de conexão.
  2. Determinar o tipo de dados de solicitação usados pelo modelo.
  3. Crie um aplicativo que chame o serviço da web.

Dica

Os exemplos neste documento são criados manualmente sem o uso de especificações OpenAPI (Swagger). Se você tiver habilitado uma especificação OpenAPI para sua implantação, poderá usar ferramentas como o swagger-codegen para criar bibliotecas de cliente para seu serviço.

Importante

Alguns comandos da CLI do Azure neste artigo usam a extensão azure-cli-ml ou v1 do Azure Machine Learning. O suporte à extensão v1 terminará em 30 de setembro de 2025. Você poderá instalar e usar a extensão v1 até essa data.

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

Informações de conexão

Observação

Use o SDK do Azure Machine Learning para obter as informações do serviço Web. Esse é um SDK de Python. Você pode usar qualquer linguagem 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 propriedades Webservice que são úteis para criar um aplicativo cliente:

  • auth_enabled ꟷ se a autenticação de chave estiver habilitada, True; caso contrário, False.
  • token_auth_enabled ꟷ se a autenticação de token estiver habilitada, True; caso contrário, False.
  • scoring_uri -O endereço da API REST.
  • swagger_uri ꟷ o endereço da especificação OpenAPI. Esse URI estará disponível se você tiver habilitado a geração automática de esquema. Para saber mais, confira Implantar modelos com Azure Machine Learning.

Há várias maneiras de recuperar essas informações para os serviços Web implantados:

APLICA-SE A:SDK azureml do Python v1

  • Quando você implanta um modelo, um objeto Webservice é retornado 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)
    
  • Você pode usar Webservice.list para recuperar uma lista de serviços da Web implementados para modelos em seu workspace. Você pode adicionar filtros para restringir a lista de informações retornadas. Para obter mais informações sobre o que pode ser filtrado, consulte a documentação de referência do Webservice.list.

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

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

A tabela a seguir mostra a aparência desses URIs:

Tipo de URI Exemplo
URI de pontuação http://104.214.29.152:80/api/v1/service/<service-name>/score
URI do Swagger http://104.214.29.152/api/v1/service/<service-name>/swagger.json

Dica

O endereço IP será diferente para a sua implantação. Cada cluster do AKS terá seu próprio endereço IP, que é compartilhado pelas implantações nesse cluster.

Serviço Web protegido

Se tiver protegido o serviço Web implantado usando um certificado TLS/SSL, você poderá usar HTTPS para se conectar ao serviço usando a pontuação ou URI swagger. O HTTPS ajuda a proteger as comunicações entre um cliente e um serviço Web criptografando as comunicações entre os dois. A criptografia usa o TLS (Transport Layer Security). Às vezes, o TLS ainda é mencionado como SSL (Secure Sockets Layer), que foi o predecessor do TLS.

Importante

Os serviços Web implantados pelo Azure Machine Learning só oferecem suporte a TLS versão 1.2. Ao criar um aplicativo cliente, verifique se ele dá suporte a essa versão.

Para obter mais informações, consulte Usar o TLS para proteger um serviço Web por meio do Azure Machine Learning.

Autenticação para serviços

O Azure Machine Learning fornece duas maneiras de controlar o acesso aos serviços Web.

Método de autenticação ACI AKS
Chave Desabilitadas por padrão Habilitado por padrão
Token Não disponível Desabilitado por padrão

Ao enviar uma solicitação para um serviço protegido com uma chave ou token, use o cabeçalho de autorização para passar a chave ou o token. A chave ou token deve ser formatado como Bearer <key-or-token>, em que <key-or-token> é seu valor de chave ou token.

A principal diferença entre chaves e tokens é que as chaves são estáticas e podem ser regeneradas manualmente, e os tokens precisam ser atualizados após a expiração. A autenticação baseada em chave tem suporte para serviços da Web implantados da Instância de Contêiner do Azure e do Serviço de Kubernetes do Azure, e a autenticação baseada em token está disponível apenas para implantações do Serviço de Kubernetes do Azure. Para saber mais sobre como configurar a autenticação, confira Configurar a autenticação para modelos implantados como serviços Web.

Autenticação com chaves

Ao habilitar a autenticação para uma implantação, você cria automaticamente as chaves de autenticação.

  • A autenticação é ativada por padrão ao implantar no Serviço de Kubernetes do Azure.
  • A autenticação é desabilitada por padrão ao implantar nas Instâncias de Contêiner do Azure.

Para controlar a autenticação, use o parâmetro auth_enabled ao criar ou atualizar uma implantação.

Se a autenticação estiver ativada, você poderá usar o método get_keys para recuperar uma chave de autenticação primária e secundária:

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

Importante

Se você precisar regenerar uma chave, use service.regen_key.

Autenticação com tokens

Quando você habilita a autenticação de token para um serviço Web, um usuário precisa fornecer um token JWT do Azure Machine Learning para o serviço Web para acessá-lo.

  • A autenticação de token é desabilitada por padrão ao implantar no Serviço de Kubernetes do Azure.
  • Não há suporte para a autenticação de token ao implantar nas Instâncias de Contêiner do Azure.

Para controlar a autenticação de token, use o parâmetro token_auth_enabled ao criar ou atualizar uma implantação.

Se a autenticação do token estiver habilitada, você poderá usar o método get_token para recuperar um token de portador e a hora da expiração do token:

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

Se você tiver a CLI do Azure e a extensão de aprendizado de máquina, poderá usar 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 maneira de recuperar o token é usando o SDK do Azure Machine Learning ou a extensão de aprendizado de máquina da CLI do Azure.

Será necessário solicitar um novo token depois do período de refresh_by do token.

Dados de solicitação

A API REST espera que o corpo da solicitação seja um documento JSON com a seguinte estrutura:

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

Importante

A estrutura dos dados precisa corresponder ao esperado pelo script e modelo de pontuação no serviço. O script de pontuação pode modificar os dados antes de transmiti-lo ao modelo.

Dados binários

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

Dica

A habilitação do suporte para dados binários ocorre no arquivo score.py usado pelo modelo implantado. No cliente, use a funcionalidade HTTP da sua linguagem de programação. Por exemplo, o trecho a seguir envia o conteúdo de um arquivo 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'})

CORS (Compartilhamento de Recursos entre Origens)

Para obter informações sobre como ativar o suporte CORS em seu serviço, confira Compartilhamento de Recursos entre Origens.

Chamar o serviço (C#)

Este exemplo demonstra como usar o C # para chamar o serviço da Web criado a partir do exemplo Treinar no caderno:

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 retornados são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Chamar o serviço (Ir)

Este exemplo demonstra como usar o recurso Go para chamar o serviço da Web criado a partir do exemplo Train dentro do notebook:

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 retornados são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Ligue para o serviço (Java)

Este exemplo demonstra como usar o Java para chamar o serviço da Web criado a partir do exemplo Trainar no notebook:

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 retornados são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

Chamar o serviço (Python)

Este exemplo demonstra como usar o Python para chamar o serviço da Web criado a partir do exemplo Traino no notebook:

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 retornados são semelhantes ao seguinte documento JSON:

[217.67978776218715, 224.78937091757172]

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

Se você usou a geração automática de esquema com sua implantação, pode obter o endereço da especificação OpenAPI para o serviço usando a propriedade swagger_uri. (Por exemplo, print(service.swagger_uri).) Use uma solicitação GET ou abra o URI em um navegador para recuperar a especificação.

O documento JSON a seguir é um exemplo de um esquema (especificação OpenAPI) gerado para uma implantaçã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 saber mais, confira a especificação OpenAPI.

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

Dica

Você pode recuperar o documento JSON do esquema depois de implantar o serviço. Use a propriedade swagger_uri do serviço Web implantado (por exemplo, service.swagger_uri) para obter o URI para o arquivo Swagger do serviço Web local.

Consumir o serviço por meio do Power BI

O Power BI dá suporte ao consumo de serviços Web do Azure Machine Learning para enriquecer os dados no Power BI com previsões.

Para gerar um serviço Web com suporte para consumo no Power BI, o esquema deve dar suporte ao formato exigido pelo Power BI. Saiba como criar um esquema com suporte ao Power BI.

Depois que o serviço Web for implantado, ele será consumível pelos fluxos de dados do Power BI. Saiba como consumir um serviço Web do Machine Learning do Azure no Power BI.

Próximas etapas

Para exibir uma arquitetura de referência para a pontuação em tempo real dos modelos de aprendizado profundo e Python, acesse o Centro de Arquitetura do Azure.