1. 从 400 到 80:账单压缩的底层逻辑不是“少用”,而是“用对”
先把结论摆在前面:一个月把 API 账单从 400 块压到 80 块,靠的绝对不是“少写代码”或者“少问问题”,而是把每一次调用的模型选择、上下文长度、缓存命中率、任务拆分方式这四个变量重新调了一遍。很多人一看到账单高,第一反应是“我是不是用太多了”,于是开始省着用,结果效率下降、返工变多,账单没降多少,人先崩了。我踩过这个坑,后来才想明白:账单高的本质是用 Opus 干了 Sonnet 的活,用全量上下文干了增量修改的活,用重复提问干了缓存复用的活。
这篇文章适合两类人看:一类是刚上手 Claude Code、看着后台用量曲线心里发慌的开发者;另一类是已经把 Claude Code 接进日常开发流、但账单一直下不来的团队。我会把整个压缩过程拆成可复现的步骤,包括我怎么判断哪些任务该降级、上下文怎么裁剪、缓存怎么命中、以及那些看起来省不了钱但实际影响巨大的配置细节。全文基于我自己的实际操作记录,涉及参数的地方我会给出计算过程,涉及取舍的地方我会说明为什么这么选。
先给一个整体框架,让你知道这 320 块的差价是从哪几个口子省出来的:
| 优化方向 | 预估节省占比 | 核心动作 |
|---|---|---|
| 模型分级调用 | 约 45% | Opus 只留给架构决策和疑难排查 |
| 上下文裁剪 | 约 25% | 用精准文件引用替代全仓库投喂 |
| 缓存命中优化 | 约 20% | 稳定前缀 + 合理会话复用 |
| 任务拆分与批处理 | 约 10% | 合并同类小请求,减少往返次数 |
这个比例是我自己账单明细倒推出来的,不同项目结构会有浮动,但量级上不会差太远。下面逐个展开。
2. 模型分级:Opus 和 Sonnet 的价差到底值不值得省
2.1 先算清楚 Opus 和 Sonnet 的成本差距
很多人对“Opus 贵”只有一个模糊印象,但具体贵多少、什么任务值得用,心里没数。我拿自己的实际用量算过一笔账:在同等输入输出 token 量的前提下,Opus 的单价比 Sonnet 高出数倍,具体倍数随官方定价调整会变,但“贵一个量级”这个判断是稳的。这意味着如果你把 70% 的 Opus 调用换成 Sonnet,账单直接砍掉一大半。
但问题来了:Sonnet 能不能干 Opus 的活?我的实测结论是——大部分日常编码任务,Sonnet 完全够用,甚至在某些场景下响应更快、更少跑偏。Opus 的优势集中在需要深度推理的地方,比如跨模块的架构重构、复杂 bug 的根因分析、涉及多文件依赖关系的改动方案设计。而像“给这个函数加个参数校验”“把这段循环改成 map”“补一个单元测试”这类任务,Sonnet 做得又快又准。
我给自己定了一条硬规则,写在项目根目录的说明文件里,每次开新会话先看一眼:
- 必须用 Opus 的场景:涉及三个以上文件的联动改动、需要理解业务语义才能做的重构、报错信息指向不明确需要推理的排查。
- 默认用 Sonnet 的场景:单文件内的功能实现、代码解释、格式转换、测试用例生成、文档撰写。
- 可以用更轻量模型的场景:简单的字符串处理、正则编写、命名建议。
2.2 怎么在 Claude Code 里切换模型而不打断心流
切换模型这件事,最怕的是打断思路。我试过几种方式,最后固定下来的做法是:在会话开始时根据任务类型选好模型,中途尽量不切。因为频繁切换会导致上下文重建,反而增加成本。
具体操作上,Claude Code 支持在启动时指定模型,也支持在会话中通过命令切换。我的习惯是开两个终端窗口,一个挂着 Opus 用于处理疑难问题,一个挂着 Sonnet 用于日常编码。遇到需要 Opus 的问题,把相关代码片段复制过去问,拿到方案后回到 Sonnet 窗口执行。这样做的额外好处是:Opus 窗口的上下文保持精简,只装真正需要深度推理的内容,单次调用成本也可控。
这里有个细节值得说:不要因为“反正 Opus 更聪明”就把所有问题都丢给它。我早期就是这么干的,结果 Opus 窗口的上下文越滚越大,每次调用都在为历史对话付费,账单里 Opus 的占比高得离谱。后来我把 Opus 窗口当成“专家咨询窗口”,问完就清,成本立刻下来了。
2.3 一个真实的降级案例
举个具体例子。我当时在做一个数据导出功能,需要把数据库查询结果转成多种格式。最初我用 Opus 来做,它确实一次就给了一个很完整的方案,但那个方案里包含了很多我用不上的抽象层。后来我换成 Sonnet,直接说“给我一个函数,输入是查询结果数组,输出是 CSV 字符串,不要额外抽象”,Sonnet 给的代码更短、更贴合需求,而且我少花了好几轮对话去砍掉多余设计。
这个案例让我意识到:Opus 的“过度设计倾向”在某些场景下反而是成本——不仅是调用成本,还有你阅读和删减它输出的时间成本。Sonnet 更“听话”,你说什么它做什么,对于目标明确的任务反而更高效。
3. 上下文裁剪:你投喂的每一行代码都在计费
3.1 全仓库投喂是最贵的坏习惯
我见过不少人用 Claude Code 的方式是:打开项目,直接让它“读一下整个项目然后帮我改某个功能”。这个操作在账单上的体现就是——输入 token 爆炸。一个中等规模的仓库,几万行代码,全量读进去,单次调用的输入成本就够你喝一壶的。而且更糟的是,这些代码里 90% 跟当前任务无关,它们不仅花钱,还会稀释模型的注意力,导致输出质量下降。
我自己的做法是:永远只给模型看它真正需要的文件。Claude Code 支持通过文件路径引用让模型读取特定文件,而不是整个目录。比如我要改用户认证模块,我就只引用认证相关的几个文件,加上必要的类型定义文件,其他一概不给。
这里有个判断标准:如果一个文件的内容,你在向同事解释这个任务时都不会提到,那就不要给模型看。这个标准帮我砍掉了大量无效上下文。
3.2 用“任务边界”倒推需要哪些文件
具体怎么操作?我的流程是这样的:
- 先明确这次任务要改哪个函数或哪个类。
- 找到这个函数所在的文件。
- 看它依赖了哪些类型定义、工具函数、常量配置。
- 只把这些文件加入上下文。
举个例子,我要给一个订单处理函数加折扣逻辑。这个函数在order_service文件里,它用到了一个DiscountRule类型和一个calculate_tax工具函数。那么我只需要引用这三个文件,而不是整个services目录。这样上下文从可能的上万 token 压缩到几百 token,单次调用成本直接降一个数量级。
提示:Claude Code 在读取文件时,如果文件很大,它可能会截断或分段处理。主动控制引用范围,比让它自己判断更可靠,也更省钱。
3.3 长会话的上下文膨胀问题
另一个容易被忽视的成本来源是长会话。很多人习惯在一个会话里连续问几十个问题,觉得这样“有上下文连贯性”。但实际上,每一轮新提问都会把之前所有对话历史重新作为输入发出去,token 量是累加的。一个开了两小时的会话,到后面每问一句,输入成本可能是第一句的几十倍。
我的应对策略是:按任务切分会话,而不是按时间。一个任务做完,如果下一个任务跟当前上下文无关,就开新会话。如果有关联但关联不大,我会手动总结一下关键信息,粘贴到新会话里,而不是让旧会话一直挂着。
这个习惯养成后,我的平均单次调用输入 token 量下降了大概六成。省下来的都是真金白银。
4. 缓存机制:稳定前缀是省钱的关键杠杆
4.1 缓存到底省的是什么钱
Claude 的 API 有一个提示缓存机制:如果你连续多次调用的输入前缀是相同的,那么这部分前缀在后续调用中可以以更低的价格计费。这个机制对于 Claude Code 这种“反复在同一个项目上工作”的场景特别有用,因为你的系统提示、项目说明、常用文件内容往往是稳定的。
但缓存要命中是有条件的:前缀必须完全一致,包括空格和换行。我早期没注意这一点,每次开新会话时项目说明的措辞都略有不同,结果缓存一直不命中,白白多花了很多钱。
4.2 怎么构造稳定的缓存前缀
我的做法是把所有稳定不变的内容固化下来,放在每次会话开头,一字不改:
- 项目技术栈说明(语言、框架、版本)
- 代码风格约定(命名规范、缩进、注释语言)
- 常用工具函数的签名说明
- 当前项目的目录结构概览
这些内容我写在一个固定的文本文件里,每次开新会话第一件事就是把它粘贴进去。因为内容完全一致,缓存命中率非常高。实测下来,这部分内容的计费能降到原价的很小一部分。
4.3 缓存失效的常见原因和规避
缓存失效最常见的原因有三个:一是前缀内容被无意修改(比如你手动改了项目说明里的一个错别字);二是会话中途插入了新的系统级指令,打乱了前缀结构;三是不同会话之间用了不同的模型,缓存不跨模型共享。
我的规避方法是:把稳定前缀和动态内容严格分开。前缀部分只放那些整个项目周期都不会变的内容,动态内容(比如当前任务描述、要改的文件)放在前缀之后。这样即使动态内容每次不同,前缀部分的缓存依然有效。
还有一个细节:不要在会话中途修改前缀部分的内容。如果你发现项目说明写错了,宁可开一个新会话重新来,也不要在当前会话里改。因为一旦修改,后续所有调用的缓存都会失效,反而更贵。
5. 任务拆分与批处理:减少往返次数就是减少开销
5.1 为什么“一次问清楚”比“来回追问”便宜
每一次 API 调用都有固定的开销,包括系统提示的处理、上下文的加载等。如果你把一个任务拆成十次小提问,每次都要重新加载一遍上下文,总成本远高于一次把需求说清楚。我早期习惯是“想到一点问一点”,结果一个功能改下来问了十几轮,账单里全是零碎的调用。
后来我改成:在提问之前,先把需求在脑子里过一遍,把所有要改的点、要遵守的约束、期望的输出格式一次性写清楚。这样通常一轮就能拿到可用的结果,最多两轮微调。调用次数少了,总成本自然下来。
5.2 批量处理同类小任务
有些任务是重复性的,比如给十个函数分别加日志、给五个文件分别补类型注解。这种任务如果一个个问,就是十次调用。我的做法是:把同类任务合并成一个请求,让模型一次性处理多个目标。
比如我会这样写:“以下五个函数需要加日志,日志格式统一为[模块名] 函数名 参数,请分别给出修改后的代码。”然后把五个函数的代码一起贴进去。这样一次调用就搞定,虽然单次输入变长了,但总调用次数从五次变成一次,综合成本更低。
5.3 什么时候不该合并
但合并也不是万能的。如果任务之间逻辑差异大,合并会导致模型混淆,输出质量下降,反而要花更多轮次去修正。我的判断标准是:如果这些任务共享同一套规则和上下文,就合并;如果每个任务都有独特的约束,就分开。
举个例子,给五个函数加同一种日志,合并没问题。但如果五个函数分别要做不同的业务逻辑改动,那还是分开问更稳妥。省钱的目的是为了更高效地工作,不是为了省钱而牺牲质量。
6. 那些看起来不起眼但实际很费钱的配置细节
6.1 输出长度控制
模型的输出也是计费的,而且输出通常比输入贵。很多人没意识到,自己账单里有一部分是花在了“让模型说废话”上。比如你问“这个函数有什么问题”,模型可能先给你一段总结,再列几个点,最后再给建议,洋洋洒洒几百字,其中一半是客套话。
我的做法是在提问时明确约束输出:“直接给修改后的代码,不要解释”“只列出问题点,每条不超过一行”“不要总结,不要客套”。这些约束能显著压缩输出长度。实测下来,同样的任务,加了输出约束后,输出 token 量能减少三到四成。
6.2 避免让模型重复你已经知道的信息
另一个浪费是让模型复述你已经提供的内容。比如你贴了一段代码问“这段代码有什么问题”,模型可能会先把你的代码复述一遍再分析。这个复述就是纯浪费。我会在提问时加一句“不要复述我给的代码”,直接砍掉这部分输出。
6.3 会话超时与自动清理
Claude Code 的会话如果长时间挂着不用,再次唤醒时可能会重新加载上下文。我的习惯是:任务做完就关掉会话,不要留着。下次需要时重新开,用固化好的前缀重建上下文,成本反而更低。留着旧会话看似方便,实际上是在为“随时可能用到的历史上下文”持续付费。
7. 我的日常操作清单与踩坑记录
7.1 每天开工前的三分钟准备
我现在每天开始用 Claude Code 之前,会花三分钟做几件事:
- 确认今天的任务类型,决定主用 Opus 还是 Sonnet。
- 把今天可能用到的稳定前缀内容准备好(项目说明、风格约定)。
- 把要改的文件路径列出来,避免临时翻找导致上下文混乱。
这三分钟的准备,换来的是全天调用效率的提升和账单的下降。听起来很琐碎,但坚持下来效果很明显。
7.2 我踩过的三个大坑
第一个坑:用 Opus 做代码格式化。早期我图省事,把一段乱糟糟的代码丢给 Opus 让它整理格式。后来发现这种任务 Sonnet 甚至更轻量的模型都能做,用 Opus 纯属浪费。这个坑让我损失了不少钱。
第二个坑:会话不关,上下文越滚越大。有一个会话我挂了一整天,到后面每问一句都感觉响应变慢、账单飙升。后来看明细才发现,那个会话的输入 token 量是正常会话的十几倍。
第三个坑:缓存前缀被无意破坏。有一次我在项目说明里改了一个版本号,结果后面所有调用的缓存全部失效,那一天的账单比平时高出一截。从那以后,我把前缀内容冻结,要改就开新会话。
7.3 一个帮我省最多钱的小习惯
如果只让我推荐一个习惯,那就是:每次提问前,先问自己“这个任务真的需要模型吗”。有些问题我自己查文档两分钟就能解决,丢给模型反而要等响应、要花 token。把模型用在真正需要它的地方,比任何技巧都省钱。
8. 从 400 到 80 之后,我的工作方式发生了什么变化
账单降下来之后,最大的变化不是省钱本身,而是我用模型的姿势变了。以前是“有问题就丢给模型”,现在是“先判断问题类型,再决定用哪个模型、给多少上下文、怎么问”。这个判断过程只需要几秒钟,但它带来的效率提升和成本下降是持续的。
我现在每个月的 API 支出稳定在 80 块左右,做的事情却比之前 400 块的时候更多。因为省下来的钱让我可以更放心地在关键任务上使用 Opus,而日常任务用 Sonnet 快速推进。这种“好钢用在刀刃上”的分配方式,才是账单压缩的真正意义。
如果你现在账单偏高,我建议你先别急着减少使用量,而是花一个下午把过去一周的调用记录翻出来,看看钱到底花在了哪里。大概率你会发现,问题不在“用得多”,而在“用得粗”。把模型分级、上下文裁剪、缓存命中这三件事做好,账单自然就下来了。