从文本到多模态路由:vLLM 语义路由中的视觉信号加固
大多数路由系统都是从提示词(prompt)开始并选择一个模型端点。vLLM 语义路由器(VSR)采取了不同的策略:在请求到达服务模型之前,系统应提取信号,将这些信号组合成决策,并使所选路径具有可观察性、可审计性和可编程性。
这一理念始于文本。Iris 引入了“信号-决策”架构,使 VSR 不再局限于固定的领域分类器,而是演进为一个更丰富的系统,其中意图、关键词、嵌入、安全性、PII(个人身份信息)、语义缓存和插件都可以参与路由决策。Athena 将这一理念进一步推进:语义路由器不仅是 vLLM 前端的一个快速分类器,更是面向模型混合(Mixture-of-Models)和智能体部署的系统级智能层。

下一个前沿领域是多模态路由。一旦图像、截图、扫描件或文档页面进入请求,路由器就不再仅仅针对提示词进行推理,而是在针对请求证据进行推理。图像可能是使该请求变得临床化、受监管、涉及安全敏感、域外或值得路由到更强大的视觉语言模型(VLM)的关键部分。如果路由器只能看到文本,那它处理的就是一个残缺的请求。
本文旨在探讨如何跨越这一边界。关键步骤不仅仅是添加一个图像编码器,而是将视觉证据转化为可信的 VSR 信号,使其能够与文本信号在同一个决策架构中进行组合。
下文的“强化”故事解释了为什么这种区别至关重要。一个基于 multi-modal-embed-small 的多模态路由路径看起来出现了“自信的错误”。最初的解释似乎很明显:也许是因为紧凑型视觉编码器不够强大。但真正的问题对于生产系统而言更具价值且更为关键:VSR 使用的 Rust/Candle 路径与同一模型的 PyTorch 参考路径不匹配。
多模态路由不仅仅是图像分类
纯文本路由早已不仅仅处理主题匹配。在“信号-决策”模型中,信号是独立的观察结果,决策将这些观察结果按优先级和布尔逻辑进行组合,插件或模型引用则定义接下来的操作。这种分离使 VSR 能够表达诸如“安全敏感的代码审查应使用更强的推理模型和越狱检查”这类策略,而不是简单的“计算机科学请求进入代码模型”。
多模态路由保持了同样的形态,但将分析单元从文本提示词转变为完整请求。文本可能是通用的,而图像却携带了决定性的证据。
| 请求证据 | 纯文本路由看到的内容 | 多模态路由应看到的内容 |
|---|---|---|
| “总结这个” + 护照图像 | 通用总结 | 身份证明文档、PII 风险、受限处理 |
| “这显示了什么?” + 胸部 X 光片 | 模糊的视觉问题 | 临床图像、医疗领域策略、具备能力的 VLM 目标 |
| “找 Bug” + 代码截图 | 编码请求 | 代码构件、潜在机密泄露、安全审查路径 |
| 医疗提示词 + 不相关的汽车图像 | 医疗文本 | 域外视觉证据、澄清或拒绝路径 |
创新之处不在于 VSR 可以计算图像嵌入,而在于图像嵌入成为了一种类型化信号,与文本意图、PII、越狱、领域、语义相似度、插件和模型选择处于同一架构中。换句话说,多模态支持将 VSR 从“提示词级路由”提升为“请求级策略”。

这也是信号正确性为何成为控制平面要求的原因。如果文本信号出错,策略可能会路由到错误的模型或跳过错误的插件。如果视觉信号出现反相关(anti-correlated),问题会更严重:路由器可能会产生“自信的错误”,同时还留下清晰、可重复的审计轨迹来支持错误的决定。
因此,参考一致性(Reference parity)不仅仅是模型质量卫生问题。对于 VSR 而言,它是控制平面的不变量。部署的信号路径必须与参考模型路径含义一致,否则决策层组合的就是错误的证据。
当视觉信号表现出“自信的错误”时
第一个征兆并非准确率的小幅下降。在一项跨越 3 个垂直领域、包含 21 个候选标签的 11 张图像探测测试中,部署的 multi-modal-embed-small (mmes) 路径在 11 张图像中有 9 张将错误的垂直领域排名最高。医疗 X 光片的得分比医疗候选者更接近半导体候选者。身份证明文档也无法可靠地落在身份锚点附近。
这是 82% 的倒置率。该信号不仅是有噪声的,而且是反相关的。

