Непрерывное обучение LLM: модель на ноутбуке без забывания

Непрерывное обучение LLM: модель на ноутбуке без забывания

У каждой языковой модели есть день, когда она перестаёт учиться. Веса замораживают, выкладывают, и дальше модель может только притворяться: дообучение на новых данных неизбежно разрушает часть старого. Это называют катастрофическим забыванием, и до недавнего времени считалось, что обойти его без огромных ресурсов нельзя. Проект mini-AGI, появившийся на GitHub этой осенью, ставит эксперимент против этого правила: языковая модель на 826 миллионов параметров обучается с нуля на одной видеокарте с 8 ГБ и продолжает учиться на каждом тексте, который читает.

Автор проекта, Алексей Борский, сразу снимает вопрос о масштабе: это игрушечная модель, а не заявка на фронтир. Ценность здесь в другом. README превращён в аккуратный отчёт с измерениями, честными оговорками и воспроизводимыми экспериментами, которые показывают, что непрерывное обучение из единого потока данных возможно без катастрофического забывания и что хватает для этого ноутбука.

Что такое mini-AGI

mini-AGI это байтовая языковая модель непрерывного обучения: она обучается с нуля на потребительской видеокарте от 8 ГБ и не останавливается, продолжая учиться на всём, что ей дают читать. Веса хранятся обычными файлами на диске и подгружаются на карту по мере надобности, поэтому размер модели ограничен не видеопамятью, а свободным местом на диске.

Имя наполовину шутка. Оно описывает не сегодняшние способности модели, а её свойства: непрерывное обучение из одного потока и подстройку размера под доступные ресурсы. Именно это автор ждёт от AGI, а «мини» здесь означает лишь игрушечный масштаб памяти. Промежуточные веса и чекпоинт, на котором измерялись все эксперименты, уже лежат на Hugging Face.

Почему непрерывное обучение сложно

Обычный жизненный цикл модели выглядит так. Её обучают один раз, фиксируют веса, выпускают. Владелец может дообучить её по краям: LoRA, адаптеры, стек промптов. Но полноценно учиться она уже не будет. Как только вы пробуете скормить ей свои данные, начинается забывание: часть прежних навыков исчезает. Получается, что персональная модель это чужая модель с тонким слоем ваших данных сверху, которая перестала учиться в день релиза.

Дизайн mini-AGI задают три ограничения. Первое: всё должно помещаться в 8 ГБ, причём не с квантизацией. Для обучения нужны градиенты и состояния оптимизатора, а это примерно втрое больше самих весов, поэтому веса живут на диске, а на карте оказываются только эксперты, нужные текущему проходу. Второе: модель не должна забывать, потому что непрерывно обучающаяся модель, затирающая себя, хуже модели, которая не учится вовсе. Третье: она должна уметь читать что угодно. Алфавит здесь это 256 байтовых значений, поэтому токенизатор не нужен, а новые типы данных не требуют новых словарей.

Как устроена архитектура

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

Глубина меняется от символа к символу. «Голова остановки» оценивает каждый символ на каждом ряду, и символ останавливается, как только следующий ряд уже не изменил бы ответ. Лёгкие символы проходят один ряд, сложные берут много: в визуализации проекта ряды, которые модель отказалась тратить, показаны серым. Учится это по рецепту PonderNet: каждый ряд символа взвешен его вероятностью остановки, и взвешивание попадает прямо в градиент.

Маршрутизация работает не на символ, а на каждое применение блока: каждый проход берёт свои top-8 экспертов из 32, находящихся на карте. За все применения один символ успевает задеть куда большую часть пула, чем подсказывает это число, а один и тот же эксперт может быть выбран несколько раз на разных глубинах. Никакому эксперту не назначена тема: ярлыков в системе нет, способности распределяются мягкой маршрутизацией сами. Плата за это ожидаемая: способности делят параметры и могут мешать друг другу.

Отдельная деталь: чтение и генерация это один и тот же проход. Когда модель пишет, стек ведёт себя точно так же (11,8 ряда на символ против 12,1 при чтении), и экспертов выбирает весь текст целиком. Промпт голосует за экспертов первым, ответ продолжает набирать голоса, и карта загруженных экспертов меняется только тогда, когда меняется голосование. Во время генерации модель не обучается: запись ничего не меняет в весах.

Эксперты на диске: 826M параметров на карте с 8 ГБ

