Qwen3.8-27B · Pruned RU+EN+Code · IQ3_XXS (12 ГБ) + Q4_K_M (24 ГБ)
27-миллиардная Qwen, у которой вырезан «лишний» кусок словаря, и две сборки квантования: IQ3_XXS — целиком в 12 ГБ видеопамяти, Q4_K_M — на карту 24 ГБ. Не дистилляция, не файнтюн, не abliteration — веса модели не тронуты вообще. Изменён только токенизатор и две словарные матрицы (embeddings + lm_head), из которых удалены токены письменностей, не используемых в русско-английском рабочем тексте и коде: CJK, корейский, арабский, иврит, деванагари, тайский, греческий, армянский, грузинский и т. п.
248 320 → 172 822 токенов (−75 498, −30.4%)
−0.77B параметров словаря (embed + lm_head, 5120 строк на матрицу)
55.56 GB (BF16 оригинал) → 10.24 GiB (эта модель, IQ3_XXS)
Перплексия на held-out: ru −0.12%, en −0.02%, code −0.01% (квант-к-кванту)
🔹 Главная фишка: 27B-модель целиком в 12 ГБ видеопамяти
Сборка IQ3_XXS (10.235 GiB, 3.31 BPW) целиком помещается в VRAM карты 12 ГБ (RTX 3060 12GB / 2070 Super / 4070 / A2) — без офлоада на RAM, где CPU-гибрид даёт 1–2 токена/с и для диалога непригодна. Рабочий контекст: ~10–26k токенов при KV-кэше
q8_0, ~17–45k приq4_0.Спекулятивное декодирование — штатное, без отдельного draft-файла: в модели есть родной MTP-слой (
blk.64.nextn.*), работает--spec-type draft-mtp --draft 4.Плата за размер — качество кванта: PPL у IQ3_XXS на 4.5–6% выше, чем у Q4_K_M той же модели (см. раздел про перплексию). Если есть карта 24 ГБ — берите Q4_K_M-сборку из этого же репозитория, она статистически неотличима от оригинала.
Две сборки в одном репозитории
| IQ3_XXS | Q4_K_M | |
|---|---|---|
| Файл | qwen3.8-27b-pruned-enru-IQ3_XXS.gguf |
qwen3.8-27b-pruned-enru-Q4_K_M.gguf |
| Размер | 10 989 410 464 B (10.235 GiB) | 16 272 092 320 B (15.15 GiB) |
| BPW | 3.31 | 4.90 |
| Целевая карта | 12 ГБ | 24 ГБ (3090/4090/A5000) |
| Контекст | ~10–26k (q8_0), ~17–45k (q4_0) |
128k при q8_0 (нужно 20.7 GiB) |
| Иматрикс | обязателен (готовый файл встроен в историю сборки) | не нужен |
| PPL vs оригинал Q4_K_M | +4.4…+6.1% (через Q4_K_M-ступень) | −0.12…−0.01% |
Промежуточные ступени линейки (Q3_K_M 12.11 GiB — впритык без контекста; IQ2_M 8.88 GiB; IQ2_S 8.43 GiB — единственный способ дать 128k на 12 ГБ) в репозиторий не выложены: IQ3_XXS — лучший квант, который ещё оставляет 12-гигабайтной карте контекст.
Откуда эта модель (цепочка происхождения)
Прунить квантованный GGUF нельзя: блоки квантов разбиты на суперблоки, и разрезать такую матрицу «по строкам словаря» посередине блока невозможно. Поэтому прунинг делался на исходной HF-модели в BF16, а GGUF собирается и квантуется заново.
| Этап | Артефакт | Источник |
|---|---|---|
| 1. Оригинал (источник весов) | Qwen3.8-27B, BF16, 18 шардов, 55.56 ГБ |
Qwen/Qwen3.8-27B |
| 2. Прунинг словаря + embedding-весов | словарь 172 822, 5 шардов, 54.02 ГБ | lossless-прунинг BPE-словаря (метод — ниже) |
| 3. Промежуточный GGUF | q8_0, 28 221 569 824 B (8.50 BPW), 866 тензоров | llama.cpp convert_hf_to_gguf.py |
| 4. Иматрикс (для IQ3_XXS) | 27 300 160 B (26 MiB), 496 записей, 120 чанков × 512 токенов | llama-imatrix по ru+en+code-калибровке |
| 5. Квантование | IQ3_XXS 10.235 GiB (25 мин 50 с) и Q4_K_M 15.15 GiB (607 с) | llama-quantize --allow-requantize |
Калибровка иматрикса: 602 522 символа, ~150 630 токенов (ru 84 / en 245 / code 79 документов).
Иматрикс для этой модели получился маленьким (26 MiB, а не гигабайты): запись на тензор имеет
длину ne[0] × ne[2] × ne[3] — один float на входной столбец, а не на весовой элемент.
Почему прунинг словаря, а не слоёв
Словарь Qwen3.8-27B (248 320) участвует в двух матрицах: embed_tokens и lm_head,
обе 5120 × 248 320. Итого 2.543B параметров — 9.2% модели уходят на языки, которых нет
в задаче. Это самый дешёвый способ похудеть: он не трогает attention и MLP, то есть
не трогает логику, код и рассуждение, которые живут в слоях.
Второй мотив — качество генерации: модель, обученная «на всём мире», при русском выводе регулярно соскальзывает в CJK-сегментацию и байтовый fallback. Прунинг делает такой вывод невыгодным по построению.
Qwen использует byte-level BPE (247 587 мержей, byte-fallback, карта GPT-2), поэтому применима классическая логика lossless-прунинга. Идея взята из Qwen-Tokenizer-Pruner, реализация собственная.
Как гарантируется «lossless»
Четыре условия, все проверяются по факту, а не «на глаз»:
Сохраняются все special/служебные токены:
<|im_end|>,<|endoftext|>, pad/bos, vision/image/video-токены, byte-токены — их ровно 37 + 161 362 байтовых, и они не удаляются никогда. Byte-fallback целая, поэтому любой редкий символ (и иероглиф, и эмодзи) остаётся достижимым побайтово, просто дороже по токенам.Сохраняются все токены опорного корпуса: en + ru + код. Корпус — 109 679 документов, 248M символов (30 000 en / 73 752 ru / 5 927 code).
Замыкание по merges: если оставлен родитель
a+b, то детиaиbобязаны остаться. Иначе BPE-алгоритм теряет часть правил и сегментация «плывёт». Дано:+1 608токенов.Fixed-point проверка: опорный корпус сегментируется старым и новым токенизатором и сверяется токен-в-токен. Результат этого запуска:
Fixed-point iter 0: сегментация совпала для 109679/109679 документов; расхождений-кусков: 0Сходится с первой итерации, расхождений ноль. Это формальная гарантия: для английского, русского и кода новый токенизатор выдаёт ровно те же id, что и оригинал. Никакого «переучивания» модели не требуется, поэтому веса можно не трогать.
Баланс маски:
Старый словарь: 248 320 токенов (248 044 базовых + 33 added), 247 587 мержей
Seed (special + bytes): 161 399
Токены опорного корпуса: 121 295 уникальных, из них новых 9 815
Замыкание по merges: +1 608
Новый словарь: 172 822 (удалено 75 498 = 30.4%)
Мержей сохранено: 172 464 / 247 587
Сэкономлено параметров: 0.77B (BF16-модель: 55.56 → 54.02 ГБ)
Ключевая деталь реализации — корректное byte-level BPE декодирование (карта GPT-2
_BYTE_DECODER, сверена с gguf-py::bytes_to_unicode): первая версия на naive latin-1
давала иллюзию «хорошего» прунинга (−32.0%) и ломала round-trip. Финальная маска — v2, −30.4%.
Служебные id после remap: <|im_end|> = 172 791, <|endoftext|> = bos = pad = 172 789,
image = 172 801, vision_start = 172 798; added-tokens — 33.
Числа
Архитектура (не менялась)
| Параметр | Значение |
|---|---|
| GGUF arch | qwen35, dense 27B + VL, 64 слоя + 1 MTP (block_count = 65) |
| Attention | 17 слоёв обычного attention (full_attention_interval = 4) + 48 слоёв linear_attn (gated delta net) |
| Linear-state | conv_kernel 4, state 128, group 16, inner 6144, time_step_rank 48; состояние F32, от длины контекста не зависит |
| Hidden / FFN | 5120 / 17 408, head_dim 256, GQA 24/4, attn_output_gate |
| MTP | qwen35.nextn_predict_layers = 1 → спекуляция --spec-type draft-mtp без отдельного draft-файла |
| Контекст в файле | 262 144 (метаданные; практический упор в память, см. бюджет) |
| Словарь | 172 822 токена, merges 172 464, pre-tokenizer qwen35 |
| Chat-шаблон | канонический Qwen3.8 (с `< |
| Sampling по умолчанию (в метаданных) | temp 1.0, top_k 20, top_p 0.95 |
Типы тензоров (замер по готовым файлам)
IQ3_XXS (866 тензоров): IQ3_XXS по умолчанию — FFN (ffn_gate/up/down), attn_gate,
ssm_alpha/beta/out; attn_q/attn_k → IQ2_S (только 17 слоёв обычного attention),
attn_qkv/attn_v → Q4_K, attn_output → IQ3_S; token_embd → IQ3_S,
output (lm_head) → Q5_K; нормы и ssm-мелочи — F32 без изменений (360 тензоров);
MTP-слой blk.64.* → Q4_K через --tensor-type override.
Счёт: 384 × IQ3_XXS + 72 × Q4_K + 32 × IQ2_S + 17 × IQ3_S + 1 × Q5_K + 360 × F32 = 866.
Q4_K_M (866 тензоров): 439 × Q4_K + 67 × Q6_K + 360 × F32.
Перплексия, held-out (не пересекается с опорным корпусом)
Методика: llama-perplexity, 8 сэмплов × 1024 токена, held-out-хвост опорного корпуса
(ru 3 785 / en 1 737 / code 5 411 токенов). Оригинал прошёл тот же путь q8_0 → Q4_K_M,
поэтому сравнение честное.
Эффект прунинга (оба файла — Q4_K_M, 4.90 BPW):
| Язык | оригинал Q4_K_M | прунутая Q4_K_M | Δ |
|---|---|---|---|
| ru | 4.8798 | 4.8738 | −0.12% |
| en | 5.6153 | 5.6140 | −0.02% |
| code | 2.8902 | 2.8899 | −0.01% |
Дельты на два порядка меньше разброса оценки (±0.12…0.46) → прунутая статистически неотличима от эталона. Порог стоп-сигнала — рост PPL больше 10–15%; здесь роста нет.
Эффект кванта IQ3_XXS (та же прунутая модель, базовая линия — её Q4_K_M):
| Язык | Q4_K_M (4.90 BPW) | IQ3_XXS (3.31 BPW) | Δ |
|---|---|---|---|
| ru | 4.8738 ±0.27 | 5.0928 ±0.28 | +4.49% |
| en | 5.6140 ±0.46 | 5.9082 ±0.50 | +5.24% |
| code | 2.8899 ±0.12 | 3.0672 ±0.13 | +6.14% |
Сравнение парное: те же тексты, та же модель, тот же путь q8_0 → квант, отличается только BPW. +4.5–6% — реальная цена перехода на трёхбитный квант (для сравнения: эффект самого прунинга — десятые доли процента). Типично для трёхбитных квантов: код потерпил больше всех, русский — меньше всех. Если задача — код и точные ответы, предпочтительна Q4_K_M; IQ3_XXS — когда нет другого выбора по видеокарте.
Смоук-пробы (обе сборки, 8/8)
TEMP 0.1, seed 42, -n 256, 8 проб (арифметика, дроби, код с русскими докстрингами,
пересказ, правка текста, англ. код, англ. объяснение, силлогизм):
17 × 23→ 391 с проверкой разложением — верно;84/126→ разложения, НОД = 42, итог 2/3 — верно, на IQ3_XXS доведён до конца;- решето Эратосфена с русским докстрингом и типизацией
list[int]— код корректен; - пересказ делового текста — цифры точные («4,2 млрд рублей», «+18%»);
- силлогизм «все ромбы — фигуры, некоторые фигуры синие» → «нет, не следует» с корректным именем ошибки (недопустимое среднее) и контрпримером;
- кириллица во всех ответах чистая — ни CJK, ни byte-fallback артефактов.
Итог: 8/8 на обоих квантах. Видимой деградации IQ3_XXS на коротких задачах не обнаружено; потеря видна в PPL, где она и ожидалась. Смоук не покрывает: длинные рассуждения, редкую лексику, длинный контекст — там разница с Q4_K_M будет заметнее.
Сколько влезает (бюджет памяти)
Правило: веса + KV(контекст) + recurrent-state + compute buffer.
KV-кэш у этой архитектуры дешёвый: полномерный attention только в 17 слоях из 64
(остальные 48 — linear_attn с фиксированным состоянием). KV = 17 × 2 × 4 головы × 256 =
34 816 элементов на токен → на 128k: f16 8.30 GiB, q8_0 4.41 GiB, q4_0 2.33 GiB.
Состояние 48 linear-слоёв: 0.146 GiB на последовательность, F32, от длины контекста не
зависит (это не KV-кэш, сжать нельзя).
IQ3_XXS на 12 ГБ
Веса 10.235 + recurrent-state 0.146 + compute/CUDA-графики 0.5–1.0 = 10.9–11.4 GiB,
на KV остаётся 0.3–0.8 GiB → ~10–26k токенов при -ctk q8_0 -ctv q8_0,
~17–45k при -ctk q4_0 -ctv q4_0 (типично 20k / 35k).
- Начинать с
-c 16384иq8_0-кэша. - 128k на 12 ГБ с этим квантом не помещается — это уровень IQ2_S +
q4_0-кэш (11.81 GiB), в репозиторий не выложен. - При нехватке VRAM:
--no-cuda-graph,-ub 128,--n-cuda-graph-batches 2,-ngl 60. - Vision (mmproj ~0.46B, +0.9 GiB в f16) с большим контекстом в 12 ГБ не влезает.
Q4_K_M на 24 ГБ
15.15 (веса) + 4.41 (KV 128k q8_0) + 0.15 (state) + ~1 (compute) = ~20.7 GiB →
полные 128k контекста на 3090/4090/A5000.
| Железо | Вердикт для Q4_K_M |
|---|---|
| 24 ГБ | ✅ влезает с 128k (q8_0) |
| 16 ГБ | ❌ веса 15.15 GiB, на кеш не остаётся ничего |
| 12 ГБ | ❌ → для этого IQ3_XXS (эта сборка) |
| 6 ГБ + 32 ГБ RAM | гибрид: часть слоёв в RAM (-ngl 9 и ниже), генерация ~1.2 ток/с |
Бюджеты — аналитические (по метаданным GGUF и симулятору типов llama_tensor_get_type,
сверенному пофайлово с готовой сборкой); GPU-замеров на 12/24 ГБ железе не делалось —
точную цифру памяти печатает сам llama.cpp при загрузке.
Запуск в llama.cpp
IQ3_XXS (карта 12 ГБ)
.\llama-server.exe -m ".\models\qwen3.8-27b-pruned-enru-IQ3_XXS.gguf" `
--jinja -ngl 99 -fa 1 -c 16384 -ctk q8_0 -ctv q8_0 -b 2048 -ub 128 `
--spec-type draft-mtp --draft 4
Q4_K_M (карта 24 ГБ)
.\llama-server.exe -m ".\models\qwen3.8-27b-pruned-enru-Q4_K_M.gguf" `
--jinja -ngl 99 -fa 1 -c 131072 -ctk q8_0 -ctv q8_0 -b 2048 -ub 128 `
--spec-type draft-mtp --draft 4
Пути .\models\... — условный пример.
--jinja— chat template из файла (ru/en системные промты работают).-ctk/-ctvработают только с-fa 1.- Спекуляция — родным MTP-слоем модели, отдельный draft-файл не нужен и не существует.
-rea off(в запросе/клиенте) — если не нужно рассуждение, экономит сотни токенов на ответ.- CPU-режим (
-ngl 0): ~1.2–2.2 токена/с генерация, загрузка модели 2–4 минуты — годится только для редких запросов.
⚠ MTP-черновик унаследован от оригинала и не переобучался после прунинга словаря (в IQ3_XXS он к тому же квантован в Q4_K без иматрикса — иматрикс на MTP-граф не заводится из-за
embd_state). Accept rate черновика может быть ниже расчётного.
Запуск в LM Studio
- My Models → + Add Model → Download from Hugging Face →
Igor282/qwen3.8-27b-pruned-enru-GGUF, выбрать вариант IQ3_XXS (12 ГБ) или Q4_K_M (24 ГБ). - LM Studio подхватит GGUF и встроенный chat-шаблон из метаданных — отдельный JINJA не нужен.
- Speculative decoding: Advanced Configuration → включить спекуляцию, тип — MTP (draft-модель не указывается: черновик встроен в сам GGUF), max draft tokens — 4.
- Контекст: 16k для 12 ГБ карты (KV
q8_0), 128k для 24 ГБ,flashAttention: true.
Что умеет и что сломалось
Работает как раньше:
- русский и английский проза/диалог — сегментация идентична оригиналу токен-в-токен;
- код (идентификаторы, ключевые слова, синтаксис, спецсимволы) — цел, PPL не изменился;
- thinking/reasoning-режим, tool-calling, chat-шаблон;
- спекулятивное декодирование родным MTP;
- vision-энкодеры не тронуты (input-модальности целые; для картинок нужен отдельный mmproj от оригинала — словари vision-части прунинг не касался).
Ухудшилось — и это и есть цель:
- генерация на вырезанных письменностях (китайский, японский, корейский, арабский, хинди, тайский и т. п.). Понимать их модель не перестала — она их не может произнести своими токенами и будет раскладывать через byte-fallback, то есть дорого и грязно.
- Редкие символы и типографская юникод-матрица вне Latin/Cyrillic/Common — аналогично, через байты.
Честные ограничения:
- Немецкий, французский, испанский, португальский и другие латинские языки частично выжили — латиница общая с английским, вырезать их lossless-способом, не повредив английскому, невозможно.
- Языки вырезаны только из ввода-вывода, не из весов: знания о них живут в attention/FFN. Полноценное вытеснение даёт только continual pre-training — он в эту сборку не входил.
- Модель не дообучалась. Прунинг lossless, поэтому дообучение здесь — опциональное улучшение, а не починка.
- Это не «русская модель». Это Qwen3.8-27B, у которой убрали 30.4% словаря, чтобы она влезала в потребительскую видеопамять и не тратила байты на письменности, которые в русско-английском рабочем тексте и коде не встречаются.
Файлы
| Файл | Размер | Что это |
|---|---|---|
qwen3.8-27b-pruned-enru-IQ3_XXS.gguf |
10 989 410 464 B | target, IQ3_XXS (imatrix), vocab 172 822, карта 12 ГБ |
qwen3.8-27b-pruned-enru-Q4_K_M.gguf |
16 272 092 320 B | target, Q4_K_M, vocab 172 822, карта 24 ГБ |
Иматрикс-файл (qwen38-27b-pruned-enru-imatrix.dat, 27 300 160 B, 496 записей,
120 чанков × 512 токенов, калибровка ru+en+code) — по запросу, для самостоятельного
переквантования; метаданные о нём записаны в заголовок IQ3_XXS-файла
(quantize.imatrix.*).
Родственные сборки (другой трек, та же метода)
Gemma-4-E4B, прунутая той же логикой: Igor282/gemma-4-e4b-pruned-ru-en-Q4_K_M и Igor282/gemma-4-e4b-pruned-ru-Q4_K_M — там же полный разбор метода lossless-прунинга.
Лицензия и атрибуция
Apache-2.0 — та же лицензия, что у исходной модели, без дополнительных ограничений. Модель отдаётся свободно, использовать можно в том числе в коммерческих проектах.
- Веса: производные от Qwen/Qwen3.8-27B © Alibaba Qwen, Apache-2.0.
- Идея lossless-прунинга BPE-словаря: Qwen-Tokenizer-Pruner.
- Квантование и спекуляция: llama.cpp.
Маска словаря (keep_sorted) воспроизводима детерминированно из опорного корпуса и фильтра
письменностей — то есть любой может собрать свою вариацию процента вырезания и проверить её
fixed-point-инвариантом.