使用 VLM(视觉语言模型)作为生成图像的闸门,并通过 Bifrost 实现供应商故障转移
使用 VLM(视觉语言模型)作为生成图像的闸门,并通过 Bifrost 实现供应商故障转移
TL;DR:在 Photoroom,我们在生成的产品图像到达客户之前,会运行一个视觉语言模型作为最后一道检查。当某个 VLM(视觉语言模型)供应商出现性能下降时,这道闸门就会停滞,导致图像排队积压。我们将 Bifrost 部署在这些调用之前,以实现自动故障转移和按团队预算控制。以下是它解决的问题,以及它未能解决的问题。
一切都在等待的闸门
先介绍一些背景,因为这里的架构很重要。Photoroom 使用扩散模型生成产品照片。在图像被提供之前,会经过一道 VLM(视觉语言模型)检查:裁剪是否干净,物体边缘附近是否存在幻觉伪影,接触阴影在物理上是否合理。我们最初使用 GPT-4o-mini 来处理这一检查,后来在边缘情况下又加入了 Claude 和 Gemini 作为第二意见。
这里的微妙之处在于,这个 VLM(视觉语言模型)步骤在服务路径上是同步的。扩散采样可以完美运行,28 步,在 L40S 上耗时 1.4 秒,但如果审核调用挂起,客户仍然需要等待。
而它确实会挂起。三月份,我们记录到一个 6 分钟的时间窗口,其中某个供应商的视觉端点在约 40% 的请求上返回了 529 错误。我们的闸门设置了 12 秒的超时,因此这些请求并没有快速失败,而是卡在那里。在我们的重试逻辑放弃之前,标题和检查工作进程的队列深度增加了两倍。
我们期望从网关中获得什么
在评估任何方案之前,我在白板上草拟了需求——这是我通常的启动方式。共有三点。
第一,一个统一的多模态接口,这样相同的 base64 图像负载可以发送到 OpenAI、Anthropic 或 Vertex,而无需在我们的 Python 服务中使用三个独立的客户端包装器。第二,自动故障转移,以便返回 529 错误的供应商可以被跳过,而无需我们发布新代码。第三,按团队预算核算,因为研究组织和生产组织共享密钥,我永远无法判断哪个实验消耗了月度预算。
我们研究了 LiteLLM、Portkey 和 Bifrost。现在我们运行的是 Bifrost。精确说明原因的话,它是一个 Go 二进制文件,附加值低延迟,并且我们在同一 VPC 内的推理集群旁边自行托管它,因此没有额外的网络跳转到 SaaS 控制平面。
取代重试代码的配置
无缝替换是打动团队的部分。我们的服务已经使用 OpenAI 的聊天补全格式,因此 Bifrost 可以作为直接替代品插入:只需修改端点 URL,然后我们就在配置中定义了按供应商的路由、故障转移顺序和预算限制。以下是为我们运行的内容(为清晰起见进行了简化):
routes:
- name: vlm-gate
model: gpt-4o-mini
fallbacks:
- claude-3-opus
- gemini-1.5-pro
provider_order:
- openai
- anthropic
- google
budget:
team: prod-vlm
monthly_limit: 5000
这意味着单个服务调用 model: gpt-4o-mini 可以回退到 Anthropic 或 Google,而无需在我们的 Python 代码中编写条件逻辑和重试循环。预算字段将每个请求计入 prod-vlm 团队,并在接近上限时静默拒绝新调用,从而防止财务意外。
延迟问题:不是网关的错,但仍然很痛苦
坦率的实况调查:Bifrost 添加了约 3 毫秒的代理延迟,这可以忽略不计。但是,即使有故障转移,第一个供应商的超时仍然会延迟整个请求,达到我们配置的超时值。在 529 事件中,当我们设置 12 秒超时且 OpenAI 持续失败时,Bifrost 在故障转移之前等待了整整 12 秒。然后 Claude 成功了,但请求已经慢了 12 秒。
我们调整了每个供应商的超时值。现在 OpenAI 在 Bifrost 级别获得 5 秒,如果失败,Claude 和 Gemini 各自获得 3 秒。总截止时间为 12 秒,但如果在 5 秒内检测到 529,我们会在 5 秒后转移到下一个供应商,而不是 12 秒。这有助于,但并非万能药:如果某个供应商在超时边界上恰好返回 200,但渲染速度很慢,你仍然会在它上挂起。网关无法区分即将发生的超时和即将成功的响应。
比较:我们之前未能追踪的预算
预算追踪功能出乎意料地成为一个显著的胜利。在 Bifrost 之前,我们的月度 OpenAI 账单是一个神秘的单一数字。现在仪表板显示 prod-vlm、research-exp 和 prototyping 各自消耗了多少。我们发现,一个研究实验使用大型上下文缓存提示进行批量评估,消耗了 prod-vlm 团队 30% 的预算。我们移动了那个工作负载,账单下降了,而无需争论“谁用了所有密钥。”
它没有解决什么
Bifrost 无法神奇地使提供商更快。如果两个供应商同时出现故障,你仍然会降级。三月份,OpenAI 和 Anthropic 在 7 分钟的时间窗口内都出现了 5xx 错误。Bifrost 忠实地尝试了所有三个提供商,并在 12 秒后失败了,用户收到了 503 错误。没有魔法。
它也不能帮助你进行 VLM(视觉语言模型)版本管理,或检测同一模型的缓慢退化。如果供应商悄悄降低了准确性但延迟正常,Bifrost 感到满意,但你的图像质量检查可能会接受到更差的输出。我们通过一个单独的监控管道来捕获这一点,该管道将已知为无瑕疵的一组合成图像发送给所有提供商,并跟踪每次调用的一致性分数。
它还没有解决根本的同步架构问题。将 VLM(视觉语言模型)检查移到后处理队列中,并将图像立即返回给用户,这将完全消除闸门问题,但代价是更复杂的最终用户状态管理。我们在这个方向上进行了实验,但我对那部分结果还不满意。
基于我们一周经验的结果
对于在生成图像路径上运行同步质量检查的团队来说,一个带有故障转移和预算核算的网关提供了一个净收益。具体来说:
- 我们在生产服务中移除了 40 行 Python 重试和路由代码。
- 按团队的预算可见性将我们的 VLM(视觉语言模型)月度账单降低了约 15%,因为我们将迁移了不需要的工作负载。
- 在单个供应商中断的情况下,中位数端到端延迟从 14 秒下降到 6 秒(5 秒超时 + 3 秒从下一个提供商获得响应)。
下一个里程碑是适当的异步架构,这样闸门永远不会阻塞渲染管道。但与此同时,Bifrost 作为我们可能期望的中间步骤表现良好。