🎁 新人 免费注册,送 10 次调用,最高 $1,免绑卡。
上游漂移:默认路由如何推高 LLM 成本

上游漂移:默认路由如何推高 LLM 成本

目录
  1. 触发漂移的两个条件
  2. 20 次完全相同的请求会发生什么
  3. 结论 A:预期成本与实际成本
  4. 结论 B:缓存不可达,延迟收益也不存在
  5. 五分钟审计自己的配置
  6. 应该关注什么
  7. 结语
  8. 常见问题

你已经启用了 prompt cache,命中计数器也偶尔会跳一下,但账单几乎没变。先别急着怪 prompt 结构,应该检查一个控制台通常不会展示的信息:每次请求究竟由哪个上游处理。

多供应商网关会把同一个模型分配给多个上游供应商,并为每次请求选择其中一个。Prompt cache 按供应商隔离,通常在供应商内部还会按节点隔离。因此,第二个完全相同的请求如果落到另一个上游,即使 prompt 一个字节都没变,也会 cache miss。这就是上游漂移。在按 token 计费的模型上,它会悄无声息地成倍推高成本。

TL;DR

  • 使用出厂默认路由时,某个多供应商网关把 20 次完全相同的调用分散到了 9 个上游,prompt cache 只命中 4/20。
  • 单后端网关在相同负载下命中 19/20;受漂移影响,前者本轮成本约为后者的 3.9x($0.0102 对 $0.0026)。
  • 在实测的 DeepSeek 系列模型上,一次 cache miss 的成本约为命中的 4x(每次调用的中位数分别为 $0.00062 和 $0.00015)。
  • 漂移情况因模型而异:同一个网关把某个 GPT 级模型的全部 20 次调用都路由到同一个上游,命中率为 19/20。

触发漂移的两个条件

这不是你主动选择的错误配置,而是开箱即用的默认行为:

  1. 默认自动路由。 请求只指定模型,没有固定上游,因此网关会为每次调用选择上游。
  2. 供应商默认排序 = “default (balanced)”。 网关会在符合条件的上游之间做负载均衡,而不是始终使用同一个上游。

两项都是出厂默认设置。什么都不改就会发生漂移;要避免漂移,反而必须修改配置。

20 次完全相同的请求会发生什么

我们在上述默认配置下,向一个常用的多供应商网关连续发送了 20 次相同的、前缀约为 8K token 的请求,并要求每次返回上游自身报告的供应商和缓存字段。对于 DeepSeek 系列中使用磁盘缓存的某个模型:

  • 20 次调用由 9 个不同的上游处理:N***aS***wM***hD***aA***LP***lS***eV***eA***d
  • Cache 命中率:4/20(20%)。 只有请求碰巧落到已经缓存该前缀的上游时,才能命中。

把相同的 20 次调用发送给单后端网关,也就是一个模型只对应一个上游且不做负载均衡,完全相同负载的命中率为 19/20(95%)。模型、prompt 和调用次数都相同,唯一的变量是路由是否发生漂移。

作为对照,在完全相同的多供应商网关上,某个 GPT 级模型的全部 20 次调用都被路由到了同一个上游(A***e),命中率为 19/20。漂移并不会均匀影响所有模型,而只会影响网关碰巧分散到多个上游的模型。在本轮测试中,受影响的是 DeepSeek 系列模型。

结论 A:预期成本与实际成本

发生漂移的模型,其单次调用成本会按照缓存结果明显分成两档:

调用类型每次调用成本中位数
cache hit~$0.00015
cache miss~$0.00062

在这个模型上,一次 miss 的成本约为一次 hit 的 4x(如果只看原始输入 token,公开定价的差距更大,约为 50x)。再计算 20 次调用的总成本:

场景命中率20 次相同调用的成本
预期(缓存可达)95%$0.0026
实际(默认漂移)20%$0.0102

模型、prompt 和 20 次请求完全相同。上游漂移让本轮成本增加到 ~3.9x。缓存始终处于“开启”状态,只是路由层让大部分 token 都按 miss 价格计费。生产端点如果一整天都在重复发送较长且稳定的前缀,这部分差额将占据绝大多数输入成本。

结论 B:缓存不可达,延迟收益也不存在

缓存不只影响成本。Prefill 预热后,首个 token 会更快返回。路由漂移导致缓存不可达时,这部分加速同样会消失。我们对重复的相同调用测量了首 token 延迟(TTFT):

GPT 级模型(始终路由到同一个上游,缓存可达):

调用TTFT
第 1 次(冷缓存,miss)~1760 ms
后续调用(热缓存,hit)~1130 ms

缓存让首 token 的返回速度提高了约 36%,而且表现稳定:每次热缓存调用的延迟都集中在很窄的区间内。

DeepSeek 系列模型(默认漂移,缓存很少可达):

  • 连续重复调用 10 次,cache hit:0
  • 各次调用的 TTFT 在 ~1000 ms 到 ~4500 ms 之间波动,偶尔还会返回空响应。

由于几乎每个请求都会落到一个全新的上游,延迟始终停留在冷 prefill 水平,还会受到实际响应供应商延迟波动的影响。GPT 模型通过可达的缓存将 TTFT 降低了 36%;发生漂移的模型没有任何改善,最快与最慢调用之间还相差 4.5x。

五分钟审计自己的配置

不要直接相信这些数字,也不要直接相信任何人的数字。连续多次发送相同的长前缀,观察两个字段即可。代码中没有写死任何域名,通过环境变量指向你自己的网关。

import os, uuid
from openai import OpenAI

client = OpenAI(api_key=os.environ["GW_KEY"], base_url=os.environ["GW_BASE"])
SYS = f"[probe {uuid.uuid4().hex}]\n\n" + ("You are a support assistant. " * 300)

seen, hits = {}, 0
for i in range(20):
    r = client.chat.completions.create(
        model=os.environ["GW_MODEL"], max_tokens=16,
        messages=[{"role": "system", "content": SYS},
                  {"role": "user", "content": f"q{i}"}],
        extra_body={"usage": {"include": True}})
    d = r.model_dump()
    det = r.usage.prompt_tokens_details
    cached = (getattr(det, "cached_tokens", 0) or 0) if det else 0
    seen[d.get("provider")] = seen.get(d.get("provider"), 0) + 1   # populated when exposed
    hits += 1 if cached else 0

print(f"hit rate {hits}/20; upstreams seen: {len(seen)}")

同一个模型出现多个上游,就说明存在漂移。如果命中率远低于 prompt 的稳定程度,就说明你正在为漂移额外付费。更完整的方法参见 LLM 网关是否虚报缓存命中?

应该关注什么

解决漂移需要从路由结构入手:把同一个模型稳定地路由到固定后端,确保下一个请求能够访问已经预热的缓存。不要对每次调用进行负载均衡,把它分配给从未见过该前缀的新上游。评估网关时,连续 20 次发送相同前缀,然后统计上游数量。理想结果是 1 个。出现 9 个,就意味着额外成本。

需要明确的是,所有平台的 prompt cache 都是尽力而为。即使使用单一后端,采用磁盘缓存的模型在长时间空闲后,命中率仍会下降。消除漂移不会让缓存永久有效,但能消除最大、也最浪费的一类 miss。这类 miss 并非你主动选择,而且通常不可见。

结语

“支持 prompt cache”和“你的缓存可达”是两回事。一个网关即使不断把同一模型轮流分散到不同上游,也可以如实声称支持缓存,但实际结果可能只有 20% 的命中率、约 4x 的账单,以及相差 4.5x 的首 token 延迟。真正应该关注的,不是服务是否宣传支持缓存,而是实测命中率,以及相同请求实际经过了多少个上游。运行探测脚本,让数据给出答案。

完整审计方法参见 LLM 网关是否虚报缓存命中?;要了解缓存存在的原因,参见 KV Cache 与 TTL 的工作原理

常见问题

这是我这边的配置错误吗? 不是。出厂默认配置就会出现这种情况:使用自动路由,同时将供应商排序保留为 “default (balanced)”。要避免漂移,需要主动固定上游,而不是反过来。

固定一个上游就能解决吗? 它能消除跨供应商漂移,但单个上游通常仍运行多个副本,而且不一定具备前缀亲和性,因此命中状态仍可能反复变化。固定后应该重新测量,不要直接假设问题已经解决。

为什么 GPT 级模型没有发生漂移? 在本轮测试中,网关碰巧把它路由到了单一上游。漂移因模型而异,取决于网关会在多少个符合条件的上游之间进行负载均衡,并不会均匀发生。

成本差距真的有 ~4x 吗? 从实测的单次调用总成本看,一次 miss 约为一次 hit 的 ~4x;按照这一模型类别公开的原始输入 token 定价,hit 与 miss 的差距更接近 50x。无论按哪种口径,把原本应当命中的请求变成 miss,都是成本上升的主要原因。

应该监控哪一个指标? 持续监控每个模型的 cache 命中率,同时统计每个模型对应的不同上游数量。命中率下降或上游数量增加,都意味着实际 token 成本已经上升。

← 返回博客