На шаге 618 315 параметры модели выглядели так: ядро 8,27 млн, роутеры 0,13 млн, пул экспертов 817,9 млн (260 экспертов по 3,15 млн каждый), всего 826,3 млн. На карте одновременно живут только 32 эксперта, около 109 млн параметров, поэтому пул может расти дальше на скромной видеопамяти. По стоимости вычислений на байт модель эквивалентна плотному трансформеру примерно на 344 млн параметров, а не на 826 млн.

Как всё разложено по железу. На диске лежат все эксперты, и ограничивает рост пула свободное место. Над диском стоит RAM-кэш последних использованных экспертов с вытеснением по принципу наименьшей недавности. На карте находятся 32 слота: только те эксперты, которых допустил текущий проход, могут быть выбраны для маршрутизации.

Правило отбора одно: экспертов выбирает текст. Каждый символ ранжирует весь пул через роутер, строки которого всегда лежат на карте, поэтому эксперт на диске оценивается наравне с резидентом. Символ запрашивает свои top-8, первый проход добавляет эти запросы в «голосование текста», и проходу выдаются самые востребованные, пока не заполнятся 32 слота. После этого каждый символ маршрутизируется только среди допущенных, а кто не попал, получает лучших из допущенных.

Три правила проекта выглядят почти бухгалтерскими. Каждый эксперт шагается со своими моментами Adam: моменты принадлежат эксперту, а не слоту, иначе эксперт унаследует импульс предыдущего жильца, и обучение будет выглядеть здоровым, пока подменённые эксперты тихо теряют свою историю. Эксперт, уже находящийся на карте, остаётся в своём слоте: допуск это множество, а не ранжирование. И эксперта, которого ничего не учило, не нужно писать обратно на диск: копия там уже верна, а лишние записи стоят времени. В среднем шаг обучения загружает 2,4 эксперта, потому что соседние окна одного текста просят почти те же самые.

Есть и тонкая настройка, без которой пул работал бы в четверть силы. Роутер сам по себе склонен выбирать одни и те же эксперты: на удержанных данных он задействовал лишь 59 из 118. Поэтому в лосс добавлен балансирующий член из Switch Transformer, но с поправкой: доля использования считается не по текущему батчу, а по последней тысяче проходов. Текст должен быть свободен хотеть мало экспертов, а равномерность нужна между текстами. В тесте на 15 минут с весом 0,01 число используемых экспертов выросло с 59 до 114, ценой 0,023 ната удержанного лоса.

Модель, которая сама растёт и сама себя подрезает

Пул экспертов динамический. Когда ёмкости не хватает, модель выращивает новых экспертов, а когда части пула перестают быть нужными, удаляет их. Новый эксперт добавляется «на спекуляции»: он появляется с маленьким гейтом, почти ничего не меняет в поведении и остаётся только если его начинают выбирать. Собирается он рекомбинацией: целые скрытые юниты берутся у нескольких существующих экспертов. Клон одного родителя недостаточно нов, чтобы его кто-то выбрал, а случайный эксперт не считает ничего полезного, так что работает только новизна, собранная из обученных частей.

Решение о росте принимается, только если согласны все тормоза: есть место на диске и в VRAM; ранее добавленная ёмкость действительно востребована; предыдущая когорта выжила испытательный срок; слишком много экспертов уже не висит на испытании; и качество на обучающих и удержанных данных не разъехалось. А «мёртвый» здесь означает «никем не адресуемый»: и механизм роста, и прунер смотрят только на то, как давно проход в последний раз допускал эксперта.

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

Главный эксперимент: миллион символов чужого домена

Центральное измерение проекта это проверка забывания. Модель холодно переключают на PG19, корпус викторианских романов XIX века, которого она никогда не видела, и заставляют прочитать 1 048 576 идущих подряд символов этого домена и ничего больше. Батч равен единице, никакого перемешивания. Это худший возможный сценарий катастрофического забывания, и именно на нём проверяется дизайн.

Спасает скорость обучения ствола. Ствол это всё, через что проходит каждый символ: эмбеддинги, внимание, роутеры, голова остановки. На него приходится 98% квадратичной нормы градиента, и если учить его на 0,1 от скорости экспертов, картина меняется радикально.

