news 2026/9/1 6:00:44

大模型 API 成本评估指南:拆解计费结构、沉淀可复现对比流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型 API 成本评估指南:拆解计费结构、沉淀可复现对比流程

在实际项目的模型选型讨论中,经常会出现一句话把成本问题一笔带过的现象:“某个模型更便宜,直接换过去就行。”比如当大家看到“GLM-5.3 成本仅为 FABLE 5 的八分之一”这类结论时,不要急着把它当既定事实写进方案。大模型 API 的计费并不是“一个单价 × 调用次数”这么简单,真正的账单由输入 token、输出 token、缓存命中、上下文长度和调用链路共同决定。如果只拿一份公开价格表对比,算出来的结论很可能和实际账单差出好几倍。

这篇文章从成本评估方法入手,先拆解大模型 API 的计费结构,再给出一个可复现的对比脚本,最后说明如何验证“八分之一成本”这类结论是否在自己的任务上成立,以及怎样避免被单点价格误导。无论是做技术选型、模型切换,还是日常的账单排查,都可以沿用这套流程。

1. 成本对比不是看单价表就够的,先拆解大模型 API 的计费结构

1.1 为什么按“千 token 单价”直接比大小往往会算错

很多平台在文档里都会列出每百万 token 的价格,看起来只要把两个模型的价格放在一起相除就能得出结论。但实际项目里,两个模型的计费口径经常不一致,常见的差异点包括:

  • 同一段中文文本在不同模型的分词器下,token 数量可能相差 20% 到 50%。一个模型按 300 token 计费,另一个模型可能按 450 token 计费,即使单价相同,实际成本也不同。
  • 输入和输出的单价往往不一样,输出 token 通常更贵。如果任务偏长输出,输出价格会成为总成本的主要部分,只对比输入价格没有意义。
  • 部分模型支持上下文缓存,命中缓存的输入 token 会按折扣价计费,不命中的输入 token 按原价计费。缓存命中率不同,同样请求的账单就不一样。
  • 不同模型对上下文的处理方式不同。有的模型会自动截断或压缩历史消息,有的模型必须把完整历史重新发送,导致每次请求的输入 token 数量完全不同。

所以,正确的做法不是比较“单价”,而是比较“完成同一个任务的实际支出”。单价只是成本模型里的一个参数,不是结论本身。

1.2 一次完整请求的成本由哪几部分叠加

一个标准的大模型 API 请求,账单通常可以拆成四个部分:

  1. 输入 token:用户发送的 prompt、历史会话、工具定义等所有进入模型的文本,按输入单价计费。
  2. 输出 token:模型生成的补全内容,按输出单价计费,一般比输入单价高。
  3. 缓存写入 token:第一次携带相同前缀请求时,系统把前缀写入缓存产生的费用。
  4. 缓存读取 token:后续请求命中缓存时,读取缓存前缀产生的费用,通常远低于普通输入价格。

计算单次请求成本的公式可以写成:

单次成本 = 输入token数 × 输入单价 + 输出token数 × 输出单价 + 缓存写入token数 × 缓存写入单价 + 缓存读取token数 × 缓存读取单价

如果接口不暴露缓存的拆分字段,计算时就退化为前两项。生产环境中,多轮对话、批量任务和带系统提示词的任务,缓存字段对总账单的影响非常大,这一点放到第 4 节专门展开。

1.3 成本对比的必要前提:相同任务、相同输出语义

成本对比最容易犯的错误是“任务不一致”。同样叫“让模型总结一段会议纪要”,如果任务 A 要求 200 字以内的中文摘要,任务 B 要求 1000 字的英文要点,输出 token 差距可以达到 5 倍以上。没有统一任务样本,任何成本结论都没有可比性。

做对比前至少要统一这几个维度:

维度对比时必须统一的内容
任务类型文本摘要、代码生成、信息抽取、对话问答等要分开测试
输入长度同一条输入,或按相同长度分布构造输入样本
输出长度通过 prompt 约束或 max_tokens 参数保持一致量级
温度参数同一 temperature,避免输出随机性放大成本波动
调用方式同步、流式、批量接口分别统计,因为批量可能有折扣
缓存状态冷启动和缓存命中后的成本要分开记录

只有在这些条件一致时,“GLM-5.3 成本仅为 FABLE 5 的八分之一”这句话才是一个可以验证的命题,而不是一个无法追溯的营销表述。

