Как выбирать GGUF-квантование для локальной LLM: Q4_K_M, IQ4_NL, UD, K, S/M/L/XL и MTP

При скачивании локальной LLM легко столкнуться с десятками файлов с названиями вроде:

Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf
Qwen3.6-35B-A3B-UD-IQ4_XS.gguf
Qwen3.6-35B-A3B-UD-IQ4_NL.gguf

На первый взгляд это выглядит как набор случайных суффиксов. На самом деле в имени зашито сразу несколько вещей:

  • какая это модель;
  • сколько у неё параметров;
  • MoE она или dense;
  • какой алгоритм квантования используется;
  • насколько агрессивно сжаты веса;
  • применяется ли модель-специфический рецепт Unsloth Dynamic;
  • иногда — есть ли дополнительные веса для speculative decoding / MTP.

Ниже — практическая расшифровка всей этой номенклатуры.


1. Что вообще делает квантование

Обычные веса модели могут храниться в BF16/FP16, то есть примерно по 16 бит на параметр.

Условная модель на 35 млрд параметров в BF16 требует порядка:

35B × 2 байта ≈ 70 ГБ

Не считая KV-cache, рабочих буферов и других структур.

Квантование уменьшает точность хранения весов:

BF16 / FP16   ≈ 16 bit/weight
Q8            ≈ 8 bit/weight
Q6            ≈ 6 bit/weight
Q5            ≈ 5 bit/weight
Q4            ≈ 4–5 bit/weight
Q3            ≈ 3–4 bit/weight
Q2            ≈ 2–3 bit/weight

Это не точные значения размера файла. У большинства современных схем есть scales, superblocks и другие служебные данные, поэтому реальный показатель удобнее называть bpw — bits per weight.

Главный компромисс очевиден:

меньше bpw
→ меньше файл
→ меньше VRAM/RAM
→ обычно больше ошибка квантования

2. Что означает Q4_K_M

Классическое имя:

Q4_K_M

можно читать так:

Q4      — примерно 4-битный класс
K       — семейство K-quants
M       — Medium-рецепт

Это один из самых популярных форматов llama.cpp.

Исторически именно Q4_K_M долгое время был универсальным sweet spot:

  • модель заметно меньше BF16;
  • деградация качества обычно умеренная;
  • kernels хорошо поддерживаются;
  • скорость хорошая;
  • формат широко совместим с llama.cpp и производными.

Для очень многих моделей, если нет жёсткого дефицита памяти, Q4_K_M остаётся хорошей отправной точкой.


3. Что такое K-quants

До K-quants часто использовались более простые варианты:

Q4_0
Q4_1
Q5_0
Q5_1

Они квантуют небольшие блоки весов относительно простой схемой.

K-quants используют более сложную блочную структуру с superblocks, локальными scales и различными рецептами для разных tensor types.

Поэтому:

Q4_K_M

и

Q4_0

— это не просто две записи одного и того же «4-битного» формата.

Q4_K_M обычно даёт лучшее качество при сопоставимом размере.


4. Что означают S, M, L

В старой номенклатуре llama.cpp встречаются:

Q3_K_S
Q3_K_M
Q3_K_L

Q4_K_S
Q4_K_M

Q5_K_S
Q5_K_M

Упрощённо:

S = Small
M = Medium
L = Large

Но важно: это не просто разные block size и не буквально «4.0 / 4.5 / 5.0 бит».

Это разные рецепты смешанного квантования.

Например, одна часть tensor-ов может храниться в более агрессивном формате, а чувствительные tensor-ы — в более точном.

Поэтому:

Q4_K_S

обычно чуть меньше,

а:

Q4_K_M

чуть больше и обычно качественнее.


5. Реальные цифры llama.cpp

В актуальном llama-quantize для эталонной Llama-3-8B приводятся примерно такие варианты:

Quant Примерный класс
Q3_K_S ~3.4 bpw
Q3_K_M ~3.7 bpw
Q3_K_L ~4.0 bpw
IQ4_XS 4.25 bpw
Q4_K_S ~4.4 bpw
IQ4_NL 4.50 bpw
Q4_K_M ~4.6 bpw
Q5_K_S ~5.2 bpw
Q5_K_M ~5.3 bpw
Q6_K ~6.1 bpw

