Depurar scripts de pontuação com o servidor HTTP de inferência do Azure Machine Learning
O servidor HTTP de inferência do Azure Machine Learning é um pacote Python que expõe sua função de pontuação como um ponto de extremidade HTTP e encapsula o código do servidor Flask e as dependências em um pacote singular. O servidor está incluído nas imagens predefinidas do Docker para inferência que são usadas na implantação de um modelo com o Azure Machine Learning. Usando o pacote sozinho, é possível implantar o modelo localmente para produção e validar facilmente seu script de pontuação (entrada) em um ambiente de desenvolvimento local. Se houver um problema com o script de pontuação, o servidor retornará um erro e o local do erro.
O servidor também pode ser usado para criar portas de validação em um pipeline de implantação e integração contínua. Por exemplo, você pode iniciar o servidor com o script do candidato e execute o conjunto de testes no ponto de extremidade local.
Este artigo dá suporte a desenvolvedores que desejam usar o servidor de inferência para depurar localmente e descreve como usar o servidor de inferência com pontos de extremidade online no Windows.
Pré-requisitos
Para usar o servidor HTTP de inferência do Azure Machine Learning para depuração local, sua configuração deve incluir os seguintes componentes:
- Python 3.8 ou posterior
- Anaconda
O servidor HTTP de inferência do Azure Machine Learning é executado em sistemas operacionais baseados no Windows e no Linux.
Explorar opções de depuração local para pontos de extremidade online
Ao depurar pontos de extremidade localmente antes de implantar na nuvem, é possível detectar antecipadamente erros no código e na configuração. Para depurar pontos de extremidade localmente, você tem várias opções, incluindo:
- O servidor HTTP de inferência do Azure Machine Learning
- Um ponto de extremidade local
Este artigo descreve como trabalhar com o servidor HTTP de inferência do Azure Machine Learning no Windows.
A tabela a seguir fornece uma visão geral dos cenários para ajudar você a escolher a melhor opção:
Cenário | Servidor HTTP de inferência | Ponto de extremidade local |
---|---|---|
Atualizar o ambiente Python local, sem a recomposição de imagem do Docker | Sim | Não |
Criar script de pontuação | Sim | Sim |
Atualizar configurações de implantação (implantação, ambiente, código, modelo) | Não | Sim |
Integrar o depurador do VS Code (Microsoft Visual Studio Code) | Sim | Sim |
Ao executar o servidor HTTP de inferência localmente, você poderá se concentrar na depuração do script de pontuação sem preocupação com as configurações do contêiner de implantação.
Instalar o pacote azureml-inference-server-http
Para instalar o pacote azureml-inference-server-http
, execute o seguinte comando:
python -m pip install azureml-inference-server-http
Observação
Para evitar conflitos de pacote, instale o servidor HTTP de inferência em um ambiente virtual.
Use o comando pip install virtualenv
para habilitar ambientes virtuais para sua configuração.
Depurar o script de pontuação localmente
Para depurar o script de pontuação localmente, você tem várias opções para testar o comportamento do servidor:
- Tente um script de pontuação fictício.
- Use o Visual Studio Code para depurar com o pacote azureml-inference-server-http.
- Execute um script de pontuação real, um arquivo de modelo e um arquivo de ambiente em nosso repositório de exemplos.
Testar o comportamento do servidor com script de pontuação fictício
Crie um diretório chamado server_quickstart para armazenar seus arquivos:
mkdir server_quickstart cd server_quickstart
Para evitar conflitos de pacote, crie um ambiente virtual, como myenv, e ative-o:
python -m virtualenv myenv
Observação
No Linux, execute o comando
source myenv/bin/activate
para ativar o ambiente virtual.Após testar o servidor, execute o comando
deactivate
para desativar o ambiente virtual do Python.Instale o pacote
azureml-inference-server-http
do feed pypi:python -m pip install azureml-inference-server-http
Crie o script de entrada. O exemplo a seguir cria um script de entrada básico e o salva em um arquivo chamado score.py:
echo -e "import time def init(): \n\t time.sleep(1) \n\n def run(input_data): \n\t return {"message":"Hello, World!"}" > score.py
Inicie o servidor com o comando
azmlinfsrv
e defina o arquivo score.py como o script de entrada:azmlinfsrv --entry_script score.py
Observação
O servidor é hospedado em 0.0.0.0, o que significa que ele escuta todos os endereços IP do computador de hospedagem.
Envie uma solicitação de pontuação para o servidor usando o programa utilitário
curl
:curl -p 127.0.0.1:5001/score
O servidor posta a seguinte resposta:
{"message": "Hello, World!"}
Após o teste, selecione Ctrl + C para encerrar o servidor.
Agora é possível modificar o arquivo de script de pontuação (score.py) e testar suas alterações executando o servidor novamente com o comando azmlinfsrv --entry_script score.py
.
Integrar com o Visual Studio Code
Para usar o VS Code e a Extensão do Python para depuração com o pacote azureml-inference-server-http, use os modos Iniciar e Anexar.
Para o Modo de inicialização: configure o arquivo launch.json no VS Code e inicie o servidor HTTP de inferência do Azure Machine Learning no VS Code:
Inicie o VS Code e abra a pasta que contém o script (score.py).
Adicione a seguinte configuração ao arquivo launch.json para esse espaço de trabalho no VS Code:
launch.json
{ "version": "0.2.0", "configurations": [ { "name": "Debug score.py", "type": "python", "request": "launch", "module": "azureml_inference_server_http.amlserver", "args": [ "--entry_script", "score.py" ] } ] }
Inicie a sessão de depuração no VS Code selecionando Executar>Iniciar depuração ou use o atalho de teclado F5.
Para o Modo de anexação: inicie o servidor HTTP de inferência do Azure Machine Learning em uma janela de comando e use o VS Code com a extensão Python para anexar ao processo:
Observação
Para Linux, primeiro instale o pacote
gdb
executando o comandosudo apt-get install -y gdb
.Adicione a seguinte configuração ao arquivo launch.json para esse espaço de trabalho no VS Code:
launch.json
{ "version": "0.2.0", "configurations": [ { "name": "Python: Attach using Process Id", "type": "python", "request": "attach", "processId": "${command:pickProcess}", "justMyCode": true } ] }
Em uma janela de comando, inicie o servidor HTTP de inferência usando o comando
azmlinfsrv --entry_script score.py
.Inicie a sessão de depuração no VS Code:
Selecione Executar>Iniciar depuração ou use o atalho de teclado F5.
Na janela de comando, exiba os logs do servidor de inferência e localize a ID do processo do
azmlinfsrv
comando (não ogunicorn
):No Depurador do VS Code, insira a ID do processo do comando
azmlinfsrv
.Caso não visualize o seletor de processo do VS Code, poderá inserir manualmente a ID do processo no campo
processId
do arquivo launch.json para esse espaço de trabalho.
Para ambos os modos, defina pontos de interrupção e depure o script passo a passo.
Usar um exemplo de ponta a ponta
O procedimento a seguir executa o servidor localmente com arquivos de amostra (script de pontuação, arquivo de modelo e ambiente) do repositório de exemplo do Azure Machine Learning. Para obter mais exemplos de como usar esses arquivos de amostra, consulte Implantar e pontuar um modelo de machine learning usando um ponto de extremidade online.
Clone o repositório de exemplo:
git clone --depth 1 https://github.com/Azure/azureml-examples cd azureml-examples/cli/endpoints/online/model-1/
Crie e ative um ambiente virtual com conda:
Neste exemplo, o pacote
azureml-inference-server-http
é instalado automaticamente. O pacote é incluído como uma biblioteca dependente do pacoteazureml-defaults
no arquivo conda.yml:# Create the environment from the YAML file conda env create --name model-env -f ./environment/conda.yml # Activate the new environment conda activate model-env
Analise seu script de pontuação:
onlinescoring/score.py
import os import logging import json import numpy import joblib def init(): """ This function is called when the container is initialized/started, typically after create/update of the deployment. You can write the logic here to perform init operations like caching the model in memory """ global model # AZUREML_MODEL_DIR is an environment variable created during deployment. # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION) # Please provide your model's folder name if there is one model_path = os.path.join( os.getenv("AZUREML_MODEL_DIR"), "model/sklearn_regression_model.pkl" ) # deserialize the model file back into a sklearn model model = joblib.load(model_path) logging.info("Init complete") def run(raw_data): """ This function is called for every invocation of the endpoint to perform the actual scoring/prediction. In the example we extract the data from the json input and call the scikit-learn model's predict() method and return the result back """ logging.info("model 1: request received") data = json.loads(raw_data)["data"] data = numpy.array(data) result = model.predict(data) logging.info("Request processed") return result.tolist()
Execute o servidor HTTP de inferência especificando o script de pontuação e o arquivo de modelo:
O diretório de modelo especificado no parâmetro
model_dir
é definido usando a variávelAZUREML_MODEL_DIR
e recuperado no script de pontuação.Nesse caso, você especifica o diretório atual ./ porque o subdiretório é especificado no script de pontuação como model/sklearn_regression_model.pkl.
azmlinfsrv --entry_script ./onlinescoring/score.py --model_dir ./
Quando o servidor é iniciado e invoca com êxito o script de pontuação, o log de inicialização de exemplo é aberto. Caso contrário, o log mostrará mensagens de erro.
Teste o script de pontuação com amostra de dados:
Abra outra janela de comando e altere para o mesmo diretório de trabalho em que você executa o comando.
Use o programa utilitário
curl
a fim de enviar uma solicitação de exemplo para o servidor e receber um resultado de pontuação:curl --request POST "127.0.0.1:5001/score" --header "Content-Type:application/json" --data @sample-request.json
Quando não há problemas no script de pontuação, o script retorna o resultado da pontuação. Se ocorrerem problemas, tente atualizar o script de pontuação e iniciar o servidor novamente para testar o script atualizado.
Examinar as rotas do servidor
O servidor HTTP de inferência escuta na porta 5001 por padrão nas seguintes rotas:
Nome | Rota |
---|---|
Investigação de atividade | 127.0.0.1:5001/ |
Pontuação | 127.0.0.1:5001/score |
OpenAPI (Swagger) | 127.0.0.1:5001/swagger.json |
Examinar parâmetros do servidor
O servidor HTTP de inferência aceita os seguintes parâmetros:
Parâmetro | Obrigatório | Padrão | Description |
---|---|---|---|
entry_script |
Verdadeiro | N/D | Identifica o caminho relativo ou absoluto para o script de pontuação. |
model_dir |
Falso | N/D | Identifica o caminho relativo ou absoluto para o diretório que contém o modelo usado para inferência. |
port |
Falso | 5001 | Especifica a porta de serviço do servidor. |
worker_count |
Falso | 1 | Fornece o número de threads de trabalho para processar solicitações simultâneas. |
appinsights_instrumentation_key |
Falso | N/D | Fornece a chave de instrumentação para os insights do aplicativo em que os logs são publicados. |
access_control_allow_origins |
Falso | N/D | Habilita o CORS para as origens especificadas, em que várias origens são separadas por uma vírgula (,), como microsoft.com, bing.com . |
Explorar o processamento de solicitações do servidor
As etapas a seguir demonstram como a inferência do servidor HTTP do Azure Machine Learning (azmlinfsrv
) trata as solicitações de entrada:
Um wrapper da CLI do Python fica em torno da pilha de rede do servidor e é usado para iniciar o servidor.
Um cliente envia uma solicitação ao servidor.
O servidor envia a solicitação por meio do servidor WSGI (Interface de Gateway do Servidor Web), que envia a solicitação para um aplicativo de trabalho do Flask:
O aplicativo de trabalho Flask manipula a solicitação, que inclui o carregamento do script de entrada e quaisquer dependências.
O script de entrada recebe a solicitação. Ele faz uma chamada de inferência para o modelo carregado e retorna uma resposta:
Explorar logs do servidor
Há duas maneiras de obter dados de log para o teste de servidor HTTP de inferência:
- Execute o pacote
azureml-inference-server-http
localmente e exiba a saída de logs. - Use pontos de extremidade online e exiba os logs de contêiner. O log do servidor de inferência é chamado de versão< do > servidor HTTP de Inferência do Azure Machine Learning.
Observação
O formato de registro em log foi alterado desde a versão 0.8.0. Se o log usar um estilo diferente do esperado, atualize o pacote azureml-inference-server-http
para a versão mais recente.
Exibir logs de inicialização
Quando o servidor é iniciado, os logs mostram as configurações iniciais do servidor da seguinte maneira:
Azure Machine Learning Inferencing HTTP server <version>
Server Settings
---------------
Entry Script Name: <entry_script>
Model Directory: <model_dir>
Worker Count: <worker_count>
Worker Timeout (seconds): None
Server Port: <port>
Application Insights Enabled: false
Application Insights Key: <appinsights_instrumentation_key>
Inferencing HTTP server version: azmlinfsrv/<version>
CORS for the specified origins: <access_control_allow_origins>
Server Routes
---------------
Liveness Probe: GET 127.0.0.1:<port>/
Score: POST 127.0.0.1:<port>/score
<logs>
Por exemplo, ao iniciar o servidor seguindo o exemplo de ponta a ponta, o log é exibido da seguinte maneira:
Azure Machine Learning Inferencing HTTP server v0.8.0
Server Settings
---------------
Entry Script Name: /home/user-name/azureml-examples/cli/endpoints/online/model-1/onlinescoring/score.py
Model Directory: ./
Worker Count: 1
Worker Timeout (seconds): None
Server Port: 5001
Application Insights Enabled: false
Application Insights Key: None
Inferencing HTTP server version: azmlinfsrv/0.8.0
CORS for the specified origins: None
Server Routes
---------------
Liveness Probe: GET 127.0.0.1:5001/
Score: POST 127.0.0.1:5001/score
2022-12-24 07:37:53,318 I [32726] gunicorn.error - Starting gunicorn 20.1.0
2022-12-24 07:37:53,319 I [32726] gunicorn.error - Listening at: http://0.0.0.0:5001 (32726)
2022-12-24 07:37:53,319 I [32726] gunicorn.error - Using worker: sync
2022-12-24 07:37:53,322 I [32756] gunicorn.error - Booting worker with pid: 32756
Initializing logger
2022-12-24 07:37:53,779 I [32756] azmlinfsrv - Starting up app insights client
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - Found user script at /home/user-name/azureml-examples/cli/endpoints/online/model-1/onlinescoring/score.py
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - run() is not decorated. Server will invoke it with the input in JSON string.
2022-12-24 07:37:54,518 I [32756] azmlinfsrv.user_script - Invoking user's init function
2022-12-24 07:37:55,974 I [32756] azmlinfsrv.user_script - Users's init has completed successfully
2022-12-24 07:37:55,976 I [32756] azmlinfsrv.swagger - Swaggers are prepared for the following versions: [2, 3, 3.1].
2022-12-24 07:37:55,977 I [32756] azmlinfsrv - AML_FLASK_ONE_COMPATIBILITY is set, but patching is not necessary.
Entender o formato de dados de log
Todos os logs do servidor HTTP de inferência, exceto o script inicializador, apresentam dados no seguinte formato:
<UTC Time> | <level> [<pid>] <logger name> - <message>
A entrada consiste nos seguintes componentes:
<UTC Time>
: hora em que a entrada foi inserida no log.<pid>
: ID do processo associado à entrada.<level>
: primeiro caractere do nível de registros em log da entrada, comoE
para ERROR,I
para INFO e assim por diante.<logger name>
: nome do recurso associado à entrada de log.<message>
: conteúdo da mensagem de log.
Há seis níveis de registro em log no Python com valores numéricos atribuídos de acordo com a gravidade:
Nível de log | Valor numérico |
---|---|
CRÍTICO | 50 |
ERROR | 40 |
AVISO | 30 |
INFORMAÇÕES | 20 |
DEBUG | 10 |
NOTSET | 0 |
Solucionar problemas de servidor
As seções a seguir fornecem dicas básicas de solução de problemas para o servidor HTTP de inferência do Azure Machine Learning. Para solucionar problemas de pontos de extremidade online, consulte Solucionar problemas de implantação de pontos de extremidade online.
Verifique os pacotes instalados
Siga estas etapas para resolver problemas com pacotes instalados.
Colete informações sobre versões e pacotes instalados para o seu ambiente Python.
Confirme que a versão do pacote Python
azureml-inference-server-http
especificada no arquivo de ambiente corresponde à versão do servidor HTTP de inferência do Azure Machine Learning exibida no log de inicialização.Em alguns casos, o resolvedor de dependência PIP instala versões inesperadas do pacote. Talvez seja necessário executar
pip
para corrigir pacotes e versões instalados.Se você tiver especificado o Flask ou as respectivas dependências em seu ambiente, remova esses itens.
- Os pacotes dependentes incluem
flask
,jinja2
,itsdangerous
,werkzeug
,markupsafe
eclick
. flask
é listado como uma dependência no pacote do servidor. A melhor abordagem é permitir que o servidor de inferência instale o pacoteflask
.- Quando o servidor de inferência é configurado para dar suporte a novas versões do Flask, o servidor recebe automaticamente as atualizações de pacote à medida que ficam disponíveis.
- Os pacotes dependentes incluem
Verificar a versão do servidor
O pacote do servidor azureml-inference-server-http
é publicado no PyPI. A página do PyPI lista o log de mudanças e todas as versões anteriores.
Se você estiver usando uma versão anterior do pacote, atualize sua configuração para a última versão. A seguinte tabela resume versões estáveis, problemas comuns e ajustes recomendados:
Versão do pacote | Descrição | Problema | Resolução |
---|---|---|---|
0.4.x | Agrupado em imagens de treinamento datadas 20220601 ou anteriores e azureml-defaults versões de pacote de .1.34 a 1.43 . A versão estável mais recente é 0.4.13. |
Para versões do servidor anteriores à 0.4.11, você pode encontrar problemas de dependência do Flask, como "can't import name Markup from jinja2" . |
Atualize para a versão 0.4.13 ou 0.8.x, a última versão, se possível. |
0.6.x | Pré-instalado em imagens de inferência datadas de 20220516 e anteriores. A versão estável mais recente é 0.6.1. |
N/D | N/D |
0.7.x | Dá suporte ao Flask 2. A versão estável mais recente é 0.7.7. | N/D | N/D |
0.8.x | Formato de log alterado. O suporte ao Python 3.6 terminou. | N/D | N/D |
Verificar dependências do pacote
Os pacotes dependentes mais relevantes para o pacote do servidor azureml-inference-server-http
incluem:
flask
opencensus-ext-azure
inference-schema
Se você especificou o pacote azureml-defaults
em seu ambiente Python, o pacote azureml-inference-server-http
será um pacote dependente. A dependência é instalada automaticamente.
Dica
Se você usar o SDK do Python v1 e não especificar explicitamente o pacote azureml-defaults
em seu ambiente Python, o SDK poderá adicionar automaticamente o pacote. No entanto, a versão do empacotador está bloqueada em relação à versão do SDK. Por exemplo, se a versão do SDK for 1.38.0
, a entrada azureml-defaults==1.38.0
será adicionada aos requisitos de pip do ambiente.
TypeError durante a inicialização do servidor
Você pode encontrar o seguinte TypeError
durante a inicialização do servidor:
TypeError: register() takes 3 positional arguments but 4 were given
File "/var/azureml-server/aml_blueprint.py", line 251, in register
super(AMLBlueprint, self).register(app, options, first_registration)
TypeError: register() takes 3 positional arguments but 4 were given
Esse erro ocorre quando você tem o Flask 2 instalado em seu ambiente Python, mas sua versão do pacote azureml-inference-server-http
não dá suporte ao Flask 2. O suporte para Flask 2 está disponível no pacote azureml-inference-server-http
versão 0.7.0 e posterior, e no pacote azureml-defaults
versão 1.44 e posterior.
Se você não usar o pacote Flask 2 em uma imagem do Docker do Azure Machine Learning, use a última versão do pacote
azureml-inference-server-http
ouazureml-defaults
.Se você usar o pacote Flask 2 em uma imagem do Docker do Azure Machine Learning, conforme se a versão de build da imagem é de julho de 2022 ou posterior.
Você pode encontrar a versão da imagem nos logs de contêiner. Por exemplo:
2022-08-22T17:05:02,147738763+00:00 | gunicorn/run | AzureML Container Runtime Information 2022-08-22T17:05:02,161963207+00:00 | gunicorn/run | ############################################### 2022-08-22T17:05:02,168970479+00:00 | gunicorn/run | 2022-08-22T17:05:02,174364834+00:00 | gunicorn/run | 2022-08-22T17:05:02,187280665+00:00 | gunicorn/run | AzureML image information: openmpi4.1.0-ubuntu20.04, Materialization Build:20220708.v2 2022-08-22T17:05:02,188930082+00:00 | gunicorn/run | 2022-08-22T17:05:02,190557998+00:00 | gunicorn/run |
A data de build da imagem é exibida após a notação
Materialization Build
. No exemplo anterior, a versão da imagem é20220708
ou 8 de julho de 2022. A imagem neste exemplo é compatível com o Flask 2.Se você não vir uma mensagem similar no log de contêineres, sua imagem estará desatualizada e deverá ser atualizada. Se você usar uma imagem CUDA (arquitetura de dispositivo unificado de computação) e não encontrar uma imagem mais recente, verifique se sua imagem foi preterida em AzureML-Containers. Você pode encontrar substituições designadas para imagens preteridas.
Se você usar o servidor com um ponto de extremidade online, também poderá encontrar os logs em Logs na página Pontos de extremidade no Estúdio do Azure Machine Learning.
Se você implantar com o SDK v1 e não especificar explicitamente uma imagem em sua configuração de implantação, o servidor aplicará o pacote openmpi4.1.0-ubuntu20.04
com uma versão que corresponda ao conjunto de ferramentas do SDK local. No entanto, a versão instalada pode não ser a versão mais recente disponível da imagem.
Para o SDK versão 1.43, o servidor instala a versão do pacote openmpi4.1.0-ubuntu20.04:20220616
por padrão, mas essa versão do pacote não é compatível com o SDK 1.43. Certifique-se de usar o SDK mais recente para sua implantação.
Se não for possível atualizar a imagem, você poderá evitar temporariamente o problema fixando as entradas azureml-defaults==1.43
ou azureml-inference-server-http~=0.4.13
no arquivo de ambiente. Essas entradas direcionam o servidor para instalar a versão mais antiga com flask 1.0.x
.
ImportError ou ModuleNotFoundError durante a inicialização do servidor
Você pode encontrar um ImportError
ou ModuleNotFoundError
em módulos específicos, como opencensus
, jinja2
, markupsafe
ou click
, durante a inicialização do servidor. O exemplo a seguir mostra a mensagem de erro:
ImportError: cannot import name 'Markup' from 'jinja2'
Os erros de importação e módulo ocorrem quando você usa a versão 0.4.10 ou versões anteriores do servidor que não fixam a dependência do Flask a uma versão compatível. Para evitar o problema, instale uma versão posterior do servidor.