mistral-finetune
— это легкая кодовая база, которая позволяет эффективно использовать память и выполнять точную настройку моделей Mistral. Он основан на LoRA, парадигме обучения, в которой большинство весов заморожены и обучаются только 1-2% дополнительных весов в виде возмущений матрицы низкого ранга.
Для максимальной эффективности рекомендуется использовать графический процессор A100 или H100. Кодовая база оптимизирована для обучающих установок с несколькими графическими процессорами и одним узлом, но для меньших моделей, таких как 7B, достаточно одного графического процессора.
Примечание
Цель этого репозитория — предоставить простую и управляемую точку входа для точной настройки моделей Mistral. По существу, он довольно самоуверен (особенно в отношении форматирования данных) и не претендует на исчерпывающий охват нескольких моделей архитектур или типов оборудования. Если вам нужны более общие подходы, вы можете ознакомиться с другими замечательными проектами, такими как torchtune.
13.08.2024 : Mistral Large v2 теперь совместим с mistral-finetune
!
Рекомендуется использовать более низкую скорость обучения по сравнению с другими моделями, например , lr=1e-6 должен работать хорошо в большинстве случаев.
Для тонкой настройки Mistral-Large v2 требуется значительно больше памяти из-за большего размера модели. На данный момент установите для seq_len
значение <= 8192.
Загрузите инструкцию 123B здесь и установите model_id_or_path
в каталог загруженной контрольной точки.
19.07.2024 : Mistral Nemo теперь совместим с mistral-finetune
!
Рекомендуется использовать те же гиперпараметры, что и для 7B v3.
Точная настройка Мистраль-Немо в настоящее время требует гораздо больше памяти из-за большего размера словаря, что увеличивает пиковые требования к памяти из-за потери CE (скоро мы добавим сюда улучшенную потерю CE). На данный момент установите для seq_len
значение <= 16384.
Запустите pip install --upgrade mistral-common
, чтобы получить версию, поддерживающую Tekkenizer ( >=1.3.1
).
Загрузите 12B Base или Instruct здесь и установите model_id_or_path
в загруженный каталог контрольной точки.
Чтобы начать тонкую настройку Mistral LoRA, выполните следующие действия:
Клонируйте этот репозиторий:
cd $HOME && git clone https://github.com/mistralai/mistral-finetune.git
Установите все необходимые зависимости:
cd mistral-finetune pip install -r requirements.txt
Мы рекомендуем доработать одну из официальных моделей Mistral, скачать которую можно здесь:
Модель | Связь | Контрольная сумма |
---|---|---|
7B База V3 | База 7Б | 0663b293810d7571dad25dae2f2a5806 |
7B Инструкция v3 | 7B Инструкция v3 | 80b71fcb6416085bcb4efad86dfb4d52 |
8x7B База V1 | База 8x7B | (ВЧ-ссылка) |
8x7B Инструкция V1 | 8x7B Инструктировать | 8e2d3930145dc43d3084396f49d38a3f |
8x22 Инструкция V3 | 8x22 Инструктировать | 471a02a6902706a2f1e44a693813855b |
8x22B База V3 | База 8x22B | a2fa75117174f87d1197e3a4eb50371a |
12B Инструктировать | 12Б Инструкт (Мистраль-Немо) | 296fbdf911cb88e6f0be74cd04827fe7 |
База 12Б | 12 База (Мистраль-Немо) | c5d079ac4b55fc1ae35f51f0a3c0eb83 |
Мистраль Большой 2 | 123B Инструкция (большая версия 2) | fc602155f9e39151fba81fcaab2fa7c4 |
Важное примечание : для 8x7B Base V1 и 8x7B Instruct V1 необходимо использовать наш токенизатор v3 и расширить размер словаря до 32768 перед точной настройкой. Подробные инструкции по этому процессу можно найти в разделе «Расширение модели».
Например, чтобы загрузить базовую модель 7B, вы можете выполнить следующую команду:
mkdir -p ~/${HOME}/mistral_modelscd ${HOME} && wget https://models.mistralcdn.com/mistral-7b-v0-3/mistral-7B-v0.3.tar tar -xf mistral-7B-v0.3.tar -C mistral_models
Обязательно измените сценарий обучения и добавьте путь к загруженной папке как model_id_or_path
.
Например, измените example/7B.yaml, включив в него абсолютный путь к $HOME/mistral_models/7B
:
model_id_or_path: "/Users/johndoe/mistral_models/7B"
Чтобы обеспечить эффективное обучение, mistral-finetune
предъявляет строгие требования к форматированию обучающих данных.
Все файлы данных должны храниться в файлах формата jsonl.
Вы можете создать два типа файлов данных:
Данные предварительной подготовки соответствуют обычным текстовым данным, хранящимся в ключе "text"
. Например:
{"text": "Текст, содержащийся в документе № 1"} {"text": "Текст, содержащийся в документе №2"}
В настоящее время поддерживаются два различных типа инструкций и следующих данных:
Instruct : разговорные данные, хранящиеся в клавише "messages"
в виде списка. Каждый элемент списка представляет собой словарь, содержащий ключи "content"
и "role"
. "role"
— это строка, имеющая значения «пользователь», «помощник» или «система». Убыток будет рассчитан только в том случае, если «роль» == «помощник». Например:
{ "сообщения": [ { "role": "user", "content": "Взаимодействие с пользователем №1, содержащееся в документе №1" }, { "role": "assistant", "content": "Взаимодействие с ботом № 1, содержащееся в документе № 1" }, { "role": "user", "content": "Взаимодействие с пользователем № 2, содержащееся в документе № 1" }, { "role": "assistant", "content": "Взаимодействие с ботом № 2, содержащееся в документе № 1" } ] } { "сообщения": [ { "role": "user", "content": "Взаимодействие с пользователем №1, содержащееся в документе №2" }, { "role": "assistant", "content": "Взаимодействие с ботом №1 содержится в документе №2" }, { "role": "user", "content": "Взаимодействие с пользователем №2, содержащееся в документе №2" }, { "role": "assistant", "content": "Взаимодействие с ботом №2 содержится в документе №2", "weight": 0, # не тренироваться на №2 }, { "role": "user", "content": "Взаимодействие с пользователем № 3, содержащееся в документе № 2" }, { "role": "assistant", "content": "Взаимодействие с ботом № 3 содержится в документе № 2" } ] }
Вызов функции : разговорные данные, хранящиеся в клавише "messages"
в виде списка. Каждый элемент списка представляет собой словарь, содержащий ключи "role"
и "content"
или "tool_calls"
. "role"
— это строка, имеющая значения «пользователь», «помощник», «система» или «инструмент». Убыток будет рассчитан только в том случае, если «роль» == «помощник».
Примечание . При вызове функции "id"
"tool_calls"
и "tool_call_id"
представляют собой случайно генерируемые строки длиной ровно 9 символов. Мы рекомендуем генерировать это автоматически в сценарии подготовки данных, как это сделано здесь.
Например:
{ "сообщения": [ { "role": "system", "content": "Вы полезный помощник, у которого есть доступ к следующим функциям, чтобы помочь пользователю, вы можете использовать эти функции при необходимости" }, { "role": "user", "content": "Можете ли вы помочь мне создать анаграмму слова "слушать"?" }, { "роль": "помощник", "tool_calls": [ { "id": "TX92Jm8Zi", "type": "function", "function": { "name": "generate_anagram", "arguments": "{"word": "listen"}" } } ] }, { "role": "tool", "content": "{"anagram": "silent"}", "tool_call_id": "TX92Jm8Zi" }, { "role": "assistant", "content": "Анаграмма слова «слушать» — «молчать».» }, { "role": "user", "content": "Это потрясающе! Можете ли вы создать анаграмму для слова "раса"?" }, { "роль": "помощник", "tool_calls": [ { "id": "3XhQnxLsT", "type": "function", "function": { "name": "generate_anagram", "arguments": "{"word": "race"}" } } ] } ], "инструменты": [ { "type": "function", "function": { "name": "generate_anagram", "description": "Сгенерировать анаграмму заданного слова", "parameters": { "type": "object", " Properties": { "word": { "type": "string", "description": "Слово, анаграмму которого нужно сгенерировать" } }, "обязательно": [ "слово" ] } } } ] }
Прежде чем начать обучающий прогон, вам следует убедиться, что ваш набор данных правильно отформатирован, и получить оценку времени обучения. Вы можете сделать это с помощью сценария ./utils/validate_data.
Обратите внимание, что этот шаг имеет решающее значение для обеспечения правильного форматирования данных.
Давайте рассмотрим простой пример обучения модели по следующей инструкции:
Загрузите кусок Ultachat_200k.
Создайте папку данных и перейдите к ней.
cd $HOME && mkdir -p data && cd $HOME/data
Загрузите данные в фрейм данных Pandas.
Примечание . Убедитесь, что установлены pandas и pyarrow ( pip install pandas pyarrow
).
импортируйте панд как pddf = pd.read_parquet('https://huggingface.co/datasets/HuggingFaceH4/ultrachat_200k/resolve/main/data/test_gen-00000-of-00001-3d4cd8309148a71f.parquet')
Разделить на поезд и оценку
df_train=df.sample(frac=0,95,random_state=200)df_eval=df.drop(df_train.index)
Сохраняем данные в jsonl
df_train.to_json("ultrachat_chunk_train.jsonl", orient="records",lines=True)df_eval.to_json("ultrachat_chunk_eval.jsonl", orient="records",lines=True)
Измените свой тренировочный yaml, включив в него набор данных ультрачата, и проверьте yaml.
Измените файл example/7B.yaml, включив в него абсолютный путь к $HOME/data/ultrachat_chunk_train.jsonl
а также вес смешивания набора данных для обучения и $HOME/data/ultrachat_chunk_eval.jsonl
для оценки, например
data: instruct_data: "/Users/johndoe/data/ultrachat_chunk_train.jsonl" eval_instruct_data: "/Users/johndoe/data/ultrachat_chunk_eval.jsonl"
Теперь вы можете проверить свой тренировочный yaml, чтобы убедиться, что данные правильно отформатированы, и получить оценку времени вашего обучения.
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml
По завершении вы должны увидеть отчет об ошибках со многими из следующих ошибок:
The data in line 1412 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1413 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1414 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1415 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user
Кажется, что многие разговоры заканчиваются ролью «пользователя», которая не нужна, поскольку мы обучаемся только на сообщениях «помощника» и, таким образом, обрабатываем данные без необходимости.
Вы можете использовать ./utils/reformat_data.py для исправления данных:
cd $HOME/mistral-finetune python -m utils.reformat_data $HOME/data/ultrachat_chunk_train.jsonl python -m utils.reformat_data $HOME/data/ultrachat_chunk_eval.jsonl
Вы должны увидеть, что несколько образцов будут пропущены.
Возможно изменение количества этапов обучения.
После исправления набора данных запустите скрипт еще раз.
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml
Вы должны получить сводку введенных данных и параметров обучения:
Train States -------------------- { "expected": { "eta": "00:52:44", "data_tokens": 25169147, "train_tokens": 131072000, "epochs": "5.21", "max_steps": 500, "data_tokens_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "25169147.0" }, "train_tokens_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "131072000.0" }, "epochs_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "5.2" } }, }
Если для max_steps
установлено значение 500, это приведет к повторению набора данных примерно 5 раз, что разумно, но может быть слишком много. Ниже показана рекомендуемая настройка, которая займет всего 30 минут в кластере 8xH100.
Далее давайте рассмотрим более сложный вариант использования для точной настройки модели вызова функций. Вызов функции требует, чтобы данные были в формате, описанном выше. Давайте рассмотрим пример.
Загрузите версию набора данных вызова функции Glaive в формате чата.
Создайте папку данных и перейдите к ней.
cd $HOME && mkdir -p data && cd $HOME/data
Загрузите данные в фрейм данных Pandas.
Примечание . Убедитесь, что установлены pandas и pyarrow ( pip install pandas pyarrow
).
импортируйте панд как pddf = pd.read_parquet('https://huggingface.co/datasets/Locutusque/function-calling-chatml/resolve/main/data/train-00000-of-00001-f0b56c6983b4a78f.parquet')
Разделить на поезд и оценку
df_train=df.sample(frac=0,95,random_state=200)df_eval=df.drop(df_train.index)
Сохраняем данные в jsonl
df_train.to_json("glaive_train.jsonl", orient="records",lines=True)df_eval.to_json("glaive_eval.jsonl", orient="records",lines=True)
Переформатировать набор данных
Как видно, набор данных не соответствует требуемому формату вызова функций, поэтому его необходимо переформатировать. Помимо прочего, "from"
следует переименовать в "user"
и удалить лишние символы "n"
. Для этого набора данных вы можете использовать ./utils/reformat_data_glaive.py
:
cd $HOME/mistral-finetune python -m utils.reformat_data_glaive $HOME/data/glaive_train.jsonl python -m utils.reformat_data_glaive $HOME/data/glaive_eval.jsonl
Выполнение этой команды позволит убедиться, что большинство образцов имеют правильный формат.
Примечание . Невозможно написать сценарии переформатирования, работающие со всеми типами наборов данных. Если у вас есть наборы данных, которые еще не соответствуют требуемому формату, указанному выше, вам, скорее всего, придется создать сценарий переформатирования самостоятельно (mistral-chat илиchat-gpt — ваш лучший друг здесь!).
Проверить набор данных
Теперь вы можете проверить набор данных, установив для data.instruct_data
и data.eval_instruct_data
$HOME/data/glaive_train.jsonl
и $HOME/data/glaive_eval.jsonl
в example/7B.yaml
соответственно.
В переформатированных наборах данных все еще есть некоторые ошибки, которые можно удалить с помощью --create_corrected
. Для этого обязательно добавьте --create_corrected
следующим образом:
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml --create_corrected
Выполнение этой команды покажет пару ошибок и сохранит два новых набора данных $HOME/data/glaive_train.jsonl.corrected
и $HOME/data/glaive_eval.jsonl.corrected
. Обязательно используйте эти два набора данных в example/7B.yaml
и запустите команду еще раз. Теперь набор данных должен быть правильно отформатирован!
Пройдя раздел проверки набора данных, мы можем начать обучение. Для более быстрого обучения мы рекомендуем установить max_steps только на 300. Обязательно определите run_dir
для папки эксперимента и, при необходимости, установите wandb_project
для проекта Weights & Biases для ведения журнала, например :
max_steps: 300 run_dir: "/Users/johndoe/ultra_chat_test" wandb.project: ultra_chat
При желании вы также можете установить wandb
Сохраните конфигурацию тренировки и приступайте к тренировке! Обязательно установите --nproc-per-node
на количество доступных графических процессоров.
cd $HOME/mistral-finetune torchrun --nproc-per-node 8 --master_port $RANDOM -m train example/7B.yaml
Обучение ультрачату должно занять около 30 минут на узле 8xH100, а полученные веса должны дать оценку MT Bench около 6,3.
Обучение glaive должно занять около 1 часа на узле 8xH100, а полученные веса должны хорошо работать для вызова функций.
Пример mistral-finetune/examples/7B
определяет разумные параметры скорости обучения, снижения веса и т. д., но вам рекомендуется настроить эти параметры для вашего варианта использования.
Как правило, конфигурация обучения должна содержать следующие параметры:
model_id_or_path
определяет модель, с которой начинается обучение. Это может быть путь к предварительно обученной модели или локальному каталогу модели.
run_dir
определяет каталог, в котором хранятся контрольные точки обучения и показатели.
seq_len
определяет длину последовательности для обучения. Это максимальная длина входных последовательностей, которые будет обрабатывать модель. Образцы упаковываются так, чтобы достигать длины seq_len
для максимальной эффективности обучения.
batch_size
определяет количество обучающих примеров, используемых на один графический процессор. Примечание . Общий эффективный размер пакета (в токенах) для всех графических процессоров равен num_gpus
x batch_size
x seq_len
.
max_steps
определяет максимальное количество шагов обучения. Это общее количество итераций, которые будет выполнять процесс обучения. Его можно настроить в зависимости от конкретных потребностей вашего сценария обучения. Общее количество токенов, наблюдаемых во время обучения, равно max_steps
x num_gpus
x batch_size
x seq_len
.
optim.lr
определяет скорость обучения. Это начальная скорость обучения оптимизатора.
optim.weight_decay
определяет снижение веса. Снижение веса — это метод регуляризации, используемый для предотвращения переобучения путем штрафования больших весов. Мы рекомендуем оставить значение 0,1.
optim.pct_start
определяет процент общего количества шагов обучения, используемый для фазы разминки скорости обучения, прежде чем она начнет снижаться. Он соответствует pct_start OneCycleLR PyTorch.
lora.rank
определяет размер адаптеров LoRA (адаптация низкого ранга). Мы рекомендуем 64 или меньше, что регулирует ранг разложения низкого ранга, используемого в LoRA.
seed
определяет случайное начальное число для инициализации и перетасовки/выборки данных. Установка затравки обеспечивает воспроизводимость результатов.
log_freq
определяет частоту регистрации. Это определяет, как часто (в шагах) регистрировать показатели обучения.
data.instruct_data
— это путь к данным инструкции, используемым для обучения. Это поле должно быть заполнено одним или несколькими источниками данных в формате, как описано выше. Каждый источник данных должен представлять собой либо путь к файлу jsonl, либо путь к каталогу, содержащему файлы jsonl, с последующим взвешиванием, чтобы определить важность этого набора данных:
. Например: data.instruct_data: "/path/to/data1.jsonl:5.,/path/to/data2.jsonl:1.,/path/to/dir_of_jsonls:1."
data.data
— это необязательный путь к дополнительным данным предварительного обучения в формате, описанном выше. Обратите внимание, что это поле можно оставить пустым.
data.eval_instruct_data
— это необязательный путь к данным инструкции оценки для запуска перекрестной проверки на каждом этапе eval_freq
. Метрики перекрестной проверки отображаются как loss
и perplexity
.
eval_freq
определяет, как часто (в шагах) оценивать модель. Это определяет интервал, с которым модель оценивается в наборе проверки.
no_eval
— это флаг, позволяющий включить или отключить промежуточную оценку. Установка значения False включает периодическую оценку во время обучения.
ckpt_freq
определяет, как часто (в шагах) сохранять контрольные точки. Это определяет интервал, с которым сохраняется состояние модели.
save_adapters
определяет, следует ли сохранять только обученные контрольные точки LoRA или обученный LoRA следует напрямую объединить с базовой моделью и сохранить. Примечание . При настройке save_adapters=False
убедитесь, что у вас достаточно памяти ЦП и ГП для сохранения полной модели в одном процессе (обычно это возможно только для модели 7B).
wandb.key
используется для передачи вашего ключа API Weights & Biases (wandb) для ведения журнала. Это позволяет вам регистрировать показатели обучения на панели управления wandb.
wandb.project
определяет имя проекта wandb. Здесь в интерфейсе wandb будет регистрироваться тренировочный прогон.
Как только ваша модель будет обучена, вам следует опробовать ее в выводе. Мы рекомендуем использовать мистральный вывод.
Убедитесь, что mistral_inference
правильно установлен:
pip install mistral_inference
Предполагая, что ваш lora.safetensors
сохранен в $HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensors
, вы можете общаться с моделью, используя mistral_inference
, например :
mistral-chat /mnt/slow/runs/patrick/mistral-finetune/7B/ --max_tokens 256 --temperature 1.0 --instruct --lora_path $HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensors
Мы добавили явную поддержку весов и смещений, чтобы помочь вам отслеживать и визуализировать свои тренировочные пробежки. Эта интеграция позволяет легко регистрировать различные показатели и отслеживать эксперименты.
Чтобы использовать веса и смещения с mistral-finetune
, выполните следующие действия:
Установите веса и смещения:
Убедитесь, что у вас установлена библиотека wandb
. Вы можете установить его с помощью pip:
pip установить wandb
Как только обучение начнется, вы сможете отслеживать прогресс в режиме реального времени, посетив панель управления проектом wandb. Все показатели, включая потери при обучении, потери в оценке, скорость обучения и т. д., будут регистрироваться и визуализироваться.
Для получения более подробной информации о том, как использовать wandb, посетите документацию Weights and Biases.
Важно : обратите внимание, что можно точно настроить только модели мистраля, совместимые с токенизатором v3, что означает, что модели имеют размер словаря 32768, а не 32000. Однако можно легко расширить более старую версию словаря размером 32000, чтобы иметь размер словаря. из 32768, используя:
python -m utils.extend_model_vocab --original_model_ckpt /folder/to/old/model --extended_model_ckpt /folder/to/extended/model
Как только расширение заработает, его можно будет настроить, используя вновь созданную контрольную точку модели в /folder/to/extended/model
.
Какова наилучшая практика тонкой настройки МО?
Мы видим более высокую степень различия в производительности при точной настройке моделей MoE. Нет ничего необычного в том, что точная настройка моделей MoE с разными начальными значениями может привести к большим различиям в производительности. У плотных моделей мы не наблюдали такой высокой дисперсии. Поэтому мы предлагаем запустить несколько экземпляров одного и того же процесса тонкой настройки моделей Министерства образования и выбрать тот, который работает лучше всего.
Как определить количество токенов, используемых в процессе обучения модели?
Чтобы это узнать, вы можете использовать следующий скрипт: https://github.com/mistralai/mistral-finetune/blob/main/utils/validate_data.py. Этот сценарий принимает в качестве входных данных обучающий файл .yaml и возвращает количество токенов, на которых обучается модель.
Что делать, если я столкнулся с ошибкой нехватки памяти CUDA?
Одним из возможных решений является уменьшение размера пакета на один графический процессор. Размер пакета равен seq_len
x batch_size
. Попробуйте установить batch_size
равным 1 и уменьшить seq_len
. Вы можете определить batch_size
и seq_len
в файле .yaml.