Implantar modelos de linguagem em pontos de extremidade em lote
APLICA-SE A:Azure CLI ml extension v2 (current)Python SDK azure-ai-ml v2 (current)
Os pontos de extremidade em lote podem ser usados para implantar modelos caros, como modelos de linguagem, sobre dados de texto. Neste tutorial, você aprenderá a implantar um modelo que pode executar o resumo de texto de longas sequências de texto usando um modelo do HuggingFace. Ele também mostra como fazer otimização de inferência usando HuggingFace optimum
e accelerate
bibliotecas.
Sobre este exemplo
O modelo com o qual vamos trabalhar foi construído usando os populares transformadores de biblioteca da HuggingFace, juntamente com um modelo pré-treinado do Facebook com a arquitetura BART. Foi introduzido no artigo BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation. Este modelo tem as seguintes restrições, que são importantes ter em mente para a implantação:
- Pode trabalhar com sequências de até 1024 tokens.
- É treinado para resumir texto em inglês.
- Vamos usar a Tocha como backend.
O exemplo neste artigo é baseado em exemplos de código contidos no repositório azureml-examples . Para executar os comandos localmente sem ter que copiar/colar YAML e outros arquivos, primeiro clone o repositório e, em seguida, altere os diretórios para a pasta:
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli
Os arquivos para este exemplo estão em:
cd endpoints/batch/deploy-models/huggingface-text-summarization
Acompanhe em Jupyter Notebooks
Você pode acompanhar este exemplo em um Caderno Jupyter. No repositório clonado, abra o bloco de anotações: text-summarization-batch.ipynb.
Pré-requisitos
Uma subscrição do Azure. Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar. Experimente a versão gratuita ou paga do Azure Machine Learning.
Uma área de trabalho do Azure Machine Learning. Para criar um espaço de trabalho, consulte Gerenciar espaços de trabalho do Azure Machine Learning.
Verifique se você tem as seguintes permissões no espaço de trabalho Aprendizado de Máquina:
- Criar ou gerenciar pontos de extremidade em lote e implantações: use uma função Proprietário, Colaborador ou Personalizada que permita
Microsoft.MachineLearningServices/workspaces/batchEndpoints/*
o . - Criar implantações do Azure Resource Manager no grupo de recursos do espaço de trabalho: use uma função Proprietário, Colaborador ou Personalizada que permita
Microsoft.Resources/deployments/write
a entrada no grupo de recursos onde o espaço de trabalho está implantado.
- Criar ou gerenciar pontos de extremidade em lote e implantações: use uma função Proprietário, Colaborador ou Personalizada que permita
Instale o seguinte software para trabalhar com Machine Learning:
Execute o seguinte comando para instalar a CLI do Azure e a extensão para o
ml
Azure Machine Learning:az extension add -n ml
As implantações de componentes de pipeline para pontos de extremidade em lote são introduzidas na versão 2.7 da
ml
extensão para a CLI do Azure. Use oaz extension update --name ml
comando para obter a versão mais recente.
Ligar à sua área de trabalho
O espaço de trabalho é o recurso de nível superior para Machine Learning. Ele fornece um local centralizado para trabalhar com todos os artefatos que você cria quando usa o Machine Learning. Nesta seção, você se conecta ao espaço de trabalho onde executa suas tarefas de implantação.
No comando a seguir, insira os valores para sua ID de assinatura, espaço de trabalho, local e grupo de recursos:
az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>
Registo do modelo
Devido ao tamanho do modelo, ele não foi incluído neste repositório. Em vez disso, você pode baixar uma cópia do hub do modelo HuggingFace. Você precisa dos pacotes transformers
e torch
instalados no ambiente que está usando.
%pip install transformers torch
Use o código a seguir para baixar o modelo para uma pasta model
:
from transformers import pipeline
model = pipeline("summarization", model="facebook/bart-large-cnn")
model_local_path = 'model'
summarizer.save_pretrained(model_local_path)
Agora podemos registrar esse modelo no registro do Azure Machine Learning:
MODEL_NAME='bart-text-summarization'
az ml model create --name $MODEL_NAME --path "model"
Criando o ponto de extremidade
Vamos criar um ponto de extremidade em lote chamado text-summarization-batch
onde implantar o modelo HuggingFace para executar o resumo de texto em arquivos de texto em inglês.
Decida o nome do ponto de extremidade. O nome do ponto de extremidade termina no URI associado ao seu ponto de extremidade. Por isso, os nomes de ponto de extremidade em lote precisam ser exclusivos dentro de uma região do Azure. Por exemplo, pode haver apenas um ponto de extremidade em lote com o nome
mybatchendpoint
emwestus2
.Nesse caso, vamos colocar o nome do ponto de extremidade em uma variável para que possamos facilmente consultá-lo mais tarde.
ENDPOINT_NAME="text-summarization-batch"
Configurar seu ponto de extremidade em lote
O seguinte arquivo YAML define um ponto de extremidade em lote:
endpoint.yml
$schema: https://azuremlschemas.azureedge.net/latest/batchEndpoint.schema.json name: text-summarization-batch description: A batch endpoint for summarizing text using a HuggingFace transformer model. auth_mode: aad_token
Crie o ponto de extremidade:
az ml batch-endpoint create --file endpoint.yml --name $ENDPOINT_NAME
Criando a implantação
Vamos criar a implantação que hospeda o modelo:
Precisamos criar um script de pontuação que possa ler os arquivos CSV fornecidos pela implantação em lote e retornar as pontuações do modelo com o resumo. O script a seguir executa essas ações:
- Indica uma
init
função que deteta a configuração de hardware (CPU vs GPU) e carrega o modelo de acordo. Tanto o modelo quanto o tokenizador são carregados em variáveis globais. Não estamos usando umpipeline
objeto do HuggingFace para explicar a limitação nos comprimentos de sequência do modelo que estamos usando atualmente. - Observe que estamos realizando otimizações de modelo para melhorar o desempenho usando
optimum
eaccelerate
bibliotecas. Se o modelo ou hardware não oferecer suporte a ele, executaremos a implantação sem essas otimizações. - Indica uma
run
função que é executada para cada minilote fornecido pela implantação em lote. - A
run
função lê todo o lote usando adatasets
biblioteca. O texto que precisamos resumir está na colunatext
. - O
run
método itera sobre cada uma das linhas do texto e executa a previsão. Como este é um modelo muito caro, executar a previsão em arquivos inteiros resultará em uma exceção de falta de memória. Observe que o modelo não é executado com opipeline
objeto detransformers
. Isso é feito para levar em conta longas sequências de texto e a limitação de 1024 tokens no modelo subjacente que estamos usando. - Ele retorna o resumo do texto fornecido.
código/batch_driver.py
import os import time import torch import subprocess import mlflow from pprint import pprint from transformers import AutoTokenizer, BartForConditionalGeneration from optimum.bettertransformer import BetterTransformer from datasets import load_dataset def init(): global model global tokenizer global device cuda_available = torch.cuda.is_available() device = "cuda" if cuda_available else "cpu" if cuda_available: print(f"[INFO] CUDA version: {torch.version.cuda}") print(f"[INFO] ID of current CUDA device: {torch.cuda.current_device()}") print("[INFO] nvidia-smi output:") pprint( subprocess.run(["nvidia-smi"], stdout=subprocess.PIPE).stdout.decode( "utf-8" ) ) else: print( "[WARN] CUDA acceleration is not available. This model takes hours to run on medium size data." ) # AZUREML_MODEL_DIR is an environment variable created during deployment model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model") # load the tokenizer tokenizer = AutoTokenizer.from_pretrained( model_path, truncation=True, max_length=1024 ) # Load the model try: model = BartForConditionalGeneration.from_pretrained( model_path, device_map="auto" ) except Exception as e: print( f"[ERROR] Error happened when loading the model on GPU or the default device. Error: {e}" ) print("[INFO] Trying on CPU.") model = BartForConditionalGeneration.from_pretrained(model_path) device = "cpu" # Optimize the model if device != "cpu": try: model = BetterTransformer.transform(model, keep_original_model=False) print("[INFO] BetterTransformer loaded.") except Exception as e: print( f"[ERROR] Error when converting to BetterTransformer. An unoptimized version of the model will be used.\n\t> {e}" ) mlflow.log_param("device", device) mlflow.log_param("model", type(model).__name__) def run(mini_batch): resultList = [] print(f"[INFO] Reading new mini-batch of {len(mini_batch)} file(s).") ds = load_dataset("csv", data_files={"score": mini_batch}) start_time = time.perf_counter() for idx, text in enumerate(ds["score"]["text"]): # perform inference inputs = tokenizer.batch_encode_plus( [text], truncation=True, padding=True, max_length=1024, return_tensors="pt" ) input_ids = inputs["input_ids"].to(device) summary_ids = model.generate( input_ids, max_length=130, min_length=30, do_sample=False ) summaries = tokenizer.batch_decode( summary_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False ) # Get results: resultList.append(summaries[0]) rps = idx / (time.perf_counter() - start_time + 00000.1) print("Rows per second:", rps) mlflow.log_metric("rows_per_second", rps) return resultList
Gorjeta
Embora os arquivos sejam fornecidos em minilotes pela implantação, esse script de pontuação processa uma linha de cada vez. Este é um padrão comum ao lidar com modelos caros (como transformadores), pois tentar carregar o lote inteiro e enviá-lo para o modelo de uma só vez pode resultar em alta pressão de memória no executor de lote (exepções OOM).
- Indica uma
Precisamos indicar em qual ambiente vamos executar a implantação. No nosso caso, o nosso modelo funciona
Torch
e requer as bibliotecastransformers
,accelerate
eoptimum
do HuggingFace. O Azure Machine Learning já tem um ambiente com suporte a Tocha e GPU disponível. Vamos apenas adicionar algumas dependências em umconda.yaml
arquivo.ambiente/torch200-conda.yaml
name: huggingface-env channels: - conda-forge dependencies: - python=3.8.5 - pip - pip: - torch==2.0 - transformers - accelerate - optimum - datasets - mlflow - azureml-mlflow - azureml-core - azureml-dataset-runtime[fuse]
Podemos usar o arquivo conda mencionado anteriormente da seguinte forma:
A definição de ambiente está incluída no arquivo de implantação.
deployment.yml
compute: azureml:gpu-cluster environment: name: torch200-transformers-gpu image: mcr.microsoft.com/azureml/openmpi4.1.0-cuda11.8-cudnn8-ubuntu22.04:latest
Importante
O ambiente
torch200-transformers-gpu
que criamos requer um dispositivo de hardware compatível com CUDA 11.8 para executar o Torch 2.0 e o Ubuntu 20.04. Se o seu dispositivo GPU não suporta esta versão do CUDA, você pode verificar o ambiente conda alternativotorch113-conda.yaml
(também disponível no repositório), que executa o Torch 1.3 sobre o Ubuntu 18.04 com CUDA 10.1. No entanto, a aceleração usando as bibliotecas eaccelerate
não será suportadaoptimum
nessa configuração.Cada implantação é executada em clusters de computação. Eles dão suporte a clusters de computação do Azure Machine Learning (AmlCompute) ou clusters Kubernetes. Neste exemplo, nosso modelo pode se beneficiar da aceleração da GPU, e é por isso que usamos um cluster de GPU.
az ml compute create -n gpu-cluster --type amlcompute --size STANDARD_NV6 --min-instances 0 --max-instances 2
Nota
Você não será cobrado pela computação neste momento, pois o cluster permanece em 0 nós até que um ponto de extremidade em lote seja invocado e um trabalho de pontuação em lote seja enviado. Saiba mais sobre como gerenciar e otimizar custos para AmlCompute.
Agora, vamos criar a implantação.
Para criar uma nova implantação sob o ponto de extremidade criado, crie uma
YAML
configuração como a seguinte. Você pode verificar o esquema YAML do ponto de extremidade de lote completo para obter propriedades extras.deployment.yml
$schema: https://azuremlschemas.azureedge.net/latest/modelBatchDeployment.schema.json endpoint_name: text-summarization-batch name: text-summarization-optimum description: A text summarization deployment implemented with HuggingFace and BART architecture with GPU optimization using Optimum. type: model model: azureml:bart-text-summarization@latest compute: azureml:gpu-cluster environment: name: torch200-transformers-gpu image: mcr.microsoft.com/azureml/openmpi4.1.0-cuda11.8-cudnn8-ubuntu22.04:latest conda_file: environment/torch200-conda.yaml code_configuration: code: code scoring_script: batch_driver.py resources: instance_count: 2 settings: max_concurrency_per_instance: 1 mini_batch_size: 1 output_action: append_row output_file_name: predictions.csv retry_settings: max_retries: 1 timeout: 3000 error_threshold: -1 logging_level: info
Em seguida, crie a implantação com o seguinte comando:
az ml batch-deployment create --file deployment.yml --endpoint-name $ENDPOINT_NAME --set-default
Importante
Você notará nesta implantação um alto valor no
timeout
parâmetroretry_settings
. A razão para isso deve-se à natureza do modelo que estamos a executar. Este é um modelo muito caro e a inferência em uma única linha pode levar até 60 segundos. Ostimeout
parâmetros controlam quanto tempo a implantação em lote deve aguardar até que o script de pontuação termine o processamento de cada minilote. Como nosso modelo executa previsões linha por linha, o processamento de um arquivo longo pode levar tempo. Observe também que o número de arquivos por lote está definido como 1 (mini_batch_size=1
). Isto está, mais uma vez, relacionado com a natureza do trabalho que estamos a realizar. Processar um arquivo de cada vez por lote é caro o suficiente para justificá-lo. Você notará que este é um padrão no processamento de PNL.Embora você possa invocar uma implantação específica dentro de um ponto de extremidade, geralmente deseja invocar o próprio ponto de extremidade e deixar que o ponto de extremidade decida qual implantação usar. Essa implantação é chamada de implantação "padrão". Isso lhe dá a possibilidade de alterar a implantação padrão e, portanto, alterar o modelo que serve a implantação sem alterar o contrato com o usuário invocando o ponto de extremidade. Use as seguintes instruções para atualizar a implantação padrão:
DEPLOYMENT_NAME="text-summarization-hfbart" az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
Neste ponto, nosso ponto de extremidade em lote está pronto para ser usado.
Testando a implantação
Para testar nosso endpoint, vamos usar uma amostra do conjunto de dados BillSum: A Corpus for Automatic Summarization of US Legislation. Este exemplo está incluído no repositório na pasta data
. Observe que o formato dos dados é CSV e o conteúdo a ser resumido está sob a coluna text
, conforme esperado pelo modelo.
Vamos invocar o ponto de extremidade:
JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input data --input-type uri_folder --query name -o tsv)
Nota
O utilitário
jq
pode não ser instalado em todas as instalações. Você pode obter instruções neste link.Gorjeta
Observe que, ao indicar um caminho local como entrada, os dados são carregados na conta de armazenamento padrão do Azure Machine Learning.
Um trabalho em lote é iniciado assim que o comando retorna. Você pode monitorar o status do trabalho até que ele termine:
az ml job show -n $JOB_NAME --web
Quando a implantação estiver concluída, podemos baixar as previsões:
Para baixar as previsões, use o seguinte comando:
az ml job download --name $JOB_NAME --output-name score --download-path .
Considerações ao implantar modelos que processam texto
Como mencionado em algumas das notas ao longo deste tutorial, o processamento de texto pode ter algumas peculiaridades que exigem configuração específica para implantações em lote. Leve a seguinte consideração ao projetar a implantação em lote:
- Alguns modelos de PNL podem ser muito caros em termos de memória e tempo de computação. Se for esse o caso, considere diminuir o número de arquivos incluídos em cada minilote. No exemplo acima, o número foi levado ao mínimo, 1 arquivo por lote. Embora este possa não ser o seu caso, leve em consideração quantos arquivos seu modelo pode pontuar em cada vez. Tenha em mente que a relação entre o tamanho da entrada e a pegada de memória do seu modelo pode não ser linear para modelos de aprendizagem profunda.
- Se o seu modelo não conseguir lidar com um arquivo de cada vez (como neste exemplo), considere ler os dados de entrada em linhas/partes. Implemente o processamento em lote no nível da linha se precisar obter uma taxa de transferência ou utilização de hardware mais alta.
- Defina o
timeout
valor da sua implantação de acordo com o quão caro é o seu modelo e a quantidade de dados que você espera processar. Lembre-se de que otimeout
indica o tempo que a implantação em lote esperaria que o script de pontuação fosse executado para um determinado lote. Se o lote tiver muitos arquivos ou arquivos com muitas linhas, isso afetará o valor correto desse parâmetro.
Considerações para modelos MLflow que processam texto
As mesmas considerações mencionadas acima aplicam-se aos modelos MLflow. No entanto, como você não é obrigado a fornecer um script de pontuação para a implantação do modelo MLflow, algumas das recomendações mencionadas podem exigir uma abordagem diferente.
- Os modelos MLflow em Batch Endpoints suportam a leitura de dados tabulares como dados de entrada, que podem conter longas sequências de texto. Consulte Suporte a tipos de arquivo para obter detalhes sobre quais tipos de arquivo são suportados.
- As implantações em lote chamam a função de previsão do seu modelo MLflow com o conteúdo de um arquivo inteiro como dataframe Pandas. Se os dados de entrada contiverem muitas linhas, é provável que a execução de um modelo complexo (como o apresentado neste tutorial) resulte em uma exceção de falta de memória. Se este for o seu caso, pode considerar:
- Personalize como seu modelo executa previsões e implemente lotes. Para saber como personalizar a inferência do modelo MLflow, consulte Registrando modelos personalizados.
- Crie um script de pontuação e carregue seu modelo usando
mlflow.<flavor>.load_model()
o . Consulte Usando modelos MLflow com um script de pontuação para obter detalhes.