跳到主要内容

微调冷启动:云供应商如何将延迟计入你的闲置成本

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的微调变体在平稳的工作日每分钟处理几百个请求,p99 延迟仪表盘基本保持平稳。然后,在周二当地时间 03:14,某个请求的 p99 延迟从 800 毫秒飙升至 4.6 秒,随后恢复正常。第二天晚上,同样的情况再次发生,模式基本一致,时间也大致相同。你向供应商提交了一个工单询问这次飙升。得到的回复准确但毫无用处:他们的仪表盘显示其侧没有任何异常,没有速率限制,没有故障,在飙升时刻你的 token 使用量也很寻常。4.6 秒确实发生了。但账单上没有体现。

这种差距——用户明显感受到的延迟事件与未记录任何异常的账单之间——就是“微调冷启动税”的体现。这并不是你代码中的 bug,也不是供应商侧的性能回退。它是两种计费模式交汇的缝隙:供应商向你收取适配器上的活跃推理时间费用,而将适配器“加载”到服务槽位的成本隐藏在了供应商的基础设施层,在那里,它表现为你的延迟,却是他们的成本。如果你的流量模式低于供应商的预热阈值,那么每次流量回升时,你都要为 p99 延迟中的这段往返时间买单。

陷阱在于,托管微调模型给人的感觉就像基础模型,因为 API 接口完全相同。你只需将模型标识符从 provider/base-large-v3 更改为 acct_123/ft-large-v3-customerA,其余每一行代码都保持不变。基础模型的服务集群是温热的,因为每个客户都在访问它;而你的微调适配器的服务槽位只有在你的流量保持它的情况下才是温热的。在低于特定请求速率时,供应商会将适配器缩容至零,而下一个请求——也就是你的请求,那个用户正在等待的请求——就必须支付重新加载税。

看起来像 Serverless 但定价并非如此的部署模式

大多数托管微调服务都遵循两种模式,它们的冷启动行为截然不同。

第一种是带有热插拔适配器的共享多租户集群。单个基础模型驻留在 GPU 上,而你的 LoRA 适配器是服务器可以换入和换出的数十个或数百个适配器之一。当你的请求到达且适配器当前不在内存中时,服务器会从主机内存(快速,亚秒级)或对象存储(慢速,几秒钟)加载它。这是 Cloudflare Workers AI 和几家超大规模云厂商提供的“自带 LoRA” (BYO-LoRA) 方案所采用的路径。从供应商的角度来看,这是成本最低的,因为基础权重由多个租户摊销。这种路径下的冷启动延迟通常主要由适配器权重的传输决定,最近的研究论文报告称,通过主动预取和 KV 缓存重用等技术可以减少 23–55% 的延迟——但其底线仍然是以数百毫秒计的,而不是稳态请求那几十毫秒的底线。

第二种是专用的预置吞吐量槽位。Bedrock 的微调模型、OpenAI 的预留容量 SKU 以及 Azure 和 Vertex AI 上的同类企业级服务都属于此类。一旦你在这条赛道上微调了模型,你就根本无法通过按需池来提供服务——你必须按小时购买模型单元,最便宜的层级起价约为每小时 7 美元,较大的模型则超过每小时 20 美元。延迟底线非常出色,因为槽位是你的,并且始终是温热的。无论该槽位处理了一个请求还是 100 万个请求,账单都会如期而至。一个每小时 20 美元的模型单元,连续运行一个月大约需要 14,400 美元,而这仅仅是消除冷启动的价格,还没算推理本身的费用。

如果一个团队构建的产品尚不足以支撑每月 1.4 万美元的专用容量支出,默认情况下最终会进入第一条赛道。而第一条赛道存在冷启动问题,这在团队的预算之外。

为什么账单没有体现用户的感受

这种账单选择从供应商的角度来看是合理的,但从你的角度来看则是危险的。当供应商的调度器决定移除你的适配器时,这个决定对你来说是不可见的。当下一个请求触发重新加载时,用户看到的挂钟延迟包含了加载时间,但供应商的计费器只在适配器就绪后才开始计算推理算力。从计费器的角度来看,你购买了一个请求的推理服务。从用户的角度来看,他们等待了四秒钟。

这造成了一种特定形式的仪表盘不匹配。你的应用程序请求时长直方图显示出一个长尾,带有零星的长达数秒的异常值。而你的供应商成本仪表盘显示,这些异常值对应的请求非常寻常——正常的 token 数量,正常的价格。这两个视图永远无法达成一致,运行应用程序的团队开始将这些飙升归咎于网络抖动、调度器故障、用户的连接,或者是除了部署模式之外的任何原因。人们可能需要花费长得令人尴尬的时间才能注意到,这些异常值集中在每次流量低谷的末尾,因为仪表盘的设计初衷并不是为了回答这个问题。

三件事共同导致了这一现象难以被察觉:

  • 重新加载税只影响静默期后的第一个请求,而不是该期间的所有请求。当你开始调查时,流量看起来又恢复正常了。
  • 供应商文档几乎从不明确说明缩容至零的阈值。淘汰策略是平台成本优化的一部分,他们没有动力去公开它。
  • 这种飙升看起来与其他尾部事件(生成内容过长、后端故障重试、瞬时模型错误)完全一样。如果没有具备部署意识的视角,它只是众多异常值中的一个。

将冷启动视为部署级别的 SLI,而非长尾事件

解决这一问题的纪律借鉴了成熟无服务器平台处理 Lambda 冷启动的方法:将冷启动延迟作为一个独立信号进行测量,与稳态延迟区分开来,并针对部署级事件而非请求级事件进行跟踪。

