ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大模型API成本优化:从Token控制到模型路由的实战指南

大模型API成本优化:从Token控制到模型路由的实战指南

1. 预算到底是被谁吃掉的:先拆解那张让人肉疼的账单

1.1 一个“小流量但高消耗”的问答应用翻车现场

我最近在跟进一个知识库问答应用,核心场景并不复杂:用户选一份文档,然后让大模型基于文档内容回答问题。日活几百人,很多页面还是静态展示,理论上API调用量应该很有限。结果月底对账的时候,账单数字比团队预估的高出好几倍。A同学截图发到群里以后,我第一反应不是“模型太贵”,而是直接去翻调用链路的日志。翻完就清楚了,问题根本不在“回答一个问题多少钱”,而在一次用户请求的背后,模型被悄悄调用了好几轮。

这类翻车现场在团队里非常常见。为了让答案更准确,我们先调用一次小模型判断用户意图,再把整篇长文档拼进上下文,让大模型生成答案,之后又觉得原文太长,再让模型输出一版摘要。一个问答请求,背后可能藏着三四次模型调用,每次调用都完整计费。更隐蔽的是,这些中间调用经常没有日志埋点,月底看到账单时已经无法回溯每一笔花了多少。所以要控制大模型成本,第一步永远不是“换便宜模型”,而是先把全链路的调用关系画出来,弄清楚每一笔钱到底产生在哪一个环节。

1.2 成本基本公式,以及三个最容易漏掉的隐藏入口

不管用哪一家大模型API,计费的基本逻辑都是按Token走,而且输入和输出Token的单价往往不一样。大致可以归纳成这么一条公式:

单次请求成本约等于输入Token数乘输入单价,再加上输出Token数乘输出单价。

输出Token通常比输入更贵,因为生成内容比读取已有内容消耗更多算力。所以很多优化动作只盯着输入词数,却忽略了输出长度同样可能成为第一大头。除了目标函数本身,还有三个隐藏入口特别容易漏掉。

第一个是系统提示词过长。有些产品把几十条规则、背景说明、few-shot示例一股脑塞进系统提示词,每次请求都带着这一大坨。只要请求量级一上来,光固定输入就会把账单撑大一大截。第二个是日志回灌和调试链。开发调试时反复调用会计费,生产环境把每次完整响应写进日志,后续又拿日志去喂模型做摘要或质检,相当于同一段内容买了两次单。第三个是重试机制。网络抖动、上游超时都会触发自动重试,如果上一次请求已经在服务端生成了部分内容,这笔费用一样要算,重试一次可能就是双倍成本。

1.3 模型档位价差:最大的浪费往往来自“一锅端”

很多产品团队的习惯是,所有请求都统一走旗舰级模型,图省心。但真实项目的流量分布不是均匀的,固定话术回复、简单标签抽取、格式转换这类任务,让一线轻量模型来做完全是杀鸡用牛刀,价格却可能是旗舰模型的五分之一甚至更低。只有真正涉及复杂推理、长文分析、多轮纠错的请求,才值得把最贵的算力用上去。

我按项目经验大概分过一档:

任务类型典型场景建议模型档位理由
简单重复问候语、固定FAQ、关键词回复轻量模型规则或模板可覆盖,调用频繁但成本极低
中等理解标签抽取、意图识别、单文档摘要中型模型能力够用,价格适中,质量稳定
复杂推理多文档比对、长链条推理、代码排错旗舰模型效果优先,必须严格控制请求频次

这张表看起来朴素,但大多数项目真正可优化的空间就在分级上。简单问题不要占用贵模型,复杂问题也不要硬塞给便宜模型,否则账单和效果会一起崩。

2. 提示词瘦身和输出控制:趁Token还没进账先把钱省下来

2.1 提示词不是越长越好,而是“够用就好”

不少人调提示词有个误区,总觉得写得多、写全面,效果才会稳。实际上提示词里的大部分修饰语对模型来说属于冗余噪声,不仅提高输入Token成本,还可能削弱真正的指令。我在问答应用里做过一轮系统提示词瘦身,把原来一大段固定文本拆成参数化模板,只有和当前问题相关的知识片段才会在请求时动态拼进去。

具体操作可以按三步走。第一步,把所有恒定不变的指令抽到公共模板里,能放进版本配置的就不套在用户上下文中;第二步,把文档内容先做切块和索引,只选择与用户问题最相关的几块拼进上下文,而不是把整份文档都拖进来;第三步,few-shot示例只保留最必要的两三条,示例越多,每次请求额外支付的固定成本就越高。这轮调整做完,我们线上平均输入Token直接降了约四成,而效果几乎没有变化。