Эти числа не надо переносить один в один на любую архитектуру: итоговый размер зависит от состава tensor-ов конкретной модели и от рецепта квантования.

Но для понимания относительного масштаба таблица полезна.


6. Что такое IQ-quants

Отдельное семейство:

IQ2_XXS
IQ2_XS
IQ3_XXS
IQ3_S
IQ4_XS
IQ4_NL

Это I-quants — более сложные схемы квантования, особенно интересные при низком количестве бит на вес.

Они не являются разновидностью K-quants.

То есть:

Q4_K_M

и

IQ4_NL

— разные алгоритмы.


7. IQ4_NL: что означает NL

IQ4_NL

означает 4-битное non-linear quantization.

В отличие от простого равномерного отображения диапазона весов на 16 уровней, здесь используется нелинейная сетка значений.

Интуитивно это можно представить так.

Линейная сетка:

-1.0  -0.87  -0.73  ...  0  ...  0.73  0.87  1.0

Нелинейная:

-1.0  -0.65  -0.40  -0.25  -0.14 ... 0 ... 0.14 0.25 0.40 0.65 1.0

Это только иллюстрация, не реальные значения codebook.

Идея в том, что уровни можно разместить там, где они лучше соответствуют реальному распределению весов нейросети.

В актуальном llama.cpp:

IQ4_NL = 4.50 bpw

8. IQ4_XS: чем отличается от IQ4_NL

IQ4_XS

— другая I-quant схема.

В llama.cpp она имеет примерно:

4.25 bpw

То есть она компактнее IQ4_NL.

Поэтому нельзя читать названия как:

NL < XS

или:

XS = автоматически хуже

Это разные структуры квантования.

Практически:

IQ4_XS
→ меньше размер

IQ4_NL
→ немного больший битовый бюджет

Какой вариант даст лучший результат на конкретной архитектуре, лучше смотреть по benchmark/KL-divergence или проверять на своих задачах.


9. Что такое UD-

Вот здесь появилась более новая часть номенклатуры:

UD-Q4_K_M
UD-Q4_K_XL
UD-IQ4_XS
UD-IQ4_NL

UD означает Unsloth Dynamic.

Это не новый базовый GGUF datatype.

Это модель-специфический рецепт квантования, который Unsloth накладывает поверх типов llama.cpp.

Основная идея Dynamic 2.0:

разные слои и tensor-ы модели имеют разную чувствительность к ошибке квантования, поэтому нет смысла квантизовать всю модель абсолютно одинаково.

Unsloth калибрует конкретную модель и для разных частей может выбирать разные типы и точность.

То есть:

UD-Q4_K_M

не обязательно означает:

каждый tensor модели физически хранится как Q4_K_M.

Скорее это означает:

базовый бюджет и класс модели близок к Q4_K_M, но часть tensor-ов может быть upcast/downcast по модель-специфическому рецепту.


10. Зачем Dynamic-квантование особенно полезно современным моделям

Классическая Llama относительно однородна:

Attention
MLP
Attention
MLP
...

Современные модели могут включать:

Attention
MoE experts
MoE routers
Gated DeltaNet
gates
shared experts
embeddings
output head

Все эти компоненты могут иметь разную чувствительность к квантованию.

Например, условный рецепт может выглядеть так:

MoE expert weights       → Q4
attention projection     → Q5
router                    → Q6
отдельные чувствительные → ещё выше

Конкретный рецепт зависит от модели.

Именно поэтому одинаковая надпись Q4 у современных dynamic GGUF уже не всегда означает «каждый вес модели ужат одинаково до 4 бит».


11. Что означает XL

У Unsloth появились варианты вроде:

UD-Q2_K_XL
UD-Q3_K_XL
UD-Q4_K_XL

Это уже не классический llama.cpp суффикс S/M/L.

XL относится к рецептам Unsloth Dynamic.

Например, для некоторых MoE-моделей Unsloth описывает:

UD-Q3_K_XL
→ MoE в основном Q3_K_M
→ attention upcasted

