Files
claude-code/docs/context/token-budget.mdx
claude-code-best b844f639f9 docs: 重写令牌预算,移除实现常量和重复代码片段
聚焦 token 管理的设计考量:两级计数策略、分层压缩(截断→微压缩→自动压缩)、
缓存感知的压缩设计和 slot 优化设计哲学。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 06:46:48 +08:00

129 lines
6.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "令牌预算"
description: "200K 上下文窗口不是全部。理解 Claude Code 如何管理 token 预算:动态计算、近似 vs 精确计数、分层压缩策略和缓存优化。"
keywords: ["Token 预算", "上下文窗口", "token 计算", "压缩策略"]
---
## 核心约束200K 不是全部
Claude 的上下文窗口为 200K tokens部分模型支持 1M但实际可用于对话的空间远小于此
```
上下文窗口200K
├── 系统提示词(~15-25K
├── 工具定义(~10-20K含 MCP 工具)
├── 用户上下文CLAUDE.md、git status 等)
├── 输出预留AI 响应的空间)
└── 剩余:对话历史空间(随对话增长而缩小)
```
**设计挑战**:对话历史不断增长,可用空间持续缩小。系统必须在"保留足够的上下文让 AI 理解对话"和"不超出 token 限制"之间持续平衡。
### 上下文窗口的动态解析
上下文窗口大小不是硬编码的。系统按优先级从多个来源解析:
1. 用户环境变量覆盖(强制指定)
2. 模型名后缀标记(如 `[1m]` 表示 1M 窗口)
3. 模型自身的能力声明
4. 特定 beta 功能的支持情况
5. 兜底值200K
这种分层解析意味着同一个系统可以适配不同模型和不同配置,而不需要为每种情况写特殊逻辑。
## Token 计数:近似 vs 精确
Token 计数是所有预算决策的基础。系统采用两级策略:
### 近似估算(毫秒级)
基于一个简单的经验公式:大约每 4 个字节 ≈ 1 个 token。对不同内容类型有调整
- **JSON/JSONL**:更密集,每 2 字节 ≈ 1 token
- **图片/文档**:固定估算值(基于尺寸上限的保守估计)
- **普通文本**:每 4 字节 ≈ 1 token
### 精确计数(需要 API 调用)
使用 Anthropic 的 token 计数端点。不同 Provider 的支持程度不同:
| Provider 类别 | 精确计数支持 | 注意事项 |
|---------------|-------------|----------|
| Anthropic 直连 | 原生支持 | 最准确 |
| 云平台Bedrock/Vertex | 各自的 SDK 接口 | 需要额外依赖 |
| 第三方兼容OpenAI/Gemini/Grok | 不支持 | 退回近似估算 |
### 为什么需要两级策略
近似估算用于**热路径**——每轮 agentic loop 都需要判断"是否需要压缩",这个检查必须足够快。精确计数用于**关键决策点**——压缩前后对比、费用计算等需要准确数字的场景。
**设计权衡**:近似估算可能偏差 10-20%,这意味着自动压缩的触发时机可能略有提前或延后。但这个偏差是可以接受的——提前压缩只多花一点 token延后压缩最多触发一次 API 错误然后紧急压缩。
## 分层压缩策略
系统不是等到"满了才压缩",而是采用了由轻到重的分层策略:
### 第一层:工具结果截断
单个工具的输出有硬性上限(通常 100K 字符)。超长的命令输出、文件内容在写入消息前就被截断。
这是最轻量的"压缩"——只是防止单个工具结果占用过多空间。
### 第二层微压缩Micro-Compact
在触发全量压缩之前,系统先尝试只压缩旧的工具调用结果:
- 超过一定时间的工具结果被替换为简短占位符
- 图片/文档结果替换为 `[image]` / `[document]` 文本
- 每次替换释放 token可能推迟全量压缩的触发
**设计考量**:为什么不直接全量压缩?因为全量压缩需要调用 AI 生成摘要,成本高且耗时。微压缩是确定性操作(简单替换),几乎零成本,可以频繁执行。
### 第三层自动压缩Auto-Compact
当对话接近 token 上限时,系统用 AI 自身来总结之前的对话:
1. **剥离非必要内容**:图片、文档附件被替换为文本标记
2. **生成摘要**:通过一个独立的 agent 调用生成对话摘要
3. **重建上下文**:用摘要替代原始对话,同时重新注入关键信息(最近操作的文件、活跃的计划等)
**设计考量**:压缩后会重新读取最近操作的 5 个文件。这是因为在实际使用中AI 最可能需要的就是刚刚操作过的文件——重新读取它们比让 AI 再次搜索更高效。
### 压缩的安全阀
- **连续失败上限**:连续 3 次压缩失败后停止尝试(断路器模式)
- **压缩来源的查询不触发压缩**:防止压缩本身触发无限递归
- **手动压缩**:用户可以随时通过 `/compact` 主动触发
## 缓存感知的压缩设计
压缩操作本身需要调用 API 生成摘要——这是整个会话中最昂贵的操作之一。系统通过**复用主线程的缓存前缀**来优化:
系统 prompt + 工具定义 + 上下文消息通常不变,这部分可以通过 API 的 prompt cache 机制缓存。压缩时的摘要请求复用了这些缓存,使得缓存命中率从接近 0% 提升到接近 100%。
**设计洞察**:这不是一个独立的优化——它是整个缓存策略的一部分。系统 prompt 的组装策略("不变内容在前")和压缩时的缓存复用,都是为了最大化 prompt cache 的命中率。
## 输出 Token 的 Slot 优化
一个容易被忽视但影响深远的优化AI 输出的 token 上限默认只设为 8K而不是模型支持的最大值32K 或 64K
**为什么**?因为 API 服务端按 `max_tokens` 参数预留推理容量slot。99% 的请求实际输出不到 5K tokens但如果所有请求都预留 32K 的 slot会导致严重的容量浪费。
降到 8K 后,不到 1% 的请求会被截断——这些请求自动获得一次高上限的干净重试。
**设计哲学**:用 1% 的请求多一次重试的代价,换取 99% 请求的更快响应。这是一个典型的"优化常见路径,用重试处理边缘情况"的设计模式。
## 选择性压缩
除了全量压缩,用户还可以选择只压缩对话的某一部分:
- **压缩早期内容**(保留最近对话):适用于"开头说了很多背景,但后面只需要关注最近操作"的场景
- **压缩近期内容**(保留早期对话):适用于"早期的架构决策很重要,但最近的工具调用结果不需要"的场景
两种方向对缓存有不同的影响——保留前缀(早期内容)可以维持 prompt cache修改前缀则破坏缓存。
## 接下来
- **上下文压缩** — 深入了解压缩的触发条件和摘要生成机制
- **项目记忆** — 理解跨会话的记忆持久化设计
- **穷鬼模式** — 了解如何减少 token 消耗