2.2 输出Token才是更容易失控的那一半

输入Token再大,至少在请求发出前还能估算和控制;输出Token是模型现场生成的,谁也猜不准它会写多少。尤其是提示词里写“请详细说明”“请补充更多建议”这类话,模型会很听话地输出长篇大论,账单立刻失控。我们后来查线上统计,发现平均输出Token居高不下,根源就是产品引导语鼓励用户问长问题,同时提示词又要求模型“多角度、多维度分析”。

控制输出可以用几招组合:在API参数里设置合理的最大输出上限,别让模型无限发挥;提示词里明确写“直接给结论,不要解释过程”;如果是基于文档找答案,就要求“只引用原文,不添油加醋”。这些调整都很基础,生效却极快。但这里有个坑要提醒:最大输出上限如果设得太小,答案会被截断,用户看到的是一段残句,反馈变差后又会逼着你切到更贵的模型去补效果,两边都在花钱。所以这个参数要结合真实长尾问题反复试,找一个既不会截断关键答案、又能压住废话的临界值。

2.3 结构化输出:让模型从“写作文”变成“填表单”

把输出限定成JSON或者其他固定字段格式,不只是方便程序解析,更是一笔成本账。结构化输出从机制上压缩了寒暄、过渡句和补充说明的空间,回复长度天然减小。比如在知识库问答里,我们不再要求模型输出大段文字,而是固定输出“结论、依据、置信度”三个字段,前端拿到数据以后直接渲染。同一批问题做过对比,自由发挥版本平均输出接近四百个Token,结构化版本平均只有一百八十个左右,输出费用差不多省了一半。

结构化的关键不是简简单单在提示词里写一句“请返回JSON”,而是要配合严格的解析和校验。模型偶尔会返回不合规范的格式,程序解析失败后又去请求一次,一来一回就是重复计费。要么在提示词里给一个最小可用示例,要么用约束解码能力把输出格式固定住,别让纠错成本转嫁到下游。

3. 模型分级路由:让简单问题不再占用旗舰模型

3.1 路由设计的两条路线:规则优先,模型打分兜底

模型路由是整个成本优化里见效最快的一环。理念非常直白:根据请求难度把流量分到不同档位模型上,能便宜解决的就不请专家。但落地时有个经典难点——怎么判断一个问题到底难不难?完全靠规则会漏掉大量边界情况,完全靠模型打分则意味着每个请求都要额外调一次分类模型,分类成本又抵消一部分收益。

我建议用“规则优先,模型打分兜底”的两级方案。第一级是规则分类器,判断请求里是否包含特定专业术语、是否出现“对比”“总结全文”“写出推理过程”这类强指令,只要命中就直接分流到对应档位。第二级是轻量分类模型兜底,规则分不出来的请求,交给一个小模型打难度分,分数低的走便宜档位,分数高的才升级到旗舰。这样绝大多数请求在第一级就完成了分流,真正需要额外调用分类模型的占比很小,回归算力成本几乎可以忽略。

3.2 一份可以直接抄的路由配置样例

下面这份配置不是唯一答案,但结构非常有代表性。它先定义优先级规则,再定义兜底分类的阈值,然后按顺序匹配:

  • 请求包含“产品名/价格/保修”等明确业务关键词,且文本长度较小,直接走轻量模型
  • 请求包含“对比”“总结全文”“给推理过程”“对比优缺点”等高频复杂指令,直接走旗舰模型
  • 其余请求交给轻量分类模型,难度评分高于阈值才升级,低于阈值一律走轻量模型

这里有两个细节非常关键。第一个是路由层本身也要做缓存和熔断,不然分类模型一旦出故障,在线请求全部阻塞,只能干等。第二个是路由规则会随着产品功能迭代而失效,最好每两周复查一次分类准确率,看看哪些简单问题被误判去了旗舰,哪些复杂问题被漏判去了轻量。我见过不少团队上线路由后就再也不管,结果业务改了话术、换了领域,旧规则悄悄把高难度请求送进便宜模型,用户投诉一堆,再回头改已经很被动。

3.3 路由上线后的实际收益:效果没降,费用直降

路由在问答应用里上线后,我们统计了分流比例:大约只有27%的请求最终走到了旗舰模型,其余全部落在轻量或中型模型上。整体API费用下降了一半还多,线上质量抽查评分基本持平。业务场景本来就是典型二八分布,少部分复杂问题需要强推理,大部分请求靠轻量模型足够。路由把资源按需分配,是在不牺牲体验的前提下,把成本结构彻底换了一遍。