UD-Q4_K_XL
→ MoE в основном Q4_K_M
→ attention upcasted

Поэтому XL лучше воспринимать как:

более щадящий dynamic-рецепт с дополнительным битовым бюджетом для чувствительных частей,

а не как универсальный новый datatype llama.cpp.


12. Как читать полное имя модели

Возьмём:

Qwen3.6-35B-A3B-UD-Q4_K_M.gguf

Разбираем:

Qwen3.6
│
├─ семейство модели
│
35B
│
├─ всего около 35 млрд параметров
│
A3B
│
├─ MoE: около 3 млрд параметров активно на токен
│
UD
│
├─ Unsloth Dynamic quantization recipe
│
Q4
│
├─ примерно 4-битный класс
│
K
│
├─ K-quant family
│
M
│
└─ Medium recipe

13. MoE: почему 35B-A3B важно для локального запуска

Запись:

35B-A3B

обычно означает:

35B total parameters
3B activated parameters per token

Это Mixture-of-Experts.

Отсюда два разных требования:

Память

Хранить всё равно надо почти все 35B весов:

VRAM/RAM зависит от total parameters

Скорость вычисления

На каждый токен используется только часть экспертов:

compute ближе к activated parameters

Поэтому MoE может занимать память как большая модель, но генерировать токены заметно быстрее dense-модели сопоставимого общего размера.


14. Почему «самый большой quant, который влезает» не всегда лучший вариант

Допустим, у нас 24 ГБ VRAM.

Можно выбрать:

Q4_K_M weights
100k context
Q4 KV-cache

или:

IQ4_NL weights
132k context
Q8 KV-cache
MTP

Вторая модель имеет чуть сильнее сжатые веса, но вся система может оказаться лучше для coding-agent.

Поэтому выбирать надо не только quant весов.

Нужно учитывать одновременно:

качество весов
+
длина контекста
+
точность KV-cache
+
runtime buffers
+
speculative decoding
+
скорость prompt processing
+
скорость generation

15. KV-cache — отдельная память

Вес модели и KV-cache — разные вещи.

Например:

--cache-type-k q4_0
--cache-type-v q4_0

говорит llama.cpp хранить K/V cache в квантованном формате.

Можно использовать и более точный вариант:

--cache-type-k q8_0
--cache-type-v q8_0

Компромисс:

Q4 KV
→ меньше VRAM
→ можно увеличить context

Q8 KV
→ больше VRAM
→ меньше ошибка KV quantization

Для агента на длинном контексте дополнительные десятки тысяч токенов иногда полезнее, чем переход KV с Q4 на Q8.

Это надо проверять на конкретной задаче.


16. Контекст может стоить очень по-разному у разных архитектур

У обычного full-attention Transformer KV-cache растёт примерно линейно с контекстом:

context × layers × KV heads × head dimension

Но современные hybrid-модели могут иметь attention только в части слоёв.

Например, Qwen3.6-35B-A3B использует гибрид:

10 × (
    3 × Gated DeltaNet
    +
    1 × Gated Attention
)

То есть полноценный attention есть только в части слоёв.

Поэтому 100k–130k контекста у такой модели может оказаться заметно дешевле по памяти, чем у обычного 35B full-attention Transformer.


17. Практический пример: 2× RTX 3060 12 ГБ

Реальный рабочий вариант на суммарных 24 ГБ VRAM:

CUDA_VISIBLE_DEVICES=0,1 ./llama-server \
  -m ./models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf \
  --alias Qwen3.6-35B \
  --host 127.0.0.1 \
  --port 8080 \
  -c 100000 \
  -ngl 99 \
  --parallel 1 \
  --flash-attn auto \
  --cache-type-k q4_0 \
  --cache-type-v q4_0 \
  --jinja

Это интересный пример того, почему нельзя оценивать модель только по надписи 35B.

Здесь одновременно работают:

MoE
+
4-bit quant
+
hybrid attention
+
quantized KV cache
+
2 GPU

В результате 35B-модель с большим контекстом может реально работать в 24 ГБ VRAM.


18. Что такое MTP / NextN

Некоторые новые модели обучаются с Multi-Token Prediction.

