Если коротко: для большинства локальных задач берите 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_M | 4,8944 | 4,58 |
| Q5_K_M | 5,7036 | 5,33 |
| Q6_K | 6,5633 | 6,14 |
| Q8_0 | 8,5008 | 7,95 |
| F16 | 16,0005 | 14,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 × бит / 8 | 4,89 ГБ | 5,70 ГБ | 6,56 ГБ | 8,50 ГБ |
| 14B: 14 × бит / 8 | 8,57 ГБ | 9,98 ГБ | 11,49 ГБ | 14,88 ГБ |
| 32B: 32 × бит / 8 | 19,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 8B | 2 × 36 × 8 × 128 × 2 байта | 144 КиБ | 1,13 ГиБ | 4,5 ГиБ |
| Qwen3 14B | 2 × 40 × 8 × 128 × 2 байта | 160 КиБ | 1,25 ГиБ | 5,0 ГиБ |
| Qwen3 32B | 2 × 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.cpp | Ollama | LM Studio | |
|---|---|---|---|
| Источник GGUF | Свой файл или -hf user/model:tag | Библиотека Ollama или импорт через Modelfile | Загрузчик из Hugging Face |
| Квантование самому | llama-quantize | Нет: импорт не квантует GGUF, подготовьте файл в llama-quantize | Нет, выбираете готовый вариант |
| Квантование KV-кэша | -ctk, -ctv | OLLAMA_KV_CACHE_TYPE, глобально для всех моделей | Flash Attention и контекст в параметрах загрузки модели |
| Длина контекста | -c | num_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 |
|---|---|---|---|
| f16 | 6,2332 | — | 0,0006 |
| Q8_0 | 6,2343 | 0,0027 | 0,0014 |
| Q6_K | 6,2534 | 0,0217 | 0,0055 |
| Q5_K_M | 6,2886 | 0,0570 | 0,0108 |
| Q4_K_M | 6,4071 | 0,1755 | 0,0313 |
| Q2_K | 9,7516 | 3,5199 | 0,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.