这里要把账算清楚,不能只看平均单价。路由的价值还在于它让后续优化有了入口:当你想继续降本时,只需要盯住“哪些旗舰请求被过度服务”这件事,继续拆解那一部分请求的共性,就能往下压;当你觉得效果不够时,也能精准定位哪些请求被错送去了便宜模型。整个优化循环由此变得可控。

4. 缓存与批处理:重复问题和离线任务,不该每次都重新花钱

4.1 用缓存挡掉重复请求:从精确命中到语义命中

知识库问答有一个明显特征:用户的高频问题高度重复,问法略有变化,但答案指向的是同一条文档内容。如果每个问题都真金白银地调用大模型,那等于你在同一份答案上反复买单。缓存是这里性价比最高的方案,没有之一。

第一层是精确缓存,把归一化后的用户问题组合上参数做键,命中了就返回历史结果。这一层只能挡住完全相同的请求,命中率通常不高,但实现成本几乎为零。第二层是语义缓存,把用户问题向量化,再和历史问题算相似度,超过阈值就复用当时的答案。这一层能把“保修期是多久”和“多久保修”这类同义不同形的请求也挡在外面。需要注意缓存必须有合理时效,知识库内容一旦更新,以前生成的答案就不能继续复用,否则用户在同一套问题下得到的永远可能是过期信息。我们当时给缓存加了版本号,文档库更新时整库失效,简单粗暴但非常有效。

4.2 离线批处理:把批量任务放进队列,而不是同步逐个调用

很多团队会忽略任务形态对成本的影响。产品里那些报告生成、批量润色、定时总结等功能,最忌讳的就是用一个同步循环去逐个调API。串行太慢,高并发又容易触发限流,限流一出现就是重试,重试账单往往比主流程贵得多。离线任务天然不要求秒级返回,就不该按在线请求的方式去烧钱。

正确处理是统一进入消息队列,用固定并发数消费,同时优先利用厂商提供的批量接口。不少平台对这类非实时任务有价格折扣,允许更长的处理时间,把耗时体现在产品文案里,用户看到的只是“任务生成中”。我们后来把定时日报生成改成队列加批量接口,单次任务成本基本砍半,而且再没有出现过限流重试的隐性支出。

4.3 超时、重试与并发:三个参数直接影响你的账单

性能优化时常会调整超时和重试参数,但很多人没意识到,这个动作本身可能变成成本黑洞。上游响应稍慢,客户端立刻超时触发重试,但上一次调用其实已经在服务端产生费用,结果是用两倍甚至三倍成本换一个“响应及时”的假象。我的建议是区分读场景和写场景。读场景可以适当放宽超时、减少重试次数,把用户的等待感交给流式输出和过渡动画去缓解;写场景则务必做幂等设计,重试之前先确认上一次请求到底有没有成功。

并发数对成本的影响更加直接。并发太高,限流概率上升,重试增多,账单涨;并发太低,任务排队积压,体验崩。一个实用做法是设置“并发水位线”,从低并发慢慢往上压,观察失败率和账单增幅,找到稳定临界点以后固定运行。不要全凭感觉拍一个大并发数,很多隐性成本都是这么“拍”出来的。

5. 响应速度和成本本来就是同一件事:性能优化别只会调大并发

5.1 流式输出:首字节延迟下降,用户感知完全不同

大模型调用天然慢,动辄几秒甚至十几秒。大多数团队遇到“慢”的第一反应是升级模型、加并发、上服务器,但却忽略了慢的本质可能来自“总响应时间”和“首字节时间”的错位。开启流式输出以后,模型边生成边返回,用户几乎在几百毫秒内就能看到第一个字,等待焦虑大幅缓解。这项功能不一定直接省钱,但它能避免你为了解决“慢”而花更大代价去升级模型或加机器。很多时候产品不是真慢,而是把全部内容攒完才吐出来。

5.2 上下文精简:变快和变省是同一件事

请求慢的一个核心原因是上下文太长。输入Token增加,模型要读取的内容变多,计算耗时和费用同步上涨。所以我做性能优化的第一件事往往不是改服务框架,而是去看线上平均输入Token。如果发现每个请求都带着一整本手册的全文,那不管换什么模型都很难快得起来。处理办法和提示词瘦身一脉相承:静态上下文压到最小,文档按相关性动态切片,真正相关的片段才进入请求。