Конфигурация Новый домен (PG19) Восемь своих доменов Курс обмена
Эксперты заморожены, ствол учится как все -0,2909 +1,2663 0,23
Полная замена экспертов, ствол как все -0,3106 +1,2628 0,25
Замена экспертов, ствол на 0,1 скорости -0,4216 +0,1297 3,25
PG19 читается вперемешку с остальными -0,3124 -0,0065 забывания нет

Знак минус означает улучшение: столько натов лоса модель отыграла на домене. Плюс во второй колонке означает потерю на восьми доменах, которые модель знала до эксперимента. «Курс обмена» показывает, сколько натов выучено на каждый потерянный нат.

Первые две строки это то, что происходит с наивными конфигурациями: за миллион символов чужой домен осваивается слабо, зато каждый из восьми своих доменов теряет больше ната, то есть модель забывает почти всё, что знала. Третья строка, рабочая настройка проекта, меняет обмен в 13 раз: домен осваивается глубже (-0,4216 против -0,3106), а потери падают до +0,1297. Четвёртая строка показывает, что при перемешивании обмен исчезает вовсе: добавление девятого домена вперемешку с восемью старыми не стоит ничего, более того, несколько старых доменов даже улучшаются. Сохранённые способности в этом режиме: 100,13%.

Два вывода автора стоят отдельного внимания. Первый: пул экспертов это не то, что предотвращает забывание. Заморозка экспертов меняет забывание на 0,0035 ната, то есть почти ни на что, и при этом учится новому медленнее всех. В этом прогоне 137 из 174 экспертов вообще не получили градиента, а модель всё равно развалилась: терять способности можно и без изменения большинства весов, потому что урон наносится в стволе. Второй вывод виден на срезе всего чтения: градиент получили лишь 44 эксперта из 174. Три четверти модели остались структурно нетронутыми, потому что маршрутизация их не выбирала, а урон концентрируется там, где представления пересекаются. Сильнее всего просели текстовые дорожки вроде chat, stories и reasoning, ближайшие к викторианской прозе, а шахматы и арифметика почти не сдвинулись, плюс 0,009 и 0,043.

Худший сценарий, впрочем, в реальной работе не встречается. Живой цикл устроен мягче: модель читает пассаж в 32 768 символов, переходит к другой теме и возвращается к первой примерно через 262 144 символа. Автор сравнивает это с разницей между человеком, который неделю занят одним делом, и человеком, который меняет занятия в течение дня. В таком режиме новый домен как девятая дорожка не стоит ничего, что и показала четвёртая строка таблицы.

Отдельная деталь в конце раздела: скорость обучения нигде не расписана по расписанию. Косинусное расписание подразумевает, что прогон заканчивается, а для модели, которая читает непрерывно, это неправда. Вместо него контроллер следит за удержанным лоссом и двигает скорость в обе стороны: явное улучшение покупает чуть больше, отсутствие улучшений её приостанавливает, подтверждённый скачок лоса откатывает назад. Все эксперименты с забыванием можно повторить: проба, четыре конфигурации, фигуры и веса выложены в папке replication. «Измерение, которое нельзя воспроизвести, это уже не измерение, а утверждение», формулирует автор.

Что с качеством и честностью цифр

Текущие числа проекта, на момент когда README фиксировал 1 265,6 млн прочитанных символов и 260 экспертов: удержанный лосс 0,6420 ната на символ, то есть 0,9262 бита на байт, на обучающих данных 0,5272. Лучше всего модель справляется с шахматами (0,414) и рассказами (0,427), хуже всего с Википедией (1,063) и диалогами chat_hermes (0,904).

На тестовой части PG19 модель показывает 2,091 бита на байт против 0,94 на собственном миксе. Разрыв большой, но здесь важна честность автора: PG19 для модели вне распределения, она не читала викторианских романов, так что значительная часть разрыва это тематика, а не потолок возможностей. Кривая масштабирования укладывается в степенной закон вида L пропорционально D в степени минус 0,232 с R² 0,98, между коэффициентом Kaplan 0,095 и Chinchilla 0,28.

Темп обучения тоже измерен. 1,27 млрд символов за примерно 15 дней работы, около 1 181 символа в секунду по стенным часам, включая проверки и прогоны сэмплов, потому что чтение их ждёт. Ещё примерно 11 дней чтения, и модель дойдёт до 0,80 бита на байт на своём миксе, а полный проход корпуса в 7,88 млрд символов займёт около 65 дней. Числа двигаются, и автор отдельно оговаривает шум: одинаковая конфигурация в двух запусках расходится на 0,014 ната, потому что диспетчеризация экспертов на CUDA не детерминирована. Реальным отличием здесь считается только разница больше 0,03.

