localaiforum
Войти
Руководство › Основы

Внутри трансформера

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

Остаточный поток

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

x = embed(token_ids) + positions      # токены становятся векторами (dim ~4k)
for layer in range(N):                # N ≈ 32 для 8B-модели
    x = x + attention(x)              # токены обмениваются информацией
    x = x + ffn(x)                    # каждый токен преобразует сам себя
logits = unembed(x[-1])               # последняя позиция → оценка на каждую запись словаря
p = softmax(logits)                   # вероятность по каждому следующему токену
  • Эмбеддинг: каждый ID токена индексирует обученную таблицу векторов. Позиционная информация подмешивается (ротационные эмбеддинги в современных моделях), поэтому «собака кусает человека» отличается от «человек кусает собаку».
  • Слои одинаковы по форме, различны по содержанию. Ранние слои отвечают за синтаксис и поверхностные паттерны; глубокие несут смысл, факты и поведенческие навыки.
  • Unembedding: финальный вектор сравнивается с каждой записью словаря; softmax превращает оценки в вероятности. Сэмплирование выбирает одну (сэмплирование).

Self-attention на четырёх токенах

Механизм обмена. Вектор каждого токена порождает три производных вектора: запрос (что я ищу), ключ (что я рекламирую) и значение (что я отдаю, если меня выбрали). Предложение: "The cat sat on". Что должна подтянуть позиция "sat"?

token:          The     cat     sat     on
q·k scores:     1.2     4.1     3.0     0.4      (скалярные произведения, иллюстративно)
softmax →        0.05    0.60    0.31   0.04     (веса в сумме дают 1.0)

output("sat") = 0.05·v(The) + 0.60·v(cat) + 0.31·v(sat) + 0.04·v(on)

"sat" сильнее всего смотрит на "cat" — подлежащее, которое ей нужно. Каждая позиция делает это одновременно. Одно ограничение превращает это в языковую модель: каузальная маскировка — каждый токен может смотреть только на более ранние, никогда на поздние, поэтому один проход обучает все предсказания следующего токена в последовательности сразу.

Это весь математический инструментарий: оценки похожести (скалярные произведения), нормализованные в смесь (softmax), поверх векторов-значений.

Как рецепт — одна голова внимания на одной позиции:

  1. Вычислить векторы запроса, ключа и значения для каждого токена.
  2. Скалярно умножить запрос на ключ каждого более раннего токена; поделить на √(head_dim).
  3. Прогнать softmax по оценкам — получить веса, сумма которых 1.
  4. Выдать взвешенную сумму значений этих токенов.
  5. Склеить выходы всех голов и спроектировать — это и есть вклад внимания слоя.

Многоголовость: паттерны параллельно

Одна голова = одна тройка запрос/ключ/значение = один тип связей, который она может выражать (подлежащее↔сказуемое, прилагательное↔существительное, кореферентность). Слои гоняют много голов параллельно (например 32) на низкоразмерных срезах и склеивают результаты. Больше голов — больше типов связей на слой: широта паттернов, а не глубина мышления.

  • Головы фиксируются при обучении; «мышление» между позициями — то, что внимание записывает обратно в остаточный поток.
  • Размер головы (например 128) × головы (например 32) = скрытая размерность (4096): головы — параллельные срезы той же конвейерной ленты, а не отдельные модели.

FFN: где живут параметры

Вторая половина каждого слоя — сеть из двух матриц, применяемая к каждому токену независимо: расширить вектор (~4×), нелинейность, спроектировать обратно. В типичной плотной модели примерно две трети всех параметров живут здесь, а не во внимании. Полезная интуиция: key-value-память — первая матрица хранит паттерны для обнаружения, вторая — что добавить на ленту, когда паттерн срабатывает. Значительная часть того, что люди называют «фактами модели», хранится в весах FFN (см. параметры).

Компонент Доля параметров (типичная плотная 7–9B)
Внимание (Q, K, V, O) ~10–15%
FFN ~60–70%
Эмбеддинги + выходная голова ~10–25% (растёт с размером словаря)

Посчитайте параметры сами

Карточки моделей публикуют пять чисел; перемножьте их — и получите количество параметров. Для реальной открытой модели класса 8B (32 слоя, скрытая размерность 4096, 32 головы с 8 KV-головами, ширина FFN 14336, словарь ~128k):

attention/layer:  q: 4096×4096 + k,v: 2×(4096×1024) + o: 4096×4096
                  ≈ 42M на слой × 32 слоя            ≈ 1.3B
FFN/layer:        3 × (4096×14336), gated ≈ 176M × 32     ≈ 5.6B
embeddings:       2 × (128k × 4096), input + output head  ≈ 1.1B
total                                                     ≈ 8.0B

Арифметика совпадает с «8B» на карточке модели почти точно. Отсюда два урока: FFN доминирует в количестве параметров (а значит, и в бюджете памяти), и большой словарь стоит около миллиарда параметров ещё до первого слоя — часть причины, почему мультиязычные модели с большими словарями весят больше, чем подсказывают их плотные собратья.

GQA: починка цены внимания

Во время генерации каждый новый токен должен прочитать ключи и значения каждого предыдущего токена — они хранятся в KV-кэше. Оригинальное многоголовое внимание хранит по одному K и одному V на голову на токен. Grouped-query attention (GQA) делит горстку KV-голов между многими головами запросов (например 32 головы запросов, 8 KV-голов), сжимая кэш в 4 раза при ничтожной потере качества. Multi-query attention (MQA) делит одну KV-голову. Фактически каждая современная открытая модель использует GQA; эта экономия — большая часть причины, почему длинный контекст вообще применим (KV-кэш).

Длина контекста = диапазон внимания

Внимание позволяет каждому токену видеть каждый более ранний токен, поэтому вычисления префилла растут квадратично с длиной промпта, а кэш растёт линейно с каждым сгенерированным токеном. Модель с «128k контекста» добирается туда позиционными трюками и обученным расширением, и качество у дальнего края окна обычно хуже, чем у начала. Заполняйте длинные окна только когда необходимо.

Проверьте сами: положите факт в начало окна, заполните середину шумом, спросите о нём. Большинство моделей проходят у начала и конца окна и проваливаются в середине — известный паттерн «потерянных в середине» (lost in the middle). Относитесь к заявленному контексту как к ёмкости, а не гарантии качества.

Почему этого достаточно

Из одной этой структуры выводятся практические факты: потребность в памяти = веса + KV-кэш (математика VRAM); скорость декодирования = как быстро можно перечитать веса (префилл и декодирование); возможности следуют за количеством параметров (параметры); цена контекста = диапазон внимания. Архитектура проста — миллиарды обученных весов внутри неё и есть та часть, которую никто не мог написать руками.

Связанные разделы: что такое LLM · KV-кэш · префилл и декодирование · параметры