如果你也是被 Gemini API 账单吓一跳的那种人,这篇文章就是写给你的。我在一个模拟项目X里接入了 Gemini API,最初只是做点文本分类和摘要,结果月底看到消耗时直接愣住——Token 像流水一样哗哗往外走,费用肉眼可见地涨。后来我花了两周时间专门做用量监控和成本优化,把同样的业务量压到了原先三分之一左右的成本。这里把整套思路和实操记录整理出来,从成本构成、监控体系到优化手段一次讲透,适合所有正在用或准备用 Gemini API 做应用的开发者。
先交代一下背景,项目本身是模拟项目X,主要场景是长文档问答、信息抽取和批量内容打标,日均请求量不算大,但单次请求上下文偏长,Prompt 动不动就几千甚至上万 token。这种“低频长文本”的调用方式其实是成本失控的重灾区,因为你的注意力全放在单次调用的效果上,对账单数字缺少感知。真正开始治理之后我才发现,Gemini API 的费用并不是无规律乱涨,它完全是可预测、可监控、可压缩的,关键是你有没有把对应机制用起来。
1. 先搞清楚钱花在哪:Gemini API 的成本构成拆解
1.1 从按 Token 计费说起:输入、输出为什么单价不一样
Gemini API 的计费逻辑和大多数 LLM API 类似,按 Token 计费,Token 可以理解为模型处理文本的最小单位,英文里一个单词大约对应 1 到 2 个 Token,中文里一个汉字通常要占 1 到 2 个 Token。这里有个反直觉的点:API 的输入 token 和输出 token 单价往往不一样,输出通常比输入贵不少。拿某代 Flash 模型举例,输入部分大概在 0.075 美元/百万 token,输出部分大概在 0.30 美元/百万 token,价格会随官方调整,具体以官方定价页为准,但“输出更贵”这个规律是长期存在的。
为什么会这样?模型处理输入时做的是一次性推理准备,而生成输出时是一步步自回归采样,每生成一个 token 都要做一次完整的 forward 计算,计算量截然不同。从开发者的角度说,这个差异意味着优化输出 token 数的收益远大于优化输入 token 数。我见过很多团队死抠 Prompt 里的措辞来减少几百个输入 token,但回答里让模型重复了一整段原文,多花几千个输出 token,这种优化方向就反了。正确做法是先把输出约束住,再去压缩输入。
另一个容易被忽略的点是,系统指令也会计入输入 token。很多人以为 system prompt 是免费的,但它在每次请求里都会跟着用户消息一起发给模型,按输入价格收费。换句话说,你那条写得巨细无遗的提示词,实际上是在为每一条请求付钱。后面聊 Prompt 优化时我得再强调一次,这里先记住一个原则:凡是每次请求都会带的文本,都属于成本基数,越精简越好。
1.2 上下文越长,成本越离谱:隐形开销藏在 Prompt 里
如果你做的是长文档场景,成本大头几乎全在输入 token。以模拟项目X为例,最初版本把整份 PDF 转出的文本直接拼进 Prompt,一份文档动辄两三万 token,加上问题、历史对话,单次调用输入接近 3 万 token。按百万 token 单价折算,一次调用的输入成本不算吓人,但当你每天跑几百次、连续跑一个月,这就是一笔可观的固定支出。
更隐蔽的开销是多次对话时的上下文累积。如果你用 Gemini API 做多轮 Agent 或 Chatbot,每轮对话都携带全部历史消息,Token 会随轮数线性甚至超线性增长。假设第一轮上下文 1000 token,第二轮 2000,第三轮 4000,到第十轮可能已经上万。你只是多聊了几句,账单却悄悄上了好几个台阶。这里没有玄学,就是因为你发送的输入文本变长了,模型必须要处理这些文本。
所以做长文本场景,第一件事就是把“输入内容”的边界划清楚。哪些内容必须一次全量进入模型,哪些可以检索后只拼片段,哪些可以交给缓存机制复用,这些是成本优化的基本盘。我自己的经验是,先按业务场景列一张输入内容清单,再逐项判断是否真的需要参与计算。大多数情况下,全量塞入模型是“最懒”的实现方式,但绝不是“最省”的实现方式。
1.3 模型选型决定费用下限:Flash、Pro、Ultra 的定位差异
Gemini API 同一系列里通常有不同规格的模型,比如轻量级的 Flash、中高端的 Pro,以及面向复杂任务的 Ultra。三者的能力依次增强,价格也依次上涨,差一个量级都不稀奇。很多项目一开始图省事,直接默认调用最高配置模型,结果大量简单任务也用上了“大炮打蚊子”,成本自然压不住。
我的建议很简单:先按任务难度画像,再决定模型档位。如果是结构提取、分类、关键词过滤这类模式化任务,Flash 级别完全够用;如果是复杂推理、长篇幅创意写作,再考虑 Pro 甚至 Ultra。实际上我见过不止一个项目把 80% 的简单任务都跑在最高档模型上,这相当于开着跑车去小区门口取快递,体验是挺爽,但每一单都在烧油。更合理的做法是做一个模型路由层,根据任务类型动态选择模型档位,这在后面优化实战部分会具体展开。
另外要注意模型版本迭代很快,新版本往往在相同价位下提供更强能力,这相当于官方帮你“加量不加价”。所以每隔一段时间去翻一下模型列表和定价页,及时把已废弃的高价旧模型迁移到新版,是零成本但见效明显的优化。我见过有团队用了半年旧模型接口,性能和成本都吃亏,只是因为没人去关注新版本。
2. 用量监控三板斧:日志、指标、告警怎么搭
2.1 让账目透明:记录每一次请求的 Token 明细
不监控就谈不上优化。在治理成本之前,我第一件事就是给项目加上调用日志,把每次请求的模型名、输入 token 数、输出 token 数、响应耗时、状态码、调用方业务标识全部记下来。Gemini API 的响应对象里通常会返回 usage_metadata 字段,里面包含 prompt_token_count、candidates_token_count、total_token_count 这几个核心值,直接落库即可。
这里有个实操细节:不要把日志只打到本地文件就完事,要设计成可以按业务维度聚合的结构。比如模拟项目X里我加了一个 biz_type 字段,标记这次请求来自“文档摘要”还是“内容打标”,这样后续分析时就能直接回答“哪个业务消耗最多”。没有业务维度的日志只是数据,有了维度才叫资产。我见过太多人的日志里只有模型返回的原始内容,没有 token 信息,这类日志对成本分析基本没用。
日志落库之后,建议还要算一个累计成本字段。虽然日志里只有 token 数没有金额,但你可以通过车型单价做换算:估算成本等于输入 token 乘以输入单价,加上输出 token 乘以输出单价。存一个 cost_estimate 字段,每天出一个汇总报表,你的成本感知才会从“月末惊吓”变成“每日掌握”。
2.2 关键指标看哪些:RPM、TPM、延迟、缓存命中率
日志是基础,指标是提炼。当请求量上来之后,裸看日志效率太低,必须提炼成几个核心指标盯住。我做了一个简易的监控大盘,包含四类指标:
RPM(每分钟请求数):用来观察调用频率,判断并发设计是否合理。TPM(每分钟 token 数):比 RPM 更准确反映资源消耗,因为请求有大有小。P95/P99 延迟:用来感知模型响应速度,如果异常升高,往往是 Prompt 过长或模型负载抖动。缓存命中率:这个指标太重要了,只有缓存命中率高,你前面多花的缓存配置工夫才真正便宜了,后面会细说。
这四个指标不需要额外接特别复杂的监控系统,用定时任务把日志表按分钟/小时粒度聚合成指标表,存进简单的时序表,用现成的看板工具画折线图就够了。如果项目跑在云平台,也可以把日志接入云监控的日志系统,用查询语句做聚合。但不管用什么工具,核心是先把口径定下来:RPM 是成功请求数还是全部请求数,TPM 是输入加输出还是单算输入,这些口径不一致会导致团队沟通成本增加。
我建议你从项目第一天起就统一口径,TPM 默认指“输入 token 加输出 token 的总吞吐”,缓存命中率单独拆开看输入命中部分和输出不命中部分,别混在一起。模拟项目X当时就因为口径混乱,我和前端同事对“为啥费用涨了”各执一词,最后发现我们看的数据根本不是同一套。
2.3 阈值告警与预算播报:费用失控之前先动手
监控指标如果不能触发动作,就只是事后复盘工具。我比较看重的是阈值告警,设置规则非常简单:比如日消耗金额超过预算的 80% 时告警,或者单次请求 token 超过 10 万时告警,或者某业务 RPM 突增超过平时 3 倍时告警。告警可以发到即时通讯工具或邮件,关键是看到后能快速定位是哪个业务、哪条 Prompt、哪个模型在烧钱。
除了阈值告警,我还会写一个定时任务,每天早上把昨天的成本汇总发到群里,同时对比一周前的数据,给出环比变化。这种“日报式播报”的用处不是技术意义上的,而是让整个团队对成本有持续感知。很多人嘴上说重视成本,实际一个月才看一次账单,那当然什么都来不及优化。
这里要给一个比较具体的告警参数参考:对于日预算 100 美元规模的项目,我建议把“单日成本超过预算 80%”和“单日成本环比增长超过 50%”都设为告警线。而对于单次请求,如果异常 token 消耗超过正常值的 5 倍,基本可以判断是触发了未预期的长上下文分支,需要立刻检查代码。告警不必做得太复杂,先保证“能发现问题”再追求“自动修复”。
3. 成本优化的六种实战手段
3.1 Prompt 瘦身:先砍掉无意识膨胀
多数人一提到优化就想着换模型或上缓存,其实最基础的还是 Prompt 瘦身。我用一个笨办法统计了模拟项目X里所有历史 Prompt,发现里面有大量“无意识膨胀”:完整的角色背景设定、多条重复示例、冗长的输出格式说明,这些内容每次请求都带着,按输入 token 收费,但它们真的每次都起效吗?未必。
做 Prompt 瘦身时我会逐个词问:删掉这句话,模型表现会不会下降?如果不会,就删掉。比如“你是一个擅长总结的助手,请用简洁的语言总结以下内容”这类铺垫,在大多数情况下可以直接压缩成“请总结以下内容”,前面的身份描述未必能显著改善结果。再比如输出格式说明,如果模型本身已经能稳定输出 JSON,那一大段“请确保输出是合法 JSON,不要包含多余文本,键名必须为……”就可以压缩成一句“以 JSON 输出”。
这里有一个权衡:不追求把所有 Prompt 压到最短,而是保留稳定输出效果所需的最少信息。如果你发现删某些词导致输出质量明显波动,那就说明这些词对当前模型是有功能的,要保留。优化 Prompt 的过程必须配合回归验证,用固定测试集对比压缩前后输出,不能只看 token 数量下降就沾沾自喜。
3.2 上下文缓存:项目里最容易被忽略的“打折券”
Gemini API 的上下文缓存是一个非常核心的省钱机制,中文文档里叫上下文缓存或 Context Caching。原理很简单:如果你有一段内容是反复多次提交给模型的,比如长文档背景、固定的系统指令、不变的参考语料,那这段内容可以写入缓存,后续请求命中缓存时,对应输入 token 的价格大幅降低。官方说法里缓存命中的输入 token 折扣力度很大,可能比正常输入价格低一个量级,实际数值以官方定价为准。
我在模拟项目X里的做法是这样的:把共享文档库、固定的领域知识包、长期不变的业务规则放在一个公共前缀里,同时把所有相关内容组织成一个可以复用的缓存块。Gemini API 要求可缓存文本位于请求的开头,并对缓存块的最小 token 数有要求,通常要达到一定规模才划算,比如几千 token 以上。如果你的请求中确实包含大段重复内容,开启缓存之后效果立竿见影。
有个容易踩的坑:缓存是按内容前缀来命中的,也就是说你必须在请求里保证前缀完全一致,任何细微改动(多一个空格、调换一句顺序)都会导致缓存 miss,退回原价。所以如果你要在 Prompt 里做动态插值,务必把所有变化部分放在缓存块之后,而不是混在缓存块中间。我就遇到过一个人为了在 Prompt 里拼时间戳,把整段稳定内容全部改成 f-string 动态渲染,结果缓存命中率几乎为零,费用完全没降下来。
3.3 用小模型解决大问题:模型路由
模型路由是成本优化里收益最高、也最需要业务判断的手段。核心思想:不是所有任务都需要最强模型,把任务按难度分流到不同档位模型,整体成本才能大幅下降。我在模拟项目X里设了一个简单的路由函数:先根据任务类型判断复杂度,如果只是从文本中抽取实体、判断情感倾向、格式化输出,直接走 Flash 级别;如果是多步推理、生成详细解释、处理争议性内容,再走 Pro 级别。
这个路由逻辑刚开始可以用 if-else 写死,跑一段时间后再根据日志里的失败率、重试率调优。更优雅的方案是做一个轻量级评估器:先用小模型做初步处理,如果置信度不够再升级到大模型。举个例子,文档问答场景里,先让 Flash 模型尝试回答并返回一个置信度分数,低分样本才转到 Pro 重答。这样既保住了质量,又把高成本调用数压到了一个很低的水平。
注意别把路由做成玄学。你要对每个业务线的效果指标负责,不能只看成本下降。模拟项目X里我每次调整路由策略后,都会跑一遍同样的评估集,对比输出质量分数。质量没降但成本降,这是有效的优化;质量降了成本也降,那是变相砍功能,需要谨慎。
3.4 异步批处理:能排队就别实时跑
Gemini API 提供批量处理模式,适合那些不需要实时返回的任务,比如离线批量打标、夜间数据清洗、定时内容审核。批量任务可以排队异步处理,官方通常会在价格上给予较大折扣,比实时调用便宜不少。如果你的业务里只要不是用户界面直接等待结果的场景,都优先考虑异步批处理。
模拟项目X里的内容打标任务就是典型例子:每天有大量新文章需要分类和提取关键词,这些任务本身不要求秒级响应,前一晚跑完第二天出结果完全没问题。我改造后把打标请求全部切到异步批处理,成本直接降下来一大截。这个改造的工程量并不大,主要是把单条调用的代码改成提交批量任务,再写一个轮询或回调获取结果。
这里提醒一下,异步批量虽然便宜,但排队的延迟不太可控,不适合生产核心链路。而且批处理同样消耗 token,只是单价更便宜,你依然要关注批内数据的规模和调用频率。我在实际项目中遇到过把实时接口排到批量任务里导致用户体验问题的情况,所以在上批量之前,先区分清楚业务对实时性的要求,别为了省钱把体验也省掉了。
3.5 结构化输出、少样本示例的精打细算
有些人会在 Prompt 里放大量示例来“教”模型输出格式,这本身没问题,但示例放在用户消息里还是系统指令里,成本差别不大,真正的问题是示例数量。每个 few-shot 示例都对应几百甚至上千 token,而它们往往只服务一个简单格式约束。对提取类任务我更推荐用一个非常紧凑的结构化描述代替多个示例,比如用一行 JSON 示例加字段说明,而不是五个完整的输入输出样例。
结构化输出模式也值得用起来,它能帮你约束模型按照 JSON Schema 输出,减少因为格式不符合预期而产生的重试次数。重试就是烧钱,一次失败重试相当于两倍输出成本。我的做法是给核心提取任务配上 JSON Schema 约束,让模型一次性输出干净的结构化结果,同时把输出 token 控制在最小可用范围。比如字段只需要 id 和 label,就不要让模型顺带输出 explain 字段。
还有一个小技巧:如果你需要让模型做多选题或选项判断,可以把选项编码成字母而不是完整文本,输出时只让模型返回字母。这样输出 token 从几十压缩到几个,成本降得十分明显。这类“输出 token 压缩”的思路很容易被忽略,但输出单价高于输入单价,实际上收益相当可观。
3.6 配额与限流:别让并发帮你烧钱
很多项目成本失控不是因为某项单价贵,而是因为并发高导致调用量被放大。恶意刷接口、重试风暴、前端事件重复触发,这些都会让 RPM 和 TPM 直接冲破预期。尤其注意重试机制,网络抖动导致失败后,如果代码里默认立即重试,网络恢复瞬间会形成一层重试高峰,费用在几分钟内成倍上涨。
我的建议:给 API 客户端设置合理的限流策略,比如按桶存储令牌控制每秒请求数,同时对重试采用指数退避加抖动,避免集中冲击。在服务端可以加一层简单的熔断开关:当某业务线的错误率超过阈值时,自动降级走缓存或返回兜底结果,而不是继续无脑调用模型。
这里要特别说一个意识问题:并发本身不是目的,单位时间内真正有价值的请求数才是。模拟项目X有一次做联调测试,测试脚本没有睡长老,以最快速度循环调 API,结果一个晚上跑出了等同于生产环境的消耗。后面我把测试环境单独用低配模型和 mock 接口,禁止测试流量直接打到生产 API,才把这类“测试烧钱”堵住。
4. 实测过程中的常见问题与排查实录
4.1 账单比预期高:先查缓存命中率
有一次我把上下文缓存配置好了,也确认公共前缀没变,但月底对账发现成本只降了几个百分点,远低于预期。排查过程是这样的:先看日志里的缓存命中情况,Gemini API 的响应里通常会有缓存相关字段,我发现大量请求的缓存命中显示为 miss。再看请求内容,问题出在一个细节上:我在公共前缀后面拼接了用户 ID,因为拼了动态内容,缓存整体失效。
这是个非常典型的错误:把动态字段混进了缓存前缀。按官方机制,缓存命中要求前缀完全一致,前缀中一旦有任意字符变化,整个前缀都无法命中。解决办法是把动态字段从公共前缀里挪走,放到消息列表的靠后位置。调整之后再看命中率,果然恢复到 90% 以上,成本也明显降下来了。这告诉我们一个原则:缓存设计必须从请求结构层面保证前缀稳定性,而不是指望模型或 API 帮你自动优化。
4.2 428 限流排查:并发与峰值设计
Gemini API 遇到限流时通常会返回特定状态码,我印象里是 428 或 429 这类与配额相关的错误,具体以官方文档为准。当时模拟项目X在流量高峰阶段突然出现大量限流错误,业务方反馈处理速度变慢。我检查监控面板发现 RPM 已经顶到配额上限,而很多请求是同一批任务里可以串行处理的,不需要同时打过去。
排查思路是确认限流对象是 RPM 还是 TPM。RPM 限流说明每秒请求数太多;TPM 限流说明单次请求 token 太大或请求过于密集。我的做法是给客户端加一个轻量级并发控制,把瞬时并发数控制在配额的一半以下,再配合缓慢重试。改完之后限流错误基本消失,而且因为重试少了,费用反而更稳定。
另外一个值得注意的细节是:不要把生产环境和测试环境共用一个 API key。模拟项目X早期所有环境共用一把钥匙,测试脚本一跑,生产流量跟着受限,排查起来特别痛苦。后来我按环境拆分了 key,并给测试 key 设置了极低的配额,问题才彻底解决。
4.3 日志积压和检索:别把监控本身搞贵
监控体系如果不注意效率,也会变成新的成本黑洞。模拟项目X的日志表增长非常快,每天几百万行的 Token 明细,如果每次查“某业务昨天消耗多少”都做全表扫描,数据库 CPU 会撑不住。我后来做了两件事:一是按天分区,只保留最近 30 天的明细,更早的聚合数据归档到冷表;二是预聚合日报表,业务查询直接走报表而不是明细表。
日志写入这一侧也要优化。不要在业务主流程上同步写日志,否则 API 返回延迟会被日志拖慢。我用消息队列把日志异步写入,或者干脆先写本地缓冲再定期批量入库。如果你用的是云日志服务,要注意日志索引和存储时长都是要花钱的,不需要长期保留的 debug 日志及时设置过期时间,别让日志服务本身变成成本大头。
4.4 排查清单速查表
这里给一份我在实际项目中反复使用的排查清单,遇到成本异常可以直接对照检查:
| 症状 | 排查方向 | 常见原因 | 处理建议 |
|---|---|---|---|
| 单日费用突增 | 检查日志中请求量、平均 token | 测试脚本误打生产 key、重试风暴 | 分环境 key,限流退避 |
| 缓存配置了但费用没降 | 查看缓存命中率 | 动态文本混入缓存前缀 | 把动态字段移到前缀之后 |
| 大量 428/429 限流 | 监控 RPM、TPM 是否到顶 | 并发控制缺失 | 加并发控制,后端排队 |
| 输出 token 远超预期 | 查看候选返回内容 | 模型输出冗余内容、Prompt 未约束 | 压缩输出格式,加约束 |
| 多轮对话费用快速上涨 | 检查历史消息 token 累积 | 所有历史全部发送 | 保留关键上下文,定期截断 |
| 高模型档位费用高 | 统计各模型调用占比 | 默认使用最强模型 | 模型路由分流到 Flash |
| 每日报表缺失 | 检查数据处理定时任务 | 日志未落库、聚合失败 | 补充定时任务,增加告警 |
这张表不用背,贴在你的项目文档里当 check list 用就行。每次成本异常时,按表格从上往下过一遍,基本能找到 80% 的问题。剩下的 20% 往往是新功能上线时 Prompt 设计不合理或业务逻辑发生变更,需要结合代码 diff 来看。
最后分享一点个人经验
做完这一轮监控和优化之后,我最大的感受是:Gemini API 的成本并不是一个黑盒,它完全由请求结构、模型档位、缓存利用率和并发策略决定,四个变量都控制住了,费用就自然下来了。模拟项目X经过这次改造,日成本下降了大约 68%,效果指标没有明显回退,这 68% 来自缓存命中、批量处理、模型路由和 Prompt 压缩四部分的叠加,不是单一技巧的功劳。
我建议每个接入 Gemini API 的项目在开发第一天就把日志和成本估算加上,哪怕只是简单记一下 token 数,也比你一个月后面对账单时再去反推代码路径容易得多。那些说“以后再做监控”的项目,最后基本都是靠月底账单吓一跳才意识到问题的。
最后再分享一个小技巧:每次写调用代码前,先在注释里标注这行调用预期消耗多少 token、为什么需要这个量级的上下文。这个动作花不了几秒钟,但能让你的代码在长时间维护后依然保持成本敏感度。AI 的能力很强,但它不是免费午餐,把每一笔调用当成一次有预算的购买,你就不会养出一只吞金兽。