Qwen3.8-27B-NVFP4
Quantized build of Qwen/Qwen3.8-27B, produced by vrfai.
Format: NVFP4 (W4A4), serialized as compressed-tensors.
Size: 18.4 GB (base model: 52 GB).
[!IMPORTANT] Hardware requirement. NVFP4 arithmetic requires a GPU with compute capability 10.0 or newer (NVIDIA Blackwell: B100/B200/GB200). On older hardware — including H100/H200 (SM90) and Ada (SM89) — vLLM loads this checkpoint through the Marlin weight-only FP4 path: it runs correctly and keeps the memory saving, but weights are expanded before each GEMM, so compute-bound work (prefill, large batches) is slower than the bf16 model rather than faster.
This also means the scores below are not W4A4 scores. They were measured on an H100, where the Marlin path leaves activations in bfloat16 and ignores the
input_global_scalethis checkpoint carries for all 400 quantized modules — so what was measured is effectively W4A16. Quantizing activations as well, which is what Blackwell will actually do, raises the relative error of a linear layer's output by 1.37x on average (6.7% to 9.1%, measured over 27 layers spanning the depth of the model using real activations). Treat these numbers as an upper bound on Blackwell accuracy, not a prediction of it.
What was quantized
The language model is quantized; the vision tower is not. Within the language model, three groups are deliberately held at bf16.
| Component | Precision |
|---|---|
MLP gate_proj / up_proj / down_proj | NVFP4 (W4A4) |
Gated DeltaNet in_proj_qkv / in_proj_z / out_proj | NVFP4 (W4A4) |
Attention q_proj / k_proj / v_proj / o_proj | NVFP4 (W4A4) |
Gated DeltaNet in_proj_a / in_proj_b | bf16 |
lm_head | bf16 |
Vision tower (model.visual.*) | bf16 |
All normalization layers, conv1d, embeddings | bf16 (untouched) |
93.28% of all nn.Linear weight is quantized; 6.72% is held at bf16.
Why those three stay in bf16:
lm_headis a 5120 x 248320 projection feeding the softmax directly — the most accuracy-sensitive layer in the model.- The vision tower is 456M of 26B parameters. Quantizing it saves almost nothing while every answer is conditioned on its output.
in_proj_a/in_proj_bemit the per-head decay and delta-rule beta that drive the Gated DeltaNet recurrence. Error there compounds along the whole sequence instead of staying local to one position, and at 0.09% of Linear weight they are the cheapest place to spend precision.
Quantization configuration
| Method | llmcompressor 0.13.0 |
| Scheme | NVFP4 |
| Weights | 4-bit NVIDIA float, group size 16, FP8 block scales + FP32 global scale |
| Activations | 4-bit NVIDIA float, group size 16 |
| SmoothQuant | enabled, alpha = 0.8 |
| Calibration data | abisee/cnn_dailymail (512 samples @ 2048 tokens) |
| Modules held at bf16 | 207 |
Benchmark results
Performance
Thinking enabled at the model's default reasoning_effort, greedy decoding.
This is how the model is meant to be run, so these are the only absolute scores
quoted here.
| Task | n | This model | bf16 | Qwen card |
|---|---|---|---|---|
| MathVision (testmini) | 304 | 81.91 | 86.18 | 90.0 |
| ERQA | 400 | 66.25 | 65.00 | 65.5 |
The bf16 column is our own measurement of the original weights under this harness, and it lands within half a point of Qwen's published ERQA figure — which is the evidence that the harness measures what their card measures. The remaining gaps are protocol: every run here is greedy, while Qwen sample at temperature 1.0 / top_p 0.95 / top_k 20.
How far this checkpoint drifts from bf16
Absolute scores are a poor instrument for this question. With thinking on, the
same bf16 weights measured twice — changing only the batch size — move up to
2.30 points on their own, because greedy decoding is not reproducible on this
architecture: vLLM's VLLM_BATCH_INVARIANT mode refuses to start
(not supported for GDN_ATTN; 48 of the 64 layers are Gated DeltaNet), so GEMM
reduction order still depends on how requests batch together, and one flipped
token early in a long chain rewrites everything after it.
Short answers do not have that problem: there the pipeline reproduces itself to within 0.13 points. So the comparison below runs in that regime — chosen for measurement sensitivity, not because it reflects normal use. It reports drift only, never a score.
| Task | n | Δ vs bf16 | floor | verdict |
|---|---|---|---|---|
| AI2D | 3,088 | -2.59 | 0.00 | measurable loss |
| ChartQA | 2,500 | +0.36 | 0.00 | no measurable difference |
| ScienceQA-IMG | 2,017 | -1.59 | 0.05 | measurable loss |
| MMStar | 1,500 | +1.93 | 0.07 | no measurable difference |
| OCRBench | 1,000 | +0.00 | 0.00 | no measurable difference |
| CountBenchQA | 491 | +0.61 | 0.00 | no measurable difference |
| RealWorldQA | 765 | -1.57 | 0.13 | no measurable difference |
| OmniDocBench | 981 | -2.55 | 0.06 | measurable loss |
| MathVision (testmini) | 304 | -4.28 | 2.30 | below this task's floor |
| ERQA | 400 | +1.25 | 1.00 | below this task's floor |
floor is how far the score moved between two runs of the unmodified bf16
weights. A Δ smaller than the floor beside it is a property of the inference
pipeline, not of quantization. p-values are Holm-Bonferroni adjusted across all
30 task × checkpoint tests; without that correction roughly one would reach
significance by chance.
10 tasks, 13,046 documents, deterministic scorers only. Tasks graded by an LLM judge (MathVista, MMMU, CharXiv, HallusionBench, MMBench) are excluded: a second model's variance has no place in a measurement about numerics.
| Quantized weights | 18.4 GB |
| Hardware | 1x NVIDIA H100 80GB HBM3 |
| Runtime | vLLM 0.27.1 |
| Harness | lmms-eval, greedy decoding |
Usage
No quantization flag is required — vLLM reads the format from config.json.
vllm serve vrfai/Qwen3.8-27B-NVFP4 --trust-remote-code
from vllm import LLM, SamplingParams
llm = LLM(
model="vrfai/Qwen3.8-27B-NVFP4",
trust_remote_code=True,
max_num_seqs=64, # Gated DeltaNet holds one state block per decode
# sequence, so the default 1024 exceeds the pool
)
print(llm.generate(["The capital of France is"],
SamplingParams(temperature=0.0, max_tokens=64))[0].outputs[0].text)
Requires vLLM >= 0.27.1, the first release with Qwen3_5ForConditionalGeneration.
[!WARNING] Everything below this line is reproduced verbatim from the base model card, Qwen/Qwen3.8-27B. The benchmark tables it contains were measured by the Qwen team on the original bf16 weights. They were not measured on this quantized checkpoint. For numbers measured on these weights, see the Benchmark results section above.
Qwen3.8-27B
[!Note] This repository contains model weights and configuration files for the post-trained model in the Hugging Face Transformers format.
These artifacts are compatible with Hugging Face Transformers, vLLM, SGLang, TokenSpeed, etc.
[!Tip] For users seeking managed, scalable inference without infrastructure maintenance, the official Qwen API service is provided by Qwen Cloud. In particular, Qwen3.8-27B will be available as a hosted version with more production features, e.g., 1M context length by default, official built-in tools. For more information, please refer to the Qwen3.8-27B Overview. The service is coming soon. Stay tuned for updates.
Following the widespread community adoption of the Qwen3.5 and Qwen3.6 series, we are pleased to introduce Qwen3.8, the most capable generation in the Qwen open-model family to date.
Built on the architectural foundation of Qwen3.5, Qwen3.8 delivers substantial gains across coding, professional work, research, and long-horizon agentic tasks. Qwen3.8-27B brings these advances to a compact, deployment-friendly dense model: a native vision-language model that understands images and videos, with flexible thinking control, designed to carry complex, multi-step tasks through to completion with greater reliability.
Qwen3.8 Highlights
Qwen3.8-27B features the following enhancements:
- Core Capabilities: Comprehensive improvements across coding, professional work, research, and long-horizon agentic tasks.
- Agent Execution: Stronger autonomous planning and better handling of environment feedback, leading to more reliable end-to-end task completion.
- Downstream Compatibility: Broader support for popular harnesses and development tools, making it easier to integrate into your existing stack.
- Flexible Thinking Control: Thinking mode is on by default and can be disabled per request; reasoning depth can be tuned with
reasoning_effort, and reasoning context from historical messages is retained viapreserve_thinking. - Vision-Language Understanding: Native support for image and video understanding, from STEM diagrams and documents to hour-scale videos.
Model Overview
- Type: Causal Language Model with Vision Encoder
- Training Stage: Pre-training & Post-training
- Language Model
- Number of Parameters: 27B
- Hidden Dimension: 5120
- Token Embedding: 248,320 (Padded)
- Number of Layers: 64
- Hidden Layout: 16 × (3 × (Gated DeltaNet → FFN) → 1 × (Gated Attention → FFN))
- Gated DeltaNet:
- Number of Linear Attention Heads: 48 for V and 16 for QK
- Head Dimension: 128
- Gated Attention:
- Number of Attention Heads: 24 for Q and 4 for KV
- Head Dimension: 256
- Rotary Position Embedding Dimension: 64
- Feed Forward Network:
- Intermediate Dimension: 17,408
- LM Output: 248,320 (Padded)
- MTP (Multi-Token Prediction): trained with multiple steps
- Context Length: 262,144 natively and extensible up to 1,000,000 tokens.
Benchmark Results
Text Performance
VL Performance
Quickstart
For streamlined integration, we recommend using Qwen3.8 via APIs.
Serving Qwen3.8
[!Important] Inference efficiency and throughput vary significantly across frameworks. We recommend using the latest framework versions to ensure optimal performance and compatibility. For production workloads or high-throughput scenarios, dedicated serving engines such as SGLang, vLLM, or TokenSpeed are recommended.
Qwen3.8 can be deployed with popular inference frameworks, e.g.:
API Usage
[!Important] Qwen3.8 models operate in thinking mode by default, generating thinking content signified by
<think>\n...</think>\n\nbefore producing the final response. To disable thinking content and obtain a direct response, refer to the examples here.
[!Tip] We recommend using the following sets of sampling parameters for generation:
- Thinking Mode:
temperature=1.0,top_p=0.95,top_k=20,min_p=0.0,presence_penalty=0.0,repetition_penalty=1.0- Instruct (or non-thinking) mode:
temperature=0.7,top_p=0.80,top_k=20,min_p=0.0,presence_penalty=1.5,repetition_penalty=1.0Please note that the support for sampling parameters varies according to inference frameworks.
Qwen3.8 comes with official support for reasoning_effort, which can be used to adjust reasoning depth and control cost:
xhigh(default): for complex tasks demanding thorough analysismedium: balancing accuracy and speedlow: efficient reasoning optimizing for speed and cost
In addition, preserve_thinking is enabled by default for all workloads for the best out-of-the-box experience. To disable preserved thinking, refer to the examples here.
[!Tip] In multi-turn agentic tasks, lower reasoning effort does not always reduce overall task completion time. Although it may produce faster per-turn responses, it can also lead to insufficient analysis, more failures, and repeated retries, which may increase total latency and token consumption.
Chat Completions API
The Chat Completions API can be used with most inference frameworks, as well as Qwen Cloud. Before starting, make sure the OpenAI Python SDK is installed and the API key and the API base URL are configured, e.g.:
pip install -U openai
# Set the following accordingly
export OPENAI_BASE_URL='your-base-url'
export OPENAI_API_KEY='your-api-key'
Text-Only Input
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [{"role": "user", "content": "Write a Python function to merge two sorted linked lists."}]
completion = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
extra_body={
"chat_template_kwargs": {
"enable_thinking": True, # on by default
"preserve_thinking": True, # on by default
},
},
reasoning_effort="xhigh", # xhigh by default; supported levels are xhigh, medium, and low
stream=True,
stream_options={"include_usage": True},
)
reasoning_content = ""
answer_content = ""
is_answering = False
print("\n" + "=" * 20 + "Reasoning" + "=" * 20 + "\n")
for chunk in completion:
if not chunk.choices:
print("\nUsage:")
print(chunk.usage)
continue
delta = chunk.choices[0].delta
if hasattr(delta, "reasoning_content") and delta.reasoning_content is not None:
if not is_answering:
print(delta.reasoning_content, end="", flush=True)
reasoning_content += delta.reasoning_content
elif hasattr(delta, "reasoning") and delta.reasoning is not None:
if not is_answering:
print(delta.reasoning, end="", flush=True)
reasoning_content += delta.reasoning
if hasattr(delta, "content") and delta.content:
if not is_answering:
print("\n" + "=" * 20 + "Answer" + "=" * 20 + "\n")
is_answering = True
print(delta.content, end="", flush=True)
answer_content += delta.content
messages.append({
"role": "assistant",
"content": answer_content,
"reasoning_content": reasoning_content,
"reasoning": reasoning_content,
})
Image Input
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/CI_Demo/mathv-1327.jpg"
}
},
{
"type": "text",
"text": "The centres of the four illustrated circles are in the corners of the square. The two big circles touch each other and also the two little circles. With which factor do you have to multiply the radii of the little circles to obtain the radius of the big circles?\nChoices:\n(A) $\\frac{2}{9}$\n(B) $\\sqrt{5}$\n(C) $0.8 \\cdot \\pi$\n(D) 2.5\n(E) $1+\\sqrt{2}$"
}
]
}
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
)
print("Chat response:", chat_response)
Video Input
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/video/N1cdUjctpG8.mp4"
}
},
{
"type": "text",
"text": "How many porcelain jars were discovered in the niches located in the primary chamber of the tomb?"
}
]
}
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
)
# When vLLM is launched with `--media-io-kwargs '{"video": {"num_frames": -1}}'`,
# video frame sampling can be configured via `extra_body` (e.g., by setting `fps`).
# This feature is currently supported only in vLLM.
#
# By default, `fps=2` and `do_sample_frames=True`.
# With `do_sample_frames=True`, you can customize the `fps` value to set your desired video sampling rate.
# chat_response = client.chat.completions.create(
# model="Qwen/Qwen3.8-27B",
# messages=messages,
# extra_body={
# "mm_processor_kwargs": {"fps": 2, "do_sample_frames": True},
# },
# )
print("Chat response:", chat_response)
Instruct (or Non-Thinking) Mode
Qwen3.8-27B will think by default before responding. You can obtain a direct response from the model without thinking by configuring the API parameters. For example,
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/RealWorld/RealWorld-04.png"
}
},
{
"type": "text",
"text": "Where is this?"
}
]
}
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
temperature=0.7,
top_p=0.8,
presence_penalty=1.5,
extra_body={
"top_k": 20,
"chat_template_kwargs": {"enable_thinking": False},
},
)
print("Chat response:", chat_response)
[!Note] If you are using APIs from Qwen Cloud, in addition to changing
model, please use"enable_thinking": Falseinstead of"chat_template_kwargs": {"enable_thinking": False}.
Disable Preserved Thinking
By default, Qwen3.8 retains thinking blocks from all historical messages, maintaining a complete reasoning trace across the conversation. This behavior, known as preserved thinking, ensures full context continuity and is especially beneficial for agent scenarios where decision consistency and reduced redundant reasoning are critical. It also improves KV cache utilization, optimizing inference efficiency in both thinking and non-thinking modes.
If you prefer to retain only the thinking blocks from the latest user message, you can disable this behavior by setting preserve_thinking to False:
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [...]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
extra_body={
"chat_template_kwargs": {"preserve_thinking": False},
},
)
print("Chat response:", chat_response)
[!Note] If you are using APIs from Qwen Cloud, in addition to changing
model, please use"preserve_thinking": Falsedirectly instead of wrapping it inchat_template_kwargs.
Best Practices
To achieve optimal performance, we recommend the following settings:
-
Sampling Parameters: We suggest using the following sets of sampling parameters:
- Thinking Mode:
temperature=1.0,top_p=0.95,top_k=20,min_p=0.0,presence_penalty=0.0,repetition_penalty=1.0 - Instruct (or non-thinking) mode:
temperature=0.7,top_p=0.80,top_k=20,min_p=0.0,presence_penalty=1.5,repetition_penalty=1.0
For supported frameworks, you can adjust the
presence_penaltyparameter between 0 and 2 to reduce endless repetition. However, using a higher value may occasionally result in language mixing and a slight decrease in model performance. - Thinking Mode:
-
Adequate Output Length: To optimize performance on agentic tasks, we recommend allocating sufficient output length to allow the model to generate detailed and comprehensive responses. For frameworks that support separate token limits for internal reasoning and final outputs, we suggest the following configuration within the 1M context length:
- Reasoning Content: Set the maximum output length to 262,144 tokens.
- Final Response: Set the maximum output length to 131,072 tokens.
These settings provide the necessary capacity for complex reasoning while ensuring ample space for high-quality final deliverables.
-
Processing Ultra-Long Texts: Qwen3.8-27B natively supports context lengths of up to 262,144 tokens. For long-horizon tasks where the total length (including both input and output) exceeds this limit, we recommend using RoPE scaling techniques to handle long texts effectively, e.g., YaRN.
YaRN is currently supported by several inference frameworks, e.g., vLLM, SGLang, and TokenSpeed. In general, there are two approaches to enabling YaRN for supported frameworks:
-
Modifying the model configuration file:
In the
config.jsonfile, change therope_parametersfields intext_configto:{ "mrope_interleaved": true, "mrope_section": [ 11, 11, 10 ], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144, } -
Passing command line arguments:
For vLLM, you can use
VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 vllm serve ... --hf-overrides '{"text_config": {"rope_parameters": {"mrope_interleaved": true, "mrope_section": [11, 11, 10], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144}}}' --max-model-len 1000000For SGLang, you can use
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python -m sglang.launch_server ... --json-model-override-args '{"text_config": {"rope_parameters": {"mrope_interleaved": true, "mrope_section": [11, 11, 10], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144}}}' --context-length 1000000For TokenSpeed, you can use
TOKENSPEED_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 tokenspeed serve ... --hf-overrides '{"text_config": {"rope_parameters": {"mrope_interleaved": true, "mrope_section": [11, 11, 10], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144}}}' --max-model-len 1000000
[!NOTE] All the notable open-source frameworks implement static YaRN, which means the scaling factor remains constant regardless of input length, potentially impacting performance on shorter texts. We advise modifying the
rope_parametersconfiguration only when processing long contexts is required. It is also recommended to modify thefactoras needed. For example, if the typical context length for your application is 524,288 tokens, it would be better to setfactoras 2.0. -
-
Long Video Understanding: To optimize inference efficiency for plain text and images, the
sizeparameter in the releasedvideo_preprocessor_config.jsonis conservatively configured. It is recommended to set thelongest_edgeparameter in the video_preprocessor_config file to 469,762,048 (corresponding to 224k video tokens) to enable higher frame-rate sampling for hour-scale videos and thereby achieve superior performance. For example,{"longest_edge": 469762048, "shortest_edge": 4096}Alternatively, override the default values via engine startup parameters. For implementation details, refer to: vLLM / SGLang.
Citation
If you find our work helpful, feel free to give us a cite.
@misc{qwen38,
title = {{Qwen3.8-Max}: A New Bar for Coding and Cowork},
url = {https://qwen.ai/blog?id=qwen3.8},
author = {{Qwen Team}},
month = {August},
year = {2026}
}