CoolFace
Modelpublic

lribeiro/Qwen3.8-27B-FP8-Pessoa

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
3likes107kdownloads
Model Card

Qwen3.8-27B-FP8-Pessoa

FP8 (W8A16) weight-only, GPTQ-quantized variant of Qwen/Qwen3.8-27B, produced with llm-compressor and saved in compressed-tensors format for direct use with vLLM.

Pessoa is the best FP8 quantization of Qwen3.8-27B of a set of experiments with autoresearch it reached the the lowest KLD (0.0056) achieved by any practical-size FP8 model in a 97-model quantization sweep. Every linear language-model layer MLP, self-attention, and linear-attention uses FP8 E4M3 weight-only (W8A16) with per-channel weights, BF16 activations, and GPTQ Hessian error correction. The vision tower and MTP head are kept in BF16, so the model retains full image/video understanding and multi-token-prediction speculative decoding capability.

Named after Fernando Pessoa (1888–1935), the Portuguese poet who wrote under dozens of heteronyms — each a distinct literary persona with its own voice. This model too has multiple selves: the quantized language model, the unquantized vision tower, and the MTP speculative head three complete personas in one checkpoint.
TopicNotes
Checkpoint size31.24 GB (3 safetensors shards)
BF16 base55.6 GB → 1.78× smaller
ArchitectureQwen3_5ForConditionalGeneration (VLM: vision encoder + language model + MTP)
Vision tower333 BF16 tensors (460.7M params), kept unquantized from base
MTP head15 BF16 tensors, kept unquantized from base
Hardware requirementNVIDIA Blackwell (SM120) or Ampere/Hopper (FP8 E4M3 support)
EnginevLLM 0.26.1rc0 (infernal-invocation fork), FlashInfer backend

Model Details

Qwen3.8-27B (qwen3_5 / Qwen3_5ForConditionalGeneration):

  • —Type: Vision-language model (hybrid linear + full attention language model + vision encoder + MTP head)
  • —Parameters: 27B (language model) + 460.7M (vision tower) + 82.3M (MTP head)
  • —Layers: 64 — 48 linear-attention (GatedDeltaNet) + 16 full-attention (every 4th layer: 0, 4, 8, …, 60)
  • —Hidden size: 5,120
  • —Intermediate size: 17,408 (MLP is 3.4× hidden — dominates parameter count)
  • —Attention heads: 24 × 256 dim
  • —KV heads: 4 (GQA 6:1) — only on 16 full-attention layers
  • —Vocabulary: 248,320
  • —Activation: SiLU
  • —Context: 262,144 tokens native
  • —Vision encoder: 27-layer ViT, hidden size 1,152, patch size 16, 16 heads, temporal patch size 2
  • —MTP: 1 hidden layer, multi-token-prediction speculative decoding head

Each linear-attention layer has in_proj_qkv, in_proj_z, out_proj plus recurrent state paths in_proj_a/in_proj_b. Each full-attention layer has standard q/k/v/o_proj. All layers share gate_proj/up_proj/down_proj MLP blocks. The vision tower (model.visual.*) processes image/video patches and injects embeddings into the language model via image/video token boundaries. The MTP head (mtp.*) provides speculative decoding tokens for inference acceleration.


Quantization Configuration

Precision Assignment

Module groupFormatWeightsActivationsLayers
MLP (gate/up/down)FP8 W8A16 (E4M3)8-bit float, sym, channel, memoryless_minmax, actorder=staticBF16 (none)all 64
self_attn (Q/K/V/O)FP8 W8A16 (E4M3)sameBF16 (none)all 16 full-attn layers
linear_attn (qkv/z/out)FP8 W8A16 (E4M3)sameBF16 (none)all 48 lin-attn layers
KV cacheFP8 E4M3, tensor, static———