2. 搭建一个可复现的成本评估环境

2.1 环境准备和依赖安装

成本评估脚本只需要普通的 Python 环境,不需要额外服务。推荐 Python 3.10 以上版本,使用 requests 或各模型的官方 SDK 都可以。为了脚本通用,这里使用 OpenAI SDK 风格的接口,因为大多数平台都兼容这套请求格式。

python -m venv venv source venv/bin/activate pip install openai

如果目标平台不提供 OpenAI 兼容接口,也可以直接用 requests 调 HTTP 接口,核心逻辑不变,区别只是请求头和响应报文。

评估环境的重点是记录每次请求的 usage 数据。绝大多数平台在响应里都会返回类似下面的结构:

{ "usage": { "prompt_tokens": 512, "completion_tokens": 128, "total_tokens": 640 } }

部分平台还会返回prompt_tokens_detailsprompt_cache_hit_tokens之类的字段,用来区分缓存命中部分。脚本里要优先收集这些字段,拿到最细粒度的数据。

2.2 用统一脚本记录请求级 token 消耗

下面这个脚本封装了一次 API 调用,并把请求文本、响应文本和 token 明细记录成一条 JSON 记录。实际评估时,把脚本跑在同一个环境、同一个网络条件下,避免网络重试和超时策略对结果产生干扰。

import json import time from openai import OpenAI def call_and_record(client, model, messages, output_record, max_tokens=1024): start = time.time() resp = client.chat.completions.create( model=model, messages=messages, max_tokens=max_tokens, temperature=0.2, ) usage = resp.usage record = { "model": model, "prompt_tokens": usage.prompt_tokens, "completion_tokens": usage.completion_tokens, "total_tokens": usage.total_tokens, "latency_ms": round((time.time() - start) * 1000, 2), "request": json.dumps(messages, ensure_ascii=False), "response": resp.choices[0].message.content, } if hasattr(usage, "prompt_tokens_details"): cached = getattr(usage.prompt_tokens_details, "cached_tokens", 0) record["prompt_cache_hit_tokens"] = cached or 0 output_record.append(record) return record

记录字段里最关键的是prompt_cache_hit_tokens。如果不记录这个字段,后面计算成本时只能按全部输入原价计算,会高估那些命中次数多、上下文长但增量小的请求。

2.3 建立任务样本集,避免用单条提示词下结论

成本对比不能只跑一条提示词。单条结果受随机性和任务偏差影响很大,建议构造一个至少 20 到 50 条的样本集,覆盖真实业务中占比最高的几类任务。样本集保存成 JSONL,一行一个任务:

{"task": "summary", "input": "请用 150 字以内总结以下会议纪要:...", "max_tokens": 300} {"task": "extract", "input": "从以下合同中抽取甲方、乙方、金额和期限:...", "max_tokens": 200} {"task": "codegen", "input": "用 Python 写一个读取 CSV 并统计分组的函数:...", "max_tokens": 500}

样本集需要满足三个条件:一是和线上任务同分布;二是输入长度有一定跨度,从几百 token 到几千 token 都有;三是输出长度通过 prompt 和 max_tokens 都做了约束,避免不同模型输出长度差异过大导致成本失真。

一个可供参考的样本构成是:摘要类 30%、信息抽取类 25%、代码生成类 20%、多轮对话类 15%、短文本改写类 10%。比例按自己的业务调整,重点是测试结果要能代表真实流量结构,而不是只代表最容易跑通的那一条示例。

3. 用实际脚本计算并对比单次任务成本

3.1 通过 API 返回的 usage 字段统计成本

有了样本集和调用记录,下一步就是按统一价格计算单次请求成本。计费价格不建议硬编码在脚本里,而是放到一个单独的配置文件中,便于按平台和有效期修改。下面是一个价格配置的例子:

pricing: glm_5_3: input_per_million: 0.5 output_per_million: 2.0 cache_write_per_million: 1.0 cache_read_per_million: 0.1 fable_5: input_per_million: 4.0 output_per_million: 16.0 cache_write_per_million: 8.0 cache_read_per_million: 0.8

这里的数字只是演示结构,不是实际价格,落地前必须替换成目标平台当前文档中的真实报价。计算成本时,按照之前提到的公式逐条记录累加:

