今天聊一個每個本地部署 Qwen 的人遲早會踩的坑 —— 聊天模板
事情是這樣的,最近想用 Qwen3.6 跑點 Agent 任務,結果一上手就翻車:在 LM Studio 里偶爾工具調用剛發出去模型就 <|im_end|> 提前收攤,換到 llama.cpp 上 loop.previtem 直接報解析錯誤,搬到 vLLM 上想跑 Codex 工具發個 developer role 又被官方模板嫌棄……一通操作下來感覺自己不是在用模型,是在調試一個 Jinja 模板
后來才知道,這些不是我用錯了,全是 Qwen 官方 jinja chat template 的鍋
HuggingFace 上有個叫 froggeric 的老哥實在看不下去,干脆自己 fork 了官方模板,專門治這些病
![]()
項目名簡單粗暴:Qwen-Fixed-Chat-Templates,目前已經迭代到 v19,專為 Qwen 3.5 和 Qwen 3.6 全系列(27B / 32B / 35B 都包)打造
簡介
一句話講清楚:這是一個 drop-in 直接替換 的 jinja 聊天模板,專修官方版本的渲染錯誤、KV Cache 失效、token 浪費和 Agent 任務下的致命卡死
? 直接把官方 chat_template.jinja 換成 froggeric 這個版本就行,模型權重不用動,量化文件不用重做
經過實測,在以下推理引擎上都能跑:
LM Studio :右側面板換 Prompt Template 直接保存
llama.cpp / koboldcpp :
--jinja --chat-template-file chat_template.jinjavLLM :替換
tokenizer_config.json里的chat_template字段,配合--tool-call-parser qwen3_coderMLX / oMLX :覆蓋本地模型目錄的
chat_template.jinja,啟動加--jinja任意支持 HuggingFace Jinja 模板的引擎也通吃
直接上 froggeric 整理的"罪狀表"(v19 視角):
類別
問題
后果
Agent 死循環
提前停機 Bug
模型想邊說話邊調工具,結果一上頭就 `<
Agent 死循環
重試自旋
工具明明報錯了,模型還在原地反復發同一個失敗的
Agent 死循環
工具調用后過度思考
拿到數據后陷入"我該不該回答"的內心戲
Agent 死循環
誤判錯誤
返回結果里只要帶個 error 字樣,立刻誤以為工具失敗
性能
KV Cache 失效
歷史 prune 每輪都改變,整個 prompt 重新算一遍,速度起飛(向下)
性能
"空 think" 中毒
歷史里殘留一堆空
,模型學會"不思考才能用工具"的詭異認知
兼容性
老舊 C++ 引擎崩潰
loop.previtem
在老版 llama.cpp / minijinja 上直接掛
兼容性
工具調用格式錯
Qwen 訓練時用的是 XML 格式
,官方模板卻給改成 JSON,vLLM 的 qwen3_coder 解析器直接懵
兼容性
Jinja C++ 崩潰
Python 專屬過濾器 map 、 first 在 minijinja 上是一炸一個準
穩定性
對話中插系統消息崩潰
框架想中途插一句 system 指令,模板硬錯
穩定性
沒用戶消息直接崩
純 Agent loop 或系統消息上下文里 raise_exception 觸發
穩定性
思考沒關就調工具
XML 標簽泄漏到工具解析器
邊界 case developer
角色被拒
Claude Code / Codex / OpenCode 現代 API 都用 developer 角色,官方模板不認
邊界 case --reasoning off
被忽略
明明關了思考,錯誤升級路徑里又偷偷開了
塊
邊界 case
關思考時幻覺 reasoning 標簽
Qwen 自己會幻覺出多余的 \n ,堆棧空格炸了
v19 改了什么(這是最值得看的部分) ![]()
v19 三大修復 · The Agentic Loop Cure
v19(2026-05-18 發布)的核心是 The Agentic Loop Cure,三件大事:
1. 干掉"空 think 中毒"
之前的版本為了省 token,把歷史里的
塊清空成空標簽,結果模型把"空思考 = 可以調工具"和"完整思考 = 必須接對話"建立了一個錯亂的關聯,80% 以上的過早收攤 Bug 都來自這個,v19 直接重寫 AST 歷史渲染,徹底不再注入空 think 塊
2. 拆掉系統提示詞里的"邏輯陷阱"
老版的
塊里給了一道死命令:" 之后必須調工具",模型一遇到只想聊天的場景就 panic,v19 改成了 Universal Synthesis 指令,允許模型從 直接轉入對話回復,不必再為這條規則做內心 debate
3. KV Cache 100% 命中 + Amnesia 修復
preserve_thinking 現在默認 true,過去的思考鏈嚴格按時序保留,**完全治好了多步工具循環里的"失憶卡頓"**,同時數學保證 100% Prefix KV Cache 命中率,本地推理速度直接拉滿
這一波下來,agent loop 基本可以一氣跑完,不再卡在中途亂拐彎
安裝方式
按你用的引擎選一個:
LM Studio
1. 右側面板打開 Qwen 模型
2. 找到 Prompt Template
3. 把 chat_template.jinja 全文粘進去
4. 保存
llama.cpp / koboldcpp
--jinja --chat-template-file chat_template.jinja
vLLM
把 tokenizer_config.json 里的 chat_template 字段整段替換成 jinja 文件原文,然后配合 Qwen 原生 XML 工具解析器:
--tool-call-parser qwen3_coder
oMLX
覆蓋本地模型目錄的 chat_template.jinja,啟動時加 --jinja,把所有 chat_template_kwargs 覆蓋項刪掉,模板內部已全自動處理
? Qwen 3.5 / 3.6 全系列(35B / 32B / 27B / 14B)共用同一個 chat_template.jinja,不需要分版本思考模式開關,省錢小妙招
這套模板還有一個我特別喜歡的功能:思考模式可以在 prompt 里隨時切換
直接在 system 或 user 消息里塞一個 control token:
快速回答,不思考:
System: You are a coding assistant. <|think_off|>
User: What's 2+2?深度推理:
System: You are a coding assistant. <|think_on|>
User: Implement a red-black tree in Rust.
模板會自動攔截這個 tag,從最終上下文里刪掉,模型看不到,但模式已經切了
為什么用 <|think_on|> 而不是早期社區流行的 /think?因為 Qwen 控制 token 的 delimiter 絕不會和正常文本或文件路徑打架,安全等級高一檔
想再省點 token?
v19 默認 preserve_thinking=true,主打 KV Cache 命中率,但如果你顯存吃緊、context window 緊張,可以在引擎模板 kwargs 里關掉:
{
"preserve_thinking": false
}
代價是多輪對話 KV Cache 命中率會下降(prompt 字符串會動態變化),但能省下一截 context
唯一的小坑:升級到 v19 的時候,preserve_thinking默認改成 true 了,如果你之前自己改過 kwargs,記得對照一下
總結
老實講,這是那種"看起來不起眼但用過就回不去"的項目,沒有花哨的功能,就是把官方挖的坑一個一個填了
適合的人群:
用 llama.cpp / LM Studio / vLLM 本地跑 Qwen 3.5 / 3.6 的所有人
想跑 Agent / 工具調用 / Coder 任務的開發者
被 KV Cache 失效折磨到懷疑硬件的同學
用 Claude Code / Codex / OpenCode 接 Qwen 的玩家
唯一的勸退點是:得自己手動替換模板,對純小白稍微有門檻,但跟著官方 README 一步步來五分鐘就能搞定
_template .cpp
制作不易,如果這篇文章覺得對你有用,可否點個關注。給我個三連擊:點贊、轉發和在看。若可以再給我加個,謝謝你看我的文章,我們下篇再見!
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.