AIBrix vLLM Semantic Router 实战指南:基于 Envoy ext_proc 的多模型语义路由部署与配置

发布时间:2026/9/18 17:29:52
AIBrix vLLM Semantic Router 实战指南:基于 Envoy ext_proc 的多模型语义路由部署与配置
AIBrix vLLM Semantic Router 实战指南基于 Envoy ext_proc 的多模型语义路由部署与配置【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix在构建一个需要同时处理数学作业、法律咨询、创意写作和医疗问题的 AI 助手时与其用单个大模型扛下所有负载不如让系统自动把 STEM 与推理类问题交给推理优化模型把日常对话类请求转发给更快更轻量的模型——而且客户端完全无感知。AIBrix vLLM Semantic Router正是为此设计的它以 Envoy External Processorext_proc的形式驻留在模型舰队之前对每个入站 prompt 按主题与意图分类再转发给最匹配的模型并注入正确的推理配置。客户端始终调用同一个端点、同一套 OpenAI 兼容 API路由逻辑全部由路由器在链路中透明完成。本文基于 AIBrix 仓库中的官方文档 docs/source/features/semantic-router.rst并结合 samples/semantic-router/ 目录下的完整示例清单模型 Deployment、路由器 ConfigMap、EnvoyPatchPolicy完整讲解语义路由的工作原理、从零部署步骤、路由规则与推理配置的写法、插件机制、可观测性以及常见故障排查。读完本文你将能够在 AIBrix Envoy Gateway 集群上部署一套Model of ModelsMoM语义路由系统在qwen3-8bSTEM 与推理与llama3-8b-instruct商务、法律与通用问答之间自动分流并独立扩展出你自己的领域路由规则。工作原理一个 Envoy ext_proc 链路内请求改写器语义路由器以Envoy External Processorext_proc的形式集成——这是一个 gRPC sidecarEnvoy 在转发每个请求之前会先咨询它。完整的请求路径如下Client │ ▼ Envoy Gateway (aibrix-eg) ← 接收原始请求 │ gRPC ext_proc (端口 50051) ▼ Semantic Router ← 分类 prompt、改写 model 字段 │ 例如 MoM → qwen3-8b ▼ AIBrix Gateway Plugins ← 限流、鉴权等网关级插件 │ ├──► qwen3-8b (STEM reasoning) └──► llama3-8b-instruct (business, legal, general)路由器对每个请求执行以下操作通过 gRPC 从 Envoy 接收完整缓冲BUFFERED的请求体提取用户消息内容运行基于 embedding 的领域分类器或对 think step by step 这类显式信号运行快速的关键词扫描器选择优先级最高的匹配决策改写请求——替换model字段、注入 system prompt并可选启用推理模式reasoning mode将改写后的请求返回给 Envoy由其转发到选定的后端。客户端始终使用model: MoMModel of Models模型之母。路由器将其替换为真实的后端模型名客户端代码无需任何改动。从架构定位看见 DESIGN.md路由器是标准的 KubernetesDeployment部署在vllm-semantic-router-system命名空间纯粹是一个链路内 HTTP 请求改写器——它从不终结与客户端的连接Envoy 持有原始请求通过 gRPC 交给路由器拿回一组变更新 header、新 body再把改写后的请求转发给路由器选定的后端。为什么用 BUFFERED 模式在 gwapi-resources.yaml 的 ext_proc 过滤器配置中processing_mode同时设置了request_body_mode: BUFFERED与response_body_mode: BUFFEREDrequest_header_mode: SEND、response_header_mode: SENDtrailer 为SKIP。BUFFERED 意味着 Envoy 会先把完整的请求/响应体累积起来再交给路由器这样路由器可以无流式复杂度地读取每一个/v1/chat/completions请求的完整 JSON 载荷。响应体同样缓冲是为了给语义缓存插件semantic cache留出在响应阶段写入/读取缓存的余地。前置条件开始前请确保具备一个已运行的 Kubernetes 集群且已安装 AIBrix内含 Envoy Gateway已配置好可访问集群的kubectl可用于模型服务的 GPU 节点一个 Hugging Face 账号与 API token用于下载模型权重模型权重已预置在节点/data01/models/目录或可访问 HuggingFace 拉取。示例使用qwen3-8b与llama3-8b-instruct每个模型需要一张至少48 GB 显存的 GPU。示例中的模型 Deployment 资源请求/限制为 1 张nvidia.com/gpu、12 核 CPU、48G 内存。第一步创建命名空间与凭据为语义路由器创建专用命名空间并将 Hugging Face token 存为 Kubernetes Secret路由器启动时用它下载 embedding 模型kubectl create namespace vllm-semantic-router-system export HF_TOKENyour-huggingface-token kubectl create secret generic hf-token-secret \ --from-literaltoken${HF_TOKEN} \ -n vllm-semantic-router-system在 semantic-router.yaml 中该 Secret 通过secretKeyRefkey 为token注入到容器的HF_TOKEN与HUGGINGFACE_HUB_TOKEN两个环境变量且标记为optional: true——只有下载受限模型如embeddinggemma-300m时才必须提供。第二步部署后端模型服务路由器必须等真实模型服务运行起来后才能转发请求。部署两个后端kubectl apply -f samples/semantic-router/models/llama3-8b-instruct.yaml kubectl apply -f samples/semantic-router/models/qwen3-8b.yaml每个清单都会在default命名空间创建一个Deployment3 个副本和一个Service。从清单看两个 Deployment 使用 vLLM 镜像aibrix-public-release-cn-beijing.cr.volces.com/vllm/vllm-openai:0.11.0通过model.aibrix.ai/name与model.aibrix.ai/port: 8000标签声明模型身份AIBrix 控制器会自动为每个模型创建HTTPRoute供 Envoy Gateway 发现。其中qwen3-8b的 Deployment 还额外开启了 KV cache 事件--kv-events-config端口 5557/5559用于 AIBrix 的 KV cache 感知调度llama3-8b-instruct则保持基础 vLLM 服务配置。两个模型权重均通过 hostPath 挂载自节点/data01/models。部署完成后等待两个 Deployment 就绪kubectl rollout status deployment/llama3-8b-instruct -n default kubectl rollout status deployment/qwen3-8b -n default第三步部署语义路由器应用路由器的 ConfigMap路由规则与 Deploymentkubectl apply -f samples/semantic-router/semantic-router-configmap.yaml kubectl apply -f samples/semantic-router/semantic-router.yaml路由器容器ghcr.io/vllm-project/semantic-router/extproc:latest在启动时自动下载 embedding 模型——预留最多60 秒。可以这样观察进度kubectl logs -f deployment/semantic-router -n vllm-semantic-router-system从 semantic-router.yaml 可以看到路由器不再依赖 initContainer 预下载模型而是使用内置的 Go 模型下载模块根据 config.yaml 中的注册信息从 HuggingFace 拉取。由于模型加载耗时较长Deployment 配置了startupProbeTCP 探测 50051 端口periodSeconds: 10、failureThreshold: 360最长容忍约 60 分钟以及livenessProbe/readinessProbe初始延迟 30 秒每 30 秒探测一次。路由器暴露三个端口端口协议用途50051gRPCext_proc 接口——接收来自 Envoy 的请求8080HTTP分类 REST API便于调试9190HTTPPrometheus 指标在 Deployment 中对应三个容器端口grpc、classify-api、metrics并分别由semantic-routerService50051/8080与semantic-router-metricsService9190暴露。另外两个值得注意的细节容器以--securefalse启动即禁用 gRPC ext_proc 连接的 TLS。示例中流量都在集群内部可以接受生产部署前应移除该参数启用 TLS。ConfigMap 被挂载到两个路径/app/config/config.yamlsubPath: config.yaml与/app/config/tools_db.jsonsubPath: tools_db.json模型缓存目录/app/models使用 hostPath 指向/data01/models。容器资源请求为 1 核/3Gi上限 2 核/7Gi。RBAC 说明semantic-router.yaml 中创建的是ClusterRole 而非 Role因为IntelligentPool与IntelligentRouteCRD 是集群级资源路由器需要跨命名空间 watch 它们如果你们的 CRD 是命名空间级的可以替换为限定在vllm-semantic-router-system的 Role RoleBinding。第四步把路由器接入 Envoy Gateway应用 Gateway API 资源把语义路由器注册为 Envoy listener 上的 ext_proc 过滤器kubectl apply -f samples/semantic-router/gwapi-resources.yaml这条命令应用了一个EnvoyPatchPolicyai-gateway-prepost-extproc-patch-policy位于aibrix-system命名空间targetRef 指向 Gatewayaibrix-eg内含两个 JSON patchPatch 1在 Envoy 过滤器链的default_filter_chain中新增semantic-router-extprocHTTP 过滤器。关键配置type:envoy.extensions.filters.http.ext_proc.v3.ExternalProcessorgrpcService.envoyGrpc.clusterName: semantic-routerauthority: semantic-router.vllm-semantic-router-system:50051timeout与message_timeout均为 60sprocessing_mode使用BUFFEREDbody 模式详见上文allow_mode_override: true允许过滤器在运行时覆盖处理模式。Patch 2将路由器注册为一个上游集群semantic-router类型STRICT_DNS、启用http2_protocol_optionsgRPC 需要 HTTP/2、lb_policy: ROUND_ROBIN、connect_timeout: 60s使 Envoy 知道如何到达semantic-router.vllm-semantic-router-system.svc.cluster.local:50051。验证 patch 已被接受kubectl describe envoypatchpolicy ai-gateway-prepost-extproc-patch-policy -n aibrix-system在Conditions下查找Status: True。第五步访问网关本地测试先对 Envoy 服务做端口转发export ENVOY_SERVICE$(kubectl get svc -n envoy-gateway-system \ --selectorgateway.envoyproxy.io/owning-gateway-namespaceaibrix-system,gateway.envoyproxy.io/owning-gateway-nameaibrix-eg \ -o jsonpath{.items[0].metadata.name}) kubectl port-forward -n envoy-gateway-system svc/${ENVOY_SERVICE} 8080:80生产环境改用 LoadBalancer 的外部 IPLB_IP$(kubectl get svc -n envoy-gateway-system \ -l gateway.envoyproxy.io/owning-gateway-nameaibrix-eg \ -o jsonpath{.items[0].status.loadBalancer.ingress[0].ip})第六步测试语义路由所有请求都使用虚拟模型名MoM路由器透明地选择正确后端。数学问题 → 路由到 qwen3-8b启用推理curl http://localhost:8080/v1/chat/completions \ -H Content-Type: application/json \ -d { model: MoM, messages: [ {role: user, content: What is the derivative of x^3 2x?} ], max_tokens: 200 }路由器将该请求分类为math领域选择qwen3-8b注入数学专家 system prompt并启用链式思考推理chat_template_kwargs.enable_thinking: true。商务问题 → 路由到 llama3-8b-instruct标准模式curl http://localhost:8080/v1/chat/completions \ -H Content-Type: application/json \ -d { model: MoM, messages: [ {role: user, content: What are the key factors to consider when entering a new market?} ], max_tokens: 200 }显式推理触发 → 覆盖领域分类如果用户明确要求逐步思考thinking关键词规则优先级 15配置中最高会无视检测到的领域直接触发curl http://localhost:8080/v1/chat/completions \ -H Content-Type: application/json \ -d { model: MoM, messages: [ {role: user, content: Walk me through how to structure a business merger proposal.} ], max_tokens: 300 }尽管这是商务类提问但 walk me through 命中了thinking关键词集合因此路由到qwen3-8b并启用推理。输入端请求格式要点路由器期望标准的 OpenAI 兼容 chat completions 请求见 DESIGN.mdmodel必须为MoM或你定义的任何虚拟模型名路由器会替换为真实模型名messages——路由器读取所有消息内容做领域分类user轮的内容是主要信号其他 OpenAI 参数temperature、max_tokens、stream等原样透传除非被插件修改路由器可能注入或替换system消息见下文system_prompt插件。路由规则参考完整 15 条规则示例的完整路由表定义在 semantic-router-configmap.yaml 中共 15 条规则配置版本version: v0.3领域 / 关键词匹配类型模型推理优先级thinking关键词step by step, think step, chain of thought, reason through, show your work, walk me throughkeywordqwen3-8b开15mathdomainqwen3-8b开10physicsdomainqwen3-8b开10computer sciencedomainqwen3-8b开10biologydomainqwen3-8b开10chemistrydomainqwen3-8b开10engineeringdomainqwen3-8b开10businessdomainllama3-8b-instruct关10lawdomainllama3-8b-instruct关10psychologydomainllama3-8b-instruct关10healthdomainllama3-8b-instruct关10economicsdomainllama3-8b-instruct关10historydomainllama3-8b-instruct关10philosophydomainllama3-8b-instruct关10other兜底 catch-alldomainllama3-8b-instruct关5高优先级规则先被评估。thinking关键词规则优先级 15始终覆盖领域规则优先级 10。规则之间的重叠与优先级细节ConfigMap 的注释揭示了几个容易踩坑的设计点business与economics重叠两者都路由到llama3-8b-instruct且优先级同为 10。涉及金融分析、市场或公司财务的提问可能同时命中两个领域此时声明顺序靠前的business_decision获胜应用的是它的资深商务顾问人设 system prompt。如果你希望经济学问题使用经济学家人设需要把economics_decision的优先级提到 10 以上或把它移到列表更靠前的位置。thinking关键词刻意收窄配置注释强调关键词集合故意保持狭窄以避免误路由到推理模型——像 think 或 careful 这类宽泛词汇会命中日常口语I think...、be careful导致每个这样的请求都被悄悄升级到更慢的 qwen3-8b 链式思考路径。权衡是用户必须显式给出这些信号或命中 math/physics/computer science/engineering 等始终启用推理的领域才会走推理路径。同优先级平局时YAML 列表中的声明顺序决定胜负first wins。理解配置结构所有路由行为都由 semantic-router-configmap.yaml 控制。下面是各关键部分如何组合。决策结构Decision每个路由决策形如routing: decisions: - name: math_decision description: Mathematics and quantitative reasoning priority: 10 # 值越大越优先平局时列表先声明者获胜 rules: operator: OR conditions: - name: math # 必须匹配 routing.signals 下声明的信号 type: domain # 或 type: keyword modelRefs: - model: qwen3-8b use_reasoning: true # 激活链式思考模式 plugins: - type: system_prompt configuration: enabled: true mode: replace system_prompt: You are a mathematics expert. ...规则类型Rule Types类型匹配方式domain基于 embedding 的 prompt 与命名领域标签之间的余弦相似度。路由器选择与 prompt 嵌入最接近的领域。keyword快速的精确子串搜索默认不区分大小写。关键词集合中任意一个出现在 prompt 中即匹配。优先级策略Priority Strategy使用strategy: priority默认值对应 ConfigMap 中的global.router.strategy: priority时收集所有规则匹配 prompt 的决策priority值最高的决策获胜平局按YAML 中的声明顺序打破——先声明者胜。信号目录Signals Catalog规则中用到的每个领域或关键词集合都必须先在routing.signals下声明routing: signals: domains: - name: math - name: physics - name: business # ... 在这里新增领域标签 keywords: - name: thinking case_sensitive: false operator: OR keywords: - step by step - chain of thought - reason through # ... 在此扩展示例 ConfigMap 中声明了 14 个领域business、law、psychology、biology、chemistry、history、other、health、economics、math、physics、computer science、philosophy、engineering与 1 个关键词集合thinking含 6 个关键词。模型注册与后端引用providers: defaults: default_model: llama3-8b-instruct # 兜底默认模型 default_reasoning_effort: high models: - name: llama3-8b-instruct backend_refs: - endpoint: llama3-8b-instruct.default.svc.cluster.local:8000 name: aibrix-vllm weight: 1 - name: qwen3-8b reasoning_family: qwen3 backend_refs: - endpoint: qwen3-8b.default.svc.cluster.local:8000 name: aibrix-vllm weight: 1其他全局配置ConfigMap 中还包含若干值得了解的生产配置项global.integrations.tools工具集成开关enabled: true、tools_db_path: config/tools_db.json、top_k: 3、similarity_threshold: 0.2、fallback_to_empty: true。随 ConfigMap 挂载的tools_db.json定义了一个内置工具目录weather 的get_weather、search 的search_web、math 的calculate、communication 的send_email、productivity 的create_calendar_event每个工具都带 OpenAI function calling 格式的 schema 与用于语义检索的描述/tags。global.services.api.batch_classification批量分类调优max_batch_size: 100、max_concurrency: 8、concurrency_threshold: 5并支持duration_buckets/size_buckets等指标分桶配置。listeners: []示例中为空未启用额外监听器。routing.modelCards为llama3-8b-instruct声明了 6 个 LoRA 专家卡science-expert、social-expert、math-expert、law-expert、humanities-expert、general-expert描述其面向的领域——这是配置中为后续 LoRA 路由预留的扩展点。模型推理激活Reasoning ActivationmodelRef上的use_reasoning: true/false标志控制路由器是否向转发请求注入推理激活参数。不同模型家族使用不同的参数。推理家族Reasoning Families定义在providers.defaults.reasoning_families下providers: defaults: default_reasoning_effort: high reasoning_families: qwen3: parameter: enable_thinking type: chat_template_kwargs # → {chat_template_kwargs: {enable_thinking: true}} deepseek: parameter: thinking type: chat_template_kwargs gpt: parameter: reasoning_effort type: reasoning_effort # → {reasoning_effort: high} gpt-oss: parameter: reasoning_effort type: reasoning_effort为模型分配推理家族providers: models: - name: qwen3-8b reasoning_family: qwen3 # 关联到上面的 qwen3 推理家族 backend_refs: - endpoint: qwen3-8b.default.svc.cluster.local:8000 name: aibrix-vllm weight: 1 - name: llama3-8b-instruct # 没有 reasoning_family → 推理永远不会被激活 backend_refs: - endpoint: llama3-8b-instruct.default.svc.cluster.local:8000 name: aibrix-vllm weight: 1当qwen3-8b命中use_reasoning: true的决策时路由器会向出站请求体追加{ chat_template_kwargs: { enable_thinking: true } }vLLM 读取该字段并激活 Qwen3 内置的链式思考路径。而当use_reasoning: false或模型没有reasoning_family时不注入任何额外参数模型以标准模式响应。决策 → 推理激活速查表决策模型use_reasoning注入的参数thinking_decisionqwen3-8btruechat_template_kwargs.enable_thinking truemath_decisionqwen3-8btrue同上physics_decisionqwen3-8btrue同上computer_science_decisionqwen3-8btrue同上biology_decisionqwen3-8btrue同上chemistry_decisionqwen3-8btrue同上engineering_decisionqwen3-8btrue同上business_decisionllama3-8b-instructfalse无law_decisionllama3-8b-instructfalse无other_decision兜底llama3-8b-instructfalse无插件机制决策选定后插件按声明顺序依次应用。system_prompt 插件注入或替换messages[]中的 system 消息plugins: - type: system_prompt configuration: enabled: true mode: replace # replace | prepend | append system_prompt: You are a mathematics expert. ...模式行为replace移除所有已有 system 消息前置一条新的{role: system, ...}。prepend插入到已有 system 消息之前。append插入到已有 system 消息之后。示例配置中每个决策都携带一个领域专属人设例如business_decision使用资深商务顾问与战略顾问人设覆盖公司战略、运营管理、财务分析、市场营销、组织发展law_decision使用法律专家人设并明确声明回复仅供信息参考、不构成法律意见health_decision使用健康与医学信息专家人设并强调教育用途与专业就医建议。semantic-cache 插件按 prompt embedding 相似度缓存响应。缓存命中时路由器短路后端调用直接把缓存响应返回给 Envoy——非常适合高频重复提问的场景plugins: - type: semantic-cache configuration: enabled: true similarity_threshold: 0.92 # 0.0–1.0越大要求匹配越严格缓存的全局设置TTL、最大条目数、淘汰策略配置在global.stores.semantic_cache下global: stores: semantic_cache: enabled: true backend_type: memory embedding_model: mmbert similarity_threshold: 0.8 # 全局默认决策级阈值会覆盖它 ttl_seconds: 3600 max_entries: 1000 eviction_policy: fifo示例配置中psychology_decision阈值 0.92、health_decision阈值 0.95非常严格与other_decision阈值 0.75更宽松都启用了语义缓存——这正是文档中强调的场景health 与 other 领域有大量措辞略有差异但本质相似的问题缓存收益最明显。语义缓存依赖响应体 BUFFERED 模式在请求阶段查询缓存在响应阶段写入缓存见 DESIGN.md 的请求流程第 7 步。新增一条路由三步完成以新增 cybersecurity 领域为例只需三步加一次配置重载1. 在routing.signals.domains下声明领域- name: cybersecurity2. 在routing.decisions下添加决策- name: cybersecurity_decision description: Cybersecurity and network security topics priority: 10 rules: operator: OR conditions: - name: cybersecurity type: domain modelRefs: - model: qwen3-8b use_reasoning: true plugins: - type: system_prompt configuration: enabled: true mode: replace system_prompt: You are a cybersecurity expert with deep knowledge of network security, threat modeling, and secure coding practices. ...3. 应用配置并重载kubectl apply -f samples/semantic-router/semantic-router-configmap.yaml # 滚动重启立即生效新配置 kubectl rollout restart deployment/semantic-router -n vllm-semantic-router-system注意路由器只在启动时读取配置ConfigMap 以只读方式挂载在/app/config/config.yaml因此修改 ConfigMap 后必须滚动重启 Deployment 才能生效。可观测性路由器在9190端口暴露 Prometheus 指标。本地抓取kubectl port-forward -n vllm-semantic-router-system \ deployment/semantic-router 9190:9190然后在浏览器打开http://localhost:9190/metrics或将其接入 Prometheus。集群内则可通过semantic-router-metricsService 抓取。要启用分布式追踪OpenTelemetry / Jaeger在 ConfigMap 中设置global: services: observability: tracing: enabled: true exporter: endpoint: jaeger:4317 insecure: true type: otlp示例 ConfigMap 中追踪默认关闭enabled: falseprovider 为opentelemetry采样策略always_onrate: 1并带有service_name: vllm-semantic-router、service_version: v0.1.0、deployment_environment: development等资源属性。此外batch_classification配置项中还内置了详细的指标埋点detailed_goroutine_tracking、duration_buckets、size_buckets、high_resolution_timing、sample_rate可用于观测分类 API 的延迟分布。故障排查路由器 Pod 启动缓慢embedding 模型下载可能耗时 60 秒。启动探针最长重试 60 分钟failureThreshold: 360见 semantic-router.yamlPod 最终会变为 ready。观察日志kubectl logs -f deployment/semantic-router -n vllm-semantic-router-systemEnvoy 无法访问路由器确认 EnvoyPatchPolicy 已被接受kubectl describe envoypatchpolicy ai-gateway-prepost-extproc-patch-policy -n aibrix-system检查路由器 Service 是否可达kubectl get svc -n vllm-semantic-router-system所有请求都落到兜底模型other_decision优先级 5会接住任何未命中已知领域的 prompt。此时先确认领域 embedding 是否已加载——直接调用分类 APIkubectl port-forward -n vllm-semantic-router-system deployment/semantic-router 9080:8080 curl http://localhost:9080/classify \ -H Content-Type: application/json \ -d {text: What is the integral of sin(x)?}配置变更不生效路由器在启动时读取配置。应用新 ConfigMap 后滚动重启 Deploymentkubectl rollout restart deployment/semantic-router -n vllm-semantic-router-system示例文件清单本示例的所有清单都在 AIBrix 仓库中samples/semantic-router/README.md —— 快速上手指南samples/semantic-router/DESIGN.md —— 深入架构参考samples/semantic-router/semantic-router-configmap.yaml —— 完整路由配置含全部 15 条规则samples/semantic-router/semantic-router.yaml —— 路由器 Deployment、Services 与 RBACsamples/semantic-router/gwapi-resources.yaml —— 将路由器接入网关的 EnvoyPatchPolicysamples/semantic-router/models/ —— 模型 Deployment 与 Service 清单如果你希望进一步了解 AIBrix 网关插件的整体机制语义路由器之后执行的限流、鉴权等网关级插件可以继续阅读仓库中的 pkg/plugins/gateway 目录该目录下 138 个 Go 源文件实现了 AIBrix Gateway Plugins 的完整插件体系是理解 ext_proc 链上后续处理环节的最佳入口。【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考