跳转到内容

04 模块化系统提示词构建

学习目标

本章要解决什么问题:Cline 如何管理 11 种模型变体的系统提示词?组件化组装如何提高可测试性和缓存利用率?

前置知识

本章涉及系统提示组装的通用原理,建议先阅读:

下文假设你已理解分层提示和缓存边界,直接聚焦 Cline 的具体实现。


项目实践

三层组装结构

Cline 的系统提示词在 src/core/prompts/system-prompt/ 目录下采用三层组装:

system-prompt/
├── components/ # 可复用段落
│ ├── role.md # 角色定义
│ ├── rules.md # 行为规则
│ ├── capabilities.md # 能力说明
│ └── ...
├── variants/ # 模型特定变体(11 种)
│ ├── generic/ # 通用变体
│ ├── next-gen/ # 下一代模型
│ ├── gpt-5/ # GPT-5 专用
│ ├── xs/ # 小模型专用
│ └── ...
└── tools/ # 各工具的指令定义
├── read_file.md
├── write_to_file.md
├── execute_command.md
└── ...

组装流程

  1. 根据当前模型选择对应的 variant 目录
  2. 加载 variant 中定义的组件列表
  3. 从 components/ 加载对应组件内容
  4. 加载 tools/ 中所有可用工具的指令
  5. 拼接为完整的系统提示词

11 种模型变体

变体适用模型特点
generic大多数提供商通用指令,XML 工具格式
next-genClaude Sonnet 4.5+利用更强的推理能力
gpt-5GPT-5适配 OpenAI Responses API 原生工具调用
xs小模型(如 GPT-4o-mini)简化指令,减少 Token

设计启示:不同模型的提示词需要针对性优化。对强模型可以使用更复杂的指令(它们能理解),对小模型需要精简。通过变体目录管理,而非条件判断拼接,提高了可维护性。

快照测试验证提示词

Cline 使用 snapshot 测试验证系统提示词的结构:

# 伪代码:快照测试
test("generic variant should match snapshot", () => {
const prompt = buildSystemPrompt("generic")
expect(prompt).toMatchSnapshot()
})

为什么用快照测试? 系统提示词的正确性很难用断言表达(如”语气是否合适”)。快照测试将整个提示词保存为基准,当提示词变化时,diff 直观展示变化内容,便于 code review。

缓存友好性

组件化设计有利于 prompt cache 的利用:

  • components/role.mdcomponents/rules.md 是静态的,可以被多个请求缓存
  • tools/ 中的工具指令也是静态的,只要工具集不变就命中缓存
  • 只有用户输入部分是动态的,每次不同

缓存边界:以组件为单位设置缓存边界,避免动态内容污染静态提示词的缓存。


问题与规避

陷阱场景对策
组件遗漏variant 忘记引用某个 component快照测试检测组件完整性
工具指令不一致新增工具未添加到所有 varianttools/ 目录统一管理,variant 只引用
变体膨胀每新增一个模型就创建一个 variant相似模型共享同一 variant

设计取舍

组件化 vs 模板字符串

方案优势代价
组件化(文件目录)可测试、可组合、变体管理方便文件数量多,组装逻辑复杂
模板字符串(代码中拼接)实现简单难以测试、变体管理混乱

Cline 选择组件化,因为 11 种变体和 25+ 种工具的组合数太多,模板字符串会不可维护。

变体驱动 vs 条件判断

方案优势代价
变体目录新增变体不修改现有代码需要理解目录结构
条件判断(if-else)代码集中修改一个变体可能影响其他

Cline 选择变体目录,因为条件判断在变体数量增加后会变得难以维护。


参考来源

  • Cline 源码:apps/vscode/src/core/prompts/system-prompt/
  • Cline 测试:apps/vscode/__tests__/ 中的 snapshot 测试