对于路由器来说,这种失效模式比基准分数更重要。一个弱分类器通常会产生不确定性,而一个倒置的分类器会以错误的方向产生自信。在多模态策略层中,这可能比根本没有图像信号更糟糕。
暴露该问题的生产表面是围绕 multi-modal-embed-small 的图像模态路由工作,包括 vllm-project/semantic-router PR #1881 中引入的 E2E 路由配置。一旦真实图像流经 Candle 绑定路径,差距就显现出来了。
诱人的解释:升级编码器
最初的假设很自然:也许是紧凑型编码器对路由任务来说不够强大。与此同时,团队正在探索 SigLIP2 系列和更大的 multi-modal-embed-large (mmEL) 方向。这使得升级编码器看起来是个明显的修复方案。
我们直接测试了该假设:
- SigLIP2-base 在同样的 21 个候选探测中得分为 10/10。
- 通过 Hugging Face Transformers 运行的 SigLIP-base 也获得了 10/10。
- 其视觉塔基于 SigLIP2 的 mmEL 得分为 10/10。
- 直接通过 PyTorch 参考路径加载的 mmes 模型卡也获得了 10/10。

这一结果改变了调查方向。编码器系列不是根本问题。即使是之前所谓的“失败”的 mmes 模型,在通过参考路径加载时表现也是正常的。
这次探索并非徒劳。更大的 SigLIP2-so400m 变体在此次探测中表现出了更强的域外拒绝能力,比小型变体更有效地抑制了意外包含的汽车引擎图像。这在内存允许的情况下对于未来的防御性路由可能很重要。但它并不是导致生产信号倒置的那个 Bug。
改变调查方向的参考检查
决定性的测试很简单:通过两条路径在相同的护照固定样本上运行同一个 mmes 模型,并比较嵌入行为。
PyTorch 参考路径针对相关护照锚点返回的余弦相似度为 0.7204。部署的 Candle 绑定路径在同一图像和概念管道上返回了 0.1576。在同一模型和固定样本上,这存在 5-8 倍的数量级差距。

至此,调查不再是关于模型选择的问题。有价值的问题变成了:生产路径在何处偏离了参考路径?
教训很直接:对于多模态路由,参考比较应该是第一诊断手段,而不是最后手段。当生产嵌入路径表现异常时,在假设模型本身过弱之前,请先将其与模型卡的参考加载器进行对比。
这在 VSR 中尤为重要,因为嵌入不仅仅是一个检索基元,它还可以成为策略证据。如果该证据的方向与参考模型相反,那么下游的每一层在逻辑上可能是正确的,但在操作上却是错误的。
究竟哪里出了问题
偏差源于 Candle 路径的实现细节,而非模型权重。通过三次修复,问题被隔离到了具体的层级。
首先,池化头(pooling head)是错误的。candle-binding/src/model_architectures/embedding/multimodal_embedding.rs 中的 SigLIPVisionEncoder::forward 实际上执行的是 BERT 风格的 mean + Linear + tanh 池化,而 SigLIP 使用的是注意力探针池化头。PR #1927 在 Candle 绑定中复刻了 SigLIP 的多头注意力池化行为。
其次,图像归一化路径不完整。Go 图像加载器生成的是 [0, 1] 范围内的 CHW float32 像素,而 SigLIP 期望的归一化等同于 (x - 0.5) / 0.5。PR #1928 在 Rust 编码器路径中应用了该归一化。
第三,预处理在池化和归一化修复后仍存在残留偏差。旧的 Go 端调整大小路径使用了 4-tap 双线性实现。PyTorch 参考路径通过 SiglipProcessor 使用 PIL 风格的图像预处理。PR #1943 使用 image crate 并结合 Catmull-Rom 过滤,将图像解码、调整大小和 CHW float32 转换移动到了 Rust 端,以近似 PIL 的双三次+抗锯齿行为。

