Skip to content

03.1 上下文窗口的物理学

上下文窗口不是"你能贴多少字",是一块被多方瓜分的稀缺内存。

读完你能做什么:知道每一个 token 花在哪了,并能在会话变慢变笨之前提前干预。


一、Token 的基本换算

内容约等于
1 个 token约 0.75 个英文单词
1 个汉字约 1-2 个 token(中文的 token 效率低于英文)
1 行普通代码约 10-20 token
1 页 A4 纯文字约 500-800 token
1 个中等大小的源文件(300 行)约 3000-6000 token
1 份 50 页 PDF约 25,000-40,000 token

一条实用心算:中文文本的 token 数大约是字数的 1-1.5 倍;英文大约是单词数的 1.3 倍。


二、谁在占用你的上下文

这是最多人低估的部分。在一个 Claude Code 会话开始时,还没输入任何东西,上下文里已经有了:

text
┌───────────────────────────────────────────┐
│  系统提示词(工具定义、行为指令、安全规则)    │  ← 数千 token
├───────────────────────────────────────────┤
│  MCP 工具定义(每个工具的 schema)           │  ← 每个工具几百 token
├───────────────────────────────────────────┤
│  CLAUDE.md(用户级 + 项目级 + 本地)         │  ← 你写多少算多少
├───────────────────────────────────────────┤
│  .claude/rules/ 中的无条件规则               │  ← 同上
├───────────────────────────────────────────┤
│  Auto Memory 的 MEMORY.md 索引              │  ← 前 200 行 / 25KB
├───────────────────────────────────────────┤
│  Skill 的 name + description(每个技能)     │  ← 每个几十 token
├───────────────────────────────────────────┤
│  环境信息(工作目录、git 状态、平台)          │  ← 少量
├───────────────────────────────────────────┤
│                                           │
│           ↓ 剩下的才是你的  ↓               │
│                                           │
│  对话历史 + 读取的文件 + 工具返回结果          │
│                                           │
└───────────────────────────────────────────┘

2.1 查看真实占用

text
> /context

这条命令会显示:

  • 每一部分实际占用了多少
  • 哪些 Memory files 真的被加载了
  • 剩余可用空间

这是诊断"为什么会话变慢/变笨"的第一个动作。

2.2 查看 Skill 的 token 成本

text
> /skills

在列表中按 t 可以按 token 数排序,立刻看到哪个技能最占地方。


三、五大隐形消耗源

消耗源 1:MCP 工具定义

症状:装了 8 个 MCP server,每个暴露 20 个工具 = 160 个工具定义常驻上下文。

成本:一个工具定义(名字 + 描述 + 参数 schema)通常 100-500 token。160 个工具可能吃掉 3-8 万 token。