Key difference from W8A8: This model uses weight-only FP8 (W8A16) — weights are FP8 E4M3 per-channel, but activations remain BF16. This eliminates activation quantization error entirely, halving KLD versus W8A8 (0.0056 vs 0.0102). The tradeoff is ~18% slower prefill (4,875 vs 6,213 tok/s) because BF16 activations require dequantization before GEMM.

GPTQ: Hessian-based weight correction, sequential targets Qwen3_5DecoderLayer, actorder=static, dampening_frac=0.01, block_size=128. GPTQ corrects the weight quantization residual by adjusting remaining weights using the calibration data's second-order statistics — this is what gives Pessoa 2.3× lower KLD than ModelOpt's max-calibration FP8 (0.0056 vs 0.0127).

Tensor Inventory

CategoryCountFormatShard
MLP (gate/up/down)384FP8 W8A16shards 1–2
self_attn (Q/K/V/O + norms)192FP8 W8A16shards 1–2
linear_attn (qkv/z/out)576FP8 W8A16shards 1–2
embed/norm/lm_head211BF16 (unquantized norms/embed)shards 1–2
Vision tower333BF16shard 3
MTP head15BF16shard 3
Total1,6313 shards

Modules Kept in BF16

PatternCountReason
re:.*visual.*333Vision tower — small (460M), quantization-sensitive, not worth the risk
re:^mtp.*15MTP speculative-decoding head — kept BF16 for functional speculative decoding
lm_head1Output projection directly produces logits — quantizing increases KLD by ~30%
linear_attn.norm (×48)48Numerically fragile normalization path in GatedDeltaNet
linear_attn.in_proj_a (×48)48Recurrent state accumulator — quantizing compounds error across sequence, produces NaN
linear_attn.in_proj_b (×48)48Recurrent state accumulator — same as inproja
linear_attn (whole, ×48)48Parent module ignore — covers any submodules not explicitly listed
Total ignore entries195

Calibration

  • —Source: malaiwah/qwen38-27b-fidelity-suite-v3 tokens (181 contexts × 2048 tokens)
  • —Samples: 181
  • —Max sequence length: 2048
  • —Format: Decoded token IDs from suite, not raw text
  • —Dampening: dampening_frac=0.01 (default — confirmed optimal for FP8; tested 0.001–0.1, all within noise)

Compressed-Tensors Config

json
{
  "quant_method": "compressed-tensors",
  "format": "float-quantized",
  "quantization_status": "compressed",
  "version": "0.18.0",
  "config_groups": {
    "group_0": {
      "targets": ["Linear"],
      "weights": {
        "num_bits": 8,
        "type": "float",
        "symmetric": true,
        "group_size": null,
        "strategy": "channel",
        "dynamic": false,
        "actorder": "static",
        "observer": "memoryless_minmax"
      },
      "input_activations": null
    }
  },
  "kv_cache_scheme": {
    "num_bits": 8,
    "type": "float",
    "symmetric": true,
    "strategy": "tensor",
    "dynamic": false,
    "observer": "static_minmax"
  }
}

Evaluation

Distribution Fidelity (KLD)

Hidden-state capture after final RMSNorm → shared BF16 LM-head replay → full-vocabulary KL(BF16_ref ‖ candidate), two-pass log-sum-exp normalization. Body-only comparison (candidate LM head unused). Suite: 136 contexts × 2048 tokens, 278,392 scored positions over 248,320-token vocabulary.

MetricValue
Token mean KLD0.005559
Token median KLD0.001166
p95 KLD0.020902
p99 KLD0.085659
p99.9 KLD0.316350
Max KLD4.421645
Mean JSD (bits)0.001958
Top-1 agreement97.47%
Validation tierExcellent (KLD < 0.006, Top-1 > 97%)

KLD by Domain

StratumContextsMean KLD
multilingual70.00192
scientific390.00193
encyclopedic130.00377
code360.00596
literary410.00985

Literary text remains the dominant KLD contributor — 5.1× the scientific stratum. Creative/prose generation is disproportionately affected by quantization, but the gap is narrower than in W8A8 configs (v17: 5.4×) and much narrower than 4-bit configs. Pessoa's weight-only approach preserves activation distributions, keeping literary KLD under 0.01.

