老王开了一家“AI食堂”,后厨里有好几位手艺不同的师傅:有用料讲究的星级大厨,也有快手实惠的街坊师傅。每天各包间的客人络绎不绝——搜索组爱点大厨的招牌菜,客服组偏好街坊师傅的快手菜。每道菜从下单到上桌,都要经过前台那台智能点餐系统登记:谁点的、哪位师傅做的、用了多少食材、几点出的菜。月底老王翻账本,一眼就能看出哪道菜最费食材、哪桌客人吃得最多、下周该备多少货。这套“记账、盘账、算账”的本事,放在大模型推理服务里,就是Token消耗追踪与监控。本文就带你跟着老王的账本,把网关层的Token计量、性能关联、成本报表和容量规划一次讲透。
学会在网关层精准计量每次请求的Token用量,并将性能指标与成本报表关联起来,你就能从“模型跑得慢”升级为“钱花在哪、怎么省”,这是大模型推理平台工程师做成本治理与容量规划的核心能力。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
Token 用量趋势 模型费用分布 Gateway Token 消耗追踪仪表盘:实时监控输入/输出 Token 用量、按模型计算费用、关联 GPU 利用率,支持多维度成本分析。
1. Token消耗基础:备料与成菜,分开记账
在AI食堂里,一道菜的成本从来不是铁板一块。客人点一份“智能问答”,后厨先要备料——把菜谱上的食材清单过一遍,这是输入Token;接着师傅动手炒菜,端上桌的成品菜才是输出Token。老王从不把备料和成菜的价钱混在一起算,因为两者的“工夫”不一样贵。
大模型推理服务的Token计量也是同样的道理。一次请求的输入Token由Prompt经过分词器切分而来,输出Token则是模型逐字生成的回复长度。这两类Token不仅来源不同,在计费时单价也往往相差数倍——输出Token通常更贵。因此,任何不做区分、只记一个“总Token数”的监控方案,都会让成本账面失真。
Token的计量粒度由分词器决定,同一个中文词在不同分词器下可能被切成1个或多个Token;更关键的是计量位置。应用层统计会因为缓存命中、请求重试、流式中断等原因和真实推理用量产生偏差,而网关层位于所有请求的必经之路上,在这里计量才能拿到“最接近账单”的数字。
老王把这套规则刻在前台的记账系统里:每一道菜,备料多少、成菜多少,分得清清楚楚。正是拜这种“分开记账”的执念所赐,月底他才能一眼看出哪位师傅的手艺最费食材——接下来的章节,我们就跟着老王的账本,看每一笔Token流水是怎么被记录、汇总和变成钱的。
- 输入Token(T_input)Prompt经过分词器切分后得到的Token总数,代表“备料”阶段的用量。
- 输出Token(T_output)模型生成的回复Token总数,流式响应时需把各分片累加。
- 单请求总用量(T_req)两者相加得到一次请求的Token总消耗,是计费与统计的最小单元。
2. 网关层日志采集:每道菜都要过前台
前台的点餐系统是AI食堂的咽喉。不管客人是搜索组还是客服部,不管点的是大厨的招牌菜还是街坊师傅的快手菜,订单都必须经过前台登记。小票上写着桌号、师傅编号、备料用量、成菜份量、出菜时刻——这就是一份元数据完整的“交易流水”。
在推理服务架构里,这个“前台”就是服务网关。实践中我们在网关的中间件里埋点,拦截每一次HTTP请求与响应,把租户ID、模型版本、输入Token数、输出Token数、响应耗时、时间戳等字段拼成一行结构化日志。相比在业务代码里打点,网关埋点不侵入应用、覆盖所有流量,是天然的计量点。
日志质量决定报表可信度。高并发下要防止日志丢失和写入抖动,通常先经内存队列缓冲再异步落盘;同时要监控日志完整率——如果丢了一部分请求的记录,统计出的成本就会偏低。完整率指标本身也要纳入告警,就像食堂绝不允许小票丢失。
老王给前台定了一条规矩:小票一张都不能少,哪怕是打烊前最后一桌客人。因为账本缺了一张小票,月底盘库存就会少算一份食材。日志完整率,就是AI食堂的“小票抽查”。
- 成功记录数(N_logged)网关日志中实际落盘的请求条数。
- 总请求数(N_total)网关在同一时间段内处理的总请求量。
- 完整率(CR)两者相除再乘以100%,低于99%就要告警排查。
3. 用量统计方法:关店后的盘账功夫
每天打烊后,老王开始盘账:今天一共做了多少道菜?平均每桌吃多少食材?上周五为什么食材消耗突然翻倍?这些问题的答案藏在不同的统计口径里。
对应到推理服务,Token用量的统计至少有三个视角。累计视角:按时间窗口(小时/天)累加所有请求的Token,得到总量曲线;分布视角:计算单请求Token的均值、P50/P95/P99,捕捉“少数大请求吃掉多数Token”的长尾现象;异常视角:对窗口总量做同比、环比,突增或骤降都值得排查——突增可能是有泄漏流量的调用方,骤降可能代表服务故障。
窗口的选择也很讲究。窗口太短(秒级)噪声大,太长(月度)又会掩盖峰值。实践中常用多级窗口:原始明细保留7天,小时级聚合保留30天,天级聚合长期保存,既控制存储成本,又能随时下钻。
老王的盘账口诀是“先总量、再分布、后异常”。总量告诉他生意规模,分布告诉他谁是大胃王,异常告诉他哪天出了岔子。三招用全,账本才有灵魂。
- 单次请求Token(T_in + T_out)每一条网关日志都携带输入与输出Token数。
- 窗口内求和(Σ)把窗口内N条请求的Token逐一累加。
- 窗口总用量(Tok_window)累加结果用于绘制趋势曲线和触发异常告警。
4. 性能指标关联:光看用量不够,还要看病灶
老王渐渐发现,光盯食材消耗还不够。同样的食材,隔壁酒楼翻台快、上菜快,利润就高;自家后厨如果高峰期灶台全满、出菜龟速,再省食材也白搭。于是他把账本和前厅的出菜记录、后厨的忙碌状态贴在了一起。
推理服务的“翻台率”就是吞吐量,衡量指标是每秒处理的Token数(TPT)和每秒请求数(QPS);“上菜速度”是时延——首次Token时延(TTFT)和总生成时延;“后厨忙碌程度”是GPU等资源利用率。把这些指标与Token消耗按时间对齐,就能回答三个问题:吞吐上去了,Token消耗是否同步增长?时延变高时,是不是某些超长输出请求在拖累?资源打满时,哪个模型的Token产出效率最差?
关联分析最常见的做法是将网关日志与性能指标按时间戳对齐到同一张宽表,然后做分组对比。例如按模型版本统计“每千Token耗时时延”和“每卡每秒产出Token”,这两个比值直接反映钱花得值不值。
老王在吧台挂了块白板,左边是食材消耗曲线,右边是翻台率和出菜速度,中间用线连起来。哪个环节堵了、哪道菜拖慢了全店,一眼便知。性能指标与Token消耗的关联,就是这块“连起来”的白板。
- 总Token量(Tok_total)时间窗口内所有请求的输入输出Token之和。
- 时间窗口(Δt)统计所跨的时长,通常取分钟或小时。
- Token吞吐率(TPT)两者相除,反映服务的“消化”能力。
5. 成本报表生成:月底的算账时刻
月底是老王最紧张也最期待的时刻。他把全月的食材账本翻出来,乘以各自的单价,算出每位师傅、每个包间各花了多少钱。菜价不是一刀切——备料便宜、成菜贵,不同师傅的工时费也不同。
Token计费同理,需要给输入和输出Token分别设定单价(供应商通常按百万Token计价)。单次请求成本 = 输入Token×输入单价 + 输出Token×输出单价。以此为基础,按租户分组得到“哪个部门烧钱”,按模型分组得到“哪个模型烧钱”,再叠加时间维度就是成本趋势。报表还要做环比和预算对比,超出预算线的租户要自动标红。
生成报表时要注意“计价口径”的一致性:是网关记录的用量还是应用上报的数量?是否扣除缓存命中的部分?口径不一致的报表会让财务部门抓狂,所以报表血缘要清晰:每一分钱都能追溯到具体请求ID。
老王把账本摊在桌上,每一行都给包间和师傅标了价。老板只看一眼就知道:翻译业务用大厨纯属杀鸡用牛刀,客服业务该让街坊师傅多接单。成本报表的终极价值,不是算出花了多少钱,而是决定明天怎么省钱。
- 输入/输出单价(P_in、P_out)两个价格基准,P_out通常是P_in的数倍。
- 各自相乘Token数与对应单价相乘,得到两项费用。
- 求和(C_req)两项相加即单请求成本,全部请求累加即总成本。
6. 模型版本分析:给师傅们排座次
食堂里三位师傅各怀绝技:大厨用料猛但翻台快,街坊师傅便宜但点的人多,快手师傅胜在稳定。老王想搞清楚到底谁在大量消耗食材、谁在创造利润,于是给每位师傅单独立了一本账。
推理平台做模型版本分析时,同样要为每个模型版本单独核算:累计Token消耗、累计成本、平均单请求成本、P99请求成本。再结合请求来源(租户×场景),生成“场景画像”——哪个业务在用大模型处理短文本?哪个业务在生成长文档?画像清晰后,成本热点无所遁形:可能5%的调用方消耗了80%的Token。
版本成本占比是最直观的排座次指标,分子是该版本成本,分母是全部版本成本之和。配合单位成本(每千Token成本、每请求成本)和性能指标(每千Token时延),就能评估一个版本的“性价比”。新版模型上线前,先跑一遍成本对比试验,用数据决定是否全量替换。
三个月后,老王终于敢在股东面前拍胸脯:大厨虽然贵,但招牌菜撑起了门面;街坊师傅是利润奶牛;快手师傅可以考虑换成更便宜的学徒。给模型版本排座次,就是用数据把“感觉”变成“决策”。
- 版本成本(C_m)模型版本m在一个周期内的总成本。
- 全部版本成本之和(ΣC_j)分母是所有模型版本成本的加总。
- 成本占比(Ratio_m)相除再乘以100%,得到该版本的烧钱份额。
7. 容量规划优化:备菜的艺术
AI食堂最怕的不是客人多,而是高峰期灶台不够、食材备少了。老王慢慢学会了备菜的艺术:根据上周客流量预测下周备货量,给每种食材设一道红线,快烧到红线就提前采购、调整窗口安排。
推理平台的容量规划同理:基于历史Token消耗趋势,预测未来周期(下周/下月)的用量与成本。预测值逼近预算上限时触发预警,运营同学据此决定:是否扩容GPU集群、是否把部分流量降级到更便宜的模型、是否开启上下文缓存复用。Token消耗追踪为这些决策提供了唯一的依据——没有准确的账本,扩容就是拍脑袋。
预测模型不必复杂,按天粒度回归日平均消耗、乘以未来天数即可得到粗略预算;更精细的做法是按小时×星期做季节性预测。预测结果要与实际对比,持续回填校准,误差收敛后再用于自动化扩缩容。
老王把食材红线贴在后厨门口,每周一更新。红线亮红灯的那周,他会提前加订食材、把部分菜单的份量调小。推理平台的预算预警,就是这盏红灯——让成本从“事后心疼”变成“事前规划”。
- 日均成本(C̄_day)近30天Token成本的平均值,消除单日波动。
- 未来天数(D_period)预测周期包含的天数。
- 预测成本(Ĉ_period)两者相乘得到周期预算,超预算触发预警。
AI 应用场景
大模型API网关的实时计量与计费
阶段:推理服务观测与计量
解决的问题:传统按调用次数计费无法反映真实开销——一个几百字Prompt的短问答和一个万字长文生成的成本天差地别。在网关层埋点计量输入/输出Token后,可以按实际用量计费、支持预算预警。
具体案例:某金融公司的大模型平台在网关中间件中记录租户、模型版本、Token用量,按小时聚合到分析库,仪表盘实时展示各业务线消耗Top榜。某部门因违规调用大模型生成营销文案被及时拦截,当月省下30%成本。
多租户SaaS的成本分摊报表
阶段:成本治理(FinOps)
解决的问题:多个业务线共用一个模型服务时,“糊涂账”导致没人对成本负责。按租户×模型版本生成月度成本分摊报表,让每个业务领导看到自己的账单。
具体案例:某SaaS公司每月底自动生成《Token成本分摊报告》,把成本按租户、模型、场景三个维度切开,并标出环比增幅Top5的租户。CEO据此推动客服组引入Prompt缓存,成本下降40%。
模型迭代的A/B成本对比
阶段:模型选型与上线
解决的问题:新模型效果好但价格可能翻倍,凭感觉换模型风险高。借助网关计量能力,在灰度期间对两个版本做同流量成本对比。
具体案例:某电商团队上线新对话模型前,将10%流量切到新版本,对比每千Token成本、P95时延和用户满意度,发现新版本成本高22%但满意度提升有限,决定暂缓全量,等待更优版本。
Python 演示
#!/usr/bin/env python3"""推理网关 Token 消耗追踪与成本报表示例"""import jsonfrom collections import defaultdict INPUT_PRICE = 2e-6 # 每输入 token 单价(元)OUTPUT_PRICE = 8e-6 # 每输出 token 单价(元) SAMPLE_LOGS = [ {"req_id": "a01", "tenant": "搜索组", "model": "gpt-4o", "prompt_tokens": 320, "completion_tokens": 180}, {"req_id": "a02", "tenant": "客服组", "model": "deepseek-v3", "prompt_tokens": 150, "completion_tokens": 90}, {"req_id": "a03", "tenant": "搜索组", "model": "gpt-4o", "prompt_tokens": 600, "completion_tokens": 420}, {"req_id": "a04", "tenant": "推荐组", "model": "qwen-max", "prompt_tokens": 80, "completion_tokens": 40}, {"req_id": "a05", "tenant": "客服组", "model": "deepseek-v3", "prompt_tokens": 220, "completion_tokens": 310},] def load_logs(path=None): if path: with open(path, encoding="utf-8") as f: return [json.loads(line) for line in f if line.strip()] return SAMPLE_LOGS def request_cost(record, in_price=INPUT_PRICE, out_price=OUTPUT_PRICE): return record["prompt_tokens"] * in_price + record["completion_tokens"] * out_price def build_report(logs): by_model = defaultdict(lambda: {"requests": 0, "in_tok": 0, "out_tok": 0, "cost": 0.0}) by_tenant = defaultdict(lambda: {"requests": 0, "in_tok": 0, "out_tok": 0, "cost": 0.0}) for rec in logs: cost = request_cost(rec) for bucket in (by_model[rec["model"]], by_tenant[rec["tenant"]]): bucket["requests"] += 1 bucket["in_tok"] += rec["prompt_tokens"] bucket["out_tok"] += rec["completion_tokens"] bucket["cost"] += cost return by_model, by_tenant def print_report(buckets, title): print("== " + title + " ==") total_cost = 0.0 for key, v in sorted(buckets.items(), key=lambda kv: -kv[1]["cost"]): total_cost += v["cost"] print(f"{key:<12} 请求{v['requests']:>3} | 输入{v['in_tok']:>6} | " f"输出{v['out_tok']:>6} | 成本{v['cost']:.4f}元") print(f"{'合计':<12} 成本{total_cost:.4f}元") print() if __name__ == "__main__": logs = load_logs() by_model, by_tenant = build_report(logs) print_report(by_model, "按模型版本") print_report(by_tenant, "按租户")
from collections import defaultdict给统计桶“自动初始化”的能力,首次访问某个模型或租户时无需判断键是否存在。def request_cost(record, in_price=INPUT_PRICE, out_price=OUTPUT_PRICE):把“输入×输入单价+输出×输出单价”封装成唯一的计费函数,保证全局口径一致。for bucket in (by_model[rec["model"]], by_tenant[rec["tenant"]]):一行代码让同一条日志同时进入模型和租户两个账本,避免重复遍历。bucket["cost"] += cost累计成本,所有聚合字段都在这里增长。sorted(buckets.items(), key=lambda kv: -kv[1]["cost"])按成本从高到低排序,最烧钱的模型或租户排在最前面。if __name__ == "__main__":脚本既可独立运行,也可以被其他模块导入复用。
常见误区
误区我在应用代码里把Prompt和Response的长度统计一下,不就得出了Token用量吗?何必还要搞网关日志那么麻烦。
正解应用层统计会漏掉缓存命中、请求重试、流式中断提前释放的场景,而且不同应用的实现口径不一,最后汇总的账本对不上。网关层是所有流量的必经路口,在路口设卡才能保证“一辆车都不漏”。就像让每位服务员自己记客人吃了什么,不如让前台小票统一登记——后者才是权威账本。
为何常见:应用层埋点开发简单、见效快,第一反应都是在业务代码里加日志,忽视了网关层这个更根本的计量位置。
误区反正都是Token,统计的时候记一个总数,单价也用同一个,算出来差不多吧?
正解输出Token的单价通常是输入的数倍(例如输入2元/百万、输出8元/百万)。把两者混为一个总数再乘平均单价,会严重扭曲成本结构——长生成类业务会被低估,短问答类会被高估。必须严格分开记录、分开计价,就像食堂里备料和成菜的工时费不一样。
为何常见:很多模型API的文档把两个价格放在一起展示,初学者只记住“每百万Token X元”,便想当然用一个单价。
误区我做了Token趋势图、成本报表,监控已经很完善了,还要关联性能干嘛?
正解同一份Token总量,既可以是低并发下慢速生成,也可以是高并发下满负荷运转,两者的资源成本天差地别。只有把Token消耗与吞吐、时延、资源利用率对齐,才能拆出是“效率低”还是“用量大”,才能指导扩容和优化。就像只知道食堂用了500斤食材,却不知道是翻台快还是出菜慢,就无从改善经营。
为何常见:Token和性能指标通常来自两套系统(网关日志 vs 监控系统),关联需要时间戳对齐的额外工作量,容易被跳过。
误区报表上日均成本10万元,看起来很平稳,就不需要预警了吧?
正解平均值掩盖了峰值。如果某天晚上8点出现3倍突增,平均下来只是“略高”,但容量规划恰恰要按峰值准备资源。正确的做法是同时看P50/P95/P99和峰值窗口,峰值逼近预算线就要预警。就像食堂备菜要按周末高峰期备,不能按周平均客流备。
为何常见:平均值的计算最简单,一张趋势图就能画完;而分位数统计对存储和计算的要求更高,容易被省略。
面试题
Q1. 在大模型推理服务中,为什么选择在网关层计量Token用量?
- A.能拿到应用层的业务逻辑
- B.网关覆盖全部请求流量← 正确答案
- C.网关层无需存储日志
- D.网关层不产生任何开销
答案:B。网关是所有请求的必经路口,在路口计量才能保证“一辆车不漏”,B正确。应用层业务逻辑与Token计量无关;网关层同样需要存储日志,也会产生轻微开销,C、D说法过于绝对。
Q2. 输出Token与输入Token的单价关系通常是?
- A.输出单价等于输入单价
- B.输出单价高于输入单价← 正确答案
- C.输出单价低于输入单价
- D.输出单价可高可低
答案:B。输出Token是模型逐字生成的,计算代价更高,主流供应商的定价通常是输入单价的数倍。把两者混为一谈会严重扭曲成本报表,这也是本文强调分开记账的原因。
Q3. 单次请求的Token总用量如何计算?
- A.只统计输入Prompt的长度
- B.只统计模型输出的长度
- C.输入加输出Token总和← 正确答案
- D.按响应时长折算用量
答案:C。一次请求消耗两部分Token:Prompt切分出的输入Token,加上模型生成的输出Token,二者相加才是账单上的总用量。只统计其中任何一部分都会低估成本。
Q4. 推理网关的请求日志中,应记录哪些关键字段?
- A.租户标识与模型版本号← 正确答案
- B.请求与响应的Token数← 正确答案
- C.请求时间戳与响应耗时← 正确答案
- D.用户的完整对话正文
答案:ABC。租户、模型、Token、时间、耗时可支撑成本分摊、版本对比与性能关联,是网关日志的核心字段。完整对话正文属于隐私数据且体积巨大,通常不落入日志。
Q5. 关于Token吞吐率(TPT)指标,下列描述正确的是?
- A.每秒处理的Token总数← 正确答案
- B.每秒成功的请求数
- C.每个请求的平均时延
- D.每张GPU的显存占用
答案:A。TPT = 窗口内总Token量 ÷ 时长,衡量服务“消化Token”的速度。每秒请求数对应QPS,平均时延是延迟指标,显存占用属于资源指标,均与TPT定义不符。
Q6. 哪些情况会导致应用层统计与网关层计量不一致?
- A.请求重试被重复统计← 正确答案
- B.流式响应中途被中断← 正确答案
- C.缓存命中未计入日志← 正确答案
- D.日志时间戳格式不同
答案:ABC。重试会让应用层重复计数,流式中断导致输出Token少算,缓存命中时应用层仍可能按完整Prompt计费。时间戳格式只影响日志对齐匹配,不影响数量一致性,故D不选。
Q7. 按租户维度生成成本报表的主要用途是?
- A.提升模型回答的准确率
- B.实现成本分摊与预算管控← 正确答案
- C.降低输出Token的单价
- D.增加服务的并发上限
答案:B。按租户分摊成本,让每个业务部门看到自己的账单,是成本治理和预算管控的基础。准确率、单价、并发都是模型或架构层面的问题,与租户报表目的无关。
Q8. 容量规划时,以下哪个数据更值得重点关注?
- A.每天的平均Token消耗量
- B.高峰窗口的Token消耗峰值← 正确答案
- C.全年的请求总数
- D.模型的参数量大小
答案:B。容量规划要按峰值备资源,平均量会淹没突发峰值,导致高峰期算力不足或预算超支。峰值窗口数据直接决定GPU集群规模和成本红线设置。
Q9. 下列哪些手段可以有效降低Token成本?
- A.对重复Prompt开启缓存复用← 正确答案
- B.限制输出Token的最大长度← 正确答案
- C.将简单任务路由到小模型← 正确答案
- D.删除网关层的计量日志
答案:ABC。缓存复用省去重复输入计费,限制输出上限控制生成成本,小模型降级路由降低单价,三者都是主流优化策略。删除计量日志只会让账本缺失,无法省钱。
Q10. 某模型输入Token单价2元/百万,输出8元/百万。一次请求输入500 Token、输出200 Token,成本为?
- A.0.0026元← 正确答案
- B.0.0056元
- C.0.0020元
- D.0.0016元
答案:A。成本 = 500×2÷1e6 + 200×8÷1e6 = 0.001 + 0.0016 = 0.0026元。这道题考察输入输出分开计价的口径:若误用同一单价就会选错,正是误区2的实战版。