def compute_cost(record, price): prompt_tokens = record["prompt_tokens"] completion_tokens = record["completion_tokens"] cache_hit = record.get("prompt_cache_hit_tokens", 0) cache_miss = prompt_tokens - cache_hit cost = ( cache_miss * price["input_per_million"] / 1_000_000 + cache_hit * price["cache_read_per_million"] / 1_000_000 + completion_tokens * price["output_per_million"] / 1_000_000 ) return round(cost, 6)

如果平台没有暴露缓存字段,就把cache_hit按 0 处理。此时计算结果会偏保守,适合做最坏情况估计;而平台实际对缓存命中的折扣不会体现在该结果里,所以还要结合平台文档单独测算缓存收益。

3.2 预估成本和实际成本之间的偏差来源

本地估算和平台账单对不上,通常不是脚本算错了,而是下面几个原因:

  1. 输出 token 被max_tokens截断。响应里如果带了finish_reason="length",说明输出还没生成完就被截断,实际内容不完整但依然按完整 token 计费,同时会影响任务质量。
  2. 请求重试。每次超时重试都会重新产生 token 费用,账单上会出现一模一样的重复请求。
  3. 模型别名路由。部分平台用同一个模型名接入多家服务商,实际被路由到不同模型,价格自然不同。
  4. 上下文自动扩展。多轮对话中,每次请求都会携带完整历史,输入 token 随轮数增长,和单轮预估完全不一样。

所以在对比两个模型成本时,不能只看一两次调用,要统计整批样本的平均成本、中位数成本和 P95 成本。平均值会被个别超长请求拉高,中位数更接近普通请求体验,P95 则是容量规划时应该关注的上限。

3.3 验证“八分之一成本”类结论要检查哪些点

当有人说“A 模型成本只有 B 模型的八分之一”时,按下面的清单逐项核对:

检查项核对内容
对比口径比的是输入单价、输出单价,还是单次任务实际成本?
样本任务两个模型跑的是同一批任务吗?输出长度限制一致吗?
计费时段价格有没有包含限时折扣、新用户优惠或批量折扣?
缓存状态是否都处于冷启动状态?有没有一个模型命中缓存而另一个没有?
输出质量便宜的那一方的失败率、拒答率和格式错误率是否在可接受范围?
并发与配额便宜模型是否限制了并发数,导致需要更多实例从而摊低成本优势?

只有这六项都核对通过,成本倍率才有工程意义。否则“八分之一”很可能只是某个特定 prompt、某个特定时段下的偶然结果。

4. 影响最终成本的隐藏因素:缓存、模型路由、超时与重试

4.1 上下文缓存如何改变实际账单

上下文缓存是目前影响大模型账单最明显的隐藏因素。它的原理是:平台把请求前缀按内容哈希缓存起来,下次请求如果前缀相同,就直接复用缓存,不再把整段前缀重新计算一遍。对系统提示词长、历史会话多的业务来说,缓存命中率可以占到总输入 token 的 80% 以上。

缓存对成本的影响可以从两个方向看:

场景缓存不命中缓存命中结论
第一次请求全量输入按原价计费无缓存可用冷启动成本高
后续相同前缀请求重新计算,费用高按折扣价计费,费用低热请求成本明显下降
前缀经常变化每次部分写入、部分命中命中率不稳定成本波动大

对比两个模型时,如果 A 模型缓存命中率 85%,B 模型只有 30%,即使两者单价相同,实际账单也会差出不少。因此评估脚本里必须单独记录缓存命中 token,并且用真实业务中的前缀分布来测试,而不是在脚本里人工拼一个固定前缀。

注意:缓存命中率必须在真实前缀分布下测试才有效。临时构造的固定前缀会得到虚高的命中率,会严重低估实际成本。

4.2 模型路由和降级策略对成本的影响

在线上系统里,成本对比往往不是“单模型 vs 单模型”,而是“路由策略 vs 路由策略”。很多团队采用主模型加备用模型的降级方案:主模型用低成本模型,遇到限流、超时或质量不达标时,降级到高成本模型。

降级策略会显著改变总成本。假设低成本模型单次任务 0.01 元,高成本模型单次任务 0.08 元,如果低成本模型的失败率是 15%,则平均成本变为:

平均成本 = 0.01 × 0.85 + 0.08 × 0.15 = 0.0205 元

失败率从 15% 提高到 30% 时,平均成本变成 0.031 元,几乎翻倍。所以选型时不能只看模型单价,还要看这个模型在真实任务上的成功率。低成本模型如果经常触发降级,综合成本不一定比高成本模型低。

