Как (быстро) сделать русский локальный ChatGPT
- понедельник, 11 сентября 2023 г. в 00:00:18
Эта история началась в начале марта этого года. ChatGPT тогда был в самом расцвете. Мне в Telegram пришёл Саша Кукушкин, с которым мы знакомы довольно давно. Спросил, не занимаемся ли мы с Сашей Николичем языковыми моделями для русского языка, и как можно нам помочь.
И так вышло, что мы действительно занимались, я пытался собрать набор данных для обучения нормальной базовой модели, rulm, а Саша экспериментировал с существующими русскими базовыми моделями и кустарными инструктивными наборами данных.
После этого мы какое-то время продолжали какое-то время делать всё то же самое. Я потихоньку по инерции расширял rulm новыми наборами данных. Посчитав, что обучить базовую модель нам в ближайшее время не светит, мы решили сосредоточиться на дообучении на инструкциях и почти начали конвертировать то, что есть, в формат инструкций по аналогии с Flan. И тут меня угораздило внимательно перечитать статью.
Там я обнаружил вот эту картинку:
По этой картинке выходило, что с текущими базовыми моделями для русского нам ловить нечего. Самой большой именно русской моделью на тот момент была rugpt3large с 760 миллионами параметров, что соответствует самому началу этого графика. При этом существует другая известная картинка из поста OpenAI, из-за которой мы изначально всё это затевали:
Моделей с 760 миллионами параметров на ней вообще нет, а дообучение для всех размеров стабильно показывает хорошие результаты. А отличие тут в данных и в метрике. У Flan’а это автоматически сконвертированные наборы данных для различных NLP задач, а у OpenAI - ручная разметка. Кроме того, на картинке OpenAI оцениваются предпочтения пользователей, а на картинке Flan'а — реальные метрики на реальных задачах. Проблема тут вот какая...
На что ответ был:
Нам чертовски повезло. За 4 дня до этого вышла Альпака, которая по сути генерировала околочеловеческий инструктивный набор данных с помощью GPT-3. Мы решили сделать ровно то же самое, но на русском и с gpt-3.5-turbo вместо text-davinci-003 для удешевления процесса.
Сказано - сделано! Данные собрали быстро, за 4 дня. Ещё какое-то время ушло на оптимизацию обращений к API и добор до 30 тысяч примеров. После чего мы начали дообучать разные базовые модели. Начали с rugpt, xglm и mt0_xxl. Получалось приемлемо, но ничего особенного.
Модели мы выкладывали на 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 и перенесли его на открытую базовую модель.
И мы сделали то же самое, но для русского. Сделали это дешевле, потому что использовал уже доступный на тот момент gpt-3.5-turbo. И ещё прогнали каждое задание отдельным вызовом API. Получилось что-то вроде такого:
Дообучение даже 7-миллиардной модели пару лет назад казалось не самой простой задачей, в основном из-за требований к VRAM. Эвристика тут такая: для 16-битных моделей нужно умножить количество миллиардов на 2, и получится примерно количество гигабайт, которое занимает эта модель. Для 7 миллиардов это 14Гб. Но кроме самой модели нужно хранить ещё и её градиенты и состояние оптимизатора, и мы вылезаем за типичные 24Гб VRAM.
С приходом адаптеров всё изменилось. Оказалось, что оригинальную модель вообще не нужно трогать, можно просто навесить новые веса и обучать только их. Или обучать только маленькие кусочки оригинальной модели, например только bias. Или обучать виртуальные токены. Или не просто навесить новые веса, но и встроить их параллельно старым, уменьшив размерность за счёт перемножения двух низкоранговых матриц.
Собственно последний вариант и называется LoRA, а вся совокупность методов — PEFT, parameter-efficient fine-tuning.
В нашем контексте 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, есть упомянутые выше сотни статей про разные варианты квантований.
Ещё одна непредставимая пару лет назад вещь — запуск 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:
Saiga2 13B в 4 битах на CPU: ссылка
Ответы на вопросы по вашим документам: ссылка
Saiga1 13B на GPU: ссылка
Инструкции по запуску и обучению на своих машинах можно найти в репозитории и карточках моделей.
С первой версии поменялось много чего:
Модель теперь зовётся Сайгой
LLaMA стала второй
Добавилось много разных наборов данных: от меня, от OpenAssistant, от добрых людей
Разработчики ggml минимум три раза поменяли формат моделей
Суть же осталась той же: учим большую базовую модель отвечать на русском языке и выкладываем её в открытый доступ.
Появились ещё и модели от Яндекса и Сбера, YandexGPT и GigaChat. Первая получила сегодня вторую версию. По нашим замерам, которым возможно вообще не стоит верить, GigaChat лучше YandexGPT и на уровне ChatGPT. Лучше он как минимум потому, что не цензурирует значительную часть запросов. Ни одна из них не открыта, доступна только базовая 13-миллиардная модель Сбера.
Все наши модели и все ссылки можно найти в репозитории: IlyaGusev/rulm.
Доклад с Датафеста: видео, слайды. Ссылку на Телеграм-канал не дам, у меня его нет.