第 3 章 性能与成本优化

学习目标

  • 将一次请求的延迟分解为各个区间,选择预期改善效果最大的环节。
  • 正确处理流式传输事件,区分流式输出能够减少什么,以及不能减少什么。
  • 编排提示词,使缓存命中率提高,并计算使用缓存的盈亏平衡点。
  • 选择适合使用批处理API及相应处理档位的任务,并安全地取回处理结果。
  • 设计按模型档位进行路由的规则和升级条件,以每项任务的成本为依据,判断延迟与成本之间的权衡。

引言

某个团队收到“响应太慢”的投诉后,换用了价格最高的模型。结果响应变得更慢,账单金额也变成了原来的三倍。另一个团队为了节省费用,把提示词缩短了一半,质量却下降了,延迟也几乎没有变化。两个团队有一个共同点:都在测量之前就进行了修改。延迟和成本是多个区间、多个项目相加的结果,其中哪一项占得最多,只有实际测量之后才能知道。

本章从测量开始。我们先学习如何把延迟分解为各个区间,以及OpenAI归纳的缩短延迟原则,然后依次学习:降低用户体感延迟的流式输出,复用重复输入的提示词缓存,以较低费用处理不紧急任务的批处理API和处理档位,以及为每次请求选择适当模型的路由。最后,用每项任务成本这一统一尺度来比较这些方法。

核心概念

将延迟分段

用户的等待时间由多个区间相加而成:应用队列、输入预处理、模型处理、工具执行、后处理、网络传输依次衔接。模型处理也分为读取全部输入与逐个生成输出token两部分。因此,测量指标也分为三种。

指标 含义 主要影响因素
首个token耗时(TTFT) 从请求到首个输出片段到达 队列、输入长度、思考时间、缓存命中
输出速度 每秒生成token数 模型档位、处理档位
完整响应时间 到最后一个token为止 输出长度×速度、工具往返次数

还要从用户角度看“首个可用结果”何时出现。即使首片段很快到达,若必须等结构化结果完整后才能绘制界面,体感延迟仍接近完整响应时间。投诉往往来自尾部,因此应看p95(最慢5%的分界值),而非平均值。

降低延迟的七项原则

OpenAI的延迟优化指南提出了七项原则。这些原则是对通用方法的归纳,无论采用哪一家供应商,都适用。

原则 要点
更快地处理token 较小的模型通常速度更快,价格也更低
减少输出token 输出量减少50%,延迟也会减少接近50%
减少输入token 即使提示词缩短50%,延迟改善也只有约1~5%。除非上下文非常长,否则效果较小
减少请求次数 将原本按顺序执行的步骤合并到一个提示词中,以减少请求往返
并行处理 彼此不使用对方结果的步骤,同时发起调用
让用户少等待 流式输出最为有效。显示当前处理进度也有帮助
不要默认使用LLM 能够提前计算,或用预先确定的界面解决的任务,不调用模型也可以处理

关键在于,输出是影响延迟最大的因素。重复用户问题的开场白、冗长的结束语,以及不必要的全文重写,都会让延迟与成本一起增加。

流式输出如何工作

流式输出以服务器发送事件(SSE)逐步接收响应。就像收到快递发货通知并不改变到达时间一样,流式输出只是更早展示首批内容,并不减少需要生成的token数量或费用。

Anthropic流按固定顺序发送事件:message_start → 每个区块的content_block_start、content_block_delta(多次)、content_block_stop → message_delta → message_stop,其中可能穿插ping。处理时注意以下事项。

  • stop_reason在message_start中为null,在message_delta中确定。
  • message_delta中的usage为累计值,每次事件相加会造成重复统计。
  • 即使已收到HTTP 200,仍可能出现error事件(如overloaded_error)。仅按状态码处理错误会漏掉这些情况。
  • 无须亲自处理事件时,可用SDK累积辅助方法(Python get_final_message()、TypeScript finalMessage())获取完整消息。

OpenAI Responses API发送response.created、response.output_text.delta、response.completed、error等语义事件;Gemini通过SDK流选项或REST的alt=sse启用流式输出。

设计完整流式链路

