Views
No views yet
Qwen/Qwen3.5-4B для onnxruntime-genai на CUDA EP. Собрана для голосового ввода
в Dispatch, где модель работает корректором диктовки:
расставляет пунктуацию и регистр и возвращает англоязычные технические термины, которые
распознаватель речи свёл к похожим по звучанию русским словам.onnx-community genai-сборок Qwen3.5 нет: Qwen3.5-4B/2B/0.8B-ONNX опубликованы в формате
transformers.js без genai_config.json, а единственная с genai (9B) весит 15.9 ГБ
неквантованной. Эта сборка закрывает пробел.prune_lm_headprune_lm_head=true — перед LM head вставляются Gather+Unsqueeze, так что на
префилле считается только логит последней позиции: вход MatMul [B,1,H] вместо [B,S,H].
Для корректора это принципиально: задача копирующая, выходных токенов десятки, а логиты на всю
длину промпта — главный потребитель памяти (при vocab 248 320 это ~607 КБ на позицию).без prune_lm_head | с prune_lm_head | |
|---|---|---|
| VRAM, пик | 9528 МиБ | 4674 МиБ |
| VRAM, прирост от загрузки к пику | +4941 МиБ | +1148 МиБ |
| p50 на фразу | 0.168 с | 0.152 с |
| качество (свой набор) | 19/23 | 19/23 |
| размер на диске | 3.5 ГБ | 3.5 ГБ |
max_length cannot be greater than model context_length: контекст
здесь 262 144 токена.python -m onnxruntime_genai.models.builder \
-m Qwen/Qwen3.5-4B -o <out> -p int4 -e cuda -c <cache> \
--extra_options exclude_embeds=false hf_token=false prune_lm_head=trueexclude_embeds=false обязателен. Qwen3.5 — VL-модель, и по умолчанию билдер делает
декодер на inputs_embeds, несовместимый с append_tokens. Без флага получается
бесполезная сборка, и это выясняется только при запуске.hf_token=false — иначе билдер падает с LocalTokenNotFoundError даже на публичном
репозитории.onnx_ir и onnxscript ставить отдельно — в зависимости onnxruntime-genai они не
входят, билдер падает на импорте.Gather в
список квантуемых типов и загоняет в int4 то, что обязано остаться точным: таблицу
эмбеддингов и кэши RoPE (model.rotary_emb.cos_cache / sin_cache). Тригонометрические
значения в диапазоне [-1, 1] на 16 уровнях int4 разрушают позиционное кодирование —
модель генерирует мусор (декодируется в '�'), и ошибка ничем не сигнализируется.
Проверять сборку стоит по типам: у корректной model.embed_tokens.weight — FLOAT16,
rotary_emb.*_cache — FLOAT, узлов GatherBlockQuantized нет.matmul_mixed_precision=last_matmul:int8,linear_attn:int8 — на
0.5 ГБ больше, медленнее, качество то же; shared_embeddings=true вместе с int4 разделяет
lm_head и таблицу эмбеддингов, то есть кладёт эмбеддинги в int4 с тем же результатом, что выше.full_attention чередуется с linear_attention (GatedDeltaNet, рекуррентное
состояние вместо KV-кэша). 32 слоя, hidden 2560, 16 голов внимания, 4 KV-головы, head_size 256,
vocab 248 320, контекст 262 144.Qwen/Qwen3.5-4B, лицензия Apache-2.0 сохраняется. Веса не переобучались —
только экспорт в ONNX и int4-квантование весов.