教程·阅读约 2 分钟·
OpenRouter 实战避坑:同一个模型,换个 Provider 就像换了另一个模型

OpenRouter 实战避坑:同一个模型,换个 Provider 就像换了另一个模型

同一个 DeepSeek V4 Flash,不同 Provider 的 TAU-Bench 成绩能差二十多个百分点。一位处理过 1800 万条消息的开发者,把用 OpenRouter 踩过的 10 个坑整理成了清单。

原文来源:Mo Moustafa — 处理过 1800 万条消息之后,作者把用 OpenRouter 调开源模型踩过的坑整理成了一份清单。

表面上看,用 OpenRouter 很简单:一个 API Key,几百个模型,OpenAI 兼容接口。但作者说,往下走全是坑。

背景值得先说一句。作者在做一个叫 Olly 的 AI 助手,跑在 iMessage 里,用的是 OpenRouter 上的开源模型。到目前为止 Olly 处理了超过 1800 万条消息,其中大约三分之一走开源模型。这个量级足以把每个边界情况都撞上一遍。

先统一词汇:模型指那堆权重;Provider 是 OpenRouter 把你路由过去的那家公司,权重跑在他们的 GPU 上,用他们选的精度和"专有"优化,配他们自己的 XML 和工具解析器——也就是说,每家也有一份"专有"的 bug 清单。当你要 deepseek/deepseek-v4-flash,背后是大约 20 家你多半没听说过的公司。纸面上是同一个模型,实际上差别很大。

1. 同一份权重,Provider 之间能差 20 个点

OpenRouter 会给同一模型上的不同 Provider 跑基准,常见的是 GPQA Diamond 和 TAU-Bench Airline(工具调用任务)。以 DeepSeek V4 Flash 0731 为例,所有 Provider 提供的权重完全一样:

  • DeepSeek 官方:GPQA 90%,TAU 81%
  • DigitalOcean(同样权重):75% 和 58%

大多数托管商在工具调用上比官方低 5 到 7 个点,还有四家在知识题上直接崩掉。对 Agent 来说 TAU 才是有意义的分数,二十多个点的差距不是噪声。作者补充说 7 月更夸张:Fireworks 的 TAU 只有 46%,和官方差了三十多个点。

结论很简单:信任某个 Provider 之前,先看最贴近你工作负载的那个基准;换模型时也要重新看,因为同一批 Provider 在 GLM-5.3 上的表现完全不同。

—— 广告 ——

2. 图像任务上的不确定性

作者在图像任务上注意到反常行为,就把三张小图(一个字母、一块纯色、一个带背景的词)过了一遍两个开源视觉模型的全部托管商。

结果是:DeepInfra 的 Qwen 把 K 读成 R,把红色说成蓝色,把词"umbrella"描述成"funny",而同样权重的另外四家全对。Venice 和 Together 压根没看到 MiniMax 的图。模型页写着支持图像输入,但有两家 Provider 不支持,更糟的是它们还假装一切 200 OK。

3. reasoning.effort 不是到哪都有用

reasoning.effort 这个参数到处都被接受,但它是否真的起作用取决于模型和 Provider。作者锁定了所有提供 DeepSeek V4 Flash 0731 的 Provider,从生产机器上在 low、high、max 三档各发三次同样的提示,然后对比推理 token 的输出量——差异巨大。结论是:要按 Provider 追踪你的 effort 设置到底有没有生效。

4. 拿精度过滤 Provider 是个坏主意

OpenRouter 允许按声明的精度过滤 Provider,比如 quantizations: ["fp8"],直觉是位数越少模型越笨。作者用这个过滤跑了 DeepSeek 一个月,再把基准榜和各家声明的精度放在一起看——fp4 的托管商落在 fp8 那群的正中间。

DeepSeek 上三个最差的 GPQA 分数,分别来自一家 fp4、一家 fp8,和一家什么都没声明的。GLM 在两个基准上表现最好的 Wafer,什么都没声明。精度是个糟糕的质量代理指标,硬过滤还会缩小 OpenRouter 在 Provider 挂掉时的回退池。作者的建议是:看榜,别看位数。

5. 工具调用的解析器会漏

理想情况是:模型按某种标记发出调用,Provider 的解析器把它转成结构化工具调用,你的代码执行它。但有时解析器会漏,然后模型吐出的原始标记就原样返回,需要你自己兜底。

这种问题的复现率因 Provider 而异,而且很顽固。有两类情况要用相反的思路处理:工具调用被 wrapper 多包了一层,以及回复内容被包住或半包住。

6. 200 OK 但没有答案

推理模型有时把内容全放进 reasoning 字段,返回 content: nullfinish_reason: "stop"——345 个补全 token,HTTP 200,但用户那边什么都没拿到。

200 只说明请求被服务了,不代表里面有答案。没有 content 也没有工具调用,就是失败,应该抛错重试。

7. 空洞补全

相关但不同的问题:有些 endpoint 返回 200,content、reasoning 都是 null,连 usage 对象都没有。7 月是 DeepSeek 上的 StreamLake,占了作者约 20% 的流量和 92% 的空补全。一个月后,同样的事换成了 DeepSeek 0731 checkpoint 上的 Together。

8. 历史记录规则因 Provider 而异

DeepSeek 在思考模式下会输出 reasoning_content 块。在 Agent 循环里,模型经常带着空的 reasoning 发起工具调用。如果你把这个空的 reasoning 历史传回去,而它路由到 SiliconFlow,就会 400 报错 20015,提示 thinking 模式下的 reasoning_content 必须回传。Baidu、Alibaba、Cloudflare 收下同样的历史却毫无怨言。

所以契约不是按模型定的,是按 Provider 定的。而且别想着跳过工具历史,否则模型会一直重试同一个任务。

9. 从生产环境测,别在笔记本上测

这既是为了速度和延迟,本身也是个例子:Venice 和 Novita 在作者的 Mac 上跑 DeepSeek V4 Flash 一切正常,但从自己的基础设施探测几乎每次都 429。同一个 Key,同一分钟。作者的判断是它们按 IP 限流。

要测就从生产环境跑,一次几个,样本量要比你以为的更多。

10. 为什么不干脆锁死一个 Provider

作者一度把 provider.order 设成三家的列表并关掉回退,等于锁了 3 家可靠 Provider 而不是 1 家。两周后:Baidu 开始对一切 429,Cloudflare 被发现根本不再提供这个模型,100% 流量落到 Alibaba,然后 Alibaba 也开始 429。OpenRouter 的头号模型锁在最可靠的 3 家 Provider 上,结果把整个 Olly 拖挂了。

压成几条可执行的规则

把这份经验收拢一下:

  1. 选 Provider 看基准榜,而且要看贴近自己工作负载的那个,不是通用总分
  2. 用精度过滤代替不了实测,反而会缩小回退池
  3. 把"200 但没内容"当成失败处理,抛错重试
  4. 工具调用的解析要有自己的兜底,按 Provider 分别处理和记录
  5. 历史记录的怪癖按 Provider 记,别按模型记
  6. 探测从生产环境发,样本要多
  7. 别把流量锁死在少数几家

原文作者还开源了他在 Olly 里用的解析示例、一个 AI SDK,以及全部原始数据。

分享到
微博Twitter

© 2026 四月

原文链接:https://www.aprilzz.com/tutorials/openrouter-provider-pitfalls