即使在API中开启了流式输出,用户也可能仍然面对空白界面。这是因为,如果中间层收集响应后才一次性传给下游,流式传输的效果就会消失。因此,需要检查整条传输链路。

  1. 在SSE路径上,关闭反向代理与API网关的响应缓冲。某些压缩设置也可能先聚集片段再发送。
  2. 服务器应将收到的片段立即向下游传递,但界面更新可以按适当单位(句子、100ms)合并进行,以减轻浏览器的负担。
  3. 用户关闭窗口或取消操作时,使用HTTP客户端的取消信号(如AbortController),同时中断上游请求。如果继续把无人查看的内容生成到最后,就只会产生费用。
  4. 对需要后处理的结果,判断能否逐片段处理。OpenAI文档警告,流式输出会让输出内容审核(moderation)变得更加困难。因此,应先确定相关内容是否必须在检查完整个响应之后才能公开。
  5. 对工具参数或JSON,可以将收到的片段依次拼接,但执行工具和保存数据,都必须等内容完整并通过校验之后再进行(第2章)。

提示词缓存原理

可以这样理解:每次开会时,不再把同一份资料从头读一遍,而是在已经读过的部分做上标记,只阅读新增加的页面。提示词缓存会保存对请求前面部分(prefix,前缀)的处理结果,在下一次请求时重新使用。因此,前缀只要有一个字符不同,从那个位置开始就无法再使用先前的处理结果。

提示词缓存并不是保存生成的输出,再把它返回的功能。响应仍然每次重新生成。OpenAI文档也明确说明,缓存不会改变输出token的生成方式。正是在这一点上,它与直接复用先前答案的响应缓存有着根本区别(见深入阅读)。提示词缓存有两方面效果:从缓存读取的输入按更低价格计费;同时,输入处理所需时间缩短,因此首个token能够更早返回。

各厂商缓存比较

项目 Anthropic OpenAI Gemini
启用方式 顶层cache_control(自动)或各区块cache_control(显式),最多4个断点 支持的模型默认启用 Gemini 2.5及之后模型默认隐式缓存
最短长度 按模型为512~4,096token,不足时不报错但不缓存 GPT-5.6及之后为1,024token Gemini 4 Argon与3.x为4,096token,2.5为2,048token
保留时间 默认5分钟,每次使用免费续期,可选1小时 GPT-5.6及之后使用prompt_cache_options.ttl(默认30m,可选12h);更早模型使用prompt_cache_retention(in_memory、24h) 供应商自动管理
价格 写入1.25倍(5分钟)或2倍(1小时),读取0.1倍(部分最新模型更低) GPT-5.6及之后写入1.25倍,读取大多0.1倍(部分模型0.05倍) Gemini 4 Argon缓存输入优惠95%
确认字段 cache_creation_input_tokens、cache_read_input_tokens、input_tokens(最后断点之后) usage.input_tokens_details.cached_tokens Interactions API为usage.total_cached_tokens,generateContent为usageMetadata.cachedContentTokenCount
速率限制 大多数模型的缓存读取不计入每分钟输入token限额(ITPM) 缓存输入也计入每分钟token限额(TPM) —

Anthropic使用缓存时,input_tokens只表示最后一个断点之后的token。总输入应将三项相加。

总输入token = cache_read_input_tokens + cache_creation_input_tokens + input_tokens

Gemini在Interactions API和Gemini 4 Argon及之后模型中仅支持隐式缓存。自行创建管理的显式缓存,只能在支持它的更早模型中,通过generateContent API使用。

编排提示词以提高缓存命中率

三家的共同原则只有一条:不变的放前面,变化的放后面。开头只放一行当前时间,就可能让之后数千token全都无法命中。

  1. 固定顺序。Anthropic按tools → system → messages构成前缀。工具定义、固定指令、参考资料、示例放前面,时间、用户信息、问题放末尾。
  2. 断点放在固定部分末尾。在每次变化的区块设置断点,只会反复写入。
  3. 稳定序列化。工具列表顺序、JSON键顺序、空格若每次不同,即使内容相同也是不同前缀。从集合或哈希表生成工具列表,顺序可能波动。
  4. 掌握破坏缓存的变更。Anthropic修改工具定义会使全部缓存失效;修改tool_choice或增删图片使消息部分缓存失效。修改顶层effort或output_config.format也会使缓存失效。
  5. 检查最短长度。前缀不足模型最低要求时,即使标记也会静默不缓存。
  6. 实测。比较部署前后缓存读取比例,并使用能指出连续请求前缀从何处分歧的工具,例如Anthropic缓存诊断功能。

OpenAI保持工具列表不变,仅用allowed_tools改变可调用范围,有利于保留缓存。prompt_cache_key在更早模型中只影响路由,GPT-5.6及之后主要用于按客户汇总缓存用量。GPT-5.6及之后模型默认在最近消息末尾设置断点,若末尾每次变化,应在固定部分末尾设置prompt_cache_breakpoint才会命中。Anthropic缓存不跨组织共享,Claude API还按工作区隔离。

缓存的盈亏平衡点

