habrahabr

Как (быстро) сделать русский локальный ChatGPT

  • понедельник, 11 сентября 2023 г. в 00:00:18
https://habr.com/ru/articles/759386/

Эта история началась в начале марта этого года. ChatGPT тогда был в самом расцвете. Мне в Telegram пришёл Саша Кукушкин, с которым мы знакомы довольно давно. Спросил, не занимаемся ли мы с Сашей Николичем языковыми моделями для русского языка, и как можно нам помочь.

Русская турбо-альпака
Русская турбо-альпака

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

После этого мы какое-то время продолжали какое-то время делать всё то же самое. Я потихоньку по инерции расширял rulm новыми наборами данных. Посчитав, что обучить базовую модель нам в ближайшее время не светит, мы решили сосредоточиться на дообучении на инструкциях и почти начали конвертировать то, что есть, в формат инструкций по аналогии с Flan. И тут меня угораздило внимательно перечитать статью.

Там я обнаружил вот эту картинку:

Масштабирование по Flan
Масштабирование по Flan

По этой картинке выходило, что с текущими базовыми моделями для русского нам ловить нечего. Самой большой именно русской моделью на тот момент была rugpt3large с 760 миллионами параметров, что соответствует самому началу этого графика. При этом существует другая известная картинка из поста OpenAI, из-за которой мы изначально всё это затевали:

Масштабирование по InstructGPT
Масштабирование по InstructGPT

Моделей с 760 миллионами параметров на ней вообще нет, а дообучение для всех размеров стабильно показывает хорошие результаты. А отличие тут в данных и в метрике. У Flan’а это автоматически сконвертированные наборы данных для различных NLP задач, а у OpenAI - ручная разметка. Кроме того, на картинке OpenAI оцениваются предпочтения пользователей, а на картинке Flan'а — реальные метрики на реальных задачах. Проблема тут вот какая...

На что ответ был:

Нам чертовски повезло. За 4 дня до этого вышла Альпака, которая по сути генерировала околочеловеческий инструктивный набор данных с помощью GPT-3. Мы решили сделать ровно то же самое, но на русском и с gpt-3.5-turbo вместо text-davinci-003 для удешевления процесса.

Сказано - сделано! Данные собрали быстро, за 4 дня. Ещё какое-то время ушло на оптимизацию обращений к API и добор до 30 тысяч примеров. После чего мы начали дообучать разные базовые модели. Начали с rugpt, xglm и mt0_xxl. Получалось приемлемо, но ничего особенного.

RuGPT-large. Последний вопрос там специально, потому что его гарантированно не могло быть в обучающей выборке из-за зацензуренности ChatGPT.
RuGPT-large. Последний вопрос там специально, потому что его гарантированно не могло быть в обучающей выборке из-за зацензуренности ChatGPT.

Модели мы выкладывали на HuggingFace по мере готовности, и нас начали спрашивать про дообучение LLaMA. У меня было довольно сильное мнение по этому поводу, я читал оригинальную статью и видел, что почти во всех частях обучающей выборки оставляли только английский, а остальные языки выфильтровывали. Единственное исключение — Википедия. Для неё оставили 20 языков с латиницей или кириллицей, в том числе и русский.

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

Надо ли говорить, что я был не прав.

И оно заработало! Заработало лучше, чем все существующие на тот момент русские базовые модели.

В этот момент история Сайги началась по-настоящему.

База

Языковая модель — это модель, которая предсказывает следующее слово по предыдущим. Или символ, или токен, то есть часть слова. Где-то до 2017 года самыми известными языковыми моделями были N-граммные, которые просто сохраняли, какие слова шли после каких, и считали вероятности на основе этого.

Не читали курс Лены Войты? Серьёзно, не читали? Ну так почитайте!
Не читали курс Лены Войты? Серьёзно, не читали? Ну так почитайте!

Были языковые модели и на основе рекуррентных сетей, и ваш покорный слуга их даже тогда использовал, но в прикладном аспекте N-граммные модели были всё ещё важнее. Использовались они в спеллчекерах и ASR для учёта контекста.

Конечно, можно сказать, что word2vec из 2013 тоже своего рода языковая модель, но тогда так никто особо не говорил.

