Views
No views yet
compressed-tensors quantization of
ibm-granite/granite-4.1-3b.Linear layers inside the transformer blocks; lm_head is
left in BF16 (the base model has tie_word_embeddings: true, so quantizing it
would also perturb the input embedding)lm_head stay BF16, so the whole-checkpoint
saving is smaller than 2× (and smaller the smaller the model, since the
100k-entry vocab is a larger share of it)Purpose. This checkpoint was produced for inference-performance benchmarking (INT8/AMX on Xeon and INT8 kernels on GPU). No accuracy evaluation was run on it — see Accuracy before using it for anything where quality matters.
vllm serve devpramod-intel/granite-4.1-3b-quantized.w8a8 --max-model-len 327681from vllm import LLM, SamplingParams
2from transformers import AutoTokenizer
3
4model_id = "devpramod-intel/granite-4.1-3b-quantized.w8a8"
5tokenizer = AutoTokenizer.from_pretrained(model_id)
6llm = LLM(model=model_id, max_model_len=4096)
7
8prompt = tokenizer.apply_chat_template(
9 [{"role": "user", "content": "Who are you? Please respond in pirate speak!"}],
10 tokenize=False, add_generation_prompt=True,
11)
12print(llm.generate(prompt, SamplingParams(temperature=0.3, max_tokens=256))[0].outputs[0].text)1python quantize_w8a8_granite41.py \
2 --model-dir ibm-granite/granite-4.1-3b \
3 --out granite-4.1-3b-quantized.w8a8 \
4 --smoothing-strength 0.8 --dampening-frac 0.1 \
5 --observer mse --num-samples 5121quant_stage:
2 quant_modifiers:
3 SmoothQuantModifier:
4 smoothing_strength: 0.8
5 ignore: [lm_head]
6 mappings:
7 - - ['re:.*q_proj', 're:.*k_proj', 're:.*v_proj']
8 - re:.*input_layernorm
9 - - ['re:.*gate_proj', 're:.*up_proj']
10 - re:.*post_attention_layernorm
11 - - ['re:.*down_proj']
12 - re:.*up_proj
13 GPTQModifier:
14 targets: [Linear]
15 ignore: [lm_head]
16 scheme: W8A8
17 dampening_frac: 0.1
18 weight_observer: mse
19 sequential_targets: [GraniteDecoderLayer]recipe.yaml in this repo is what llm-compressor actually applied and is
authoritative. It additionally shows block_size: 128 and actorder: static,
which are llm-compressor 0.9.0.4 defaults rather than choices — the older
Granite cards predate actorder defaulting on, so this checkpoint is not
bit-identical to what their recipe produced in 2025.neuralmagic/LLM_compression_calibration, train split,
shuffle(seed=42).select(512), the dataset's raw text field with
add_special_tokens=True, max_seq_length=8192.recipe.yaml files for the
nearest architectural precedents — ibm-granite/granite-4.1-3b is a dense
GraniteForCausalLM with Llama-style blocks (q/k/v + gate/up/down, RMSNorm), so
the Granite 3.1 W8A8 recipes transfer directly.| Precedent | Relationship | Knobs it contributes |
|---|---|---|
| RedHatAI/granite-3.1-8b-instruct-quantized.w8a8 | same family, same class, same size class | smoothing_strength=0.8, llama mappings, dampening_frac=0.1, weight observer mse, INT8 channel-weight / token-dynamic-activation config group |
| RedHatAI/granite-3.1-2b-instruct-quantized.w8a8 | smaller sibling | confirms the same structure at small scale (it uses 0.7 / 0.01) |
| RedHatAI/granite-4.1-8b-fp8 | Red Hat's own quantization of this generation | confirms targets=[Linear], ignore=[lm_head] is the whole story for granite-4.1 — no MoE/vision special-casing |
max_seq_length=8192, not the 8196 printed on the Granite cards (a typo).sequential_targets set to the decoder-layer class, following current
Red Hat cards; it lowers peak VRAM and does not change the result.| Evidence | Measured recovery vs BF16 |
|---|---|
granite-3.1-8b-instruct W8A8, identical recipe (Red Hat card) | OpenLLM v1 99.95% (70.26 vs 70.30), OpenLLM v2 98.64%, HumanEval 99.3% |
granite-3.1-2b-instruct W8A8 (Red Hat card) | OpenLLM v1 99.52% (61.68 vs 61.98) |
| a granite-4.1-8b derivative quantized with this exact script (internal, 7-dataset classification basket) | aggregate ≈99.4%, 46/48 byte-identical decodes on CPU |
lm-eval against both this checkpoint and the BF16 base and
report the ratio.config.json → quantization_config: format: int-quantized, weights
num_bits 8 / channel / symmetric / observer mse, input activations
num_bits 8 / token / dynamic, ignore: ["lm_head"]