Вместо обычной схемы:

основная модель
→ следующий токен
→ снова основная модель
→ следующий токен

добавляется обученный MTP/NextN-модуль, который пытается дешево предложить будущие токены.

Затем основная модель проверяет draft.

Это разновидность speculative decoding.


19. MTP нельзя просто «включить флагом» для любого GGUF

Если модель распространяется отдельно как:

Qwen3.6-35B-A3B-GGUF

и:

Qwen3.6-35B-A3B-MTP-GGUF

то для MTP нужен GGUF, содержащий необходимые дополнительные веса.

То есть обычный:

Qwen3.6-35B-A3B-UD-Q4_K_M.gguf

нельзя автоматически превратить в MTP-модель одной серверной опцией.

Нужна MTP-версия весов.


20. Как MTP запускается в llama.cpp

Пример:

export LLAMA_CACHE="unsloth/Qwen3.6-35B-A3B-MTP-GGUF"

./llama.cpp/llama-server \
    -hf unsloth/Qwen3.6-35B-A3B-MTP-GGUF:UD-Q4_K_XL \
    -ngl 99 \
    -c 8192 \
    -fa on \
    -np 1 \
    --spec-type draft-mtp \
    --spec-draft-n-max 2

Здесь:

--spec-type draft-mtp

включает MTP drafter,

а:

--spec-draft-n-max 2

ограничивает максимальную длину speculative draft.

Важно: это не означает, что сервер всегда принимает два токена.

MTP может предложить несколько токенов, после чего target-модель их проверяет.

Если draft неверный, часть предложений отвергается.


21. Можно ли поставить --spec-draft-n-max 3 или 4

Runtime может поддерживать более длинный draft:

--spec-draft-n-max 3

или:

--spec-draft-n-max 4

Но это не гарантирует дополнительного ускорения.

Чем длиннее speculative chain:

тем больше потенциальный выигрыш

но одновременно:

тем ниже вероятность принять весь draft

Поэтому важная метрика — acceptance rate.

Для конкретной модели оптимум может быть:

1
2
3
4

и его лучше измерять benchmark-ом.

Unsloth для Qwen3.6 показывает пример с:

--spec-draft-n-max 2

а также более новый chained-вариант:

--spec-type ngram-mod,draft-mtp
--spec-draft-n-max 4

где ngram-механизм ловит повторяющиеся фрагменты из prompt, а MTP пытается предсказывать новые токены.


22. Что означает -np 1

В llama-server:

-np 1

— это один parallel slot.

Эквивалентно по смыслу:

--parallel 1

То есть сервер обслуживает одну последовательность одновременно.

Для одного локального coding-agent это обычно правильный вариант:

вся доступная память
→ одному длинному context

В текущем MTP-режиме Qwen3.6 Unsloth отдельно предупреждает, что:

-np > 1

пока не поддерживается.


23. Практическая шкала выбора quant-а

Очень грубо:

Quant Когда использовать
Q2 / IQ2 модель иначе вообще не помещается
Q3_K_S очень жёсткий дефицит памяти
Q3_K_M допустимый компромисс ради более большой модели
Q3_K_L / Dynamic XL попытка получить максимум из ~3–4 bpw
IQ4_XS хороший вариант при дефиците памяти
IQ4_NL более тяжёлый nonlinear 4-bit вариант
Q4_K_S базовый хороший 4-bit
Q4_K_M универсальный sweet spot
UD-Q4_K_XL больше битов чувствительным частям модели
Q5_K_M если хватает памяти и качество важнее размера
Q6_K очень небольшая деградация
Q8_0 память почти не ограничивает

24. Главное правило: сначала выбирать модель, потом quant

Обычно разумнее:

сильная 30–35B модель в хорошем Q4

чем:

слабая 14B модель в Q8

Квантование Q4 обычно не превращает сильную модель в слабую.

А разница между архитектурой/размером/обучением моделей может быть намного больше, чем разница между Q4 и Q6.

Поэтому порядок выбора такой:

  1. Выбрать самую сильную модель, подходящую под задачу.
  2. Определить необходимый контекст.
  3. Посчитать память под KV-cache и runtime.
  4. Найти самый качественный quant, который стабильно помещается.
  5. Только после этого оптимизировать KV-cache и speculative decoding.

