如何降低 Claude API 账单:实用 token 成本指南
如果你不断发送同一个庞大的系统提示、三条先前消息和完整的工具 schema,并且在只需要 120 个词时生成了包含 2,000 个 token 的回答,那么一次“总结这张工单”的调用,就可能悄然变成按 20,000 个 token 计费的账单。在实践中,团队往往因此把问题归咎于模型,而真正的问题其实在于请求结构。
如果你想降低 Claude API 账单,最大的收益通常来自严谨的工程实践,而不是对模型的玄学揣测:复用稳定的前缀、大幅精简上下文、选择能胜任任务的最小模型、限制输出,并在请求层面衡量浪费。目标很简单:为有用的 token 付费,而不是为意外产生的 token 买单。
理解 token 预算的思维模型
每个请求都有两项成本驱动因素:
- 输入词元:系统提示、用户消息、对话历史、工具定义、检索到的文档,以及未命中缓存时仍会计入用量的缓存前缀。
- 输出 token 数:模型的回复,包括不必要的冗长内容和重试产生的输出。
一个实用的估算公式是:
request_cost ≈ input_tokens × input_rate + output_tokens × output_rate
这听起来显而易见,但它会改变你排查支出的方式。如果平均每个请求的输出成本很低,而输入成本很高,那么从系统提示中删减 400 个 token,可能比要求模型回答得更简洁更有效。
从模型选择入手
并非每项任务都需要能力最强的模型。在实际系统中,模型选择往往是成本最低的优化方式。
| 任务类型 | 推荐默认选择 | 有效的原因 | 不适用的情况 |
|---|---|---|---|
| 快速分类、提取、路由 | Haiku | 延迟低、费用少,推理能力通常足够 | 多步骤分析、杂乱的文档 |
| 常规编程辅助、摘要、转换 | Sonnet | 在质量与成本之间取得良好平衡 | 长期规划、存在歧义的推理 |
| 高难度推理、深度综合分析、容易出错的指令 | Opus | 最适合失败代价高的场景 | 结构重复的常规任务 |
| 上下文庞大且高度依赖检索的工作 | 需要时选择支持更大上下文的模型 | 降低分块处理的复杂度 | 仅在任务确实需要时使用 |
一个常见陷阱是“默认选高配”。团队往往把每条提示都发给顶级模型,因为感觉这样更稳妥。实际上,对于无法从中受益的任务,这相当于购买昂贵的保险。建立路由层通常值得投入:
- Haiku 用于快速分类、JSON 提取、日志标注和初步分诊。
- Sonnet 用于大多数智能体或开发者工具工作负载。
- Opus 仅用于确实需要更强推理能力、细致综合分析的任务,或你已衡量过失败成本的场景。
一套简单而有效的策略是:
- 对于成本低的结构化任务,先尝试 Haiku。
- 如果置信度低或输出格式不正确,则升级到 Sonnet。
- 仅对确实困难的情况升级到 Opus。
这种逐级回退链通常比每次请求都支付 Opus 费率更便宜。
大刀阔斧地精简系统提示
系统提示中的 token 浪费往往就在眼前,却容易被忽略。它会像技术债一样不断膨胀:这里加一条策略,那里加一条风格规则,再加上无人删除的五个示例。
应删除的内容
- 应用程序已经强制执行的重复指令。
- 不会改变行为的冗长“请提供帮助”类文字。
- 针对已不再重要的边缘情况的旧示例。
- 在每个请求中重复出现的策略文本。
- 用简洁的 schema 就足够时,仍然冗长的工具描述。
应保留的内容
- 不可妥协的行为约束。
- 输出格式规则。
- 对安全至关重要的指令。
- 能显著提高可靠性的最少量示例。
在实践中,我见过团队从重复使用的前缀中删去数百甚至数千个 token,而模型质量并未改变。诀窍是像对待生产代码一样对待系统提示:删除无效文本、去除重复规则,只保留能影响行为的内容。
更好的做法是用结构化表达代替散文式描述:
{
"style": "concise",
"output": "json",
"must_include": ["root_cause", "next_steps"],
"must_avoid": ["speculation", "apologies"]
}
这比三段叙述式指令更容易理解和分析。
为稳定的前缀使用提示缓存
如果你的技术栈支持提示缓存,就将它用于跨请求重复出现的内容:系统提示、工具 schema、少样本示例和较长的策略文本块。
关键并不是“缓存免费”。它并不免费。真正的收益是,你不再需要在每次调用时为同一个前缀重复支付全价。
适合缓存的内容
- 整个产品通用的系统提示
- 大型函数或工具定义
- 重复使用的检索指令
- 用于格式或风格的静态示例
- 很少变化的智能体基础框架
不适合缓存的内容
- 每个请求特有的用户上下文
- 新检索到的文档
- 快速变化的指令
- 特定会话的草稿区内容
常见错误是把变化频繁的内容放进前缀,然后疑惑为什么缓存命中率低。要让缓存发挥价值,应保持缓存部分稳定,并将请求特有的数据放在其后。
请求结构示例:
{
"system": "Stable application prompt + tool definitions + output contract",
"messages": [
{ "role": "user", "content": "New ticket text here" }
]
}
保持稳定部分不变,才能让缓存真正发挥作用。如果每次请求的前缀都发生变化,你只是在支付缓存管理开销,却没有获得任何收益。
设置 max_tokens 切实执行
一个最容易被忽视的成本来源,是设置过高的生成输出上限。如果你将 max_tokens 设得非常大,只为“以防万一”,就容易得到冗长的回复,尤其是在模型不确定或倾向于详细回答时。
使用仍足以完成任务的最低上限。
实用范围
- 提取 / 分类:32–128 个 token
- 简短摘要:128–256 个 token
- 代码差异 / 解释:256–800 个 token
- 开放式生成:仅设为必要的上限
如果任务是“返回一个 JSON 对象”,就为它设置一个硬性上限。如果任务是“解释这个架构”,除非你确实想要一部长篇小说,否则不要给模型留下写出长篇大论的空间。
很多团队还会忘记限制重试循环。如果解析失败后,你自动要求模型在同样宽松的输出上限下重试,单次用户操作的输出费用就可能翻倍甚至增加到原来的三倍。
将小任务合并成批
当你有许多小型、相互独立且指令开销相近的任务时,批处理会很有帮助。
不要这样做:
- 50 个独立的分类请求
- 50 次重复的系统提示词
- 50 次重复的工具定义
改为这样做:
- 一个包含 50 个条目的请求
- 一个共享的指令块
- 一个精简的输出结构定义
提示词模式示例:
Classify each item into one of: bug, feature, question, billing.
Items:
1. "App crashes after login"
2. "Can you add dark mode?"
3. "How do I reset my password?"
以及响应约定:
[
{"id": 1, "label": "bug"},
{"id": 2, "label": "feature"},
{"id": 3, "label": "question"}
]
这能减少重复开销,而且通常能提高吞吐量。代价是失败的影响范围更大:如果某个条目违反了格式要求,可能需要对整批结果进行恢复处理。对于高价值任务,或面向用户且对延迟敏感的处理路径,较小的批次可能仍然更合适。
流式输出改善响应体验,而非 token 成本
流式输出非常有利于用户体验,有时也有助于控制成本,但它并不会 并不能 仅凭自身就神奇地减少计费 token 数。模型生成的内容仍然都要付费。
流式输出真正有帮助的地方在于 提前停止:
- 用户能更早看到进展。
- 应用可以在获得足够内容后取消生成。
- 你可以在失控的回答达到配置上限之前停止它。
最后一点很重要。如果你正在为下游解析器生成回答,而前 120 个 token 已经包含所需的 JSON,就不要继续收集另外 800 个 token 的解释。
在实践中,如果应用能在生成过程中作出反应,流式输出就值得采用。如果你只是把流式内容写入日志,仍然要等待完整回答,那么你能获得用户体验方面的好处,却很难显著降低成本。
衡量每次请求的成本,而不只是每月总费用
每月支出告诉你存在问题。请求级指标告诉你问题在哪里。
至少跟踪以下指标:
input_tokensoutput_tokenscache_hit_tokens如果可获取- 模型名称
- 端点 / 功能路径
- 延迟
- 重试次数
- 截断率或解析失败率
一个简单的日志记录数据体可能如下所示:
usage = response["usage"]
record = {
"model": response["model"],
"input_tokens": usage["input_tokens"],
"output_tokens": usage["output_tokens"],
"latency_ms": latency_ms,
"cache_hit_tokens": usage.get("cache_read_input_tokens", 0),
"request_type": "ticket_summary",
}
print(record)
然后集中计算成本:
def estimate_cost(input_tokens, output_tokens, input_rate, output_rate):
return (input_tokens * input_rate) + (output_tokens * output_rate)
具体费率取决于你的提供商和模型,但工作流程保持不变。一旦能按成本对请求进行排序,导致高费用的因素通常就会一目了然:
- 一个带有巨大隐藏前缀的“小”提示词
- 每轮都会重新发送完整文档的工具调用
- 生成输出上限是任务所需的 10x
- 悄悄让用量翻倍的重试循环
- 本该使用 Haiku,却始终使用 Opus 的路由
避免隐性浪费
大多数 token 浪费都很不起眼,因此往往能逃过代码审查。
常见的浪费来源
- 每轮都重新发送同样的冗长对话历史
- 只需要差异内容时,却包含完整源文件
- 结构化的 JSON 已经足够,却要求生成文字描述
- 向机器端返回冗长解释
- 传入比实际任务还庞大的工具结构定义
- 让自动重试重新执行同一个昂贵的提示词
- 将日志或内部备注保留在模型上下文中
一个特别棘手的陷阱是“出于好意扩充上下文”。检索系统经常获取过多内容,只因为有人想求稳。如果模型只需要最相关的三个段落,就不要仅仅因为分块层让传入整篇文档变得容易,便把整篇文档都交给它。
还有一种情况:如果你在模型外再加一层提示词,要求它“简洁一些”,你可能只是增加了 token,试图解决一个本应通过更严格的输出结构定义来解决的冗长问题。
实用的请求设计
下面这种模式适用于许多生产环境任务:
request = {
"model": "claude-sonnet-4.6",
"max_tokens": 180,
"system": "Extract the root cause and next action. Return strict JSON.",
"messages": [
{
"role": "user",
"content": "Investigate this incident summary: ... "
}
]
}
这种设计有效的原因:
- 所选模型足以胜任中等难度的推理。
- 输出上限能限制失控的冗长输出。
- 系统提示词简短且具体。
- 输出格式便于机器处理。
- 用户数据体仅包含任务所需的输入。
如果需要更多上下文,就有目的地添加。不要让上下文在无意中越积越多。
哪些措施真正影响账单
如果要对收益最大的措施进行排序,我会这样排:
- 为简单任务选择更便宜的模型
- 精简臃肿的提示词
- 限制
max_tokens严格一些 - 对稳定的前缀使用提示词缓存
- 将小型独立任务合并成批
- 衡量请求级用量
- 防止重试循环让支出翻倍
这个顺序很重要。团队往往在解决显而易见的问题之前,就开始尝试复杂的优化:他们只是过于频繁地向最昂贵的模型提出过多要求,还附带了过多上下文。
实践要点
- 使用 Haiku 用于简单的提取和路由任务, Sonnet 用于大多数产品相关工作,而 Opus 仅在任务确有需要时使用。
- 将这场 系统提示词 视为一个成本中心;删除重复的文字,只保留会改变模型行为的指令。
- 启用 提示词缓存 用于政策、工具结构定义和少样本示例等稳定的前缀。
- 设置
max_tokens设为满足实际需要的最低上限,并针对每项任务重新评估。 - 批量处理 小型独立任务,尤其是在指令开销占主导时。
- 跟踪 输入 token、输出 token、缓存命中、重试和延迟 以每次请求为单位。
- 留意 隐性浪费:重复的历史记录、过量的检索内容、冗长的输出以及自动重试循环。
如果你愿意,我可以将这篇内容扩展为一篇配套文章,提供一个具体的成本仪表盘示例,以及一些 Haiku/Sonnet/Opus 的路由规则。
一个 API 密钥即可使用 Claude Opus 5.5、Sonnet 5、Haiku 4.5 和 Fable 5.1,以及 GPT-6 个模型。按量付费,无需订阅。
获取 API 密钥 →