对策

  1. 启用 tool search(工具延迟加载),见 07.5
  2. 按项目隔离 MCP 配置(--scope project
  3. 临时禁用不需要的 server
bash
# 只加载指定的 MCP 配置,忽略其他所有
claude --strict-mcp-config --mcp-config ./project-mcp.json

消耗源 2:臃肿的 CLAUDE.md

症状CLAUDE.md 写了 800 行,涵盖了整个项目的架构说明。

成本:每次会话开头就吃掉几千 token。而且文件越长,单条指令的遵守率越低

对策

  • 官方建议单个 CLAUDE.md 控制在 200 行以内
  • 把"只在特定目录生效"的内容移到 .claude/rules/ 并加 paths 前置元数据
  • 把"多步流程"移到 Skill(按需加载,不用时零成本)
text
> /doctor

在 v2.1.206+ 中,/doctor 会主动为已提交的 CLAUDE.md 提出精简建议 —— 它会砍掉 Claude 能从代码库自己推导的内容(目录结构、依赖列表、架构概览),保留那些它推导不出来的(坑、决策理由、与工具默认行为不同的约定)。

消耗源 3:大文件的全量读取

症状:让它「看一下这个文件」,那个文件有 5000 行。

对策:明确指定范围。

text
❌ 看一下 src/services/order.ts
✅ 读 src/services/order.ts 的第 200-350 行,那里是对账逻辑
✅ 先用 grep 找到 reconcile 相关的函数定义,再只读那几个函数

消耗源 4:工具返回的大量输出

症状:跑一次测试,输出 3000 行日志,全部进上下文。

对策

bash
# ❌ 全量输出
npm test

# ✅ 只要失败部分
npm test 2>&1 | grep -A 5 -E "(FAIL|Error|✕)" | head -50

# ✅ 或者先看统计,再按需深入
npm test 2>&1 | tail -20

在提示词里明确要求:

text
运行测试时,用管道过滤只保留失败信息,不要把完整输出读进来。

消耗源 5:对话历史的复利效应

症状:第 40 轮时明显变慢。

机制:每一轮推理,前面所有轮次的内容都要重新参与计算。第 40 轮的成本 ≈ 前 39 轮内容总和 + 本轮。

对策:见 03.4 压缩 Compact 与会话续航


四、上下文压力的三个阶段

占用率表现该做什么
< 50%一切正常继续
50-75%开始出现指令遗忘、格式漂移重申关键约束;准备 /compact
> 75%明显变笨、变慢;早期约束基本失效立刻 /compact/clear
接近上限自动触发压缩,可能丢失关键信息已经晚了

关键:不要等到系统自动压缩。自动压缩发生时你无法控制保留什么,手动 /compact 时你可以指示保留重点。


五、一个反直觉的事实

上下文里的内容不是越多越好,即使它们全都是相关的。

原因有三:

  1. 注意力被摊薄 —— 100 条相关信息里,每一条获得的注意力权重都低于 10 条相关信息中的每一条。
  2. 矛盾信息互相干扰 —— 同一个函数的三个版本同时在上下文里,模型不知道该以哪个为准。
  3. 成本线性增长,收益边际递减 —— 第 50 个文件带来的信息增量,远小于第 5 个。

实践原则:给它刚好够用的上下文,不是所有可能相关的上下文。

text
❌ 我把整个 src 目录都读进来了,你分析一下架构问题
✅ 我先给你 3 个核心文件(入口、路由、核心 service)。
   看完后,告诉我你还需要读哪些文件才能做出判断。

第二种写法让模型自己驱动信息收集,比你一次性倒进去效果好得多,成本也低得多。


六、上下文预算表(实用工具)

在开始一个大任务前,先做预算:

项目预估 token备注
系统 + 工具定义待测/context 查看
CLAUDE.md + rules待测同上
需要读的代码文件文件行数 × 15
参考文档页数 × 700
预计对话轮数 × 每轮平均轮数 × 1500含你的输入和它的输出
合计应 < 窗口的 70%

如果超预算,优先砍:

  1. 参考文档 → 改成按需检索(RAG 或 grep)
  2. 代码文件 → 改成先索引后精读
  3. 对话轮数 → 拆成多个会话

七、快速诊断脚本

放在项目里,随时检查你的配置有多重:

bash
#!/usr/bin/env bash
# .claude/scripts/context-audit.sh
# 粗略估算常驻上下文的字符数(token 约为字符数的 1/3 到 1/1)

echo "=== CLAUDE.md 系列 ==="
for f in ./CLAUDE.md ./.claude/CLAUDE.md ./CLAUDE.local.md ~/.claude/CLAUDE.md; do
  [ -f "$f" ] && printf "%-40s %6s 行 %8s 字符\n" "$f" "$(wc -l < "$f")" "$(wc -c < "$f")"
done

echo
echo "=== .claude/rules/ ==="
if [ -d ./.claude/rules ]; then
  find ./.claude/rules -name '*.md' -exec sh -c \
    'printf "%-40s %6s 行\n" "$1" "$(wc -l < "$1")"' _ {} \;
fi

echo
echo "=== Skills ==="
find ./.claude/skills ~/.claude/skills -name 'SKILL.md' 2>/dev/null -exec sh -c \
  'printf "%-40s %6s 行\n" "$1" "$(wc -l < "$1")"' _ {} \;

echo
echo "=== MCP 配置 ==="
[ -f ./.mcp.json ] && echo "项目级 MCP server 数量: $(grep -c '"command"\|"url"' ./.mcp.json)"

echo
echo "提示:运行 /context 查看真实占用"
bash
chmod +x .claude/scripts/context-audit.sh
./.claude/scripts/context-audit.sh

延伸阅读

基于 VitePress 构建 · 内容采用原作者授权