25. Для coding-agent требования отличаются от обычного чата

Для локального агента особенно важны:

  • tool calling;
  • соблюдение JSON/schema;
  • repository-level reasoning;
  • длинный контекст;
  • скорость prefill;
  • cache reuse;
  • generation throughput;
  • стабильность при десятках последовательных шагов.

Поэтому максимальный quant весов сам по себе не является целью.

Иногда:

Q4_K_M + 80k context

проиграет:

IQ4_NL + 130k context + MTP

даже если первая модель немного точнее на коротком benchmark.

Для агента надо тестировать весь inference stack.


26. Быстрый алгоритм выбора GGUF

Если хочется максимально простого правила:

Памяти много

Берите:

Q5_K_M / Q6_K

Нужен хороший универсальный баланс

Начинайте с:

Q4_K_M

или его качественного Dynamic-варианта.

Чуть не помещается

Смотрите:

IQ4_NL
IQ4_XS
Q4_K_S

Всё ещё не помещается

Переходите к:

Q3_K_L
Q3_K_M
Dynamic Q3_K_XL

Q2

Использовать стоит, когда альтернатива — вообще не запустить нужную по интеллекту модель.


27. Что я бы выбирал для 24 ГБ VRAM и длинного agent context

Если модель типа Qwen3.6-35B-A3B влезает полностью на GPU:

Вариант A — качество весов

UD-Q4_K_M
+
Q4 KV
+
максимально возможный context

Вариант B — больше запаса памяти

UD-IQ4_NL / UD-IQ4_XS
+
более длинный context
+
возможно Q8 KV
+
возможно MTP

Вариант C — если помещается

UD-Q4_K_XL

может дать ещё более щадящий model-specific recipe.

Но выбирать между ними лучше не по названию файла, а по трём метрикам:

качество на вашей задаче
tokens/sec
максимальный стабильный context

28. Что benchmark-ить самому

Для локального AI-agent я бы сравнивал минимум:

1. prompt processing tok/s
2. generation tok/s
3. VRAM на полном context
4. tool-call success rate
5. JSON/schema validity
6. качество на собственных coding tasks
7. MTP acceptance rate
8. стабильность после 20–50 agent turns

Perplexity полезна, но для агента она далеко не полностью описывает реальное качество.


Короткий итог

Если упростить всю статью до нескольких правил:

Q4_K_M
= хороший классический универсальный quant

K
= семейство K-quants

S / M / L
= разные рецепты размера/качества, а не просто число бит

IQ
= отдельное семейство importance-aware / nonlinear quants

IQ4_XS
= примерно 4.25 bpw

IQ4_NL
= примерно 4.50 bpw nonlinear quant

UD
= Unsloth Dynamic: модель-специфический mixed-quant recipe

XL
= более щадящий Dynamic-рецепт Unsloth, а не стандартный datatype llama.cpp

A3B
= у MoE из общего числа параметров около 3B активны на токен

MTP / NextN
= speculative decoding с дополнительными обученными весами

А главный принцип выбора такой:

Не ищите самый высокий quant. Ищите лучший баланс модели, quant-а, длины контекста, KV-cache и скорости именно для вашей задачи.

Для локального coding-agent хороший Q4 большой модели с длинным контекстом зачастую полезнее, чем почти lossless quant меньшей модели.


Источники

  • llama.cpp — quantize README:
    https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md

  • llama.cpp — актуальный список quant types и bpw:
    https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/quantize.cpp

  • llama.cpp Wiki — Tensor Encoding Schemes:
    https://github.com/ggml-org/llama.cpp/wiki/Tensor-Encoding-Schemes

  • Unsloth Dynamic v2.0 GGUFs:
    https://unsloth.ai/blog/dynamic-v2

  • Qwen3.6-35B-A3B GGUF:
    https://huggingface.co/unsloth/Qwen3.6-35B-A3B-GGUF

  • Qwen3.6-35B-A3B MTP GGUF:
    https://huggingface.co/unsloth/Qwen3.6-35B-A3B-MTP-GGUF