Throughput

Single NVIDIA RTX PRO 6000 Blackwell (SM120, 96 GB), vLLM 0.26.1rc0, FlashInfer backend. Duration-based sustained decode, 30s cells, temperature 0.0, ignore_eos=true.

MetricValue
Prefill (2k context)4,875 tok/s
TTFT (2k)0.418 s
Decode C1 (0 ctx)45.6 tok/s
Decode C1 (2k ctx)45.0 tok/s
Decode C4 (0 ctx)166.6 tok/s
Decode C4 (2k ctx)158.9 tok/s

NOTE: This was not optimized for speed, but for equal grounds between all experiments and models tested. An optimized setup with a 6kpro reaches >100tok/s with MTP.

Composite Score

$$\text{score} = \frac{\text{prefill}{2k} \times \text{decode}{c1}}{\text{KLD} \times 10^6} = \frac{4875 \times 45.6}{0.00556 \times 10^6} = \mathbf{40.02}$$

Highest composite score among all practical-size FP8 models in the 97-model sweep.


Context Within Experiment Series

Pessoa is the FP8 weight-only winner from a systematic 97-model quantization sweep of Qwen3.8-27B, exploring NVFP4, MXFP8, and FP8 formats via both ModelOpt (NVIDIA) and GPTQ (llm-compressor). The sweep evaluated GPTQ vs ModelOpt, weight-only vs weight+activation, single-format vs mixed-precision, and per-layer sensitivity.

Key Finding: Weight-Only Beats Weight+Activation for FP8

ConfigKLDPrefillDecodeScore
Pessoa (W8A16 weight-only) ★0.00564,87545.640.02
FP8 W8A8 (GPTQ)0.01026,21346.628.46
FP8 W8A16 (ModelOpt)0.01276,02645.421.65

Weight-only FP8 eliminates activation quantization error entirely. GPTQ corrects the weight quantization residual. The result is 2× better KLD than W8A8 and 2.3× better than ModelOpt at the cost of ~18% slower prefill (BF16 dequantization before GEMM).

Key Finding: GPTQ Beats ModelOpt by 2.3×

FormatModelOpt best KLDGPTQ best KLDRatio
FP8 (weight-only)0.012650.005562.3×
FP8 (W8A8 mixed)0.017250.010161.7×
MXFP8 (weight-only)0.012650.010721.2×
NVFP4 (mixed)0.350260.0108732×

GPTQ's Hessian-based weight correction compensates for quantization error by adjusting remaining weights using calibration data's second-order statistics. ModelOpt's max calibration only computes scale factors without weight correction.

Pareto Position

ObjectiveBest ModelKLDPrefillDecodeScore
Best quality (any size) [way too big]gptq-fp8-attn-only0.00264,45830.952.53
Best FP8 (~28 GB)Pessoa ★0.00564,87545.640.02
Best MXFP8 (~28 GB)gptq-mxfp8-mixed0.01075,91746.125.44
Best NVFP4 (~27 GB)gptq-nvfp4-mixed-80.01095,95648.126.38
Best all-FP8 (W8A8)v170.01237,30649.829.55

Pessoa dominates the practical-size Pareto frontier: 2× lower KLD than any other ~28 GB model, with the highest composite score in its class.


Usage

bash
# vLLM serve (requires Blackwell SM120 + FlashInfer)
vllm serve /models/Qwen3.8-27B-FP8-Pessoa \
  --max-model-len 262144 \
  --max-num-seqs 16 \
  --quantization compressed-tensors \
  --kv-cache-dtype fp8 \
  --trust-remote-code \
  --speculative-config '{"method":"mtp","num_speculative_tokens":3}'
`--max-num-seqs` matters on this architecture. 48 of 64 layers use linear attention, and vLLM allocates one Mamba-style cache block per decode sequence. The default max_num_seqs=1024 can exceed available blocks and fail during CUDA graph capture with max_num_seqs (1024) exceeds available Mamba cache blocks. Lower to 16–512 or raise --gpu-memory-utilization. This is a property of the base model, not of quantization.
python
from vllm import LLM, SamplingParams

