Что такое assisted generation и зачем она нужна
Assisted generation - это техника ускорения генерации текста, представленная в библиотеке Hugging Face Transformers в 2023 году. Метод использует меньшую модель-ассистента для генерации кандидатных токенов, которые основная модель проверяет за один forward pass. Результат - снижение задержки до 10 раз без изменения основной модели и без потери качества выходного текста.
Практическая ценность метода очевидна: вы получаете ту же большую модель, но она отвечает быстрее. Ускорение достигает 3 раз при использовании INT8-квантизации, 2 раз на обычных GPU и 10 раз при memory offloading для моделей, не помещающихся в память устройства. Для ML-инженеров, работающих с LLM в продакшене, это прямой способ снизить latency без переобучения и деградации качества.
Assisted generation не требует менять архитектуру основной модели. Вы просто добавляете вторую, меньшую модель в пайплайн генерации. Основная модель по-прежнему определяет, какие токены попадут в итоговый ответ. Ассистент лишь предлагает черновик, который основная модель подтверждает или отвергает.
В этой статье разберем, почему генерация текста медленная, как именно работает assisted generation, какие цифры ускорения реальны на практике и как выбрать подходящую модель-ассистента. Материал ориентирован на разработчиков и ML-инженеров, которые уже знакомы с основами инференса LLM и ищут конкретные способы оптимизации.
Почему генерация текста медленная: проблема memory-bound
Генерация текста автогрессивна. Каждый новый токен зависит от всех предыдущих, поэтому модель не может обрабатывать их параллельно. Для каждого токена модель загружает все свои веса из памяти устройства в вычислительные блоки, выполняет вычисления, выдает один токен, и цикл повторяется.
Ключевой факт: для LLM с миллиардами параметров загрузка весов занимает больше времени, чем сами вычисления. Это делает генерацию memory-bound задачей - узкое место в пропускной способности памяти, а не в вычислительной мощности GPU. Увеличение batch size не решает проблему, потому что последовательная природа генерации не позволяет обрабатывать несколько токенов одновременно в рамках одного запроса.
При обычном инференсе модель загружает все веса для каждого сгенерированного токена. Если модель весит 7 миллиардов параметров в FP16, это около 14 ГБ данных, которые нужно прочитать из памяти для одного токена. Современные GPU имеют пропускную способность памяти 1-3 ТБ/с, поэтому загрузка 14 ГБ занимает несколько миллисекунд. Вычисления же занимают доли миллисекунды. Модель простаивает, ожидая данные.
Assisted generation обходит это узкое место. Вместо загрузки весов для одного токена основная модель загружает их один раз и проверяет сразу несколько кандидатных токенов, предложенных ассистентом. Это радикально сокращает количество загрузок весов на единицу сгенерированного текста.
Если вы работали с методами декодирования, то знаете, что выбор стратегии генерации влияет на качество и скорость. Assisted generation добавляет еще один уровень оптимизации поверх этих методов, не конфликтуя с ними.
Как работает assisted generation: пошаговый разбор
Алгоритм assisted generation состоит из четырех шагов. Сначала модель-ассистент, которая значительно меньше основной, генерирует несколько кандидатных токенов. Затем основная модель проверяет все эти токены за один forward pass, используя их как контекст. Токены, совпадающие с предсказаниями основной модели, принимаются. При первом несовпадении процесс повторяется с этого места.
Аналогия: ассистент пишет черновик, основная модель редактирует. Если черновик хорош, правка занимает минимум времени. Если ассистент ошибается, основная модель исправляет и продолжает сама.
Качество генерации определяется основной моделью. Ассистент лишь ускоряет процесс, предлагая вероятные продолжения. Если ассистент предлагает токен, который основная модель не подтверждает, этот токен отбрасывается. Итоговый текст генерирует основная модель, поэтому качество не ухудшается.
Роль модели-ассистента и основной модели
Модель-ассистент должна быть значительно меньше основной модели - обычно 10-20% от ее размера. Она должна использовать тот же токенизатор, что и основная модель. Это критическое требование, без которого метод не работает.
Основная модель выполняет проверку кандидатов. Она не генерирует токены сама в обычном смысле, а оценивает, насколько предложенные ассистентом токены соответствуют ее собственным предсказаниям. Если ассистент предложил последовательность, которую основная модель считает вероятной, все токены принимаются. Если на каком-то шаге основная модель предсказала другой токен, кандидат отклоняется, и основная модель генерирует свой токен.
Выбор ассистента напрямую влияет на эффективность. Слишком маленькая модель будет часто ошибаться, и основная модель будет вынуждена исправлять почти каждый токен, сводя ускорение к нулю. Слишком большая модель-ассистент сама будет медленной, и выигрыш также снизится.
Пример кода: использование assisted generation в Transformers
Минимальный пример на Python с Hugging Face Transformers выглядит так:
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# Основная модель
model_name = "meta-llama/Llama-2-7b-chat-hf"
assistant_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16)
assistant_model = AutoModelForCausalLM.from_pretrained(assistant_name, torch_dtype=torch.float16)
prompt = "Объясни, что такое assisted generation"
inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(
**inputs,
assistant_model=assistant_model,
max_new_tokens=128,
do_sample=False
)
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(result)Ключевой параметр - assistant_model. Он указывает библиотеке использовать переданную модель как ассистента для спекулятивного декодирования. Остальные параметры генерации работают как обычно: max_new_tokens ограничивает длину ответа, do_sample=False включает жадное декодирование.
Важно: обе модели должны использовать совместимые токенизаторы. В примере выше Llama-2 и TinyLlama используют один и тот же токенизатор, поэтому код работает корректно.
Практические результаты: насколько быстро можно ускориться
Цифры ускорения зависят от сценария использования. Тесты Hugging Face показывают три основных случая: обычные GPU без квантизации, INT8-квантизация и memory offloading для больших моделей.
На обычных GPU без квантизации ускорение достигает 2 раз. Это базовый сценарий, когда основная модель помещается в память GPU целиком, но загрузка весов все равно занимает значительное время. Ассистент сокращает количество загрузок, что дает двукратный прирост скорости.
С INT8-квантизацией ускорение достигает 3 раз. Квантизация уменьшает размер модели в 2 раза, что само по себе ускоряет загрузку весов. Assisted generation добавляет поверх этого сокращение числа проходов, и эффекты складываются.
Максимальное ускорение - до 10 раз - достигается при memory offloading. В этом сценарии модель не помещается в GPU, и веса подгружаются с CPU или диска. Загрузка с диска на порядки медленнее, чем из GPU-памяти, поэтому сокращение количества загрузок дает самый большой выигрыш.
Ускорение с INT8-квантизацией
INT8-квантизация уменьшает размер модели в 2 раза по сравнению с FP16, что снижает время загрузки весов. Assisted generation дополнительно сокращает количество проходов. Комбинация этих двух техник дает ускорение до 3 раз по сравнению с базовым FP16 инференсом без ассистента.
Пример: модель 7B в INT8 весит около 7 ГБ. Загрузка 7 ГБ на GPU с пропускной способностью 2 ТБ/с занимает 3.5 мс. Ассистент размером 1B позволяет проверять в среднем 3-4 токена за один проход, что сокращает время на токен с 3.5 мс до примерно 1 мс.
Ускорение с memory offloading
Memory offloading используется, когда модель не помещается в GPU. Веса хранятся на CPU или диске и подгружаются по мере необходимости. Скорость загрузки с CPU через PCIe составляет 16-32 ГБ/с, с диска NVMe - 3-7 ГБ/с. Это на порядки медленнее, чем из GPU-памяти.
Assisted generation позволяет проверять несколько токенов за одну загрузку весов. Если ассистент предлагает в среднем 5 правильных токенов подряд, основная модель загружает веса один раз для 5 токенов вместо 5 раз для одного токена. Это сокращает накладные расходы на загрузку в 5 раз, а с учетом медленного offloading общее ускорение достигает 10 раз.
Для моделей, не помещающихся в память, этот метод может быть единственным практичным способом получить приемлемую скорость генерации без покупки более дорогого оборудования.
Ограничения метода и как выбрать модель-ассистента
Assisted generation имеет два основных ограничения. Первое - совместимость токенизаторов. Модель-ассистент должна использовать тот же токенизатор, что и основная модель. Если токенизаторы различаются, кандидатные токены не будут совпадать с предсказаниями основной модели, и метод не даст ускорения.
Второе ограничение - качество ассистента. Если ассистент слишком мал или обучен на других данных, он будет генерировать много неверных кандидатов. Основная модель будет отклонять их, и ускорение снизится до нуля или даже станет отрицательным из-за накладных расходов на проверку.
Совместимость токенизаторов
Токенизатор преобразует текст в последовательность числовых идентификаторов. Если основная модель и ассистент используют разные токенизаторы, один и тот же текст будет преобразован в разные последовательности токенов. Основная модель не сможет проверить кандидатов ассистента, потому что они представлены в другой системе координат.
Практический пример: для LLaMA нужно использовать ассистента с тем же токенизатором, например TinyLlama. Для Mistral подойдет ассистент из семейства Mistral. Для моделей с нестандартными токенизаторами может быть сложно найти подходящего ассистента, и это ограничивает применимость метода.
Критерии выбора модели-ассистента
Оптимальный размер ассистента - 10-20% от размера основной модели. Ассистент должен быть обучен на похожих данных и иметь высокую вероятность совпадения токенов с основной моделью. Эту вероятность можно оценить на тестовых данных, сравнив предсказания обеих моделей.
Слишком маленький ассистент (менее 5% от основной модели) будет часто ошибаться. Слишком большой ассистент (более 30%) сам будет медленным, и выигрыш от его использования снизится. Оптимальный баланс достигается, когда ассистент угадывает 70-80% токенов правильно.
Рекомендация: выбирайте ассистента из того же семейства моделей. Для Llama-2 используйте TinyLlama, для Mistral - маленькую Mistral, для Qwen - Qwen меньшего размера. Это гарантирует совместимость токенизатора и высокую вероятность совпадения предсказаний.
Сравнение с другими методами ускорения
Assisted generation - один из нескольких методов ускорения инференса LLM. Квантизация уменьшает размер модели и ускоряет загрузку весов, но не меняет количество проходов. Прунинг удаляет часть параметров, что ускоряет вычисления, но требует переобучения и может снизить качество. Дистилляция переносит знания большой модели в меньшую, но меньшая модель всегда будет слабее оригинала.
Assisted generation отличается тем, что не изменяет основную модель и не требует переобучения. Вы используете ту же модель, что и раньше, просто добавляете ассистента. Метод комбинируется с квантизацией: квантизация ускоряет загрузку весов, ассистент сокращает количество загрузок, эффекты складываются.
Спекулятивное декодирование - это общее название подхода, а assisted generation - конкретная реализация в Hugging Face Transformers. Если вы уже используете спекулятивное декодирование, assisted generation предоставляет готовую, протестированную реализацию с простым API.
Для агентных моделей, таких как Qwen3-8B, спекулятивное декодирование с обрезанной draft-моделью дает ускорение до 1.4 раза на локальных устройствах. Assisted generation в Transformers предоставляет более универсальную реализацию, которая работает с любой совместимой парой моделей.
Заключение: когда стоит использовать assisted generation
Assisted generation - эффективный метод ускорения генерации для больших моделей, особенно в сценариях с ограниченной памятью. Если у вас есть подходящая модель-ассистент с совместимым токенизатором, вы можете получить ускорение от 2 до 10 раз без изменения основной модели и без потери качества.
Метод наиболее полезен в трех случаях: продакшен-инференс с требованиями к latency, работа с моделями, не помещающимися в GPU, и комбинация с квантизацией для максимального ускорения. Если вы используете memory offloading, assisted generation может быть единственным способом достичь приемлемой скорости.
Ограничения метода - совместимость токенизаторов и качество ассистента - легко проверить до внедрения. Запустите тест на ваших данных, сравните скорость и качество с базовым инференсом, и вы сразу увидите, работает ли метод в вашем случае.
Assisted generation активно развивается и поддерживается в Hugging Face Transformers. API простой: один дополнительный параметр в вызове generate(). Если вы работаете с LLM в продакшене, попробуйте этот метод на своей модели - вероятно, вы получите значительное ускорение без каких-либо затрат на переобучение.