Внутреннее устройство LLM: архитектура, обучение и генерация текста

Технический курс о том, как работают большие языковые модели изнутри — от токенизации до генерации текста. Материал подан в стиле «практик-практику»: без лишней теории, с фокусом на реальных инженерных принципах современных систем вроде ChatGPT.

1. Основы токенизации и векторизации текста

Основы токенизации и векторизации текста

Представьте, что вы приехали в страну, где никто не говорит по-русски, а вы не знаете местного языка. Первое, что вам нужен — переводчик, который превратит ваши слова в понятные местным жителям символы. Именно такую роль выполняет токенизация — процесс, без которого ни одна языковая модель не смогла бы обработать ни единого слова. И если вы думаете, что компьютер «читает» текст так же, как вы, — вас ждёт сюрприз.

Почему компьютер не понимает слова напрямую

Компьютер работает с числами. Совсем. Он не видит букву «к» — он видит число 1072 в кодировке UTF-8. Но для языковой модели этого мало: ей нужно не просто закодировать символы, а захватить смысловые единицы языка. Именно поэтому на вход LLM текст поступает не посимвольно и не пословно, а через токены — промежуточные единицы, которые могут быть целым словом, частью слова или даже отдельной буквой.

Зачем нужна эта сложность? Если разбивать текст на слова, словарь английского языка потребует сотни тысяч записей, а редкие формы слов вроде «антидискриминационный» будут встречаться единожды и не дадут модели ничего полезного. Если разбивать на символы — модель будет думать слишком долго, обрабатывая каждую букву отдельно. Токенизация — это компромисс между размером словаря и информативностью каждой единицы.

Как работает BPE: алгоритм, который строит словарь сам

Самый распространённый метод токенизации в современных LLM — Byte Pair Encoding (BPE), адаптированный из алгоритма сжатия данных 1990-х годов. Принцип работы удивительно прост:

  • Начинаем с базового словаря: все отдельные символы (буквы, цифры, пробелы, знаки препинания).
  • Проходим по всему обучающему корпусу и находим пару соседних токенов, которая встречается чаще всего.
  • Объединяем эту пару в новый токен и добавляем его в словарь.
  • Повторяем шаги 2–3, пока словарь не достигнет заданного размера.
  • Допустим, в корпусе часто встречается слово «трансформер». На первой итерации алгоритм может объединить «т» и «р» в «тр», затем «а» и «н» в «ан», затем «тр» и «ан» в «тран» и так далее. В итоге частотные слова целиком попадут в словарь как один токен, а редкие будут разбиты на знакомые подслова.

    > BPE — это не магия, а статистика. Алгоритм не знает русского или английского языка. Он просто считает, какие кусочки текста слипаются чаще остальных.

    На практике размер словаря современных моделей составляет от 32 000 до 128 000 токенов. Для сравнения: словарь русского языка Ожегова содержит около 80 000 слов. Но токены — это не слова: один токен может быть словом «и», а другой — подстрокой «ционный».

    От токена к числу: эмбеддинги

    После токенизации каждый токен получает уникальный числовой идентификатор — индекс в словаре. Слово «привет» может стать числом 45 217. Но это число — просто адрес в словаре, оно не несёт никакой информации о смысле. Число 45 217 не «близко» к числу 45 218 по значению — это просто соседние строки в таблице.

    Здесь в игру вступают эмбеддинги — векторные представления токенов. Каждому индексу из словаря сопоставляется вектор из сотен или тысяч вещественных чисел (типичная размерность — от 768 до 12 288). Эти векторы хранятся в матрице эмбеддингов — по сути, в гигантской таблице размером «размер словаря × размерность».

    | Параметр | Типичное значение | |---|---| | Размер словаря | 32 000 – 128 000 | | Размерность эмбеддинга | 768 – 12 288 | | Размер матрицы эмбеддингов | от 25 млн до 1,5 млрд чисел |

    Матрица эмбеддингов — это обучаемый параметр. В начале обучения векторы инициализируются случайно, а затем корректируются градиентным спуском. Через миллиарды примеров модель «настраивает» эти векторы так, что семантически близкие слова оказываются рядом в многомерном пространстве.

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

    Что значит «рядом» в пространстве из тысяч измерений? Представьте карту метро, но вместо двух осей (север-юг, запад-восток) у вас тысячи осей. Каждая ось — это некое абстрактное свойство: «животность», «размер», «цвет», «эмоциональная окраска», «формальность» и так далее. Вектор слова «кот» будет близок к вектору «собака» (оба — домашние животные), но далёк от вектора «квантовая механика».

    Классический пример: если взять вектор «король», вычесть вектор «мужчина» и прибавить вектор «женщина», результат окажется рядом с вектором «королева». Это не случайность — модель действительно выучила гендерное измерение как одну из осей пространства.

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

    Позиционные эмбеддинги: порядок имеет значение

    Есть ещё одна проблема. Архитектура трансформера обрабатывает все токены одновременно, а не последовательно. Это даёт огромное преимущество в скорости, но создаёт вопрос: как модель узнает, что «собака укусила человека» — это не то же самое, что «человек укусил собаку»?

    Ответ — позиционные эмбеддинги. К каждому токену прибавляется дополнительный вектор, кодирующий его позицию в последовательности. В оригинальной статье «Attention Is All You Need» использовались синусоидальные функции, но в современных моделях чаще применяются обучаемые позиционные эмбеддинги — отдельная матрица, где каждой позиции (от 0 до максимальной длины контекста) соответствует свой вектор.

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

    2. Архитектура трансформера и механизм внимания

    Архитектура трансформера и механизм внимания

    Почему именно трансформер, а не рекуррентная сеть, которая «помнит» предыдущие слова? Ответ кроется в одном инженерном решении, которое изменило всю индустрию: трансформер обрабатывает все токены параллельно, а не по одному. Это значит, что обучение модели на 100 миллиардах параметров занимает недели, а не десятилетия. Но как модель при этом улавливает связи между словами, стоящими далеко друг от друга? Разберёмся.

    Блок трансформера: из чего состоит один слой

    Стандартный блок трансформера (transformer block) — это повторяющаяся структура, которая штабелируется десятки или сотни раз. Каждый блок содержит два ключевых компонента:

  • Слой внимания (attention layer) — определяет, какие токены должны обмениваться информацией.
  • Feed-Forward Network (FFN) — по отдельности обрабатывает каждый токен после внимания, добавляя нелинейность.
  • Вокруг каждого компонента работает нормализация (LayerNorm или RMSNorm) и остаточное соединение (residual connection) — прямой «мостик», который пропускает входной сигнал мимо блока и складывает его с выходом. Residual connections критически важны: без них градиенты затухают при прохождении через десятки слоёв, и модель перестаёт обучаться.

    Self-Attention: как токены «смотрят» друг на друга

    Это сердце трансформера. Механизм самовнимания (self-attention) позволяет каждому токену «спросить» у всех остальных токенов последовательности: «Насколько ты важен для понимания меня?»

    Для каждого токена вычисляются три вектора из его эмбеддинга:

  • Query (Q) — «что я ищу?»
  • Key (K) — «что я могу предложить?»
  • Value (V) — «какую информацию я передам?»
  • Эти векторы получаются умножением эмбеддинга на три обучаемые матрицы проекции , , . Затем вычисляется оценка внимания между каждой парой токенов:

    Разберём по шагам:

  • — скалярное произведение запроса каждого токена на ключи всех остальных. Чем больше результат, тем «внимательнее» токен А к токену Б.
  • Деление на (квадратный корень из размерности ключа) — предотвращает слишком большие значения, которые «размазывают» softmax.
  • Softmax превращает сырые оценки в вероятности от 0 до 1, суммирующиеся к 1.
  • Умножение на — взвешенная сумма значений: каждый токен получает долю информации от тех, кто ему «важен».
  • Предложение «Маша любит кошек, потому что они пушистые»: когда модель обрабатывает слово «они», механизм внимания присвоит высокий вес токену «кошек» — именно на него ссылается местоимение. При этом «Маша» получит низкий вес, хотя стоит ближе.

    Маскированное внимание: запрет заглядывать в будущее

    В режиме генерации (когда модель предсказывает следующий токен) есть фундаментальное ограничение: токен на позиции не должен «видеть» токены на позициях . Иначе модель просто подсмотрит ответ.

    Для этого используется маскированное внимание (masked attention или causal attention): перед softmax в матрицу оценок добавляется маска — на позициях, где токен «смотрит вперёд», ставится . После softmax эти позиции получают вероятность, близкую к нулю, и фактически не участвуют в вычислениях.

    | Тип внимания | Где используется | Может ли токен видеть будущее? | |---|---|---| | Полное (bidirectional) | Энкодер (BERT, T5) | Да | | Маскированное (causal) | Декодер (GPT-подобные) | Нет | | Кросс-attention | Между энкодером и декодером | Только из энкодера |

    Multi-Head Attention: несколько точек зрения одновременно

    Один механизм внимания может уловить только один тип связи за раз. Многоголовое внимание (multi-head attention) запускает несколько параллельных «голов» — каждый head работает со своими матрицами , , и обучается ловить разные паттерны.

    Например, в предложении «Илон Маск основал SpaceX в 2002 году» одна голова может отслеживать грамматические связи (подлежащее — сказуемое), вторая — именованные сущности (Илон Маск → SpaceX), третья — временные маркеры (2002 → основал).

    Результаты всех голов конкатенируются и проецируются через ещё одну матрицу . Если размерность эмбеддинга 4096 и голов 32, каждая голова работает с векторами размерности 128.

    > Multi-head — это не принципиально новая способность, а оптимизация: несколько узких «линз» работают эффективнее одной широкой.

    FFN: второй ключевой компонент блока

    После внимания каждый токен проходит через Feed-Forward Network — двухслойную нейросеть с нелинейной активацией (обычно SwiGLU или GELU). FFN расширяет размерность (например, с 4096 до 11 000), применяет активацию, затем сжимает обратно.

    Если attention отвечает за обмен информацией между токенами, то FFN — за «переработку» этой информации внутри каждого токена. Есть гипотеза, что FFN работает как «фактологическая память» модели: веса FFN хранят знания, усвоенные при обучении.

    Стек слоёв: почему глубина решает

    Современные LLM содержат от 32 до 120+ слоёв трансформера. Каждый слой — это ещё один проход внимания и FFN. На ранних слоях модель улавливает синтаксис и локальные паттерны, на средних — семантические связи, на глубоких — абстрактные рассуждения и логические цепочки.

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

    3. Процесс обучения и предсказание следующего токена

    Процесс обучения и предсказание следующего токена

    Модель с миллиардами параметров не рождается «умной». Она начинает как гигантский генератор случайного текста, который путает «кот» с «код» и не может закончить предложение. Превращение этого хаоса в систему, способную вести диалог и писать код, — результат двухэтапного обучения, каждый этап которого решает свою задачу. Разберём, что именно происходит на каждом этапе и почему без одного из них модель остаётся бесполезной.

    Предобучение: учимся предсказывать следующий токен

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

    Почему такая простая задача даёт такие впечатляющие результаты? Потому что для точного предсказания следующего токена модели нужно выучить грамматику, факты, логику, стиль и даже элементы здравого смысла. Чтобы предсказать последнее слово в «Столица Франции — это ___», модель должна «знать» географию. Чтобы завершить сложную юридическую формулировку — понимать синтаксис.

    Функция потерь: как модель понимает, что ошиблась

    Обучение работает через кросс-энтропию (cross-entropy loss). Модель для каждого токена выдаёт распределение вероятностей по всему словарю. Если словарь содержит 50 000 токенов, модель говорит: «Следующий токен — это "столица" с вероятностью 0,003, "собака" с вероятностью 0,0001, ...». Функция потерь штрафует модель за то, что правильный токен получает низкую вероятность.

    Градиентный спуск (обычно AdamW) обновляет все параметры модели — матрицы внимания, FFN, эмбеддинги — чтобы на следующем шаге правильный токен стал чуть более вероятным. Этот процесс повторяется на триллионах токенов.

    Масштаб обучающих данных

    Предобучение современных моделей потребляет корпуса объёмом от 1 до 30 триллионов токенов. Это книги, статьи, код из репозиториев, веб-страницы, научные публикации. Для сравнения: вся Википедия на английском языке — это примерно 4 миллиарда токенов. Модель «прочитывает» эквивалент тысяч Википедий.

    | Параметр | Типичный диапазон | |---|---| | Объём обучающих данных | 1–30 трлн токенов | | Количество параметров | 7 млрд – 405 млрд | | Стоимость обучения | от 2 млн до 100 млн долл. | | Время обучения | от нескольких дней до нескольких месяцев |

    Fine-tuning: превращаем энциклопедию в помощника

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

    Fine-tuning (дообучение) решает эту проблему. Модель обучается на небольших, но тщательно подобранных датасетах, содержащих пары «запрос — желаемый ответ». Здесь используется Supervised Fine-Tuning (SFT): модель видит примеры диалогов и учится генерировать полезные, структурированные ответы.

    RLHF: учим модели на основе обратной связи человека

    SFT — это необходимый, но недостаточный шаг. Человеческие оценки качества ответов гораздо тоньше, чем «правильно/неправильно». Модель может дать фактически верный, но токсичный ответ. Или полезный, но слишком длинный.

    Reinforcement Learning from Human Feedback (RLHF) добавляет ещё один этап:

  • Модель генерирует несколько вариантов ответа на один запрос.
  • Человек-рейтер ранжирует варианты от лучшего к худшему.
  • На основе этих ранжировок обучается модель вознаграждения (reward model) — отдельная нейросеть, которая оценивает качество ответа.
  • Основная модель дообучается с помощью PPO (Proximal Policy Optimization) — алгоритма обучения с подкреплением, который максимизирует оценку reward model.
  • В 2024–2025 годах появился альтернативный подход DPO (Direct Preference Optimization), который убирает отдельную reward model и обучает модель напрямую на парах «предпочтительный ответ — непредпочтительный ответ». DPO проще в реализации и стабильнее в обучении.

    Почему предсказание следующего токена — это не просто «догадка»

    Важно понимать: модель не выбирает токен случайно. На этапе предобучения она выучивает распределение вероятностей — функцию, которая для каждого контекста отображает, насколько вероятен каждый из 50 000+ токенов словаря. Это распределение кодирует статистические закономерности языка: после «доброе» с высокой вероятностью идёт «утро», после «import» — название библиотеки, после открывающей скобки — выражение или закрывающая скобка.

    Модель не «думает» в человеческом смысле. Она экстраполирует паттерны, заученные на триллионах примеров. Но масштаб этих паттернов настолько велик, что результат выглядит как понимание.

    4. От логитов к тексту: декодинг и генерация

    От логитов к тексту: декодинг и генерация

    Последний слой трансформера выдал вектор размерностью 4096. Что дальше? Как из этого набора чисел получается слово «привет»? Этот переход — от внутреннего представления к конкретному токену — называется декодинг, и именно здесь принимается единственное «творческое» решение во всей работе модели. Всё остальное — детерминированная математика, а здесь — управляемый случай.

    Unembedding: от скрытого вектора к распределению вероятностей

    После прохождения всех слоёв трансформера у каждого токена есть скрытый вектор (hidden state) — плотное числовое представление, содержащее всю контекстную информацию. Чтобы превратить его в предсказание, применяется unembedding layer — матрица размерности «размерность эмбеддинга × размер словаря».

    Умножение скрытного вектора на эту матрицу даёт логиты — по одному числу для каждого токена в словаре. Если словарь содержит 50 000 токенов, получается вектор из 50 000 чисел. Эти числа — не вероятности. Они могут быть отрицательными, больше единицы, чем угодно. Чтобы превратить их в вероятности, применяется функция softmax:

    где — логит для токена , — размер словаря, — вероятность токена .

    После softmax получается распределение, где все значения от 0 до 1 и суммируются к 1. Токен с наибольшей вероятностью — самый «очевидный» продолжение текста.

    > Unembedding — это, по сути, транспонированная матрица эмбеддингов. Во многих моделях веса эмбеддинга и unembedding-а共享 (tied weights), что экономит память.

    Стратегии выбора токена: temperature, top-k, top-p

    Если всегда выбирать токен с максимальной вероятностью (greedy decoding), текст получается грамматически правильным, но скучным и повторяющимся. Модель будет ходить по кругу: «Я думаю, что я думаю, что я думаю...». Чтобы генерация была разнообразной и живой, применяются стратегии сэмплинга.

    Temperature (температура)

    Перед softmax логиты делятся на параметр — температуру:

  • — стандартное распределение, как есть.
  • (например, 0.3) — распределение становится «острее», модель чаще выбирает вероятные токены. Текст детерминированнее, факты точнее.
  • (например, 1.5) — распределение «сглаживается», маловероятные токены получают больше шансов. Текст креативнее, но выше риск бессмыслицы.
  • Top-k сэмплинг

    Модель сортирует токены по вероятности и оставляет только лучших. Остальные обнуляются, и выборка идёт из этого сокращённого набора. При модель никогда не выберет 49 950-й по вероятности токен — даже если он теоретически возможен.

    Top-p (nucleus) сэмплинг

    Более гибкий подход: модель берёт минимальный набор токенов, чьи вероятности суммируются до порога (обычно 0.9 или 0.95). В контексте, где распределение «острое» (один токен явно вероятнее остальных), набор будет маленьким. В контексте с высокой неопределённостью (например, конец открытого вопроса) — набор расширится.

    | Стратегия | Когда использовать | Риск | |---|---|---| | Greedy () | Факты, код, переводы | Повторы, отсутствие креативности | | Низкая температура () | Технические ответы | Может «застрять» на шаблоне | | Высокая температура () | Генерация идей, художественный текст | Бессмыслица, галлюцинации | | Top-p = 0.95 | Универсальный выбор | Зависит от контекста |

    На практике часто комбинируют: например, temperature = 0.7 + top-p = 0.9.

    Autoregressive генерация: один токен за раз

    Генерация текста — это авторегрессионный процесс. Модель предсказывает один токен, добавляет его в последовательность, затем предсказывает следующий, учитывая все предыдущие. И так до тех пор, пока не будет сгенерирован специальный токен конца последовательности (EOS) или не достигнут лимит длины.

    Ключевой инженерный приём — KV-кэш (key-value cache). При генерации каждого нового токена модель вычисляет attention. Но ключи и значения для уже обработанных токенов не меняются. Поэтому модель кэширует их и при каждом шаге вычисляет Q, K, V только для нового токена, а attention считает между новым Q и всеми закэшированными K.

    Без KV-кэша генерация 1000 токенов потребовала бы пересчёта внимания для всей последовательности на каждом шаге — сложность по длине. С кэшем — на каждый шаг, что даёт ускорение в сотни раз.

    Почему модель «галлюцинирует»

    Механизм генерации объясняет феномен галлюцинаций — ситуации, когда модель выдаёт правдопозвучащую, но фактически неверную информацию. Модель не проверяет факты в базе данных. Она предсказывает наиболее вероятное продолжение текста. Если в обучающих данных часто встречается ложная корреляция (например, вымышленная цитата, приписываемая реальному человеку), модель с высокой вероятностью её воспроизведёт.

    Это не баг, а фундаментальное свойство авторегрессионной генерации: модель оптимизирует правдоподобие текста, а не истинность фактов.

    5. Инженерные ограничения и реальность работы LLM

    Инженерные ограничения и реальность работы LLM

    Видеокарта за 2000 долл. рендерит киберпанк-город в реальном времени с трассировкой лучей, но генерирует текст со скоростью печатной машинки. Почему? Потому что GPU — это не спорткар, а грузовик: он проектирован для огромного параллелизма, а не для минимальной задержки. И именно это определяет все инженерные компромиссы, с которыми сталкиваются разработчики LLM. Разберём главные ограничения, от которых зависит реальная работа моделей.

    Память: главный bottleneck

    Каждый параметр модели занимает память. Модель с 70 миллиардами параметров в формате FP16 (2 байта на параметр) требует 140 ГБ видеопамяти только для хранения весов. Добавьте KV-кэш, активации и служебные буферы — и вы получаете 180–200 ГБ. Для сравнения: топовая потребительская видеокарта имеет 24 ГБ.

    Отсюда вытекают все основные инженерные решения:

  • Квантизация — снижение точности весов с FP16 (2 байта) до INT8 (1 байт) или даже INT4 (0.5 байта). Модель на 70B параметров в INT4 занимает ~35 ГБ — помещается в две потребительские карты.
  • Распределение по GPU — модель разбивается на части (tensor parallelism) или слои (pipeline parallelism) и загружается на несколько GPU одновременно.
  • Offloading — часть весов или KV-кэша выгружается в оперативную память CPU и подгружается по мере необходимости. Работает, но медленно.
  • | Формат | Байт на параметр | 70B модель | Потеря качества | |---|---|---|---| | FP32 | 4 | 280 ГБ | Нет | | FP16 / BF16 | 2 | 140 ГБ | Минимальная | | INT8 | 1 | 70 ГБ | Незначительная | | INT4 | 0.5 | 35 ГБ | Заметная на сложных задачах |

    KV-кэш: скрытый потребитель памяти

    В предыдущей статье мы обсудили KV-кэш как приём ускорения генерации. Но у него есть оборотная сторона: он растёт с каждым новым токеном. Для контекста длиной 32 000 токенов и модели с 32 слоями, 32 головами внимания и размерностью головы 128 KV-кэш занимает единицы гигабайт на каждый запрос. При обслуживании сотен пользователей одновременно это превращается в серьёзную проблему.

    Инженеры борются с этим несколькими способами:

  • GQA (Grouped-Query Attention) — несколько голов внимания共享 одни и те же K и V, что сокращает кэш в 4–8 раз.
  • MQA (Multi-Query Attention) — крайний случай: все головы используют одинаковые K и V.
  • PagedAttention — управление KV-кэшем как виртуальной памятью в ОС: вместо непрерывного блока выделяются страницы, что снижает фрагментацию.
  • Латентность vs. пропускная способность

    GPU оптимизирован для throughput (пропускной способности) — количества токенов в секунду при обработке большой пачки запросов. Но пользователю важна latency (задержка) — время до первого токена ответа. Эти два показателя конфликтуют.

    При batch size = 1 (один пользователь) GPU простаивает: тысячи ядер ждут, пока несколько из них обработают один запрос. При batch size = 256 GPU загружен максимально, но каждый пользователь ждёт дольше своей очереди.

    > Оптимальная точка зависит от сценария: чат-бот оптимизирует latency, а пакетная обработка документов — throughput.

    Контекстное окно: дешевле не значит лучше

    Увеличение контекстного окна (от 4 096 токенов в ранних моделях до 128 000 и более) выглядит как чистое улучшение. Но цена растёт квадратично: сложность attention — по длине последовательности. Контекст в 100 000 токенов требует в 600 раз больше вычислений, чем 4 096.

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

    Mixture of Experts: как обойти ограничения масштаба

    Все крупные модели 2024–2026 годов перешли на архитектуру Mixture of Experts (MoE). Вместо того чтобы активировать все параметры при каждом токене, модель содержит «экспертов» — подсети — и на каждом шаге активирует только несколько из них.

    Модель с 400 миллиарда параметров, но 8 экспертами и активацией 2 из них, при генерации задействует только ~100 миллиарда параметров. Это даёт качество полной модели при скорости и потреблении памяти значительно меньшей.

    > MoE — это не принципиально новая способность, а инженерная оптимизация: вы получаете качество большой модели с затратами маленькой.

    Реальность инференса: что происходит на сервере

    Когда вы отправляете запрос в LLM-сервис, под капотом происходит следующее:

  • Токенизация на CPU — быстрая операция, не требующая GPU.
  • Prefill — обработка всего входного контекста на GPU. Это параллельная операция, и она быстрая.
  • Decode — генерация выходных токенов по одному. Это последовательная операция, и она медленная.
  • Сэмплинг — выбор токена из распределения вероятностей на CPU.
  • Детокенизация — превращение индекса токена обратно в текст.
  • Шаг 3 — узкое место. Каждый токен требует полного прохода через все слои модели, и эти проходы нельзя распараллелить (каждый следующий токен зависит от предыдущего). Именно поэтому генерация длинного ответа занимает секунды, а не миллисекунды.

    Quantization, speculative decoding и другие оптимизации

    Инженерное сообщество активно ищет способы ускорения:

  • Speculative decoding — маленькая модель быстро генерирует «черновик» из нескольких токенов, а большая модель проверяет их пачкой. Если «черновик» верен — принимается целиком, если нет — генерируется правильный токен. Ускорение в 2–3 раза без потери качества.
  • FlashAttention — переписывает вычисление attention так, чтобы минимизировать чтения из видеопамяти (которые в сотни раз медленнее вычислений). Не меняет математику, но даёт ускорение в 2–4 раза.
  • Continuous batching — новые запросы подмешиваются в текущий батч, не дожидаясь завершения всех текущих. Снижает простой GPU.
  • Каждая из этих оптимизаций — результат десятков инженерных часов и глубокого понимания архитектуры GPU. LLM — это не только математика, но и искусство заставить железо работать на пределе возможностей.