Реставрация ruGPT-3 XL: как я вернул к жизни забытую русскую языковую модель

Реставрация ruGPT-3 XL: как я вернул к жизни забытую русскую языковую модель

Несколько дней подряд я занимался восстановлением легаси-модели ai-forever/rugpt3xl — классической языковой модели от SberDevices с 1,3 млрд параметров. Это скромный по современным меркам foundation-модель, разработанная ещё в 2021 году. Она умеет только продолжать текст, но обучена исключительно на русскоязычном корпусе и генерирует русский язык очень уверенно.

Модель была обучена с нуля, а её архитектура представляет собой глубокую модификацию GPT-2. Подробнее о ней можно прочитать в научной статье “A family of pretrained transformer language models for Russian” на Google Scholar.

Почему это важно

Модель формально доступна на HuggingFace, но фактически была недоступна для использования — она «заживо замурована» в устаревшем стеке технологий. Для её запуска требовались Megatron-LM, DeepSpeed, apex и древние версии PyTorch 1.7 и transformers 3.5. Это делало запуск в 2026 году почти невозможным.

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

Ранее я трижды пытался это сделать, но не хватало опыта и инструментов. В этот раз я воспользовался современными кодовыми агентами: предварительную работу выполнял Cursor, а я корректировал направление и тестировал результат.

Конвертация в формат Hugging Face

Цель была проста: получить полностью рабочую модель, максимально близкую к оригиналу, которую можно загружать через transformers и дообучать — как с помощью LoRA, так и через SFT-тренеры.

После анализа исходников ai-forever/ru-gpts, современной библиотеки transformers и примеров кастомных моделей (например, DeepSeek-Coder), удалось понять структуру весов и реализовать конвертацию.

Ключевое отличие оригинальной модели — объединённая QKV-проекция размером [6144, 2048], которую нужно разбить на три отдельных слоя (Q, K, V) по [2048, 2048]. Также потребовалось явно добавить lm_head, скопировав веса из токенизационных эмбеддингов.

Был составлен полный маппинг весов из формата Megatron-LM в структуру, близкую к GPT2Model. На его основе написан скрипт convert.py, который преобразует оригинальный чекпоинт mp_rank_00_model_states.pt в модель с safetensors-весами.

Создание кастомных классов

Оригинальный код модели — это толстая обёртка вокруг Megatron-LM, требующая torch.distributed, инициализации model parallelism и других устаревших компонентов. Для современного использования это неработоспособно.

Я создал новые классы с нуля, вдохновляясь структурой transformers:

  • RuGPT3XLConfig — наследник PretrainedConfig с параметрами модели
  • RuGPT3XLAttention — multi-head attention с отдельными Q/K/V и поддержкой DynamicCache
  • RuGPT3XMLP — перцептронный блок (up_proj → GELU → down_proj)
  • RuGPT3XLDecoderLayer — декодерный слой (LayerNorm → Attention → LayerNorm → MLP)
  • RuGPT3XLModel — базовая модель (эмбеддинги + 24 слоя + финальный LayerNorm)
  • RuGPT3XLForCausalLM — обёртка с lm_head

Преимущества новой реализации:

  • Нет зависимостей от Megatron-LM, DeepSpeed, apex, torch.distributed
  • Стандартный forward(), совместимый с любыми тренерами
  • Результаты возвращаются в CausalLMOutputWithPast
  • Поддержка KV-кеша через DynamicCache для быстрой генерации
  • Поддержка gradient checkpointing для экономии памяти при обучении
  • Работа на CPU, GPU, с device_map="auto" — без обязательного CUDA

Математика осталась идентичной оригиналу: те же размерности, Pre-LayerNorm, GELU, токенизатор. Изменилась только обвязка — теперь она современная и удобная.

Конвертированная модель доступна на HuggingFace: evilfreelancer/ruGPT3XL.

Тестирование

Первые тесты показали, что модель генерирует связный текст на промптах вроде “Москва — столица”, “Искусственный интеллект — это”, “В далёком космосе”. Для foundation-модели 2021 года на 1,3 млрд параметров это достойный результат.

Дальнейшее тестирование проводилось на 24 промптах разного типа — от продолжения текста (“Однажды в студёную зимнюю пору”) до вопросов через chat template (“Вопрос: Какая столица России? Ответ:”). Тесты проводились на RTX 4090 (48 Гб, float16).

Ключевые наблюдения:

  • Средняя скорость генерации — 66,7 токенов/сек
  • На коротких промптах модель часто останавливается рано (15–30 токенов)
  • На длинных — уверенно генерирует до max_new_tokens
  • Ответы на вопросы иногда творческие: на “Кто написал «Войну и мир»?” модель ответила “Пушкин”
  • Хорошо справляется с продолжением фактического текста — рецепты, физика, история
  • На вопрос “Сколько планет в Солнечной системе?” ответила “Пять”, а затем ушла в рассуждения о цивилизациях Млечного Пути

Модель была протестирована на бенчмарке MERA — открытом наборе из 23 задач для оценки русскоязычных моделей. Общий скор — 0,198 (на модерации).

Результаты по ключевым задачам:

  • PARus (здравый смысл) — 0,500
  • ruHateSpeech — 0,558
  • BPS (код/математика) — 0,528
  • RWSD (рассуждения) — 0,488
  • ruTiE (диалоговый контекст) — 0,502
  • ruMMLU — 0,252 (на уровне случайного угадывания, что ожидаемо для base-модели)

Математика (SimpleAr — 0,012, ruModAr — 0,001) и генерация кода (ruHumanEval, ruCodeEval — 0/0/0) находятся на нуле, что логично — модель никогда не обучалась этим задачам.

Конвертация в GGUF

Для дальнейшего упрощения использования я конвертировал модель в формат GGUF для llama.cpp. Благодаря предыдущей работе с transformers, это оказалось относительно просто.

Модель структурно близка к GPT-2, поэтому достаточно было объединить отдельные q_proj, k_proj, v_proj обратно в единый QKV-тензор, как того ожидает LLM_ARCH_GPT2.

Я отправил PR #21011 в llama.cpp, прошёл ревью, внес правки (включая хеш токенизатора), и пулл-реквест был успешно смержен.

После этого я смог конвертировать и сквантовать модель. GGUF-версии доступны на HuggingFace: evilfreelancer/ruGPT3XL-GGUF.

Теперь модель можно запускать:

  • Прямо в терминале через llama.cpp
  • Через локальный OpenAI-совместимый сервер с веб-интерфейсом
  • В Ollama — где теперь собрано всё семейство ruGPT-3: small (125M), medium (356M), large (760M) и xl (1.3B)

Так появился цифровой музей классических русских языковых моделей в современной упаковке.

Ссылки

  • evilfreelancer/ruGPT3XL — модель в формате HuggingFace (safetensors)
  • evilfreelancer/ruGPT3XL-GGUF — квантованные GGUF-веса для llama.cpp и Ollama
  • EvilFreelancer/rugpt3xl-convert — исходники скриптов конвертации
  • evilfreelancer/rugpt3 — всё семейство ruGPT-3 на Ollama
  • PR #21011 в llama.cpp — патч для поддержки RuGPT3XL (смержен)
  • ai-forever/rugpt3xl — оригинальная модель
  • ai-forever/ru-gpts — оригинальная кодовая база
  • “A family of pretrained transformer language models for Russian” — научная статья
Читать оригинал