Прямой ответ
Квантование — уменьшение разрядности весов модели: вместо 16-битных чисел с плавающей точкой используются 8- или 4-битные целые. Практический эффект: модель 7B в FP16 занимает около 14 ГБ, в INT4 — около 4 ГБ. Это позволяет запускать модели на ноутбуке и ускоряет инференс за счёт меньшего объёма чтения памяти, который обычно и является узким местом.
Основные схемы:
- INT8 (Llm.int8(), bitsandbytes). Почти без потери качества, даёт двукратное сжатие. Подходит, когда памяти впритык, а качество критично.
- GPTQ. Постслойное квантование до 4 бит с компенсацией ошибки по вторым производным. Хорошо работает на GPU, требует калибровочного набора данных.
- AWQ (Activation-aware Weight Quantization). Защищает небольшой процент «значимых» весов, определяемых по активациям; обычно сохраняет качество лучше GPTQ при той же разрядности.
- GGUF (k-quants: Q4_K_M, Q5_K_S и др.). Формат контейнера llama.cpp с блочным квантованием: разные слои получают разную точность. Самый удобный путь для CPU и гибридного CPU+GPU запуска.
Как читать обозначения GGUF: Q4_K_M означает 4-битное квантование, k-quant-схему, средний (Medium) профиль распределения точности по слоям. S — меньше размер и чуть ниже качество, L — наоборот.
Что важно понимать:
- Квантование сжимает веса, а не активации и не KV-кэш. Память под контекст растёт линейно с длиной контекста и остаётся в высокой точности — при длинном контексте она может превышать объём весов. Как управлять контекстом — в статье про контекстное окно.
- Качество деградирует не линейно. Переход FP16 → Q8 почти незаметен, Q8 → Q5 малозаметен, Q5 → Q4 заметен на сложных задачах, Q3 и ниже — существенная потеря.
- Влияние зависит от задачи. Суммаризация и извлечение фактов деградируют медленнее, чем рассуждения и генерация кода.
Практика: выбор кванта под железо
Ориентировочные требования для модели 7–8B (веса + KV-кэш на контекст 8K):
| Квант | Размер весов | Где запускается |
|---|---|---|
| Q8_0 | ~8 ГБ | GPU 12 ГБ, CPU с 16 ГБ RAM |
| Q5_K_M | ~5.5 ГБ | GPU 8 ГБ, CPU с 16 ГБ RAM |
| Q4_K_M | ~4.5 ГБ | GPU 6 ГБ, CPU с 8–16 ГБ RAM |
| Q3_K_M | ~3.7 ГБ | CPU с 8 ГБ RAM, компромисс по качеству |
Практические шаги:
- Начинайте с Q4_K_M или Q5_K_M. Это точка баланса для большинства задач.
- Измеряйте на своих задачах, а не по средним бенчмаркам. Соберите набор из 20–50 реальных запросов и сравните ответы разных квантов — методика в статье про eval для LLM-приложений.
- Учитывайте разницу CPU/GPU. На CPU квантование даёт больший прирост скорости, потому что снимает ограничение пропускной способности памяти; на мощном GPU разница между Q8 и Q4 может быть небольшой.
- Проверяйте, что модель не «уехала» в swap. Если веса не помещаются в RAM, система начинает использовать диск, и скорость падает на порядок. Диагностика памяти — в статье про утечки и анализ памяти Python.
Запуск GGUF-модели:
# загрузка модели и запуск на CPU с частичным оффлоадом слоёв на GPU
./llama-cli -m qwen2.5-7b-instruct-q4_k_m.gguf \
--ctx-size 8192 --n-gpu-layers 20 --threads 8
# проверка фактических характеристик запуска
./llama-cli -m model.gguf --verbose 2>&1 | grep -Ei "llama_|kv self|model size"
Практический сценарий: модель «поглупела» после перехода на Q4
Контекст: локальный ассистент для разбора логов; после замены Q5_K_M на Q4_K_M ответы стали хуже: модель путает имена сервисов и обрезает выводы.
- Проверка гипотезы. Прогоняем один и тот же набор из 30 запросов на Q5 и Q4 с одинаковыми параметрами генерации: в 6 случаях Q4 даёт неверный ответ, в 3 — теряет детали.
- Уточнение причины. Оказалось, что проблема усиливается на длинном входе: при 6K токенов контекста часть слоёв работает с меньшей точностью, а ошибки накапливаются. Дополнительно температура 0.9 усиливала расхождения, поэтому часть «поглупения» давали параметры генерации — см. sampling-параметры.
- Решение. Возвращаем Q5_K_M для задач разбора и оставляем Q4_K_M для коротких запросов (классификация, извлечение полей). Уменьшаем контекст до фактически необходимого: 4K вместо 8K.
- Проверка. На наборе из 30 запросов расхождение с эталоном падает с 6 до 1 случая; скорость остаётся приемлемой.
- Профилактика. Фиксируем правило: смена кванта — это изменение модели, поэтому требует прогона тестового набора, а не «просто поменять файл».
Результат: качество восстановлено без возврата к тяжёлому кванту везде. Вывод: квантование — инженерный компромисс, который нужно измерять на своих задачах, а не выбирать по максимальному сжатию.
FAQ
Можно ли квантовать модель самостоятельно?
Да: llama.cpp предоставляет llama-quantize для конвертации в GGUF, для GPTQ/AWQ есть реализации в экосистеме Hugging Face. Для GPTQ и AWQ нужен калибровочный набор — обычно несколько сотен примеров, близких к вашей задаче; без него качество заметно хуже.
Почему Q4_K_M иногда быстрее Q8, а иногда медленнее? Скорость упирается в чтение весов из памяти: меньше байт — быстрее. Но более агрессивные схемы квантования добавляют вычислительные операции на распаковку, поэтому на мощном GPU с быстрой памятью выигрыш может исчезнуть.
Влияет ли квантование на длину контекста? Напрямую нет: KV-кэш не квантуется в типовых настройках. Но поскольку веса занимают меньше памяти, освобождается место под больший контекст — это главный практический выигрыш на устройствах с ограниченной памятью.
Что выбрать для серверного инференса с высокой нагрузкой? Для GPU-сервера обычно берут AWQ или GPTQ в связке с движком, поддерживающим непрерывное батчингирование, — например vLLM. Для CPU и гибридных сценариев — GGUF. Подробности сервинга — в статье про vLLM.
Источники: llama.cpp (GitHub), Hugging Face Transformers (quantization), AWQ paper — ссылки в шапке.