llm = LLM(model="/models/Qwen3.8-27B-FP8-Pessoa",
          quantization="compressed-tensors",
          kv_cache_dtype="fp8",
          max_model_len=262144,
          trust_remote_code=True)

# Text-only generation
out = llm.generate(
    ["Explain 4-bit quantization in two sentences."],
    SamplingParams(temperature=0.7, max_tokens=256),
)
print(out[0].outputs[0].text)

# Vision: image + text via chat template
from vllm.inputs import TextPrompt
messages = [{
    "role": "user",
    "content": [
        {"type": "image_url", "image_url": {"url": "https://example.com/image.png"}},
        {"type": "text", "text": "Describe this image."},
    ],
}]
prompt = llm.get_tokenizer().apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True)
out = llm.generate(
    {"prompt": prompt, "multi_modal_data": {"image": image_placeholder}},
    SamplingParams(temperature=0.7, max_tokens=512),
)
print(out[0].outputs[0].text)

Docker Compose

A docker-compose.yml is provided in the experiment workspace for one-command deployment. The image bundles the vLLM infernal-invocation fork with FlashInfer and SM120 kernels; only the quantized checkpoint must be mounted from the host.

bash
# Place the checkpoint at ./models/Qwen3.8-27B-FP8-Pessoa, then:
docker compose up -d

# Or override the model path and port:
MODEL_DIR=/data/models/Qwen3.8-27B-FP8-Pessoa PORT=8001 docker compose up -d

The endpoint is OpenAI-compatible: http://localhost:8000/v1.

<details> <summary><b>docker-compose.yml</b></summary>

yaml
# docker-compose.yml — Qwen3.8-27B-FP8-Pessoa
#
# Serves the FP8 W8A16 weight-only GPTQ quantization via mainline vLLM.
# Image: vllm/vllm-openai:latest
#
# Requirements:
#   - NVIDIA Blackwell (SM120) GPU with FP8 E4M3 tensor cores
#   - NVIDIA Container Toolkit (nvidia-docker) installed on host
#   - Quantized checkpoint at ${MODEL_DIR}
#
# Customize via .env file or shell environment variables:
#
#   PORT=8000                           API server port
#   SERVED_MODEL_NAME=qwen38-27b-pessoa Model name returned by /v1/models
#   MAX_MODEL_LEN=262144                Maximum context length (tokens)
#   MAX_NUM_SEQS=16                     Maximum concurrent decode sequences
#   MAX_NUM_BATCHED_TOKENS=16384        Maximum tokens per batching iteration
#   GPU_MEMORY_UTILIZATION=0.97         Fraction of GPU memory for vLLM (0.0–1.0)
#   TENSOR_PARALLEL_SIZE=2              Tensor-parallel degree (1, 2, or 4)
#   KV_CACHE_DTYPE=fp8                  KV cache dtype: fp8 | auto | bfloat16
#   CUDA_VISIBLE_DEVICES=0,1            GPU indices to use
#   MODEL_DIR=./models/Qwen3.8-27B-FP8-Pessoa  Host path to checkpoint

