Как устроена LLM: разбор архитектуры Qwen3 в реальных пропорциях

Как устроена LLM: разбор архитектуры Qwen3 в реальных пропорциях

Почти каждая схема трансформера, которую вы видели, вводит в заблуждение в одном и том же месте. Attention и feed-forward сеть нарисованы двумя блоками примерно одного размера. В реальной модели это давно не так: в Qwen3 на feed-forward приходится 151 миллион параметров из 193 на блок, то есть 78%. На attention остаются 22%, и разрыв растёт с каждым поколением.

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

Есть и вторая проблема, потише. Эмбеддинги рисуют на одной схеме, attention на другой, feed-forward на третьей. Каждая картинка по отдельности честная, но вместе они не складываются в один объект, поэтому даже люди, которые отлично помнят, что «делает» внимание, не могут показать, где оно находится. Автор канала Inductive Bias собрал всё это в один объект: нарисовал языковую модель целиком, в реальных пропорциях, и прошёл её маршрут в том порядке, в котором модель сама им пользуется (видео разбора). Дальше этот маршрут целиком, от токенов до сэмплера. И заодно ответ на вопрос, почему классическая диаграмма не просто неточная, а с каждым годом всё более неточная.

Токены: модель не получает буквы

Языковая модель не видит текст. На вход ей подают список целых чисел, поэтому первое, что происходит с вашей фразой, это разбиение на токены из фиксированного словаря. У Qwen3 в словаре 151 936 записей, и любое сообщение, которое вы когда-либо отправите, должно быть собрано только из них. Фраза «The capital of Taiwan is» превращается в пять токенов.

Токен это не слово, и разница важнее, чем кажется. Слово strawberry в середине предложения это один токен, а в начале предложения то же самое слово распадается на три: один из кусочков тащит на себе пробел впереди себя, другой нет. Это не баг и не редкий крайний случай. Это то, чем токенизация является: схема сжатия, подогнанная под гигантский корпус текста, которая понятия не имеет, что такое слово.

Отсюда растут странности, которые все замечали. Модель не получает strawberry как последовательность букв, поэтому вопрос «сколько букв r в слове strawberry» просит её вспомнить факт о символе, которого она никогда не видела. С числами ещё хуже: 4096, размерность, из которой построена эта модель, приходит пятью отдельными токенами. Каждая цифра всегда идёт сама по себе, так что арифметика это не то, что модель читает, а то, что она вынуждена собирать заново. Даже собственное имя qwen это два токена.

Таблица эмбеддингов: 15% языковой модели это поиск

Пять чисел на входе должны стать чем-то, что умеет умножаться на матрицу. У модели есть таблица: одна строка на каждый токен словаря, и каждая строка длиной 4096 чисел. Вся операция это поиск строки, никаких вычислений. Выглядит скромно, но таблица не маленькая: 151 936 строк по 4096 чисел это 622 миллиона чисел, а вторая такая же таблица нужна на выходе. Вместе они занимают около 15% всего, что есть в модели. Пятнадцать процентов языковой модели это таблица поиска.

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

Дальше включается проблема: пока ничто в модели не знает о порядке слов. «Taiwan is the capital of» и «the capital of Taiwan is» дают одни и те же строки. Оригинальный трансформер решал это сложением с позиционным вектором, но так почти никто не делает уже много лет. Вместо сложения вектор поворачивают на угол, который зависит от позиции токена. Механизм называется rotary position embeddings, и причина его победы укладывается в одну фразу: угол между двумя токенами зависит только от расстояния между ними, а не от их мест. Относительная позиция достаётся бесплатно, без единого дополнительного параметра.

Как устроена LLM в миниатюре: один блок, повторённый 36 раз

Теперь можно отойти на шаг назад. Модель это 36 блоков, и они одинаковые. Не похожие, а именно одинаковые: та же разметка, те же размеры, те же операции, и только числа внутри разные. В блоке 4 и блоке 31 одно и то же число голов, одна и та же ширина, один и тот же порядок операций. Никакого отдельного дизайна для ранних и поздних слоёв нет. Если ранние и поздние слои в итоге занимаются разными вещами (а они занимаются), это результат обучения, а не архитектуры. В каждом блоке ровно две вещи: attention и feed-forward сеть. Всё, что вы слышали про трансформеры, так или иначе про эти две коробки и провод, который проходит мимо них.

