В марте 2026 года Google публикует пост про алгоритм сжатия памяти для языковых моделей. Звучит скучно, правда? Но акции Micron, SanDisk, Samsung, SK Hynix и других производителей памяти за неделю теряют суммарно почти $90 млрд капитализации. Инвесторы паникуют: если модели начнут тратить в разы меньше памяти, то зачем столько железа?
Алгоритм, который навел весь этот шум, называется TurboQuant — герой этой статьи.
Я не буду говорить, что это «революция» или «переворот в индустрии» — это было бы явное преувеличение. Но штука действительно интересная, и уже есть рабочие реализации. Если вы деплоите LLM в продакшн или просто прогоняете модели локально, то вам 100% будет полезно об этом узнать. Разберем, что из заявленного правда, а что преувеличение, и главное — как это попробовать прямо сейчас.
Главная уязвимость LLM: в чем проблема с KV-кэшем
Чтобы понять, зачем нужен TurboQuant, нужно сначала понять, что такое KV-кэш и почему он может стать проблемой. Дальше совсем на пальцах постараюсь рассказать, о чем речь.
Когда LLM генерирует текст, на каждом шаге она учитывает все предыдущие токены. Чтобы не пересчитывать их заново, модель сохраняет промежуточные вычисления в памяти. Это и есть KV-кэш (Key-Value cache). Штука достаточно полезная: без нее инференс был бы в разы медленнее и дороже — это обусловлено самим устройством слоев внимания.
Но есть проблема: KV-кэш растет линейно с длиной контекста (чем длиннее текст мы генерируем, тем больше данных нужно хранить).
Вот конкретные числа, чтобы прочувствовать масштаб: у модели Llama 3.1 70B при контексте 128K токенов KV-кэш в формате BF16 занимает около 40 ГБ (при использовании Grouped Query Attention с 8 KV-головами). Сама модель в BF16 весит порядка 140 ГБ. В итоге один запрос требует 180 ГБ памяти, из-за чего он не помещается на ускоритель H100 (80 ГБ) даже в одиночку. Если же нужно параллельно обслуживать четырех пользователей на контексте в 128K, только под KV-кэш уйдет 160 ГБ — а это уже больше, чем весят сами параметры модели.
Где это критично
Проблема KV-кэша становится критической в трех сценариях. При RAG-подходе с большими документами попытка загрузить в контекст кодовую базу или длинный PDF забивает всю VRAM еще до отправки первого запроса.
В агентских циклах многошаговый диалог с вызовом инструментов быстро раздувает контекст до тысяч токенов. В итоге память заканчивается, историю приходится обрезать, а агент теряет контекст даже последних трех шагов, и мы получаем в лучшем случае стажера на полставки, а не AGI.
Наконец, при батчинге в нагруженных сервисах KV-кэш каждого пользователя фиксируется в памяти — и чем длиннее диалоги, тем меньше параллельных сессий помещается на одну GPU.
Решение
Проблему пытались решать по-разному. Метод GQA, например, уменьшает количество KV-голов, отлично работает и активно используется еще со времен Llama 2, Qwen2 и других моделей.
При Sliding Window Attention каждый слой внимания смотрит только на фиксированное окно недавних токенов, а не на весь контекст. В результате KV-кэш для этих слоев перестает расти бесконечно и ограничивается размером окна.
MLA у DeepSeek — это уже архитектурное решение: оно сжимает KV до латентных векторов и убирает около 93% кэша.
Все эти методы хороши, но они либо требуют переобучения модели (что дорого и сложно), либо режут контекст, ухудшая результаты.
TurboQuant хорош как раз тем, что предлагает другой подход — просто сжать то, что уже есть, без изменения архитектуры, калибровки и файн-тюнинга. Вы просто берете модель, включаете метод, и KV-кэш сжимается в 5–6 раз.
Как работает TurboQuant
Скажу сразу — TurboQuant содержит большую и взрослую математику. Но чтобы понять суть метода и начать его использовать, зарываться в формулы не обязательно. Мы сейчас пропустим сухую теорию и просто поверим, что умные люди все проверили (ICLR 2026 принял, значит доверять можно) и разберемся на пальцах, почему это вообще работает.
Если вы любите хардкор, три теоремы, доказательства near-optimal distortion rate, бета-распределения, информационно-теоретические нижние границы — вам прямая дорога к полному исследованию. Это фундаментальный труд, и тем, кому интересно погрузиться, лучше начинать с него, но сразу готовьте несколько дней или недель жизни на это (в общем — приятного чтения).
Квантизация KV-кэша — идея, прямо скажем, не новая: взять float16-значения и упаковать их в меньшее количество бит. Проблема в том, что наивная квантизация (равномерная сетка) работает плохо: значения в KV-кэше распределены неравномерно, и большинство традиционных методов либо теряют качество, либо требуют калибровочных данных под конкретную модель.
Идея первая — случайное вращение. Перед квантизацией вектор умножается на случайную ортогональную матрицу. Звучит странно: зачем крутить данные перед тем как их сжимать?
А вот зачем: после такого вращения компоненты вектора становятся почти независимыми и распределены предсказуемо. Из произвольного и сложного распределения получаем что-то близкое к нормальному, а с этим уже гораздо приятнее работать.
Идея вторая — оптимальный квантизатор для известного распределения. Если мы знаем, как распределены данные, то можно заранее просчитать оптимальную сетку квантизации (это называется Lloyd-Max квантизатор). Не равномерную, а такую, где ошибка минимальна именно для этого распределения: кодбук считается один раз, хранится статично и не требует никакой калибровки под конкретную модель.
Комбинация этих двух идей и дает результат: алгоритм доказуемо находится в пределах ~2,7× от теоретического минимума ошибки квантизации. Это называется near-optimal, и, как вы понимаете, довольно интересно.
На самом деле есть еще и третий компонент — QJL-коррекция остатка. Теоретически он красиво описан и обоснован, но на практике сообщество выяснило: в наивной реализации через стандартный attention softmax экспоненциально усиливает дисперсию от 1-bit коррекции, и результат становится хуже, а не лучше.
В vLLM PR #38479 проблему решили через norm correction (варианты с суффиксом _nc), в llama.cpp форках QJL чаще всего просто отключают или упрощают.
Главное, что нужно запомнить: алгоритм data-oblivious. Ему не нужны калибровочные данные, не нужен файн-тюнинг — он сразу работает на любой трансформерной модели. Берете модель, которая у вас уже есть, и просто включаете (ну почти): на момент написания статьи Google еще не выложила официальный код. Все, что есть и что можем попробовать, — это реализации от комьюнити.
Получаем, что несколько независимых команд собрали рабочие реализации буквально по формулам из статьи, и результаты совпали с заявленными. Об этом подробнее ниже.
8x и «zero loss» — реальные цифры
Давайте поговорим о цифрах. Google заявляет: «up to 8x speedup on H100 GPUs». И нет, к сожалению, ваш инференс не станет в восемь раз быстрее (в 99% случаев). Восьмикратный рост измерен относительно FP32, который никто не использует в продакшене. Относительно реально рабочего FP16-бейзлайна это будет примерно 4x.
И это еще не все. Четырехкратный рост — это ускорение только attention, не end-to-end инференса. В реальном пайплайне attention — лишь часть времени, а есть же еще линейные слои, sampling, IO.
Реального wall-clock времени от токена до токена в предложенной методике нет — есть только ускорение attention, а это лишь часть пайплайна. А еще сообщество намерило overhead на префил порядка 21–27 мс на квантизацию (не катастрофа, но и не бесплатно).
Все, тогда расходимся, нас всех оверхайпнули? На самом деле нет, потому что реальная ценность TurboQuant не в скорости, а в памяти. Сжать KV-кэш в пять раз — это значит впихнуть в одну GPU контекст, который раньше не влезал. Например, на Llama 3.1 70B это разница между ~109K токенов и ~536K токенов на 34 ГБ VRAM. Вот это реально полезно.
«Zero accuracy loss» с оговорками
Продолжим идти по цифрам — на бенчмарках LongBench и Needle-in-a-Haystack результаты действительно впечатляют: модель Llama-3.1-8B-Instruct при квантовании до 3,5 бит набирает 50,06 балла на LongBench (ровно столько же, сколько в оригинальном FP16), а на Needle держит показатель 0,997 на контексте вплоть до 104K токенов.
Если коротко — на длинном контексте качество не разваливается, и это главное.
Однако с практической точки зрения картина уже не такая радужная: все замеры проводились на небольших моделях до ~12B параметров (Llama-3.1-8B, Mistral-7B, Gemma). Данных для архитектур масштаба 70B+ в исследовании нет вовсе, и это риск — переносимость на крупные модели остается открытым вопросом.
Спасает то, что комьюнити уже провело самостоятельные тесты, и первые результаты обнадеживают: на модели 104B с пресетом turbo3 прирост перплексии (PPL) составил всего +3,6%. Однако «мы тут сами проверили, вроде работает» — это не замена нормального бенчмарка.
Отдельно в исследовании режет глаз отсутствие классической базы. Метрики WikiText-2 perplexity, MMLU — это тот минимум, без которого нормально сравнить метод с конкурентами в одной системе координат не получится.
Кроме того, есть еще один нюанс: ключи и значения в KV-кэше — это не одно и то же. У Qwen2.5, например, нормы ключей на порядки больше норм значений.
Отсюда вывод: симметричная квантизация с одинаковой разрядностью для K и V — это костыль, ключам по-хорошему нужно больше бит. Асимметричные пресеты вроде K8V4, которые появились в vLLM и в форках llama.cpp, — тому доказательство.
А что конкуренты
TurboQuant — далеко не единственный метод сжатия KV-кэша и даже не обязательно лучший для вашего конкретного сценария.
Метод KVTC строится на совершенно иной философии. Если TurboQuant работает по принципу «повернул и квантизовал», то KVTC — это своего рода аналог JPEG для KV-кэша. Разработчики заявляют о сжатии вплоть до 20 раз (против 5–6x у TurboQuant) с потерей точности менее одного процентного пункта. При этом KVTC тестировался на куда более широкой линейке моделей — от 1,5B до 70B.
Явный минус подхода — необходимость однократной калибровки (примерно на 200K токенов). Для продакшен-сервисов с фиксированной моделью это не станет проблемой, однако для локального сценария «скачал GGUF и запустил свою модель» уже будет больно. Подробное описание метода доступно в статье, а в открытом доступе есть open-source реализация.
RotorQuant — community-проект, который решает конкретную проблему TurboQuant: умножение на полную d×d ортогональную матрицу — это 16 384 операций для d=128. RotorQuant заменяет ее на математическую хитрость, которая дает ~100 операций.
В результате вращение выполняется в 10–31 раз быстрее, а сам алгоритм требует в 44 раза меньше параметров при сопоставимом качестве attention (косинусное сходство 0,990 против 0,991 у TurboQuant). Минус: проект пока проигрывает по качеству TurboQuant и находится на ранней стадии. Но идея красивая, и если авторы «дожмут» качество, проект может стать дефолтным выбором для мобильных и edge-сценариев. Исходный код проекта доступен на GitHub.
KIVI — проверенный бейзлайн (представленный на ICML 2024), который уже встроен в экосистему Hugging Face Transformers. Метод использует асимметричную 2-битную квантизацию (поканальную для ключей и потокеновую для значений). Такой подход сжимает KV-кэш в 16 раз, снижая пиковое потребление видеопамяти (peak memory) примерно в 2,6 раза. Для продакшена, где стабильность важнее максимального сжатия — вполне хороший вариант. Включить эту квантизацию в Transformers можно через cache_implementation="quantized" в методе generate().
Быстрая шпаргалка:
| Метод | Сжатие | Калибровка | Модели | Статус |
| TurboQuant | ~5-6x | Нет | до 8B | 15+ community-реализаций |
| KVTC (NVIDIA) | до 20x | Да (PCA) | 1,5B–70B | OpenReview + open-source |
| RotorQuant | ~5x | Нет | до 7B | Ранний community |
| KIVI | ~16x (KV) / 2,6x peak mem | Нет | широко | В HuggingFace |
Что работает прямо сейчас и как попробовать
Комьюнити уже создало более 15 реализаций — от простых Python-пакетов, устанавливаемых через pip install, до специализированных Metal-шейдеров.
Ниже внимательнее посмотрим на самые интересные и перспективные решения: одни из них уже готовы к использованию в продакшене, другие пока остаются полем для экспериментов.
llama.cpp
Если вы прогоняете модели локально через llama.cpp, это ваш основной вариант. TheTom/turboquant_plus (GitHub) — самый зрелый форк: есть поддержка Metal, CUDA, CPU, протестирован на моделях от 1,5B до 104B.
Собираем и запускаем:
git clone https://github.com/TheTom/turboquant\_plus.git
cd turboquant_plus
cmake -B build -DGGML_METAL=ON -DCMAKE_BUILD_TYPE=Release # для Apple Silicon
# или -DGGML_CUDA=ON для NVIDIA
cmake --build build -j
# Симметричный turbo3 (3-bit K + 3-bit V), работает на большинстве моделей
./build/bin/llama-cli -m model.gguf \
-ctk turbo3 -ctv turbo3 \
-fa on -ngl 99 -c 32768
# Асимметричный — для моделей с Q4_K_M весами (Qwen2.5 и подобные)
./build/bin/llama-cli -m model.gguf \
-ctk q8_0 -ctv turbo3 \
-fa on -ngl 99 -c 32768
Доступные форматы KV-кэша:
- turbo2 (2-bit) — сжатие в 6,4 раза, увеличение перплексии (PPL) на 6,5%. Подходит для экстремальной экономии памяти;
- turbo3 (3-bit) — сжатие в 5 раз, рост PPL порядка 1%. Оптимальный выбор, с которого стоит начинать;
- turbo4 (4-bit) — сжатие в 3,8 раза. По точности практически неотличим от исходного формата FP16.
Бонусом идет Sparse V — это пропуск позиций с низкими attention-весами при декодинге. До +22,8% скорости декодирования на 32K контекста без потери качества.
На что стоит обратить внимание:
- Симметричный turbo на Q4_K_M весах может выдать мусор. Это происходит, потому что квантизация весов уже снизила точность, и дополнительное сжатие KV-кэша на ключах добивает attention-маршрутизацию. Решение — использовать асимметричный режим, при котором ключи хранятся с более высокой точностью:
-ctk q8_0 -ctv turbo3; - Модели с head_dim=64 могут падать: TurboQuant валидирован на head_dim ≥ 128;
- Хорошая новость по масштабированию: большие модели переносят сжатие лучше, чем маленькие. 104B на turbo3 — всего +3,6% PPL, тогда как 70B — уже +11,4%.
Python + HuggingFace
back2matching/turboquant (GitHub, PyPI) — готовая интеграция для экосистемы Hugging Face Transformers. На сегодня это единственный пакет, который можно установить одной командой pip install и сразу получить сжатие KV-кэша ниже 8 бит (sub-8-bit).
pip install turboquant
from turboquant import TurboQuantMSE
# Квантизация любых векторов — KV-кэш, эмбеддинги
tq = TurboQuantMSE(dim=128, bits=4, device='cuda')
# Квантизация
indices, norms = tq.quantize(vectors) # vectors: (N, 128)
# Деквантизация
vectors_hat = tq.dequantize(indices, norms)
Для интеграции с генерацией:
from turboquant import TurboQuantCache
cache = TurboQuantCache(
key_bits=4,
value_bits=2,
protected_layers=[0, 1, -1, -2] # первые/последние слои в FP16 - НУЖНО для лучшего качества
)
outputs = model(**inputs, past_key_values=cache, use_cache=True)
Обратите внимание на параметр protected_layers — это найденный комьюнити костыль. Первые и последние слои модели передают основной объем сигнала через остаточные связи (residual stream), поэтому их квантизацию лучше отключать.
Важное уточнение: в текущем виде пакет остается исследовательским инструментом. Он подходит для прототипирования и проверки гипотез, но для запуска в продакшене пока рановато.
vLLM
Поддержка TurboQuant уже замержена в основной репозиторий vLLM. Если собрать vLLM из ветки main, алгоритм заработает из коробки. Для тех, у кого vLLM уже развернут в продакшене, это самый простой и прямой путь внедрения.
Достаточно одного флага:
# 3-bit с norm correction — рекомендуемый дефолт
vllm serve meta-llama/Llama-3.1-8B-Instruct \
--kv-cache-dtype turboquant_3bit_nc
# Другие доступные пресеты:
# turboquant_4bit_nc — 4-bit, самый безопасный по качеству
# turboquant_k8v4 — 8-bit ключи + 4-bit значения
# turboquant_k3v4_nc — 3-bit ключи + 4-bit значения + norm correction
Под капотом реализован отдельный TurboQuantAttentionBackend.
Несколько цифр по емкости из бенчмарков PR с добавлением поддержки:
- Qwen3.5-35B-A3B (гибридная MoE) — емкость KV-кэша выросла с 1,67M до 6,69M токенов, итого четырехкратный рост;
- Gemma-3-27B (dense) — с 207K до 415K токенов, больше в два раза.
Важный урок из обсуждения в Pull Request, который стоит знать до того, как запускать в продакшн:
Дефолтный tq3 может убить reasoning. Проблема в том, что 2-bit значения оказываются слишком грубыми для задач на многошаговое рассуждение.
Решение: используйте пресеты с коррекцией нормы (флаг _nc) либо асимметричный пресет k8v4 (8-битные ключи и 4-битные значения). Если ваша модель решает логические или вычислительные задачи, обязательно тестируйте ее на профильных бенчмарках, а не ограничивайтесь сравнением косинусного сходства.
SGLang — еще в процессе
Поддержка метода находится в разработке (PR #21617 в состоянии Work In Progress / Draft). На данный момент уже реализованы базовая квантизация, Lloyd-Max кодбуки, выделение выбросов (outlier detection), Triton-ядра и интеграция с бэкендами FlashInfer и Triton. Все 42 юнит-теста проходят успешно, но до полноценного мержа в основную ветку ещё далеко. Отслеживать прогресс можно в Issue #21618.
Что выбрать — зависит от вашего сценария
| Ваш сценарий | Инструмент | Как запустить |
| Локально на Mac (скорость) | turboquant_plus (Metal) | -ctk turbo3 -ctv turbo3 -fa on |
| Локально на NVIDIA | turboquant_plus (CUDA) | -ctk turbo3 -ctv turbo3 -ngl 99 |
| Python + HuggingFace | pip install turboquant | TurboQuantCache(key_bits=4, value_bits=2) |
| Продакшн (vLLM) | vLLM из main | --kv-cache-dtype turboquant_3bit_nc |
Общие рекомендации
Собрал несколько важных советов от комьюнити.
Ключи важнее значений. Ключам нужно больше бит. Оптимальный баланс по консенсусу: K=4-8bit, V=2-3bit.
Защищайте крайние слои. Первые два и последние два слоя трансформера лучше оставлять в формате FP16.
4-bit — безопасный дефолт. Если сомневаетесь, начинайте с 4-bit KV-кэша. При таком уровне сжатия сгенерированный текст при temperature=0 на большинстве моделей побитово совпадает с FP16. Формат 3-bit — отличный рабочий вариант для моделей от 8B параметров. Режим 2-bit стоит использовать только при критическом дефиците памяти и готовности к некоторой деградации качества.
Грубая формула для планирования VRAM. Сочетание весов 4-bit (GPTQ/AWQ) и 3-bit TurboQuant KV-кэша позволяет разместить модель 70B с контекстом 500K+ токенов примерно в 34 ГБ видеопамяти. По сути, это позволяет уместить на 1–2 видеокартах то, что раньше требовало целого вычислительного кластера.
Когда это нужно, а когда есть варианты лучше
TurboQuant решает одну конкретную проблему — чрезмерное потребление памяти KV-кэшем. Если ваш сценарий упирается именно в это ограничение, отлично, вы по адресу. В противном случае можно не тратить время.
Когда TurboQuant действительно нужен:
- Длинный контекст от 32K+ токенов. На коротких контекстах (4K–8K) KV-кэш занимает мало места, и overhead квантизации перевешивает экономию. А вот на отрезках от 32K токенов кэш начинает доминировать в расходе VRAM, и именно здесь TurboQuant раскрывается в полной мере.
- RAG с большими документами. При загрузке в контекст всей кодовой базы или длинных PDF-файлов KV-кэш расходует видеопамять гораздо быстрее самих весов модели.
- Агентные пайплайны. Агент с инструментами, многошаговой историей и накапливающимся контекстом — идеальный клиент для TurboQuant. Без сжатия приходится обрезать историю, агент забывает, что делал, и качество падает;
- Батчинг / высокий concurrency. Если вы обслуживаете много пользователей параллельно — KV-кэш каждого сидит в памяти;
- Локальный инференс на ограниченном железе. На сетапах вроде Mac Mini с 24 ГБ объединённой памяти или RTX 4080 с 16 ГБ VRAM метод позволяет запустить модели и длинные контексты, которые раньше физически не помещались.
Когда TurboQuant не поможет (или есть лучше):
Короткий контекст (< 8K токенов).
Модель не влезает по весам. TurboQuant сжимает KV-кэш, не веса.
MLA-архитектуры (DeepSeek V3, V4). Multi-head Latent Attention уже сжимает KV-кэш до латентных векторов архитектурно и убирает ~93% кэша. TurboQuant поверх MLA — это попытка сжать уже сжатое. Может дать что-то, но выигрыш будет минимальным по сравнению с обычными моделями.
Вам нужно максимальное сжатие и вы готовы к калибровке. KVTC от NVIDIA заявляет до 20x сжатия (против 5-6x у TurboQuant), но требует одноразовой PCA-калибровки. Если у вас фиксированная модель в продакшне и вы можете потратить время на калибровку, то KVTC может оказаться куда лучшим выбором.
Очень маленькие модели (< 1B). На 0.6B моделях качество деградирует заметно, модели не хватает избыточности, чтобы пережить сжатие. Начиная с 3B–4B все нормально, на 8B+ отлично.
Быстрый чеклист
Ответьте на три вопроса:
- Ваш контекст > 16K токенов? Если нет, то, скорее всего, не нужно.
- KV-кэш занимает > 30% вашего VRAM? Если нет, есть более полезные оптимизации.
- Модель ≥ 8B с head_dim ≥ 128? Если нет, результаты могут быть нестабильными.
Если три «да», ставьте turbo4, проверяйте качество на ваших примерах, и если все ок, то переключайтесь на turbo3 для большей экономии.
Вывод
Если коротко: TurboQuant — это рабочий практический инструмент для решения конкретной задачи: оптимизации KV-кэша при работе с длинным контекстом. Он работает без переобучения и калибровки модели, а его ограничения легко учитываются на практике.
Если хочется погрузиться глубже — рекомендую посмотреть блог Google Research, и обязательно заглянуть в главный технический тред в llama.cpp — там сообщество в реальном времени разбирает все тонкости, с которыми можно столкнуться при реальном использовании. Для альтернативного взгляда стоит почитать про KVTC от NVIDIA: он предлагает иную философию и другие компромиссы, которые в некоторых сценариях могут оказаться предпочтительнее.