Improved Chat Template for Qwen 3.x
An advanced, production-hardened Jinja2 Chat Template engineered specifically for Qwen 2.5, Qwen 3.x, QwQ, and Hybrid Reasoning / Tool-Calling LLMs.
This template delivers a resilient, unified prompt engine that seamlessly integrates multi-tier Chain-of-Thought (CoT) reasoning, dual-format agentic tool execution, automatic error-recovery heuristics, and strict token-waste elimination.
🏛️ Lineage & Acknowledgments
This template is a synthesis and evolution built directly upon architectural breakthroughs and design patterns from four foundational templates in the open-source community:
- Jackrong/Qwen-Tool-Calling-Template-Fix:
- Contributed the core foundation for multi-system message head aggregation, inline control token stripping, multi-turn synthetic agent loop index recovery, and the consecutive tool error classification warning loop.
- peculiar-ragdoll/Qwen-Sharp-Chat-Templates:
- Contributed dynamic thinking-aware tool prompt adapting (preventing tool prompt
<think>instructions when reasoning is disabled), optional conciseness (terse) system prompt controls, and broadmessage.reasoning/message.thinkingfield extraction.
- Contributed dynamic thinking-aware tool prompt adapting (preventing tool prompt
- Kwaipilot/KAT-Coder-V2.5-Dev:
- Contributed robust multimodal vision pad counting macros (
<|vision_start|><|image_pad|><|vision_end|>), vision parameter indexing, and clean function call parameter serialization.
- Contributed robust multimodal vision pad counting macros (
- ornith-ai/Ornith-1.5-35B-A3B:
- Contributed baseline XML parameter structuring mechanisms, strict role separation checks, and early prompt validation concepts.
⚡ Key Improvements & Innovations in v22.5.1
- 🧠 Granular Reasoning Effort & Dynamic Think Control: Control thinking depth on-the-fly via API kwargs (
reasoning_effort="low"|"medium"|"xhigh"|"ultracode"|"extreme"|"deep"|"long") or inline prompt triggers (<|think_off|>,<|think_xhigh|>,<|think_deep|>). - 🛠️ Dual-Mode Agentic Tool Calling: Seamlessly toggle between native Qwen XML format (
<tool_call><function=...></tool_call>) and OpenAI-compatible JSON format ({"name": ...}) without prompt drift. - 🛡️ Self-Healing Tool Heuristics: Automatically detects tool execution failures (non-zero exit codes, Python tracebacks, HTTP 404/500, Rate Limits, connection drops) and injects progressive diagnostic warnings (
⚠️ SYSTEM WARNING) into subsequent model turns. - 🧹 Zero Ghost-Think Bloat: Historical turns without reasoning do not output empty
<think></think>blocks into context, preserving precious KV cache space. - 🔒 Crash-Proof Multi-Turn Text Preservation: Safe multi-split logic prevents text drops when assistants write markdown or code blocks containing
</think>tags. - 🌐 API Gateway & Proxy Resilient: Built-in normalization for string-booleans (
"false",'0') and safe integer casting to prevent Python runtimeTypeErrorcrashes in FastAPI, vLLM, LiteLLM, and OpenRouter environments.
📊 Feature Comparison Matrix
| Feature | Stock Qwen Template | Strict Terse Templates | Jack Template (v22.5.1) |
|---|---|---|---|
| **Inline Think Toggles (`< | think_* | >`)** | ❌ No |
| History Reasoning Sanitization | ❌ Injects Empty Tags | ⚠️ Inconsistent | ✅ Smart (No Ghost Tags) |
| Consecutive Tool Error Warning Loop | ❌ No | ❌ No | ✅ Dynamic 2-Stage Warning |
| Dual Tool Modes (XML & JSON) | ⚠️ XML only | ⚠️ Inflexible | ✅ XML + JSON Adaptive |
| String-Boolean & API Type Safety | ❌ Crashes on "false" |
❌ Crashes | ✅ Fully Normalized |
Reasoning Preservation (reasoning_content) |
⚠️ Flaky | ⚠️ Drops dicts | ✅ Strings & Dicts Supported |
| Unconstrained Deep Reasoning by Default | ✅ Yes | ❌ Forced terseness | ✅ Full Performance Preserved |
⚙️ Configurable Template Parameters (chat_template_kwargs)
All parameters are optional and can be supplied via chat_template_kwargs or API request bodies:
| Parameter | Type | Default | Description |
|---|---|---|---|
enable_thinking |
bool / str |
true |
Enables or disables the <think> reasoning block. Accepts true, false, "true", "false", 1, 0. |
reasoning_effort |
str |
"medium" |
Sets reasoning intensity: 'none', 'low', 'minimal', 'medium', 'high', 'xhigh', 'ultracode', 'extreme', 'deep', 'long'. |
tool_call_format |
str |
'xml' |
Chooses between 'xml' (Qwen native <function=...>) and 'json' ({"name": ...}). |
auto_disable_thinking_with_tools |
bool / str |
false |
Automatically disables reasoning during tool-calling turns for low-latency agent routing. |
max_tool_arg_chars |
int / str |
0 (disabled) |
Truncates tool argument strings longer than $N$ characters to prevent memory/context overflows. |
max_tool_response_chars |
int / str |
0 (disabled) |
Truncates tool execution outputs longer than $N$ characters before injection into context. |
preserve_reasoning |
bool / str |
true |
Preserves historical thinking blocks across multi-turn chats. Set false to drop past reasoning while retaining current turn reasoning. |
add_vision_id |
bool / str |
false |
Prepends human-readable labels (Picture 1: , Video 1: ) before multimodal vision pads. |
terse |
bool / str |
false |
Enables strict conciseness prompt rules. Kept false by default to avoid harming deep CoT reasoning. |
🎯 Inline Reasoning Control Tokens
You can dynamically adjust reasoning on a per-turn basis by including any of the following tags anywhere inside user or system messages:
- Disable Thinking:
<|think_off|> - Enable Standard Thinking:
<|think_on|>,<|think_medium|> - Low / Fast Thinking:
<|think_low|>,<|think_minimal|> - Deep / Ultracode Thinking:
<|think_high|>,<|think_xhigh|>,<|think_max|>,<|think_ultracode|>,<|think_extreme|>,<|think_deep|>,<|think_long|>
Note: The template automatically strips these control tokens during rendering, preventing token leakage into the final context.
🚀 Deployment & Integration
1. Hugging Face Transformers (Python)
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-72B-Instruct")
# Load template from file
with open("chat_template.jinja", "r") as f:
tokenizer.chat_template = f.read()
messages = [
{"role": "system", "content": "You are an expert systems programmer."},
{"role": "user", "content": "<|think_xhigh|> Implement a lock-free ring buffer in C++."}
]
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
chat_template_kwargs={
"enable_thinking": True,
"reasoning_effort": "xhigh"
}
)
print(prompt)
2. vLLM Server Launch
Pass the template directly to the vLLM OpenAI-compatible server:
vllm serve Qwen/Qwen2.5-32B-Instruct \
--chat-template ./chat_template.jinja \
--enable-auto-tool-choice \
--tool-call-parser hermes
3. SGLang Server Launch
python3 -m sglang.launch_server \
--model-path Qwen/Qwen2.5-32B-Instruct \
--chat-template ./chat_template.jinja \
--port 30000
4. LiteLLM / Proxy Configuration
model_list:
- model_name: qwen-jack
litellm_params:
model: vllm/Qwen/Qwen2.5-72B-Instruct
api_base: http://localhost:8000/v1
chat_template: ./chat_template.jinja
📄 License
This project is licensed under the Apache License 2.0. You are free to use, modify, distribute, and integrate it into commercial and open-source systems.
- Downloads last month
- -