写入缓存比处理普通输入更贵,因此,必须有足够多的重复使用,才能获得收益。下面将处理前缀的成本设为1,按照Anthropic的计费倍数来计算。

请求次数(保留期内,相对费用:不缓存1次=1.00) 不缓存 5分钟缓存 1小时缓存
1 1.00 1.25 2.00
2 2.00 1.35 2.10
3 3.00 1.45 2.20
10 10.00 2.15 2.90

以读取价格为0.1倍计算,5分钟缓存在保留时间内的第二次请求开始产生收益,1小时缓存则从第三次开始产生收益(读取价格倍数更低的模型,收益还会更大)。反过来,如果两次请求的间隔长于保留时间,每次都只发生缓存写入,那么5分钟缓存会比不使用缓存贵25%,1小时缓存会贵100%。这时,选择更长的保留时间或关闭缓存更合适。保留时间是从请求开始时计算的,因此,响应生成耗时越长,所剩的缓存可用时间也越短,计算时同样需要考虑这一点。此外,缓存还能提升吞吐量。Anthropic的大多数模型不会将缓存读取计入ITPM,因此,命中率高时,就能在相同限额下处理更多输入。

批处理API

不需要当天送达的包裹,可以用便宜的普通邮寄。批处理API将不需要即时响应的大量请求集中异步处理,并提供折扣。

项目 OpenAI Batch API Anthropic Message Batches API Gemini Batch API
折扣 50% 50% 标准价格的50%
处理时间 24小时窗口 大多1小时内,24小时未完成则过期 目标24小时,超过48小时过期
规模 每批50,000条,输入文件200MB 100,000条或256MB 内联低于20MB,文件最大2GB
结果保留 完成30天后删除输出文件 创建后29天 默认6周
结果配对 custom_id custom_id 自定义键

OpenAI与Anthropic明确说明,结果顺序可能与输入不同,必须按标识符配对。Gemini API参考文档说明按输入顺序返回,但为确保换供应商后同一代码仍有效,按键配对更安全。Anthropic异步校验请求,批次结束才知道格式错误,建议先用Messages API测试一条同格式请求。失败请求计费也不同:Anthropic不对错误、取消、过期请求收费;OpenAI批次过期时取消未完成请求,仅对已完成的收费。可与缓存结合,但Anthropic说明批次内缓存命中是尽力而为,建议公共上下文使用1小时缓存。Gemini批处理文档说明命中部分适用上下文缓存费率,实际单价应查各模型价格表。批处理限额独立于同步API管理。

选择处理档位

同一模型也可以选择不同请求处理档位。

档位 示例 特点
慢但便宜 OpenAI Flex(service_tier: "flex") Batch API费率,响应较慢。容量不足时返回内容为Resource Unavailable的429(不收费)。文档示例将SDK超时从10分钟延至15分钟
快但昂贵 OpenAI Fast mode(原名priority processing,service_tier: "fast") 每token加价。流量骤增时,部分请求降为标准档位,响应显示service_tier: "default"
优先容量 Anthropic Priority Tier(service_tier),部分Opus模型的fast mode(speed: "fast") 是否使用优先容量,通过响应usage.service_tier确认。fast mode有独立速率限制

档位选择取决于时间价值。评估运行或数据补全等晚几分钟也无妨的任务,走便宜档位;客户等待路径中,只有超出延迟目标的部分才走快速档位。使用快速档位时,记录响应中的实际处理档位,关注降级比例。

模型档位路由与升级

所有请求都交给最大模型,就像派大卡车跑附近的小差事。路由按请求特点分配模型,升级(escalation)则在小模型结果不达标时交由更高档模型重新处理。

方式 判断依据 注意事项
规则路由 业务类型、输入长度、客户等级 简单快速,但可能漏掉规则之外的请求
分类器路由 小模型分类难度、意图 分类本身的延迟及误分类成本
基于校验的升级 小模型结果未通过schema或业务校验,则交高档模型 按失败比例增加成本与延迟

不要把升级决定交给模型自报的置信分数,因为置信度并不总与正确性一致。应依据可验证信号(通过schema、包含必需事实、无禁止表述),各路径分别用评估集测量质量、延迟与成本。推理模型也可按同样方式路由推理强度。

判断延迟与成本的权衡

各方法的收益与代价不同。

方法 延迟 成本 代价
流式输出 减少体感延迟 不变 实现复杂度、审核时机
提示词缓存 缩短首个token耗时 重复输入优惠 提示词结构约束、写入加价
缩减输出 大幅降低 降低 重新设计响应格式
批处理、便宜档位 大幅增加 降低 失去即时性
快速档位 降低 增加 加价、降级管理
小模型路由 通常降低 降低 升级设计、逐路径评估