4.3 超时重试和流式输出带来的成本波动

请求超时重试是另一个容易忽略的成本项。一个请求如果第一次超时,第二次成功,那么第一次请求消耗的 token 同样会计费。把超时时间设得过短,会导致高并发下大量请求重复发送,账单成倍增长;把超时时间设得过长,又会拖慢用户体验。

建议的做法是:评估时按真实业务的重试策略统计“有效请求数”和“总请求数”,计算一个重试放大系数。成本公式修正为:

实际成本 = 单次请求成本 × (1 + 重试率)

流式输出本身不改变 token 总数,但会影响超时和断连判断。客户端如果在中途断开流式连接,有些平台会按已经生成的 token 计费,有些平台会取消计费。这个差异也要在选型前确认,否则线上日志里出现大量半截响应,账单仍然照收。

5. 常见问题与排查路径

5.1 现象:账单金额和本地估算差别很大

可能原因:

  • 出现了重试请求,账单里有重复记录。
  • 缓存字段没有取到,漏算了缓存读取折扣或缓存写入费用。
  • 平台对同一请求额外收取了系统级 token,比如自动注入的指令或安全提示。
  • 一次业务操作触发了多个模型调用,本地却只算了一次。

检查方式:从平台导出按 request_id 维度的用量明细,和本地记录的request_idprompt_tokenscompletion_tokens逐条对比。先找多出来的请求,再找 token 数对不上的请求。

5.2 现象:同一请求在不同时间价格不同

可能原因:

  • 平台的计费规则调整,价格表有版本差异。
  • 请求前缀的缓存状态变化,第一次没有命中,之后命中,价格自然会降。
  • 平台在不同时段的批量折扣不同,比如夜间批量任务有折扣。
  • 通过不同的接入端点调用,价格本来就不同。

检查方式:保留每次请求的时间戳、模型名和端点信息,按小时或按天聚合再看趋势。如果时间、端点和模型名都一致,价格仍然不同,就要重点看缓存命中字段。

5.3 现象:长输入短输出的任务反而比想象中贵

可能原因:

  • 多轮对话中每轮都带完整历史,输入 token 是轮数乘以单轮历史长度。
  • 长输入没有触发缓存,每次都按全量输入原价计算。
  • prompt 被平台自动拆分成多次内部调用,比如需要检索或分析的过程,产生了额外 token。

处理建议:这类任务优先开启上下文缓存,并且把系统提示词、工具定义等固定内容放在前缀最前面,保证前缀稳定。不要让用户消息随机插入系统提示词之前,否则缓存命中率会明显下降。

5.4 排查顺序建议

遇到成本异常时,按照下面的顺序排查:

  1. 确认对比口径:本地脚本和平台账单是否使用同一请求 ID 和同一统计周期。
  2. 确认请求数量:先数次数,再数 token,最后才算钱。次数对不上,后面都白算。
  3. 确认 token 明细:逐条比对prompt_tokenscompletion_tokens和缓存字段。
  4. 确认重试与降级:看日志里是否有失败后重试或降级转发的记录。
  5. 确认计费规则:阅读平台最新的计费文档,看是否有最低消费、按请求计费或附加费用。

注意:排查成本问题不要只看总额,一定要拿到请求级明细。总额只能告诉你“贵了”,请求级明细才能告诉你“贵在哪里”。

6. 成本评估的落地建议和可复用检查清单

6.1 把成本评估做成固定工作流,而不是一次性脚本

成本评估应该像性能测试一样进入迭代流程。每次更换模型、调整 prompt 或改变缓存策略,都重新跑一遍样本集。推荐把这个流程固化到 CI 或发布前的检查脚本中,至少包含四步:

  1. 准备样本集:从线上日志中抽样,保证任务分布真实。
  2. 跑批评估:对每个候选模型跑同一批样本,记录 token 和耗时。
  3. 计算成本:按统一价格配置计算单任务成本、成功率和缓存命中率。
  4. 生成对比报告:输出平均成本、P95 成本、失败率和缓存命中率,供选型决策。

把第 1 步到第 4 步固化成脚本后,任何人拿到新模型,都能在半小时内得到一份可对比的成本报告,而不是靠口头传说。脚本本身没有太高技术门槛,真正有价值的是样本集和统计口径的稳定性。

6.2 发布前成本检查清单

在做模型切换或大版本上线前,建议按表格逐项确认:

