Background: AI slop
Current LLMs write fluent imitations of good prose that match the surface but not the craft: tweets
that read like a brand account, essays that resolve into generic motivational endings, "mini-paper"
abstracts that over-cover and dump numbers. Standard pairwise and single-score LLM judges fail to catch
this — they often prefer model writing to real expert writing. Following FAIR's unslop work, the fix is
not a better absolute judge but rubrics that separate expert from model writing, used as an RL reward.
Method: calibrated expert-rubric reward + GRPO
Our take on RL-XAR, on a text-only prose slice:
- Rubrics. For each expert excerpt (tweets from the Broad Twitter Corpus, scientific abstracts from
arXiv, blog essays from PG / Sivers / sama), a frozen per-item rubric is generated and kept fixed for
the whole run — no rubric drift during RL.
- Length-blind judge. A calibrated Claude Opus judge scores a candidate against its rubric on a
0–10 quality scale
q, with a length-blind system prompt so it rewards craft, not verbosity.
- Calibrated reward.
reward = L(words, target) · σ(a_d · (q − μ_d)), where L is a length factor
against the item's target length and (μ_d, a_d) are a per-domain calibration fit on the
Qwen3.8-27B reference distribution. This keeps the signal about quality, not length.
- RL. GRPO on
Qwen/Qwen3.8-27B via verl, batch 128 (16 prompts × 8 samples), 100 steps,
lr 2e-5, kl_loss_coef 0.002, thinking disabled. Generation is served by vLLM colocated with FSDP.
Over 100 steps the mean reward rose ~0.35 → 0.55 while entropy settled from 1.5 to ~0.43 (convergence on
a consistent voice, not a single degenerate pattern — see examples).
Results
Held-out prose, graded by the same calibrated length-blind Opus judge on the same frozen rubrics. We
compare the base model, this model (antislop), and Altworld/Hemmingway-1 (a creative-writing
finetune of the same base).
Table with columns: model, mean q (0–10) ↑, tweets, articles, blogs| model | mean q (0–10) ↑ | tweets | articles | blogs |
|---|
| base Qwen3.8-27B | 6.31 | 7.18 | 5.75 | 5.53 |
| Qwen3.8-27B-antislop | 8.28 | 8.76 | 6.94 | 8.03 |
| Hemmingway-1 | 7.10 | 7.66 | 7.06 | 6.56 |
Pairwise win-rate (per-item, higher q):
- antislop vs base: 50–0 (2 ties)
- antislop vs Hemmingway-1: 43–6 (3 ties) → 82.7%
EQ-Bench 4 (independent check)
We ran EQ-Bench 4 with the exact canonical leaderboard
configuration from the official repo — persona model google/gemini-3.1-pro-preview; pairwise judge
panel gemini-3.1-pro-preview, gpt-5.5, claude-opus-4-6; pointwise judge claude-opus-4-8; the bundled
120 personas (16-message chats) and the fixed anchor set — then folded this model into that anchor Elo
table via the official pairwise-vs-anchors re-aggregation (--redo-elo: 366 fresh pairwise comparisons
against the 28 anchors, 11 056 total). No judge, persona or anchor was swapped, so the Elo below is on the
same scale as the official leaderboard.
Headline Elo: 1320.1 (95% CI 1309–1332) — rank 4 of 29. The 27B antislop model places above
GPT-5.5, Claude Opus 4.7, Claude Opus 4.8, GPT-5.4, Claude Sonnet 5 and the rest of the field; only
Claude Opus 5 (1383), Kimi K3 (1335) and Claude Fable 5 (1331) rank higher.
Table with columns: rank, model, Elo (95% CI)| rank | model | Elo (95% CI) |
|---|
| 1 | claude-opus-5 | 1382.9 (1366–1401) |
| 2 | moonshotai/kimi-k3 | 1334.6 (1321–1349) |
| 3 | claude-fable-5 | 1330.9 (1320–1342) |
| 4 | Qwen3.8-27B-antislop (this model) | 1320.1 (1309–1332) |
| 5 | openai/gpt-5.5 | 1314.4 (1304–1323) |
| 6 |
This is a prose-RL model, not a chat/EQ finetune — the ranking reflects that the calibrated-rubric reward
pushes toward natural, non-sloppy writing that the EQ-Bench panel also rewards in open-ended conversation.
The pointwise judge's behavioural-trait profile for this model (0–10, mean over 90 scored
conversations):
Table with columns: trait, score, trait, score| trait | score | trait | score |
|---|
| native_frame_adaptation | 8.19 | directive_advice_orientation | 5.89 |
| analytical | 6.56 | interpretive_boldness | 5.04 |
| naturalness_authenticity | 6.54 | challenge_propensity | 3.40 |
| frame_capture | 6.42 | boundary_setting | 3.07 |
These are descriptive traits, not a single quality score; the headline is the Elo above. Full transcripts
and all judge outputs (366 pairwise comparisons, per-persona results, the 29-model Elo table) are archived
in the run repo under pod/results/eqbench4/.
Examples — baseline vs antislop
Freshly generated from this model vs the base, same prompt, same decoding (enable_thinking=False,
temp 0.8). The baseline reaches for abstract, generic phrasing and tidy clichés; the antislop model stays
concrete and in-voice.
Continue an essay — "The problem with productivity advice is that it treats attention as a resource
to be spent, when really"
base: …it's more like a weather pattern. You don't "manage" the rain… Stop trying to hoard every
minute like it's gold. The quiet gaps aren't waste; they're where the actual thinking happens.
antislop: …it's more like a mood. You just end up staring at it for forty minutes because the cursor
is blinking and you're too tired to close the tab. You're not optimizing, you're just hovering over the
document like a ghost who forgot to leave the building.
Continue a product memo — "We looked at why users churn in week one, and the honest answer is"
base: …they can't find value fast enough. The onboarding flow is too long… If we don't make the
first ten seconds count, they'll leave before they even understand what the product does.
antislop: …they don't know what to do next. The dashboard is empty, the onboarding tooltip
disappears after three seconds, and there's no clear button saying "invite your team". They close the
tab, assume it's broken, and never come back.
Finish a casual tweet — prefix "first coffee of the day and"
base: first coffee of the day and i'm finally functional. save me, caffeine.
antislop: first coffee of the day and i already know i'm not functioning before 10am
What's in this repo
Table with columns: path, what, notes| path | what | notes |
|---|
./ (root) | full bf16 model | base Qwen3_5ForConditionalGeneration with vision tower + MTP head intact; GRPO-updated LLM. 1199 tensors. |
mxfp4-a16/ | MXFP4 weight-only quant | OCP microscaling FP4 (group 32, E8M0), text-only, for compact inference. Real 4-bit speed needs Blackwell (B200). |
The GRPO weight updates were written directly into the base safetensors (no transformers load/save), so
the vision tower and MTP head survive byte-exact. The result was verified against the training-time
reference on a held-out prompt: 48/48 greedy tokens identical, max |Δlogit| 0.875, no NaN.
Usage
from transformers import AutoModelForCausalLM, AutoTokenizertok = AutoTokenizer.from_pretrained("rawmodels/Qwen3.8-27B-antislop")model = AutoModelForCausalLM.from_pretrained("rawmodels/Qwen3.8-27B-antislop", dtype="bfloat16", device_map="auto", trust_remote_code=True)msgs = [{"role": "user", "content": "Finish this tweet naturally: Monday mornings are"}]text = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True, enable_thinking=False)ids = tok(text, return_tensors="pt").to(model.device)print(tok.decode(model.generate(**ids, max_new_tokens=64, do_sample=True, temperature=0.8)[0][ids.input_ids.shape[1]:]))
Training details & versions
Table | |
|---|
| base model | Qwen/Qwen3.8-27B @ 1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0 |
| RL algo | GRPO (verl @ 76e837e) |
| steps / batch | 100 / 128 (16×8) |
| lr / kl_loss_coef | 2e-5 / 0.002 |
| reward judge | Claude Opus (length-blind, frozen per-item rubrics) |
| domains | tweets, scientific abstracts, blog essays (EN) |
| hardware | 2× H200 (SECURE) |
Code: AlexWortega/capability-vectors, branch claude/astra4-calibrated-grpo (commit a91d24a),
under sep/antislop_grpo/verl_prose/. A copy of the training/eval scripts is in training_code/ here.
Acknowledgements & citation
This is an independent reimplementation of Meta FAIR's RL-XAR / unslop idea on a different base model and a
different judge/calibration stack. Please cite the original work:
@misc{fair_unslop, title = {Unslop: RL from eXpert Aligned Rubrics (RL-XAR)}, author = {Meta FAIR}, url = {https://facebookresearch.github.io/RAM/blogs/unslop/}, note = {Research blog}}
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 via preserve_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
Benchmark Results
Text 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\n before 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.0
Please 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 analysis
medium: balancing accuracy and speed
low: 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 accordinglyexport OPENAI_BASE_URL='your-base-url'export OPENAI_API_KEY='your-api-key'
Text-Only Input
from openai import OpenAI# Configured by environment variablesclient = 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 = Falseprint("\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,})
from openai import OpenAI# Configured by environment variablesclient = 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)
from openai import OpenAI# Configured by environment variablesclient = 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 variablesclient = 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": False instead 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 variablesclient = 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": False directly instead of wrapping it in chat_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 parameter 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.
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}}