Гайд по LLM-инжинирингу: 45 концепций для production-систем

Автоматический перевод Эта статья была автоматически переведена с оригинальной английской версии.

LLM-сервис может нарушить свой latency SLO, если декодирование ограничено пропускной способностью памяти, KV-кэш израсходовал бюджет батча или очередь маскирует обе причины. Файн-тюнинг может завершиться сбоем по другой версии той же проблемы: состояние модели больше не помещается в доступное железо. Правильное исправление определяется боттлнеком, а не самым длинным списком техник.

Это справочник для инженеров, которые уже знакомы с базовыми концепциями ML и систем и хотят связать production-симптом с соответствующей частью стека. В нём разобраны 45 концепций из областей железа, инференса, обучения, деплоя, приложений и эксплуатации. Используйте нужный раздел, чтобы определить механизм, его практическое следствие и условие, ограничивающее приведённый результат; затем изучите связанный подробный материал или проведите собственный бенчмарк, чтобы принять решение.

Примечание о границах охвата

Это справочник, а не линейный учебник. Начните с части, которая соответствует текущему решению.

ЧастьТемыРазделы
I — Основы аппаратного обеспеченияМодель Roofline, память GPU, глоссарий по железу1–3
II — Основы инференсаЛатентность, throughput, KV-кэш, аттеншн, квантизация4–9
III — Оптимизации инференсаCUDA-ядра, FlashAttention, батчинг, PagedAttention, speculative decoding10–17
IV — Архитектура моделиВнутреннее устройство Transformer, decoder-only, MoE, токенизация, контекстные окна18–22
V — Обучение и alignmentПретрейнинг, LoRA, mixed precision, ZeRO, scaling laws, RLHF/DPO/GRPO, дистилляция23–32
VI — Масштабирование и деплойПараллелизм, фреймворки сервинга, выбор GPU, роутинг33–36
VII — ПриложенияЭмбеддинги, RAG, ИИ-агенты, промпт-инжиниринг37–40
VIII — Эксплуатация в productionRate limiting, режимы отказа, мониторинг, стоимость, планирование ёмкости41–45

Как использовать этот гайд как хаб

Эта страница намеренно охватывает широкий круг тем. Используйте её как карту, а когда решение станет конкретным, переходите к подробным материалам.

Если вы решаете…Начните сЗатем прочитайте
Как сервить модельОсновы инференса и деплойРуководство по сервингу LoRAX
Нужно ли выполнять файн-тюнингОбучение и alignmentРуководство по файн-тюнингу LLM
Как встроить retrieval в приложениеЭмбеддинги и RAGМетрики эвала RAG
Как работают агентные системыИИ-агенты и промпт-инжинирингЦиклы ризонинга ИИ-агентов
Как ранжировать результаты поискаЭмбеддинги и реранкингСтек ранжирования поиска

Начните с боттлнека, используйте минимальный стек, который позволяет его выявить, проведите бенчмарк на реальной нагрузке и добавляйте сложность только там, где это оправдано численными показателями.


Часть I — Основы аппаратного обеспечения

Арифметическая интенсивность, иерархия памяти GPU и аппаратные термины из этой части объясняют многие решения, которые будут рассмотрены далее в руководстве.

1. Ограничение памятью и ограничение вычислениями: модель roofline

Отправная точка для оценки производительности LLM — арифметическая интенсивность: сколько полезных вычислений выполняет GPU на каждый байт данных, загруженный из памяти? Это соотношение определяет, будет ли операция ограничена вычислениями (ожиданием процессора) или ограничена памятью (ожиданием загрузки данных).

У каждого GPU есть порог «критической интенсивности», при котором пиковая вычислительная производительность равна пропускной способности памяти. Для NVIDIA H100 SXM с плотными Tensor Core в форматах BF16 или FP16 (989 TFLOPS; в спецификации на 1 979 TFLOPS предполагается структурированная разреженность):

989 TFLOPS3.35 TB/s295 FLOPs/byte\frac{989 \text{ TFLOPS}}{3.35 \text{ TB/s}} \approx 295 \text{ FLOPs/byte}

На графике roofline декодирование с batch size 1 находится ниже порога отношения вычислений к пропускной способности H100, а длинный или батчевый префилл — ближе к области, ограниченной вычислениями.На графике roofline декодирование с batch size 1 находится ниже порога отношения вычислений к пропускной способности H100, а длинный или батчевый префилл — ближе к области, ограниченной вычислениями.

Декодирование с batch size 1 и длинный либо достаточно крупный батчевый префилл обычно находятся по разные стороны этого порога:

  • Декодирование ограничено памятью. Последовательная генерация токенов требует загрузки многогигабайтной матрицы весов из памяти для умножения на один новый токен. В упрощённом анализе для плотного 16-битного режима и batch size 1 операция имеет около 1 FLOP/байт — примерно в 295 раз ниже порога roofline для H100. Именно этот разрыв объясняет, почему в таком режиме декодирование не может приблизиться к пиковой вычислительной производительности.
  • Длинный или достаточно крупный батчевый префилл часто ограничен вычислениями. Обработка большого числа токенов промпта позволяет повторно использовать веса в крупных матричных умножениях, что может поднять арифметическую интенсивность выше порога roofline. Короткие промпты и небольшие батчи, напротив, могут быть ограничены трафиком памяти или накладными расходами на запуск ядер.

Поэтому для ускорения decode работайте над пропускной способностью памяти: уменьшайте размеры весов с помощью квантизации, снижайте накладные расходы KV-памяти с помощью GQA и PagedAttention, а также повышайте интенсивность с помощью батчинга. Для длинного или хорошо забатченного префилла могут помочь более быстрые матричные вычисления и вычисления в формате с меньшей точностью; короткие префиллы профилируйте отдельно.

2. Иерархия памяти GPU

У GPU есть четыре уровня памяти, расположенные в виде пирамиды: большая, но медленная основная память (HBM) внизу и крошечные, но очень быстрые регистры наверху. Перемещение данных по этой иерархии — одно из главных ограничений производительности.

Иерархия памяти H100: от регистров на уровне потоков и shared memory каждого SM через общую кэш-память L2 к HBM3.Иерархия памяти H100: от регистров на уровне потоков и shared memory каждого SM через общую кэш-память L2 к HBM3.

От самой быстрой к самой медленной на H100:

  1. Регистры — самая быстрая память, напрямую связанная с вычислительными потоками. В WGMMA для Hopper матрица A может поступать из регистров или shared memory, а матрица B — из shared memory.
  2. SRAM (shared memory) — быстрая внутрикристальная рабочая память, локальная для каждого SM.
  3. Кэш L2 — общий слой объёмом 50 МБ. Он позволяет обслуживать данные, повторно используемые разными SM, без повторной загрузки из HBM.
  4. HBM3 — основная память объёмом 80 ГБ, в которой хранятся веса модели и KV-кэш; её пропускная способность составляет ~3,35 ТБ/с.

FlashAttention и fusion ядер снижают трафик в HBM, сохраняя промежуточные результаты на кристалле или объединяя операции. PagedAttention решает другую задачу: он сопоставляет логические KV-блоки с несмежными физическими блоками памяти GPU, уменьшая фрагментацию и позволяя совместно использовать блоки.

3. Глоссарий аппаратных терминов GPU

Термины ниже встречаются в остальной части руководства.

HBM (High Bandwidth Memory) объединяет стеки кристаллов DRAM, подключённые через TSV (through-silicon vias), рядом с кристаллом GPU. К поколениям относятся HBM2e (A100, 2 ТБ/с), HBM3 (H100, 3,35 ТБ/с) и HBM3e (H200/B200, 4,8–8 ТБ/с). В режимах decode, ограниченных пропускной способностью памяти, пропускная способность HBM напрямую ограничивает TPOT.

GDDR (Graphics DDR) — традиционная графическая память, используемая в потребительских и рабочих GPU, таких как RTX 4090 и L40S. У неё ниже пропускная способность, чем у HBM, но ниже стоимость одного ГБ. GDDR6X в RTX 4090 обеспечивает около 1 ТБ/с против 3,35 ТБ/с пропускной способности HBM3 у H100.

SM (Streaming Multiprocessor) — базовый вычислительный блок GPU NVIDIA. Каждый SM содержит CUDA Cores, Tensor Cores, shared memory и планировщик варпов. В H100 — 132 SM; в A100 — 108.

Tensor Cores — специализированные блоки matrix-multiply-accumulate внутри каждого SM. Они ускоряют матричные умножения со смешанной точностью, которые доминируют в вычислениях трансформеров. Tensor Cores H100 SXM обеспечивают 494,5 TFLOPS для плотного или 989 TFLOPS для разреженного TF32; при сравнении этого показателя всегда указывайте точность и режим разреженности.

CUDA Cores — универсальные блоки для операций с числами с плавающей точкой и целыми числами. Они выполняют поэлементные операции, функции активации и другие нематричные вычисления, пока Tensor Cores обрабатывают поддерживаемые матричные операции.

Warp — группа из 32 потоков, выполняющих инструкции синхронно на одном SM; это минимальная единица планирования в NVIDIA. Специализация варпов распределяет разные варпы между перемещением данных и вычислениями, чтобы эти задачи могли выполняться перекрывающимся образом.

NVLink — это высокоскоростной интерфейс межсоединения GPU–GPU от NVIDIA внутри одной ноды. NVLink 4.0 в H100 обеспечивает двунаправленную пропускную способность 900 GB/s, а NVLink 5.0 в B200 достигает 1,8 TB/s. Эта пропускная способность важна для тензорного параллелизма, поскольку GPU обмениваются частичными результатами на каждом слое трансформера.

InfiniBand — это высокоскоростная сетевая фабрика для межнодового обмена данными. Адаптеры InfiniBand класса ConnectX обеспечивают межнодовую фабрику для трафика пайплайн-параллелизма и распределённого обучения; пропускная способность зависит от адаптера и конфигурации порта.

RDMA (Remote Direct Memory Access) позволяет устройству обращаться к памяти другой машины, не пропуская тракт передачи данных через CPU. GPUDirect RDMA поддерживает прямую передачу данных между GPU разных нод, включая передачу KV-кэша в дизагрегированном сервинге.

NVMe (Non-Volatile Memory Express) — это интерфейс SSD, используемый для выгрузки KV-кэша и параметров в ZeRO-Infinity, когда памяти GPU и CPU недостаточно. Последовательная пропускная способность зависит от накопителя и рабочей нагрузки и остаётся намного ниже пропускной способности HBM.

TFLOPS и PFLOPS — это триллионы и квадриллионы операций с плавающей точкой в секунду. Один TFLOPS равен 101210^{12} FLOPS. H100 достигает 989 sparse TF32 tensor TFLOPS, а FlashAttention-3 показывает около 1,2 PFLOPS в FP8; эти значения относятся к разным форматам, поэтому их нельзя сравнивать как одну метрику.


Часть II — Основы инференса

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

4. Латентность: TTFT, TPOT и перцентили

Time to First Token (TTFT) — это сквозная задержка от отправки запроса до первого выходного токена. Она включает постановку в очередь, токенизацию, планирование, префилл промпта, первый шаг декодирования и сетевую доставку. Более длинные промпты обычно увеличивают компонент префилла, но доминировать может любой из этих этапов. Целевые значения зависят от продукта; MLPerf Inference v5.0 использует ограничение P99 для TTFT в \leq 450 мс в интерактивном сценарии с Llama 2 70B.

Time Per Output Token (TPOT) — это средний интервал между последовательными токенами после первого. Он соответствует фазе декодирования. Декодирование при размере батча один или низкой интенсивности обычно упирается в пропускную способность памяти, а достаточно большие батчи могут стать ограниченными вычислениями:

TPOT=E2E LatencyTTFTOutput Tokens1\text{TPOT} = \frac{\text{E2E Latency} - \text{TTFT}}{\text{Output Tokens} - 1}

Это определение требует как минимум двух выходных токенов; для ответа из одного токена TPOT не определён.

Средняя скорость чтения про себя на английском языке для взрослых составляет около 238 слов в минуту для нехудожественных текстов (Brysbaert, 2019). Целевые значения для стриминга всё равно следует определять по результатам тестирования продукта; MLPerf использует ограничение P99 для TPOT в \leq 40 мс в своём интерактивном сценарии.

Латентность P50 и P99 важна, поскольку медиана скрывает хвост распределения. Система с хорошим P50 и плохим P99 может иметь проблемы с батчингом, вытеснением, очередями или перекосом рабочей нагрузки; чтобы различить эти причины, нужны трейсы.

5. Пропускная способность: токены в секунду и компромисс с латентностью

Пропускную способность измеряют в выходных токенах в секунду для конкурентных запросов. Число запросов в секунду само по себе менее показательно: ответ из 10 токенов и ответ из 1 000 токенов имеют очень разную стоимость. Опубликованные результаты бенчмарков зависят от модели, точности, оборудования, длины промпта и ответа, уровня конкурентности и SLO. Сравнивайте vLLM, SGLang и TensorRT-LLM с помощью одного харнесса, а не объединяйте их заявленные результаты.

Компромисс выглядит так: при низком уровне конкурентности каждый запрос получает отличную латентность, но GPU используется не полностью. Увеличение размера батча почти линейно повышает пропускную способность, пока вычислительные ресурсы не будут исчерпаны; после этого латентность резко возрастает. Goodput — число запросов в секунду, которые укладываются в целевые показатели SLO, — связывает сырую пропускную способность с тем, что реально получают пользователи.

6. KV-кэш: боттлнек, лежащий в основе большинства других боттлнеков

При авторегрессионной генерации каждый новый токен учитывает все предыдущие токены. KV-кэш хранит проекции Key и Value каждого токена на каждом слое, чтобы избежать O(n2)O(n^2) повторных вычислений. Без него для генерации токена nn пришлось бы повторно прогонять модель по всем n1n-1 предыдущим токенам.

KV-кэш может стать главным источником нагрузки на переменную память при большой длине последовательности или высокой конкурентности, поскольку он растёт линейно с длиной последовательности, размером батча и числом слоёв:

KVcache=2×L×hkv×dh×s×B×bytesKVcache = 2 \times L \times h_{kv} \times d_h \times s \times B \times \text{bytes}

где:

  • LL = число слоёв
  • hkvh_{kv} = число KV-heads
  • dhd_h = размерность head
  • ss = длина последовательности
  • BB = размер батча
  • bytes\text{bytes} = число байт на кэшируемый элемент, задаваемое точностью KV-кэша

Конкретные примеры для FP16 и размера батча 1: Llama 3.1 8B при 8 192 токенах использует около 1,0 ГБ KV-кэша, а при 128K токенах — 16 ГБ. Llama 3.1 70B при 128K токенах требует около 40 ГБ для одной последовательности — половину VRAM H100. При высокой конкурентности или длинном контексте KV-кэш может занимать больше памяти, чем веса модели; результат зависит от длины последовательности, размера активного батча, точности KV-кэша и числа KV-heads. Наивные реализации теряют 60–80% выделенной памяти KV-кэша из-за фрагментации — именно эту проблему решает PagedAttention.

Основные оптимизации: GQA (меньше KV-heads), квантизация KV-кэша (FP8/INT8), PagedAttention (выделение памяти блоками с потерями менее 4%) и выгрузка KV-кэша в CPU или NVMe.

7. Префилл и декодирование: две фазы, два боттлнека

Фаза префилла обрабатывает входной промпт параллельно и заполняет KV-кэш. Длинные префиллы или префиллы с достаточно большим батчем часто упираются в вычисления, поскольку используют крупные матричные умножения; короткие префиллы могут оставаться ограниченными пропускной способностью памяти или накладными расходами на запуск ядер. Префилл влияет на время до первого токена (TTFT) наряду с постановкой в очередь, токенизацией, планированием, первым шагом декодирования и доставкой по сети. Фаза декодирования генерирует по одному токену за шаг. Каждый шаг считывает веса модели и KV-кэш из HBM, поэтому декодирование с размером батча 1 ограничено пропускной способностью памяти и в основном определяет время на выходной токен (TPOT).

Префилл обрабатывает токены промпта параллельно, а декодирование последовательно генерирует выходные токены; TTFT включает префилл, а TPOT — последующие шаги декодирования.Префилл обрабатывает токены промпта параллельно, а декодирование последовательно генерирует выходные токены; TTFT включает префилл, а TPOT — последующие шаги декодирования.

Чанкинг префилла разбивает промпт на чанки фиксированного размера вместо обработки целиком за один раз. Планировщик может чередовать эти чанки с работой декодирования, чтобы один длинный промпт не монополизировал итерацию. Sarathi-Serve сообщает о более выгодном компромиссе между throughput и латентностью на протестированных нагрузках, однако выигрыш зависит от модели, оборудования, распределения длин запросов, размера чанка и базовой линии сравнения. Дополнительное планирование и меньшие ядра могут увеличить TTFT для нового запроса.

Дизагрегированный сервинг размещает префилл и декодирование в отдельных GPU-пулах, позволяя каждому пулу оптимизироваться под свой боттлнек. Splitwise и DistServe описывают этот паттерн. Пулы передают данные KV-кэша по быстрому интерконнекту, например RDMA, поэтому стоимость коммуникации становится частью дизайна.

8. GQA и MQA: уменьшение KV-кэша

Сравнение MHA, MQA и GQA: у каждого query head свой KV head, один общий KV head и совместное использование KV-head группами.Сравнение MHA, MQA и GQA: у каждого query head свой KV head, один общий KV head и совместное использование KV-head группами.

Стандартный Multi-Head Attention (MHA) выделяет каждому query head собственные K- и V-head. Multi-Query Attention (MQA) использует один общий KV-head для всех query head — это предельное сокращение. Grouped-Query Attention (GQA) — практический компромисс: группы query head используют один KV-head.

В Llama 3 70B используется 64 query head, но только 8 KV-head, что дает 8-кратное сокращение KV-кэша по сравнению с той же архитектурой, где каждому query head соответствует отдельный KV-head. В Llama 3.1 405B используется 128 query head и 8 KV-head — 16-кратное сокращение по тому же расчету (Meta, 2024). Ainslie и соавторы сообщают, что в протестированных ими моделях качество GQA близко к MHA, а скорость приближается к MQA. Более компактный KV-кэш позволяет поддерживать батчи большего размера, однако фактический выигрыш в латентности и throughput по-прежнему зависит от ядра и нагрузки.

9. Квантизация: обмен битов на скорость и память

Квантизация снижает точность весов модели и/или активаций. Основные компромиссы:

ФорматБитыПамять под веса (модель 7B)Примечание о качестве
FP16/BF1616~14 ГББазовый вариант для сравнения
FP88~7 ГБНативная поддержка на Hopper; оцените модель
INT88~7 ГБЗависит от калибровки и ядра
INT44~3,5 ГБМаксимальное сжатие; требуется тщательная оценка

AWQ (Activation-Aware Weight Quantization) определяет значимые каналы весов по величинам активаций и применяет к ним поканальное масштабирование. Требования к калибровке зависят от модели и конфигурации; в одном сравнении OPT-6.7B INT3-g128 AWQ использовал 16 калибровочных последовательностей, а GPTQ — 192. Воспроизводимое описание эксперимента должно включать и число последовательностей, и их длину. GPTQ использует приближённую информацию второго порядка для послойной квантизации. bitsandbytes умеет выполнять квантизацию при загрузке модели без отдельного пререйтингового прохода; его формат NF4 используется для файн-тюнинга QLoRA. FP8 на железе класса Hopper вдвое уменьшает объём памяти под веса по сравнению с FP16/BF16, однако качество и скорость по-прежнему зависят от модели, калибровки и ядра.

Ядро для сервинга может быть не менее важным, чем алгоритм квантизации. В разделе 10 приведён ограниченный результат для Marlin и объясняется, почему прирост зависит от конфигурации сервинга.


Часть III — Оптимизации инференса

Оптимизации в этой части решают разные задачи. FlashAttention уменьшает трафик между аттеншном и HBM; PagedAttention улучшает аллокацию KV; continuous batching не позволяет завершившимся последовательностям занимать ёмкость батча.

10. CUDA-ядра и fusion ядер

CUDA-ядро — это функция, написанная для GPU и выполняемая параллельно тысячами потоков. Когда CPU вызывает ядро, GPU распределяет работу между своими SM: каждый SM выполняет несколько warp’ов по 32 потока, а каждый поток обрабатывает свой фрагмент данных. В инференсе LLM любая операция — от матричного умножения до сэмплирования токенов — в конечном счёте выполняется через запуск ядра. Один forward pass через модель на 70B параметров вызывает от сотен до тысяч запусков ядер, и разница между наивным и оптимизированным ядром может определить, уложится ли система в заданный latency SLO.

Основные категории ядер в сервинге LLM:

  • GEMM-ядра для матричного умножения, которые определяют основную вычислительную нагрузку и на этапе префилла, и на этапе decode.
  • Attention-ядра, такие как FlashAttention, которые разбивают вычисления на тайлы, чтобы данные оставались в SRAM, а не выгружались в HBM.
  • Fused-ядра, объединяющие несколько операций (например, add + layer norm или QKV projection) в один запуск и устраняющие промежуточные обращения к HBM.
  • Ядра сэмплирования, преобразующие логиты в ID токенов с помощью сэмплирования top-k, top-p или по температуре.

Качество ядра может определить, дадут ли сжатые веса ускорение. В статье о Marlin сообщается об ускорении end-to-end до 2,8 раза относительно базовой конфигурации FP16 для протестированных конфигураций vLLM с weight-only INT4. Этот результат относится к моделям, GPU, размерам батчей и конфигурации сервинга из статьи, поэтому его нельзя считать универсальным приростом для INT4.

Triton снижает порог входа в разработку кастомных ядер, предоставляя доступ к программированию GPU через Python вместо низкоуровневого CUDA C++. Благодаря этому оптимизация на уровне ядер становится доступна ML-инженерам, а не только специалистам по GPU. Большинство оптимизаций, рассматриваемых далее в этой части (FlashAttention, fused-ядра, PagedAttention), — это либо более эффективные ядра, либо более умная оркестрация их запусков.

Фьюжн ядер объединяет последовательные операции в одно GPU-ядро и исключает промежуточные записи в HBM. К распространённым фьюжнам относятся проекция QKV, attention вместе с softmax, add вместе с RMSNorm (FlashNorm) и активация SwiGLU (DeepFusionKernel). Triton делает такие ядра доступными через Python. Точный выигрыш по количеству запусков и утилизации зависит от графа модели, компилятора, GPU и фреймворка сервинга, поэтому вместо универсального процента профилируйте задеплоенный стек.

11. FlashAttention: тайлинг attention для работы в SRAM

Стандартный attention материализует полную N×NN \times N матрицу attention в HBM, что требует O(N2)O(N^2) памяти и создаёт большой объём трафика памяти. Идея FlashAttention заключается в том, чтобы вообще не материализовать эту матрицу. Q-, K- и V-матрицы разбиваются на блоки, помещающиеся в SRAM; внутри каждого тайла вычисляется частичный attention, а результаты объединяются с помощью online softmax (максимум и сумма накапливаются по блокам). Потребление памяти снижается с O(N2)O(N^2) до O(N)O(N), а количество чтений из HBM — на порядок.

Каждая версия нацелена на боттлнек своего поколения GPU:

  • FlashAttention v1 (A100, 2022) доказала работоспособность идеи тайлинга и online softmax. В статье сообщается об ускорении в 2–4 раза по сравнению со стандартным attention, но утилизация GPU составляла лишь 25–40%: планирование запусков оставляло много SM без работы.
  • FlashAttention v2 (A100, 2023) переработала параллелизм: распараллеливание выполнялось по размерности последовательности, а не по batch и attention heads. На A100 была достигнута утилизация 50–73%, а скорость стала примерно в 2 раза выше, чем у v1.
  • FlashAttention v3 (H100 Hopper, 2024) добавила специализацию варпов (отдельные варпы для перемещения данных и математики) и конвейеризацию GEMM-softmax, чтобы перекрыть загрузку данных из памяти с вычислениями. В статье сообщается о производительности до 740 TFLOPS/s в FP16 (утилизация 75%) и почти 1,2 PFLOPS/s в FP8 на H100. Featured paper на NeurIPS 2024.
  • FlashAttention v4 (B200 Blackwell, 2026) устраняет новый боттлнек: на Blackwell пропускная способность tensor core растёт настолько быстро, что операции, не относящиеся к матричному умножению (экспоненты softmax и рескейлинг), становятся ограничивающим фактором. FA4 эмулирует экспоненту программно с помощью полиномиальных аппроксимаций на FMA-блоках, использует условный рескейлинг для снижения накладных расходов и хранит промежуточные значения в выделенной tensor memory (TMEM) Blackwell, а не в регистрах. В статье сообщается о производительности около 1,6 PFLOPS на B200 в BF16: это в 1,3 раза быстрее, чем cuDNN 9.13, и в 2,7 раза быстрее, чем Triton в проведённых тестах.

12. FlashDecoding: распараллеливание боттлнека decode

Стандартный FlashAttention загружает GPU, распределяя работу по размеру batch и длине запроса. Во время decode модель генерирует ровно 1 токен за раз (длина запроса = 1). Если произведение размера batch на количество attention heads меньше общего числа SM на GPU (108 на A100), большая часть GPU простаивает, пока несколько блоков последовательно обрабатывают историю токенов.

FlashDecoding решает эту проблему, добавляя новое измерение параллелизации: саму длину последовательности KV. Он разбивает KV-кэш на небольшие чанки и распределяет их между всеми простаивающими GPU-процессорами для параллельного вычисления, а затем объединяет частичные результаты с помощью редукции log-sum-exp.

В бенчмарке Stanford для CodeLlama-34B с длиной последовательности от 512 до 64K токенов FlashDecoding обеспечил ускорение полного цикла генерации до 8 раз по сравнению с протестированными базовыми решениями и сохранял почти постоянную латентность аттеншна вплоть до 64K. Этот результат относится к конкретным аппаратным условиям и бенчмарку, а не является общей гарантией для декодирования.

13. Continuous batching vs static batching

Статический батчинг ждёт завершения каждой последовательности в батче перед запуском следующего, поэтому короткие последовательности расходуют GPU-циклы впустую после достижения конца последовательности. Continuous batching (представленный в статье Orca, OSDI 2022) работает на уровне отдельных итераций: на каждом шаге декодирования завершённые последовательности удаляются, а новые добавляются.

В бенчмарке Anyscale для OPT-13B оптимизированный статический батчинг достиг ускорения в 4 раза относительно наивного baseline, continuous batching — в 8 раз, а vLLM с continuous batching и PagedAttention — в 23 раза (Anyscale, 2023). Continuous batching также усиливает нагрузку на аллокацию KV, поэтому его часто используют вместе с управлением страничной памятью.

14. PagedAttention: виртуальная память для KV-кэша

PagedAttention в vLLM применяет идею виртуальной памяти из ОС к управлению KV-кэшем. KV-кэш разбивается на блоки фиксированного размера (обычно по 16 токенов), блоки выделяются по мере генерации токенов, а логические (последовательные) позиции сопоставляются с физическими (разбросанными) адресами памяти через таблицы блоков. Несколько запросов с общим префиксом (системными промптами, beam search) могут указывать на одни и те же физические блоки.

В более ранних системах из-за фрагментации и предварительного выделения терялось 60–80% памяти KV-кэша. PagedAttention снижает этот показатель до <4%, что позволяет увеличить пропускную способность в 2–4 раза при той же латентности и до 24 раз по сравнению с HuggingFace Transformers (блог vLLM, 2023).

15. Speculative decoding: несколько токенов за один forward pass

Схема speculative decoding: draft-модель предлагает токены, target-модель параллельно оценивает их, а rejection sampling принимает префикс или выбирает корректирующий токен.Схема speculative decoding: draft-модель предлагает токены, target-модель параллельно оценивает их, а rejection sampling принимает префикс или выбирает корректирующий токен.

В speculative decoding небольшая draft-модель генерирует KK токенов-кандидатов, после чего большая target-модель оценивает все позиции KK за один forward pass. Декодер принимает токены draft-модели слева направо с вероятностями, полученными из распределений target- и draft-моделей. После первого отклонения он сэмплирует корректирующий токен из остаточного распределения target-модели и отбрасывает оставшиеся токены draft-модели. Этот модифицированный шаг rejection sampling сохраняет распределение выходов target-модели с учётом аппаратной арифметики; одного лишь точного совпадения токенов для этого недостаточно.

Наиболее заметный выигрыш вероятен при небольших батчах сервинга и короткой длине черновика, когда оценка черновика в основном упирается в передачу весов, KV-кэша или коммуникационный трафик, а не в дополнительные вычисления для токенов. В исходной статье о speculative sampling сообщалось об ускорении декодирования в 2–2,5 раза для протестированной конфигурации Chinchilla 70B; в EAGLE-3 сообщалось об ускорении до 6,5 раза в проведённых тестах. К вариантам относятся Medusa (дополнительные prediction heads без отдельной модели), prompt lookup decoding (сопоставление n-грамм с входом без отдельного forward pass черновой модели) и EAGLE (экстраполяция на уровне признаков).

При больших размерах батча дополнительные вычисления для черновика и верификации могут свести выигрыш на нет. Speculative decoding наиболее перспективен, когда батч сервинга достаточно мал, а доля принятых токенов черновика высока; измеряйте производительность полного serving-цикла, а не только ядра верификации.

16. Prefix caching и повторное использование KV-кэша

Вместо того чтобы удалять KV-кэш после завершения запроса, prefix caching сохраняет его для повторного использования в новых запросах с теми же токенами префикса. Это сокращает избыточный префилл для системных промптов, few-shot-примеров, RAG-контекста и истории многоходового диалога.

Automatic Prefix Caching в vLLM хэширует KV-блоки и использует глобальную хэш-таблицу для поиска. RadixAttention в SGLang поддерживает radix tree с кэшированными KV-тензорами на уровне отдельных токенов. Оба подхода зависят от повторяющихся побайтно идентичных префиксов, поэтому вместе с латентностью или throughput указывайте hit rate.

17. Стриминг на практике

Стриминг отправляет токены клиенту по мере их генерации, не дожидаясь полного ответа. Многие фреймворки для сервинга предоставляют эту возможность через Server-Sent Events: клиент открывает долгоживущее HTTP-соединение, а сервер отправляет каждый токен или батч токенов как событие data:. TTFT определяет, когда пользователь впервые увидит результат; TPOT помогает оценить плавность вывода. Целевые значения следует выбирать по результатам продуктового тестирования и с учётом выбранной модели взаимодействия.

На стороне клиента стриминг требует решений о буферизации. Отрисовка токен за токеном может вызывать визуальные рывки, особенно для Markdown или блоков кода, которым для корректного форматирования нужен контекст из нескольких токенов. Распространённые варианты — буферизация на уровне слов (накапливать токены до границы пробела), буферизация на уровне строк (ждать перевода строки перед отрисовкой) и адаптивная буферизация (сразу отображать обычный текст, а блоки кода буферизовать). В OpenAI Chat Completions API параметр stream_options: {"include_usage": true} добавляет финальный usage-чанк перед сообщением data: [DONE]. Совместимые с OpenAI серверы могут вести себя иначе, поэтому проверяйте выбранную реализацию.

Chunked prefill — один из способов не допустить, чтобы длинный префилл блокировал доставку токенов другим пользователям. Планирование с приоритетом декодирования может защищать запросы, находящиеся в процессе обработки, а disaggregated serving изолирует префилл и декодирование в отдельных пулах GPU.


Часть IV — Архитектура модели

Архитектура определяет объём памяти, поведение аттеншна и динамику обучения, которые учитываются в разделах о сервинге и обучении.

18. Основы архитектуры Transformer

Современный decoder-only Transformer (GPT, Llama) — это стек идентичных слоёв, каждый из которых состоит из двух субблоков: аттеншн и feed-forward. Каждый субблок обёрнут residual connection и нормализацией. Ключевые компоненты:

Multi-Head Attention позволяет каждому токену взвешивать информацию из токенов, доступных согласно attention mask. Вход проецируется в три матрицы: Queries (что я ищу?), Keys (что я содержу?) и Values (какую информацию я несу?). Затем scores аттеншна вычисляются так:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

Скалярное произведение QKTQK^T измеряет сходство между каждой парой токенов. Деление на dk\sqrt{d_k} не позволяет скалярным произведениям становиться слишком большими (иначе softmax попадёт в области с исчезающими градиентами). Softmax преобразует scores в вероятности, а умножение на VV даёт взвешенную комбинацию векторов values. Параллельное выполнение этого вычисления для нескольких attention heads позволяет модели одновременно учитывать разные взаимосвязи (одна attention head — для синтаксиса, другая — для кореференции и так далее).

Feed-Forward Network (FFN) независимо преобразует представление каждого токена после того, как аттеншн смешал информацию между токенами. В современных LLM часто используется SwiGLU вместо исходного ReLU-FFN с двумя матрицами:

SwiGLU(x)=(Swish(xWgate)xWup)Wdown\text{SwiGLU}(x) = \left(\text{Swish}(xW_{gate}) \odot xW_{up}\right)W_{down}

В SwiGLU используются три матрицы весов вместо двух в ReLU-FFN, а также плавная функция Swish. Их используют Llama, Mistral и Qwen; в Gemma используется приближённый GeGLU. Знакомое правило двух третей применимо к обычному full-MHA-блоку с dff4dd_{ff} \approx 4d: его две FFN-матрицы содержат примерно 8d28d^2 параметров против примерно 4d24d^2 у аттеншна. Это не универсальная оценка для архитектур SwiGLU/GQA. В Llama 3 8B d=4,096d=4{,}096, dff=14,336d_{ff}=14{,}336 и восемь key/value heads дают для FFN 3d×dff1763d \times d_{ff} \approx 176M параметров на слой против примерно 42M параметров attention-проекций: около 81% этих весов проекций без учёта эмбеддингов и нормализации.

Residual connections добавляют выход каждого субблока обратно к его входу: Output=Input+Sublayer(Input)\text{Output} = \text{Input} + \text{Sublayer}(\text{Input}). Skip path улучшает распространение сигнала и градиентов через глубокий стек.

RMSNorm широко используется в современных семействах LLM. LayerNorm повторно центрирует значения, вычитая среднее, и масштабирует их по стандартному отклонению. RMSNorm не вычитает среднее и только выполняет масштабирование; в статье сообщается об ускорении на 7–64% на протестированных моделях без потери качества в этих экспериментах. Также часто используется размещение pre-norm, при котором нормализация выполняется перед аттеншном или FFN, поскольку оно улучшает стабильность градиентов.

Оценка количества параметров для decoder-only-модели:

TotalV×d+12×L×d2\text{Total} \approx V \times d + 12 \times L \times d^2

где VV — размер словаря, dd — размерность hidden state, а LL — количество слоёв. Член V×dV \times d — это матрица входных эмбеддингов; член 12×d212 \times d^2 приближённо описывает веса аттеншна и FFN в каждом слое. Для Llama 3 8B (V=128,256V=128{,}256, d=4,096d=4{,}096, L=32L=32) оценка составляет около 0.53B+6.44B=6.97B0.53B + 6.44B = 6.97B параметров. Опубликованное общее значение 8,03B выше, поскольку приближение не учитывает архитектурные детали, такие как точная ширина FFN и отдельная выходная проекция.

19. Декодерные модели для генерации общего назначения

Оригинальный Transformer (2017) включал и энкодер, и декодер. С тех пор область разделилась на три архитектурных семейства, и одно из них стало стандартом для генеративного AI.

Модели только с энкодером (BERT, RoBERTa) используют двунаправленный аттеншн: каждый токен учитывает все остальные токены в обоих направлениях. Это позволяет получать богатые представления для задач понимания (классификация, NER, семантическое сходство), но не позволяет авторегрессионно генерировать текст. Модели только с энкодером по-прежнему часто используются как основа для эмбеддинг-моделей, реранкеров и лёгких классификаторов (например, роутеров на базе BERT в RouteLLM).

Энкодер-декодерные модели (T5, BART, оригинальный Transformer) разделяют понимание и генерацию. Энкодер обрабатывает весь вход с двунаправленным аттеншном, затем декодер авторегрессионно генерирует выход, обращаясь к представлениям энкодера через cross-attention. Это давало естественное преимущество в задачах sequence-to-sequence, таких как перевод, где вход и выход являются разными последовательностями. T5 от Google показала, что любую NLP-задачу можно представить как преобразование текста в текст, и энкодер-декодерные модели по-прежнему лежат в основе некоторых специализированных систем (Whisper для распознавания речи, FLAN-T5 для следования инструкциям).

Модели только с декодером (GPT, Llama, Mistral, Gemini) используют каузальный (однонаправленный) аттеншн: каждый токен учитывает только предыдущие токены. Они широко применяются для генерации текста общего назначения, поскольку одна цель языкового моделирования с каузальной маской масштабируется на непарных текстовых данных, а во время инференса инструкции, few-shot-демонстрации и запрос рассматриваются как токены одного префикса. Повторяющийся блок декодера также избавляет от отдельного стека энкодера и пути cross-attention. Энкодер-декодерные модели остаются полезными, когда задаче выгодно отдельно кодировать вход и генерировать результат на основе этого представления, включая перевод и распознавание речи.

20. Mixture of experts

MoE заменяет плотный FFN в каждом трансформерном слое несколькими небольшими экспертными FFN и лёгким роутером гейтинга. Роутер вычисляет оценку для каждого эксперта (обычно это softmax над обученными линейными проекциями) и выбирает для каждого токена top-kk экспертов. Вычисления выполняются только активированными экспертами, поэтому модель может обладать огромной общей ёмкостью при низкой стоимости обработки одного токена. Это разреженные условные вычисления: общее число параметров определяет, что модель может представить, а число активных параметров — сколько стоит её запуск.

МодельВсего параметровАктивных параметровЭксперты (маршрутизируемые + общие)Top-kk
Mixtral 8x7B47B~13B8 + 02
DeepSeek-V3671B37B256 + 18

Общий эксперт в DeepSeek-V3 активируется для каждого токена. Он обеспечивает базовое представление, поверх которого маршрутизируемые эксперты могут специализироваться.

У обучения MoE есть три постоянно повторяющиеся проблемы: дисбаланс нагрузки, коллапс экспертов и накладные расходы на коммуникацию при параллелизме экспертов. Традиционные MoE-модели добавляют вспомогательную функцию потерь, штрафующую дисбалансный роутинг, но эта функция потерь может конфликтовать с основной целевой функцией. DeepSeek-V3 в основном использует стратегию балансировки по батчу без вспомогательной функции потерь: bias-термы вне backpropagation снижают скор перегруженных экспертов и повышают скор недоиспользуемых. Кроме того, применяется очень маленькая дополнительная sequence-wise функция потерь для балансировки, предотвращающая сильный дисбаланс внутри последовательности. В статье сообщается о лучшем балансе роутинга без компромисса, связанного с основной вспомогательной функцией потерь, в описанной конфигурации.

21. Токенизация: BPE, SentencePiece и tiktoken

LLM не видят текст. Они работают с последовательностями целочисленных ID токенов. Токенизатор разбивает исходный текст на токены (субсловные фрагменты) и сопоставляет каждому из них ID. Выбор токенизатора влияет на качество модели, скорость инференса и мультиязычную справедливость.

Byte Pair Encoding (BPE) — распространённый алгоритм. Он итеративно объединяет наиболее часто встречающиеся соседние пары в обучающем корпусе. Упрощённый пример:

  1. Начать со словаря на уровне символов: [l, o, w, e, r, _]
  2. Самая частая пара — (l, o) → объединить в lo → словарь: [l, o, w, e, r, _, lo]
  3. Следующая по частоте пара — (lo, w) → объединить в low → добавить в словарь low
  4. Продолжать, пока словарь не достигнет целевого размера (например, 128K токенов)

Распространённые слова вроде “the” становятся одним токеном, а редкие слова вроде “defenestration” разбиваются на субсловные фрагменты, например ["def", "en", "est", "ration"]. Компромисс здесь возникает между размером словаря и длиной последовательности.

Большую часть production-сценариев покрывают три реализации токенизаторов:

  • SentencePiece обучается непосредственно на исходном Unicode-тексте, без языко-зависимого препроцессора токенизации. Он сохраняет пробелы с помощью метасимвола и при необходимости может переключаться на токены UTF-8 bytes. Поддерживаются модели BPE и unigram; SentencePiece используется в Llama 1/2, T5 и Mistral.
  • tiktoken — токенизатор OpenAI на Rust, использующий BPE на уровне bytes. В опубликованном бенчмарке GPT-2 он работал в 3–6 раз быстрее, чем протестированная конфигурация GPT2TokenizerFast. В Llama 3 алгоритм SentencePiece был заменён алгоритмом tiktoken.
  • Hugging Face Tokenizers — широко используемая библиотека на Rust с поддержкой BPE, WordPiece и Unigram.

Fertility измеряет, сколько токенов токенизатор создаёт на одно слово или другую выбранную единицу текста. Показатель зависит от конкретного токенизатора, языка, письменности, нормализации, домена и выборки. Измеряйте его на репрезентативном трафике, а не экстраполируйте по одному токенизатору или языку.

22. Контекстные окна и позиционные кодировки

Контекстное окно — максимальное число токенов, которое модель может обработать за один forward pass. За последнее время оно значительно увеличилось:

МодельКонтекстное окноГод
Llama 12 0482023
Llama 3.1128K2024
GPT-4.11 047 5762025
Gemini 2.5 Pro1 048 5762025

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

Распространены три подхода:

  • RoPE (Rotary Position Embeddings) поворачивает векторы query и key на зависящие от позиции углы, поэтому их скалярное произведение зависит от относительной позиции. Содержимое токенов по-прежнему определяет значение аттеншна; RoPE добавляет информацию о позиции без обучаемых эмбеддингов абсолютных позиций. Этот подход используется в открытых семействах моделей, включая Llama, Mistral и Qwen.

  • ALiBi (Attention with Linear Biases) не изменяет эмбеддинги, а напрямую добавляет штраф к значениям аттеншна: чем дальше друг от друга находятся два токена, тем больше отрицательный bias. Обучаемых позиционных параметров нет. В оригинальной статье модель 1.3B, обученная на последовательностях длиной 1 024 токена, показала на 2 048 токенах результаты, сопоставимые с моделью на синусоидальных позициях, обученной на последовательностях длиной 2 048 токенов. Поведение за пределами протестированных в статье моделей и длин зависит от конкретной модели.

  • YaRN (Yet another RoPE extensioN) расширяет контекст модели с RoPE за пределы обучающего контекста. Он делит частотные измерения на три категории и масштабирует каждую по-разному. В статье заявлено в 10 раз меньше токенов для файн-тюнинга и в 2,5 раза меньше шагов обучения по сравнению с базовым методом интерполяции позиций.


Часть V — Обучение и выравнивание

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

23. Претрейнинг, файн-тюнинг и выравнивание

Пайплайн обучения: от претрейнинга с предсказанием следующего токена через supervised файн-тюнинг и alignment по предпочтениям, где дистилляция показана как отдельный путь от учителя к ученику.Пайплайн обучения: от претрейнинга с предсказанием следующего токена через supervised файн-тюнинг и alignment по предпочтениям, где дистилляция показана как отдельный путь от учителя к ученику.

Претрейнинг — это self-supervised предсказание следующего токена на большом корпусе. Требования к вычислениям могут различаться на много порядков; например, для Llama 3 405B использовалось 3.8×10253.8 \times 10^{25} FLOPs. Supervised fine-tuning (SFT) адаптирует претрейненную модель к размеченным данным для конкретных задач. RLHF / RLAIF использует данные о предпочтениях для формирования поведения: обычный пайплайн RLHF собирает сравнения, обучает reward-модель, а затем оптимизирует policy. В RLAIF часть человеческих оценок заменяется фидбэком, сгенерированным ИИ.

< EOC_TEXT >Вычислительные затраты зависят от размера модели, длины последовательности, объёма данных, оптимизатора и метода. PPO также требует хранить больше состояния модели, поскольку типичная конфигурация включает policy-, reference-, reward- и critic-модели. Полный фреймворк выбора метода файн-тюнинга разобран в гайде по файн-тюнингу LLM.

24. LoRA и QLoRA: параметрически эффективный файн-тюнинг

LoRA замораживает веса претрейнинговой модели и добавляет обучаемые низкоранговые матрицы AA (r×kr \times k) и BB (d×rd \times r), так что обновлённый вес имеет вид W0+BAW_0 + BA. В статье о LoRA количество обучаемых параметров GPT-3 175B в описанной конфигурации было сокращено примерно до 18 миллионов. Ранг — это гиперпараметр, а не правило, напрямую связанное со сложностью задачи; выбирайте его с помощью перебора по качеству и потреблению памяти. После обучения LoRA-адаптеры можно слить с базовыми весами, чтобы при инференсе не использовать отдельный путь адаптера.

QLoRA загружает базовую модель с 4-битной квантизацией NF4, а LoRA-адаптеры обучает в BF16. NormalFloat4 размещает больше уровней квантизации около нуля — там, где плотность весов максимальна. В статье сообщается о файн-тюнинге модели 65B на одной GPU с 48 ГБ памяти и результатах, близких к результатам её 16-битных базовых конфигураций. Компромиссы между скоростью выполнения и потреблением памяти зависят от конкретного протестированного стека.

25. Обучение со смешанной точностью

Каждый формат с плавающей точкой распределяет свои биты между тремя полями: знаком (всегда 1 бит), экспонентой (задаёт динамический диапазон) и мантиссой (задаёт точность). Чем больше битов выделено под экспоненту, тем шире диапазон представимых величин; чем больше битов у мантиссы, тем тоньше различия между близкими значениями. В целочисленных форматах экспоненты нет: они представляют только равномерно расположенные целые числа в фиксированном диапазоне.</ EOC_TEXT >

ФорматБитыРаскладка (S / E / M)ДиапазонТочностьТипичное применение
FP32321 / 8 / 23±3.4×1038\pm 3.4 \times 10^{38}~7 десятичных знаковОсновные веса, состояния оптимизатора (момент и дисперсия Adam)
BF16161 / 8 / 7±3.4×1038\pm 3.4 \times 10^{38}~2 десятичных знакаПредпочтительный формат для обучения; тот же диапазон, что у FP32, и обычно без масштабирования loss
FP16161 / 5 / 10±65,504\pm 65{,}504~3 десятичных знакаОбучение с масштабированием loss (старые GPU); инференс на hardware до Hopper
FP8 E4M381 / 4 / 3±448\pm 448~1 десятичный знакПрямой проход на Hopper (H100) — более высокая точность для весов и активаций
FP8 E5M281 / 5 / 2±57,344\pm 57{,}344~0,6 десятичного знакаОбратный проход на Hopper — больший диапазон для градиентов
INT88фиксированная точка128-128 до 127127Точные целые числаКвантизация весов после обучения для инференса (W8A8); квантизация KV-кэша
INT44фиксированная точка8-8 до 77Точные целые числаАгрессивная квантизация только весов (AWQ, GPTQ) для инференса на hardware с ограниченной памятью

BF16 имеет тот же диапазон, что и FP32, поскольку диапазон задаётся полем экспоненты, а BF16 сохраняет все 8 бит экспоненты из FP32. Вместо этого он жертвует битами мантиссы (7 против 23), обменивая точность на двукратное сокращение потребления памяти и избегая многих проблем с диапазоном, характерных для обучения в FP16. В FP16 всего 5 бит экспоненты, поэтому конечный диапазон ограничен примерно значением 65K. Многие градиенты, наоборот, слишком малы для FP16 и при андерфлоу стремятся к нулю. Масштабирование loss умножает loss перед обратным распространением, чтобы такие градиенты оставались представимыми, а затем отменяет масштабирование перед шагом оптимизатора; при динамическом масштабировании коэффициент уменьшается при возникновении оверфлоу. Более широкий диапазон экспоненты BF16 обычно позволяет обойтись без этого.

Целочисленные форматы редко используются для основных вычислений при обучении, поскольку обратному распространению нужен широкий динамический диапазон. Зато они широко применяются для инференса, где замороженные веса можно сопоставить с откалиброванными scale-факторами. Квантизация весов INT4 уменьшает размер модели на 7B примерно с 14 ГБ до 3,5 ГБ без учёта накладных расходов рантайма; качество необходимо измерять для выбранных модели и метода.

Обучение в FP8 на H100 через Transformer Engine использует E4M3 там, где важна точность, и E5M2 там, где важен широкий диапазон. В статье FP8-LM сообщается, что её фреймворк смешанной точности обучил GPT-175B на 75% быстрее, чем базовый вариант BF16 Megatron-LM, и на 37% быстрее, чем NVIDIA Transformer Engine, в протестированной конфигурации на H100. DeepSeek-V3 использовала смешанную точность FP8 и сообщила примерно о $5,6 млн вычислительных затрат в эквиваленте аренды для финального запуска обучения, без учёта R&D и инфраструктуры.

26. Градиентный чекпоинтинг

Каждый слой прямого прохода создаёт промежуточный выход, называемый активацией:

Input[Layer 1]activation1[Layer 2]activation2[Layer 3]output\text{Input} \rightarrow [\text{Layer 1}] \rightarrow \text{activation}_1 \rightarrow [\text{Layer 2}] \rightarrow \text{activation}_2 \rightarrow [\text{Layer 3}] \rightarrow \text{output}

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

Градиентный чекпоинтинг обменивает вычисления на память: большая часть активаций удаляется, а во время бэкпропагации вычисляется заново по мере необходимости. Стандартная стратегия (Chen et al., 2016) делит сеть из nn слоёв на n\sqrt{n} равномерно распределённых сегментов и сохраняет только граничную активацию каждого сегмента. Эти сохранённые границы и называются «чекпоинтами». Все промежуточные активации внутри сегмента удаляются сразу.

Когда обратный проход достигает слоя внутри сегмента, его активации пересчитываются от ближайшего чекпоинта. При равномерном разбиении объём памяти под сохранённые активации снижается с O(n)O(n) до O(n)O(\sqrt{n}). Фактическая экономия памяти и накладные расходы на пересчёт зависят от модели, границ чекпоинтов, длины последовательности, фреймворка и реализации, поэтому измеряйте оба показателя на целевом обучающем запуске. FlashAttention применяет тот же принцип внутри аттеншна, не материализуя полную матрицу аттеншна. Включить его в HuggingFace можно с помощью gradient_checkpointing=True.

27. Стадии DeepSpeed ZeRO

При стандартном дата-параллелизме каждый GPU хранит полную копию весов модели, градиентов и состояний оптимизатора. Для Adam каждый параметр занимает 2 байта под FP16-вес + 4 байта под мастер-вес в FP32 + 4 байта под моментум + 4 байта под дисперсию + 2 байта под градиент — всего 16 байт на параметр. Модель с 7,5 млрд параметров требует около 120 ГБ на GPU, причём каждый GPU хранит одну и ту же копию. На 64 GPU это 64 идентичные копии по 120 ГБ. Большая потеря ресурсов.

DeepSpeed ZeRO (Zero Redundancy Optimizer) устраняет это дублирование, распределяя эти компоненты между GPU вместо их репликации:

  • Стадия 1 — партиционирование состояний оптимизатора. Каждый GPU хранит только 1/N состояний оптимизатора (мастер-веса в FP32, а также первый и второй моменты Adam — 12 байт на параметр). Когда GPU нужно обновить вес, он обновляет только свою часть и рассылает результат. При приведённых ниже допущениях объём памяти снижается примерно со 120 ГБ до ~41,3 ГБ на GPU.
  • Стадия 2 — дополнительно партиционирование градиентов. Градиенты (2 байта на параметр) больше не выполняется all-reduce на каждом GPU. Каждый GPU получает только нужную ему часть градиентов через reduce-scatter. При тех же допущениях объём памяти снижается до ~28,1 ГБ на GPU.
  • Стадия 3 — дополнительно партиционирование весов модели. Каждый GPU хранит только 1/N FP16-весов. Перед прямым или обратным проходом каждого слоя GPU вызывает all-gather, чтобы временно восстановить полные веса слоя с остальных GPU, выполняет вычисления и удаляет собранные веса. При тех же допущениях объём памяти снижается до ~15,0 ГБ на GPU.
КонфигурацияСостояния оптимизатораГрадиентыВесаПриблизительный объём памяти под состояние модели на GPU (7.5B, 8 GPU)
Без ZeROРеплицированыРеплицированыРеплицированы~120 ГБ
Stage 1ПартиционированыРеплицированыРеплицированы~41.3 ГБ
Stage 2ПартиционированыПартиционированыРеплицированы~28.1 ГБ
Stage 3ПартиционированыПартиционированыПартиционированы~15.0 ГБ

Это приблизительные значения состояния модели для модели с 7.5B параметров на 8 GPU (world size N=8N=8), с весами и градиентами в FP16, а также мастер-весами, momentum и variance Adam в FP32. В расчёт не входят активации, временные буферы all-gather, фрагментация аллокатора и накладные расходы фреймворка/рантайма. Граница расчёта — 7.5B×7.5B \times байт на параметр; каждое состояние делится на NN только в тех строках, где в таблице оно отмечено как партиционированное.

Компромисс — коммуникации. Stage 1 добавляет минимальные накладные расходы, а Stage 2 заменяет all-reduce на reduce-scatter с сопоставимой стоимостью. Stage 3 требует вызовов all-gather перед каждым слоем и в прямом, и в обратном проходе — примерно в 1,5 раза больше объёма коммуникаций, чем стандартный data parallelism.

ZeRO-Infinity расширяет Stage 3, выгружая партиционированные состояния в RAM CPU и даже на NVMe SSD. Это может сделать возможным обучение моделей с триллионами параметров на GPU-кластерах ограниченного размера. Выгрузка на накопитель добавляет затраты на PCIe и передачу данных; фактическое влияние зависит от накопителя, топологии PCIe, партиционирования, префетчинга, перекрытия передач и характера нагрузки. Используйте этот механизм для удовлетворения требований к ёмкости, а не исходя из фиксированного замедления, и профилируйте целевую конфигурацию.

28. FSDP: шардирование нативными средствами PyTorch

Fully Sharded Data Parallel (FSDP) — встроенный в PyTorch ответ на DeepSpeed ZeRO-3. Он распределяет параметры, градиенты и состояния оптимизатора между GPU, используя ту же основную идею. Механика для каждого слоя представляет собой простой цикл:

  1. All-gather полные параметры со всех GPU (временно восстановить полный слой).
  2. Выполнить прямой или обратный проход для этого слоя.
  3. Немедленно освободить собранные параметры. Каждый GPU хранит только свой шард.
  4. Reduce-scatter градиенты, чтобы каждый GPU получил только назначенный ему срез градиентов.

Поскольку FSDP нативен для PyTorch, он напрямую интегрируется с инструментами отладки и профилирования PyTorch, а также с torch.compile. Производительность относительно DeepSpeed ZeRO-3 зависит от политики wrapping, топологии коммуникаций, настроек offload и размера модели, поэтому сравнивайте их на одном и том же кластере.

КритерийFSDP (PyTorch)DeepSpeed ZeRO
Стиль управленияПолный шардинг через API PyTorchВыбираемые стадии ZeRO
ОффлоадингОффлоадинг на CPUCPU + NVMe с ZeRO-Infinity
Интеграция с фреймворкомНативный PyTorch, пути torch.compileОтдельная библиотека и система конфигурации
Критерий выбораПрофилирование целевого пайплайна PyTorchПрофилирование требуемых возможностей и оффлоадинга

FSDP2 (2024–2025) — это переписанная версия, которая улучшает интеграцию с torch.compile для более эффективного fusion ядер, добавляет поддержку обучения в FP8 через TorchAO и упрощает API. И FSDP, и DeepSpeed доступны через HuggingFace Accelerate, что позволяет переключаться между ними одним изменением конфигурации.

29. Законы масштабирования и ловушка Chinchilla

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

Одна из стратегий оптимизации стоимости жизненного цикла — обучать меньшую модель на существенно большем объёме данных:

МодельПараметрыОбучающие токеныТокены/параметрТокены/параметр ÷ 20 (расчётное)
Chinchilla70B1.4T20:1
Llama 165B1.4T22:1
Llama 270B2.0T29:11.4×
Llama 3 8B8B15T1,875:194×
Qwen3-0.6B0.6B36T60,000:13,000×

Это отображаемое соотношение токенов на параметр, делённое на приблизительное значение 20 токенов на параметр из статьи о Chinchilla. Это описательное соотношение, а не измеренный множитель качества или стоимости.

Для модели, которая обслуживает большой поток запросов, дополнительные вычисления на этапе обучения меньшей модели могут снизить стоимость жизненного цикла. Llama 3 8B иллюстрирует эту стратегию, однако её преимущество зависит от требуемого качества и прогнозируемого объёма инференса. Термин «оптимальность по Chinchilla» относится к эффективности вычислений при обучении и описывает другую цель, нежели стоимость жизненного цикла.

30. RLHF, DPO, GRPO и ландшафт alignment

Alignment направляет претрейн-модель к желаемым инструкциям, предпочтениям и политикам безопасности. Сам по себе он не гарантирует ни достоверность, ни безопасное поведение. Описанные ниже методы различаются по сложности реализации, требованиям к данным, степени exploration и стабильности обучения.

Классический пайплайн RLHF: SFT → сбор пар человеческих предпочтений → обучение reward model на этих парах → файн-тюнинг политики с помощью PPO (Proximal Policy Optimization). PPO одновременно хранит в памяти 4 копии модели (политику, reference-модель, critic/value model и reward model) и чувствителен к гиперпараметрам. Кроме того, он подвержен reward hacking: модель эксплуатирует особенности reward model — например, генерирует многословные ответы, звучащие уверенно, — вместо реального повышения качества.

DPO (Direct Preference Optimization) отказывается от обучаемой reward model и online RL-цикла, оптимизируя loss непосредственно на парах предпочтений. Это упрощает пайплайн обучения. Стандартный DPO работает в offline-режиме: он обучается на фиксированном датасете и не исследует новые ответы в цикле обновления. Значимость этого ограничения зависит от задачи и полноты покрытия данных.

GRPO (Group Relative Policy Optimization, DeepSeek) убирает обучаемый critic PPO: для каждого промпта генерируются несколько completions, а групповые относительные rewards используются как baseline. По сравнению с типичной конфигурацией PPO это уменьшает требования к памяти для хранения состояний моделей. В отличие от DPO, GRPO работает в on-policy-режиме: во время обучения модель генерирует новые ответы. DeepSeek-R1 сочетает GRPO с RLVR (reinforcement learning from verifiable rewards), используя проверки математических ответов, компиляции кода и unit-тесты. Такие rewards проще аудировать, чем обучаемый score предпочтений, однако неполные тесты и proxy-цели всё ещё можно эксплуатировать.

МетодТипичное состояние моделейСигнал rewardOnline/offlineКлючевое ограничение
PPO4 (policy, ref, critic, reward)Обучаемая reward modelOnlineReward hacking, сложный тюнинг
DPO2 (policy, reference)Неявный (пары предпочтений)OfflineНет exploration, фиксированные данные
GRPO2 с rule rewards; 3 с learned reward (policy, reference, reward)Явный (rule/verifier или learned)OnlineЗависимость от качества reward и информативной вариативности внутри группы

31. Distillation: сжатие знаний между моделями

Knowledge distillation переносит capabilities от большой teacher-модели к меньшей student-модели. Logit-based distillation обучает student повторять распределение выходов teacher. При data-based distillation teacher генерирует примеры, на которых затем выполняется файн-тюнинг student. Data-based методы широко применяются для LLM, поскольку они могут работать с разными архитектурами и teacher-моделями, доступными только через API, однако их ценность ограничена качеством teacher, покрытием данных, фильтрацией и стоимостью генерации.

DeepSeek-R1 сформировала смесь примерно из 800 000 примеров — около 600 000 samples, связанных с ризонингом, и 200 000 samples без ризонинга — и использовала её для дистилляции моделей Qwen2.5 и Llama 3 с 1,5B–70B параметров. В оценке из статьи:

  • DeepSeek-R1-Distill-Qwen-32B набирает 72,6% на AIME 2024 и 94,3% на MATH-500 — это выше опубликованных в статье результатов OpenAI o1-mini.
  • DeepSeek-R1-Distill-Qwen-7B набирает 55,5% на AIME 2024 — это выше результата QwQ-32B-Preview из статьи, несмотря на меньший размер модели.

В экспериментах DeepSeek-R1 с небольшими моделями дистилляция превзошла прямой GRPO на протестированных базовых моделях. Этот результат поддерживает использование дистилляции в данном сетапе, но не устанавливает универсального превосходства дистилляции над RL или наоборот.

32. Генерация синтетических данных

Данные для обучения, сгенерированные LLM, используются в нескольких распространённых сценариях:

  • Self-Instruct запускается с небольшого набора инструкций, написанных людьми: LLM генерирует новые инструкции, входные данные и выходы, после чего они фильтруются и добавляются обратно в пул. В проекте Alpaca использовалось 52 000 примеров, сгенерированных на основе 175 исходных инструкций. Stanford сообщил о генерации данных при стоимости 500andfinetuningunder500 and fine-tuning under 100, что давало начальную стоимость воспроизведения ниже $600; сравнение с GPT-3.5 было ограниченной проектной эвалуацией, а не подтверждением широкой эквивалентности.
  • Evol-Instruct (WizardLM) берёт существующие инструкции и итеративно усложняет их по разным направлениям: добавляет ограничения, углубляет ризонинг и делает задачи более конкретными. Так формируются постепенно более сложные обучающие примеры.
  • Phi-4 от Microsoft (14B) использовала синтетические данные для значительной части претрейнинга, включая генерацию, критику, саморедактуру и обращение инструкций. В техническом отчёте результаты по STEM и кодингу сравниваются с результатами более крупных моделей на выбранных бенчмарках.

Здесь важен риск коллапса модели: если модели рекурсивно обучать на синтетических данных предыдущих поколений, хвосты исходного распределения постепенно исчезают. Модель переоценивает распространённые паттерны и теряет редкие, но важные вариации (Shumailov et al., 2024). В отдельном исследовании классификатора Ahrefs в апреле 2025 года с каждой из 900 000 страниц выбиралась по одной недавно обнаруженной англоязычной странице на домен; классификатор определил, что 74,2% страниц содержат некоторый объём текста, сгенерированного ИИ. Это исследование вендора не является переписью всего веба. Митигацию начинают со смешивания синтетических и реальных данных, фильтрации и отслеживания lineage, чтобы можно было измерять долю материала, созданного рекурсивно.


Часть VI — масштабирование и деплой

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

33. Четыре формы параллелизма

Четыре стратегии параллелизма: data parallelism копирует модель, tensor parallelism разделяет слои, pipeline parallelism распределяет диапазоны стадий, а expert parallelism распределяет экспертов.Четыре стратегии параллелизма: data parallelism копирует модель, tensor parallelism разделяет слои, pipeline parallelism распределяет диапазоны стадий, а expert parallelism распределяет экспертов.

Tensor Parallelism (TP) разделяет отдельные матрицы весов между GPU и обычно требует обмена данными после каждого слоя. Быстрые соединения внутри узла, например NVLink, делают этот подход наиболее практичным в пределах одного узла. Чем больше шардов, тем меньше памяти и вычислений приходится на одно устройство, но тем выше коммуникационные затраты, поэтому степень параллелизма следует выбирать по результатам бенчмарка латентности.

Пайплайн-параллелизм (PP) последовательно распределяет слои между GPU и передаёт активации между стадиями. Его схема коммуникации может работать между нодами, но пузырьки пайплайна и неодинаковое время выполнения стадий снижают утилизацию. В крупных деплоях часто комбинируют TP внутри ноды и PP между нодами.

Параллелизм по данным (DP) реплицирует сервируемую модель, поэтому каждая реплика обрабатывает независимые запросы без межрепличной коммуникации для каждого запроса. Он эффективен, когда модель помещается в доступную память, а трафик можно сбалансировать. В обучении DP обычно комбинируют с ZeRO или FSDP для шардинга состояния.

Параллелизм по экспертам (EP) распределяет экспертов MoE между GPU, используя all-to-all-коммуникацию для роутинга токенов. Производительность зависит от баланса токенов, размещения экспертов и топологии интерконнекта; трафик all-to-all может стать главным боттлнеком.

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

  • Модель помещается на одном GPU: начните с независимых реплик и измерьте масштабирование DP.
  • Модель помещается в одной ноде: протестируйте TP внутри ноды, а затем при необходимости реплицируйте эту группу.
  • Модель распределяется между нодами: протестируйте комбинацию TP и PP с учётом интерконнекта и целевой латентности.
  • Mixture of experts: добавляйте EP только при необходимости распределить экспертов.

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

34. Сравнение фреймворков для сервинга

vLLM предоставляет постраничное выделение KV, continuous batching, API, совместимый с OpenAI, и несколько режимов параллелизма. Поддержка моделей и оборудования часто меняется, поэтому проверяйте целевую модель по актуальной матрице совместимости.

SGLang объединяет RadixAttention для повторного использования префиксов, собственный планировщик и структурированную генерацию. Заявленные приросты пропускной способности зависят от рабочей нагрузки и конфигурации; сравнивайте его с vLLM и TensorRT-LLM на идентичных промптах, выходах, оборудовании и SLO.

TensorRT-LLM ориентирован на низкую латентность одиночного запроса за счёт слияния CUDA-графов и оптимизации ядер, а также поддерживает FP8/FP4 нативно. Заявленные показатели зависят от оборудования и модели. Компромисс — более крутая кривая обучения и поверхность деплоя, специфичная для NVIDIA.

TGI интегрируется с экосистемой Hugging Face и поддерживает несколько аппаратных бэкендов. Перед выбором для нового деплоя проверьте актуальные состояние поддержки и набор возможностей репозитория.

Ollama делает акцент на простом локальном рабочем процессе с моделями. Используйте его для удобства разработки; при высокой конкурентности или необходимости явно контролировать SLO бенчмаркайте другой стек сервинга.

llama.cpp — переносимый рантайм на C/C++ с путями для ARM, x86, Metal, CUDA, ROCm и Vulkan. GGUF поддерживает несколько уровней квантизации. Производительность сильно варьируется в зависимости от модели, квантизации, контекста и бэкенда, поэтому используйте локальный инструмент бенчмаркинга на целевой машине.

35. Выбор GPU для инференса

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

GPUПамятьПропускная способность
B200 SXM180 GB HBM3eДо 8 TB/s
H200 SXM141 GB HBM3e4.8 TB/s
H100 SXM80 GB HBM33.35 TB/s
A100 80 GB SXM80 GB HBM2e2.039 TB/s

Сначала выбирайте GPU по соответствию объёму памяти, затем — по измеренной пропускной способности при целевой латентности. Ёмкость H200 в 141 GB может упростить некоторые деплои больших моделей, а B200 предлагает поддержку FP4, 180 GB HBM3e и новое поколение NVLink. GPU меньшего размера на базе GDDR могут быть экономичнее для квантизованных моделей, если ограничения по памяти и интерконнекту соответствуют нагрузке.

AWQ и GPTQ обслуживают 4-битные модели, деквантизуя поддерживаемые матричные операции в вычислительный формат, например FP16 или BF16. Совместимость и скорость по-прежнему зависят от архитектуры модели, формата квантизации, бэкенда сервинга, ядра и GPU, поэтому проверяйте матрицу поддержки бэкенда и бенчмарк конкретного артефакта. Hopper (H100/H200) и Ada (L40S/4090) аппаратно ускоряют FP8, а Blackwell (B200) добавляет нативные FP4 Tensor Cores. Все перечисленные GPU поддерживают матричные операции INT8.

Декодирование LLM часто упирается в пропускную способность памяти, поэтому при сервинге нагрузок ёмкость и пропускная способность HBM могут быть важнее пикового значения TFLOPS. Сравнивайте GPU при неизменных модели, точности, распределении батчей, длине контекста и целевой латентности.

36. Каскадирование и роутинг моделей

Роутинг моделей выбирает одну модель до начала выполнения, а каскадирование начинает работу с более дешёвой модели и повышает уровень модели, когда её acceptance score слишком низок.Роутинг моделей выбирает одну модель до начала выполнения, а каскадирование начинает работу с более дешёвой модели и повышает уровень модели, когда её acceptance score слишком низок.

Роутинг моделей выбирает LLM, которая обработает каждый запрос, на основе предсказанной сложности или требуемых возможностей. RouteLLM (LMSYS/UC Berkeley, ICLR 2025) сообщает о снижении стоимости на 85% в своей конфигурации MT-Bench при сохранении 95% от базового уровня качества GPT-4. Окупаемость роутинга зависит от текущих цен, состава трафика, ошибок роутера и минимально допустимого уровня качества.

Роутеры варьируются от лёгковесных классификаторов до джаджей на базе LLM. Каскадирование — последовательный вариант: запрос начинается с более дешёвой модели и передаётся на более мощную, когда scoring function отклоняет ответ. FrugalGPT сообщает о снижении стоимости до 98% или повышении точности до 4% в протестированном пуле моделей. Для production-каскада нужны калиброванные критерии эскалации и мониторинг запросов, которые дешёвая модель принимает ошибочно.


Часть VII — Применения

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

37. Эмбеддинг-модели и генеративные модели

Эмбеддинг-модели кодируют текст в векторы фиксированной размерности, отражающие семантическое значение. В отличие от генеративных моделей, которые создают последовательности токенов, они выдают для входных данных один плотный вектор — обычно от нескольких сотен до нескольких тысяч измерений. В их основе лежат двунаправленные encoder-only-трансформеры и модели, производные от decoder-архитектур и адаптированные для обучения представлений. Слой pooling часто сворачивает представления отдельных токенов в один вектор с помощью mean pooling, специального classification-токена или специфичного для модели метода на основе последнего токена. Затем контрастивный файн-тюнинг сближает семантически похожие тексты и отдаляет непохожие.

Современные эмбеддинг-системы покрывают разные требования к деплою. Qwen3-Embedding-8B поддерживает настраиваемую размерность выхода и множество языков. Gemini Embedding 2 принимает текст, изображения, видео, аудио и документы. pplx-embed-v1-4B исследует плотные эмбеддинги с пониженной точностью. OpenAI text-embedding-3-large поддерживает укороченные эмбеддинги через параметр dimensions. Это примеры, а не рейтинг: оценивайте язык, модальность, задачу, размерность и стоимость сервинга на одном retrieval-датасете.

Matryoshka Representation Learning (MRL, Kusupati et al., NeurIPS 2022) делает размерность эмбеддингов гибкой. Названный в честь русских матрёшек, MRL организует эмбеддинг так, чтобы его первые mm измерений были столь же информативны, как и независимо обученная модель размерности mm. Во время обучения MRL агрегирует лоссы по выбранному набору O(logd)O(\log d) префиксных размерностей, обычно представляющих собой последовательные деления пополам; в примере из статьи с размерностью 2048 используется {8,16,,1024,2048}\{8, 16, \ldots, 1024, 2048\}. Агрегированный лосс заставляет первые измерения нести грубую семантическую информацию, а последующие добавляют более тонкие детали.

После обучения MRL-эмбеддинг можно усечь до поддерживаемой префиксной размерности. OpenAI сообщает, что text-embedding-3-large с размерностью 256 превосходит text-embedding-ada-002 с размерностью 1 536 в приведённом сравнении на MTEB. Это даёт шестикратное сокращение объёма хранения сырых векторов; латентность поиска и стоимость базы данных также зависят от индекса, метаданных, фильтрации и аппаратного обеспечения.

Эмбеддинг-модель — один из важных компонентов RAG-пайплайна наряду с парсингом, чанкингом, поиском, реранкингом и генерацией. Если релевантные свидетельства не были извлечены, более сильный генератор не сможет надёжно восстановить их.

38. Архитектура RAG в продакшене

Архитектура RAG с офлайн-путём загрузки документов в векторы и онлайн-путём, который преобразует запрос или напрямую строит для него эмбеддинг перед гибридным поиском, реранкингом и генерацией.Архитектура RAG с офлайн-путём загрузки документов в векторы и онлайн-путём, который преобразует запрос или напрямую строит для него эмбеддинг перед гибридным поиском, реранкингом и генерацией.

Retrieval-Augmented Generation предоставляет LLM документы, извлечённые во время обработки запроса. Это позволяет использовать актуальные или приватные свидетельства, отсутствующие в весах модели, однако retrieval не гарантирует, что ответ корректно использует эти данные. Продакшен-система RAG — это многоэтапный пайплайн, этапы которого необходимо оценивать отдельно.

Пайплайн ingestion работает офлайн. Сначала сырые документы (PDF, HTML, Markdown, базы данных) парсятся в чистый текст — это сложнее, чем кажется: один только парсинг PDF может привести к потере таблиц, заголовков и форматирования. Затем текст разбивается на чанки, которые независимо преобразуются в эмбеддинги и индексируются.

Чанкинг влияет и на полноту retrieval, и на объём контекста, доступного генератору. Подходящий размер зависит от структуры документа, гранулярности запроса, ограничений эмбеддера и реранкера. Распространённые подходы — чанки фиксированного размера с перекрытием, рекурсивное разбиение по границам документа и семантический чанкинг по сходству эмбеддингов. Сравнивайте их на разметке релевантности уровня страниц или секций, а не принимайте один диапазон токенов как универсальный.

Затем каждый чанк преобразуется в эмбеддинг с помощью модели, например из раздела 37, и сохраняется в векторной базе данных (Pinecone, Weaviate, Qdrant, pgvector и т. д.).

Пайплайн retrieval работает во время обработки запроса. Начните с измеримого baseline, а затем добавляйте этапы, если анализ ошибок показывает, что они устраняют конкретный miss:

  • Гибридный поиск объединяет retrieval по плотным векторам со sparse retrieval, например BM25; результаты часто объединяются с помощью Reciprocal Rank Fusion (RRF). Dense search обрабатывает семантические перефразирования, а sparse search находит точные идентификаторы, коды ошибок и акронимы. Вендорские бенчмарки показывают прирост по сравнению с baseline только на векторах, но его величина зависит от корпуса и разметки релевантности.
  • Реранкинг передаёт найденные кандидаты модели, которая совместно оценивает запрос и документ. Это может повысить точность на уровне тонких различий в релевантности, но требует ещё одного вызова модели. Количество кандидатов, количество сохраняемых результатов и латентность нужно настраивать совместно. Полный мультистадийный пайплайн я разбирал в статье Building a Modern Search Ranking Stack.
  • Трансформация запроса переписывает запрос пользователя перед retrieval, чтобы повысить полноту. HyDE (Hypothetical Document Embeddings) заставляет LLM сгенерировать гипотетический ответ, который затем преобразуется в эмбеддинг и используется для retrieval. Multi-query expansion генерирует несколько формулировок одного и того же вопроса. Step-back prompting сначала задаёт более общий вопрос, чтобы получить более широкий контекст.

Распространённые режимы отказа:

  • Сбой retrieval — нужный документ существует, но не был найден. Проверяйте чанкинг, трансформацию запроса, гибридный поиск и фильтрацию по метаданным применительно к этому miss.
  • Отравление контекста — нерелевантные найденные чанки вводят LLM в заблуждение. Проверяйте реранкинг, фильтры контекста и уменьшение количества сохраняемых результатов.
  • Lost-in-the-middle — в протестированных сценариях multi-document question answering и retrieval по ключам и значениям Liu et al. обнаружили, что качество ответов обычно было максимальным, когда релевантная информация находилась ближе к началу или концу входных данных, и ниже, когда она располагалась в середине.

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

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

39. Архитектуры агентов и tool calling

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

  • ReAct — чередует выбор действия с наблюдениями. Агент может адаптироваться после каждого результата инструмента, но растущая история увеличивает затраты на токены и латентность.
  • ReWOO — планирует вызовы инструментов с плейсхолдерами, параллельно выполняет независимые операции, а затем синтезирует результат. В статье сообщается об экономии токенов по сравнению с ReAct, но фиксированный план требует явного пути восстановления при сбое инструмента.
  • Planner-executor — разделяет планирование и выполнение и может добавлять политику перепланирования после сбоя. Это позволяет специализировать модели, но добавляет состояние оркестрации и ещё одну границу принятия решений.
ПаттернТенденция по токенамАдаптивностьПодходящая отправная точка
ReActВышеОбновление после наблюденийНеопределённое или исследовательское использование инструментов
ReWOOНижеФиксированный план, если не расширятьПредсказуемая работа с параллельными шагами
Planner-executorСредняяМожет пересматривать явный планДлинные задачи, которым полезен контроль

Function calling — распространённый механизм вызова инструментов. API предоставляют описания инструментов и возвращают структурированные аргументы, уменьшая необходимость парсить текст в свободной форме. Аргументы, соответствующие схеме, всё равно могут выбрать неправильный инструмент или содержать недопустимые значения. Parallel function calling может сократить число round trip, когда операции независимы.

Structured output и constrained decoding обеспечивают соблюдение схемы, ограничивая набор токенов, доступных на каждом шаге генерации. Движки, такие как xgrammar, используемые в vLLM и SGLang, в поддерживаемых конфигурациях могут устранить множество синтаксических ошибок и сбоев парсинга при небольших накладных расходах. Они не гарантируют корректность извлечённых значений или решений. Schema-Guided Reasoning (SGR) использует порядок полей и структуру схемы, чтобы сделать промежуточное состояние инспектируемым до принятия финального решения. В него входят три паттерна: Cascade (последовательные шаги), Routing (union types как семантические переключатели) и Cycle (ограниченные списки).

По мере роста набора инструментов и глубины действий обычно ухудшаются качество выбора инструментов, сквозная латентность и стоимость токенов. Измеряйте эти зависимости с реальными описаниями инструментов и распределением сбоев. Фреймворки, такие как LangGraph, могут сделать состояние и пути восстановления явными, но не отменяют необходимость эвалуации.

40. Промпт-инжиниринг для продакшена

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

Few-shot-примеры часто эффективны для управления форматом вывода. Начните с 3–5 примеров, охватывающих пустые входные данные, неоднозначные запросы и ответы из нескольких частей, затем измерьте результат на отложенном датасете. Примеры должны отражать реальное распределение входных данных, а не только happy path. Дополнительные примеры расходуют контекст и не гарантируют дальнейшего улучшения.

Промптинг с цепочкой рассуждений (CoT) просит модель раскрыть промежуточные рассуждения перед ответом. Kojima et al. сообщили об улучшении результатов на протестированных ими задачах на ризонинг при добавлении суффикса «Let’s think step by step», но эффект зависит от модели, а более новые API для ризонинга могут не раскрывать скрытые трейсы. В продакшене лучше использовать проверяемую декомпозицию задачи или краткое обоснование, если оно полезно эвалуатору. Self-consistency (Wang et al., 2023) сэмплирует несколько путей рассуждения и агрегирует ответы, обменивая дополнительные затраты на инференс на устойчивость на подходящих задачах.

Структурированный вывод с явными JSON-схемами (раздел 39) устраняет множество ошибок парсинга. Движки constrained decoding, такие как xgrammar, могут обеспечивать соблюдение поддерживаемой грамматики во время генерации; фактическую точность и семантическую корректность всё равно нужно проверять, а неподдерживаемые возможности схем могут потребовать дополнительной обработки.

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

Температура изменяет распределение сэмплирования. Низкие значения — разумная отправная точка для классификации или извлечения данных; более высокие значения могут повысить разнообразие при генерации идей. Точное поведение различается в разных API моделей и зависит от top_p, top_k и настроек провайдера, поэтому для конкретной задачи переберите поддерживаемые настройки, а не копируйте один диапазон.

Разделение системного и пользовательского сообщений отделяет постоянную политику от содержимого конкретного запроса. Chat templates и instruction tuning задают этим ролям разный приоритет, но не превращают системное сообщение в границу принудительного исполнения. Стабильное поведение задавайте в системном сообщении, ненадёжные данные держите в пользовательском контенте или контенте tool-вызовов, а жёсткие ограничения, например удаление PII, также обеспечивайте вне модели.

Контекст-инжиниринг расширяет работу с промптами до сборки retrieval-документов, результатов инструментов, истории диалога и примеров. Liu et al. обнаружили эффект lost-in-the-middle в протестированных ими моделях с длинным контекстом, поэтому позиция должна быть частью эвалуации, а не считаться заведомо несущественной. Более подробно этот рабочий процесс рассмотрен в материале Context Engineering for AI Agents.


Часть VIII — Продакшен-операции

Продакшен-операции превращают рассмотренные ранее концепции в лимиты допуска, нагрузочные тесты, алерты и решения по ёмкости при реальном трафике.

41. Rate limiting для запросов с переменной стоимостью

Традиционный rate limiting по числу запросов в секунду предполагает примерно одинаковую стоимость каждого запроса. LLM нарушают это предположение. Промпт для классификации на 10 токенов и анализ документа на 100K токенов обращаются к одному API-эндпоинту, но отличаются по стоимости на четыре порядка. Rate limiting по RPS либо пропускает дорогие запросы без достаточных ограничений, либо без необходимости вытесняет дешёвые запросы.

В production-системах нужен лимитинг по токенам сразу по нескольким измерениям. OpenAI документирует лимиты запросов и токенов для разных уровней использования. Anthropic разделяет лимиты входных и выходных токенов. Точные квоты и алгоритмы могут меняться, поэтому источником истины должна оставаться документация провайдера; с архитектурной точки зрения важно независимо учитывать запросы и токены.

Практический паттерн реализации — иерархия многомерных лимитов (пользователь → приложение → организация → глобальный уровень) с приоритетными уровнями для премиум-доступа. На уровне запроса ключевая техника — резервирование токен-бюджета: при допуске оценить общее число токенов (входные + max_tokens), списать их из бакета, а после завершения запроса скорректировать значение на основе фактического использования. Это не позволяет всплеску запросов с длинной генерацией исчерпать доступную ёмкость ещё до начала выдачи результата.

Для self-hosted-деплоев эквивалентом является provisioned throughput: резервирование выделенной GPU-ёмкости под целевые скорости выдачи токенов. Для деплоев на vLLM это означает настройку admission control с учётом активных decode-слотов и нагрузки на KV-кэш, а не только количества запросов. Как объясняется в разделе 5, и throughput, и admission control требуют лимитов с учётом токенов.

42. Сценарии отказа, которые нужно предусмотреть

LLM-сервинг добавляет сценарии отказа, связанные с переменной длиной последовательностей, KV-памятью и долгими decode-операциями. Спроектируйте защиты и проведите нагрузочное тестирование до того, как production-трафик начнёт от них зависеть.

Out-of-Memory (OOM) — распространённый сценарий отказа. Модели 70B в FP16 требуется около 140 ГБ только под веса, а KV-кэш для одной последовательности Llama 3.1 70B с контекстом 128K может добавить около 40 ГБ при допущениях из раздела 6. Разрыв между «модель помещается в память» и «OOM под нагрузкой» меньше, чем кажется: батч запросов с длинным контекстом может потребить больше KV-памяти, чем ожидалось. Профилактика сочетает измеренный резерв памяти с квантизацией и страничным выделением KV. Для нагрузок с высоким давлением на KV LMCache может выгружать KV-данные в память CPU или на диск; используйте опубликованные результаты как отправную точку и проведите бенчмарк локальной иерархии памяти.

Preemption возникает, когда давление на KV-кэш заставляет планировщик вытеснять или пересчитывать работу. Точная стратегия зависит от версии и конфигурации serving-системы. Со стороны пользователя симптомом является рост сквозной латентности без очевидной ошибки приложения. Отслеживайте количество preemption-событий и сопоставляйте его с использованием KV, глубиной очереди и длиной запросов.

Tail latency может резко вырасти, когда большие префиллы задерживают decode-работу. Чанковый префилл (раздел 7) и планирование с учётом длины направлены на уменьшение этого взаимного влияния. В статьях про Learning-to-Rank scheduler и CascadeInfer сообщается об улучшении относительно их базовых решений на проверенных нагрузках, но точный результат зависит от распределения длин запросов и конфигурации планировщика.

Каскадные отказы могут начаться, когда медленные запросы увеличивают очередь, upstream-клиенты исчерпывают таймаут, а ретраи добавляют нагрузку. Защита включает admission control, лимиты конкурентности для каждого тенанта, ограничения на длину вывода, бюджеты ретраев и circuit breaker на gateway. Разделение пулов префилла и decode может помочь, если нагрузочные тесты показывают устойчивое взаимное влияние этих фаз.

43. Мониторинг LLM-систем

Мониторинг LLM отличается от мониторинга традиционных API по нескольким принципиальным аспектам. Каждый запрос имеет переменную стоимость, проходит две отдельные фазы с разными боттлнеками, а занимаемый им объём памяти зависит и от длины входа, и от длины генерации. Стандартные метрики вроде латентности запроса и доли ошибок не отражают большую часть действительно важных аспектов.

Goodput — это количество запросов в секунду, которые укладываются во все заданные пороги SLO, например TTFT, TPOT и общую латентность. Это полезная комбинированная метрика: сырой throughput может выглядеть хорошо, даже если SLO по латентности нарушаются. Например, если система обрабатывает 100 запросов в секунду, но для 40% из них не выдерживает пороги, её goodput равен 60 запросам в секунду. Оптимизация по goodput позволяет видеть распределение производительности, а не только среднее значение.

vLLM предоставляет Prometheus-эндпоинт по адресу /metrics с данными о выполняющихся и ожидающих запросах, использовании KV-кэша, распределении длины генерации и статистике prefix caching. Названия метрик могут меняться между релизами, поэтому привязывайте дашборды к развернутой версии. Типичный стек использует Prometheus для метрик, Grafana для визуализации и совместимые с OpenTelemetry трейсы на уровне компонентов приложения и сервинга.

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

  • Резкий рост числа прэмпшенов — рантайм вытесняет или пересчитывает работу, что увеличивает латентность без ошибки приложения.
  • Использование KV-кэша приближается к протестированной зоне прэмпшенов — добавьте мощности или снижайте нагрузку, пока вытеснения не переросли в каскад.
  • Глубина очереди стабильно превышает протестированный батч-диапазон — контроль admission должен начать отклонять запросы или снижать их приоритет.
  • TTFT растёт, а TPOT остаётся стабильным — такое расхождение сначала указывает на проблемы с очередью, admission, сетью или давлением на префилл, а не с throughput декодирования. Используйте трейсы и метрики очередей, чтобы различить эти причины.

44. Оптимизация стоимости: стратегия с накопительным эффектом

Цены провайдеров и соотношения стоимости входа и выхода меняются. Перед принятием решения о закупках запросите актуальные тарифы: уровень модели и длина выхода могут определять основную часть счёта ещё до оптимизации инфраструктуры.

Несколько подходов можно комбинировать, но сначала измерьте, какие из них применимы к вашей нагрузке:

  1. Квантизация с FP16 до INT4 сокращает объём памяти под веса на 75%. Снизит ли это стоимость, зависит от скорости ядер, размера батча и утилизации оборудования (раздел 9).
  2. Роутинг моделей направляет подходящий трафик к более дешёвым моделям. Измерьте долю ошибочно принятых запросов роутером и качество end-to-end, прежде чем увеличивать долю трафика, обрабатываемого дешёвой моделью (раздел 36).
  3. Кэширование промптов сокращает повторную обработку префиксов. Скидки провайдеров и правила применения rate limit со временем меняются, поэтому учитывайте измеренный hit rate и актуальные условия (раздел 16).
  4. Batch API могут снизить стоимость нереалтаймовых задач, таких как эвалуации, генерация синтетических данных и массовая классификация. Проверьте актуальные цены и окна выполнения.
  5. Селф-хостинг может быть выгоднее при стабильной высокой утилизации, но универсальной точки безубыточности по объёму токенов не существует. Помимо аренды GPU учитывайте затраты на инжиниринг, оркестрацию, observability, резерв мощности и on-call.

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

45. Планирование емкости и автоскейлинг

Планирование емкости для сервинга LLM должно учитывать переменную стоимость запросов, длительную работу декодирования и зависимую от длины последовательности память. В зависимости от нагрузки ограничивающим ресурсом могут быть KV-память, пропускная способность памяти, вычислительные ресурсы или интерконнект.

Теоретический предел числа одновременных запросов по памяти определяется бюджетом KV-кэша:

max concurrent sequences=GPU memorymodel weightsoverheadper-sequence KV cache size\text{max concurrent sequences} = \frac{\text{GPU memory} - \text{model weights} - \text{overhead}}{\text{per-sequence KV cache size}}

Для расчетов емкости предположим, что рантайм предоставляет бюджет KV-памяти в 40 ГиБ для Llama 3.1 70B с KV-кэшем FP16. Каждая последовательность длиной 4K занимает около 1,25 ГиБ, а последовательность длиной 128K — около 40 ГиБ. Поэтому до учета накладных расходов аллокатора и рантайма, вариативности нагрузки и запаса под SLO этот бюджет вмещает максимум около 32 последовательностей 4K или одну последовательность 128K. Именно поэтому выбор GPU и оптимизация KV-кэша напрямую влияют на план емкости.

Формула емкости для расчета размера флота:

required GPUs=peak tokens/s×safety-factor multiplierper-GPU tokens/s at target SLO\text{required GPUs} = \frac{\text{peak tokens/s} \times \text{safety-factor multiplier}}{\text{per-GPU tokens/s at target SLO}}

Перед делением приведите обе скорости к одной единице времени. Ключевая деталь — «при целевом SLO». Множитель safety factor, например 1,3, резервирует 30% запаса; выбирайте его на основе измеренных всплесков нагрузки, сбоев и времени восстановления. Пиковая пропускная способность по токенам и пропускная способность при соблюдении SLO могут резко различаться с ростом конкурентности. Проводите бенчмарки с реальным распределением длины промптов и ответов при требуемых порогах TTFT и TPOT, а не используйте теоретический максимум.

Утилизация GPU недостаточна как единственный сигнал для автоскейлинга, поскольку она может оставаться высокой как при нормальной обработке, так и при перегрузке. Комбинируйте ее с глубиной очереди, утилизацией KV-кэша и деградацией goodput. Настраивайте пороги по результатам нагрузочных тестов; значения вроде 80% утилизации KV-памяти — это отправные точки, а не универсальные лимиты. Эти метрики введены в разделе 43.

Scale-to-zero может подходить для сред разработки и staging с длительными периодами простоя. Serverless-платформы инференса и автоскейлеры на базе Kubernetes, такие как KEDA, позволяют убрать простаивающую емкость, но экономия и время холодного старта зависят от размера модели, кэширования образа и весов, а также от инфраструктуры. Измерьте время запуска, прежде чем применять ту же политику к чувствительному к латентности продакшен-трафику.


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

Эти концепции взаимосвязаны, но все равно позволяют выделить небольшой набор полезных первичных измерений. Потребность в KV-кэше ограничивает размер батча наряду с памятью под веса, накладными расходами рантайма и длиной запросов. Большие батчи могут повысить арифметическую интенсивность, а continuous batching увеличивает churn при выделении KV-памяти; PagedAttention уменьшает возникающую фрагментацию.

Независимо выбираемые оптимизации инференса, оцененные с учетом измеренного боттлнека аппаратуры и нагрузки, а также целевых показателей приложения по качеству, латентности и стоимости.Независимо выбираемые оптимизации инференса, оцененные с учетом измеренного боттлнека аппаратуры и нагрузки, а также целевых показателей приложения по качеству, латентности и стоимости.

В части обучения стоимость жизненного цикла может сделать более выгодным обучение меньшей модели на большем числе токенов, как показывает пример Llama 3 8B. GRPO снижает нагрузку, связанную с состоянием критика, по сравнению с PPO. В протестированной конфигурации небольшой модели для DeepSeek-R1 дистилляция превзошла прямой RL. Это варианты для оценки, а не готовый рецепт.

< /EOC_TEXT >

Симптом или решениеНачать сЧто измерить до изменения стека
Первый токен появляется медленноПрефилл и декодирование, TTFTВремя в очереди, длину промпта, время префилла и P99 TTFT
Токены стримятся медленноRoofline, TPOTTPOT при разной конкурентности, пропускную способность памяти и форму батча
Длинные контексты вызывают прэмптинг или OOMKV-кэш, PagedAttentionИспользование KV, длины запросов, потери аллокатора и число прэмптингов
Модель не укладывается в бюджетКвантизация, Выбор GPUКачество, пропускную способность ядер, резерв памяти и goodput при целевом SLO
Тренировочный запуск не укладываетсяLoRA и QLoRA, ZeRO, FSDPПамять состояния модели, коммуникации, пропускную способность и качество на отложенной выборке
Растёт стоимостьРоутинг, оптимизация стоимостиДопустимость трафика, ошибки качества, долю попаданий в кэш и данные счёта

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


Дополнительные материалы

Подборка подробных материалов из этого блога, сгруппированная по темам:


Ссылки

Сгруппированы по тематическим разделам.

Инференс и аттеншн

Спекулятивный декодинг

Квантизация

Обучение и файн-тюнинг

Выравнивание

Масштабирование и архитектура

Эмбеддинги

Архитектуры ИИ-агентов

Роутинг

Бенчмарки

Архитектуры сервинга

Фреймворки для сервинга

  • vLLM — движок сервинга на основе PagedAttention
  • SGLang — RadixAttention и структурированная генерация
  • TensorRT-LLM — оптимизированный NVIDIA инференс
  • llama.cpp — переносимый инференс на C/C++
  • DeepSpeed — библиотека Microsoft для распределённого обучения
  • Ollama — раннер локальных LLM

Операции