Качество при этом честно игрушечное, и автор не прячет примеры. На отметке 648,6 млн символов модель связно и без ошибок продолжает рассказ про вишнёвое дерево, но вторая вишня у неё отращивает крылья, а фраза «only for any more» не значит ничего. Это хорошая иллюстрация уровня: модель на 826 млн параметров, прочитавшая миллиард символов, умеет строить связный текст, но не понимает его.

Кто написал код

Отдельная деталь, которая говорит о времени не меньше самих цифр. README честно фиксирует: большую часть кода проекта реализовали модели Claude Opus 5 и 5.5. Они писали и отлаживали код, искали свежие статьи по проблемам проекта, строили тесты и эксперименты, и даже анимации и графики на этой странице сделаны из реальных трейсов при помощи модели. Автор придумывал идеи, задавал направление, отбраковывал неудачные решения, следил за кодом и в тандеме с моделью писал документацию. Симметрия забавная: проект о модели, которая учится у всего, что читает, собран руками другой модели.

Как попробовать

Для запуска нужна видеокарта NVIDIA с поддержкой CUDA от 8 ГБ и Python 3.10 или новее. Референсная машина автора это RTX 3070 Laptop. Из зависимостей для обучения нужен только torch, остальное пригодится для графиков и сборки корпусов. Корпус собирается одной командой python3 -m corpora all: она скачивает четыре публичных датасета и генерирует ещё четыре дорожки. Дальше python3 train.py read data/train --save, и модель уходит учиться на дни; за прогрессом можно следить через локальный веб-интерфейс serve.py.

Самое полезное для читателя: модели можно скормить свои файлы. Команда python3 train.py read ~/notes сделает сухой проход, а --passes 3 --save сохранит результат. Готовить ничего не нужно, алфавит это байты, поэтому любой файл уже написан на единственном известном модели языке. По умолчанию ничего не сохраняется, а до и после чтения модель сама оценивает удержанный набор и сообщает, стоило ли чтение ваших файлов каких-то потерь на другом. Скорость чтения по умолчанию ниже тренировочной, и это принципиально: чтение должно подстраивать модель, а не перезаписывать её.

Часто задаваемые вопросы

Хватит ли моей видеокарты?

Минимальное требование это NVIDIA с 8 ГБ VRAM и поддержкой CUDA, меньше не хватит, больше не обязательно. Референсный прогон идёт на RTX 3070 Laptop. Темп около 1 181 символа в секунду, поэтому первые вехи занимают дни, а не часы: до 0,80 бита на байт на своём миксе модель дойдёт ещё примерно за 11 дней чтения.

Можно ли научить модель на своих текстах?

Да, это самый короткий путь к модели, которая знает что-то лично ваше. Команда python3 train.py read ~/notes --passes 3 --save читает файлы тем же путём, что и обучение, а без флага --save ничего не сохраняется. После чтения модель сама покажет, не потеряла ли она качество на других доменах.

Это AGI, раз проект так называется?

Нет, и автор подчёркивает это первым делом. Имя полушутка: оно описывает свойства, которые автор хотел бы видеть у AGI, а именно непрерывное обучение из одного потока и подстройку под ресурсы, а не сегодняшние способности модели. Пока это игрушечная модель, способная на связные рассказы и партии в шахматы.

Итог

mini-AGI показывает редкую вещь: серьёзную исследовательскую идею можно проверить не в дата-центре, а на одной видеокарте, и получить честные измерения. Непрерывное обучение без катастрофического забывания здесь не лозунг, а воспроизводимый эксперимент: миллион символов чужого домена ценой 0,13 ната забывания против 1,27 у наивных конфигураций, открытые веса и код, по которому можно повторить каждый шаг.

Следующий шаг зависит от читателя. Скачайте репозиторий, загляните в папку replication, прогоните измерение забывания на своей машине или просто дайте модели прочитать вашу папку с заметками и посмотрите, как она отчитается о результате. Непрерывное обучение LLM перестало быть только теоретической проблемой: проверить его теперь можно на ноутбуке. Если вам интересны такие разборы, посмотрите наш текст про то, как Shopify построила похожий цикл непрерывного обучения в продакшене.

← Все записи