Qwen Code 改进建议
April 5, 2026 · View on GitHub
核心洞察:现代大模型(如 Claude 3.5、Gemini 1.5 等)普遍支持 Prompt Caching(提示词缓存),能够为长且固定的前缀上下文节省高达 90% 的输入 Token 费用,并使首字响应时间减半。但 Prompt Cache 对前缀的字节级一致性要求极高。Claude Code 设计了极致的分段缓存、稳定排序与 Schema 锁定策略;而 Qwen Code 的 System Prompt 和工具列表容易发生微小抖动,导致极高的缓存未命中率。
返回 改进建议总览
一、为什么 Prompt Cache 容易失效?
在 API 调用时,Agent 的前缀通常由以下两部分构成(约占几万 Tokens):
- System Prompt (系统提示词):包含大段行为准则、项目规范、当前状态。
- Tools Schema (工具定义):包含所有工具名称、描述和 JSON Schema。
Qwen Code 的现状问题:
在 packages/core/src/core/client.ts (getMainSessionSystemInstruction) 中,Qwen Code 会将动态状态(如当前工作目录、当前打开的文件、动态的内存片段)直接拼接在整个 System Prompt 中发送。
此外,工具数组的顺序没有严格保证(如果加载了外部 MCP 工具,顺序可能会变化)。
后果:
只要前缀中有一个字符发生变化(例如当前活跃的文件变了),整个数万 Token 的前缀缓存就会被击穿,API 每次都会重新收取全量输入费用,且响应迟缓。
二、Claude Code 的解决方案:分界与锁定
在 Claude Code 的源码中(utils/api.ts, utils/toolSchemaCache.ts, services/api/promptCacheBreakDetection.ts),它为极致的缓存命中率做了四层设计:
1. Static / Dynamic 系统提示词分界
Claude Code 显式地将系统提示词分为两半:
- Static Section (静态区):包含永不改变的系统身份、核心能力、通用指令规则。
- Dynamic Section (动态区):包含当前时间、活跃文件、临时的用户偏好等。
它会在两者的交界处插入一个 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 标记,并且仅对静态区域和其上方的工具定义应用 cache_control: { type: 'ephemeral' } 缓存断点。
这样,动态区的内容随意改变,都不会影响前面数万 Token 的缓存命中。
2. 工具列表的稳定排序 (Stable Sorting)
工具 Schema 是最长的前缀之一(十几 K Token)。
Claude Code 在 utils/toolPool.ts 中强制所有内置工具(Built-in Tools)按照字母表顺序固定排列在数组最前面。
对于动态加载的 MCP 工具或项目局部工具,则始终追加在内置工具之后。这样可以确保“内置工具前缀”永远命中缓存。
3. 工具 Schema 的首帧锁定
大型 Agent 的工具 Schema 中可能会因为 A/B 测试(GrowthBook)或配置热更新而发生微小变动。
Claude Code 设计了 toolSchemaCache.ts。在会话(Session)的第一次调用时,它会深度冻结(Snapshot)并缓存当前的 Tool Schema。即使后续环境变量或开关发生改变,只要不重启 Session,它发送给 API 的 Schema 就保证绝对字节级一致。
4. 自动缓存击穿检测
Claude Code 包含一个 promptCacheBreakDetection.ts 服务。它会监控每次 API 响应中的 cache_read_input_tokens 指标。如果发现原本应该命中的缓存突然变成 0,它会在内部日志中记录警告,帮助开发者迅速定位是哪一段 Prompt 引入了抖动。
三、Qwen Code 的改进路径 (P1 优先级)
为了将长会话的 API 成本砍掉一大半并加速响应,Qwen Code 必须重构 Prompt 组装逻辑。
阶段 1:拆分核心 System Prompt
- 重构
getCoreSystemPrompt()(位于packages/core/src/core/prompts.ts)。 - 将原本混合在一起的
userMemory、环境状态等剥离到数组的后半部分。 - 确保前半部分的指令字符串完全纯净、静态。
阶段 2:强制工具数组稳定排序
- 在
client.ts或agent-core.ts组装toolsList时,增加sort()逻辑。 - 确保
Qwen Code自带的基础工具(如read_file,shell,todo_write)具有固定的索引位置。
阶段 3:注入 Cache Control 标记
- 对于支持 Prompt Caching 的模型 API(目前主要是 Anthropic Claude 系列,以及部分提供兼容 API 的国产模型)。
- 在组装
messages数组发送前,对 Static System Prompt block 和 Tools block 附加底层协议要求的 Cache 断点标记(例如 Anthropic 的cache_control)。
四、改进收益评估
- 实现成本:中等。需要深入了解不同 LLM 供应商的 Prompt Caching 协议。
- 直接收益:
- 巨额成本节约:将平均 20K~50K Tokens 的全量输入费用转化为廉价的 Cache Read 费用,API 成本直降 50%-80%。
- 响应速度起飞:模型省略了庞大系统设定的 Context 阶段,首 Token 吐出延迟(TTFT)通常可缩短一半以上。