Attention: единственное место, где токены смотрят друг на друга

Вектор токена до этого момента был одинок: Taiwan превратился в направление без всякой связи с capital или of. Attention это единственное место во всей модели, где одна позиция получает возможность посмотреть на другую. Тридцать шесть блоков, сотни матриц, и смешивание информации происходит ровно в одном из них.

Работает это так. Входящий вектор умножается на три разные матрицы, порождая query, key и value. Имена взяты из мира баз данных и помогают наполовину: query это то, что токен ищет, key это то, что токен предлагает, value это то, что он на самом деле отдаёт. Запрос каждого токена сравнивается с ключом каждого, скалярным произведением, по одному числу на пару. Большое число значит «эти двое друг для друга важны», маленькое значит «игнорируй».

В середине есть деталь, которая выглядит как уборка, а на деле не уборка. Перед нормализацией каждое произведение делится на квадратный корень из ширины головы: скалярные произведения длинных векторов получаются большими, а большие числа на входе в softmax насыщают его. Мягкое взвешивание превращается в жёсткий выбор без градиентов, и деление возвращает мягкость. Потом счётчики превращаются в веса с суммой единица, и выход каждого токена становится взвешенным средним чужих value.

Дальше идёт то, что на самом деле не оптимизация, а то, что определяет всю форму модели: половина сетки выбрасывается. Токену запрещено смотреть на всё, что идёт после него, причём не «приглушено», а минус бесконечность до softmax. Модель обучают предсказывать следующее слово, и модель, которая видит следующее слово, не учится ничему. Этот треугольник и есть причина, по которой генерация идёт слева направо. Не философия языка, а маска.

GQA и KV-кэш: почему внимание стоит денег

Есть две оптимизации, которые разделяют «модель, которую можно обслуживать» и «модель, которую нельзя». Первая: attention выполняется не один раз на блок, а 32 раза параллельно на разных срезах вектора. Тридцать две головы по 128 чисел дают ту же суммарную ширину, что и вектор. Это не дополнительная ёмкость, а та же ёмкость, разрезанная на части, и смысл в том, что одна операция внимания выдаёт одно взвешенное среднее, одно мнение о том, что важно, а 32 узких могут держать 32 разных мнения сразу.

Оговорка, которую добросовестные разборы обычно опускают: вам наверняка доводилось слышать, будто у каждой головы есть профессия, эта отслеживает синтаксис, та разрешает местоимения, третья копирует редкие слова. Часть этого правда, есть головы, которые действительно изолировали и показали, что они делают одну опознаваемую вещь. Но это меньшинство голов в меньшинстве моделей, и это куда сложнее, чем выглядят чистые примеры. Большинство голов не раскладывается в одно предложение. Безопасная формулировка скучная: 32 независимых шанса взвесить один и тот же контекст по-разному, а под что модель их приспособит, решает давление обучения.

Вторая оптимизация видна прямо в форме: запросов 32, а пар ключей и значений только восемь. Четыре головы запросов делят одну пару ключ-значение, и это не про качество, а про память. Когда модель генерирует текст, она не пересчитывает всё заново для каждого нового слова: ключи и значения, уже посчитанные раньше, хранятся и переиспользуются. Хранилище называется KV-кэш, и оно огромное. В этом разборе каждый сохранённый токен стоит 144 килобайта, а полный контекст это около 5,5 ГБ только под кэш одного разговора. Не веса модели, а разговор. Нетрудно догадаться, почему индустрия так одержима сокращением этого числа: уменьшение ключей и значений вчетверо режет счёт во столько же раз, и именно поэтому форма голов выглядит несимметричной.

Feed-forward: четыре пятых блока, о которых спорят до сих пор

Итак, внимание смешивает позиции и платит за это памятью, и при всём при этом оно меньшая половина блока. Внутри блока 193 миллиона параметров, и 151 из них в feed-forward сети, это 78%, тогда как attention достаётся 22%. Так было не всегда: у GPT-2 feed-forward занимал ровно две трети блока, и именно эту цифру до сих пор цитируют. Сдвинули баланс две вещи: гейтинг добавил третью матрицу туда, где раньше было две, а grouped query attention срезал ключи и значения до четверти. Никто не ставил целью сделать feed-forward доминирующим, это побочный эффект двух независимых решений об эффективности, которые толкали в одну сторону. В итоге стандартная диаграмма не просто неточная, она с каждым годом становится всё сильнее неточной.