在实践中,这意味着三个仪器化(instrumentation)动作。

为每个请求标记服务插槽是否处于热状态。 如果你的供应商公开了指示冷启动的标头或响应字段,请将其透传到日志中,并据此拆分延迟直方图。如果没有,则进行推断:如果一个请求的端到端延迟超过稳态 p99 的 2 倍以上,且 Token 数量正常,那么它就是一个冷启动候选对象。在边缘情况下,这个信号会有噪声,但一旦你观察流量低谷边界,这些事件的集中度将显而易见。

将冷启动频率作为比率而非分位数进行跟踪。 “有多大比例的请求支付了冷启动税?”是一个比“冷启动请求的 p99 是多少?”更有用的问题。前者告诉你当前的部署模型是否契合你的流量形态;后者告诉你一旦发生冷启动,代价有多惨重。两者都很重要,但大多数仪表板默认显示后者,从不询问前者。

关注日历,而不只是时钟。 冷启动通常集中在流量最稀疏的时段——深夜、周末、节假日——以及供应商默认的 UTC 仪表板所掩盖的人口统计边界。如果一个团队的最大客户分布在一个时区,而其流量仪表板在另一个时区,他们将系统性地误判“冷启动税”支付的时间。如果你服务于 B2B 产品,请按客户所在时区汇总冷启动频率,而不是按供应商的时钟。

遏制冷启动税的模式

一旦冷启动成为你关注的指标,遏制它的选择就会变得清晰可行。

固定热启动容量,规模小于专用层级。 如果你的供应商提供介于共享多租户和完全预留之间的层级——而且他们越来越多地提供此类服务,名称各异,如“始终在线 (always warm)”、“预留适配器 (reserved adapter)”或“低优先级专用”——那么购买刚好能在流量低谷期维持一个热插槽的容量,要比完全预留吞吐量便宜得多。其单位经济效益在于:你在低谷时段支付保温费用,并让共享池吸收高峰时段。许多从共享转向完全专用的团队是因为对事故的恐慌反应,结果几个月后才发现,部分预留本可以用三分之一的成本吸收 95% 的冷启动。

利用合成流量抑制关键路径上的逐出。 针对微调变体,每 30 到 60 秒发送一次心跳请求,可以在大多数供应商的逐出策略下保持适配器常驻。成本是真实的但很小:一个微小的请求,按按需计费率计算,每天运行大约 1–3 美元,具体取决于模型。技巧在于发送一个处理成本极低的心跳负载——一个带有 max_tokens=1 的短提示通常就足够了——并将其范围限定在重要的变体上(面向生产客户的适配器,而不是每个内部实验)。这与 Lambda 保温器的模式相同,但也带有同样的警告:这是一种变通方案,而非合同,供应商可以随时更改逐出策略。

多区域适配器预热。 如果你服务于多个区域的用户,适配器必须在用户可能触达的每个区域都保持热启动。大多数托管微调服务默认将适配器部署到一个区域,而跨区域冷启动比同区域冷启动更昂贵。解决方法是明确地将适配器预先部署到路由覆盖范围内的每个区域,并将合成流量心跳扩展到每个区域。这是账目管理工作,而非工程工作,但跳过这一步的团队在每次区域故障转移时都要支付跨区域重新加载税。

路由降级至基础模型。 最强有力且在架构上最诚实的模式是将微调变体视为首选路径,将基础模型视为可用路径。如果请求到达时微调适配器处于冷状态,则将其路由到基础模型,并使用系统提示词或 few-shot 降级方案,其表现应足够接近微调模型以处理请求,并发送一个指标以便你了解这种情况发生的频率。微调变体仍然是你的稳态选择——few-shot 提示词在 Token 消耗上更贵,质量也略差——但没有用户会为了等待插槽热启动而等待四秒。这与经典服务架构中的“断路器”模式最为相似,其生效原因也相同:在关键请求流中,降级路径几乎总是优于缓慢路径。

Serverless 与托管微调并不共用同一条成本曲线

更深层的教训在于团队在做部署决策时的心理模型。在经典 Web 基础设施中,“Serverless”意味着:按需付费、自动扩缩、无闲置成本。它非常适合峰值明显、利用率低的工作负载,在这种情况下,替代方案是为常驻服务器付费。

托管微调看起来像无服务器,因为按需样式的 API 是一样的。但它们的定价逻辑并不相同。供应商托管适配器的成本模型更接近专用服务器,而非无状态函数——在某个地方有一个热插槽,要么你直接为此付费(预留吞吐量),要么供应商付费并将其摊销到各个租户中(带有逐出机制的共享池)。当你的流量进入后者时,供应商的摊销决策就成了你的延迟预算,而你假设的延迟成本曲线——平坦、可预测、按需——结果证明是非常崎岖的。

正确预估成本的团队在开始时就将两件事纳入了部署计划。他们了解按客户群和时段划分的每分钟请求数 (RPM) 底线,并知道哪些客户群可以容忍低谷时段的一次性多秒延迟,而哪些不能。他们按细分市场而不是按模型选择部署路径。错误预估成本的团队则假设“微调变体”和“基础模型”具有相同的运维特征,因为它们具有相同的 API 接口,结果他们在一次事故中发现了延迟成本曲线的残酷——当时某位客户的 CEO 在现场演示中看到了延迟飙升。

解决方法并不深奥。它是将微调部署视为容量决策而非 API 决策,并在客户发现之前为“冷启动税”定出一个数字。

References:Let's stay in touch and Follow me for more thoughts and updates