检查项确认标准
计费价格使用当前最新价格表,确认是否含税、是否含批量折扣
样本集覆盖摘要、抽取、代码生成、多轮对话等主要任务
缓存命中率真实前缀分布下的命中率已统计
重试率按线上超时和限流配置实测
降级成本主模型失败后的平均成本已计算
输出质量同一样本上人工抽检通过率达标
并发配额模型的 RPM/TPM 限制满足预估峰值
回滚方案模型切换支持按流量比例灰度,可快速回退

这份清单在模型上线前过一遍,能避免大部分“上线后发现账单超预算”的情况。缺少任何一项,都应该在发布说明里明确标注风险。

6.3 成本对比结果的使用边界

成本是选型的重要维度,但不是唯一维度。单位成本只是“单次任务支出”,完整的成本还包括:接入开发成本、prompt 调试成本、推理延迟带来的用户体验损失、失败重试造成的人工运维成本,以及模型效果差异导致的产品指标变化。

因此,当看到“GLM-5.3 成本仅为 FABLE 5 的八分之一”这类信息时,正确的处理方式是把它当作一个待验证的假设,而不是最终结论。先用本文的样本集和脚本在真实任务上复测一遍,再结合成功率、延迟和效果指标做综合判断。真正有价值的不是“便宜八倍”这个数字,而是这个数字在什么条件下成立、你的业务是否满足这些条件。

对刚接触大模型成本评估的团队,建议从 20 条样本的小评估开始,把脚本跑通,把缓存字段接进来,再逐步扩大到完整线上分布。成本评估本身不复杂,复杂的是让评估条件贴近真实生产环境;只要口径统一、样本可复现、数据可追溯,任何成本结论都能经得起验证。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 5:58:25

掌阅秋招后端笔试复盘:核心考点与实战策略

先说一下背景,我去年秋招面了不少家,掌阅科技是我印象比较深的一家。做数字阅读的厂,技术栈在业内属于比较正统的Java后端体系,没有花里胡哨的微服务全家桶轰炸,但考察的深度一点不低。这篇复盘我想把2023年掌阅秋招后…

作者头像 李华
网站建设 2026/9/1 5:56:54

Ubuntu下ArduPilot源码编译:从环境搭建到固件烧录全指南

简介:面向在Ubuntu下开展ArduPilot飞控开发与固件编译的工程师,这份于2024年7月5日更新的源码包省去了联网克隆仓库时的卡顿与失败风险,解压后即可在Ubuntu系统中配置编译环境,直接生成APM或PX4两类固件。包内目录完整保留原始仓库…

作者头像 李华
网站建设 2026/9/1 5:56:21

RBF神经网络自适应控制:从原理到C++实现与调参实战

简介:面向自动化、智能控制方向的研究者与工程师,资源包聚焦系统模型不确定或难以建立场景下的自适应控制需求。以RBF神经网络为核心,借助径向基函数的非线性映射能力,实现在线学习系统动态特性、实时调整控制器参数,从…

作者头像 李华
网站建设 2026/9/1 5:56:19

从Sleep到Standby:GD32低功耗实验全解析

简介:这是一份面向嵌入式开发者的GD32F407VET6低功耗实验源码包,专注于Cortex-M4内核MCU在睡眠、停止、待机等模式下的功耗控制与唤醒逻辑,适合学习STM32或GD32低功耗设计的工程师参考。压缩包共88个文件,以39个h头文件和33个c源文…

作者头像 李华
网站建设 2026/9/1 5:55:05

别让 AI 直接改你文件:这 3 个案例告诉你该怎么用

摘要:本文分享用 AI 批量整理本地文件的 3 个真实案例:700 多篇笔记归档、Agent 知识库目录生成与更新、软著材料对账改名,全部附提示词原文,并总结先备份、先预览、规则具体化的实操经验,可直接参考复用。 文章目录一…

作者头像 李华
网站建设 2026/9/1 5:49:21

FUSB302实现USB PD快充协议:从寄存器配置到代码实战

简介:FUSB302 PD协议代码示例是一套面向嵌入式开发者的可运行源码,聚焦USB PD 1.0/2.0协议在单片机平台上的落地实现,适合需要快速集成PD充电功能的工程师参考。代码覆盖器件初始化、CC引脚状态检测、FIFO缓冲区读写、消息ID管理与电压/电流请…

作者头像 李华