При скачивании локальной 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
На первый взгляд это выглядит как набор случайных суффиксов. На самом деле в имени зашито сразу несколько вещей:
Ниже — практическая расшифровка всей этой номенклатуры.
Обычные веса модели могут храниться в 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
→ обычно больше ошибка квантования
Q4_K_MКлассическое имя:
Q4_K_M
можно читать так:
Q4 — примерно 4-битный класс
K — семейство K-quants
M — Medium-рецепт
Это один из самых популярных форматов llama.cpp.
Исторически именно Q4_K_M долгое время был универсальным sweet spot:
Для очень многих моделей, если нет жёсткого дефицита памяти, Q4_K_M остаётся хорошей отправной точкой.
До 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 обычно даёт лучшее качество при сопоставимом размере.
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
чуть больше и обычно качественнее.
В актуальном 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-ов конкретной модели и от рецепта квантования.
Но для понимания относительного масштаба таблица полезна.
Отдельное семейство:
IQ2_XXS
IQ2_XS
IQ3_XXS
IQ3_S
IQ4_XS
IQ4_NL
Это I-quants — более сложные схемы квантования, особенно интересные при низком количестве бит на вес.
Они не являются разновидностью K-quants.
То есть:
Q4_K_M
и
IQ4_NL
— разные алгоритмы.
IQ4_NL: что означает NLIQ4_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
IQ4_XS: чем отличается от IQ4_NLIQ4_XS
— другая I-quant схема.
В llama.cpp она имеет примерно:
4.25 bpw
То есть она компактнее IQ4_NL.
Поэтому нельзя читать названия как:
NL < XS
или:
XS = автоматически хуже
Это разные структуры квантования.
Практически:
IQ4_XS
→ меньше размер
IQ4_NL
→ немного больший битовый бюджет
Какой вариант даст лучший результат на конкретной архитектуре, лучше смотреть по benchmark/KL-divergence или проверять на своих задачах.
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 по модель-специфическому рецепту.
Классическая 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 бит».
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.
Возьмём:
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
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-модели сопоставимого общего размера.
Допустим, у нас 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
Вес модели и 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.
Это надо проверять на конкретной задаче.
У обычного 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.
Реальный рабочий вариант на суммарных 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.
Некоторые новые модели обучаются с Multi-Token Prediction.
Вместо обычной схемы:
основная модель
→ следующий токен
→ снова основная модель
→ следующий токен
добавляется обученный MTP/NextN-модуль, который пытается дешево предложить будущие токены.
Затем основная модель проверяет draft.
Это разновидность speculative decoding.
Если модель распространяется отдельно как:
Qwen3.6-35B-A3B-GGUF
и:
Qwen3.6-35B-A3B-MTP-GGUF
то для MTP нужен GGUF, содержащий необходимые дополнительные веса.
То есть обычный:
Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
нельзя автоматически превратить в MTP-модель одной серверной опцией.
Нужна MTP-версия весов.
Пример:
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 неверный, часть предложений отвергается.
--spec-draft-n-max 3 или 4Runtime может поддерживать более длинный 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 пытается предсказывать новые токены.
-np 1В llama-server:
-np 1
— это один parallel slot.
Эквивалентно по смыслу:
--parallel 1
То есть сервер обслуживает одну последовательность одновременно.
Для одного локального coding-agent это обычно правильный вариант:
вся доступная память
→ одному длинному context
В текущем MTP-режиме Qwen3.6 Unsloth отдельно предупреждает, что:
-np > 1
пока не поддерживается.
Очень грубо:
| 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 | память почти не ограничивает |
Обычно разумнее:
сильная 30–35B модель в хорошем Q4
чем:
слабая 14B модель в Q8
Квантование Q4 обычно не превращает сильную модель в слабую.
А разница между архитектурой/размером/обучением моделей может быть намного больше, чем разница между Q4 и Q6.
Поэтому порядок выбора такой:
Для локального агента особенно важны:
Поэтому максимальный quant весов сам по себе не является целью.
Иногда:
Q4_K_M + 80k context
проиграет:
IQ4_NL + 130k context + MTP
даже если первая модель немного точнее на коротком benchmark.
Для агента надо тестировать весь inference stack.
Если хочется максимально простого правила:
Берите:
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
Использовать стоит, когда альтернатива — вообще не запустить нужную по интеллекту модель.
Если модель типа Qwen3.6-35B-A3B влезает полностью на GPU:
UD-Q4_K_M
+
Q4 KV
+
максимально возможный context
UD-IQ4_NL / UD-IQ4_XS
+
более длинный context
+
возможно Q8 KV
+
возможно MTP
UD-Q4_K_XL
может дать ещё более щадящий model-specific recipe.
Но выбирать между ними лучше не по названию файла, а по трём метрикам:
качество на вашей задаче
tokens/sec
максимальный стабильный context
Для локального 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