services:
  qwen38-27b-pessoa:
    image: vllm/vllm-openai:latest
    container_name: qwen38-27b-pessoa
    ipc: host
    ports:
      - "${PORT:-8000}:${PORT:-8000}"
    volumes:
      - ${MODEL_DIR:-./models/Qwen3.8-27B-FP8-Pessoa}:/models/Qwen3.8-27B-FP8-Pessoa:ro
      - vllm-cache:/cache
      - hf-cache:/data/hf_cache
    environment:
      - CUDA_VISIBLE_DEVICES=${CUDA_VISIBLE_DEVICES:-0}
      - PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
      - OMP_NUM_THREADS=16
      - HF_HOME=/data/hf_cache
      - VLLM_CACHE_ROOT=/cache/vllm
      - TORCHINDUCTOR_CACHE_DIR=/cache/torchinductor
      - TRITON_CACHE_DIR=/cache/triton
    entrypoint: ["python3", "-m", "vllm.entrypoints.cli.main"]
    command:
      - serve
      - /models/Qwen3.8-27B-FP8-Pessoa
      - --served-model-name=${SERVED_MODEL_NAME:-qwen38-27b-pessoa}
      - --host=0.0.0.0
      - --port=${PORT:-8000}
      - --trust-remote-code
      - --quantization=compressed-tensors
      - --tensor-parallel-size=${TENSOR_PARALLEL_SIZE:-1}
      - --disable-custom-all-reduce
      - --kv-cache-dtype=${KV_CACHE_DTYPE:-fp8}
      - --block-size=128
      - --gpu-memory-utilization=${GPU_MEMORY_UTILIZATION:-0.96}
      - --max-model-len=${MAX_MODEL_LEN:-262144}
      - --max-num-seqs=${MAX_NUM_SEQS:-16}
      - --max-num-batched-tokens=${MAX_NUM_BATCHED_TOKENS:-16384}
      - --max-cudagraph-capture-size=64
      - --generation-config=vllm
      - --reasoning-parser=qwen3
      - --attention-backend=flashinfer
      - --enable-chunked-prefill
      - --enable-prefix-caching
      - --enable-auto-tool-choice
      - --tool-call-parser=qwen3_coder
      - --mm-encoder-tp-mode=data
      - --speculative-config={"method":"mtp","num_speculative_tokens":3}
      - >-
        --compilation-config={"cudagraph_mode":"FULL_AND_PIECEWISE","custom_ops":["all"]}
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [gpu]

volumes:
  vllm-cache:
  hf-cache:

</details>

Configurable variables (set in .env or shell):

VariableDefaultDescription
PORT8000API server port (OpenAI-compatible)
SERVED_MODEL_NAMEqwen38-27b-pessoaModel name returned by /v1/models
MAX_MODEL_LEN262144Maximum context length in tokens
MAX_NUM_SEQS16Maximum concurrent decode sequences (lower if Mamba cache blocks exhausted)
MAX_NUM_BATCHED_TOKENS16384Maximum tokens per batching iteration
GPU_MEMORY_UTILIZATION0.96Fraction of GPU memory allocated to vLLM
TENSOR_PARALLEL_SIZE1Tensor-parallel degree (1, 2, or 4)
KV_CACHE_DTYPEfp8KV cache dtype: fp8, auto, or bfloat16
CUDA_VISIBLE_DEVICES0GPU index(s) to use
MODEL_DIR./models/Qwen3.8-27B-FP8-PessoaHost path to quantized checkpoint

Provenance & Integrity

ArtifactSHA-256
Model index (merged)6cfd4c257d1d22456d48e8ae43a37e1bec4210124d6187f507fc9affeec982c2
Config (VLM)ee992684dffb2db4e7ade4d8e8fee9e5402bb3d075487eea16ebc3aa82c07d27
Shard 1 (quantized LM)25f10ccdeee734cc6fe0f3ed0f34830f61cc58d8cd4d608c5dcede8a19825b52
Shard 2 (quantized LM)7350bf425f9cca42f4376ce88e3069c1a7727bc59096ed81e0024d74ede64fd7
Shard 3 (BF16 vision + MTP)bf23280788e616231c29db327f7df25254673c0e8c33c717bf321e310ec5ef64
Suite tokens3f9d17f1b55f64872ad3ac19c8711654e09ba70b7ca14b0851525088fe735691
Shared LM head25a30fd5f826da0abc4efc4cc71def9f02bcb8085f7175eee284d221dee4cfff

The quantized LM weights (shards 1–2) are byte-identical to the original text-only gptq-fp8-w8a16-mlp checkpoint. Shard 3 contains 333 BF16 visual + 15 BF16 MTP tensors extracted from the base model — no re-quantization was performed on these.


