Free-LLMs

Квантование LLM и формат GGUF: как выбрать Q4, Q5 и Q8

Считаем размер GGUF по биту на вес и память под контекст, чтобы выбрать квант под свою видеокарту.

Local AI
Квантование и GGUF
🤖
Мониторинг бесплатных моделей в Telegram Бот @freellms_bot присылает новые бесплатные модели и AI-акции.
→

Если коротко: для большинства локальных задач берите Q4_K_M, при запасе в 1-2 ГБ поднимайтесь до Q5_K_M, а Q6_K и Q8_0 оставляйте для случаев, когда память некуда девать или важна максимальная близость к исходной модели. Размер файла считается по формуле «параметры × бит на вес / 8», а на длинном контексте решающим становится не файл модели, а KV-кэш. Эта статья дополняет обзор запуска LLM локально: там выбор программы и грубое правило «0,6 ГБ на миллиард параметров», здесь точный расчёт памяти и разбор квантований.

Что такое GGUF

По спецификации в репозитории ggml, GGUF — формат файла для хранения моделей под инференс на GGML и основанных на нём исполнителях. Это бинарный формат для быстрой загрузки, наследник GGML, GGMF и GGJT. Цели формата по документации: развёртывание одним файлом, расширяемость без поломки совместимости и поддержка mmap. Расшифровку аббревиатуры спецификация не даёт, поэтому популярную расшифровку «GPT-Generated Unified Format» мы не используем и опираемся только на то, что написано в документации.

Внутри один файл: метаданные в виде пар «ключ-значение» (архитектура, длина контекста, токенизатор, версия квантования) и тензоры с весами. Из-за этого модели не нужен отдельный конфиг, а имя файла несёт описание: в спецификации предложена схема BaseName-SizeLabel-FineTune-Version-Encoding-Shard.gguf, например Grok-100B-v1.0-Q4_0-00003-of-00009.gguf. Последний кусок перед расширением, Q4_0, и есть схема кодирования весов.

Как читать Q4_K_M

  • Цифра — примерная разрядность весов: Q4 около 4 бит, Q8 около 8.
  • Буква K означает семейство k-квантов: веса режутся на блоки со своими масштабами, и разные тензоры получают разную точность.
  • Суффикс S, M, L — вариант смеси типов тензоров: Q4_K_S в среднем даёт 4,67 бита на вес, Q4_K_M — 4,89.
  • Q8_0 — простая блочная схема без k: 32 восьмибитных значения плюс масштаб.
  • Префикс IQ (IQ2, IQ3, IQ4_XS) — i-кванты, в основном для сильного сжатия до 1-3 бит (есть и IQ4_XS около 4,5 бита).

Размер файла: формула и расчёт

Размер в байтах равен числу параметров, умноженному на среднее число бит на вес и делённому на 8. Среднее считается по всем тензорам: часть из них в смеси Q4_K_M хранится точнее, поэтому итог не 4, а 4,89 бита. Реальные значения есть в документации llama-quantize, где измерены варианты для Llama 3.1 8B:

КвантованиеБит на весРазмер, ГиБ (Llama 3.1 8B)
Q4_K_M4,89444,58
Q5_K_M5,70365,33
Q6_K6,56336,14
Q8_08,50087,95
F1616,000514,96

Проверим формулу. Из строки F16 получаем число параметров: 14,96 ГиБ × 230 × 8 / 16,0005 ≈ 8,03 млрд. Тогда для Q4_K_M: 8,03 млрд × 4,8944 / 8 ≈ 4,91 ГБ, или 4,58 ГиБ. Совпало с таблицей. Цифра 8,5 бита у Q8_0 объясняется устройством блока: 32 значения по 8 бит плюс масштаб в 16 бит, всего 272 бита на 32 веса.

Теперь та же формула для типичных размеров. Расчёт для номинальных 8, 14 и 32 млрд параметров с бит на вес из таблицы выше: размер (ГБ) = N (млрд) × бит / 8.

МодельQ4_K_M (4,8944)Q5_K_M (5,7036)Q6_K (6,5633)Q8_0 (8,5008)
8B: 8 × бит / 84,89 ГБ5,70 ГБ6,56 ГБ8,50 ГБ
14B: 14 × бит / 88,57 ГБ9,98 ГБ11,49 ГБ14,88 ГБ
32B: 32 × бит / 819,58 ГБ22,81 ГБ26,25 ГБ34,00 ГБ

Это оценка, а не обещание на байт. Бит на вес чуть отличается от модели к модели, потому что зависит от набора тензоров, а число параметров у модели обычно не круглое (у Llama 3.1 8B оно около 8,03 млрд). ГБ здесь десятичные, а в таблице выше ГиБ двоичные: 1 ГиБ равен 1,074 ГБ. Если у модели есть vision-часть, к размеру добавляется отдельный файл mmproj, который документация советует держать в bf16 или q8.