这类 Bug 在跨语言服务堆栈中极易被忽略。Go 层、Rust FFI 层、Candle 模型实现和 PyTorch 参考路径单独看起来似乎都合理,但在端到端组合时却产生了破坏路由的差异。
验证状态
以下数据是 #1927、#1928 和 #1943 分支堆栈的测量结果。它们作为所提议强化路径的验证追踪。在三个 PR 合并之前,这些数据应视为分支堆栈验证,而非正式发布的生产行为。
针对典型护照固定样本 (inrule_identifier_passport.jpg) 的三向量隔离实验,将模型前向偏差与预处理偏差分离开来:
| 对比 | 余弦相似度 | 最大绝对差 | 隔离内容 |
|---|---|---|---|
| Python vs Candle-PIL | 0.999989 | 0.000911 | 仅模型前向 |
| Candle-PIL vs Candle-Go | 0.999916 | 0.001992 | 仅预处理 |
| Python vs Candle-Go | 0.999902 | 0.002120 | 完整分支堆栈管道 |
第一行显示 Rust 模型前向路径可以在 fp32 级别噪声内与 PyTorch 参考路径匹配。前两次修复后剩余的偏差存在于预处理中,这就是为何将预处理移动到 FFI 边界之外至关重要。
涵盖标识符、环境、代码、对抗样本和域外示例的 20 张图像语料库的测量结果为:
- 余弦相似度:最小 0.999557,平均 0.999919,最大 0.999978
- 20/20 张图像的余弦相似度 >= 0.999 (对比 PyTorch 参考路径)
- 修复前,典型样本的预处理余弦相似度为 0.990145

重要的结果不仅是最终的余弦数值,而是这种隔离方法:将生产路径与参考路径进行对比,分离模型前向偏差与预处理偏差,然后在测试和服务中使生产路径使用与参考相同的预处理语义。
这为 VSR 带来了什么机遇
一旦视觉路径变得可信,VSR 就可以将图像视为一等公民证据,而不是辅助通道元数据。这一解锁比简单的“将图像请求路由到图像模型”更有意义。它允许文本和图像证据参与同一个“信号-决策”架构:
| 组合信号模式 | 决策示例 |
|---|---|
| 临床文本 + 临床图像 + PHI/PII 信号 | 路由到启用了隐私插件的受保护医疗 VLM 路径 |
| 通用文本 + 身份标识图像 | 在模型调用前进行拦截、脱敏或路由到身份文档处理策略 |
| 代码/安全提示词 + 代码截图 | 路由到安全专用模型,并在原始请求上保留越狱检查 |
| 域内文本 + 域外图像 | 要求澄清或拒绝图像证据,而不是强制执行错误的路由 |
这是 Iris 和 Athena 路线的自然延续。Iris 使路由决策具备了组合性。Athena 通过增加更强的模型堆栈、模型选择、记忆、重放和更丰富的信号处理,使路由器更具策略性。多模态路由将该架构从语言控制扩展到了请求级别的控制。
与此工作相关的公共演示地址为 shrader.dev。目前它演示了策略模式的文本路由版本:领域相关性检查、隐私敏感路由以及模型调用前的阻塞结果。该演示很重要,因为它展示了添加图像之前策略的形态。

文本路由路径还说明了一个对多模态生产至关重要的性能特性。分类器信号可以通过 runSignalDispatchers 并发运行,因此墙上时钟延迟受限于最慢的已启用分类器,而不是所有分类器之和。在代表性追踪中,完整的分类决策在 CPU 上大约在 1.3 秒内完成。

该故事的多模态版本并非独立的生产路径,它是同一个具有更大证据表面的策略引擎。图像和文本信号应通过相同的路由语义进行提取、验证、组合、重放和审计。
这就是强化工作的重要性所在。如果 VSR 要根据视觉证据进行路由,视觉信号路径必须“枯燥地”可靠。它必须匹配参考模型,能够跨越跨语言服务边界,并在策略变得更具表达力时保持可测试性。
接下来是什么
当务之急是落地并审查强化 PR,并在多模态路由演进过程中将验证语料库保持在循环中。更大的目标是使参考驱动的检查成为 VSR 多模态服务中常规的一部分。
由此开始,后续的架构步骤包括:
- 将图像派生的信号与文本派生的信号在同一个决策层中暴露;
- 使多模态决策在重放、指标和调试工具中保持可见;
- 使模型选择同时感知策略适配度和模态能力;
- 为 PII 和越狱等安全关键信号保持高保真度的审查;
- 将同一架构扩展到智能体工作流,使工具调用、内存写入和模型调用都通过同一个决策层进行路由。
文本路由是第一个控制面,多模态路由是下一个。目标不是在路由器旁边构建一个一次性的视觉分类器,而是让请求中每一个有意义的部分都可以被同一个可编程的路由大脑所利用。

入门
- 项目仓库:vllm-project/semantic-router
- 在线演示:shrader.dev
致谢
感谢 Huamin Chen 提供的 mmEL 指针帮助打破了编码器升级的错误诊断,感谢在 #1927、#1928 和 #1943 中进行的维护者审查,以及撰写此文的邀请。也感谢更广泛的维护团队在本文所基于的多模态分类器工作、multi-modal-embed-small 模型卡以及 Candle 绑定集成方面所做出的贡献。