Внутри feed-forward происходит следующее. Вектор в 4096 чисел поднимается вверх не одной матрицей, а двумя параллельными проекциями в 12 288 чисел. Каждое число это взвешенная сумма всех входов. Затем нелинейность, и она применяется только к одной из двух проекций: это гейт. Проекции перемножаются поэлементно, и там, где гейт близок к нулю, блок просто закрыт. Никакого смешивания внутри этой коробки нет: каждое число обрабатывается само по себе, вся работа делается матрицами. Третья матрица спускает 12 288 обратно в 4096, и на этом всё: два подъёма, нелинейность, перемножение и спуск.

А вот зачем это всё нужно, честный ответ: это один из самых нерешённых вопросов в области. Красивая версия гласит, что единицы в 12 288 это что-то вроде памяти «ключ-значение», где конкретные нейроны срабатывают на конкретные факты, а вторая матрица эти факты выписывает. У этой версии есть реальные доказательства. Но есть и свежая работа, которая её усложняет: трансформеры, обученные вообще без feed-forward сети, только более глубокий attention на сэкономленных параметрах, при выравнивании по числу параметров отстают на 0,006 ната, то есть примерно на четверть процента. Правда, это маленькие модели, меньше 90 миллионов параметров, и статья сама об этом говорит. Но вывод под этим лежит более острый: при равном размере feed-forward отвечает за знание. Разрыв проявляется на токенах, где контекст не даёт ничего и ответ нужно помнить. То есть параметры важны чрезвычайно, а их конкретная форма в коробке может значить куда меньше, чем подразумевает диаграмма.

Residual stream: канал, который почти никто не рисует

Attention и feed-forward описывают обычно как то, через что вектор проходит. Это стандартная картинка, и она неверна. Вектор не проходит через них, он идёт мимо. Attention читает поток, считает что-то и добавляет результат назад. Feed-forward читает поток, считает и добавляет назад. Ни один из них ничего не заменяет. Эта линия называется residual stream, остаточный поток, и это самая значимая вещь в архитектуре, которой почти ни одна диаграмма не даёт имени.

Из этого следуют две вещи разом. Вектор, который приходит в блок 36, всё ещё содержит эмбеддинг, найденный в блоке ноль: ничто не было перезаписано, всё только добавлялось. И каждый блок читает то, что записали все предыдущие. Семьдесят два компонента пишут в один общий канал в фиксированном порядке, и тут возникает вопрос, который область удивительно долго не хотела задавать всерьёз: как один вектор из 4096 чисел несёт всё, что хотят сказать 72 компонента, и не переписывают ли они друг друга? Короткий ответ: не вполне. Есть хорошие свидетельства, что модели упаковывают в канал куда больше признаков, чем в нём измерений, позволяя им перекрываться и терпя небольшие помехи. Забавная деталь: не похоже, чтобы это когда-то было осознанным дизайн-решением, просто однажды сработало и больше никогда не пересматривалось. Механизм при этом прост до неприличия, x плюс f от x, и он не менялся с 2015 года. Для этой области одиннадцать лет без изменений это геологическая эпоха.

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

Encoder, decoder, encoder-decoder: разница только в маске

Три слова, которые бросают так, будто это три разные архитектуры. Это не три архитектуры. Посмотрите, что меняется: маска. Только она. Разрешите треугольнику исчезнуть, и каждый токен увидит все остальные в обе стороны: это encoder. Он не умеет генерировать, он уже видел ответ, зато выдаёт представление всего отрывка сразу; так работает BERT 2018 года и многое из того, что тихо крутится в подборе результатов поиска. Оставьте треугольник на месте, и каждый токен видит только то, что было до него: это decoder, он умеет генерировать, потому что предсказание следующего токена для него единственная разрешённая работа. Склейте одно с другим, и получите оригинальный трансформер 2017 года и T5 после него.

Средний вариант какое-то время выглядел будущим: перевод действительно двусторонняя задача, и первыми большими Mixture of Experts моделями были именно encoder-decoder, GShard и Switch. Но средний вариант проиграл, и по не самой тонкой причине. Encoder-decoder должен знать, где кончается вход и начинается выход, а decoder не должен. У него один поток токенов, и он предсказывает следующий до бесконечности, не задумываясь, от вас токен пришёл или от него самого. Это оказалось более общая машина: инструкция, разговор, код, вызовы инструментов, всё это просто токены перед другими токенами. Каждая модель, которой вы сегодня генерируете текст, это правая ветка с одним и тем же блоком, одним и тем же потоком и одним и тем же треугольником маски. Энкодеры не умерли, они ушли работать в тихие места: эмбеддинги, поиск, reranking, туда, где нужно прочитать целиком и ничего не написать обратно.

Выход: модель не выбирает слова

Наверху стека 36 блоков прочитали и дописали поток. На выходе всё тот же вектор из 4096 чисел, переписанный 72 раза, всё ещё направление, всё ещё не слово. Его умножают на последнюю матрицу, зеркало таблицы из начала: 4096 чисел на входе, 151 936 на выходе, по одному счёту на каждый токен словаря. Эти счёты называются логитами и являются настоящим выходом языковой модели: не текст, а число для каждого возможного следующего куска текста. Softmax превращает их в вероятности, и дальше выбирает уже не модель, а обычный код без всякого обучения, сэмплер. Модель не выбирает слово. Она выдаёт распределение по 151 тысяче вариантов, из которого кто-то другой делает выбор.

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

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

Три замены: что произошло с архитектурой после 2025 года

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

Первая: feed-forward, те самые четыре пятых, нарезали на несколько сотен мелких копий, и для каждого токена запускаются две-три из них, остальные пропускаются. Число параметров взлетает, работа на токен почти нет. Это Mixture of Experts, и история у него куда более длинная и странная, чем принято рассказывать: она уходит в 1991 год, а версия, которой восхищаются сегодня, почти противоположна изначальной.

Вторая: attention. KV-кэш дорогой, grouped query attention срезал его вчетверо, но этого не хватило, поэтому атаковали саму операцию. Три четверти слоёв внимания в конфиге фронтирной открытой модели этого года это не attention в том виде, в каком он описан выше, а более дешёвая операция с памятью фиксированного размера, и только каждый четвёртый слой держит всю картину.

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

Три замены: feed-forward, attention, цикл. И ни одна из них не тронула residual stream. Каждая молча предполагает, что разделяемый аддитивный канал это правильный способ 72 компонентам разговаривать друг с другом. Этому предположению одиннадцать лет, и есть серьёзные работы, которые пытаются его сломать.

FAQ

Почему на схемах attention и feed-forward одинакового размера?

Диаграммы десятилетиями копируют друг друга с 2017 года, когда пропорции были ближе: у GPT-2 feed-forward занимал две трети блока. Гейтинг и grouped query attention сдвинули баланс до четырёх пятых, а схемы никто не обновил. Поэтому стандартный рисунок не просто неточный, а становится всё неточнее.

Что такое KV-кэш простыми словами?

При генерации текста модель хранит ключи и значения всех предыдущих токенов, чтобы не пересчитывать их для каждого нового слова. У Qwen3 каждый токен в кэше стоит около 144 килобайт, полный контекст это примерно 5,5 ГБ памяти на один разговор. Сокращение числа KV-голов вчетверо режет и этот счёт.

Чем encoder отличается от decoder?

Только маской внимания. Запрет смотреть вперёд превращает каждую модель в decoder, который умеет генерировать; его снятие даёт encoder, который читает текст целиком. Все генеративные модели сегодня decoder-only, а энкодеры остались в эмбеддингах, поиске и reranking.

Итог

Языковая модель это не дюжина схем, а один объект: таблица поиска, поворот за позицию, 36 одинаковых блоков, attention с его памятью, feed-forward с четырьмя пятыми параметров, поток, который никто не рисует, и треугольник маски, решающий, кто вы, энкодер или декодер. Как устроена LLM на самом деле, становится видно только когда все части собраны в одном масштабе, и главный сюрприз этой сборки в том, что attention намного меньше, чем его репутация.

Если хочется увидеть всё это одним движением и в деталях, оригинальный разбор Inductive Bias даёт именно такую картинку. А если интересно копнуть глубже в отдельные элементы, начните с вопроса: какой из них вы бы разобрали следующим?

← Все записи