比较时所用的尺度,应是每项任务的成本,而不是单次调用的成本。

每项任务成本 = (全部调用成本 + 重试、升级成本 + 人工审核成本)÷ 通过质量标准的任务数

即使单次调用费用减半,重试和人工修改增加三倍,仍然亏。先确定响应期限与失败成本,再在约束内选择每项任务成本最低的组合。

深入阅读

响应缓存何时有风险

响应缓存会将之前生成的答案原样返回。如果相同的问题很多,这样几乎可以消除延迟和成本。即使问题的措辞略有不同,只要含义接近就返回相同答案的方式,称为语义缓存;它通过嵌入相似度查找以前的问题。这种方法很强大,风险也同样明确。

  1. 个性化与权限。 如果答案中混有特定用户的信息,就可能把这个答案发送给其他人。应在缓存键中加入组织、权限、语言及资料版本,或者不对个性化答案使用响应缓存。
  2. 时效性。 如果作为依据的文档发生变化,缓存中的答案就会成为错误答案。应把文档版本放入缓存键,并在文档修订时使相应条目失效。
  3. 相似度阈值。 阈值过低时,“可以退款的期限”和“可以换货的期限”这样相似但不同的问题,也会收到相同的答案。阈值应通过收集了错误命中案例的评估集来确定。
  4. 修改操作。 对于需要执行工具的请求,不使用响应缓存。

提示词缓存没有上述风险,因为它每次都会重新生成输出。这两种缓存并非相互竞争,而是位于不同层次。对于已确定信息的说明等答案固定的部分问题,可以使用响应缓存;对于其余对话,则普遍使用提示词缓存。

如何公平比较优化实验

有几种常见情况,会让人错误地理解优化效果。第一,把不同缓存状态混在一起测量。第一次请求时缓存为空,因此既慢又贵。缓存为空和缓存已填充的状态,应分别测量。第二,没有同时测量质量。减少输出或换用较小模型,虽然可以降低延迟和成本,却也可能降低质量。因此,必须固定使用同一评估集和通过标准。第三,忽略负载。并发请求数不同,延迟的分布也会不同,因此应以接近实际峰值的并发量测量p95。第四,一次进行多项变更。如果同时修改模型、提示词和缓存编排,就无法知道哪项修改产生了效果。应遵守每次只改一项、再测量一次的原则,并以每项任务成本和p95记录结果。

工作场景

水澜语言学院:14秒空白界面的真相

在线语言学校“水澜语言学院”为学员批改英文作文。从提交作文到结果出现,平均需要14秒,这段时间里界面始终空白。运营团队提出换用更高档的模型,但开发者卓主管先测量了各个区间的耗时。

区间 平均值
服务器队列与预处理 0.3秒
首个token耗时 1.7秒
输出生成(平均950token) 11.2秒
传输至界面 0.8秒

API一侧其实早已开启流式输出。但是,企业内部API网关在开启响应缓冲的状态下转发SSE,导致浏览器在响应结束之前收不到任何内容。另外,延迟的大部分来自输出生成。模型会把整篇作文修改后重新写一遍,再在后面附上冗长的修改理由。

卓主管做了两项修改:在网关的SSE路径上关闭缓冲,并把响应格式改成“需要修改的句子、修改后的句子、一行理由”的列表。只有学员希望重写全文时,才另外发起请求。平均输出从950token减少到340token。第一条批改结果显示出来的时间缩短为2.1秒,全部完成需要5.6秒,费用减少了60%。按照评估集测得的批改准确率则保持不变。

也有被否决的方案。更高档的模型输出速度反而更慢。对于减少提示词中示例的方案,团队考虑到输入只有2,000token左右,预计几乎不会有效果,因此没有尝试。

原野流通:将评价回复分成三条路径

农产品网店“原野流通”每天为约9,000条商品评价生成回复草稿。由于全部评价都通过同步API和高档模型处理,成本不断增加。公司的政策是:普通评价在48小时内回复,1~2星的投诉评价则必须在30分钟内回复。

平台工程师魏经理根据回复时限,将处理路径分开。

  1. 投诉评价(约占11%)进入同步处理路径。先由小模型生成草稿,再由校验器检查必需元素(道歉、处理措施说明)和禁止元素(承诺补偿金额、断言未经确认的原因)。未通过检查时,升级至中档模型重新处理。第一周的升级比例为14%。
  2. 普通评价每天分两次提交给批处理API。将评价ID写入custom_id来配对结果,只有过期或发生错误的条目才重新放入下一批。
  3. 将回复指南和语气示例(约3,000token)固定在提示词前面,把评价正文和商品信息放到末尾。

团队以每项任务的成本比较了各方案。把需要人工修改的草稿审核时间也计入之后,发现全部评价都用小模型处理的方案,虽然调用费用最低,但投诉评价的修改时间增加,导致每项任务成本反而更高。最终方案的每项任务成本是原来的31%。团队也考虑过响应缓存,即对相似评价直接复用以前的回复;但由于回复会根据订单详情和商品状态变化,最终没有采用。

易错点

  • 流式输出能够降低成本。 它减少的只是用户感受到的延迟,需要生成的token数量与费用都保持不变。
  • 提示词缩短一半,延迟也会减少一半。 延迟主要由输出长度决定。减少输入所带来的延迟改善通常较小。
  • 延长缓存保留时间,就能提高命中率。 如果请求前缀每次都不同,无论保留多久,都不会命中。应先修正内容顺序与序列化方式。
  • 只要加上cache_control,就会使用缓存。 如果长度没有达到相应模型的最低要求,就不会缓存,而且不会报错。应通过使用量字段来确认。
  • 批处理结果会按输入顺序,在几小时内返回。 OpenAI和Anthropic不保证结果顺序;无论哪家供应商,处理时间都只在承诺的范围内确定(如最长24小时)。应按标识符配对结果,并做好请求过期的准备。
  • 缓存读取在所有供应商处都不计入速率限制。 Anthropic的大多数模型不把缓存读取计入ITPM,但OpenAI仍将已缓存的输入计入TPM。
  • 先使用小模型,总是比较便宜。 必须把升级、重试及人工修改的成本也加在一起,按每项任务的成本作出判断。

要点速览

  • 延迟分为TTFT、输出速度、完整时间,用p95测量。输出长度是最大变量。
  • 流式输出用于减少体感延迟,需检查网关缓冲、取消传播、审核时机的完整链路。
  • Anthropic流:stop_reason在message_delta中确定,用量为累计值,200之后仍可能出现error事件。
  • 缓存复用前缀。固定内容在前,变化内容在后,固定序列化,检查最短长度。
  • Anthropic 5分钟缓存从第二次、1小时缓存从第三次使用开始划算(读取0.1倍)。间隔长于保留期则亏。
  • 三家批处理均优惠50%。OpenAI、Anthropic不保证顺序,应按标识符配对并准备应对过期。
  • 处理档位:便宜档位牺牲速度,快速档位付出加价与降级管理成本。
  • 路由升级依据可验证信号,比较采用每项任务成本。

查阅官方文档

自测

3-1. 定义单次请求延迟测量应区分的三项指标,说明为什么看p95而非平均值。

3-2. 列出API启用流式输出后用户仍看到空白界面的两个原因,并写出应检查的流式链路项目。

3-3. 计算Anthropic 1小时缓存(写入2倍、读取0.1倍)在保留期内复用相同前缀多少次才划算,并与5分钟缓存(写入1.25倍)比较。

3-4. 说明提示词缓存与响应缓存分别复用什么,并解释对混有用户专属信息的答案使用响应缓存的风险与对策。

3-5. 列举模型档位路由中可替代模型自报置信分数的三种升级信号,解释升级比例对每项任务成本的影响。

3-6. 为响应期限分别为即时、4小时、三天的三项业务,制定选择处理路径(同步、处理档位、批处理)与模型档位的决策表,并说明依据。

实操练习

练习

延迟分段测量(45分钟)

  1. 为生产或练习中的一个功能加入分段计时器,分别测队列与预处理、首个token、输出完成、后处理、传输至界面。
  2. 同样20个输入分别关闭、开启流式输出运行,同时记录输出token数。
  3. 再制作一个通过改变响应格式缩减输出的版本,运行相同20个输入,同时记录是否达到质量标准。

完成标准: 用一张表展示三版本的TTFT、完整时间p95、平均输出token、质量通过率,并用数字说明效果最大的变更。

练习

缓存编排与盈亏平衡实验(45分钟)

  1. 用超过最短缓存长度的固定指南与简短问题构建提示词。
  2. A版将当前时间放开头,B版放末尾。两版都在固定部分末尾设置缓存断点(Anthropic cache_control,OpenAI GPT-5.6及之后用prompt_cache_breakpoint)。
  3. 每版以1分钟间隔发送相同问题五次,记录缓存相关用量字段。
  4. 按所用供应商价格倍数计算两版输入成本,也计算请求间隔长于保留期时的费用。

完成标准: 用表格展示两版缓存读写token与费用,各用一句话解释差异原因及盈亏平衡请求次数。