В 2017 появились трансформеры, в 2018 появились GPT и BERT, и языковые модели стали основой всей области обработки естественных языков. В конце 2022 вышла ChatGPT, и языковые модели добрались до обывателя, а корпорации и учёные начали пытаться это повторить.

Модель

Было несколько вариантов базовых моделей. Во-первых, были древние маленькие модели Сбера: rugpt3medium и rugpt3large, у которых от GPT-3 одно название. Во-вторых, были многоязычные модели: xglm и mt0. Но в феврале вышла LLaMA. И она оказалась чертовски особенной.

Помните законы масштабирования, которые описаны в том числе здесь? Ллама опирается на законы Шиншиллы, законы Хоффмана, законы DeepMind, законы, по которым модели нужно скормить очень много токенов, чтобы стало хорошо. И на момент выхода она была в этом уникальна среди больших открытых языковых моделей.

И снова эта картинка здесь
И снова эта картинка здесь

У Лламы оказалась ещё одна очень важная особенность — годная разбивка на русские токены. Это неожиданно, учитывая что в её наборе данных из русского была только Википедия, что составляло меньше 1% данных. Я до сих пор не очень понимаю, была ли такая токенизация случайными стечением обстоятельств, или кто-то это специально продумал. До сих пор нет ни одной открытой многоязычной модели с токенизацией лучше, чем у Лламы. Кроме RWKV-4-World, конечно, но это всё ещё экзотика.

Синтетические наборы данных

В декабре 2022 года вышла статья про self-instruct. Она тоже уникальна — для неё авторами не нужны были GPU. Авторы вручную составили 175 образцовых инструкций и примеров их выполнения, и попросили GPT-3 сгенерировать похожих. И потом дообучили саму GPT-3 на этих инструкциях через API.

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

Схватив себя за эту косичку, я изо всех сил дёрнул вверх и без большого труда вытащил из болота и себя, и своего коня, которого крепко сжал обеими ногами, как щипцами.

В марте 2023 появилась Альпака, стенфордский проект с той же идеей, что и self-instruct, но с дообучением не GPT-3, а LLaMA. По сути ребята вытащили стиль ответов из GPT-3 и перенесли его на открытую базовую модель.

Дистилляция через API — это гениально!
Дистилляция через API — это гениально!

И мы сделали то же самое, но для русского. Сделали это дешевле, потому что использовал уже доступный на тот момент gpt-3.5-turbo. И ещё прогнали каждое задание отдельным вызовом API. Получилось что-то вроде такого:

Из презентации к DataFest'у
Из презентации к DataFest'у

LoRA: Low-Rank Adaptation

Дообучение даже 7-миллиардной модели пару лет назад казалось не самой простой задачей, в основном из-за требований к VRAM. Эвристика тут такая: для 16-битных моделей нужно умножить количество миллиардов на 2, и получится примерно количество гигабайт, которое занимает эта модель. Для 7 миллиардов это 14Гб. Но кроме самой модели нужно хранить ещё и её градиенты и состояние оптимизатора, и мы вылезаем за типичные 24Гб VRAM.

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

Собственно последний вариант и называется LoRA, а вся совокупность методов — PEFT, parameter-efficient fine-tuning.

Это вся суть LoRA. Серьёзно, вся.
Это вся суть LoRA. Серьёзно, вся.

В нашем контексте LoRA позволяет сильно экономить на VRAM, потому что оригинальная модель заморожена, и по ней не нужно считать и хранить градиенты. LoRA сама по себе позволяет обучать 7-миллиардные модели в 16 битах на карточках с 24Гб VRAM.

Квантование

Но даже с LoRA обучение 13-миллиардной модели уже невозможно в 24Гб VRAM, однако же мы это много раз делали. А как так?

На самом деле, 16 бит точности — это избыточно. Большая часть весов обученной модели нормально распределена внутри своих слоёв, обычно недалеко нуля (см. Appendix F), и представлять числа типа 65504 нам не нужно. int8 вместо float16 более чем достаточно.

