Wdrażanie modeli językowych w punktach końcowych wsadowych
DOTYCZY: Rozszerzenie interfejsu wiersza polecenia platformy Azure w wersji 2 (current)Zestaw PYTHON SDK azure-ai-ml v2 (bieżąca)
Punkty końcowe usługi Batch mogą służyć do wdrażania kosztownych modeli, takich jak modele językowe, za pośrednictwem danych tekstowych. Z tego samouczka dowiesz się, jak wdrożyć model, który może wykonywać podsumowania tekstu długie sekwencje tekstu przy użyciu modelu z aplikacji HuggingFace. Pokazano również, jak przeprowadzić optymalizację wnioskowania przy użyciu bibliotek HuggingFace i accelerate
HuggingFaceoptimum
.
Informacje o tym przykładzie
Model, z który będziemy pracować, został utworzony przy użyciu popularnych transformatorów biblioteki z HuggingFace wraz ze wstępnie wytrenowanym modelem z Facebooka z architekturą BART. Został on wprowadzony w artykule BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation (Denoising Sequence-to-Sequence Pre-training for Natural Language Generation). Ten model ma następujące ograniczenia, które są ważne, aby pamiętać o wdrożeniu:
- Może działać z sekwencjami do 1024 tokenów.
- Jest on szkolony do podsumowywania tekstu w języku angielskim.
- Będziemy używać Torch jako zaplecza.
Przykład w tym artykule jest oparty na przykładach kodu zawartych w repozytorium azureml-examples . Aby uruchomić polecenia lokalnie bez konieczności kopiowania/wklejania kodu YAML i innych plików, najpierw sklonuj repozytorium, a następnie zmień katalogi na folder:
git clone https://github.com/Azure/azureml-examples --depth 1
cd azureml-examples/cli
Pliki dla tego przykładu znajdują się w następujących elementach:
cd endpoints/batch/deploy-models/huggingface-text-summarization
Postępuj zgodnie z instrukcjami w notesach Jupyter Notebook
Możesz skorzystać z tego przykładu w notesie Jupyter Notebook. W sklonowanym repozytorium otwórz notes: text-summarization-batch.ipynb.
Wymagania wstępne
Subskrypcja platformy Azure. Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto. Wypróbuj bezpłatną lub płatną wersję usługi Azure Machine Learning.
Obszar roboczy usługi Azure Machine Learning. Aby utworzyć obszar roboczy, zobacz Zarządzanie obszarami roboczymi usługi Azure Machine Learning.
Upewnij się, że masz następujące uprawnienia w obszarze roboczym usługi Machine Learning:
- Tworzenie punktów końcowych i wdrożeń wsadowych lub zarządzanie nimi: użyj roli właściciela, współautora lub niestandardowej, która zezwala na
Microsoft.MachineLearningServices/workspaces/batchEndpoints/*
usługę . - Tworzenie wdrożeń usługi Azure Resource Manager w grupie zasobów obszaru roboczego: użyj roli Właściciel, Współautor lub Niestandardowy, która umożliwia
Microsoft.Resources/deployments/write
korzystanie z grupy zasobów, w której wdrożono obszar roboczy.
- Tworzenie punktów końcowych i wdrożeń wsadowych lub zarządzanie nimi: użyj roli właściciela, współautora lub niestandardowej, która zezwala na
Zainstaluj następujące oprogramowanie do pracy z usługą Machine Learning:
Uruchom następujące polecenie, aby zainstalować interfejs wiersza polecenia platformy Azure i
ml
rozszerzenie usługi Azure Machine Learning:az extension add -n ml
Wdrożenia składników potoku dla punktów końcowych usługi Batch są wprowadzane w wersji 2.7
ml
rozszerzenia dla interfejsu wiersza polecenia platformy Azure. Użyj polecenia ,az extension update --name ml
aby pobrać najnowszą wersję.
Nawiązywanie połączenia z obszarem roboczym
Obszar roboczy to zasób najwyższego poziomu dla usługi Machine Learning. Zapewnia scentralizowane miejsce do pracy ze wszystkimi artefaktami tworzonymi podczas korzystania z usługi Machine Learning. W tej sekcji nawiąż połączenie z obszarem roboczym, w którym wykonujesz zadania wdrażania.
W poniższym poleceniu wprowadź wartości identyfikatora subskrypcji, obszaru roboczego, lokalizacji i grupy zasobów:
az account set --subscription <subscription>
az configure --defaults workspace=<workspace> group=<resource-group> location=<location>
Rejestrowanie modelu
Ze względu na rozmiar modelu nie został on uwzględniony w tym repozytorium. Zamiast tego możesz pobrać kopię z centrum modelu HuggingFace. Potrzebne są pakiety transformers
i torch
zainstalowane w używanym środowisku.
%pip install transformers torch
Użyj następującego kodu, aby pobrać model do folderu model
:
from transformers import pipeline
model = pipeline("summarization", model="facebook/bart-large-cnn")
model_local_path = 'model'
summarizer.save_pretrained(model_local_path)
Teraz możemy zarejestrować ten model w rejestrze usługi Azure Machine Learning:
MODEL_NAME='bart-text-summarization'
az ml model create --name $MODEL_NAME --path "model"
Tworzenie punktu końcowego
Utworzymy punkt końcowy partii o nazwie text-summarization-batch
gdzie wdrożyć model HuggingFace w celu uruchomienia podsumowania tekstu w plikach tekstowych w języku angielskim.
Zdecyduj o nazwie punktu końcowego. Nazwa punktu końcowego kończy się identyfikatorem URI skojarzonym z punktem końcowym. W związku z tym nazwy punktów końcowych partii muszą być unikatowe w regionie świadczenia usługi Azure. Na przykład może istnieć tylko jeden punkt końcowy wsadowy o nazwie
mybatchendpoint
w plikuwestus2
.W takim przypadku umieśćmy nazwę punktu końcowego w zmiennej, abyśmy mogli ją łatwo odwołać później.
ENDPOINT_NAME="text-summarization-batch"
Konfigurowanie punktu końcowego wsadowego
Następujący plik YAML definiuje punkt końcowy partii:
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
Utwórz punkt końcowy:
az ml batch-endpoint create --file endpoint.yml --name $ENDPOINT_NAME
Tworzenie wdrożenia
Utwórzmy wdrożenie hostujące model:
Musimy utworzyć skrypt oceniania, który może odczytywać pliki CSV dostarczone przez wdrożenie wsadowe i zwracać wyniki modelu z podsumowaniem. Poniższy skrypt wykonuje następujące akcje:
- Wskazuje funkcję, która wykrywa konfigurację
init
sprzętu (procesor CPU i procesor GPU) i odpowiednio ładuje model. Zarówno model, jak i tokenizer są ładowane w zmiennych globalnych. Nie używamypipeline
obiektu z funkcji HuggingFace, aby uwzględnić ograniczenie w sekwencji aktualnie używanego modelu. - Zwróć uwagę, że przeprowadzamy optymalizacje modelu w celu zwiększenia wydajności przy użyciu
optimum
bibliotek iaccelerate
. Jeśli model lub sprzęt nie obsługuje go, uruchomimy wdrożenie bez takich optymalizacji. run
Wskazuje funkcję, która jest wykonywana dla każdej mini-partii zapewnia wdrożenie wsadowe.- Funkcja
run
odczytuje całą partiędatasets
przy użyciu biblioteki. Tekst, który musimy podsumować, znajduje się w kolumnietext
. - Metoda
run
iteruje poszczególne wiersze tekstu i uruchamia przewidywanie. Ponieważ jest to bardzo kosztowny model, uruchomienie przewidywania dla całych plików spowoduje wyjątek braku pamięci. Zwróć uwagę, że model nie jest wykonywany z obiektempipeline
.transformers
Jest to wykonywane w celu uwzględnienia długich sekwencji tekstu i ograniczenia 1024 tokenów w używanym modelu bazowym. - Zwraca podsumowanie podanego tekstu.
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
Napiwek
Mimo że pliki są udostępniane w minisadach przez wdrożenie, ten skrypt oceniania przetwarza jeden wiersz naraz. Jest to typowy wzorzec podczas pracy z kosztownymi modelami (takimi jak transformatory), gdy próbuje załadować całą partię i wysłać ją naraz do modelu, może spowodować wysokie wykorzystanie pamięci na funkcji wykonawczej partii (exeptions OOM).
- Wskazuje funkcję, która wykrywa konfigurację
Musimy wskazać, w którym środowisku będziemy uruchamiać wdrożenie. W naszym przypadku nasz model jest uruchamiany i
Torch
wymaga bibliotektransformers
,accelerate
ioptimum
z narzędzia HuggingFace. Usługa Azure Machine Learning ma już środowisko z dostępną obsługą platformy Torch i procesora GPU. Dodamy tylko kilka zależności wconda.yaml
pliku.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]
Możemy użyć wymienionego wcześniej pliku conda w następujący sposób:
Definicja środowiska jest zawarta w pliku wdrożenia.
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
Ważne
Utworzone środowisko
torch200-transformers-gpu
wymaga zgodnego urządzenia sprzętowego CUDA 11.8 do uruchamiania platformy Torch 2.0 i Ubuntu 20.04. Jeśli urządzenie z procesorem GPU nie obsługuje tej wersji cuda, możesz sprawdzić alternatywnetorch113-conda.yaml
środowisko Conda (dostępne również w repozytorium), które uruchamia torch 1.3 w systemie Ubuntu 18.04 z cudA 10.1. Jednak przyspieszenie przy użyciuoptimum
bibliotek iaccelerate
nie będzie obsługiwane w tej konfiguracji.Każde wdrożenie jest uruchamiane w klastrach obliczeniowych. Obsługują one zarówno klastry obliczeniowe usługi Azure Machine Learning (AmlCompute) jak i klastry Kubernetes. W tym przykładzie nasz model może korzystać z przyspieszania procesora GPU, dlatego używamy klastra gpu.
az ml compute create -n gpu-cluster --type amlcompute --size STANDARD_NV6 --min-instances 0 --max-instances 2
Uwaga
W tym momencie nie są naliczane opłaty za zasoby obliczeniowe, ponieważ klaster pozostaje w 0 węzłach do momentu wywołania punktu końcowego wsadowego i przesłania zadania oceniania wsadowego. Dowiedz się więcej na temat zarządzania kosztami i optymalizowania pod kątem usługi AmlCompute.
Teraz utwórzmy wdrożenie.
Aby utworzyć nowe wdrożenie w ramach utworzonego punktu końcowego, utwórz konfigurację podobną
YAML
do poniższej. Możesz sprawdzić pełny schemat YAML punktu końcowego wsadowego pod kątem dodatkowych właściwości.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
Następnie utwórz wdrożenie za pomocą następującego polecenia:
az ml batch-deployment create --file deployment.yml --endpoint-name $ENDPOINT_NAME --set-default
Ważne
W tym wdrożeniu zauważysz wysoką wartość w
timeout
parametrzeretry_settings
. Przyczyną jest charakter uruchomionego modelu. Jest to bardzo kosztowny model i wnioskowanie w jednym wierszu może potrwać do 60 sekund. Parametrytimeout
kontrolują czas oczekiwania na zakończenie przetwarzania każdego minisadowego skryptu oceniania. Ponieważ nasz model uruchamia wiersz przewidywania według wiersza, przetwarzanie długiego pliku może zająć trochę czasu. Zwróć również uwagę, że liczba plików na partię jest ustawiona na 1 (mini_batch_size=1
). Jest to ponownie związane z naturą wykonywanej pracy. Przetwarzanie jednego pliku naraz na partię jest wystarczająco kosztowne, aby go uzasadnić. Zauważysz, że jest to wzorzec przetwarzania NLP.Chociaż można wywołać określone wdrożenie wewnątrz punktu końcowego, zazwyczaj chcesz wywołać sam punkt końcowy i pozwolić punktowi końcowemu zdecydować, które wdrożenie ma być używane. Takie wdrożenie nosi nazwę "domyślnego" wdrożenia. Daje to możliwość zmiany wdrożenia domyślnego, a tym samym zmiany modelu obsługującego wdrożenie bez zmiany umowy z użytkownikiem wywołującym punkt końcowy. Aby zaktualizować wdrożenie domyślne, użyj następującej instrukcji:
DEPLOYMENT_NAME="text-summarization-hfbart" az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
W tym momencie nasz punkt końcowy wsadowy jest gotowy do użycia.
Testowanie wdrożenia
W celu przetestowania naszego punktu końcowego użyjemy próbki zestawu danych BillSum: Corpus for Automatic Summarization of US Legislation (Podsumowanie automatyczne przepisów amerykańskich). Ten przykład znajduje się w repozytorium w folderze data
. Zwróć uwagę, że format danych to CSV, a zawartość do podsumowania znajduje się w kolumnie text
, zgodnie z oczekiwaniami modelu.
Wywołajmy punkt końcowy:
JOB_NAME=$(az ml batch-endpoint invoke --name $ENDPOINT_NAME --input data --input-type uri_folder --query name -o tsv)
Uwaga
jq
Narzędzie może nie być zainstalowane w każdej instalacji. Możesz uzyskać instrukcje w tym linku.Napiwek
Zwróć uwagę, że wskazując ścieżkę lokalną jako dane wejściowe, dane są przekazywane do domyślnego konta magazynu usługi Azure Machine Learning.
Zadanie wsadowe jest uruchamiane natychmiast po powrocie polecenia. Stan zadania można monitorować do momentu jego zakończenia:
az ml job show -n $JOB_NAME --web
Po zakończeniu wdrażania możemy pobrać przewidywania:
Aby pobrać przewidywania, użyj następującego polecenia:
az ml job download --name $JOB_NAME --output-name score --download-path .
Zagadnienia dotyczące wdrażania modeli, które przetwarzają tekst
Jak wspomniano w niektórych notatkach w tym samouczku, przetwarzanie tekstu może mieć pewne osobliwości, które wymagają określonej konfiguracji dla wdrożeń wsadowych. Podczas projektowania wdrożenia wsadowego należy wziąć pod uwagę następujące kwestie:
- Niektóre modele NLP mogą być bardzo kosztowne pod względem pamięci i czasu obliczeniowego. Jeśli tak jest, rozważ zmniejszenie liczby plików uwzględnionych w każdej minisadowej partii. W powyższym przykładzie liczba została pobrana do minimalnej, 1 pliku na partię. Chociaż może to nie być Twój przypadek, należy wziąć pod uwagę liczbę plików, które model może oceniać za każdym razem. Należy pamiętać, że relacja między rozmiarem danych wejściowych i pamięcią modelu może nie być liniowa dla modeli uczenia głębokiego.
- Jeśli model nie może nawet obsłużyć jednego pliku naraz (na przykład w tym przykładzie), rozważ odczytanie danych wejściowych w wierszach/fragmentach. Zaimplementuj przetwarzanie wsadowe na poziomie wiersza, jeśli chcesz osiągnąć większą przepływność lub wykorzystanie sprzętu.
timeout
Ustaw wartość wdrożenia odpowiednio na kosztowny model i ilość danych, które mają być przetwarzane. Należy pamiętać, że parametrtimeout
wskazuje czas oczekiwania wdrożenia wsadowego na uruchomienie skryptu oceniania dla danej partii. Jeśli w partii istnieje wiele plików lub plików z wieloma wierszami, ma to wpływ na właściwą wartość tego parametru.
Zagadnienia dotyczące modeli MLflow, które przetwarzają tekst
Te same zagadnienia, o których wspomniano powyżej, dotyczą modeli MLflow. Jednak ponieważ nie jest wymagane podanie skryptu oceniania dla wdrożenia modelu MLflow, niektóre wymienione zalecenia mogą wymagać innego podejścia.
- Modele MLflow w punktach końcowych usługi Batch obsługują odczytywanie danych tabelarycznych jako danych wejściowych, które mogą zawierać długie sekwencje tekstu. Zobacz Obsługa typów plików, aby uzyskać szczegółowe informacje o obsługiwanych typach plików.
- Wdrożenia wsadowe wywołuje funkcję predict modelu MLflow z zawartością całego pliku w ramce danych biblioteki Pandas. Jeśli dane wejściowe zawierają wiele wierszy, prawdopodobieństwo uruchomienia złożonego modelu (na przykład przedstawionego w tym samouczku) powoduje wyjątek braku pamięci. Jeśli tak jest, możesz rozważyć następujące kwestie:
- Dostosuj sposób uruchamiania przewidywań modelu i implementowanie przetwarzania wsadowego. Aby dowiedzieć się, jak dostosować wnioskowanie modelu MLflow, zobacz Rejestrowanie modeli niestandardowych.
- Utwórz skrypt oceniania i załaduj model przy użyciu polecenia
mlflow.<flavor>.load_model()
. Aby uzyskać szczegółowe informacje, zobacz Używanie modeli MLflow ze skryptem oceniania.