Skip to main content

引言

vLLMSGLangTensorRT-LLM等推理引擎解决了“怎样更高效地运行一个模型”的问题。它们通过连续批处理、分页式KV Cache、量化和并行计算等技术,让单个模型服务获得更高吞吐和更低延迟。

但当生产环境里同时存在小模型、大模型、推理模型、多模态模型、自建模型和云端模型时,问题会变成:这一条请求应该交给哪个模型,以及在调用模型前后还应执行哪些能力?

传统负载均衡器擅长在一组等价副本之间分流,却不知道“解释一个名词”和“证明一个数学定理”对模型能力的要求不同;应用代码虽然知道业务语义,却不应该长期维护模型地址、价格、上下文长度、安全边界和降级顺序。两者之间缺少一个能理解请求、执行策略并选择模型路径的共享决策层。

vLLM Semantic Router正是为这个问题而设计的。它不是另一个推理引擎,而是位于客户端、网关与模型后端之间的语义路由和控制层

一个在线客服的例子

假设一家电商同时运行四种模型:

模型特点适合处理
小模型便宜、响应快“订单在哪里”之类的简单问题
大模型推理能力强,但更慢、更贵复杂售后分析和规则解释
本地模型数据不离开企业内网包含姓名、电话和订单号的请求
多模态模型能读取图片用户上传的商品破损照片

如果客服应用永远调用大模型,简单问题也会付出较高成本;永远调用小模型,又可能答不好复杂问题。更麻烦的是,包含个人信息的请求不能随意发往云端,图片请求也不能交给只懂文字的模型。

可以把vLLM Semantic Router想成客服中心的“智能分诊台”:它先看请求有什么特征,再检查公司政策,最后把请求交给合适的处理通道。应用仍然只调用一个统一地址,不需要知道每个模型的真实地址。

这个例子展示了语义路由的基本思路:先识别请求的内容和特征,再根据成本、能力与安全要求筛选可用模型,最后把请求送往合适的处理通道。后文会沿着这条主线,逐步说明系统如何完成这些工作。

阅读前先认识几个词

