Nasazení jazykových modelů v dávkových koncových bodech

PLATÍ PRO:Rozšíření Azure CLI ml v2 (aktuální)Python SDK azure-ai-ml v2 (aktuální)

Koncové body služby Batch je možné použít k nasazení drahých modelů, jako jsou jazykové modely, přes textová data. V tomto kurzu se dozvíte, jak nasadit model, který dokáže provádět souhrny textu dlouhých sekvencí textu pomocí modelu z HuggingFace. Ukazuje také, jak provést optimalizaci odvozování pomocí HuggingFace optimum a accelerate knihoven.

O této ukázce

Model, se kterým budeme pracovat, byl sestaven pomocí oblíbených transformátorů knihovny z HuggingFace spolu s předem natrénovaným modelem z Facebooku s architekturou BART. Byla představena v dokumentu BART: Denoising Sequence-to-Sequence Pre-Training for Natural Language Generation. Tento model má následující omezení, která jsou důležitá pro nasazení:

  • Může pracovat s sekvencemi až 1024 tokenů.
  • Vytrénuje se pro shrnutí textu v angličtině.
  • Budeme používat Torch jako back-end.

Příklad v tomto článku vychází z ukázek kódu obsažených v úložišti azureml-examples . Pokud chcete příkazy spustit místně, aniž byste museli kopírovat nebo vkládat YAML a další soubory, nejprve naklonujte úložiště a pak změňte adresáře do složky:

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

Soubory pro tento příklad jsou v:

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

Sledování v poznámkových blocích Jupyter

Tuto ukázku můžete sledovat v poznámkovém bloku Jupyter. V klonovaném úložišti otevřete poznámkový blok: text-summarization-batch.ipynb.

Požadavky

Než budete postupovat podle kroků v tomto článku, ujistěte se, že máte následující požadavky:

  • Předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet. Vyzkoušejte bezplatnou nebo placenou verzi služby Azure Machine Učení.

  • Pracovní prostor služby Azure Machine Learning. Pokud ho nemáte, vytvořte ho pomocí kroků v článku Správa Učení pracovních prostorů Azure.

  • Ujistěte se, že máte v pracovním prostoru následující oprávnění:

    • Vytváření nebo správa dávkových koncových bodů a nasazení: Použijte roli Vlastník, Přispěvatel nebo Vlastní, která umožňuje Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.

    • Vytvořte nasazení ARM ve skupině prostředků pracovního prostoru: Použijte roli Vlastník, Přispěvatel nebo Vlastní, která umožňuje Microsoft.Resources/deployments/write ve skupině prostředků, ve které je pracovní prostor nasazený.

  • Abyste mohli pracovat se službou Azure Machine Učení, musíte nainstalovat následující software:

    Azure CLI a mlrozšíření pro azure machine Učení.

    az extension add -n ml
    

    Poznámka:

    Nasazení součástí kanálu pro koncové body služby Batch byla zavedena ve verzi 2.7 ml rozšíření pro Azure CLI. Slouží az extension update --name ml k získání poslední verze.

Připojení k pracovnímu prostoru

Pracovní prostor je prostředek nejvyšší úrovně pro Azure Machine Learning, který nabízí centralizované místo, kde můžete pracovat se všemi artefakty, které vytvoříte při použití služby Azure Machine Learning. V této části se připojíme k pracovnímu prostoru, ve kterém budete provádět úlohy nasazení.

Hodnoty ID předplatného, pracovního prostoru, umístění a skupiny prostředků předejte v následujícím kódu:

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

Registrace modelu

Vzhledem k velikosti modelu ho v tomto úložišti nezahrnuli. Místo toho si můžete stáhnout kopii z centra modelu HuggingFace. Budete potřebovat balíčky transformers a torch nainstalovat je v prostředí, které používáte.

%pip install transformers torch

Ke stažení modelu do složky modelpoužijte následující kód:

from transformers import pipeline

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

Tento model teď můžeme zaregistrovat v registru služby Azure Machine Učení:

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

Vytvoření koncového bodu

Vytvoříme dávkový koncový bod s názvem text-summarization-batch , kde nasadíme model HuggingFace pro spuštění sumarizace textu u textových souborů v angličtině.

  1. Rozhodněte se o názvu koncového bodu. Název koncového bodu končí v identifikátoru URI přidruženém k vašemu koncovému bodu. Z tohoto důvodu musí být názvy dávkových koncových bodů jedinečné v rámci oblasti Azure. Například může existovat pouze jeden dávkový koncový bod s názvem mybatchendpoint v westus2.

    V tomto případě umístíme název koncového bodu do proměnné, abychom na něj později mohli snadno odkazovat.

    ENDPOINT_NAME="text-summarization-batch"
    
  2. Konfigurace dávkového koncového bodu

    Následující soubor YAML definuje dávkový koncový bod:

    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. Vytvořte koncový bod:

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

