Distribuera språkmodeller i batchslutpunkter

GÄLLER FÖR:Azure CLI ml extension v2 (current)Python SDK azure-ai-ml v2 (aktuell)

Batchslutpunkter kan användas för att distribuera dyra modeller, till exempel språkmodeller, över textdata. I den här självstudien får du lära dig hur du distribuerar en modell som kan utföra textsammanfattning av långa textsekvenser med hjälp av en modell från HuggingFace. Den visar också hur du gör slutsatsdragningsoptimering med huggingFace optimum och accelerate bibliotek.

Om det här exemplet

Modellen som vi ska arbeta med byggdes med hjälp av de populära bibliotekstransformatorerna från HuggingFace tillsammans med en förtränad modell från Facebook med BART-arkitekturen. Den introducerades i tidningen BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation. Den här modellen har följande begränsningar, som är viktiga att tänka på för distributionen:

  • Det kan fungera med sekvenser upp till 1 024 token.
  • Den tränas för sammanfattning av text på engelska.
  • Vi ska använda Torch som en serverdel.

Exemplet i den här artikeln baseras på kodexempel som finns på lagringsplatsen azureml-examples . Om du vill köra kommandona lokalt utan att behöva kopiera/klistra in YAML och andra filer klonar du först lagringsplatsen och ändrar sedan kataloger till mappen:

git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli

Filerna för det här exemplet finns i:

cd endpoints/batch/deploy-models/huggingface-text-summarization

Följ med i Jupyter Notebooks

Du kan följa det här exemplet i en Jupyter Notebook. På den klonade lagringsplatsen öppnar du notebook-filen: text-summarization-batch.ipynb.

Förutsättningar

  • En Azure-prenumeration. Om du inte har någon Azure-prenumeration kan du skapa ett kostnadsfritt konto innan du börjar. Prova den kostnadsfria eller betalda versionen av Azure Mašinsko učenje.

  • En Azure Machine Learning-arbetsyta. Information om hur du skapar en arbetsyta finns i Hantera Azure Mašinsko učenje-arbetsytor.

  • Kontrollera att du har följande behörigheter på Mašinsko učenje-arbetsytan:

    • Skapa eller hantera batchslutpunkter och distributioner: Använd en ägare, deltagare eller anpassad roll som tillåter Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.
    • Skapa Azure Resource Manager-distributioner i arbetsytans resursgrupp: Använd en roll som ägare, deltagare eller anpassad som tillåter Microsoft.Resources/deployments/write i den resursgrupp där arbetsytan distribueras.
  • Installera följande programvara för att arbeta med Mašinsko učenje:

    Kör följande kommando för att installera Azure CLI och ml tillägget för Azure Mašinsko učenje:

    az extension add -n ml
    

    Distributioner av pipelinekomponenter för Batch-slutpunkter introduceras i version 2.7 av ml tillägget för Azure CLI. az extension update --name ml Använd kommandot för att hämta den senaste versionen.


Anslut till din arbetsyta

Arbetsytan är resursen på den översta nivån för Mašinsko učenje. Den ger en central plats där du kan arbeta med alla artefakter som du skapar när du använder Mašinsko učenje. I det här avsnittet ansluter du till arbetsytan där du utför dina distributionsuppgifter.

I följande kommando anger du värdena för ditt prenumerations-ID, arbetsyta, plats och resursgrupp:

az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>

Registrera modellen

På grund av modellens storlek har den inte inkluderats i den här lagringsplatsen. I stället kan du ladda ned en kopia från HuggingFace-modellens hubb. Du behöver paketen transformers och torch installeras i den miljö som du använder.

%pip install transformers torch

Använd följande kod för att ladda ned modellen till en mapp model:

from transformers import pipeline

model = pipeline("summarization", model="facebook/bart-large-cnn")
model_local_path = 'model'
summarizer.save_pretrained(model_local_path)

Nu kan vi registrera den här modellen i Azure Mašinsko učenje-registret:

MODEL_NAME='bart-text-summarization'
az ml model create --name $MODEL_NAME --path "model"

Skapa slutpunkten

Vi ska skapa en batchslutpunkt med namnet text-summarization-batch där huggingFace-modellen ska distribueras för att köra textsammanfattning på textfiler på engelska.

  1. Bestäm namnet på slutpunkten. Namnet på slutpunkten hamnar i den URI som är associerad med slutpunkten. Därför måste batchslutpunktsnamn vara unika i en Azure-region. Det kan till exempel bara finnas en batchslutpunkt med namnet mybatchendpoint i westus2.

    I det här fallet placerar vi namnet på slutpunkten i en variabel så att vi enkelt kan referera till den senare.

    ENDPOINT_NAME="text-summarization-batch"
    
  2. Konfigurera batchslutpunkten

    Följande YAML-fil definierar en batchslutpunkt:

    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. Skapa slutpunkten:

    az ml batch-endpoint create --file endpoint.yml  --name $ENDPOINT_NAME
    

