Развертывание языковых моделей в пакетных конечных точках

ОБЛАСТЬ ПРИМЕНЕНИЯ:Дополнение Azure CLI для машинного обучения версии 2 (текущая версия)Python SDK azure-ai-ml версии 2 (текущая версия)

Используйте конечные точки пакетной обработки для развертывания ресурсоемких моделей, например, языковых моделей, над текстовыми данными. В этом руководстве вы узнаете, как развернуть модель, которая может выполнять сводку текста длинных последовательностей текста с помощью модели из HuggingFace. В нем также показано, как оптимизировать вычисления с помощью библиотек HuggingFace optimum и accelerate.

Об этом примере

Модель, с которой вы работаете в этом руководстве, использует популярную transformers библиотеку от HuggingFace вместе с предварительно обученной моделью от Facebook с архитектурой BART. Модель была представлена в статье BART: Шумоподавление в предварительном обучении модели «последовательность в последовательность» для генерации текста на естественном языке. Эта модель имеет следующие ограничения, которые важно учитывать при развертывании:

  • Он работает с последовательностями до 1024 токенов.
  • Он обучен суммировать текст на английском языке.
  • Он использует Torch в качестве серверной части.

Пример в этой статье основан на примерах кода, содержащихся в репозитории azureml-examples . Чтобы выполнять команды локально, не копируя и вставляя YAML и другие файлы, используйте следующие команды, чтобы клонировать репозиторий и перейти в папку для языка программирования:

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

Файлы для этого примера находятся в следующих файлах:

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

Следуйте инструкциям в Jupyter Notebooks

Вы можете следовать этому примеру в Jupyter Notebook. В клонируемом репозитории откройте записную книжку: text-summarization-batch.ipynb.

Предварительные требования

  • Подписка Azure. Если у вас нет подписки Azure, создайте бесплатную учетную запись.

  • Рабочая область Машинного обучения Azure. Чтобы создать рабочую область, смотрите раздел Управление рабочими областями Машинное обучение Azure.

  • Следующие разрешения в рабочей области Машинное обучение Azure:

    • Для создания или управления пакетными конечными точками и развертываниями используйте роль владельца, участника или настраиваемую роль с разрешениями Microsoft.MachineLearningServices/workspaces/batchEndpoints/*.
    • Для создания развертываний Azure Resource Manager в группе ресурсов рабочей области: используйте роль «владелец», «участник» или настраиваемую роль, которая имеет разрешение Microsoft.Resources/deployments/write в группе ресурсов, в которой развернута рабочая область.
  • Интерфейс командной строки (CLI) «Машинное обучение Azure» или пакет SDK «Машинное обучение Azure» для Python:

    Выполните следующую команду, чтобы установить Azure CLI и mlрасширение для Машинное обучение Azure:

    az extension add -n ml
    

    Для развертывания компонентов конвейера для пакетных конечных точек требуется расширение версии 2.7 или более поздней для Azure CLI (текущая версия: 2.37.0). az extension update --name ml Используйте команду, чтобы получить последнюю версию.


Подключитесь к рабочей области

Рабочая область — это ресурс верхнего уровня для Машинного обучения Azure. Он предоставляет централизованное место для работы со всеми объектами, создаваемыми при использовании Машинное обучение Azure. В этом разделе описано, как подключиться к рабочей области, в которой выполняются задачи развертывания.

В следующей команде введите идентификатор подписки, имя рабочей области, имя группы ресурсов и расположение:

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

Регистрация модели

Из-за размера модели он не включен в этот репозиторий. Вместо этого можно скачать копию из репозитория моделей HuggingFace. Вам нужны пакеты transformers и torch установленные в среде, которую вы используете.

%pip install transformers torch

Используйте следующий код, чтобы скачать модель в папку model:

from transformers import pipeline

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

Теперь эту модель можно зарегистрировать в реестре Машинное обучение Azure:

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

Создание конечной точки

Мы создадим пакетную конечную точку с именем text-summarization-batch , в которой будет развернута модель HuggingFace для выполнения суммирования текста в текстовых файлах на английском языке.

  1. Определите имя конечной точки. Имя конечной точки становится частью URI, связанного с вашей конечной точкой. Из-за этого имена конечных точек пакетной службы должны быть уникальными в пределах региона Azure. Например, может быть только одна пакетная конечная точка с именем mybatchendpoint в westus2.

    В этом случае давайте поместим имя конечной точки в переменную, чтобы можно было легко ссылаться на нее позже.

    ENDPOINT_NAME="text-summarization-batch"
    
  2. Настройка конечной точки пакета

    Следующий файл YAML определяет конечную точку пакетной обработки:

    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. Создание конечной точки:

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

Создание развертывания

Создадим развертывание для размещения модели.

  1. Нам нужно создать скрипт оценки, который может считывать CSV-файлы, предоставляемые пакетным развертыванием, и возвращать оценки модели с сводкой. Следующий скрипт выполняет следующие действия:

    • Указывает init функцию, которая обнаруживает конфигурацию оборудования (ЦП и GPU) и загружает модель соответствующим образом. Модель и токенизатор загружаются в глобальные переменные. Мы не используем pipeline объект библиотеки HuggingFace для учета ограничений по длине последовательности модели, используемой в настоящее время.
    • Обратите внимание, что мы выполняем оптимизацию моделей для повышения производительности использования optimum и accelerate библиотек. Если модель или оборудование не поддерживает ее, мы будем запускать развертывание без такой оптимизации.
    • Указывает функцию run, которая выполняется для каждой мини-выборки, предоставляемой пакетной обработкой.
    • Функция run считывает весь пакет с помощью библиотеки datasets . Текст, который нужно резюмировать, находится в столбце text.
    • Метод run выполняет итерацию по каждой строке текста и выполняет прогноз. Так как это очень дорогая модель, выполнение прогноза по всем файлам приведет к исключению из памяти. Обратите внимание, что модель не выполняется с pipeline объектом из transformers. Это делается для учета длинных последовательностей текста и ограничения 1024 маркеров в базовой модели, используемой нами.
    • Он возвращает сводку предоставленного текста.

    код/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
    

    Совет

    Хотя файлы предоставляются в мини-пакетах развертывания, этот скрипт оценки обрабатывает одну строку за раз. Это распространенный шаблон при работе с дорогостоящими моделями (например, преобразователями), так как попытка загрузить весь пакет и отправить его в модель одновременно может привести к высокой нагрузке на пакетный исполнитель (исключения OOM).

  2. Нам нужно указать, в какой среде мы будем запускать развертывание. В нашем случае наша модель выполняется на Torch и требует библиотеки transformers, accelerate и optimum от HuggingFace. Машинное обучение Azure уже имеет среду с поддержкой Torch и GPU. Мы просто добавим пару зависимостей в 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. Мы можем использовать файл conda, упомянутый выше, как показано ниже.

    Определение среды включается в файл развертывания.

    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
    

    Внимание

    Для созданной среды torch200-transformers-gpu требуется устройство, совместимое с CUDA 12.1, для запуска Torch 2.0 в Ubuntu 22.04. Убедитесь, что вычислительный кластер GPU использует размер виртуальной машины, поддерживающий CUDA 12.1 или более поздней версии, например Standard_NCasT4_v3.

  4. Каждое развертывание выполняется в вычислительных кластерах. Они поддерживают как кластеры вычислений Машинное обучение Azure (AmlCompute), так и кластеры Kubernetes. В этом примере наша модель может воспользоваться ускорением GPU, поэтому мы используем кластер GPU.

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

    Примечание.

    Плата за вычислительные ресурсы на данный момент не взимается, так как кластер остается на нулевых узлах до вызова конечной точки пакетной службы и отправки задания оценки пакетной службы. Узнайте больше об управлении и оптимизации затрат для AmlCompute.

  5. Теперь настроим развертывание.

    Чтобы создать новое развертывание под созданной конечной точкой, создайте конфигурацию YAML, как показано ниже. Вы можете проверить схему YAML для полной пакетной конечной точки, чтобы получить дополнительные свойства.

    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
    

    Затем создайте развертывание с помощью следующей команды:

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

    Внимание

    Вы замечаете в этом развертывании высокое значение в timeout в параметре retry_settings. Причина заключается в характере модели, которую мы выполняем. Это дорогостоящая модель и вывод по одной строке может занять до 60 секунд. Параметр timeout определяет, сколько времени пакетное развертывание должно ожидать завершения обработки каждого мини-пакета скрипта оценки. Так как наша модель выполняет прогнозы по строкам, обработка длинного файла может занять некоторое время. Также обратите внимание, что количество файлов для каждого пакета установлено равным 1 (mini_batch_size=1). Это снова связано с характером работы, которую мы делаем. Обработка одного файла за пакет настолько дорога, что это оправдано. Вы заметили, что это шаблон в обработке NLP.

  6. Хотя вы можете вызвать определенное развертывание внутри конечной точки, обычно требуется вызвать саму конечную точку и разрешить конечной точке решить, какое развертывание следует использовать. Такое развертывание называется развертыванием по умолчанию. Это дает возможность изменять развертывание по умолчанию и, следовательно, изменять модель, обслуживающую развертывание, без изменения контракта с пользователем, вызывающим конечную точку. Чтобы обновить развертывание по умолчанию, используйте следующую инструкцию:

    DEPLOYMENT_NAME="text-summarization-hfbart"
    az ml batch-endpoint update --name $ENDPOINT_NAME --set defaults.deployment_name=$DEPLOYMENT_NAME
    
  7. Теперь наш конечный пункт пакетной обработки готов к использованию.

Тестирование развертывания

Для тестирования нашей конечной точки мы будем использовать пример набора данных BillSum: Корпус для автоматической сводки законодательства США. Этот пример включен в репозиторий в папку data. Обратите внимание, что формат данных — CSV, и содержимое, подлежащее обобщению, находится в столбце text, как ожидается, моделью.

  1. Давайте вызовем конечную точку:

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

    Примечание.

    jq Программа может не быть установлена во всех установках. Вы можете получить инструкции по этой ссылке.

    Совет

    Обратите внимание, что при указании локального пути в качестве входных данных данные передаются в учетную запись хранения по умолчанию в Машинное обучение Azure.

  2. Пакетное задание запускается сразу после возврата команды. Вы можете отслеживать состояние задания, пока оно не завершится:

    az ml job show -n $JOB_NAME --web
    
  3. После завершения развертывания можно скачать прогнозы:

    Чтобы скачать прогнозы, используйте следующую команду:

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

Рекомендации при развертывании моделей, обрабатывающих текст

Как упоминалось в некоторых заметках этого руководства, обработка текста может иметь некоторые особенности, требующие конкретной настройки для пакетных развертываний. При разработке пакетного развертывания следует учитывать следующее:

  • Некоторые модели NLP могут быть очень дорогими с точки зрения памяти и времени вычислений. Если это так, попробуйте уменьшить количество файлов, включенных в каждый мини-пакет. В предыдущем примере число было принято к минимуму, 1 файл на пакет. Даже если это не ваш случай, учитывайте, сколько файлов ваша модель может обрабатывать единовременно. Имейте в виду, что связь между размером входных данных и объемом памяти модели может не быть линейной для моделей глубокого обучения.
  • Если модель не может одновременно обрабатывать один файл (например, в этом примере), рассмотрите возможность чтения входных данных в строках или блоках. Реализуйте пакетную обработку на уровне строк, если необходимо достичь более высокой пропускной способности или аппаратного использования.
  • Установите значение timeout для развертывания в соответствии с тем, насколько дорога ваша модель и сколько данных вы планируете обработать. Помните, что timeout указывает время, в течение которого пакетное развертывание будет ожидать выполнения вашего скрипта оценки для заданной партии. Если пакет содержит много файлов или файлов с множеством строк, это влияет на правильное значение этого параметра.

Рекомендации для моделей MLflow, обрабатывающих текст

Те же рекомендации, упомянутые ранее, применяются к моделям MLflow. Однако, так как вам не требуется предоставлять скрипт оценки для развертывания модели MLflow, некоторые из упомянутых рекомендаций могут потребовать другого подхода.

  • Модели MLflow в пакетной конечной точке поддерживают чтение табличных данных в виде входных данных, которые могут содержать длинные последовательности текста. Сведения о поддерживаемых типах файлов см. в разделе " Типы файлов".
  • Пакетные развертывания вызывают функцию прогнозирования модели MLflow с содержимым всего файла, представленным в виде Pandas DataFrame. Если входные данные содержат много строк, то при запуске сложной модели (например, представленной в этом руководстве) есть вероятность столкнуться с исключением из-за нехватки памяти. Если это ваш случай, вы можете рассмотреть следующее: