Инференс и KV-Cache
Как LLM генерирует текст
Проблема: Ты пишешь вопрос, а ИИ выдаёт готовый ответ. Но как он на самом деле «думает» и создаёт текст? Неужели у него есть весь ответ заранее?
Решение: Печатная машинка с блокнотом
Представь старую печатную машинку, которая умеет печатать только по одной букве. Но рядом лежит блокнот с заметками о том, «что обычно идёт дальше». Настройки вроде температуры управляют тем, насколько смелым будет каждый выбор. Этот рабочий процесс — подать текст в обученную модель и считать её предсказание — называется вывод (inference), или инференс: модель «выводит» следующий токен. Это отдельный этап от обучения: веса модели уже зафиксированы, и инференс просто их использует.
LLM не генерирует предложения целиком. Трансформер создаёт текст токен за токеном (слово или часть слова), и каждый новый токен зависит от всех предыдущих. Сама генерация идёт в две фазы. Сначала prefill: весь промпт читается за один параллельный проход, и модель строит внутреннее представление каждого токена. Затем decode: токены выдаются по одному, каждый проход создаёт ровно один новый токен. Prefill быстрый и параллельный; decode — это медленная пошаговая часть, которую ты видишь на экране, когда ответ печатается потоком.
Зачем нужен KV-кеш
Чтобы не перечитывать всю историю на каждом шаге, модели хранят KV-кеш — сохранённые Keys и Values, которые внимание посчитало для уже увиденных токенов. Без него генерация 1000-го токена заставила бы модель заново обработать все 999 предыдущих; с ним каждый новый шаг обрабатывает только один самый свежий токен, а остальное берёт из кеша. Именно кеш делает длинные ответы доступными по цене, но он растёт вместе с контекстом (context window): больше токенов — больше кеша, который занимает память видеокарты и обычно и есть настоящий потолок длины диалога.
Задержка, пропускная способность и цена
Скорость инференса описывают два числа. Задержка (latency) — это сколько ждёшь ты: зависит от длины промпта (длинный промпт — тяжёлый prefill) и от длины ответа (больше токенов на decode). Throughput (пропускная способность) — сколько токенов вся видеокарта выдаёт в секунду на всех пользователей. Они тянут в разные стороны: серверы батчат много запросов вместе, чтобы поднять throughput и снизить цену за токен, но более полный батч добавляет немного задержки конкретному пользователю. Конкретный пример: вопрос на 50 токенов с ответом на 200 токенов кажется мгновенным, а вставленный документ на 100 000 токенов вызывает огромный prefill, забивает кеш и заставляет самое первое слово прийти заметно позже — хотя каждый следующий токен после этого всё так же идёт потоком с прежней скоростью.
Представьте это как печатную машинку с блокнотом:
- 1. Ты вводишь: «Столица Франции —»
- 2. Смотрит на ВЕСЬ предыдущий текст: Машинка смотрит на ВЕСЬ предыдущий текст
- 3. Проверяет блокнот: После такой фразы часто идёт слово "Париж"
- 4. Печатает: «Париж»
- 5. Теперь смотрит на: «Столица Франции — Париж»
- 6. Решает, что дальше: Может точка, или «, который известен...»
Этот процесс называется инференс (inference) — модель «выводит», какое слово должно быть следующим.
Где это используется?
- ChatGPT/Claude: каждый ответ генерируется слово за словом (поэтому ты видишь, как текст появляется постепенно)
- Автодополнение кода: GitHub Copilot предсказывает следующую строку
- Перевод: модели переводят по одному слову за раз
- Суммаризация: краткое изложение строится по частям
Интересный факт: GPT-4 генерирует около 50-100 токенов в секунду. Каждый токен требует миллиарды вычислений! Вот почему нужны мощные видеокарты — они делают тысячи операций параллельно.
Попробуйте сами!
Ниже — интерактивная визуализация. Посмотри, как модель генерирует текст токен за токеном, учитывая весь предыдущий контекст!
Посмотри, как LLM обрабатывает промпт и генерирует ответ. KV-Cache критичен для эффективной генерации!
Представь, что ты читаешь книгу и делаешь заметки:
- ✗Без кеша: Каждый раз перечитываешь ВСЮ книгу с начала
- ✓С кешем: Смотришь в свои заметки — быстро и эффективно
Кеш пуст
Как заметки в блокноте — хранит "конспекты" предыдущих токенов, чтобы модель не перечитывала всё заново
Что такое K и V?
- KKey — "О чём этот токен?" (краткое описание)
- VValue — "Что важного?" (полезная информация)
Прежде чем сгенерировать первое слово, модель должна прочитать и «понять» весь ваш промпт — целиком. Это называется prefill, и занимает основное время. После этого каждое новое слово генерируется быстро: модель просто смотрит в свои записи (KV-Cache) вместо того, чтобы перечитывать всё заново.
KV-Cache меняет память на скорость. K/V векторы каждого токена (~1MB на токен для больших моделей) остаются в памяти. Это ограничивает длину контекста — 128K контекст = ~128GB KV-Cache!
Частые вопросы
Что такое инференс (inference) в LLM?
Инференс — это запуск уже обученной модели: ты подаёшь текст, а модель предсказывает следующие токены. Веса при этом не меняются, в отличие от обучения. Именно на инференсе модель генерирует ответ токен за токеном.
Что такое KV-кэш и зачем он нужен?
KV-кэш хранит Keys и Values, которые внимание уже посчитало для прошлых токенов. Без него каждый новый токен заставлял бы модель заново обрабатывать всю историю. С кэшем шаг обрабатывает только один свежий токен, поэтому длинные ответы остаются быстрыми и дешёвыми.
Почему длинный контекст замедляет инференс?
Длинный промпт требует тяжёлой фазы prefill — модель должна прочитать все токены и заполнить KV-кэш, прежде чем выдать первое слово. Кэш растёт вместе с контекстом и занимает память видеокарты. Поэтому документ на 100 000 токенов даёт заметную задержку до первого ответа, хотя дальше токены идут с прежней скоростью.
Чем отличается prefill от decode?
Prefill — это первый параллельный проход по всему промпту: модель сразу строит представление всех входных токенов. Decode — пошаговая генерация, где каждый проход выдаёт ровно один новый токен. Prefill быстрый и параллельный, а decode — медленная часть, которую ты видишь как печатающийся поток текста.
Попробуй сам
Интерактивное демо этой техники
Получить ответ да/нет на простой вопрос
Да, Python является интерпретируемым языком программирования. Это означает, что код Python выполняется построчно интерпретатором, а не компилируется целиком в машинный код перед выполнением. Однако технически Python сначала компилируется в байт-код (.pyc файлы), который затем выполняется виртуальной машиной Python (CPython). Существуют также JIT-компиляторы... [продолжение на 500 слов]
Да.
Инференс авторегрессивен: каждый токен генерируется последовательно. Уменьшив max_tokens с 4096 до 10 и указав формат, мы ускорили ответ в 18 раз без потери качества.
Создайте бесплатный аккаунт для решения челленджей
4 челленджей с AI-проверкой для этого урока
Этот урок — часть структурированного курса по LLM.
Мой путь обучения