Skapa distributionen

Nu ska vi skapa den distribution som är värd för modellen:

  1. Vi måste skapa ett bedömningsskript som kan läsa CSV-filerna som tillhandahålls av batchdistributionen och returnera poängen för modellen med sammanfattningen. Följande skript utför följande åtgärder:

    • Anger en init funktion som identifierar maskinvarukonfigurationen (CPU jämfört med GPU) och läser in modellen i enlighet med detta. Både modellen och tokeniseraren läses in i globala variabler. Vi använder inte ett pipeline -objekt från HuggingFace för att ta hänsyn till begränsningen i sekvensen för den modell som vi använder för närvarande.
    • Observera att vi utför modelloptimeringar för att förbättra prestandan med hjälp av optimum och accelerate bibliotek. Om modellen eller maskinvaran inte stöder den kör vi distributionen utan sådana optimeringar.
    • Anger en run funktion som körs för varje mini-batch som batchdistributionen tillhandahåller.
    • Funktionen run läser hela batchen med hjälp av datasets biblioteket. Texten som vi behöver sammanfatta finns i kolumnen text.
    • Metoden run itererar över var och en av raderna i texten och kör förutsägelsen. Eftersom det här är en mycket dyr modell resulterar körningen av förutsägelsen över hela filer i ett undantagsfel utan minne. Observera att modellen inte körs med objektet pipeline från transformers. Detta görs för att ta hänsyn till långa textsekvenser och begränsningen för 1 024 token i den underliggande modellen som vi använder.
    • Den returnerar sammanfattningen av den angivna texten.

    kod/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
    

    Dricks

    Även om filer tillhandahålls i mini-batchar av distributionen bearbetar det här bedömningsskriptet en rad i taget. Detta är ett vanligt mönster när du hanterar dyra modeller (till exempel transformatorer) eftersom försök att läsa in hela batchen och skicka den till modellen på en gång kan leda till hög minnesbelastning på batchexekutor (OOM-exeptions).

  2. Vi måste ange över vilken miljö vi ska köra distributionen. I vårt fall körs vår modell på Torch och den kräver biblioteken transformers, accelerateoch optimum från HuggingFace. Azure Mašinsko učenje har redan en miljö med stöd för Torch och GPU. Vi ska bara lägga till ett par beroenden i en conda.yaml fil.

    miljö/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. Vi kan använda conda-filen som nämnts tidigare enligt följande:

    Miljödefinitionen ingår i distributionsfilen.

    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
    

    Viktigt!

    torch200-transformers-gpu Miljön som vi har skapat kräver en CUDA 11.8-kompatibel maskinvaruenhet för att köra Torch 2.0 och Ubuntu 20.04. Om GPU-enheten inte stöder den här versionen av CUDA kan du kontrollera den alternativa torch113-conda.yaml conda-miljön (även tillgänglig på lagringsplatsen), som kör Torch 1.3 över Ubuntu 18.04 med CUDA 10.1. Acceleration med hjälp av biblioteken optimum och accelerate stöds dock inte i den här konfigurationen.

  4. Varje distribution körs på beräkningskluster. De stöder både Azure Mašinsko učenje Compute-kluster (AmlCompute) eller Kubernetes-kluster. I det här exemplet kan vår modell dra nytta av GPU-acceleration, vilket är anledningen till att vi använder ett GPU-kluster.

    az ml compute create -n gpu-cluster --type amlcompute --size STANDARD_NV6 --min-instances 0 --max-instances 2
    

    Kommentar

    Du debiteras inte för beräkning just nu eftersom klustret ligger kvar på 0 noder förrän en batchslutpunkt anropas och ett batchbedömningsjobb skickas. Läs mer om att hantera och optimera kostnader för AmlCompute.

  5. Nu ska vi skapa distributionen.

    Om du vill skapa en ny distribution under den skapade slutpunkten skapar du en YAML konfiguration som följande. Du kan kontrollera YAML-schemat för den fullständiga batchslutpunkten för extra egenskaper.

    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
    

    Skapa sedan distributionen med följande kommando:

    az ml batch-deployment create --file deployment.yml --endpoint-name $ENDPOINT_NAME --set-default
    

    Viktigt!

    I den här distributionen ser du ett högt värde i timeout parametern retry_settings. Anledningen till det beror på vilken typ av modell vi kör. Detta är en mycket dyr modell och slutsatsdragning på en enda rad kan ta upp till 60 sekunder. Parametrarna timeout styr hur lång tid Batch-distributionen ska vänta tills bedömningsskriptet har slutfört bearbetningen av varje mini-batch. Eftersom vår modell kör förutsägelser rad för rad kan det ta tid att bearbeta en lång fil. Observera också att antalet filer per batch är inställt på 1 (mini_batch_size=1). Detta är återigen relaterat till arten av det arbete vi utför. Det är tillräckligt dyrt att bearbeta en fil i taget per batch för att motivera den. Du kommer att märka att detta är ett mönster i NLP-bearbetning.

  6. Även om du kan anropa en specifik distribution i en slutpunkt vill du vanligtvis anropa själva slutpunkten och låta slutpunkten bestämma vilken distribution som ska användas. En sådan distribution heter "standard"-distributionen. Detta ger dig möjlighet att ändra standarddistributionen och därmed ändra modellen som betjänar distributionen utan att ändra kontraktet med användaren som anropar slutpunkten. Använd följande instruktion för att uppdatera standarddistributionen:

    DEPLOYMENT_NAME="text-summarization-hfbart"
    az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
    
  7. Nu är vår batchslutpunkt redo att användas.

