为什么 Claude Code 聊着聊着就又贵又笨了?一文讲透 AI 编程助手的上下文与 Token 经济学
面向 AI 开发工程师 / 程序员。本文把两个几乎所有人都踩过的坑讲清楚:为什么一个会话越聊越烧 token,以及为什么问着问着模型就像变笨了。不是玄学,是可以量化、可以解决的工程问题。
一、现状:我们都在同一个坑里
如果你重度用过 Claude Code、Cursor、Codex CLI、Cline、Aider 这类 Agent 编程助手,大概率经历过这两幕:
- 账单之痛:同样一个功能,开一个新会话三下五除二搞定,花几分钱;但在一个聊了两小时的老会话里继续问,几个来回就烧掉几块钱,token 用量曲线像坐了火箭。
- 智商滑坡:会话前 30 分钟它聪明得像资深工程师,聊到第 60 个来回,它开始"失忆"——忘了你早就定过的约定、把刚修好的 bug 又改回去、在两个自相矛盾的方案之间反复横跳、答非所问。
社区里有个很形象的说法叫“context rot”(上下文腐烂)。很多人下意识的反应是"模型不行了 / 变笨了",于是去换模型、加提示词、反复重试——但根因往往不在模型,而在会话本身的结构。
这两幕看似无关,其实是同一个东西的一体两面:随着会话变长,上下文(context)在膨胀。膨胀既推高了成本,又稀释了模型的注意力。理解了上下文是怎么被消费和计费的,这两个问题就都能对症下药。
二、使用体验:那种"越用越不对劲"的感觉
先描述一下大家共同的体感,你八成会心一笑:
🫠“我只是问了一句话,怎么算了两万个 token?”
你输入 20 个字,它却按你整个会话历史在计费。会话越长,你每说一句话的"起步价"越高。🐌首字延迟越来越长。老会话里回车之后,要等好几秒才蹦出第一个字——因为它得先把几万 token 的历史重新"读"一遍。
🧠它开始"选择性失明"。你在会话开头强调"这个项目用 Go,别给我写 Python",聊到后面它照样甩给你一段 Python;你早就否决过的方案,它又当成好主意重新提出来。
🔁改 A 坏 B,像在跟一个记性不好的人结对编程。它刚按你的要求把函数拆开,几轮之后又自作主张合回去了。
💸明明有"缓存"却更贵了。你听说这些工具有 prompt caching(提示缓存),按理说应该省钱,但为什么缓存越多反而越贵?这恰恰是最反直觉、也最值得讲清楚的一点。
三、原因(上):为什么会话越长,token 烧得越猛
要讲清楚,得先破除一个普遍的误解:
❌误解:“我这轮只输入了一句话,那这轮就只按这一句话计费。”
✅真相:Agent 每一轮,都会把到目前为止的整个对话历史(系统提示 + 全部工具定义 + 你历轮的消息 + 模型历轮的回复 + 每一次读文件/跑命令/搜索的完整输出)当作 input,重新发给模型一次。
这是 Agent 类应用的底层工作方式决定的:大模型 API 本身是无状态的。模型不会"记得"你们聊过什么,所谓的"记忆",全靠客户端(Claude Code 等)在每一轮把完整历史重新塞进请求里。
3.1 关键推论:成本随轮数近似"平方级"增长
设想一个会话进行了 N 轮,每一轮上下文平均长度正比于当前轮数:
- 第 1 轮:处理约 1 份上下文
- 第 2 轮:处理约 2 份
- ……
- 第 N 轮:处理约 N 份
累计处理量 ≈ 1 + 2 + … + N ≈N² / 2。
这就是"越聊越贵"的数学本质:你的消息数是线性增长的,但被处理的 token 总量是平方级增长的。一个 60 轮的会话,烧掉的 token 可能是两个 30 轮会话的2 倍——即便你干的活儿一样多。
3.2 工具输出是"隐形油老虎"
在编程 Agent 里,真正撑爆上下文的往往不是你打的字,而是工具调用的输出:
- 让它读一个 3000 行的文件 → 这 3000 行永久进入上下文,此后每一轮都要重新处理一遍。
- 一次
grep/ 全局搜索命中几十处 → 全部塞进上下文。 - 一次失败的构建 → 几百行报错日志,全程带着走。
一个不起眼的"读一下这个文件",可能就给之后的每一轮都加了几千 token 的固定税。
3.3 那 Prompt Caching 到底省了什么?为什么"缓存多"还更贵?
这里是全文最关键、也最反直觉的一段,请慢读。
各家(Anthropic、OpenAI 等)都上了prompt caching:既然每轮都要重发几乎相同的历史前缀(prefix),那就把这段前缀缓存住,重复读取时打折。以 Anthropic 的计价为例(数字来自官方 SDK 文档):
| 操作 | 相对价格(以基础 input 价为 1×) |
|---|---|
| 缓存命中读取(cache read) | 约 0.1×(便宜 90%) |
| 写入缓存(cache write,5 分钟 TTL) | 1.25×(比原价还贵 25%) |
| 写入缓存(1 小时 TTL) | 2× |
| 未缓存的普通 input | 1× |
看懂这张表,"缓存多反而贵"就解释得通了。缓存不是免费的,它有三笔账:
读的那部分确实便宜(0.1×),但架不住量大。
缓存打完 9 折,可你每一轮要读的是整个膨胀的历史前缀。前缀有 8 万 token 时,哪怕 0.1×,每轮光"读历史"就相当于 8000 token 的全价开销——而且这笔钱每一轮都要付一次。每一轮的"新增量"都要花 1.25× 去写缓存。
你这轮新说的话、新产生的工具输出,要追加进缓存,写入价是1.25×(比不缓存还贵)。会话越长、每轮新增越多,这笔"写入溢价"累积得越多。缓存会过期,过期就得全价重建(最狠的一刀)。
Anthropic 默认缓存TTL 只有 5 分钟(有 1 小时的付费档)。你去开个会、喝杯咖啡,超过 5 分钟没交互,缓存整个失效。你回来发的下一句话,会触发把几万 token 的整个上下文按全价(1×,甚至叠加写入溢价)重新处理并重建缓存。这一下,可能就是几毛钱。
💡一句话总结缓存的经济学:缓存让"读旧历史"变便宜,却让"上下文膨胀"这件事本身变得更值得警惕——因为前缀越大,每轮的读取基数越大、写入增量越多、过期重建越痛。"缓存多"不是省钱的标志,而是"上下文很大"的症状,而大上下文本身就是成本的根源。
还有几个容易踩的缓存失效陷阱,一旦命中,你以为在省钱,其实全程全价:
- 前缀里有任何一个字节变化,缓存就从那一点之后全部作废。系统提示里塞了
当前时间: 2026-07-09 15:23:07、请求 ID、随机 UUID、未排序的 JSON……每轮都不一样,缓存永远命中不了。 - 中途换模型 → 缓存作废(缓存是按模型隔离的)。
- 中途增删工具 → 缓存作废(工具定义排在最前面,动它等于动整个前缀)。
四、原因(下):为什么问多了模型会"变笨"
同样的膨胀,从"质量"这一面看,就是智商滑坡。这不是模型退化,而是长上下文对模型能力的真实损害,业界叫context rot。主要有四个机制:
4.1 注意力被稀释(“Lost in the Middle”)
Transformer 的注意力是有限资源。上下文从 5k 涨到 100k,注意力就得摊薄到 20 倍的 token 上。学术界有个著名现象叫“Lost in the Middle”:模型对开头和结尾的信息记得牢,对中间的信息经常视而不见。你在会话第 20 轮定的关键约束,到第 60 轮时正好埋在"中间",于是被无视了。
4.2 上下文污染(Context Pollution)
会话里堆积的不只是有用信息,还有大量噪声:走过的弯路、失败的尝试、被否决的方案、几百行的报错、读了但其实没用的文件。这些垃圾不会自动清除,会一直干扰模型判断。你早就否决的方案还完整躺在上下文里,模型"看到"了,就可能重新捡起来。
4.3 自相矛盾的信息累积
你在会话中改主意是常事:“用方案 A"→ 三轮后"算了用 B”。但A 和 B 现在都在上下文里。模型面对自相矛盾的历史,行为就开始漂移、反复。
4.4 逼近上下文窗口 → 触发压缩 → 丢细节
当上下文快撑满窗口(哪怕是 1M 的大窗口),工具会自动做压缩/摘要(compaction),把前面的历史总结成一小段。总结必然有损——那个被你压缩掉的"边界条件",可能正是下一步的关键。
🧠一句话总结:模型不是变笨了,是你给它塞了太多东西,还夹带了太多矛盾和噪声。信噪比崩了,表现自然崩。
五、解决方案:把"上下文管理"当成一等工程能力
好消息:成本和智商这两个问题同源,所以同一套动作能同时解决两者。核心思想只有一句:
主动、频繁地把上下文"关小、削瘦、拆分",别让它自然膨胀。
5.1 心法(与工具无关的通用原则)
| 原则 | 做法 | 同时解决 |
|---|---|---|
| 一任务一会话 | 换个不相关的任务,就开新会话 //clear,别在老会话里续 | 💸 成本 + 🧠 质量 |
| 及时清场 | 当前子任务做完,主动清空或压缩上下文再进入下一个 | 💸 + 🧠 |
| 收窄任务边界 | 别让它一次读整个仓库/整个大文件;精确到函数、到具体文件 | 💸 + 🧠 |
| 固化约定别复述 | 项目级约定写进配置文件(见下),而不是每次在对话里重申 | 💸 + 🧠 |
| 用子代理隔离 | 把"调研 / 搜索 / 读一堆文件"这类脏活外包给 subagent,主会话只拿结论 | 💸 + 🧠 |
| 稳定前缀,别投毒 | 别在系统提示里放时间戳、随机 ID;保证可缓存前缀逐字节稳定 | 💸(保住缓存) |
为什么"开新会话"这么有效?因为它把 N² 的成本曲线一刀砍回原点:新会话从 1 份上下文重新起步,而不是背着几万 token 的历史。同时,干净的上下文 = 高信噪比 = 模型重新变聪明。遇事不决,/clear。
5.2 各家工具怎么落地
不同工具提供的"武器"不太一样,对号入座:
🟣 Claude Code(Anthropic)
/clear:清空当前上下文,开始新话题的首选。几乎是万能药。/compact:把当前长会话压缩成摘要后继续——保留连续性但有损,适合"同一任务但历史太长"。想彻底换任务还是/clear更干净。- 子代理 / Task 工具:把调研、跨文件搜索、大范围审计外包出去。子代理在自己的独立上下文里干活,只把结论回传主会话,主会话上下文因此保持精简。这是控制长任务上下文的杀手锏。
CLAUDE.md:项目级持久指令写这里(技术栈、代码风格、禁忌)。它随会话稳定注入,不用你每轮口头重申,既省 token 又稳定缓存前缀。- 缓存策略:Claude Code 已内建 prompt caching。你能做的是别让缓存失效——超过 5 分钟没动、频繁切模型都会触发昂贵重建;要连续干活就别中途长时间挂机。
🟢 Codex CLI / Codex(OpenAI)
- OpenAI 侧的prompt caching 是自动的(通常对超过约 1024 token 的前缀自动生效,无需配置),缓存命中的 input 一般按约五折计价(注意:折扣力度不同于 Anthropic 的九折,具体倍率和 TTL 请以 OpenAI 官方最新定价为准)。
- 实操心法一致:任务切换就开新会话,别在超长会话里硬续;收窄任务范围、减少无谓的大文件读取。
- 用
AGENTS.md之类的项目约定文件固化规则,减少每轮复述。
🔵 Cursor
- 善用其手动挑选上下文的能力(
@file、@symbol),精确投喂而不是让它自己漫无目的地读一大片。喂得准 = 上下文小 = 又省又准。 - 新任务开新 Chat;别把一个 Chat 当成万用垃圾桶。
- 用
.cursorrules固化项目规则。
🟠 Cline / Aider 等
- Aider的repo map(仓库地图)是个很聪明的设计:它不把整个仓库塞进去,而是给模型一份精炼的结构索引,需要时再拉具体文件——本质就是"用小上下文换大视野"。手动用
/add/drop精确控制在场文件。 - Cline里主动管理"哪些文件在上下文中",做完一段就移除不再需要的文件。
5.3 一张"什么时候该做什么"的速查表
症状 → 动作 回车后等很久才出字 / 单句话烧几万 token → 上下文太大了,/compact 压缩,或直接 /clear 开新会话 换了个不相关的新任务 → 无脑 /clear,别续老会话 它忘了早先的约定 / 改 A 坏 B / 重提被否决的方案 → 上下文腐烂了,/clear 重开;把约定固化进 CLAUDE.md / AGENTS.md 需要"读一大堆文件做调研"这种脏活 → 派 subagent 去做,主会话只接收结论 喝咖啡去了 >5 分钟回来发现变卡变贵 → 缓存过期重建了;要连续干活就别长时间挂机,或评估 1 小时 TTL 档 系统提示里有时间戳/随机ID,缓存从不命中 → 把易变内容挪到对话末尾,保持前缀逐字节稳定六、总结:上下文,是 AI 编程时代的新"内存管理"
把两个问题拧成一句话:
“又贵"和"又笨”,是上下文膨胀这一个病因的两个症状。控制住上下文,两个病一起好。
- 💸贵,是因为每轮重发全部历史,成本随轮数平方级增长;缓存能给旧历史打折,但大上下文本身仍是成本的根源,过期重建更是一刀一刀在放血。
- 🧠笨,是因为长上下文稀释注意力、堆积噪声与矛盾、触发有损压缩,信噪比崩塌。
作为工程师,过去我们精打细算 CPU、内存、带宽;在 AI 编程时代,上下文窗口(context window)就是新的稀缺资源,上下文管理就是新的"内存管理"。养成三个肌肉记忆,你的账单和效率会立刻改善:
- 一任务一会话,遇事不决
/clear。 - 精确投喂,拒绝"读整个仓库"式的偷懒。
- 脏活外包给子代理,约定固化进配置文件。
别再无脑抱怨"模型变笨了"——很多时候,不是模型的问题,是你的会话该清场了。
📌附:关键数字速记(以 Anthropic 官方 SDK 文档为准)
- 缓存读取 ≈0.1×基础 input 价(便宜 90%)
- 缓存写入 =1.25×(5 分钟 TTL)/2×(1 小时 TTL)
- 默认缓存TTL = 5 分钟,超时未交互即失效需全价重建
- 前缀任何字节变化都会让其后缓存全部失效;换模型、增删工具同理
- OpenAI 侧为自动缓存、折扣与 TTL 口径不同,以官方最新定价为准
(本文技术数据核对自 Anthropic 官方 SDK 文档;OpenAI 相关数字请以其官网最新定价页为准。)