mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 22:05:50 +00:00
移除全部 TypeScript 代码、源码路径和实现常量, 聚焦数组缓存驱动的架构选择、三阶段管道设计、 三种缓存模式的选择逻辑和 CLAUDE.md 多级合并的安全考量。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
152 lines
6.5 KiB
Plaintext
152 lines
6.5 KiB
Plaintext
---
|
||
title: "系统提示词"
|
||
description: "系统提示词不是一段写死的文本,而是一个动态组装、分块缓存的数组。理解三阶段管道、缓存分界标记和多级优先级选择的设计。"
|
||
keywords: ["系统提示词", "System Prompt", "动态组装", "Prompt Cache", "缓存策略"]
|
||
---
|
||
|
||
## 核心问题
|
||
|
||
AI 的行为由系统提示词(System Prompt)决定。但一个编程助手的系统提示词远不止一句"你是一个有用的助手"——它需要包含工具使用规则、安全策略、项目上下文、用户偏好等大量动态内容。
|
||
|
||
挑战在于:**这些内容每次请求都要发送,而且大部分是不变的。** 如何在保持动态性的同时最小化 token 成本?
|
||
|
||
## 从文本到数组:缓存驱动的架构选择
|
||
|
||
系统提示词不是单个字符串,而是一个 **字符串数组**。
|
||
|
||
### 为什么是数组?
|
||
|
||
Anthropic 的 Prompt Cache 以**内容块**为单位缓存。将提示词拆为多个块,不变的部分可以获得独立的缓存命中。如果是一个单字符串,任何一个字符变化(如日期更新)都会导致整个提示词的缓存失效。
|
||
|
||
一个典型的系统提示词约 20K+ tokens,通过缓存分块可以节省 30-50% 的输入 token 费用。
|
||
|
||
### 品牌类型保证
|
||
|
||
系统使用品牌类型(branded type)防止普通字符串数组被意外传入 API 调用——只有通过显式转换才能获得系统提示词类型。这是零开销的编译时安全保证。
|
||
|
||
## 三阶段组装管道
|
||
|
||
```
|
||
收集内容 → 选择优先级 → 分块 + 缓存标记
|
||
```
|
||
|
||
### 第一阶段:内容收集
|
||
|
||
系统提示词的内容分为两个区域:
|
||
|
||
| 区域 | 内容 | 特点 |
|
||
|------|------|------|
|
||
| **静态区** | 工具使用规则、安全策略、输出格式规范 | 所有用户相同 |
|
||
| **动态区** | 记忆、MCP 指令、模型覆盖、语言偏好 | 因用户/会话而异 |
|
||
|
||
两个区域之间用一个特殊的**分界标记**分隔。这个标记永远不会发送给 AI——它只是告诉缓存系统:"到这里为止是静态的,从这里开始是动态的"。
|
||
|
||
### 第二阶段:优先级选择
|
||
|
||
最终使用哪个提示词取决于五级优先级:
|
||
|
||
| 优先级 | 来源 | 场景 |
|
||
|--------|------|------|
|
||
| **Override** | 外部覆盖 | SDK 集成、自动化测试 |
|
||
| **Coordinator** | 协调者模式 | 多 Agent 编排 |
|
||
| **Agent** | Agent 定义 | 自定义 Agent |
|
||
| **Custom** | 命令行参数 | 用户的自定义提示词 |
|
||
| **Default** | 完整组装 | 正常使用 |
|
||
|
||
**设计考量**:Override 级别完全替换默认提示词(包括安全规则),这是危险的但必要的——自动化测试和 SDK 集成需要完全控制。其他级别则在默认提示词基础上追加或替换。
|
||
|
||
### 第三阶段:分块与缓存标记
|
||
|
||
分块策略根据条件选择三种模式:
|
||
|
||
**模式 1:全局缓存(1P 用户默认)**
|
||
```
|
||
[归属头] → 不缓存
|
||
[提示词前缀] → 不缓存
|
||
[静态内容] → 全局缓存(跨组织共享)
|
||
[动态内容] → 不缓存
|
||
```
|
||
|
||
**模式 2:组织缓存(MCP 工具存在时)**
|
||
```
|
||
[归属头] → 不缓存
|
||
[提示词前缀] → 组织缓存
|
||
[其余内容] → 组织缓存
|
||
```
|
||
|
||
**模式 3:组织缓存(3P 用户)**
|
||
```
|
||
[归属头] → 不缓存
|
||
[提示词前缀] → 组织缓存
|
||
[其余内容] → 组织缓存
|
||
```
|
||
|
||
**为什么 MCP 工具会降级缓存**?MCP 工具列表在会话中可能变化(连接/断开),这会改变提示词内容,破坏跨组织缓存的基础。因此当 MCP 工具存在时,只能使用组织级缓存。
|
||
|
||
### 缓存破坏的防御
|
||
|
||
动态区的某些内容(如会话特定的工具集)必须严格放在分界标记之后。如果错误地放在静态区,每个运行时条件的组合会产生 2^N 种不同的哈希值(N = 条件数量),完全破坏缓存命中率。
|
||
|
||
系统对"每轮都重新计算"的 Section 使用专门的危险标记——开发者必须给出破坏缓存的理由才能使用它。
|
||
|
||
## 上下文注入:两条独立管道
|
||
|
||
系统提示词本身不包含运行时上下文。上下文通过两条独立管道注入:
|
||
|
||
### System Context(会话级不变)
|
||
|
||
- Git 分支和状态
|
||
- 最近的提交记录
|
||
- 计算一次,整个会话期间缓存
|
||
|
||
### User Context(动态变化)
|
||
|
||
- 合并后的 CLAUDE.md 内容
|
||
- 当前日期
|
||
|
||
**为什么 User Context 不放在 System Prompt 中**?因为 User Context 作为用户消息发送,可以利用 Prompt Cache 的前缀共享——系统提示词是所有用户共享的前缀,User Context 是每个用户的变化部分。这种分层让缓存命中率最大化。
|
||
|
||
## CLAUDE.md:项目级知识注入
|
||
|
||
这是 Claude Code 最巧妙的设计之一。在项目目录中放一个 `CLAUDE.md` 文件,就能让 AI "理解"项目。
|
||
|
||
### 多级合并
|
||
|
||
```
|
||
~/.claude/CLAUDE.md ← 用户全局(个人偏好)
|
||
└── /project/CLAUDE.md ← 项目根目录(团队共享)
|
||
└── /project/src/CLAUDE.md ← 子目录(模块特定)
|
||
```
|
||
|
||
系统从当前工作目录向上遍历,合并所有匹配的 CLAUDE.md 文件。子目录的 CLAUDE.md 可以覆盖或补充父目录的规则。
|
||
|
||
**设计哲学**:项目知识应该由团队成员维护、随代码演进、可通过 git 追踪。CLAUDE.md 本质上是"给人读的项目文档,恰好 AI 也能读"。
|
||
|
||
### 安全考量
|
||
|
||
项目级 CLAUDE.md 可以被仓库中的任何人修改(包括恶意贡献者)。系统因此限制了项目级 CLAUDE.md 的影响范围——它们不能覆盖安全关键设置,也不能修改权限模型。
|
||
|
||
## Provider 差异与缓存
|
||
|
||
不同的 API Provider 有不同的缓存能力:
|
||
|
||
| Provider | 全局缓存 | 精确 Token 计数 | 特殊 Beta 功能 |
|
||
|----------|:--------:|:---------------:|:--------------:|
|
||
| Anthropic 直连 | ✓ | ✓ | ✓ |
|
||
| AWS Bedrock | ✗ | ✓(独立端点) | 部分 |
|
||
| Google Vertex | ✗ | ✗ | 部分 |
|
||
| OpenAI 兼容 | ✗ | ✗ | ✗ |
|
||
| Gemini | ✗ | ✗ | ✗ |
|
||
|
||
3P 用户的系统提示词始终使用组织级缓存,因为没有全局缓存的 API 支持。这也意味着 token 计数依赖估算,影响自动压缩的触发时机。
|
||
|
||
## 最小化模式
|
||
|
||
环境变量 `CLAUDE_CODE_SIMPLE` 可以将整个系统提示词缩减为一行——跳过所有 Section 注册、缓存分块和动态组装。用于最小化 token 消耗的测试场景。
|
||
|
||
## 接下来
|
||
|
||
- **上下文压缩** — 理解当上下文增长超出限制时的压缩策略
|
||
- **令牌预算** — 了解 token 窗口的动态计算
|
||
- **Provider 系统** — 了解多 Provider 支持的架构设计
|