В августе 2022 вышла статья, которая называется LLM.int8. В ней авторы, в частности Тим Деттмерс, аккуратно посмотрели на проблемы квантования округлением к ближайшему целому. Оказывается, в активациях (не в весах!) сети есть выбросы, которые это самое квантование ломают. Ну и авторы сделали костыль под эти выбросы. О природе выбросов, кстати, не так давно были интересные споры.

Очень понятная схема из статьи
Очень понятная схема из статьи

Но что более важно, в отличие от авторов остальных сотен статьей про квантование, они интегрировали свой метод в HuggingFace Transformers, небезызвестную библиотеку, что позволило нам воспользоваться им в одну строчку. То есть мы морозим модель в 8 битах, и учим 16-битные LoRA.

Теперь эвристика ещё проще: количество миллиардов примерно равно количеству гигабайт. И 13-миллиардные модели обучаются в 24Гб с запасом.

Это всё только верхушка айсберга: есть gptq, есть qlora, есть упомянутые выше сотни статей про разные варианты квантований.

Запуск на CPU

Ещё одна непредставимая пару лет назад вещь — запуск 13-миллиардной модели на любом ноутбуке, а того гляди и на телефоне.

Есть такой человек, Георгий Герганов. Он написал библиотеку для инференса языковых моделей на Си, ggml (где gg, очевидно, его инициалы), а также одноименный формат сериализации моделей (который недавно стал gguf). На этой основе он сделал llama.cpp, специализированную библиотеку для инференса Лламы.

Собственно модели с HuggingFace можно перевести в этот формат и пользоваться ими на CPU с приличной скоростью инференса, чем мы активно и пользуемся. 2 из 3 наших активных демо используют именно ggml модели.

Кроме того, в ggml есть свои методы квантования, вплоть до нечестных 2 бит.

Результаты

Основных тестов два: сравнение бок о бок на 176 заданиях и RussianSuperGLUE.

Вместо тысячи слов
Вместо тысячи слов

Результаты бок о бок с ChatGPT-3.5, цифры означают победы-ничьи-поражения:

  • gigasaiga vs gpt3.5-turbo: 41-4-131

  • saiga2_7b vs gpt3.5-turbo: 53-7-116

  • saiga7b vs gpt3.5-turbo: 58-6-112

  • saiga13b vs gpt3.5-turbo: 63-10-103

  • saiga30b vs gpt3.5-turbo: 67-6-103

  • saiga2_13b vs gpt3.5-turbo: 70-11-95

  • saiga2_70b vs gpt3.5-turbo: 91-10-75

Сравнения делались в Толоке, каждую пару ответов отсматривали 5 человек.

На RSG базовые Лламы не отличаются от Сайги, если их дообучать. Сама LLaMA-2 13B на 4 месте, после людей, ансамбля и Fred'а. Можно ещё смотреть на zero-shot и few-shot. У ChatGPT итоговая оценка 68.2% в zero-shot режиме, у 70-миллиардной Сайги — 64.3%.

Короче, 70-миллиардная Сайга вполне на уровне ChatGPT-3.5, но только использовать её не особо удобно, даже квантованную.

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

Старая демка: "почему трава зелёная?"
Старая демка: "почему трава зелёная?"
Старая демка: извлечение json
Старая демка: извлечение json

Инструкции по запуску и обучению на своих машинах можно найти в репозитории и карточках моделей.

Современность

С первой версии поменялось много чего:

  • Модель теперь зовётся Сайгой

  • LLaMA стала второй

  • Добавилось много разных наборов данных: от меня, от OpenAssistant, от добрых людей

  • Разработчики ggml минимум три раза поменяли формат моделей

Суть же осталась той же: учим большую базовую модель отвечать на русском языке и выкладываем её в открытый доступ.

Появились ещё и модели от Яндекса и Сбера, YandexGPT и GigaChat. Первая получила сегодня вторую версию. По нашим замерам, которым возможно вообще не стоит верить, GigaChat лучше YandexGPT и на уровне ChatGPT. Лучше он как минимум потому, что не цензурирует значительную часть запросов. Ни одна из них не открыта, доступна только базовая 13-миллиардная модель Сбера.

Все наши модели и все ссылки можно найти в репозитории: IlyaGusev/rulm.

Доклад с Датафеста: видео, слайды. Ссылку на Телеграм-канал не дам, у меня его нет.