Память на контекст: KV-кэш

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

байт на токен = 2 × слоёв × KV-голов × размер головы × байт на элемент
память кэша   = байт на токен × длина контекста

Параметры берутся из config.json модели. Для семейства Qwen3 в конфигах на Hugging Face указано: 8B — 36 слоёв, 14B — 40 слоёв, 32B — 64 слоя; у всех три размера по 8 KV-голов и размер головы 128. В f16 (2 байта на элемент):

МодельРасчёт на токенКиБ на токен8 тыс. токенов32 тыс. токенов
Qwen3 8B2 × 36 × 8 × 128 × 2 байта144 КиБ1,13 ГиБ4,5 ГиБ
Qwen3 14B2 × 40 × 8 × 128 × 2 байта160 КиБ1,25 ГиБ5,0 ГиБ
Qwen3 32B2 × 64 × 8 × 128 × 2 байта256 КиБ2,0 ГиБ8,0 ГиБ

Кэш можно квантовать. В FAQ Ollama про типы кэша сказано так: q8_0 занимает примерно половину памяти от f16 с очень малой потерей точности, обычно без заметного влияния на качество; q4_0 примерно четверть памяти при потере, которая может быть заметнее на больших контекстах. Значит, 32B на 32 тысячах токенов даст около 4 ГиБ в q8_0 и около 2 ГиБ в q4_0 вместо 8. Квантование кэша в Ollama работает при включённом Flash Attention.

Складываем на примере 32B на видеокарте с 24 ГБ. Q4_K_M: 19,58 ГБ. Кэш на 8 тысяч токенов в f16: 2 ГиБ, то есть около 2,15 ГБ, итого примерно 21,7 ГБ, остаётся около 2 ГБ запаса под вычислительные буферы и систему. Кэш на 32 тысячи в f16 даёт примерно 28,2 ГБ: не помещается. С q8_0 это 19,58 + 4,3 = около 23,9 ГБ, впритык, и на практике вы упрётесь в память. Вывод: на 24 ГБ 32B комфортно живёт при 8-16 тысячах токенов, а длинный контекст требует либо квантования кэша, либо модели меньше.

Совместимость: llama.cpp, Ollama, LM Studio

llama.cppOllamaLM Studio
Источник GGUFСвой файл или -hf user/model:tagБиблиотека Ollama или импорт через ModelfileЗагрузчик из Hugging Face
Квантование самомуllama-quantizeНет: импорт не квантует GGUF, подготовьте файл в llama-quantizeНет, выбираете готовый вариант
Квантование KV-кэша-ctk, -ctvOLLAMA_KV_CACHE_TYPE, глобально для всех моделейFlash Attention и контекст в параметрах загрузки модели
Длина контекста-cnum_ctx; по умолчанию 4k при VRAM меньше 24 ГиБВ параметрах модели

Для LM Studio в документации по загрузке сказано, что варианты вроде Q3_K_S или Q_8 — копии одной модели с разной точностью, и рекомендуется брать 4-битный вариант или выше, если позволяет машина. Параметры загрузки (выгрузка на GPU, размер контекста, Flash Attention) сохраняются для каждой модели.

Команды

Конвертация и квантование по README llama-quantize: сначала исходные веса в GGUF высокой точности, потом квантование.

# 1. Конвертация из Hugging Face в bf16 GGUF
python convert_hf_to_gguf.py --outfile model-bf16.gguf --outtype bf16 --remote Qwen/Qwen3-14B

# 2. Простое квантование
./build/bin/llama-quantize model-bf16.gguf model-Q4_K_M.gguf Q4_K_M

# 3. С матрицей важности (калибровочный текст свой)
./build/bin/llama-imatrix -m model-bf16.gguf -f calibration.txt -o imatrix.gguf
./build/bin/llama-quantize --imatrix imatrix.gguf model-bf16.gguf model-Q4_K_M.gguf Q4_K_M

Документация предупреждает, что --allow-requantize (повторное квантование уже сжатой модели) может сильно ухудшить качество по сравнению с квантованием из 16 или 32 бит, поэтому исходник держите в bf16 или f16. Матрица важности, по тому же README, помогает минимизировать потерю точности.

Запуск сервера с ограничением контекста и квантованным кэшем:

llama-server -m model-Q4_K_M.gguf -c 16384 -ngl 99 \
  -fa on -ctk q8_0 -ctv q8_0 --port 8080

