Partilhar via


Implantar modelos de linguagem em pontos finais em batch

APLICA-SE A:Azure CLI ml extension v2 (current)Python SDK azure-ai-ml v2 (current)

Utilize endpoints em lote para implementar modelos intensivos em recursos, como modelos de linguagem, sobre dados de texto. Neste tutorial, aprende a implementar um modelo que pode realizar a sumarização de texto de longas sequências de texto usando um modelo do HuggingFace. Também mostra como otimizar a inferência usando as bibliotecas HuggingFace optimum e accelerate.

Sobre este exemplo

O modelo com que trabalha neste tutorial utiliza a popular transformers biblioteca do HuggingFace juntamente com um modelo pré-treinado do Facebook com a arquitetura BART. O modelo 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:

  • Funciona com sequências até 1.024 tokens.
  • Este sistema é treinado para resumir textos em inglês.
  • Usa o Torch 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 ou colar YAML e outros arquivos, use os seguintes comandos para clonar o repositório e vá para a pasta para sua linguagem de codificação:

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

Pode seguir este exemplo num Jupyter Notebook. No repositório clonado, abra o bloco de anotações: text-summarization-batch.ipynb.

Pré-requisitos

  • Uma subscrição do Azure. Se você não tiver uma assinatura do Azure, crie uma conta gratuita.

  • 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.

  • As seguintes permissões no espaço de trabalho do Azure Machine Learning:

    • Para criar ou gerir endpoints e implementações em lote: Use uma função de Proprietário, Contribuidor ou personalizada que possua as permissões Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.
    • Para criar implementações do Azure Resource Manager no grupo de recursos do workspace: Use uma função de Proprietário, Contribuinte ou personalizada que tenha permissão Microsoft.Resources/deployments/write no grupo de recursos onde o workspace é implementado.
  • A CLI do Azure Machine Learning ou o SDK do Azure Machine Learning para Python:

    Execute o seguinte comando para instalar a Azure CLI e a ml:

    az extension add -n ml
    

    As implementações de componentes de pipeline para endpoints de lote requerem a versão 2.7 ou posterior da extensão ml para o Azure CLI (versão atual: 2.37.0). Use o az extension update --name ml comando para obter a versão mais recente.


Conectar ao seu espaço de trabalho

O espaço de trabalho é o recurso de nível superior para o Azure Machine Learning. Ele fornece um local centralizado para trabalhar com todos os artefatos que você cria quando usa o Azure 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 sua ID de assinatura, nome do espaço de trabalho, nome do grupo de recursos e local:

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 está incluído neste repositório. Em vez disso, pode descarregar uma cópia a partir do repositório de modelos do 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'
model.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"

Criar o endpoint

Vamos criar um endpoint em lote chamado text-summarization-batch para implantar o modelo HuggingFace para realizar a sumarização de texto em ficheiros de texto em inglês.

  1. Decida o nome do endpoint. O nome do ponto de extremidade acaba por ser parte do 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 endpoint de lote com o nome mybatchendpoint em westus2.

    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"
    
  2. Configurar o seu ponto final em lote

    O seguinte ficheiro YAML define um endereço 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
    
  3. 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:

  1. 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 um pipeline 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 e accelerate 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 mini-batch fornecido pela implementação em lote.
    • A run função lê todo o lote usando a datasets biblioteca. O texto que precisamos resumir está na coluna text.
    • 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. Note que o modelo não é executado com o objeto pipeline de transformers. 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.

    code/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 quando se lida com modelos caros (como transformadores), porque 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 (exceções OOM).

  2. Precisamos indicar em qual ambiente vamos executar a implantação. No nosso caso, o nosso modelo funciona em Torch e requer as bibliotecas transformers, accelerate e optimum da HuggingFace. O Azure Machine Learning já tem um ambiente com suporte a Tocha e GPU disponível. Vamos apenas adicionar algumas dependências em um conda.yaml arquivo.

    environment/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]
    
  3. 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 criámos requer um dispositivo de hardware compatível com CUDA 12.1 para correr o Torch 2.0 no Ubuntu 22.04. Certifique-se de que o seu cluster de computação GPU utiliza um tamanho de VM que suporte CUDA 12.1 ou posterior, como Standard_NCasT4_v3.

  4. 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, porque o cluster permanece sem quaisquer nós ativos até que um endpoint de processamento em lote seja invocado e um processo de avaliação em lote seja enviado. Saiba mais sobre como gerenciar e otimizar custos para AmlCompute.

  5. Agora, vamos proceder à implementaçã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 endpoint 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

    Nota-se nesta implementação um valor elevado em timeout no parâmetro retry_settings. A razão envolve a natureza do modelo que estamos executando. Este é um modelo caro e a inferência numa única linha pode demorar até 60 segundos. O timeout parâmetro controla 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 fazer. Processar um arquivo de cada vez por lote é caro o suficiente para justificá-lo. Repara que isto é um padrão no Processamento de Linguagem Natural (PLN).

  6. 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 permite alterar a implantação padrão e, assim, alterar o modelo que está a servir a implantação sem alterar o contrato com o utilizador que invoca o endpoint. 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
    
  7. Neste ponto, o nosso endpoint de batch está pronto para ser utilizado.

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.

  1. Vamos invocar o endpoint:

    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 estar 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.

  2. 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
    
  3. 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 anterior, 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 ficheiros o seu modelo pode avaliar de 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 puder processar um ficheiro de cada vez (como neste exemplo), considere ler os dados de entrada em linhas ou segmentos. 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 o timeout indica o tempo que a implantação em lote esperaria para que o seu 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 anteriormente 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 em forma de 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 Registrar modelos personalizados.
    • Crie um script de pontuação e carregue o seu modelo usando mlflow.<flavor>.load_model(). Consulte Usando modelos MLflow com um script de pontuação para obter detalhes.