对话轮数多的时候还要做历史压缩。问答应用很容易积累几十轮对话,如果每轮都把完整历史拼进去,上下文会越滚越大。我们的做法是当轮数超过阈值时,先把此前多轮对话做一个摘要,再带着摘要继续往下,既保住了上下文连贯性,也把单次请求的延迟和成本一起降下来。滑动窗口加摘要的组合,在所有长会话场景里几乎都适用。

5.3 限制和降级:与其让所有请求都慢,不如保关键请求更快

并发一高,所有请求都在排队等待,整体体验反而下降。我倾向于在网关层做一些优先级划分,核心问答请求优先占用配额,聊天、润色、灵感生成这类辅助功能可以排队,甚至降级到更便宜的模型。这个思路和机房里的带宽保障相似,总资源就那么多,关键业务保住了,非关键业务先缓冲一下,产品体验整体反而更稳。

这里要特别强调,限流不能只看每秒请求数,更要关注Token消耗速率。不同请求消耗的Token差异极大,按请求数限流很容易漏掉那些“吞Token大户”。把每分钟累计Token数和每分钟调用次数放在一起看,往往能发现几个平时根本注意不到的异常场景,修复之后成本回落非常明显。

6. 自建模型还是继续调API:这笔账必须按流量算清

6.1 两种模式的成本结构完全不同

流量起来以后,很多团队会动心“自己部署开源模型,省掉API费”。这个想法本身合理,却经常低估自建的隐性成本。API是按调用量计费,用多少花多少,团队请求少时它不会追着你收钱;自建则是先付固定成本,服务器、加速卡、带宽、存储、运维人力都要按月摊,不管有没有请求这笔钱都得出。两者的分水岭在于月请求量和平均单次成本。

可以粗略这么算:假设每月请求量是M,一次请求用API的平均成本是C,自建方案每个月折算的固定摊销加运维成本是F。只有当M乘以C明显大于F时,自建才有账可算。流量还没起来就强行自建,只会背上沉重的运维包袱。判断公式虽然简单,但团队常犯的错误是只拿单次调用成本去做对比,完全不看固定成本摊销。

6.2 硬件和量化方案:不是越强越好,而是匹配最重要

如果决定自建开源权重模型,参数量、量化精度和硬件规格必须一起考虑。一个中等规模的开源权重模型,通过4bit量化以后,在单卡或双卡级别的图形加速卡上也能跑出可用效果,适合问答、抽取、改写这类中间任务。但量化会带来一定效果损失,复杂推理场景未必合适;显存不足时模型频繁搬运数据,延迟可能比调API还要高。所以自建前必须先做负载测试,不能只在测试环境里跑一条SQL就下结论。

最容易忽略的还有吞吐测试。不能只看“跑通”,要看在目标并发下的每秒处理量。很多团队租了昂贵机器,业务峰值只有几十路并发,机器空闲率极高,固定成本却月月扣。这种情况退回API反而更划算,把省下来的运维精力投到产品迭代上,性价比要高得多。

6.3 混合部署:让钱花在最需要的地方

我最后的选择往往不是“API或自建”二选一,而是混合部署。简单、高频、格式固定的请求尽量走自建轻量模型,数据敏感、不能出内网的场景更是如此;复杂、低频、需要最新知识的请求继续走在线API。路由层根据流量特征把请求分流到两边,既享受自建的边际成本优势,又保留在线API的强能力。混合部署确实多一套运行环境,多一套监控和故障处理,所以更适合让非核心场景先小范围试点,稳定后再逐步扩大,不要一上来就把核心链路全切过去。

最后再补几句心里话

这个系列做到1.11,我自己最大的感触是,大模型成本控制本质上就是一个资源分配问题,不是单纯“省吃俭用”,而是把有限预算投到产出最高的地方。对我个人来说,最有用的工具不是某个神奇的优化器,而是一张带着Token计量、请求量、缓存命中率、档位分布的成本看板。数据齐了以后,所有优化动作都有了反馈,哪里在烧钱、哪里该加钱,一眼就能看到。

如果让我重新做一遍知识库问答应用,我一定会先把计量埋点做完再上线,而不是等到月末账单出来以后拍大腿。这个习惯看起来不起眼,却能为后续每一轮优化省下一半时间。最后再提一个小建议:把输出Token上限当成正式配置项来评审,别让它在代码里随便躺着一个默认值。这一条在很多项目里,比大多数人想象的要更值钱。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进