# или сразу с Hugging Face, выбрав квант тегом
llama-server -hf ggml-org/gemma-3-4b-it-GGUF:Q4_K_M

Допустимые типы для -ctk и -ctv в документации сервера: f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1; по умолчанию f16. Flash Attention по умолчанию стоит в режиме auto.

Ollama: свой GGUF подключается через Modelfile, справочник по Modelfile описывает инструкции FROM, PARAMETER и SYSTEM.

# Modelfile
FROM ./model-Q5_K_M.gguf
PARAMETER num_ctx 16384
PARAMETER temperature 0.6
SYSTEM Ты помощник, отвечай кратко и по делу.
OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 ollama serve

ollama create my-model-q5 -f Modelfile
ollama run my-model-q5
ollama ps    # сколько памяти занято и на каком устройстве

Если шаблон чата из метаданных GGUF не подхватился, добавьте инструкцию TEMPLATE из карточки модели.

Качество после квантования

Фиксированного «Q4 теряет столько-то процентов» не существует: потеря зависит от модели, метода и теста. Документация llama.cpp измеряет её двумя метриками: перплексией (насколько хорошо модель предсказывает следующий токен на тексте, меньше лучше) и дивергенцией Кульбака-Лейблера (KLD), которая сравнивает распределения вероятностей квантованной и исходной модели. В README инструмента perplexity есть сравнение для Llama 3 8B на тексте Wikitext-2 (базовая модель, без imatrix):

КвантованиеPPLРост PPL к f16Средняя KLD
f166,2332—0,0006
Q8_06,23430,00270,0014
Q6_K6,25340,02170,0055
Q5_K_M6,28860,05700,0108
Q4_K_M6,40710,17550,0313
Q2_K9,75163,51990,4451

Читать таблицу надо осторожно. Это одна модель на одном корпусе, а документация сама оговаривает, что перплексия разных моделей несравнима, а числа llama.cpp не переносятся на другие проекты. Тенденция видна: между Q8_0, Q6_K и Q5_K_M различия на этом тесте малы, потеря Q4_K_M уже заметнее, а Q2_K — другой класс потерь. Но перплексия на энциклопедическом тексте ничего не говорит о том, как квантованная модель пишет код, держит формат JSON или следует длинной инструкции.

Свою потерю можно измерить командами из того же README: сначала сохраняется набор логитов исходной модели, затем квантованная сравнивается с ним. Файл логитов большой: для Wikitext-2 документация называет 11 ГиБ для LLaMA 2 и 37 ГиБ для LLaMA 3.

llama-perplexity -m model-f16.gguf -f wiki.test.raw --kl-divergence-base logits.kld
llama-perplexity -m model-Q4_K_M.gguf --kl-divergence-base logits.kld --kl-divergence

Для прикладного решения надёжнее прогнать два-три кванта через собственный набор задач, как в статье про сравнение LLM на своих задачах. Класс задач с точным ответом (извлечение полей, JSON, код) страдает от сжатия раньше, чем свободный диалог.

Скорость: больше бит значит медленнее

Генерация токенов упирается в чтение весов из памяти, поэтому более крупный квант обычно медленнее. В таблице README llama-quantize для Llama 3.1 8B (железо авторов, в сравнении разных квантов по строкам) скорость генерации на 128 токенах такая: Q4_K_M — 71,9 токена/с, Q5_K_M — 67,2, Q6_K — 58,7, Q8_0 — 50,9, F16 — 29,2. Абсолютные числа на вашем железе будут другими, а порядок сохранится.

Итого

  • Размер файла: параметры × бит на вес / 8. Для Q4_K_M берите 4,89 бита, Q5_K_M — 5,70, Q6_K — 6,56, Q8_0 — 8,50. Для 8B/14B/32B это 4,9/8,6/19,6 ГБ на Q4_K_M и 8,5/14,9/34,0 ГБ на Q8_0.
  • Прибавляйте KV-кэш: 2 × слоёв × KV-голов × размер головы × байт на токен. Квантование кэша в q8_0 вдвое сокращает эту часть.
  • Старт с Q4_K_M. Если остаётся запас памяти, берите Q5_K_M. Q6_K и Q8_0 имеют смысл, когда память свободна, а точность критична.
  • Ollama не квантует GGUF при импорте: готовьте файл в llama-quantize и подключайте через FROM.
  • Потерю качества измеряйте на своих задачах. Перплексия и KLD полезны для сравнения квантов одной модели, а не как универсальный процент.
  • Какой размер модели вообще брать под вашу задачу, разбирает статья выбор размера LLM.
FL
Редакция Free-LLMsКоманда каталога бесплатных LLM API. Проверяем лимиты провайдеров и тестируем модели и инструменты руками.

Читайте также