В современном мире LLM, также известных как "чудо техники", сложилась забавная ситуация: формально LLAMA, Mistral и другие open source проекты не поддерживают ничего, кроме английского языка, но это не совсем так. Они поддерживают другие языки, даже с неплохим качеством, но есть нюанс — плотность токенизации довольно низкая-> в следствии чего модели не будут эффективно работать на языках заметно отличных от английского.

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

у нас есть русский в CommonCrawl(входит в топ10 языков интернета) + Wiki + немного в Github. Тоже самое касается китайского, корейского и прочих. 

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

Saiga

Огромный респект Илье Гусеву за создании сайги – единственной русской инструктивной модели статья.

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

Но с ней есть одна проблема - токенизация!

Если коротко: токенайзер это штука которая бьет str в циферки [0, max_tokenizer], учиться как дерево остатков те учиться пихать макс символов в токен, а BBpe токенайзеры(все начиная с gpt2 примерно~ )   умеют еще и байты переваривать. Читать больше (вы можете сунуть картинку в byte like виде в модель) 

Для нас важно что у русских(сбер, яндекс) моделей на каждые три символа приходится 1 токен, а у Llama/Mistral/Gpt4(в меньшей степени) на ~ КАЖДЫЙ символ приходится токен. 

Выглядит токенизация русского примерно так:

По русски: у вас контекст влезет в три раза меньше от того что написано в описании модели. Те вместо 4096*3 символов влезет примерно 5000 символов. Если вы строите RAG based систему то понятно какие проблемы это влечет.

Всегда найдется азиат который сделает это быстрее тебя (с), длинный обзор предидущих работ и бессовестный PR крутых ребят из МГУ.

China llama

Идея следующая: авторы расширяют токенайзер

репа+папир

и учат LORA в начале на general domain датасете(википедия, новости и прочее) а затем доучивают на chinese alpaca(синта из GPT4)

По метрикам после такого обучения правда есть проблемы, они просаживаются причем ощутимо.  

Impact of Tokenization on LLaMa Russian Adaptation

Идея такая: 

Учим русский токенайзер с нуля.

Заново инициализируем LmHead и embeddings нужного размера инитя их старыми.

Учим новые слои на 9B токенов(43GB) и получаем модель которая конкурента с оригинальной лламой.

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

Подводка закончилась, началось описание того что мы сделали.

Расширение токенайзера

Мы обучили SentencePiece токенайзер 50к на RULM, оставили только русские токены 

Из данного графика можно сделать вывод, что эффективность процесса токенизации улучшается с увеличением размера словаря. В качестве примера можно рассмотреть ruGPT, где эффективность токенизации достигает значения около 0.27 по оси Y, что соответствует в среднем 2-3 токенам на слово. Расширение словаря токенизатора приводит к улучшению этого показателя примерно на 30% (1.3-кратное увеличение), что делает процесс токенизации более эффективным.

Для T5 графа в целом не страшна неэффективность токенизации(я не понял сейчас почему так плохо и вовремя не заметил, а когда к статье строил картинку было поздно потому что статья задерживалась на 4 недели. Возможно потом сделаю), за счет relative position embeddings можно пихать столько сколько в карту влезет токенов. 

Как учить LLM если ты gpu poor?

Здесь и далее я ввожу термин gpu poor - он означает обучение в рамках одной ноды, не более месяца. При большом желании можно воспроизвести для вашего языка при вложении цены хорошего компьютера(<10k usd на все)

У нас было 4v100 32gb, те каждая карта меньше чем нужно - 7B кушает 54gb на обучение модели целиком. Спойлер: по итогу я снимал h100.

Проблемы: 

  • v100 не умеют bf16

Что делать:

  • Это sxm карты, выставляем сервер на улицу на табуретку, чтобы не перегреть, ставим питание 600watt и разгоняемся, полная сетевая связанность через NV => раскидываем модель по кусочкам на карту и учим с FSDP tensor paralel

  • Flash attention отсюда для h100

  • Включаем grad checkpointing, благо в hf все впилено

  • Используем Adamw чтобы считать по всем слоям градиент стабильно и не подбирать параметры за 10 ранов несмотря на то что он кушает больше памяти.

В среде NLPшников ходит легенда  основанная на этом твите о том что если размер токенайзера делиться на 32 или 64, то блочное умножение работает быстрее и в целом

Возможно с torch compile работало бы быстрее, но времени и желания я не нашел.

Если у вас есть - пишите кастомные Fused Kernels в стиле и будет вам счастье.

Возможно оно работает с определенного числа карт, возможно стоит трекать MFU чего я не делал, но на сингл ноде и в рамках игрушечных трейнов в целом можно очень сильно забивать на FUSED kernels, эффективные дата лоадеры и прочие радости. Чекните через torch.profiler карта не сильно стоит и ставьте учиться, либо пользуйтесь готовыми репозиториями.

Данные

Я учился на следующем миксе для 7b модели и 3b:

  • Habr(топ 100к лайкнутых) отсюда

  • Переведенный FLAN(для T5 модели, для 7b не хватило карт) отсюда

  • Инструктивная версия 7B модели полностью основана на Saiga Mistral

Flan t5 - VikhrT5-3b

Для претрена современных T5 like моделей используют не MLM( Какой <MASK> здесь токен), а Span corruption

Идея собственно в том что уча модель на разные задачи мы можем потом решать всякие Fill in the middle, или заставлять T5 быть классик LMtask моделью(S denoising).

Я использовал кодовую базу отсюда https://github.com/google-research/t5x, а затем JAX модель конвертится в torch без проблем.

dataset

VikhrT5-3b

FRED-T5-XL(1.7b)

FLAN-t5-xl(3b)

ru_mmlu

0.32

0.252

0.28(лол2)

xwinograd_ru

0.71(lol)

0.57

0.52

xnli_ru

0.4280

0.34

0.33

Mistral 7b и что там надуло? в смысле обгоняет русские модели…

В чем сложность? Модели имеют свойство тупеть после обучения в лоб, те метрики у модели которая видела русские токены метрики будут ХУЖЕ чем у модели которая русских токенов НЕ видела.

Я обнаружил это в https://huggingface.co/AlexWortega/rugpt-neo-1.3b

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

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

(В оригинале используется KL штраф), я же использую SLERP для интерполяции лоссов

Mistral metric:

dataset

Vikhr-7b-0.1 (5-shot)

Mistral-7B-v0.1 (5-shot)

GigaChat(7b)

(5shot)

mmlu_ru

0.60

0.66

0.581

xwinograd_ru

0.7243

0.68

0.7127

xnli_ru

0.3780

0.3991

Качать тут

7B модель

7B инстракт

3B T5 модель

240м T5 модель

Авторы:

Александр

Карина - https://t.me/nadlskom

Денис @den4ikresearch за помощь с подбором гиперпараметров т5

Михаил Тихомиров за early adoption чекпоинты и найденный неверный чекпоинт

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

Почитать после статьи если какие то термины были не понятные: