Image-Text-to-Text
Transformers
Safetensors
qwen3_5
qwen
multimodal
mtp
speculative-decoding
compressed-tensors
llm-compressor
fp8
w8a8
conversational
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
Upload README.md with huggingface_hub
Browse files
README.md
CHANGED
|
@@ -56,23 +56,65 @@ KLD is per-token, 8 samples from `neuralmagic/calibration` (LLM split) at `max_s
|
|
| 56 |
PPL is `wikitext-2-raw` test, non-overlapping 2048-token chunks. Baseline for both is
|
| 57 |
**bf16 `Qwen/Qwen3.8-27B` itself**, so what is measured is quantisation loss and nothing else.
|
| 58 |
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|---|---|---|---|---|---|
|
| 61 |
-
| `Qwen/Qwen3.8-27B` (bf16) | — | 0 |
|
| 62 |
-
| [`Qwen/Qwen3.8-27B-FP8`](https://huggingface.co/Qwen/Qwen3.8-27B-FP8) (official) | 407 |
|
| 63 |
-
| **This model** | 192 | 0.
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
So the reasons to prefer this build are **architectural, not average-case accuracy**:
|
| 78 |
|
|
@@ -99,6 +141,13 @@ without it, vLLM's compressed-tensors loader treats the bf16 head as a quantised
|
|
| 99 |
finds no scales, mis-loads it, and **every draft is rejected — 0 % acceptance at every
|
| 100 |
position** while the head still appears to load correctly in the logs.
|
| 101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
## Smoke tests
|
| 103 |
|
| 104 |
Text generation, vision, and MTP key presence all pass:
|
|
|
|
| 56 |
PPL is `wikitext-2-raw` test, non-overlapping 2048-token chunks. Baseline for both is
|
| 57 |
**bf16 `Qwen/Qwen3.8-27B` itself**, so what is measured is quantisation loss and nothing else.
|
| 58 |
|
| 59 |
+
**Two KLD columns, because one number cannot be fair to both checkpoints.** The official
|
| 60 |
+
release is DeepSeek-format FP8, which has to be dequantised to plain bf16 before it will
|
| 61 |
+
run at all on Blackwell — and a dequantised checkpoint runs with **bf16 activations**. Our
|
| 62 |
+
checkpoint, loaded normally, still applies its scheme's **dynamic FP8 activation quant**.
|
| 63 |
+
Comparing those two directly measures W8A8 against W8A16 and flatters whichever model was
|
| 64 |
+
dequantised. So both are reported both ways.
|
| 65 |
+
|
| 66 |
+
| Model | Modules quantised | KLD (weight-only) | KLD (as deployed) | PPL | ΔPPL |
|
| 67 |
|---|---|---|---|---|---|
|
| 68 |
+
| `Qwen/Qwen3.8-27B` (bf16) | — | 0 | 0 | 6.9416 | — |
|
| 69 |
+
| [`Qwen/Qwen3.8-27B-FP8`](https://huggingface.co/Qwen/Qwen3.8-27B-FP8) (official) | 407 | 0.0523 | 0.1001 | 6.9539 | +0.18 % |
|
| 70 |
+
| **This model** | 192 | **0.0362** | **0.0756** | **6.9325** | **-0.13 %** |
|
| 71 |
+
|
| 72 |
+
*Weight-only* = weights round-tripped through the quantised format, activations bf16.
|
| 73 |
+
*As deployed* = the same weights plus dynamic per-token FP8 activation quantisation on
|
| 74 |
+
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.
|
| 75 |
+
|
| 76 |
+
**This build has lower divergence from the bf16 parent than the official release on both
|
| 77 |
+
measures** — **31% lower** weight-only and **24% lower** as deployed — while quantising
|
| 78 |
+
192 modules to the official's 407.
|
| 79 |
+
|
| 80 |
+
On PPL the two are not meaningfully separable; both sit within noise of the bf16 parent.
|
| 81 |
+
A negative ΔPPL does **not** mean this build beats its own parent, only that the loss is
|
| 82 |
+
below measurement noise.
|
| 83 |
+
|
| 84 |
+
### What does *not* explain the difference
|
| 85 |
+
|
| 86 |
+
The intuitive story is that scale layout matters — the official uses 128x128 **block**
|
| 87 |
+
scales, `llm-compressor` emits one scale per **output channel**. We tested that directly,
|
| 88 |
+
simulating the FP8 E4M3 round-trip on real weight tensors from this model
|
| 89 |
+
([`experiment_block_scales.py`](https://github.com/huginnfork/llm-quantisation/blob/master/remote/experiment_block_scales.py)):
|
| 90 |
+
|
| 91 |
+
| scheme | #scales | rel. Frobenius err | max abs err |
|
| 92 |
+
|---|---|---|---|
|
| 93 |
+
| per-tensor | 1 | 0.02648 | 0.02065 |
|
| 94 |
+
| per-output-channel (this build) | 5120 | 0.02643 | 0.02065 |
|
| 95 |
+
| block 128x128 (official) | 5440 | 0.02643 | **0.00426** |
|
| 96 |
+
| *control:* INT8 per-tensor | 1 | 0.0750 | — |
|
| 97 |
+
| *control:* INT8 per-output-channel | 17408 | **0.0101** | — |
|
| 98 |
+
| *control:* INT8 block 128x128 | 5440 | 0.0144 | — |
|
| 99 |
+
|
| 100 |
+
All FP8 variants land within 0.1 % of each other — **including per-tensor, with a single
|
| 101 |
+
scale for the entire matrix**. The reason is that FP8 is a *floating-point* format: every
|
| 102 |
+
element carries its own exponent, so the scale only has to bring values into range rather
|
| 103 |
+
than resolve dynamic range the way a fixed-point scale must. The INT8 control shows the
|
| 104 |
+
method is sensitive enough to detect layout effects where they exist (a 7.4x spread) — and
|
| 105 |
+
that in *that* regime per-output-channel actually beats 128x128 block, having more scales.
|
| 106 |
+
|
| 107 |
+
Block scaling does buy a ~5x lower **worst-case** weight error; that is an outlier-tail
|
| 108 |
+
property, not an average one.
|
| 109 |
+
|
| 110 |
+
We also checked whether the vendor used a smarter rounding than round-to-nearest, by
|
| 111 |
+
comparing their stored weights against an RTN round-trip of the same parent tensors
|
| 112 |
+
([`experiment_rounding.py`](https://github.com/huginnfork/llm-quantisation/blob/master/remote/experiment_rounding.py)):
|
| 113 |
+
their reconstruction error matches RTN to within 0.3 %. They used plain round-to-nearest.
|
| 114 |
+
|
| 115 |
+
So the gap is not scale layout and not rounding — it is **which modules get quantised**.
|
| 116 |
+
This build leaves the attention path, the SSM block and the MTP head in bf16; the official
|
| 117 |
+
quantises all of them.
|
| 118 |
|
| 119 |
So the reasons to prefer this build are **architectural, not average-case accuracy**:
|
| 120 |
|
|
|
|
| 141 |
finds no scales, mis-loads it, and **every draft is rejected — 0 % acceptance at every
|
| 142 |
position** while the head still appears to load correctly in the logs.
|
| 143 |
|
| 144 |
+
Measured on vLLM with `--speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":1}'`
|
| 145 |
+
over greedy decoding of mixed chat/code/reasoning prompts:
|
| 146 |
+
|
| 147 |
+
| | draft tokens | accepted | acceptance |
|
| 148 |
+
|---|---|---|---|
|
| 149 |
+
| This model | 574 | 490 | **85.4%** |
|
| 150 |
+
|
| 151 |
## Smoke tests
|
| 152 |
|
| 153 |
Text generation, vision, and MTP key presence all pass:
|