Testa distributionen

För att testa vår slutpunkt ska vi använda ett exempel på datamängden BillSum: A Corpus for Automatic Summarization of US Legislation. Det här exemplet ingår i lagringsplatsen i mappen data. Observera att formatet för data är CSV och att innehållet som ska sammanfattas finns under kolumnen text, som förväntat av modellen.

  1. Nu ska vi anropa slutpunkten:

    JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input data --input-type uri_folder --query name -o tsv)
    

    Kommentar

    Verktyget jq kanske inte installeras på varje installation. Du kan få instruktioner i den här länken.

    Dricks

    Observera att genom att ange en lokal sökväg som indata laddas data upp till Azure Mašinsko učenje standardlagringskonto.

  2. Ett batchjobb startas så snart kommandot returnerar. Du kan övervaka statusen för jobbet tills det har slutförts:

    az ml job show -n $JOB_NAME --web
    
  3. När distributionen är klar kan vi ladda ned förutsägelserna:

    Om du vill ladda ned förutsägelserna använder du följande kommando:

    az ml job download --name $JOB_NAME --output-name score --download-path .
    

Överväganden vid distribution av modeller som bearbetar text

Som nämnts i några av anteckningarna i den här självstudien kan bearbetning av text ha vissa egenheter som kräver specifik konfiguration för batchdistributioner. Tänk på följande när du utformar batchdistributionen:

  • Vissa NLP-modeller kan vara mycket dyra när det gäller minne och beräkningstid. Om så är fallet bör du överväga att minska antalet filer som ingår i varje mini-batch. I exemplet ovan togs talet till minst 1 fil per batch. Även om detta kanske inte är ditt fall bör du ta hänsyn till hur många filer din modell kan göra poäng på varje gång. Tänk på att relationen mellan indatastorleken och din modells minnesfotavtryck kanske inte är linjär för djupinlärningsmodeller.
  • Om din modell inte ens kan hantera en fil i taget (som i det här exemplet) kan du läsa indata i rader/segment. Implementera batchbearbetning på radnivå om du behöver uppnå högre dataflöde eller maskinvaruanvändning.
  • Ange värdet för distributionen timeout enligt överenskommelse till hur dyr din modell är och hur mycket data du förväntar dig att bearbeta. Kom ihåg att timeout anger den tid batchdistributionen skulle vänta på att ditt bedömningsskript skulle köras för en viss batch. Om batchen har många filer eller filer med många rader påverkar detta det rätta värdet för den här parametern.

Överväganden för MLflow-modeller som bearbetar text

Samma överväganden som nämns ovan gäller för MLflow-modeller. Men eftersom du inte behöver ange ett bedömningsskript för din MLflow-modelldistribution kan vissa av de rekommendationer som nämns kräva en annan metod.

  • MLflow-modeller i Batch-slutpunkter stöder läsning av tabelldata som indata, som kan innehålla långa textsekvenser. Mer information om vilka filtyper som stöds finns i Stöd för filtyper.
  • Batchdistributioner anropar MLflow-modellens förutsägelsefunktion med innehållet i en hel fil i som Pandas-dataram. Om dina indata innehåller många rader är chansen stor att körningen av en komplex modell (som den som visas i den här självstudien) resulterar i ett undantag utan minne. Om så är fallet kan du överväga: