Точная настройка MPT-7B на Amazon SageMaker

Узнайте, как подготовить набор данных и создать обучающее задание для точной настройки MPT-7B в Amazon SageMaker.

Каждую неделю объявляются новые большие языковые модели (LLM), каждая из которых пытается превзойти свою предшественницу и занять первое место в списках лидеров. Одна из последних моделей — MPT-7B, выпущенная MosaicML. В отличие от других моделей в своем роде, эта модель с 7 миллиардами параметров имеет открытый исходный код и лицензирована для коммерческого использования (лицензия Apache 2.0) 🚀.

Базовые модели, такие как MPT-7B, предварительно обучены на наборах данных с триллионами токенов (100 токенов ~ 75 слов), просканированных из Интернета, и при правильном запросе они могут давать впечатляющие результаты. Однако, чтобы по-настоящему раскрыть ценность больших языковых моделей в реальных приложениях, интеллектуальной разработки подсказок может быть недостаточно, чтобы заставить их работать для вашего варианта использования, и поэтому точная настройка базовой модели на наборе данных для конкретной предметной области необходимый.

LLM имеют миллиарды параметров, и, следовательно, тонкая настройка таких больших моделей является сложной задачей. Хорошей новостью является то, что точная настройка намного дешевле и быстрее по сравнению с предварительной подготовкой базовой модели, учитывая, что 1) наборы данных для предметной области невелики и 2) для точной настройки требуется всего несколько проходов по обучающим данным.

Вот что мы узнаем из этой статьи:

  • Как создать и структурировать набор данных для тонкой настройки большой языковой модели.
  • Что такое и как настроить распределенное задание обучения с полностью шардированными данными параллельно.
  • Как определить оценщик 😊 HuggingFace.
  • Как запустить обучающее задание в Amazon SageMaker для тонкой настройки MPT-7B.

1. Установите зависимости и задайте пути S3

Начнем с установки SageMaker Python SDK и нескольких других пакетов. Этот SDK позволяет обучать и развертывать модели машинного обучения на AWS с помощью нескольких строк кода Python. Код ниже доступен в sagemaker_finetuning.ipynbnotebook на Github. Запустите записную книжку в SageMaker Studio, экземпляре записной книжки SageMaker или на своем ноутбуке после аутентификации в учетной записи AWS.

!pip install "sagemaker==2.162.0" s3path boto3 --quiet

from sagemaker.huggingface import HuggingFace
from sagemaker.inputs import TrainingInput
from sagemaker import s3_utils
import sagemaker
import boto3
import json

Следующим шагом является определение путей, по которым данные будут сохранены в S3, и создание сеанса SageMaker.

# Define S3 paths
bucket             = "<YOUR-S3-BUCKET>"
training_data_path = f"s3://{bucket}/toy_data/train/data.jsonl"
test_data_path     = f"s3://{bucket}/toy_data/test/data.jsonl"
output_path        = f"s3://{bucket}/outputs"
code_location      = f"s3://{bucket}/code"

# Create SageMaker session
sagemaker_session  = sagemaker.Session()
region             = sagemaker_session.boto_region_name
role               = sagemaker.get_execution_role()

2. Создайте набор данных для тонкой настройки

Мы создадим фиктивный набор данных, чтобы продемонстрировать, как настроить MPT-7B. Поскольку обучение моделей такого размера на полном наборе данных занимает много времени и является дорогостоящим, рекомендуется сначала протестировать и отладить задание обучения на небольшом наборе данных, а затем масштабировать обучение на полном наборе данных.

  • Форматировать набор данных как список словарей. Набор данных должен быть отформатирован как список словарей, где каждый пример имеет структуру ключ-значение, например,,
{
    "prompt": "What is a Pastel de Nata?",
    "response": "A Pastel de Nata is a Portuguese egg custard tart pastry, optionally dusted with cinnamon."
}

prompt — это входные данные для модели (например,, вопрос). response — это выходные данные, которые модель обучена прогнозировать (например, ответ на вопрос в prompt). Необработанное приглашение часто предварительно обрабатывается, чтобы соответствовать шаблону приглашения, который помогает модели генерировать более качественные выходные данные. Обратите внимание, что модель обучена каузальному языковому моделированию, поэтому вы можете думать о ней как о дополнителе документов. Рекомендуется спроектировать шаблон подсказки таким образом, чтобы модель думала, что она заполняет документ. Андрей Карпатий хорошо объясняет этот механизм в своем докладе State of GPT.

prompt_template = """Write a response that appropriately answers the question below.
### Question:
{question}

### Response:
"""

dataset = [
    {"prompt": "What is a Pastel de Nata?",
     "response": "A Pastel de Nata is a Portuguese egg custard tart pastry, optionally dusted with cinnamon."},
    {"prompt": "Which museums are famous in Amsterdam?",
     "response": "Amsterdam is home to various world-famous museums, and no trip to the city is complete without stopping by the Rijksmuseum, Van Gogh Museum, or Stedelijk Museum."},
    {"prompt": "Where is the European Parliament?",
     "response": "Strasbourg is the official seat of the European Parliament."},
    {"prompt": "How is the weather in The Netherlands?",
     "response": "The Netherlands is a country that boasts a typical maritime climate with mild summers and cold winters."},
    {"prompt": "What are Poffertjes?",
     "response": "Poffertjes are a traditional Dutch batter treat. Resembling small, fluffy pancakes, they are made with yeast and buckwheat flour."},
]

# Format prompt based on template
for example in dataset:
    example["prompt"] = prompt_template.format(question=example["prompt"])

training_data, test_data = dataset[0:4], dataset[4:]

print(f"Size of training data: {len(training_data)}\nSize of test data: {len(test_data)}")
  • Загрузить обучающие и тестовые данные в S3. Когда обучающие и тестовые наборы готовы и отформатированы в виде списка словарей, мы загружаем их в S3 в виде строк JSON, используя приведенную ниже служебную функцию:
def write_jsonlines_to_s3(data, s3_path):
    """Writes list of dictionaries as a JSON lines file to S3"""

    json_string = ""
    for d in data:
        json_string += json.dumps(d) + "\n"

    s3_client   = boto3.client("s3")
    
    bucket, key = s3_utils.parse_s3_url(s3_path)
    s3_client.put_object(
         Body   = json_string,
         Bucket = bucket,
         Key    = key,
    )

write_jsonlines_to_s3(training_data, training_data_path)
write_jsonlines_to_s3(test_data, test_data_path)

3. Тренировочное задание SageMaker

Имея наборы данных, доступные в S3, теперь мы создадим обучающее задание в Amazon SageMaker. Для этого нам нужно создать сценарий точки входа, изменить файл конфигурации, указав параметры обучения, и определить оценщик HuggingFace. Мы будем (повторно) использовать сценарий обучения из библиотеки LLM Foundry и средства запуска CLI библиотеки Composer, который настраивает распределенную среду обучения. Оба этих пакета поддерживаются компанией MosaicML, создавшей MPT-7B. Рабочая папка должна быть структурирована следующим образом:

└── fine-tune-mpt-7b-sagemaker/
    ├── training_script_launcher.sh
    ├── fine_tuning_config.yaml
    ├── sagemaker_finetuning.ipynb

Теперь мы углубимся в каждый из этих файлов.

  • Создайте файл конфигурации finetuning_config.yaml — шаблон, представленный в репозитории LLM Foundry, является хорошей отправной точкой, особенно файл mpt-7b-dolly-sft.yaml. Однако в зависимости от размера набора данных и обучающего экземпляра вам может потребоваться настроить некоторые из этих конфигураций, например размер пакета. Я изменил файл для точной настройки модели в SageMaker (отметьте finetuning_config.yaml). Параметры, на которые стоит обратить внимание, следующие:
max_seq_len: 512
global_seed: 17

...
# Dataloaders
train_loader:
  name: finetuning
  dataset:
    hf_name: json
    hf_kwargs:
        data_dir: /opt/ml/input/data/train/
...

eval_loader:
  name: finetuning
  dataset:
    hf_name: json
    hf_kwargs:
        data_dir: /opt/ml/input/data/test/
 
...
max_duration: 3ep
eval_interval: 1ep
...
global_train_batch_size: 128

...
# FSDP
fsdp_config:
  sharding_strategy: FULL_SHARD
  mixed_precision: PURE
  activation_checkpointing: true
  activation_checkpointing_reentrant: false
  activation_cpu_offload: false
  limit_all_gathers: true
  verbose: false

# Checkpoint to local filesystem or remote object store
save_folder: /tmp/checkpoints
dist_timeout: 2000

Themax_seq_length указывает максимальное количество токенов ввода (помните, что 100 токенов ~ 75 слов). Данные обучения и тестирования будут загружены с помощью библиотеки 😊 Наборы данных из каталога /opt/ml/input/data/{train, test} внутри контейнера, связанного с заданием обучения. Ознакомьтесь с документацией SageMaker Training Storage Folders, чтобы понять, как устроены каталоги контейнеров. max_duration указывает количество эпох для тонкой настройки. Обычно хорошим выбором является две-три эпохи. eval_interval указывает, как часто модель будет оцениваться на тестовом наборе.

Стратегия распределенного обучения — полностью разделенная параллельная обработка данных (FSDP), которая обеспечивает эффективное обучение больших моделей, таких как MPT-7B. В отличие от традиционной стратегии параллельных данных, при которой копия модели хранится в каждом графическом процессоре, FSDP сегментирует параметры модели, состояния оптимизатора и градиенты для параллельных рабочих процессов данных. Если вы хотите узнать больше о FSDP, ознакомьтесь с этим информативным вступительным постом PyTorch. FSDP интегрирован в Composer, распределенную учебную библиотеку, используемую LLM Foundry.

save_folder определяет, где сохраняется контрольная точка модели (файл .pt). Устанавливаем во временную папку /tmp/checkpoints.

  • Создайте сценарий точки входа launcher.sh — в качестве точки входа используется сценарий bash. Сценарий bash клонирует репозиторий LLM Foundry, устанавливает требования и, что более важно, запускает обучающий сценарий с помощью распределенного средства запуска библиотеки Composer. Обратите внимание, что обычно обучающие задания в SageMaker запускают обучающий сценарий с помощью такой команды, как python train.py. Однако в качестве точки входа можно передать сценарий bash, что обеспечивает большую гибкость в нашем сценарии. Наконец, мы конвертируем контрольную точку модели, сохраненную в /tmp/checkpoints, в формат модели HuggingFace и сохраняем окончательные артефакты в /opt/ml/model/. SageMaker сожмет все файлы в этом каталоге, создаст архив model.tar.gz и загрузит его на S3. Архив полезен для вывода.
# Clone llm-foundry package from MosaicML
# This is where the training script is hosted
git clone https://github.com/mosaicml/llm-foundry.git
cd llm-foundry

# Install required packages
pip install -e ".[gpu]"
pip install git+https://github.com/mosaicml/composer.git@dev

# Run training script with fine-tuning configuration
composer scripts/train/train.py /opt/ml/code/finetuning_config.yaml

# Convert Composer checkpoint to HuggingFace model format
python scripts/inference/convert_composer_to_hf.py \
    --composer_path /tmp/checkpoints/latest-rank0.pt \
    --hf_output_path /opt/ml/model/hf_fine_tuned_model \
    --output_precision bf16

# Print content of the model artifact directory
ls /opt/ml/model/
  • Определить 😊 Оценщик HuggingFace — Оценщик задает контейнер Docker, используемый для запуска задания обучения. Мы будем использовать образ с PyTorch 2.0.0 и Python 3.10. Сценарий bash и файл конфигурации автоматически загружаются в S3 и становятся доступными внутри контейнера (обрабатывается SageMaker Python SDK). Мы установили учебный экземпляр g5.48xlarge с 8 графическими процессорами NVIDIA A10G. p4d.24xlarge тоже хороший выбор. Несмотря на то, что он дороже, он оснащен 8-ю графическими процессорами NVIDIA A100. Мы также указываем метрики для отслеживания на тренировочном и тестовом наборах (перекрестная энтропия и растерянность). Значения этих метрик фиксируются с помощью выражений Regex и отправляются в Amazon CloudWatch.
# Define container image for the training job
training_image_uri = f"763104351884.dkr.ecr.{region}.amazonaws.com/huggingface-pytorch-training:2.0.0-transformers4.28.1-gpu-py310-cu118-ubuntu20.04-v1.1"

# Define metrics to send to CloudWatch
metrics = [
    # On training set
    {"Name": "train:LanguageCrossEntropy",
     "Regex": "Train metrics\/train\/LanguageCrossEntropy: ([+-]?((\d+\.?\d*)|(\.\d+)))"},
    {"Name": "train:LanguagePerplexity",
     "Regex": "Train metrics\/train\/LanguagePerplexity: ([+-]?((\d+\.?\d*)|(\.\d+)))"},
    # On test set
    {"Name": "test:LanguageCrossEntropy",
     "Regex": "Eval metrics\/eval\/LanguageCrossEntropy: ([+-]?((\d+\.?\d*)|(\.\d+)))"},
    {"Name": "test:LanguagePerplexity",
     "Regex": "Eval metrics\/eval\/LanguagePerplexity: ([+-]?((\d+\.?\d*)|(\.\d+)))"},
]

estimator_args = {
    "image_uri": training_image_uri,     # Training container image
    "entry_point": "launcher.sh",        # Launcher bash script
    "source_dir": ".",                   # Directory with launcher script and configuration file
    "instance_type": "ml.g5.48xlarge",   # Instance type
    "instance_count": 1,                 # Number of training instances
    "base_job_name": "fine-tune-mpt-7b", # Prefix of the training job name
    "role": role,                        # IAM role
    "volume_size": 300,                  # Size of the EBS volume attached to the instance (GB)
    "py_version": "py310",               # Python version
    "metric_definitions": metrics,       # Metrics to track
    "output_path": output_path,          # S3 location where the model artifact will be uploaded
    "code_location": code_location,      # S3 location where the source code will be saved
    "disable_profiler": True,            # Do not create profiler instance
    "keep_alive_period_in_seconds": 240, # Enable Warm Pools while experimenting
}

huggingface_estimator = HuggingFace(**estimator_args)

⚠️ Обязательно запросите соответствующие квоты для SageMaker Training, а также квоту Теплые бассейны, если вы используете эту классную функцию. Если вы планируете выполнять много заданий в SageMaker, взгляните на Планы сохранения SageMaker.

  • Запуск задания обучения 🚀. Все готово для запуска задания обучения на Amazon SageMaker:
huggingface_estimator.fit({
    "train": TrainingInput(
        s3_data=training_data_path,
        content_type="application/jsonlines"),
    "test": TrainingInput(
        s3_data=test_data_path,
        content_type="application/jsonlines"),
}, wait=True)

Время обучения будет зависеть от размера вашего набора данных. С нашим фиктивным набором данных обучение занимает примерно 20 минут. Как только модель будет обучена и преобразована в формат 😊 HuggingFace, SageMaker загрузит архив модели (model.tar.gz) на S3 output_path. Я обнаружил, что на практике этап загрузки занимает довольно много времени (> 1 часа), что может быть связано с размером сжимаемых артефактов модели (~ 25 ГБ).

4. Резюме

В этой статье я показал, как вы можете подготовить набор данных и создать обучающее задание в SageMaker, чтобы точно настроить MPT-7B для вашего варианта использования. Реализация использует обучающий скрипт от LLM Foundry и использует распределенную обучающую программу библиотеки Composer. После того, как вы настроили свою модель и хотите ее развернуть, я рекомендую ознакомиться с сообщениями в блоге Филиппа Шмида; существует множество примеров развертывания LLM в SageMaker. Получайте удовольствие от отлаженной модели MPT-7B! 🎉

Весь код, использованный в этой статье, доступен на Github:



— Жоао Перейра

Спасибо, что прочитали. Надеемся, что эта статья поможет вам начать работу с тонкой настройкой больших языковых моделей, таких как MPT-7B, в Amazon SageMaker. Если вы хотите читать мои будущие статьи, пожалуйста, подпишитесь на меня. Обратная связь высоко ценится! Оставьте комментарий ниже, если у вас есть какие-либо вопросы, или свяжитесь со мной напрямую по электронной почте или в LinkedIn.