Vytvoření nasazení

Pojďme vytvořit nasazení, které je hostitelem modelu:

  1. Musíme vytvořit bodovací skript, který může číst soubory CSV poskytnuté dávkovém nasazením a vrátit skóre modelu souhrnem. Následující skript provede tyto akce:

    • Označuje init funkci, která zjistí hardwarovou konfiguraci (cpu vs. GPU) a odpovídajícím způsobem model načte. Model i tokenizátor se načítají do globálních proměnných. K určení omezení v posloupnosti modelu, který aktuálně používáme, nepoužíváme pipeline objekt z HuggingFace.
    • Všimněte si, že provádíme optimalizace modelů za účelem zlepšení výkonu pomocí optimum a accelerate knihoven. Pokud ho model nebo hardware nepodporuje, spustíme nasazení bez takových optimalizací.
    • Označuje run funkci, která se spustí pro každou minidávku, kterou poskytuje dávkové nasazení.
    • Funkce run přečte celou dávku pomocí datasets knihovny. Text, který potřebujeme sumarizovat, je ve sloupci text.
    • Metoda run iteruje přes každý řádek textu a spustí predikci. Vzhledem k tomu, že se jedná o velmi drahý model, spuštění předpovědi nad celými soubory způsobí výjimku mimo paměť. Všimněte si, že se model nespustí s objektem pipeline z transformers. To se provádí s ohledem na dlouhé posloupnosti textu a omezení 1024 tokenů v podkladovém modelu, který používáme.
    • Vrátí souhrn zadaného textu.

    kód/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
    

    Tip

    I když nasazení poskytuje soubory v minidávkách, tento skript bodování zpracovává současně jeden řádek. Jedná se o běžný vzor při práci s drahými modely (například transformátory) při pokusu o načtení celé dávky a jeho odeslání do modelu najednou může vést k vysokému zatížení paměti na dávkové exekutor (exekuce OOM).

  2. Musíme určit, ve kterém prostředí nasazení spustíme. V našem případě náš model běží a Torch vyžaduje knihovny transformers, acceleratea optimum z HuggingFace. Azure Machine Učení už má prostředí s podporou Torch a GPU k dispozici. Do souboru přidáme několik závislostí conda.yaml .

    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. Soubor conda uvedený výše můžeme použít následujícím způsobem:

    Definice prostředí je součástí souboru nasazení.

    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
    

    Důležité

    Prostředí torch200-transformers-gpu , které jsme vytvořili, vyžaduje hardwarové zařízení kompatibilní s CUDA 11.8 pro spuštění Torch 2.0 a Ubuntu 20.04. Pokud vaše zařízení GPU tuto verzi CUDA nepodporuje, můžete zkontrolovat alternativní torch113-conda.yaml prostředí Conda (dostupné také v úložišti), na kterém běží Torch 1.3 přes Ubuntu 18.04 s CUDA 10.1. U této konfigurace se ale akcelerace s využitím optimum knihoven accelerate nepodporuje.

  4. Každé nasazení běží na výpočetních clusterech. Podporují jak clustery Azure Machine Učení Compute (AmlCompute), tak clustery Kubernetes. V tomto příkladu může náš model těžit z akcelerace GPU, což je důvod, proč používáme cluster GPU.

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

    Poznámka:

    Za výpočetní prostředky se vám v tomto okamžiku nebudou účtovat poplatky, protože cluster zůstane na 0 uzlech, dokud se nevyvolá dávkový koncový bod a neodesílají se úloha dávkového vyhodnocování. Přečtěte si další informace o správě a optimalizaci nákladů na AmlCompute.

  5. Teď vytvoříme nasazení.

    Pokud chcete vytvořit nové nasazení v rámci vytvořeného koncového bodu, vytvořte YAML konfiguraci jako v následujícím příkladu. Můžete zkontrolovat, jestli schéma YAML celého dávkového koncového bodu obsahuje další vlastnosti.

    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
    

    Pak vytvořte nasazení pomocí následujícího příkazu:

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

    Důležité

    V tomto nasazení si všimnete vysoké hodnoty v timeout parametru retry_settings. Důvodem je povaha modelu, který používáme. Jedná se o velmi drahý model a odvozování na jednom řádku může trvat až 60 sekund. Parametry timeout řídí, kolik času má dávkové nasazení čekat na dokončení zpracování jednotlivých minidávkových skriptů. Vzhledem k tomu, že náš model spouští řádek předpovědí po řádcích, může zpracování dlouhého souboru nějakou dobu trvat. Všimněte si také, že počet souborů na dávku je nastaven na 1 (mini_batch_size=1). To je opět v souvislosti s povahou práce, které děláme. Zpracování jednoho souboru najednou na dávku je dostatečně nákladné, aby bylo možné ho odůvodnit. Všimněte si, že se jedná o vzor při zpracování NLP.

  6. I když můžete vyvolat konkrétní nasazení uvnitř koncového bodu, obvykle chcete vyvolat samotný koncový bod a nechat koncový bod rozhodnout, které nasazení použít. Toto nasazení se nazývá výchozí nasazení. To vám dává možnost změnit výchozí nasazení a tím změnit model obsluhující nasazení beze změny kontraktu s uživatelem vyvoláním koncového bodu. K aktualizaci výchozího nasazení použijte následující pokyny:

    DEPLOYMENT_NAME="text-summarization-hfbart"
    az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
    
  7. V tuto chvíli je náš dávkový koncový bod připravený k použití.

Testování nasazení

Pro testování našeho koncového bodu použijeme vzorek datové sady BillSum: A Corpus for Automatic Summarization of US Legislation. Tato ukázka je součástí úložiště ve složce data. Všimněte si, že formát dat je CSV a obsah, který se má sumarizovat, je pod sloupcem text, podle očekávání modelu.

  1. Pojďme vyvolat koncový bod:

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

    Poznámka:

    jq Nástroj nemusí být nainstalován v každé instalaci. Pokyny najdete na tomto odkazu.

    Tip

    Všimněte si, že když jako vstup označíte místní cestu, data se nahrají do účtu úložiště Azure Machine Učení výchozím nastavení.

  2. Dávková úloha se spustí hned po vrácení příkazu. Stav úlohy můžete monitorovat, dokud se nedokončí:

    az ml job show -n $JOB_NAME --web
    
  3. Po dokončení nasazení si můžeme stáhnout předpovědi:

    K stažení předpovědí použijte následující příkaz:

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

Důležité informace o nasazení modelů, které zpracovávají text

Jak je uvedeno v některých poznámkách v tomto kurzu, zpracování textu může mít určité specifika, které vyžadují konkrétní konfiguraci pro dávkové nasazení. Při návrhu dávkového nasazení vezměte v úvahu následující skutečnosti:

  • Některé modely NLP můžou být z hlediska paměti a výpočetního času velmi nákladné. V takovém případě zvažte snížení počtu souborů zahrnutých v každé minidávce. V předchozím příkladu bylo číslo převzato na minimum, 1 soubor na dávku. I když to nemusí být váš případ, vezměte v úvahu, kolik souborů může váš model pokaždé skóre. Mějte na paměti, že vztah mezi velikostí vstupu a nároky na paměť modelu nemusí být lineární pro modely hlubokého učení.
  • Pokud váš model nedokáže zpracovat jeden soubor najednou (například v tomto příkladu), zvažte čtení vstupních dat v řádcích nebo blocích. Pokud potřebujete dosáhnout vyšší propustnosti nebo využití hardwaru, implementujte dávky na úrovni řádku.
  • timeout Nastavte hodnotu nasazení tak, aby odpovídala tomu, jak nákladný model je a kolik dat očekáváte ke zpracování. Mějte na timeout paměti, že značí dobu, po kterou dávkové nasazení počká, než se skript bodování spustí pro danou dávku. Pokud má vaše dávka mnoho souborů nebo souborů s mnoha řádky, má to vliv na správnou hodnotu tohoto parametru.

Důležité informace o modelech MLflow, které zpracovávají text

Stejné aspekty, které jsme zmínili výše, platí pro modely MLflow. Vzhledem k tomu, že pro nasazení modelu MLflow nepotřebujete zadat bodovací skript, můžou některá uvedená doporučení vyžadovat jiný přístup.

  • Modely MLflow v koncových bodech služby Batch podporují čtení tabulkových dat jako vstupních dat, která mohou obsahovat dlouhé sekvence textu. Podrobnosti o podporovaných typech souborů najdete v části Podpora typů souborů.
  • Nasazení služby Batch volá funkci predikce modelu MLflow s obsahem celého souboru v datovém rámci Pandas. Pokud vstupní data obsahují mnoho řádků, je pravděpodobné, že spuštění komplexního modelu (jako je tomu v tomto kurzu) způsobí výjimku mimo paměť. Pokud se jedná o váš případ, můžete zvážit:
    • Přizpůsobte si, jak model spouští předpovědi a implementuje dávkování. Informace o přizpůsobení odvozování modelu MLflow najdete v tématu Protokolování vlastních modelů.
    • Vytvořte bodovací skript a načtěte model pomocí mlflow.<flavor>.load_model(). Podrobnosti najdete v tématu Použití modelů MLflow se skriptem bodování.