如何降低大模型调用带来的成本
如何降低大模型调用带来的成本
降低大模型调用主要方法是利用好Prompt Caching,有时候开了缓存之后命中率长期停在 20% 上下。所以我们要注意以下内容
缓存的是 KV state,不是"答案"
传统 KV 缓存(Redis 那种)和 Prompt Caching 名字一样,语义完全不同。
Anthropic 的 Prompt Caching 缓存的是 Transformer 推理时 attention 层 prefill 阶段算出来的 KV 张量——下次请求前缀完全一致,模型直接复用这套张量,跳过 prefill。Anthropic 文档里给了 4 个断点、最小 1024 token、TTL 默认 5 分钟(命中频率够高可延到 1 小时)(Anthropic Prompt Caching)。
OpenAI 这边更省心——超过 1024 token 的前缀自动缓存,128 token 粒度匹配,TTL 大约 5-10 分钟(OpenAI Prompt Caching 指南)。
关键在"前缀完全一致"五个字。不是语义相似,是字节级精确匹配。一个空格、一个时间戳、一个用户 ID 差异,全部 miss。
前缀按物理顺序匹配,不看语义
前缀按物理位置匹配,不管两段 prompt 看起来多像。
工程报告里有团队公开过类似观察:花几个月把命中率从不到 10% 优化到 70%+,整段时间下来 token 成本直接砍掉近 60%。最常见的"破功"操作就三类:
写法 1:system prompt 里塞时间戳
# 永远 misssystem=f"当前时间:{datetime.now()}。你是一个助手..."# 时间放到 user message 末尾system="你是一个助手..."user=f"[当前时间:{datetime.now()}]\n{question}"写法 2:system prompt 顶部放用户 ID / 请求 ID
# 每个用户前缀都不同system=f"用户ID:{user_id}..."# 用户信息后置user=f"[用户:{user_name}]\n{question}"写法 3:动态生成工具定义——Agent 场景特别常见。工具集不变时把 JSON 序列化结果固定下来(sort_keys=True),别每次随机顺序重排。
动态内容不能塞在 system prompt 中间
Agent 场景下这个最难处理。
Agent 的 working memory 每一步都在变。按"system prompt + working memory + 当前消息"这种顺序拼 prompt 的话,working memory 每次动一点,前面的 system prompt 缓存就全废了——system prompt 自己一个字节没改也得从头算。
一个叫 “Relocation Trick” 的简单解法:把 working memory 从 system prompt 末尾移到 user message 末尾。只改一个位置,命中率能从 20% 以下跳到 70%+ 这个量级。
Agent 系统通常按三段拆:
- 断点 1:静态系统提示(TTL 拉满 ~1 小时)
- 断点 2:最近 N 轮对话历史(TTL 5 分钟)
- 断点 3:工具定义(工具集不变时极稳定)
working memory 和当前用户消息放最末尾,不打断点——让它们独立失效,不污染前面的缓存段。
那到底能省多少、什么时候反而不划算
前面的前提都踩对,命中率能稳在 70% 以上。一个朴素的判断:不到 50% 说明 prompt 结构有问题;70% 以上算健康;85% 以上说明前缀纪律做得很到位。
定价层面,拿 Anthropic Claude Sonnet 4.5 举例:缓存读取 0.30 / 百万 token(标准输入价 3.00),首次写入 $3.75,比标准输入贵 25%。想回本至少需要 2 次以上复用——单个 prompt 前缀被使用 2 次以上,缓存就是合算的(Anthropic 定价)。
OpenAI 这边自动给 50% 折扣,没有写入溢价。两种模式各有取舍:Anthropic 折扣更深但要手动打cache_control标签,OpenAI 折扣浅但零配置。
上线后建议盯这几个数
光看 token 账单看不出缓存效果,建议看这五个指标:
cache_creation_tokens(写入缓存的 token 数)cache_read_tokens(从缓存读取的 token 数)uncached_tokens(完全没命中的 token 数)hit_rate(命中 token / 总 prompt token)—— 核心指标TTFT(首 token 时间)—— 缓存命中能省 prefill,TTFT 会显著下降
基线参考:命中率 >70%,低于这个值基本就是 prompt 结构有问题。对于自检我们需要考虑以下几点。
- system prompt 里有没有时间戳或用户 ID?
- 工具定义是不是每次动态生成?
- system prompt 凑没凑够 1024 token?不够就主动凑,否则打不上断点
- 监控里有没有看
cache_read_tokens/cache_creation_tokens? - Agent 系统的 working memory 放在 prefix 中间还是末尾?
