Instructions to use huginnfork/Qwen3.8-27B-FP8 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use huginnfork/Qwen3.8-27B-FP8 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="huginnfork/Qwen3.8-27B-FP8") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("huginnfork/Qwen3.8-27B-FP8") model = AutoModelForMultimodalLM.from_pretrained("huginnfork/Qwen3.8-27B-FP8", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use huginnfork/Qwen3.8-27B-FP8 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "huginnfork/Qwen3.8-27B-FP8" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "huginnfork/Qwen3.8-27B-FP8", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/huginnfork/Qwen3.8-27B-FP8
- SGLang
How to use huginnfork/Qwen3.8-27B-FP8 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "huginnfork/Qwen3.8-27B-FP8" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "huginnfork/Qwen3.8-27B-FP8", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "huginnfork/Qwen3.8-27B-FP8" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "huginnfork/Qwen3.8-27B-FP8", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use huginnfork/Qwen3.8-27B-FP8 with Docker Model Runner:
docker model run hf.co/huginnfork/Qwen3.8-27B-FP8
Qwen3.8-27B-FP8
FP8_DYNAMIC W8A8, attnbf16 — FP8 (E4M3) weights with dynamic per-token activation quantisation, applied to the MLPs only. The entire self_attn path, the linear_attn (SSM) block, the vision tower, lm_head and the MTP head all stay in bf16.
A quantisation of Qwen/Qwen3.8-27B — a dense, multimodal
Qwen3.5-family model (qwen3_5) with hybrid linear + full attention, a vision tower,
and a multi-token-prediction head.
| Scheme | FP8_DYNAMIC (W8A8) |
| Size | 35.8 GiB (8 shards) vs 51.7 GiB bf16 |
| Quantised modules | 192 (the 64x3 MLP projections) |
| Kept in bf16 | self_attn, linear_attn, model.visual, lm_head, mtp |
| Recipe | recipe.yaml (fp8_dynamic_attnbf16.yaml) |
Why only the MLPs
Qwen3.8-27B sets attn_output_gate: true, which fuses the attention output gate
into q_proj — making it [12288, 5120] instead of [6144, 5120]. Half of that tensor
is a multiplicative per-head gate on what attention writes into the residual stream, and
quantisation error on a multiplicative gate behaves worse than on an additive projection.
Only 16 of the 64 layers are full_attention (the rest are linear_attn), so the whole
self_attn block is a small share of the parameters — holding it in bf16 costs little
while removing the riskiest quantisation target. The MLPs supply nearly all of the
compression.
The linear_attn (Mamba/SSM) block is kept in bf16 for the same reason it is in every
build in this line: quantising the recurrent projections measurably degrades this
architecture.
Measurements
KLD is per-token, 8 samples from neuralmagic/calibration (LLM split) at max_seq=1024.
PPL is wikitext-2-raw test, non-overlapping 2048-token chunks. Baseline for both is
bf16 Qwen/Qwen3.8-27B itself, so what is measured is quantisation loss and nothing else.
Two KLD columns, because one number cannot be fair to both checkpoints. The official release is DeepSeek-format FP8, which has to be dequantised to plain bf16 before it will run at all on Blackwell — and a dequantised checkpoint runs with bf16 activations. Our checkpoint, loaded normally, still applies its scheme's dynamic FP8 activation quant. Comparing those two directly measures W8A8 against W8A16 and flatters whichever model was dequantised. So both are reported both ways.
| Model | Modules quantised | KLD (weight-only) | KLD (as deployed) | PPL | ΔPPL |
|---|---|---|---|---|---|
Qwen/Qwen3.8-27B (bf16) |
— | 0 | 0 | 6.9416 | — |
Qwen/Qwen3.8-27B-FP8 (official) |
407 | 0.0523 | 0.1001 | 6.9539 | +0.18 % |
| This model | 192 | 0.0362 | 0.0756 | 6.9325 | -0.13 % |
Weight-only = weights round-tripped through the quantised format, activations bf16.
As deployed = the same weights plus dynamic per-token FP8 activation quantisation on
exactly the modules each checkpoint actually converts. For this build the two differ because FP8_DYNAMIC quantises activations; for the official they differ for the same reason.
This build has lower divergence from the bf16 parent than the official release on both measures — 31% lower weight-only and 24% lower as deployed — while quantising 192 modules to the official's 407.
On PPL the two are not meaningfully separable; both sit within noise of the bf16 parent. A negative ΔPPL does not mean this build beats its own parent, only that the loss is below measurement noise.
What does not explain the difference
The intuitive story is that scale layout matters — the official uses 128x128 block
scales, llm-compressor emits one scale per output channel. We tested that directly,
simulating the FP8 E4M3 round-trip on real weight tensors from this model
(experiment_block_scales.py):
| scheme | #scales | rel. Frobenius err | max abs err |
|---|---|---|---|
| per-tensor | 1 | 0.02648 | 0.02065 |
| per-output-channel (this build) | 5120 | 0.02643 | 0.02065 |
| block 128x128 (official) | 5440 | 0.02643 | 0.00426 |
| control: INT8 per-tensor | 1 | 0.0750 | — |
| control: INT8 per-output-channel | 17408 | 0.0101 | — |
| control: INT8 block 128x128 | 5440 | 0.0144 | — |
All FP8 variants land within 0.1 % of each other — including per-tensor, with a single scale for the entire matrix. The reason is that FP8 is a floating-point format: every element carries its own exponent, so the scale only has to bring values into range rather than resolve dynamic range the way a fixed-point scale must. The INT8 control shows the method is sensitive enough to detect layout effects where they exist (a 7.4x spread) — and that in that regime per-output-channel actually beats 128x128 block, having more scales.
Block scaling does buy a ~5x lower worst-case weight error; that is an outlier-tail property, not an average one.
We also checked whether the vendor used a smarter rounding than round-to-nearest, by
comparing their stored weights against an RTN round-trip of the same parent tensors
(experiment_rounding.py):
their reconstruction error matches RTN to within 0.3 %. They used plain round-to-nearest.
So the gap is not scale layout and not rounding — it is which modules get quantised. This build leaves the attention path, the SSM block and the MTP head in bf16; the official quantises all of them.
So the reasons to prefer this build are architectural, not average-case accuracy:
- the SSM and attention paths are untouched bf16, which is what you want if you care about long-context or multi-turn behaviour and are unwilling to accept quantised recurrent projections;
- it is
compressed-tensorsformat, so it loads intransformerson Blackwell (SM120). The official checkpoint is DeepSeek-format FP8 (quant_method: fp8+weight_scale_inv, block-128), which does not —transformers'finegrained_fp8integration has no SM120 recipe, and it has to be hand-dequantised even to be evaluated. (That dequantisation is how the official row above was measured, on this same harness, so the comparison is apples-to-apples.)
Both FP8 rows measure weight precision loss only; neither models dynamic activation quantisation, so the caveat applies equally to both and does not favour either.
MTP / speculative decoding
All 15 mtp.* tensors are present in bf16, re-grafted from the bf16 parent after
quantisation (llm-compressor does not save modules transformers never instantiates).
The 8 MTP Linear modules are listed in quantization_config.ignore. This matters:
without it, vLLM's compressed-tensors loader treats the bf16 head as a quantised target,
finds no scales, mis-loads it, and every draft is rejected — 0 % acceptance at every
position while the head still appears to load correctly in the logs.
Measured on vLLM with --speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":1}'
over greedy decoding of mixed chat/code/reasoning prompts:
| draft tokens | accepted | acceptance | |
|---|---|---|---|
| This model | 574 | 490 | 85.4% |
Smoke tests
Text generation, vision, and MTP key presence all pass:
- MTP tensors present:
True - Text:
True - Vision:
True— the tower correctly described the test image (The user wants a single, concise sentence describing the image. I need to identify the key subject and setting...)
Inference
vLLM (with MTP speculative decoding)
vllm serve huginnfork/Qwen3.8-27B-FP8 \
--trust-remote-code \
--gpu-memory-utilization 0.85 \
--max-model-len 8192 \
--max-num-seqs 32 \
--quantization compressed-tensors \
--speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":1}'
--max-num-seqs 32 is not optional on this architecture: the default (1024) exceeds the
available Mamba cache blocks and vLLM aborts CUDA-graph capture. FP8 GEMM runs native on Hopper (SM89+) and Blackwell.
transformers
from transformers import AutoModelForImageTextToText, AutoProcessor
import torch
repo = "huginnfork/Qwen3.8-27B-FP8"
proc = AutoProcessor.from_pretrained(repo, trust_remote_code=True)
model = AutoModelForImageTextToText.from_pretrained(
repo, dtype=torch.bfloat16, device_map="auto", trust_remote_code=True,
)
Provenance
Built with llm-compressor 0.13.0 + compressed-tensors 0.18.0 on transformers 5.14.1,
torch 2.13.0+cu130, on an RTX PRO 6000 Blackwell (SM120). Plain quantisation — no
abliteration, no fine-tuning.
Pipeline, recipes and every measurement JSON (shipped in this repo alongside the weights): https://github.com/huginnfork/llm-quantisation
- Downloads last month
- 1,363
Model tree for huginnfork/Qwen3.8-27B-FP8
Base model
Qwen/Qwen3.8-27B