本页目录
成本、性能与可靠性
把 LLM 接进生产,绕不开三件事:账单(token 怎么省)、延迟(怎么不卡)、稳定(限流和错误怎么扛)。它们散落在前几篇里,这篇收口成一张工程清单。
概述
原型跑通到上线,中间隔着工程化。Demo 里一次 messages.create 拿到结果就行;生产里要回答:这一万次调用要花多少钱?用户等几秒?撞了 429 怎么办?重试会不会把一封邮件发两遍?
这些问题的答案散在前几篇——prompt caching、流式与 thinking、usage 字段、按能力选模型。这一篇把它们按成本 / 性能 / 可靠性三条线收口,作为上线前的核对清单。
成本:token 是唯一计费单位
账单 = input token × 单价 + output token × 单价(output 通常贵 5×)。省钱的杠杆按收益排序:
1. prompt caching —— 最大的杠杆
多轮和 agent 循环里前缀高度重复。命中缓存的部分按 ~0.1x 计费(见 上下文工程)。算笔账(写入 5 分钟 TTL 是 1.25x):
- 不缓存:每次 1.0x。
- 缓存:首次写 1.25x,之后每次读 0.1x。两次就回本(1.25 + 0.1 = 1.35 < 2.0)。1 小时 TTL 写入 2x,需三次回本。
前提是前缀逐字节稳定——别在 system 插 now()/UUID、别中途改工具集或换模型,否则缓存静默失效。验证看 usage.cache_read_input_tokens,长期为 0 就是有"静默失效器"。
2. 选对模型
不是所有任务都要顶配。用 Models API 查能力、按成本分层:简单分类/抽取走便宜模型,复杂推理/agent 走 Opus。多 agent 场景把子任务派给便宜模型(但别在同一循环里换模型毁缓存,另起 subagent,见 多 Agent 编排)。
3. 控输出与思考
output 比 input 贵。max_tokens 给足以防截断,但别无脑拉满;用 effort 调思考深度(见 推理与 thinking),effort 越低 token 越省——简单任务别反射式拉 xhigh。
4. 批处理 —— 非实时任务半价
不要求即时返回的活(离线分析、批量分类、建索引)走 Batches API,所有 token 5 折:
=
# 轮询 batches.retrieve(id).processing_status 直到 "ended"(多在 1h 内, 上限 24h)
结果乱序返回——必须按 custom_id 对号,绝不能靠顺序。 这与下文"绝不靠顺序归因"是同一条铁律。
估算先行
发请求前能用 count_tokens(无状态,见 Token 与采样)估 input 量、乘单价预判成本;别用 tiktoken 估 Claude,少算 15–20%。
性能:延迟从哪来,怎么压
延迟主要是 output 长度的函数(每个 token 逐个解码)+ 思考开销 + 网络。
- 流式(streaming)是默认。 长输入/长输出/大
max_tokens一律流式:首 token 就开始返回,既改善体感(TTFT),又避开非流式请求的 HTTP 超时(SDK 对大max_tokens的非流式请求会直接拒绝,因为可能超 10 分钟把连接拖断)。要完整结果用.get_final_message()/.finalMessage()。 - effort 与回合数非线性。 agentic 任务上高 effort 常减少回合、反而更快更省;别假设"低 effort 一定快"。在自己的 eval 集上扫档(见 评估与可观测)。
- 缓存也是延迟杠杆。 命中缓存的前缀跳过重算,首请求慢可用 预热(启动时发一个
max_tokens: 0请求把前缀写进缓存)消掉。 - 并行有缓存时序坑。 N 个相同前缀的请求同时发,谁也读不到别人还在写的缓存,全付全价;先发 1 个、等它开始流式、再发其余 N−1,后面的就能命中。
可靠性:限流、重试、幂等
错误码与该不该重试
| 码 | 含义 | 可重试 |
|---|---|---|
| 400 | 请求非法(参数/格式) | ❌ 改请求 |
| 401 / 403 | 认证/权限 | ❌ |
| 404 | 模型 ID 错或端点错 | ❌ |
| 429 | 限流(RPM/TPM/TPD 超额) | ✅ 退避后重试 |
| 500 / 529 | 服务端错/过载 | ✅ 退避后重试 |
铁律:4xx(除 429)不要重试——同样的请求重发还是错。429/5xx 才退避重试。
退避与 SDK 自带重试
429 响应带 retry-after 头(等多少秒)。SDK 默认已对 408/409/429/5xx 做指数退避重试(max_retries=2)——多数情况无需自己写。只有要更激进/更克制时才自定义:指数退避 + 抖动(jitter),设上限。
超时也会被重试,所以最坏墙钟时间可达
timeout × (max_retries+1),设timeout时把这点算进去。
幂等:重试不能把副作用做两遍
退避重试遇上有副作用的工具(发邮件、扣款、git push)是隐患:第一次其实成功了只是响应超时,重试就发了两封。对策落在宿主侧,不在模型侧:
- 危险/不可逆动作走 human-in-the-loop 确认(见 Agent 循环)。
- 副作用操作带幂等键:同一逻辑动作用同一 key,服务端去重。
- 把"决定做"和"真去做"分开:模型产出意图,宿主校验+幂等执行。
归因:并发/批量结果绝不靠顺序
并发请求、Batches 结果都可能乱序返回。用 custom_id / trace id 把结果对回请求(见 评估与可观测),绝不靠到达顺序——这是批量场景最常见的串号 bug。
最佳实践
- prompt caching 先上,前缀焊死。 稳定前缀放前、动态后置,两次调用即回本;盯
cache_read_input_tokens验证命中。 - 按成本分层选模型。 简单任务便宜模型、复杂走 Opus;Models API 查能力,别猜。
- 非实时任务走 Batches,半价。 结果按
custom_id对号,绝不靠顺序。 - 长输入/输出一律流式。 改善 TTFT + 避开非流式 HTTP 超时;完整结果用
get_final_message。 - 重试只给 429/5xx,4xx 不重试。 优先用 SDK 自带退避,别重造轮子。
- 有副作用的动作要幂等 + 人工确认。 退避重试 × 副作用 = 重复执行,用幂等键 + human-in-the-loop 兜。
- 成本/延迟进监控。
usage三字段、stop_reason分布、缓存命中率上仪表盘(见 评估与可观测)。
权衡与失败模式
- 缓存静默失效:system 插时间戳/中途换模型,
cache_read长期 0、成本翻几倍 → 焊死前缀,逐字节 diff 排查。 - 无脑顶配模型:简单任务也用 Opus +
max,贵且慢 → 按任务分层,扫 effort。 - 大
max_tokens非流式:HTTP 超时、连接被拖断 → 流式 +get_final_message。 - 4xx 也重试:同样请求重发还是错,白烧配额 → 只重试 429/5xx。
- 重试踩副作用:超时重发把邮件发两遍 → 幂等键 + 人工确认危险动作。
- 靠顺序归因:Batches/并发乱序导致串号 → 一律
custom_id/trace id 对号。 - 用
tiktoken估 Claude 成本:低估 15–20% →count_tokens。
参考
- Anthropic 官方文档: Prompt Caching、Batch Processing、Rate Limits、Errors、Streaming、Models API、Token Counting(platform.claude.com,实现前以官方为准)
- 关联: 上下文工程、评估与可观测、Agent 循环与工具、多 Agent 编排
Keywords: cost optimization, token 计费, prompt caching 经济学, cache_read_input_tokens, Batches API, custom_id, 乱序归因, 50% 折扣, count_tokens, 选模型, Models API, effort, streaming, TTFT, HTTP timeout, 缓存预热, max_tokens 0, rate limit, 429, retry-after, 指数退避, exponential backoff, jitter, max_retries, 幂等, idempotency, human-in-the-loop, 错误码, 4xx 不重试