Qwen3-32B
| Tier | Input | Output | Cached input |
|---|---|---|---|
PriorityLearn more | 43.2 | 151.2 | — |
FlexLearn more | 23.1 | 80.7 | — |
Qwen3-32B is the largest dense model in its generation, and the deliberate counterpart to a sparse sibling of almost identical total size. Where that model activates three billion parameters per token, this one activates all 32.8 billion — every layer, every weight, every time. Sixty-four layers with sixty-four query heads against eight key-value heads, and the same two-mode design as the rest of the family: reasoning and direct answering, switchable by writing a tag into the conversation. Tool calling is documented on both sides, which makes a two-speed agent a real option rather than a compromise.

Qwen3-32B
The largest dense model in its generation — and the deliberate opposite of its sparse sibling.
Dense, and Why That Is the Choice
Qwen3 shipped both architectures at almost the same size, which makes this the clearest comparison available between them.
| Qwen3-32B | Qwen3-30B-A3B | |
|---|---|---|
| Total parameters | 32.8B | 30.5B |
| Active per token | 32.8B | 3.3B |
| Layers | 64 | 48 |
| Query heads | 64 | 32 |
| KV heads | 8 | 4 |
| Experts | — | 128, 8 active |
Nearly the same size on disk. Ten times the compute per token.
What dense means in practice. Every parameter participates in every token. No router deciding which experts see your input, no possibility that a token is sent to a specialist that handles it poorly, no variance in which part of the model answered.
What sparse buys instead is throughput — 3.3 billion parameters of work per token means far more requests per second on the same hardware.
Neither is better. They are different points on a curve, and the choice is workload-shaped:
Choose dense when per-request quality matters more than per-request cost, when consistency across inputs is the requirement, or when you want the model's full capacity applied to every token.
Choose sparse when volume is the constraint — classification, routing, extraction at scale, or an agent making hundreds of cheap calls.
And the layer count is the other half of the comparison. Sixty-four layers against forty-eight. Deeper as well as denser, which is where sequential reasoning lives.
Two Modes, One Model
The Qwen3 design, and it is the same at every size in the generation.
Soft switches written into the conversation:
/no_think
Which department owns this ticket?/think
Prove whether this retry schedule can starve a single tenant under sustained load.They work in a user prompt or in a system message — which matters, because placing them in the system message makes the mode a property of your application rather than something a user can change.
enable_thinking works as a parameter too, for when your code should decide.
Two cautions. Soft switches are text the model reads, so input sanitisation that rewrites user messages can strip them silently. And a switch in a user turn is visible to the user.
Tool Calling in Both Modes
Stated on the card, and uncommon:
precise integration with external tools in both thinking and unthinking modes
Most switchable models degrade tool use on the fast path. Reasoning is where a model works out which tool to call and with what arguments; remove it and the calls get sloppier.
Here both are documented capabilities, which makes a two-speed agent a design rather than a compromise — mechanical steps at full speed and full tool reliability, with reasoning invoked only for the step that needs a decision.
Architecture
| Total parameters | 32.8B |
| Non-embedding | 31.2B |
| Layers | 64 |
| Query heads | 64 |
| Key-value heads | 8 |
| Native context | 32,768 |
| Extended context | 131,072 with YaRN |
| Languages | 100+ |
Sixty-four query heads against eight key-value heads — an 8:1 grouped-query ratio, cutting the key-value cache to an eighth of what full multi-head attention would need.
On a dense 64-layer model that ratio carries more weight than on a sparse one, because every layer builds a cache. Eight-to-one is what keeps a 32,768-token context affordable on a model where nothing is skipped.
32K Is Native. 128K Is Extension.
32,768 tokens is what the model was trained at.
131,072 comes from YaRN, applied at inference — a real capability, and a different thing from training at that length.
And static YaRN, which most serving frameworks implement, holds the scaling factor constant regardless of input length. Enabling it affects short prompts too.
The rule that follows: leave the extension off unless you actually serve long inputs. Turning it on permanently to handle occasional long documents degrades every short request in between.
Specifications
| Model ID | Qwen/Qwen3-32B |
| Type | Causal language model, dense |
| Parameters | 32.8B (31.2B non-embedding) |
| Layers | 64 |
| Attention | GQA — 64 Q heads, 8 KV heads |
| Native context | 32,768 tokens |
| Extended context | 131,072 with YaRN |
| Modes | Thinking, non-thinking |
| Mode control | enable_thinking, or /think · /no_think in a message |
| Languages | 100+ |
| Licence | Apache 2.0 |
| Minimum transformers | 4.51.0 |
| Developer | Qwen Team, Alibaba |
Transformers below 4.51.0 raises KeyError: 'qwen3'.
Official builds cover the standard weights, FP8, and GGUF at q4_K_M, q5_0, q5_K_M, q6_K, and q8_0 — published by Qwen rather than converted by the community. AWQ and NVFP4 builds exist alongside.
Capabilities
| Capability | Value |
|---|---|
input_types | text |
output_types | text |
image_input | Not supported |
context_window | 40960 |
reasoning | Two modes — switchable |
mode_switch | Parameter or in-prompt soft switch |
streaming | Supported |
tool_calling | Supported in both modes |
structured_output | Supported |
requires_prompt | Yes — text prompt required |
Recommended Sampling
From Qwen's reference command, and the values differ by mode.
| Parameter | Thinking | Non-thinking |
|---|---|---|
temperature | 0.6 | 0.7 |
top_p | 0.95 | 0.80 |
top_k | 20 | 20 |
min_p | 0 | 0 |
presence_penalty | 1.5 | 1.5 |
Switching mode means switching sampling. Temperature and top-p both change, and leaving them at the other mode's values costs quality in a way that is hard to trace back to configuration.
The presence penalty at 1.5 is high, and it appears in Qwen's own command. On a reasoning model repetition inside a long trace is a real failure mode, and that value exists to suppress it.
Support varies by serving stack — top_k, min_p, and presence_penalty are not universally
honoured through an OpenAI-compatible interface.
What the Reference Command Says About Budgets
Qwen's llama.cpp invocation is worth reading as advice rather than as a snippet:
-c 40960 -n 32768 --no-context-shiftA 40,960-token context with 32,768 available for generation — four fifths of the window reserved for output.
On a model whose native context is 32,768, that allocation says what a thinking model costs. The reasoning trace can consume the great majority of what you allocate.
Copy the proportion. A thinking-mode request needs most of its budget available for output; a budget sized for the answer produces a trace and nothing else.
--no-context-shift is the other half. Silently dropping old tokens to make room is worse than
failing, because the model keeps answering from a history that quietly lost its beginning.
Using Qwen3-32B on DEVUP AI
Base URL: https://api.devupai.com/v1 · Model ID: Qwen/Qwen3-32B
Python
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEVUP_API_KEY"],
base_url="https://api.devupai.com/v1",
)
response = client.chat.completions.create(
model="Qwen/Qwen3-32B",
messages=[
{"role": "user", "content": "Hello world!"}
],
max_tokens=1024,
)
print(response.choices[0].message.content)Node.js
import DevupAI from "devupai";
const client = new DevupAI({
apiKey: process.env.DEVUP_API_KEY,
});
async function main() {
const response = await client.chat.completions.create({
model: "Qwen/Qwen3-32B",
messages: [{ role: "user", content: "Hello world!" }],
max_tokens: 1024,
});
console.log(response.choices[0].message.content);
}
main();cURL
curl -X POST "https://api.devupai.com/v1/chat/completions" \
-H "Authorization: Bearer $DEVUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-32B",
"messages": [
{ "role": "user", "content": "Hello world!" }
],
"max_tokens": 1024
}'Switching Modes, With the Sampling
conversation = []
SETTINGS = {
True: {"temperature": 0.6, "top_p": 0.95, "max_tokens": 16384},
False: {"temperature": 0.7, "top_p": 0.80, "max_tokens": 1024},
}
def ask(text: str, *, think: bool) -> str:
"""Send one turn at the requested mode, switching sampling and budget with it."""
marker = "/think" if think else "/no_think"
conversation.append({"role": "user", "content": f"{marker}\n\n{text}"})
response = client.chat.completions.create(
model="Qwen/Qwen3-32B",
messages=conversation,
extra_body={"top_k": 20, "min_p": 0, "presence_penalty": 1.5},
**SETTINGS[think],
)
choice = response.choices[0]
if choice.finish_reason == "length":
trace = getattr(choice.message, "reasoning_content", "") or ""
raise ValueError(
f"hit the ceiling at {response.usage.completion_tokens:,} tokens "
f"with {len(trace):,} characters of reasoning"
)
conversation.append(choice.message)
return choice.message.content
ask("List the tables in this schema.", think=False)
ask("Which of them could produce a duplicate row under concurrent inserts, and why?", think=True)
ask("Give me the CREATE INDEX statement for the fix.", think=False)The SETTINGS table is the part worth copying. Mode, sampling, and budget change together — one
lookup rather than four parameters you might update inconsistently.
The finish_reason check earns its place on a 32,768-token native window. Reasoning shares the
budget, and the window is modest by current standards.
Comparing Dense Against Sparse On Your Own Work
The experiment that settles the choice, using the two models in the same generation.
import time
DENSE = "Qwen/Qwen3-32B"
SPARSE = "Qwen/Qwen3-30B-A3B"
def measure(model: str, prompt: str, *, think: bool = False) -> tuple[str, float, int]:
"""Return the answer, wall-clock seconds, and completion tokens."""
marker = "/think" if think else "/no_think"
start = time.monotonic()
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": f"{marker}\n\n{prompt}"}],
temperature=0.6 if think else 0.7,
top_p=0.95 if think else 0.80,
max_tokens=16384 if think else 2048,
)
elapsed = time.monotonic() - start
return response.choices[0].message.content, elapsed, response.usage.completion_tokens
for model in (DENSE, SPARSE):
answer, seconds, tokens = measure(model, your_prompt)
print(f"{model:<24} {seconds:>6.2f}s {tokens:>6,} tokens correct={check(answer)}")Run it across twenty real prompts, not one. The dense model applies ten times the compute per token; whether that shows on your workload is an empirical question with a cheap answer.
Compare correctness first, then latency. If both are correct on most of your prompts, the sparse model is the better choice and the comparison saved you real money. If the dense model is correct where the sparse one is not, you now know where — and whether those cases matter.
A Two-Speed Agent
import json
TOOLS = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "Read a file relative to the repository root.",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
},
},
{
"type": "function",
"function": {
"name": "run_tests",
"description": "Run the test suite and return pass/fail counts with failure output.",
"parameters": {"type": "object", "properties": {}},
},
},
]
def read_file(path: str) -> dict:
"""Replace with your real, sandboxed file access."""
raise NotImplementedError
def run_tests() -> dict:
"""Replace with your real, sandboxed test runner."""
raise NotImplementedError
HANDLERS = {"read_file": read_file, "run_tests": run_tests}
session = [
{
"role": "system",
"content": (
"/no_think\n\n"
"You are working inside a git repository. Make the smallest change that fixes the "
"problem and run the tests after each edit. When a failure is not obviously explained "
"by your last change, say so and stop."
),
},
{"role": "user", "content": "The DZD invoice test fails on totals ending in .005. Fix it."},
]
CEILING = 30
for step in range(CEILING):
response = client.chat.completions.create(
model="Qwen/Qwen3-32B",
messages=session,
tools=TOOLS,
temperature=0.7,
top_p=0.80,
max_tokens=4096,
)
message = response.choices[0].message
session.append(message)
if not message.tool_calls:
print(message.content)
break
for call in message.tool_calls:
handler = HANDLERS.get(call.function.name)
if handler is None:
outcome = {"error": "unknown tool", "name": call.function.name}
else:
try:
outcome = handler(**json.loads(call.function.arguments or "{}"))
except Exception as exc:
outcome = {"error": type(exc).__name__, "detail": str(exc)}
session.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(outcome)})
else:
print(f"Stopped at the {CEILING}-step ceiling.")The switch is in the system message, which makes non-thinking a property of the loop rather than something a tool result could accidentally change.
"Say so and stop" is the escape hatch. On a fast-path model, handing an unclear failure to a person beats guessing at it — and it is cheaper than switching the whole loop to thinking mode for one confusing step.
To escalate selectively, append a /think user turn when a step fails twice and let the model
reason through that one before continuing.
Self-Hosting
Transformers 4.51.0 minimum, or the model class is not found.
Official formats: standard weights, FP8, and GGUF at five quantisations — from Qwen rather than the community, which is uncommon at this size.
A DFlash speculative decoding draft model is published for the FP8 build: five draft layers, 3.2 billion parameters, taking hidden states from five target layers and predicting a block of sixteen tokens in parallel. On a dense 32-billion-parameter model — where every token costs full compute — that acceleration matters more than it would on a sparse one.
Qwen-Agent is the recommended agent framework, and the reason is practical: it encapsulates tool-calling templates and parsers internally, removing the class of silent failure where a parser mismatch turns tool calls into prose.
Set --no-context-shift or its equivalent so truncation fails loudly.
Where It Fits
Quality-sensitive work at moderate volume, where full compute per token is worth its cost.
Consistency-critical applications, where every input gets the same model rather than whichever experts a router selected.
Two-speed agents, with tool calling documented on both sides.
Creative and conversational work — role-play, multi-turn dialogue, and human preference alignment are named strengths of this generation.
Multilingual work across 100+ languages, with translation called out.
Self-hosted deployment with official builds across three formats and a published speculative decoding draft.
Less suited to high-volume mechanical work, where the sparse sibling does the same job for a fraction of the compute — and to long-document processing beyond 32K without measuring the extension.
Practical Notes
Compare it against the sparse sibling on your own prompts before committing. The comparison is cheap and the difference in cost is not.
Change sampling when you change mode.
Reserve most of your budget for output in thinking mode.
Put soft switches in the system message when the mode is your decision rather than the user's.
Verify soft switches survive input sanitisation.
Leave YaRN off unless you serve long inputs.
Check finish_reason on thinking-mode requests — 32,768 native is tight.
If self-hosting, pair the FP8 build with the published DFlash draft.
Disable context shifting so truncation fails loudly.
Limitations
Native context is 32,768. The 131,072 figure comes from positional extension, and static YaRN degrades short prompts when left enabled.
Dense means full compute on every token. That is the design, and it is the reason this model costs more per request than its sparse sibling of nearly identical size.
Text only. No image, audio, or video input.
Soft switches are prompt text — vulnerable to input rewriting, and visible to the user in a user turn.
Thinking mode consumes output tokens against a window that is modest by current standards.
Sampling parameter support varies by serving stack.
Transformers 4.51.0 or later is required for self-hosting.
Thirty-two billion parameters. The largest dense model in this generation, and smaller than the sparse flagships that sit above it.
Reasoning traces are working notes. Unpolished, sometimes exploring abandoned branches, and occasionally contradicting the answer that follows.