术语通俗解释
请求(Request应用发给模型的一次任务,通常包含用户问题、历史消息和生成参数
提示词(Prompt模型本次需要阅读的文字或多模态输入
推理(Inference已训练好的模型根据输入生成答案的过程,不是重新训练模型
模型后端(Backend真正加载模型并提供接口的服务,例如一个运行中的vLLM实例
模型池(Model Pool路由器可以选择的一组模型或模型服务
Token模型处理文本时使用的基本片段;输入和输出越长,通常消耗越多
TTFT从发出请求到收到第一个输出Token的等待时间
上下文窗口模型一次能够读取的最大内容范围
语义路由不只看服务器负载,还根据请求含义和策略选择处理路径

从推理服务的痛点说起

不存在适合所有请求的唯一模型

生产流量通常是混合的:闲聊、摘要、代码生成、复杂推理、图像理解和安全敏感请求同时存在。模型在质量、延迟、价格、上下文长度、语言、模态、工具调用和部署位置上各有优势。

如果所有请求都使用能力最强的模型,简单问题会消耗不必要的推理时间和费用;如果所有请求都使用小模型,复杂任务的正确率、指令遵循和工具调用能力又可能不够。固定模型只能在某个平均工作负载上做妥协,无法为每条请求选择更合适的能力等级。

“是否启用推理模式”也存在类似问题。项目论文《When to Reason:Semantic Router for vLLM》指出,推理模式能够提高部分任务的准确率,但会增加响应延迟和输出Token。论文实验中,按请求判断是否需要推理,相比直接使用vLLM推理,在MMLU-Pro上提高了10.2个百分点的准确率,同时将延迟和Token消耗分别降低47.1%48.5%。这些数字来自该论文的特定模型、数据集和实验设置,不能直接视为任意生产环境的收益,但它说明了按工作负载选择执行路径的价值。

约束与优化目标互相冲突

一次路由往往同时面对两类条件:

  • 硬约束:授权、数据驻留、隐私、输入模态、上下文容量、工具兼容性等,不满足时必须排除候选模型;
  • 软目标:质量、首Token延迟(TTFT)、每输出Token时间(TPOT)、价格和负载等,需要在合法候选中继续权衡。

如果直接把所有因素塞进一个加权分数,低成本或低延迟可能意外“抵消”隐私要求。更合理的顺序是先用策略淘汰不允许的路径,再在剩余候选中优化质量、延迟和成本。

仍以客服为例:用户要求“订单信息只能在内网处理”是不能妥协的硬约束;在两个都位于内网的模型之间选择更快或更便宜的一个,才是软目标。正确顺序是先排除不合规模型,再比较合规模型

普通负载均衡看不懂请求

传统负载均衡主要解决“怎样把请求分得更均匀”:轮询会按顺序把请求依次发送给各个服务,最少连接或最少请求则优先选择当前更空闲的服务。这些方法适合多个服务都运行同一个模型的场景,因为请求交给其中任何一个,获得的处理能力都差不多。这些运行相同模型、提供相同能力的服务实例通常称为“副本”。异构模型池却不是这样:一个后端可能是本地8B模型,另一个可能是云端推理模型,第三个只能处理图像。

基础设施调度器可以知道副本是否健康、队列是否拥塞,却通常不知道提示词属于法律、代码还是闲聊,也不知道用户明确要求“只能在本地处理”。语义分类器又只理解内容,不应该越过授权和数据边界。推理服务需要把工作负载语义、业务策略与运行状态组合起来,而不是让其中任一项独自决定最终路径。

模型选择逻辑侵入应用代码

缺少统一路由层时,应用很容易出现下面的条件分支:

if contains_image(request):
call(vision_model)
elif contains_sensitive_data(request):
call(local_model)
elif looks_complex(request):
call(frontier_model)
else:
call(cheap_model)

随着业务增长,这段逻辑还会加入重试、缓存、RAG、工具过滤、系统提示词、供应商鉴权和降级规则。多个应用会复制相似代码;模型升级或策略调整则需要重新发布所有客户端。更麻烦的是,这些分支通常缺少统一的解释、评测和审计机制。

安全、缓存和上下文处理被重复实现

不同请求需要不同的附加能力。例如:

  • 隐私请求应路由到本地模型,并避免进入外部存储;
  • 高风险请求需要越狱检测、响应检查或事实核验;
  • 高频问答适合精确缓存或语义缓存;
  • 长对话可能需要上下文压缩和长期记忆;
  • 智能体请求可能只应暴露与任务相关的工具。

如果这些能力散落在各应用的中间件中,执行顺序、租户隔离和数据保留策略很难保持一致。路由不只是“选模型”,还需要把请求前处理、执行和响应后处理组织成可审查的策略。

多模型协作与反馈闭环难以工程化

有些任务适合直接选择一个模型,有些任务则适合逐级升级、并行征询、验证后重试或多轮综合。把这些流程隐藏在应用重试代码中,会导致调用次数、超时和成本边界不清晰。

此外,路由策略不能只靠直觉。团队需要知道某类请求为什么进入某条路径、最终选了哪个模型、花费多少、用户是否满意,并用回放和评测验证新策略。没有统一观测数据,所谓“智能路由”很容易成为不可解释的黑盒。

vLLM Semantic Router是什么

vLLM Semantic RoutervLLM项目下采用Apache-2.0许可证的开源项目。官方介绍将其定义为构建Mixture-of-ModelsMoM,混合模型)系统的可编程路由与控制层:应用继续调用稳定的OpenAIAnthropic兼容接口,路由器根据请求信号、用户偏好、应用策略与运行信息,选择或组合合适的模型路径。

这里的“模型路径”不只是一个模型名称,还可以包含检索、记忆、工具筛选、缓存、安全检查、事实核验、级联调用或多模型协作。

它与其他组件的边界

组件主要职责不负责的事情
vLLM等推理引擎加载权重并执行PrefillDecode不决定业务请求应使用哪个模型类别
EnvoyAPI Gateway接入、转发、鉴权和基础流量治理默认不理解提示词语义与模型能力差异
Kubernetes调度器部署、扩缩容和恢复模型副本不执行请求级语义策略
vLLM Semantic Router理解请求、执行策略、选择或编排模型路径不加载业务模型权重,也不替代副本调度器

因此,一个完整系统可以先由vLLM Semantic Router选择“代码模型”或“推理模型”,再由下游网关或推理平台在该模型的健康副本之间做负载均衡。

核心特点

  1. 语义与策略共同驱动:既支持关键词、上下文长度和元数据等显式规则,也支持领域、复杂度、偏好、PII和越狱检测等模型或相似度信号。
  2. 先约束、后优化:通过Decision表达路由资格,再由Algorithm在合法候选中按静态顺序、语义匹配、延迟或多目标策略选模型。
  3. 一个接口连接异构模型池:后端可以是自建vLLMOllamaKubernetes中的模型服务或兼容协议的云端提供商。
  4. 选择与编排统一:简单场景选择一个模型,复杂场景可使用有界的级联、评审、融合或工作流算法。
  5. 按路由挂载能力:缓存、RAG、记忆、上下文压缩、系统提示词、工具筛选和响应检查通过Plugin绑定到特定路由。
  6. 策略可配置、可验证、可解释:统一的YAML配置被CLIDashboardHelmOperator共同使用,路由结果可通过响应头、指标、追踪、回放和评测观察。
  7. 协议与部署方式灵活协议兼容性文档列出了OpenAI Chat CompletionsOpenAI ResponsesAnthropic Messages之间的支持关系;部署方式文档则覆盖本地DockerKubernetes、网关和推理平台集成。

架构设计

数据面与控制面

官方系统概览把整个系统分成数据面和控制面。初学者可以这样理解:

  • 数据面处理每一条真实请求,重点是快和稳定;
  • 控制面负责配置、验证和观察路由规则,重点是可管理和可审查。

EnvoySemantic Router共同组成数据面,但分工不同:Semantic Router负责“理解请求并选择模型”,Envoy负责“接收请求并把它送到模型”。可以把前者看成给出分诊结果的工作人员,把后者看成真正负责引导和维持通道秩序的工作人员。

Semantic Router如何接入Envoy

两者通过Envoy External Processing过滤器连接。ExtProc允许Envoy通过双向gRPC把请求头、请求体、响应头和响应体交给外部服务处理,再根据外部服务的回复继续转发、修改内容或直接返回结果。

项目生成的Envoy配置中,这种集成主要包含三部分:

  1. envoy.filters.http.ext_proc位于最终的envoy.filters.http.router之前,确保请求转发到模型前先经过语义路由;
  2. extproc_service集群通过gRPC连接Semantic RouterExternalProcessor服务;
  3. 每个模型对应一个Envoy上游集群,集群中可以包含该模型的多个服务副本。

vllm-sr serve会根据规范化YAML生成这部分Envoy配置。也可以执行vllm-sr config envoy --config config.yaml查看生成结果,因此通常不需要手工维护一份独立的envoy.yaml

一条请求如何完成协作

当前ExtProc处理器按下面的顺序处理请求:

  1. 客户端先把标准模型请求发送给Envoy,不需要感知Semantic Router的存在;
  2. Envoy通过ExtProc把请求交给Semantic Router。路由器读取提示词,执行信号、决策、算法和插件,选出合适的模型;
  3. 模型绑定逻辑把结果写入内部请求头x-selected-model,并通知Envoy重新匹配路由;
  4. Envoy根据x-selected-model选择对应的模型集群,再在该集群的健康副本之间进行负载均衡;
  5. 模型结果回到Envoy后,还可以再次经过Semantic Router完成协议转换、缓存写入、响应检查和观测记录,最后返回客户端。

如果缓存已经命中,或者安全策略要求直接拒绝请求,Semantic Router可以返回ImmediateResponse,让Envoy直接回复客户端,不再调用模型。对于流式回答,路由器也可以让EnvoySTREAMED模式继续传递响应,避免等待完整答案生成。

如果环境中已经有Envoy Gateway,只需在现有网关中配置ExtProc过滤器,使它指向Semantic RoutergRPC服务,并保证网关能够识别路由器写入的模型名称。不同网关集成中的鉴权、限流和后端管理职责,可参考官方网关集成说明

核心组件

vLLM Semantic Router包含以下组件:

组件要解决的问题核心作用
Entrypoint客户端不应绑定经常变化的物理模型根据请求中的虚拟模型名找到对应的Recipe
Recipe不同业务的规则和状态需要相互隔离封装一整套路由规则、插件及独立运行状态
Signal路由规则需要先知道请求具有哪些特征识别语义、模态、上下文、身份和风险等事实
Projection多个信号可能重叠或难以直接比较将多个信号整理成统一的分类、分数或区间
Decision必须先满足隐私、能力和业务等约束匹配业务规则,确定可用路线和候选模型
Algorithm多个候选模型之间仍需作出最终选择按质量、延迟或成本选出模型,或生成多模型计划
Plugin模型调用前后还需要检索、缓存和安全检查在处理流程中增强、改写、拦截或检查请求与响应
Provider Model逻辑模型名需要落到可访问的真实服务配置模型端点、协议、上游模型名、凭据和可靠性信息

这些组件各管一件事。例如,Signal只负责报告“请求中包含个人信息”,是否拒绝请求、隐藏信息或改用本地模型,则交给DecisionPlugin处理。这样更换检测方法时,不需要重写整套路由策略。

Entrypoint:根据公开名称找到处理方案

假设客服应用直接把small-model-v1写在每一次请求中。以后平台将它升级为small-model-v2时,网页、移动端和智能体都要跟着修改;如果不同应用还各自保存模型地址,迁移会更加麻烦。要避免这种耦合,平台需要提供一个长期稳定的公开名称,再在服务端决定这个名称采用哪套处理方案。

Entrypoint就是这个“稳定入口”。Entrypoint与Recipe文档说明,它读取客户端请求中的model字段,把一个或多个公开模型名映射到某个Recipe。它只负责找到处理方案,并不直接选择最终模型。

例如,平台可以公开vllm-sr/fastvllm-sr/quality两个名称。应用选择vllm-sr/fast,表示本次请求优先考虑响应速度;至于背后使用哪个小模型,可以由平台随时调整,应用不需要跟着修改模型地址。

如果客户端直接请求已公开的物理模型名,请求可以走直通路径。虚拟模型文档说明,这种请求会绕过Recipe中的信号、决策、路由插件、缓存、学习和会话路由。因此,希望平台统一控制选模时,应让应用请求Entrypoint公开的虚拟名称。

Recipe:封装一套完整路由方案

假设同一个路由器既服务在线客服,又服务代码助手。客服请求需要检查订单隐私、检索商品知识库,代码请求则需要识别编程语言、处理长上下文。如果两类请求共用同一组规则、缓存和记忆,很容易出现规则互相干扰,甚至把一个业务的数据带到另一个业务中。系统因此需要把一整套路由规则和运行状态打包并隔离起来。

Recipe就是这样的“处理手册”。它包含一套配套的SignalProjectionDecisionAlgorithmPlugin,既可以被多个入口复用,也是缓存、记忆和路由状态的隔离边界。

例如,同一套服务可以准备customer-servicecode-assistant两个Recipe。前者关注订单隐私、知识库和客服模型,后者关注编程语言、长上下文和代码模型。两套方案可以共享底层模型端点,但各自的缓存、记忆和路由状态不会混在一起。

Signal:从请求中提取事实

假设用户发送“请根据这张破损照片处理订单A123”。在选择模型之前,系统至少要知道请求中包含图片、内容属于售后问题,还可能带有订单标识等隐私信息。后续规则不能每次都重新分析原始请求,因此需要先把这些特征提取成可以重复使用的事实。

Signal就是负责“观察请求”的组件。它读取提示词、请求元数据或会话信息,输出领域、难度、模态或风险等事实,供后面的ProjectionDecision使用。Signal文档列出的信号可以先简单分为两类:

类型示例适合识别的内容
明确规则keywordmetadatacontextlanguagestructure指定关键词、调用方身份、上下文长度和请求格式
模型或相似度判断embeddingdomaincomplexitypreferencepiijailbreaksafety语义意图、任务难度、用户偏好和内容风险

在这个例子中,Signal只负责报告“包含图片”“属于售后”和“可能包含隐私信息”,还不会决定调用哪个模型。模型型信号可能误判,因此生产环境需要使用真实数据校准阈值。

Projection:把多个事实整理成一个结果

假设系统已经得到“提示词很长”“需要多步推理”和“需要事实核验”三个Signal。如果每个Decision都重新编写一遍组合公式,不同路线很容易算出互相矛盾的难度结果。系统需要先把多个事实统一汇总成一个可复用的分类或分数。

Projection就是位于SignalDecision之间的汇总组件。Projection文档定义了三种常见处理方式:

  • partition从多个匹配结果中得到一个一致分类;
  • score把多个输入组合成一个分数;
  • mapping把连续分数转换为“简单”“中等”“困难”等区间。

例如,可以把“提示词长度”“是否需要证明”和“是否需要事实核验”组合成一个任务难度分数,再把它映射为“简单”或“复杂”。后面的多个Decision都可以复用这个结果,不必分别重复计算。只有一个信号就足以判断时,可以直接跳过Projection

Decision:按照规则确定哪些模型可以用

假设一条请求既包含商品图片,又包含姓名和订单号。多模态云模型能够看图,但公司规定个人信息只能在内网处理。此时系统不能简单选择能力最强或速度最快的模型,而要先执行隐私、模态和业务优先级等规则,确定哪些路线有资格继续参与。

Decision就是负责执行这些路由政策的组件。它接收SignalProjection的结果,通过ANDORNOT等条件判断路线是否匹配,并给出候选模型名单。Decision文档还允许它声明优先级、后续使用的算法和需要运行的插件。

在这个例子中,“包含图片”要求候选模型支持多模态,“包含个人信息并要求本地处理”又把范围缩小到内网多模态模型。即使云端模型更快、更便宜,也会在这一阶段被排除。无条件的默认Decision可以作为兜底,处理没有命中其他规则的请求。

Algorithm:从合格模型中选择或组织调用

假设Decision筛选后还剩两个合规的本地模型:一个响应快、成本低,另一个回答质量更高。候选名单只能说明“它们都可以用”,还不能决定本次究竟选择哪一个;某些复杂任务甚至需要让多个模型依次回答和复核。系统因此还需要一个负责最终选择或组织调用的组件。

Algorithm就是这个选择器或编排器。它只处理已经通过Decision筛选的候选模型,不会把被隐私或能力规则排除的模型重新加回来。Algorithm文档将常见算法分为两类:

类别代表算法实际作用
单模型选择staticlatency_awaremulti_factorhybrid按固定顺序、延迟、质量或成本选择一个模型
多模型编排confidenceratingsremomfusionworkflows级联调用、并行评审或组合多个模型的结果

例如,两个本地模型都满足隐私要求时,latency_aware可以选择最近响应更快的一个;高风险回答也可以先由一个模型生成,再由另一个模型复核。multi_factor文档latency_aware文档指出,延迟与负载数据是单个路由器进程的本地观测,不能代替集群级调度信息。实验性算法应先使用目标流量评测,再投入生产。

Plugin:在路由过程中增加附加能力

假设路由器已经选出客服模型,但模型还需要读取最新退货政策才能回答;对于重复出现的商品问题,系统又希望直接复用缓存;模型生成答案后,还要检查内容是否安全。这些工作都发生在选模前后,却不属于“选择哪个模型”,如果分别写进每个应用就会产生大量重复代码。

Plugin就是挂在路线上的附加处理步骤。Plugin文档说明,它可以在调用模型前改写或增强请求,也可以直接返回结果,或者在模型回答后进行检查。

处理阶段典型插件具体作用
请求准备system_promptrequest_paramstools注入系统提示词、限制生成参数或筛选工具
上下文增强ragmemorycontext_compression检索资料、加载记忆或压缩过长上下文
快速返回fast_responseresponse_cache直接拒绝请求或复用已有答案,不再调用模型
响应处理hallucinationresponse_jailbreak检查事实支持和回答安全性
观测router_replayshadow_dispatch保存路由过程或将少量流量发送给影子模型

例如,普通商品问答可以先查response_cache,命中后直接返回;未命中时,再由rag检索商品资料并放入提示词。订单查询可能包含个人信息,不应在没有租户隔离和保留策略时共享缓存。Response Cache文档详细说明了作用域、有效期和安全边界。

Provider Model:把逻辑模型连接到真实后端

假设Algorithm最终选择了local-small。这个名称只代表路由策略中的逻辑模型,Envoy还不知道它运行在哪个地址、使用什么协议、上游接受什么模型名,也不知道是否有多个副本。要真正发出请求,系统需要把逻辑选择转换成可连接的后端信息。

Provider Model就是逻辑模型与真实服务之间的连接层。模型配置文档中的providers.models为每个逻辑模型定义后端地址、协议、上游使用的模型名称,以及可选的凭据、价格和可靠性设置。

例如,local-small可以指向内网中的vLLM服务,cloud-reasoning可以指向云端兼容接口。一个逻辑模型还可以配置多个语义一致的backend_refs作为副本:Semantic Router选择local-smallEnvoy再从它的健康副本中挑选一个。不同模型或不同协议的服务不应伪装成同一组副本,而应配置成不同逻辑模型供Decision选择。

模型卡还可以声明上下文窗口、模态、工具和推理能力。路由器会在运行算法前过滤不具备所需能力的候选;模型副本的部署、扩缩容和GPU调度仍由vLLMKubernetes或其他推理平台负责。

一次请求的处理流程

以“分析损坏商品照片”为例:Entrypoint先找到客服RecipeSignal识别图片和售后意图,Decision只保留支持图像的模型,Algorithm从中选出一个,Plugin补充商品资料,最后由Provider Model找到真实地址并交给Envoy调用。

初次阅读时,记住这条缩短后的链路即可:公开模型名找到处理方案,信号描述事实,决策生成合格名单,算法选择模型,插件完成附加处理。

安装与启动

环境要求

官方Quickstart给出的本地快速体验要求包括:

  • LinuxmacOSWSL2
  • Python 3.10或更高版本;
  • DockerLinux也可以使用Podman

部署方式文档建议默认让路由器运行在CPU上,只有本地嵌入或分类模型经过测量确实能从加速中获益时,才有必要为它分配GPU。该文档也明确指出,vllm-sr serve启动的是路由栈,不会自动启动自定义配置中引用的业务模型后端。

安装CLI

安装稳定版:

curl -fsSL https://vllm-sr.ai/install.sh | bash -s -- --channel stable

也可以安装PyPI包:

python -m venv .venv
source .venv/bin/activate
pip install vllm-sr
vllm-sr --version

启动本地路由栈

vllm-sr serve

首次启动可以打开http://localhost:8700,通过Dashboard连接已有模型端点并激活生成的配置。默认端口如下:

地址用途
http://localhost:8700Dashboard
http://localhost:8899对应用暴露的推理接口
http://localhost:8080路由器管理接口

常用运维命令:

vllm-sr status
vllm-sr logs router
vllm-sr logs envoy -f
vllm-sr dashboard
vllm-sr stop

如果只需要RouterEnvoy,可以使用vllm-sr serve --minimal;若希望保留只读Dashboard,可以添加--readonly

配置详解

顶层结构

配置文档给出的规范化v0.3 YAML使用以下顶层结构:

version:
listeners:
providers:
evaluation:
routing:
entrypoints:
recipes:
global:
配置段主要内容
version配置契约版本,当前为v0.3
listeners对外监听地址、端口、超时和可选访问凭据
providers模型端点、协议、价格、可靠性与默认模型
evaluation基准定义、指标索引和模型评测记录
routing默认Recipe的模型卡、信号、投影、决策和插件
entrypoints公共虚拟模型名到命名Recipe的映射
recipes额外的隔离路由策略
global共享运行时、存储、服务、观测和学习设置

不要从网络文章中猜测字段名。配置契约文档说明,可以通过CLI渐进式查询目标版本的真实字段和可用路由组件:

vllm-sr config schema
vllm-sr config schema --section routing --expanded
vllm-sr config schema --surface signal:keyword
vllm-sr config schema --surface algorithm:multi_factor

示例:两个模型之间按请求内容路由

下面的完整示例假设已经有两个兼容OpenAI API的模型服务:fast-model监听宿主机8000端口,reasoning-model监听8001端口。由于路由器运行在容器中,Docker部署文档建议使用host.docker.internal访问宿主机。

阅读这段配置时先不要逐行记忆,只看五步:开放端口 → 登记模型 → 识别复杂请求 → 选择推理模型 → 其他请求走快速模型

version: v0.3

listeners:
- name: http-8899
address: 127.0.0.1
port: 8899
timeout: 300s

providers:
defaults:
model: fast-model
models:
- name: fast-model
provider_model_id: fast-model
api_format: openai
backend_refs:
- name: fast-primary
provider: vllm
endpoint: host.docker.internal:8000
protocol: http
- name: reasoning-model
provider_model_id: reasoning-model
api_format: openai
backend_refs:
- name: reasoning-primary
provider: vllm
endpoint: host.docker.internal:8001
protocol: http

routing:
strategy: priority
signals:
keywords:
- name: complex-task
operator: OR
method: bm25
keywords:
- prove
- derive
- architecture trade-off
- root cause analysis
- 证明
- 推导
- 架构权衡
- 根因分析
bm25_threshold: 0.1
case_sensitive: false
decisions:
- name: reasoning-route
description: Use the reasoning model for complex tasks.
priority: 100
rules:
operator: AND
conditions:
- type: keyword
name: complex-task
modelRefs:
- model: reasoning-model
- name: default-route
description: Use the fast model for all remaining requests.
priority: 0
rules:
operator: AND
conditions: []
modelRefs:
- model: fast-model

这段配置实际完成了以下工作:

  1. listeners让路由接口只在宿主机8899端口监听;
  2. providers.models登记两个已经运行的模型后端;
  3. complex-task使用BM25关键词相关性识别“证明、推导、架构权衡、根因分析”等请求;
  4. 命中后,优先级为100reasoning-route选择reasoning-model
  5. 没有命中时,无条件的default-route选择fast-model

BM25可以先理解为一种关键词相关性评分:不要求整句完全相同,而是根据关键词在文本中的出现情况计算匹配程度。这个示例只用一种信号,目的是讲清配置链路。生产场景可以再加入领域、复杂度、嵌入相似度、上下文长度和业务元数据,但关键词不能代替授权或隐私边界。

先校验配置,再启动:

vllm-sr config validate --config config.yaml
vllm-sr serve --config config.yaml

示例:先预览路由,不调用模型

CLI文档中的route preview通过管理接口执行信号、决策、算法和插件匹配,但不会调用最终模型,适合在产生推理费用前检查策略:

vllm-sr route preview \
--prompt "请从第一性原理分析这个分布式系统的架构权衡" \
--json

预期结果应显示complex-task信号和reasoning-route决策。如果管理接口不在默认http://localhost:8080,可以使用--endpoint指定地址。

示例:发送真实请求

可以使用CLI

vllm-sr request chat \
--model vllm-sr/auto \
--json \
"请比较两种缓存失效策略"

也可以调用兼容OpenAI的接口,并开启一次请求的调试响应头:

curl http://localhost:8899/v1/chat/completions \
-H 'Content-Type: application/json' \
-H 'x-vsr-debug: true' \
-d '{
"model": "vllm-sr/auto",
"messages": [
{"role": "user", "content": "请证明这个算法的时间复杂度上界"}
]
}'

检查响应头中的x-vsr-selected-decisionx-vsr-selected-model,可以确认请求实际走了哪条策略和哪个逻辑模型。

示例:为某条路由增加多目标选择

下面是进阶用法,第一次阅读可以先跳过。当一个决策拥有多个合法候选时,可以让multi_factor在质量、延迟、成本和负载之间做权衡。下面是应合并到完整配置中的片段:

routing:
decisions:
- name: balanced-code-route
description: Balance quality, latency, cost, and load for code tasks.
priority: 100
rules:
operator: AND
conditions:
- type: keyword
name: code-task
modelRefs:
- model: code-small
- model: code-large
algorithm:
type: multi_factor
minimum_candidates: 2
multi_factor:
objective:
strategy: weighted
quality:
index: acme/coding-quality@1.0.0
on_missing: exclude
min_coverage: 1.0
weights:
quality: 0.5
latency: 0.2
cost: 0.2
load: 0.1
on_no_candidates: fail

这里的质量索引acme/coding-quality@1.0.0只是组织自定义索引的示例,必须在evaluation中提供真实定义和模型测量结果。缺少质量证据时使用exclude,以及没有候选时使用fail,可以避免系统静默选择不满足要求的模型。

示例:虚拟模型对应不同目标

一个部署可以通过Entrypoint暴露多个稳定名称。下面只是entrypointsrecipes片段,需要与前文的providers等配置合并:

entrypoints:
- model_names: [vllm-sr/mom-v1-flash]
recipe: flash
- model_names: [vllm-sr/mom-v1-ultra]
recipe: ultra

recipes:
- name: flash
description: Prefer the low-latency model.
routing:
decisions:
- name: fast-path
priority: 100
rules: {operator: AND, conditions: []}
modelRefs: [{model: fast-model}]
- name: ultra
description: Prefer the high-quality model.
routing:
decisions:
- name: quality-path
priority: 100
rules: {operator: AND, conditions: []}
modelRefs: [{model: reasoning-model}]

应用可以选择“低延迟”或“高质量”目标,却不需要知道目标背后的具体模型地址。切换模型、增加插件或调整策略时,公共名称不变。

参考资料

  1. vLLM Semantic Router GitHub仓库
  2. vLLM Semantic Router官方文档:Introduction
  3. vLLM Semantic Router官方文档:System Overview
  4. vLLM Semantic Router官方文档:Routing Pipeline
  5. vLLM Semantic Router官方文档:Quickstart
  6. vLLM Semantic Router v0.3 Themis发布说明
  7. vLLM Semantic Router:Next Phase in LLM Inference
  8. When to Reason:Semantic Router for vLLM
  9. Category-Aware Semantic Caching for Heterogeneous LLM Workloads