Создайте клон себя с помощью точно настроенного LLM

Создайте клон себя с помощью точно настроенного LLM

Цель этой статьи — проиллюстрировать, как эффективно и с минимальными затратами настроить высокопроизводительный LLM на пользовательском наборе данных. Мы рассмотрим использование модели Falcon-7B с адаптерами LoRA с использованием Lit-GPT.

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

Усилия сообщества ИИ привели к разработке многих высококачественных LLM с открытым исходным кодом, включая, помимо прочего, Open LLaMA, Falcon, StableLM и Pythia. Вы можете точно настроить эти модели в пользовательском наборе данных инструкций, чтобы адаптировать их к вашей конкретной задаче, например, обучить чат-бота отвечать на финансовые вопросы. Кроме того, это также может обеспечить преимущество конфиденциальности данных, когда данные не могут быть загружены или переданы через облачные API.

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

Сбор и подготовка данных

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

  • Это представляет собой дополнительную проблему, поскольку модели в основном обучаются на английских текстах.
  • Учитывая, что русский — мой родной язык, у меня есть обширная база данных, состоящая из моих личных переписок.

Сбор данных

Я выбрал Telegram, потому что он предоставляет удобный API для сбора данных. Кроме того, он служит основной платформой для большей части моего общения с друзьями. Этот выбор обеспечивает ценный набор данных, который позволяет модели глубже понять мой уникальный стиль общения и позволяет более эффективно имитировать меня.

Следуя документации, я написал небольшой скрипт, который скачивает всю переписку из приватных чатов и сохраняет их в файл:

1. Запустите клиент Telegram:

from telethon.sync import TelegramClient client = TelegramClient(PHONE_NUMBER, TELEGRAM_APP_ID, TELEGRAM_APP_HASH) client.start()

2. Получите список диалогов, отфильтровав группы и каналы:

def get_dialogs(limit: int | None = 100) -> list[Dialog]: """Get all dialogs from the Telegram.""" dialogs: list[Dialog] = client.get_dialogs(limit=limit) dialogs = [dialog for dialog in dialogs if dialog.is_user] # remove groups or channels logger.info(f"Found {len(dialogs)} dialogs") return dialogs

3. Скачайте историю переписки:

def parse_messages(dialog: Dialog, limit: int = 1000) -> list[dict]: """Get all messages from the dialog.""" all_messages_list = [] offset_id = 0 while True: messages: list[Message] = client( GetHistoryRequest( peer=dialog, offset_id=offset_id, offset_date=None, add_offset=0, limit=limit, max_id=0, min_id=0, hash=0, ) ).messages if not messages: break all_messages_list.extend( { "date": message.date.isoformat(), "message": message.message, "out": message.out, } for message in messages # Filter audio or video content if message.message and not message.is_bot ) offset_id = offset_id = messages[-1].id return all_messages_list

Вы можете найти полный сценарий здесь.

Создайте клон себя с помощью точно настроенного LLM

Стоит отметить, что я намеренно исключил аудио- и видеосообщения из набора данных и сосредоточился исключительно на текстовом контенте. В результате часть информации в диалоге могла быть потеряна. Извлечение текста из таких данных — обширная тема, которой лучше посвятить отдельную статью.

Подготовка данных

На этом этапе вы должны тщательно обработать данные в инструкциях по тонкой настройке LLM.

Тонкая настройка обычно включает обучение предварительно обученной модели следованию инструкциям или выполнению другой конкретной целевой задачи (например, классификации настроений). ChatGPT (который начинался как доработанная версия базовой модели GPT-3) — типичный пример модели, которая была доработана для следования инструкциям. Наборы данных инструкций обычно имеют три ключа: инструкция , ввод (необязательный контекст для данной инструкции) и ожидаемый ответ от LLM. Ниже приведен пример данных инструкции:

[ { "instruction": "Can cats communicate?", "context": "Cats need to communicate with each other for bonding, and relating with each other; they need to collaborate, play, and share resources...", "response": "Cat vocalizations have been categorized according to a range of characteristics...", } ]

Схематично процесс тонкой настройки можно представить следующим образом:

Создайте клон себя с помощью точно настроенного LLM

Важно помнить, что вы можете изменить формат данных в соответствии с вашими потребностями. Например, вы можете ввести функцию и попросить модель сгенерировать документацию в качестве ответа. Однако, исходя из моего опыта, модели меньшего размера (такие как 7B) могут иметь проблемы со сложными подсказками.

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

Чтобы построить инструкции на основе моего чата, я использовал несколько подходов:

  • Разделение беседы на пакеты, когда промежуток времени между двумя сообщениями превышает один день. Таким образом, мы рассматриваем это как начало новой темы общения, и, следовательно, не будет контекста из предыдущего разговора.
  • Объединение последовательных сообщений от одного пользователя в одно сообщение. Как известно, некоторые люди склонны писать несколько коротких сообщений подряд.
  • Установка максимальной длины контекста для ускорения процесса обучения.
  • Добавление меток к своим ответам и ответам собеседника, чтобы помочь модели лучше понять контекст.
Создайте клон себя с помощью точно настроенного LLM

Я также очистил историю чата от конфиденциальной информации, такой как личные пароли или электронные письма.

В итоге я получил 51 тыс. инструкций, что сопоставимо с набором данных инструкций Dolly 2.0 от Databricks (~15 тыс. инструкций) и набором данных Alpaca (~52 тыс. инструкций).

Модель

Я решил выбрать Falcon — новейшую модель большого языка с открытым исходным кодом, выпущенную Институтом технологических инноваций . Это модель авторегрессионного декодера с двумя вариантами: модель с 7 миллиардами параметров и модель с 40 миллиардами параметров. Вариант модели 40B обучался на 384 графических процессорах в AWS в течение 2 месяцев.

Создайте клон себя с помощью точно настроенного LLM

Исходя из того, что известно о модели, архитектура Falcon очень похожа на GPT-3 и LLaMA, за исключением использования многозапросного внимания ( Shazeer 2019 ) и корпуса RefinedWeb в качестве обучающего набора данных ( что может стать ключом к успеху ).

Точная настройка LLM с эффективными параметрами с помощью LoRA

Если мы рассматриваем способы улучшения моделей LLM (Large Language Model), одним из ценных ресурсов является статья OpenAI PALMS: Pre-training an Autoencoder Latent Model for Sequence Generation. В статье обсуждается использование тонкой настройки, которая включает в себя переобучение модели с использованием тех же методов, что и исходное обучение, но с более низкой скоростью обучения ~ 0,1 . Этот процесс позволяет нам обучать модель на наших конкретных данных, тем самым улучшая её реакцию в желаемой области.

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

Создайте клон себя с помощью точно настроенного LLM

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

Каждая матрица W представлена как сумма W + A * B во время обучения. Исходная матрица W замораживается, и обучаются только матрицы A и B. Следовательно, обновленные веса получаются как ΔW = W + A * B. Благодаря тому, что матрицы A и B остаются маленькими, процесс обучения становится быстрее и требует меньше ресурсов. В двух словах, это метод LoRA, который показан на рисунке ниже.

Создайте клон себя с помощью точно настроенного LLM

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

Для получения дополнительной информации и более подробной информации я рекомендую следующие ресурсы:

Эксперимент

Для проведения своих экспериментов я использовал библиотеку Lit-GPT , которая включает в себя реализацию LLM с открытым исходным кодом и работает на базе Lightning Fabric . Что касается аппаратной настройки, я использовал один графический процессор A100 с объемом памяти 40 ГБ.

Загрузка весов модели

Чтобы начать эксперименты, первый шаг включает в себя загрузку весов модели и преобразование их в формат lit-gpt. Это довольно легко сделать:

# download the model weights: python scripts/download.py --repo_id tiiuae/falcon-7b # convert the weights into a standardized form: python scripts/convert_hf_checkpoint.py --checkpoint_dir checkpoints/tiiuae/falcon-7b

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

Подготовьте набор данных

Тонкая настройка включает в себя два основных шага: сначала мы обрабатываем набор данных в формате Lit-Parrot, а затем запускаем скрипт тонкой настройки на обработанном наборе данных.

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

def generate_prompt(example: dict[str, str]) -> str: """Generates a standardized message to prompt the model""" return ( "You (I) are chatting with a user R. Write a reply to his message.\n\n" f"### Your previous communication:\n{example['context']}\n\n" f"### His new message:\n{example['instruction']}\n\n" f"### Your response:{example['response']}" )

После внесения изменений можно начинать процесс подготовки данных:

python scripts/prepare_dataset_my.py \ --checkpoint_dir checkpoints/tiiuae/falcon-7b/

Подготовка подсказок не занимает много времени. В моем случае на 51к инструкций ушло всего 2 минуты:

Создайте клон себя с помощью точно настроенного LLM

Тонкая настройка модели Falcon

После того, как вы подготовили свой набор данных, довольно просто настроить модель.

Я изменил некоторые параметры в скрипте тонкой настройки для лучших результатов, вот обзор настроек гиперпараметров, которые я использовал:

bfloat16 точность (подробнее о bfloat16 я писал в статье 7 способов ускорить вывод ваших размещенных LLM ).

  • Также скрипты были настроены для обучения моделей на 51k итераций с использованием эффективного размера пакета 128 с накоплением градиента.
  • Для LoRA я использовал ранг 16, чтобы получить обученный адаптер более высокого качества. И установите альфа на 32 ( alpha - это коэффициент масштабирования, который регулирует величину комбинированного результата, это уравновешивает знания предварительно обученной модели и новую адаптацию к конкретной задаче).

Затем вам нужно запустить скрипт finetune/lora.py, указав свой путь к данным.

python finetune/lora_my.py \ --checkpoint_dir checkpoints/tiiuae/falcon-7b/ \ --data_dir data/falcon/ \ --out_dir out/falcon \ --precision bf16-true

Следите за тонкой настройкой

Вы можете использовать команду Linux watch для повторного запуска nvidia-smi каждые полсекунды:

watch -n 0.5 nvidia-smi
Создайте клон себя с помощью точно настроенного LLM

Вы можете найти контрольные точки модели в out/falconпапке и использовать скрипт генерации, чтобы поиграть с моделью.

Для точной настройки модели на одном графическом процессоре A100 требуется около 10 часов и 30 ГБ памяти. При этом стоит отметить, что сам адаптер легкий, весит всего 40МБ . Это значительно меньше по сравнению с моделью Falcon, которая имеет размер 16 ГБ.

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

Вы можете использовать тонко настроенную контрольную точку вашего LLM для генерации текстов. Lit-Parrot предоставляет сценарии генерации. Он поддерживает int8 и int4 квантование для устройств с меньшим объемом памяти графического процессора, также вы можете изменить точность и использовать несколько устройств с несколькими графическими процессорами:

python generate/lora.py \ --checkpoint_dir checkpoints/tiiuae/falcon-7b \ --lora_path out/falcon/lit_model_lora_finetuned.pth \ --prompt "What happened to you? Tell me" \ --max_new_tokens 300 --precision bf16-true

В моем случае я запускал модель на 1 устройстве GPU, без квантования и с bfloat16 точностью. Я также изменил исходный lora-скрипт и разделил его на две части:

  • Веб-интерфейс с использованием streamlit и streamlit-chat для более быстрого тестирования модели. Вы можете найти мою версию здесь .
  • RestAPI использует веб-фреймворк FastAPI для вывода модели. Это позволяло загрузить модель в память один раз, а затем использовать её снова.

Демо (я перевел текст, чтобы было понятно):

Важно отметить, что это один из лучших примеров, которые мне попадались. Остальные были заметно хуже.

Время отклика модели, даже без квантования, было удивительно быстрым — 45,51 токена в секунду. Если вы хотите ускорить генерацию текста или минимизировать использование памяти, я рекомендую ознакомиться с моей предыдущей статьей 7 способов ускорить вывод ваших размещенных LLM .

Сравнение качества

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

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

Мне кажется, что это можно исправить несколькими способами:

  • Усовершенствуйте процессы очистки данных, чтобы обеспечить более высокое качество данных.
  • Включите дополнительные аннотированные наборы данных диалогов.
  • Увеличьте ранг LoRA с 16 до 32.
  • Используйте модель большего размера, например Falcon-40B.
  • Уменьшите длину контекста или упростите его.
  • Упростите подсказки, чтобы предоставить более четкие инструкции.

Ограничения

Хотя Lit-GPT предлагает широкий спектр функций, я бы посоветовал в первую очередь использовать его для проверки гипотез. На мой взгляд, он еще не полностью готов к использованию в производстве. Например, на момент написания этой статьи в Lit-GPT отсутствовала встроенная реализация для преобразования модели обратно в формат HuggingFace. Однако это все же возможно, и авторы библиотеки предлагают пару решений :

  • Выполните обратное преобразование для каждого из классов HuggingFace.
  • Создание версии модели HF Transformer в формате lit_gpt.model.

Обратите внимание, что первый метод не поддерживает модификации LoRA и адаптера.

Помните об этих ограничениях при разработке решения. Если вы настраиваете LLM для производства, я рекомендую использовать чистый PyTorch.

Заключение

Возможность тонкой настройки LLM с использованием всего одного графического процессора и нескольких часов действительно впечатляет. Вы можете построить множество небольших модулей LoRA для разных задач. Когда эти точно настроенные модели развертываются для логического вывода в реальном времени, вам достаточно один раз загрузить одну и ту же базовую модель. Учитывая физический размер LLM более 100 ГБ, это преимущество нельзя игнорировать.

Однако важно подходить к процессу с реалистичными ожиданиями. Вполне вероятно, что для достижения оптимальных результатов потребуются эксперименты с различными гиперпараметрами. Кроме того, аннотация и очистка набора данных являются важными шагами для обеспечения наилучших результатов. Также обратите внимание на то, на каких данных обучался LLM, и проверьте бенчмарки для задач, похожих на вашу.

Усердно следуя этим шагам, я уверен, что можно добиться отличных результатов!

11
1 комментарий

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

Ответить