Qwen3.5-9B ยท AWQ INT4 (W4A16)
4-bit quantization of Qwen/Qwen3.5-9B, produced for efficient vLLM serving. Quantized by axteam.
Revision 2026-11-01: un-smoothed RMSNorm weights restored bit-exactly from the original. llm-compressor's offset-norm handling had left BF16 rounding noise (at most 0.4% in the effective gain) in the norms that AWQ does not smooth. Quantized weights and the AWQ-smoothed norms are unchanged. The measurements on this card were taken before this change.
| Base model | Qwen/Qwen3.5-9B |
| Method | AWQ INT4 (W4A16) |
| Format | compressed-tensors pack-quantized |
| Weights / activations | W4A16 โ INT4 asymmetric weights, group size 32 (BF16 scale + INT4 zero-point), BF16 activations |
| Architecture | Hybrid (linear-attention + full-attention) ยท Dense ยท multimodal (vision) ยท MTP head |
| Size on disk | ~9.5 GB |
| Calibration | 256 samples (Korean-heavy mixed corpus) |
| License | Apache-2.0 |
Quantization details
- Scheme โ W4A16 โ INT4 asymmetric weights, group size 32 (BF16 scale + INT4 zero-point), BF16 activations, stored as compressed-tensors
pack-quantized. - Kept in BF16 โ the vision tower & projector (
model.visual.*), the multi-token-prediction head (mtp.*), all RMSNorms, token embeddings, the LM head, the SSM non-linear parts (linear_attn.conv1d/A_log/dt_bias).linear_attn.A_logand the gatedlinear_attn.norm, FP32 in the original, are stored in BF16 โ losslessly forA_log(every original value is exactly representable in BF16), and for the norm the same values vLLM and Transformers (default dtype) load at runtime. Left unquantized to preserve quality (about 28% of all parameters in this build). - Tokenizer /
chat_template/ preprocessor configs are identical to the original (the original ships nogeneration_config.json, so none is included here).config.jsonis the original plus aquantization_configblock.
This is post-training quantization (PTQ) โ no retraining. AWQ uses a small calibration set (no gradient) to protect salient weight channels before rounding.
Benchmarks (measured)
Every column was measured with the same harness and settings โ lm-evaluation-harness on vLLM, greedy, completion-style prompts without a chat template (0- or 5-shot, as listed in each row). MMLU here is lm-eval's generative variant (mmlu_generative: the model writes the answer letter and only an exact match on the first line counts), so it is not directly comparable with MMLU scores measured another way (e.g. log-likelihood scoring). Percentages are recovery vs. the BF16 original.
| Benchmark | BF16 (original) | FP8-dynamic | AWQ-8bit | NVFP4A16 | NVFP4 | AWQ-4bit (this repo) |
|---|---|---|---|---|---|---|
| MMLU (5-shot, generative) | 33.03 | 46.82 (141.8%) | 32.37 (98.0%) | 32.15 (97.3%) | 35.06 (106.1%) | 33.29 (100.8%) |
| GSM8K (5-shot, strict) | 87.11 | 86.81 (99.7%) | 86.96 (99.8%) | 84.38 (96.9%) | 84.23 (96.7%) | 86.81 (99.7%) |
| ARC-Challenge (0-shot) | 55.55 | 55.72 (100.3%) | 55.89 (100.6%) | 54.44 (98.0%) | 54.01 (97.2%) | 56.48 (101.7%) |
| Winogrande (5-shot) | 73.72 | 74.19 (100.6%) | 74.51 (101.1%) | 73.01 (99.0%) | 73.16 (99.3%) | 73.40 (99.6%) |
| KMMLU (5-shot, direct) | 58.39 | 58.05 (99.4%) | 58.51 (100.2%) | 58.26 (99.8%) | 57.41 (98.3%) | 56.96 (97.6%) |
| HAE-RAE (0-shot) | 69.48 | 69.11 (99.5%) | 69.39 (99.9%) | 70.21 (101.1%) | 68.47 (98.5%) | 67.09 (96.6%) |
| Average | 62.88 | 65.12 (103.6%) | 62.94 (100.1%) | 62.07 (98.7%) | 62.06 (98.7%) | 62.34 (99.1%) |
| Average without MMLU | 68.85 | 68.78 (99.9%) | 69.05 (100.3%) | 68.06 (98.9%) | 67.46 (98.0%) | 68.15 (99.0%) |
Note on MMLU: this task is scored on generated text (
mmlu_generative), so the score depends on whether the model answers in exactly the format the scorer expects (for MMLU only a bare answer letter on the first line counts). For this model it swings widely between builds of the same model (MMLU 32.2โ46.8), and only one quantized build, FP8-dynamic, scores well above the BF16 original (141.8%). This most likely reflects how each build formats its answers rather than quantization quality, but per-question outputs were not saved, so it was not checked answer by answer. The second average leaves it out.
Evaluation (measured)
Fidelity to the BF16 original on an internal mixed English/Korean set (100 prompts, BF16 greedy answers scored under each build โ same harness for every row).
| Metric | This model | BF16 original |
|---|---|---|
| Perplexity (lower = closer) | 1.5403 | 1.4506 (+6.2%) |
| Top-1 next-token agreement | 90.9% | 99.2% |
These measure fidelity to the base model, not absolute task scores.
Requirements
| Runtime | vLLM โ the architecture is in vLLM โฅ 0.17.0; tested here with vLLM 0.32.0. |
| vLLM install | vLLM 0.32 itself needs Python 3.11โ3.14, torch 2.13 (CUDA 13.0 build, so an NVIDIA driver with CUDA 13 support), transformers โฅ5.16.1,<5.20 and compressed-tensors 0.17.0 (both pinned by vLLM; 0.17.0 reads this checkpoint, which was saved with 0.19.0 โ do not upgrade it separately). |
| GPU | NVIDIA Turing (sm75) or newer โ weight-only INT, no special tensor cores needed. V100 (sm70) is not supported. (Kernel choice per GPU from vLLM 0.32's selection code; only B200 was run here.) |
| Memory | Weights: 9.5 GB. Add KV cache (grows with context length ร concurrent requests) and a few GB for activations / CUDA graphs; use --tensor-parallel-size N when the weights do not fit one GPU. |
| Transformers (without vLLM) | transformers>=5.2.0 + compressed-tensors>=0.15.0 (checked on CPU with Qwen3.5-0.8B FP8 / AWQ-4bit / NVFP4A16 / NVFP4). |
| trust_remote_code | not needed |
Usage (vLLM)
Start an OpenAI-compatible server:
vllm serve axteam/Qwen3.5-9B-AWQ-4bit --max-model-len 32768
Query it:
curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "axteam/Qwen3.5-9B-AWQ-4bit",
"messages": [{"role": "user", "content": "๋ํ๋ฏผ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?"}],
"max_tokens": 512
}'
Offline inference in Python:
from vllm import LLM, SamplingParams
llm = LLM(model="axteam/Qwen3.5-9B-AWQ-4bit", max_model_len=32768)
params = SamplingParams(max_tokens=1024)
out = llm.chat([{"role": "user", "content": "Explain model quantization in two sentences."}], params)
print(out[0].outputs[0].text)
# image input (URL or data: URI)
messages = [{"role": "user", "content": [
{"type": "image_url", "image_url": {"url": "https://example.com/your-image.png"}},
{"type": "text", "text": "Describe this image."},
]}]
out = llm.chat(messages, params)
print(out[0].outputs[0].text)
Thinking mode is on by default in the chat template; to turn it off pass
chat_template_kwargs={"enable_thinking": False}(Pythonllm.chat(..., chat_template_kwargs=...), or"chat_template_kwargs": {"enable_thinking": false}in the request body). Text-only serving: add--limit-mm-per-prompt '{"image": 0, "video": 0}'to skip loading the vision encoder's memory budget.
Reducing KV-cache memory (optional, serve-time)
The KV cache is kept in BF16 by default. KV-cache precision is a runtime choice, independent of the weight quantization above. This is a hybrid model: only its 8 full-attention layers keep a KV cache, while its 24 linear-attention (Gated DeltaNet) layers keep a fixed-size state per request, which --kv-cache-dtype does not change. FP8 halves the full-attention KV cache, so the saving grows with context length and is small for many short requests:
vllm serve axteam/Qwen3.5-9B-AWQ-4bit --kv-cache-dtype fp8
License
Quantized derivative of Qwen/Qwen3.5-9B (Apache-2.0). All original weights, tokenizer and chat template belong to the Qwen team.
ํ๊ตญ์ด ์์ฝ
Qwen/Qwen3.5-9B์ AWQ INT4 (W4A16) ์์ํ ๋น๋ ยท ์ ์ axteam
๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ์๋ณธ ๋ชจ๋ธ | Qwen/Qwen3.5-9B |
| ์์ํ ๋ฐฉ์ | AWQ INT4 (W4A16) |
| ์ ์ฅ ํ์ | compressed-tensors pack-quantized |
| ๋ชจ๋ธ ๊ตฌ์กฐ | ํ์ด๋ธ๋ฆฌ๋ ์ดํ ์ (์ ํ ์ดํ ์ + ํ ์ดํ ์ ) ยท Dense ยท ๋ฉํฐ๋ชจ๋ฌ(๋น์ ) ยท MTP ํค๋ |
| ์ฉ๋ | ์ฝ 9.5 GB |
| ๋ณด์ ๋ฐ์ดํฐ | ์ํ 256๊ฐ (ํ๊ตญ์ด ์์ฃผ ํผํฉ ์ฝํผ์ค) |
์์ํ ์์ธ
- ๊ฐ์ค์น: INT4 ๋น๋์นญ, ๊ทธ๋ฃน ํฌ๊ธฐ 32 (BF16 ์ค์ผ์ผ + INT4 ์์ )
- ํ์ฑํ: BF16 (์์ํํ์ง ์์)
- ์์ํ ์ ์ฐจ: PTQ(ํ์ต ํ ์์ํ, ์ฌํ์ต ์์), AWQ ๋ฐฉ์ โ ๋ณด์ ๋ฐ์ดํฐ๋ก ํ์ฑํ๊ฐ ํฐ ๊ฐ์ค์น ์ฑ๋์ ์ฐพ์ ์ฑ๋๋ณ ์ค์ผ์ผ๋ก ๋ณดํธํ ๋ค INT4๋ก ๋ฐ์ฌ๋ฆผ
- BF16 ์ ์ง: ๋น์ ํ์ยทํฌ์์ธต(
model.visual.*), MTP ํค๋(mtp.*), ๋ชจ๋ RMSNorm, ํ ํฐ ์๋ฒ ๋ฉ, LM ํค๋, SSM์ ์ ํ์ธต ์ธ ํ๋ผ๋ฏธํฐ(linear_attn.conv1dยทA_logยทdt_bias) โ ์๋ณธ์์ FP32์ธlinear_attn.A_logยท๊ฒ์ดํธlinear_attn.norm์ BF16์ผ๋ก ์ ์ฅ(A_log๋ ์๋ณธ ๊ฐ์ด ๋ชจ๋ BF16์ผ๋ก ์ ํํ ํํ๋ผ ์์ค ์์, norm์ vLLMยทTransformers(๊ธฐ๋ณธ dtype)๊ฐ ์คํ ๋ ์ฐ๋ BF16 ๊ฐ๊ณผ ๊ฐ์) โ ์ ์ฒด ํ๋ผ๋ฏธํฐ์ ์ฝ 28% - ์๋ณธ ํ์ผ: ํ ํฌ๋์ด์ ยทchat templateยท์ ์ฒ๋ฆฌ ์ค์ ์ ์๋ณธ๊ณผ ๋์ผ(์๋ณธ์
generation_config.json์ด ์์ด ์ด ๋ฆฌํฌ์๋ ์์),config.json์ ์๋ณธ์quantization_config๋ธ๋ก๋ง ์ถ๊ฐ
ํ์ง (์ค์ธก)
- ์๋ณธ ๋๋น ์ถฉ์ค๋: PPL 1.5403 (์๋ณธ 1.4506, +6.2%, ๋ฎ์์๋ก ์๋ณธ์ ๊ฐ๊น์), ๋ค์ ํ ํฐ top-1 ์ผ์น์จ 90.9% (์๋ณธ ์์ฒด ๊ธฐ์ค๊ฐ 99.2%) โ ๋ด๋ถ ์์ดยทํ๊ตญ์ด ํผํฉ ํ๋กฌํํธ 100๊ฐ, ์๋ณธ(BF16)์ greedy ๋ต๋ณ์ ๊ธฐ์ค ํ ์คํธ๋ก ์ธก์
- ๋ฒค์น๋งํฌ ํ๊ท : 62.34 (์๋ณธ 62.88, 99.1%) โ MMLU(์์ฑํ)ยทGSM8KยทARC-ChallengeยทWinograndeยทKMMLUยทHAE-RAE 6์ข ํ๊ท , lm-evaluation-harness + vLLM, chat template ์๋ ์์ฑํ ํ๋กฌํํธ(๊ณผ์ ๋ณ 0ยท5-shot, ํ ์ฐธ๊ณ )ยทgreedy, ๋ชจ๋ ๋น๋๋ฅผ ๊ฐ์ ์ค์ ์ผ๋ก ์ธก์
- MMLU(์์ฑํ) ์ ์ธ ํ๊ท : 68.15 (์๋ณธ 68.85, 99.0%) โ MMLU(์์ฑํ)๋ ์์ฑํ ๋ต์ด ์ฑ์ ๊ธฐ๊ฐ ๊ธฐ๋ํ๋ ํ์ ๊ทธ๋๋ก์ฌ์ผ ์ ์๊ฐ ๋๋ ๊ณผ์ ; ์ด ๋ชจ๋ธ์์๋ ๊ฐ์ ๋ชจ๋ธ์ ๋น๋๋ผ๋ฆฌ MMLU(์์ฑํ) 32.2~46.8๋ก ํฌ๊ฒ ํ๋ค๋ฆฌ๊ณ FP8-dynamic ๋น๋ ํ๋๋ง ์๋ณธ๋ณด๋ค ํฌ๊ฒ ๋์(141.8%), ๋ต ํ์ ์ฐจ์ด๋ก ๋ณด์ด๋ ๋ฌธํญ๋ณ ์ถ๋ ฅ์ ์ ์ฅํ์ง ์์ ๋ฌธํญ ๋จ์๋ก๋ ํ์ธํ์ง ์์
- ํ๊ตญ์ด ๋ฒค์น๋งํฌ: KMMLU 56.96 (์๋ณธ 58.39, 97.6%) ยท HAE-RAE 67.09 (์๋ณธ 69.48, 96.6%)
- MMLU ๋ฐฉ์: lm-eval ์์ฑํ ๋ณํ(
mmlu_generative) โ ๋ชจ๋ธ์ด ๋ต ๊ธ์๋ฅผ ์์ฑํ๊ณ ์ฒซ ์ค์ด ์ ํํ ์ผ์นํด์ผ ์ ๋ต์ผ๋ก ์ฑ์ ํ๋ฏ๋ก, ๋ค๋ฅธ ๋ฐฉ์(์: log-likelihood ์ฑ์ )์ผ๋ก ์ฐ MMLU ์ ์์ ์ง์ ๋น๊ต ๋ถ๊ฐ
์๊ตฌ์ฌํญ
- ์คํ ์์ง: vLLM 0.17.0 ์ด์(์ด ๊ตฌ์กฐ๋ฅผ ์ง์ํ๋ ์ฒซ ๋ฒ์ ), ์ด ๋น๋๋ vLLM 0.32.0์์ ์คํ ํ์ธ
- vLLM 0.32 ์ค์น ์กฐ๊ฑด: Python 3.11~3.14, torch 2.13(CUDA 13.0 ๋น๋, CUDA 13 ์ง์ ๋๋ผ์ด๋ฒ ํ์), transformers 5.16.1 ์ด์ 5.20 ๋ฏธ๋ง, compressed-tensors 0.17.0 โ transformersยทcompressed-tensors๋ vLLM์ด ๋ฒ์ ์ ๊ณ ์ ํ๋ฏ๋ก compressed-tensors๋ฅผ ๋ฐ๋ก ์ ๊ทธ๋ ์ด๋ํ์ง ๋ง ๊ฒ (์ด ์ฒดํฌํฌ์ธํธ๋ 0.19.0์ผ๋ก ์ ์ฅ๋์ง๋ง 0.17.0์์๋ ๋ก๋๋จ)
- GPU: NVIDIA Turing(sm75) ์ด์, V100(sm70) ๋ฏธ์ง์ โ ๊ฐ์ค์น ์ ์ฉ ์ ์ ํ์์ด๋ผ FP8ยทFP4 ์ ์ฉ ํ ์์ฝ์ด ๋ถํ์ (GPU๋ณ ์ง์ ์ฌ๋ถ๋ vLLM 0.32 ์ปค๋ ์ ํ ์ฝ๋ ๊ธฐ์ค, ์ค์ ์คํ์ B200์์๋ง ํ์ธ)
- ๋ฉ๋ชจ๋ฆฌ: ๊ฐ์ค์น 9.5 GB + KV ์บ์(์ปจํ
์คํธ ๊ธธ์ด ร ๋์ ์์ฒญ ์์ ๋น๋ก) + ํ์ฑํยทCUDA graph์ฉ ์ GB โ GPU ํ ์ฅ์ ๋ค ๋ค์ด๊ฐ์ง ์์ผ๋ฉด
--tensor-parallel-size N์ผ๋ก ๋ถ์ฐ - Transformers๋ก ์ง์ ์ฌ์ฉ: transformers 5.2.0 ์ด์ + compressed-tensors 0.15.0 ์ด์ (Qwen3.5-0.8B์ FP8ยทAWQ-4bitยทNVFP4A16ยทNVFP4 ๋น๋๋ก CPU์์ ํ์ธ)
- trust_remote_code: ๋ถํ์
์ฌ์ฉ๋ฒ
- ์๋ฒ ์คํ:
vllm serve axteam/Qwen3.5-9B-AWQ-4bit --max-model-len 32768โ OpenAI ํธํ API - Python:
LLM(model="axteam/Qwen3.5-9B-AWQ-4bit", max_model_len=32768).chat(...)โ ์ ์ฒด ์์๋ ์ ์์ด ๋ณธ๋ฌธ 'Usage (vLLM)' ์ ์ฐธ๊ณ - thinking ๋ชจ๋: ๊ธฐ๋ณธ ์ผ์ง โ ๋๋ ค๋ฉด
chat_template_kwargs={"enable_thinking": False}์ ๋ฌ(Python์llm.chat()์ธ์, HTTP๋ ์์ฒญ ๋ณธ๋ฌธ์"chat_template_kwargs": {"enable_thinking": false}) - ์ด๋ฏธ์ง ์
๋ ฅ: ๋ฉ์์ง์
image_urlํญ๋ชฉ ์ฌ์ฉ - ํ
์คํธ๋ง ์ฌ์ฉํ ๋:
--limit-mm-per-prompt '{"image": 0, "video": 0}'โ ๋น์ ํ์์ฉ ๋ฉ๋ชจ๋ฆฌ ์์ฝ์ ์๋ตํด ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ - KV ์บ์ ์ ๊ฐ(์ ํ):
vllm serve์--kv-cache-dtype fp8์ถ๊ฐ โ ํ์ด๋ธ๋ฆฌ๋ ๊ตฌ์กฐ๋ผ KV ์บ์๋ ํ ์ดํ ์ 8๊ฐ ์ธต์๋ง ์๊ณ , ์ ํ ์ดํ ์ (Gated DeltaNet) 24๊ฐ ์ธต์ ์์ฒญ๋ณ ๊ณ ์ ํฌ๊ธฐ ์ํ๋ ์ด ์ต์ ์ผ๋ก ๋ฐ๋์ง ์์ โ ํ ์ดํ ์ KV ์บ์๋ง ์ ๋ฐ์ผ๋ก ์ค์ด ๊ธด ์ปจํ ์คํธ์์ ํจ๊ณผ๊ฐ ํฌ๊ณ ์งง์ ์์ฒญ์ด ๋ง์ ๋๋ ์์ (๊ฐ์ค์น ์์ํ์ ๋ณ๊ฐ์ธ ์คํ ์ต์ )
์ฐธ๊ณ
- ์์ ์ด๋ ฅ (2026-11-01): AWQ๊ฐ ์ค๋ฌด๋ฉํ์ง ์๋ RMSNorm ๊ฐ์ค์น๋ฅผ ์๋ณธ๊ณผ ๋นํธ ๋จ์๋ก ๊ฐ๊ฒ ๋ณต์ โ llm-compressor๊ฐ ๋จ๊ธด BF16 ๋ฐ์ฌ๋ฆผ ์ค์ฐจ(์คํจ ๊ฐ์ค์น ๊ธฐ์ค ์ต๋ 0.4%) ์ ๊ฑฐ, ์์ํ ๊ฐ์ค์น์ AWQ๋ก ์ค๋ฌด๋ฉ๋ RMSNorm์ ๋ณ๊ฒฝ ์์, ํ์ง ํญ๋ชฉ์ ์ธก์ ๊ฐ์ ๋ณต์ ์ ๊ธฐ์ค
๋ผ์ด์ ์ค
- ๋ผ์ด์ ์ค: Apache-2.0 โ ์๋ณธ ๋ชจ๋ธ์ ๋ผ์ด์ ์ค๋ฅผ ๊ทธ๋๋ก ๋ฐ๋ฆ
- ๊ถ๋ฆฌ: ์๋ณธ ๊ฐ์ค์นยทํ ํฌ๋์ด์ ยทchat template์ Qwen ํ(Alibaba) ์์ , ์ด ๋ฆฌํฌ๋ ์์ํ ํ์๋ฌผ