Hardware & Runtime

FieldValue
GPU4× NVIDIA RTX PRO 6000 Blackwell Max-Q (SM120, 96 GiB GDDR7 each)
Driver595.58.03
Benchmark GPU count1
VRAM used86,616 / 97,887 MB (88.5%)
Temp (avg / max)66.3 °C / 74.0 °C
GPU util (avg)91.0%
Power (avg / max)280 W / 302 W

Reproduction

Step 1: FP8 W8A16 weight-only GPTQ quantization

bash
# Inside Docker (vLLM infernal-invocation image, llm-compressor, SM120)
CUDA_VISIBLE_DEVICES=0 SUITE_DIR=/data/suite-v3 \
  python scripts/quant_gptq_unified.py \
  --model /data/models/Qwen3.8-27B-bf16 \
  --output /data/models/Qwen3.8-27B-gptq-fp8-w8a16-mlp \
  --format fp8-w8a16-mlp --calib-samples 181

Calibration tokens from $SUITE_DIR/tokens (default /data/suite-v3/tokens). Script: scripts/quant_gptq_unified.py. Format: fp8-w8a16-mlp (FP8 E4M3 per-channel weight-only for all Linear, BF16 activations, GPTQ Hessian correction).

Step 2: Merge visual tower + MTP from base

bash
# Merge quantized LM shards with BF16 visual+mtp from base model
python /workspace/scripts/merge_vision_mixed.py \
  --src /models/Qwen3.8-27B-gptq-fp8-w8a16-mlp \
  --base /models/Qwen3.8-27B-bf16 \
  --output /data/models/Qwen3.8-27B-FP8-Pessoa

Script: scripts/merge_vision_mixed.py. Extracts 333 visual + 15 MTP tensors from the BF16 base, writes them as a 3rd shard, copies the 2 quantized shards unchanged, and patches config.json to Qwen3_5ForConditionalGeneration (VLM) with vision_config, text_config, and re:^mtp.* / re:.*visual.* added to the quantization ignore list.


Limitations

  • —Weight-only means slower prefill. BF16 activations require dequantization before GEMM, making prefill ~18% slower than W8A8 (4,875 vs 6,213 tok/s). Decode speed is comparable (45.6 vs 46.6 tok/s). If prefill throughput matters more than KLD, use the W8A8 variant (v17).
  • —Blackwell-optimized. FP8 E4M3 MMA is supported on SM120 (Blackwell), SM89/SM90 (Ada/Hopper), but the benchmark and KLD capture were run on SM120 only. Validate on your hardware.
  • —Body-only KLD. Fidelity measured against a shared BF16 LM head; end-to-end generation quality may differ slightly.
  • —Literary domain degradation. 5.1× higher KLD on literary text vs scientific — creative/prose generation is disproportionately affected, though less severely than in W8A8 or 4-bit configs.
  • —MTP speculative decoding acceptance depends on vLLM version and configuration. Ensure re:^mtp.* is in the quantization ignore list (it is, in this checkpoint) so vLLM's compressed-tensors loader leaves the BF16 MTP weights untouched.
  • —Quantization is lossy. Validate on your own workload before production use.

Acknowledgements

Standing on the shoulders of giants. This work would not exist without the **rtx6kpro** community and the broader local-inference-lab Discord — the open protocol, tooling, and baseline measurements that made systematic quantization comparison possible.

The distribution-fidelity (KLD) methodology follows the published protocol from Kimi-K3 distribution fidelity 1024×2048. The reference harness (glm52_exl3_shared_h_kld.py) and the benchmark tool (llm-inference-bench) are adapted from the rtx6kpro repository. The Gilded Gnosis EXL3 model cards established the per-bit error-ladder and validation-tier framework that this sweep builds on.

"I am the empty stage where the actors perform their various roles." — Bernardo Soares (heteronym of Fernando Pessoa), The Book of Disquiet