Downloads · 30 days
0
nrrso/Qwen3-Chat-Template-vLLM-Fixes
Qwen3-Chat-Template-vLLM-Fixes is a machine learning model from nrrso. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as apache-2.0.
Drop-in Jinja chat templates for Qwen 3.8 (Qwen/Qwen3.8-27B and quantized variants like unsloth/Qwen3.8-27B-NVFP4). The goal is reliable agentic tool calling on vLLM without drifting away from the format the model was…
Downloads · 30 days
0
Access
Public
Updated Aug 15, 2026
Repo size
—
Likes
4
Public
Click a slice to open those files.
.jinja34 KB · 76%
From the Hugging Face model README
Drop-in Jinja chat templates for Qwen 3.8 (Qwen/Qwen3.8-27B and quantized variants like unsloth/Qwen3.8-27B-NVFP4). The goal is reliable agentic tool calling on vLLM without drifting away from the format the model was trained on.
Most "fixed" templates repair one thing and quietly break another by rewording instructions the model has already internalized. This repo takes a more conservative approach: keep the official template as the skeleton, patch the real bugs, and skip the clever rewrites.
There are two templates:
| File | Use it when |
|---|---|
qwen3.8-enhanced.jinja | The recommended baseline. Official Qwen 3.8 template plus tool-calling and history-rendering fixes. |
qwen3.8-enhanced-extra.jinja | Everything in the baseline, plus extra tolerance for messy client-side history (malformed think tags, alternate field names). Renders byte-identical prompts for well-formed conversations. |
⚠️ vLLM only. These templates rely on the
from_jsonfilter, which vLLM provides but plain Jinja2 and minijinja (llama.cpp, LM Studio, MLX) don't. If you need something engine-agnostic, use froggeric/Qwen-Fixed-Chat-Templates instead.
vllm serve unsloth/Qwen3.8-27B-NVFP4 \
--chat-template qwen3.8-enhanced.jinja \
--enable-auto-tool-choice \
--tool-call-parser qwen3_xml \
--reasoning-parser qwen3
Notes on the flags:
--tool-call-parser qwen3_xml matches the XML format these templates emit (<tool_call> → <function=name> → <parameter=x>). Stuck on an older vLLM build? Fall back to qwen3_coder.--reasoning-parser qwen3 is required. The generation prompt pre-fills <think>\n, so the model's output starts mid-thought with no opening tag. This parser handles that case and splits reasoning_content from content, which is also what the template needs fed back to it on later turns.qwen3_xml leans on your tool JSON schemas for type coercion, so keep those parameters schemas honest. Loose schemas mean arguments come back as strings.qwen3.6-enhanced.jinja)tool_call.arguments is a mapping and dies with Can only get item pairs from a mapping when an OpenAI-style client echoes back stringified arguments, which most of them do. JSON strings are parsed here into proper <parameter> blocks, nested objects included, so multi-turn history always re-renders in the trained format.</think> closure. If echoed history contains a dangling <think> before a <tool_call>, the closing tag gets inserted where it belongs. Tool calls never end up trapped inside reasoning.<think>...</think> extraction. Some clients stuff reasoning into message.content instead of reasoning_content. Rather than double-wrapping it, the template pulls it out and re-renders it canonically.tojson(ensure_ascii=False) for tool definitions and argument values, so CJK text stays readable instead of turning into \uXXXX escapes.<IMPORTANT> block rather than replacing it: close </think> before tool calls, prefer tools over answering from memory, reuse ids with update_* tools, keep user-provided strings verbatim, write valid JSON for object and array parameters. There's a worked follow-up-update example too.developer role support. Leading system and developer messages are accepted and merged into a single system block. Harnesses like Codex won't work without this.reasoning_effort: "high" aliased to xhigh instead of throwing. OpenAI proxies routinely send "high".reasoning_effort steering (xhigh default, medium, low) with the official instruction wording, word for word.preserve_thinking defaults to true. Qwen 3.8 was trained with retained reasoning context; stripping it by default would fight the model.</tool_response><|im_end|> spacing and scalar argument rendering (true, null, 5 via tojson; strings verbatim).<think> blocks, even when reasoning is empty. That's the trained format, empty or not.-extra variant addsRobustness ideas adapted from froggeric/Qwen-Fixed-Chat-Templates:
<thinking>...</thinking>, </ think>, </think >, content that starts with </think>, and bare reasoning followed by </think>. These are the artifacts you get when a client echoes raw output from the prefilled <think>\n generation prompt. Every variant gets normalized back to a clean <think>...</think> on re-render.message.thinking accepted as an alias of message.reasoning_content. A handful of clients use it; reasoning_content still wins when both are present.preserve_reasoning accepted as an alias of preserve_thinking, matching llama.cpp's --reasoning-preserve naming. Takes precedence if both are passed.All three only touch the history re-render path, so both templates produce byte-identical prompts for well-formed conversations. A/B them freely; a difference only shows up when a client sends messy history.
Froggeric's template has more features than this one, and leaving them out was a deliberate trade-off. The guiding principle here is to stay on the model's training distribution, so the following features were skipped:
error: 0 trips it) and puts the whole conversation off-distribution.max_tool_arg_chars / max_tool_response_chars). History truncation belongs in the client, where it can happen without silently corrupting replayed turns.<function> blocks teaches the model to imitate malformed history. These templates parse instead.<think> blocks. The official format always emits the wrapper for preserved turns, so these templates do too.tool_call_format="json". Qwen 3.8 is trained on the XML format. Use qwen3_xml.Pass via chat_template_kwargs (vLLM) or apply_chat_template(...):
| Kwarg | Default | Description |
|---|---|---|
enable_thinking | true | false pre-fills <think>\n\n</think>\n\n to skip reasoning. |
reasoning_effort | "xhigh" | "xhigh", "medium", "low"; "high" is aliased to "xhigh". Injects the official steering instruction into the system block. |
preserve_thinking | true | false strips <think> blocks from assistant turns before the last real user query (saves tokens, breaks prefix-cache continuity for those turns). |
preserve_reasoning | n/a | (extra only) Alias of preserve_thinking; takes precedence if both are set. |
add_vision_id | false | Prefixes Picture N: / Video N: labels to vision inputs. |
| Role | Author |
|---|---|
| Qwen 3.8 models & official template | Alibaba Cloud (Qwen team) |
| Original enhanced-template lineage (3.5/3.6) | allanchan339 |
| Developer-role / effort-alias / tool-name fixes | Unsloth |
Robustness ideas adapted in the -extra variant | froggeric |
| Merge, testing & maintenance | nrrso |
Apache-2.0, inherited from Qwen.