一、AI多模型路由
多模型路由(Model Routing) 的核心思想,是大厂 AI 产品标配的架构。
豆包这类产品不会把所有请求都丢给同一个模型,而是在网关层做意图识别,然后转发到最适合的后端。
1.1 🧭 路由的决策依据
网关拿到用户请求后,会先做一轮轻量级分类,判断这是什么类型的任务。判断依据通常包括:
-
输入模态:纯文本、图片、音频、视频
-
任务类型:图片识别、图片生成、数学解题、写作、代码、翻译
-
复杂度:简单问答 vs 需要多步推理
-
实时性要求:流式对话 vs 批量处理
-
成本敏感度:免费用户 vs 付费用户
这个分类本身通常用一个小模型或规则引擎完成,不会用大模型来做,因为要控制延迟。
1.2 🏗️ 路由后的后端类型
不同任务会打到不同的服务:
| 任务类型 | 后端服务 |
|---|---|
| 图片识别 | 视觉模型(如豆包的视觉理解模型) |
| 图片生成 | 文生图模型(如 Seedream) |
| 数学解题 | 推理增强模型,可能带代码执行沙箱 |
| 写作 | 通用对话模型,可能带长文本优化 |
| 代码 | 代码专用模型,可能带执行环境 |
| 语音 | ASR + TTS 流水线 |
豆包的模型矩阵本身就包含多个专用模型:Doubao-pro (通用)、Doubao-lite (轻量低成本)、Doubao-vision (视觉)、Doubao-embedding (向量)、Seedream (文生图)、Seedance(视频生成)。网关路由就是把这些模型按需分配。
1.3⚙️ 路由的实现层次
第一层:模态路由 最简单也最必要。图片请求走视觉模型,纯文本走语言模型。这一层几乎不涉及语义理解,看输入类型就能判断。
第二层:任务路由 需要理解用户意图。比如同样是文本,"解这道题"和"写一篇作文"会走不同的模型或不同的 Prompt 模板。这一层通常用分类模型或规则引擎。
第三层:复杂度路由 同一个任务类型内部,根据难度分流。简单问题用轻量模型(快、便宜),复杂问题用大模型(慢、贵)。这叫 LLM Cascade 或 Router 模式,学术上有 RouteLLM 这类专门研究。
第四层:成本/优先级路由 免费用户走轻量模型,付费用户走大模型;或者高峰期降级、低峰期升级。
1.4 🔀 和网关护栏的关系
"护栏部署在网关前侧还是后侧"?和这里的路由是同一个网关的不同职责:
用户请求
↓
网关层
├── 身份认证
├── 输入护栏(越狱检测、注入检测)
├── 意图分类 + 路由决策 ← 这里
├── 转发到对应后端
├── 输出护栏(幻觉检测、敏感信息检测)
└── 返回用户
路由决策和护栏检测可以共用同一个轻量级分类模型,也可以分开。
大厂通常会在网关层做一次推理,多个用途------同一个分类结果既用于路由,也用于判断是否需要触发安全策略。
💭 对医学问答 Agent 的启示
目前的医学 Agent 目前是"一个问题 → 一个 RAG 流程 → 一个 Ollama 模型"。如果后续要扩展,可以考虑加一层轻量路由:
-
分诊类问题 → 走规则引擎或小模型,快速返回
-
知识问答 → 走 RAG + qwen2.5:7b
-
用药建议 → 走 RAG + 更大模型 + 强制输出护栏 + 人工审批
-
图片识别(如看化验单)→ 走视觉模型
路由层不需要很重,一个基于规则的分类器或一个小模型就能覆盖大部分场景。关键是把不同风险等级的任务分开处理,高风险任务走更严格的流程。
二、技术路线
这样的网关在实现上,通常不是自己从零写一个 Nginx 或 Spring Cloud Gateway ,而是利用已有的 AI 网关开源项目或云服务 ,把精力集中在路由策略和护栏配置上。
2.1🏗️ 技术选型:别自己造轮子
目前开源生态已经很成熟,核心选择如下:
| 项目 | 语言 | 适合场景 | 核心能力 |
|---|---|---|---|
| LiteLLM | Python/Rust | 自托管首选,OpenAI 格式接 100+ 模型 | 路由、虚拟密钥、成本追踪,社区事实标准 |
| vLLM Semantic Router | Go/Rust | 已有 vLLM 推理栈,需要语义路由 | BERT 分类器做意图路由、PII 检测、语义缓存,集成 Envoy |
| Bifrost | Go | 追求极低延迟 | 11µs P99 延迟,语义缓存,MCP 支持 |
| Kong AI Gateway | Lua/Go | 已有 Kong 基础设施 | 复用现有网关,加 AI Proxy 插件 |
对你最现实的路径 :如果你的 Agent 已经用 vLLM 做推理后端,vLLM Semantic Router + Production Stack 是自然延伸;
如果只是想先跑起来,LiteLLM 最省事。
2.2 LiteLLM配置路由和护栏
LiteLLM 的路由和护栏集成,核心逻辑都是在 config.yaml 里声明规则,然后由 Proxy 执行。你可以把它理解成一个"声明式"的 AI 流量网关。
2.2.1🛣️ 如何做路由
LiteLLM 的路由主要有两种玩法,你可以根据场景选择:
1. 基于模型的显式路由(最直接) 这是最基础的方式,客户端在请求里指定 model 名称,LiteLLM 根据 model_name 找到背后真实的部署。它天然支持一个名称对应多个后端(负载均衡)。
model_list:
# 医学问答走本地 Ollama
- model_name: "medical-qa"
litellm_params:
model: "ollama/qwen2.5:7b"
api_base: "http://localhost:11434"
# 代码辅助走另一个模型
- model_name: "coding-assistant"
litellm_params:
model: "openai/qwen-coder"
api_base: "http://vllm.internal:8000/v1"
2. 基于语义/复杂度的自动路由(更智能) 如果不想让客户端指定模型,LiteLLM 可以自动判断请求的"意图"或"复杂度",把它分发给合适的后端。这通过 auto_router 实现:
-
分类方式 :默认用启发式评分 (零 API 调用,亚毫秒级),检测关键词、代码片段、推理标记等。也可以配 LLM 分类器,用一个小模型来判断,但会增加延迟和成本。
-
分层路由:根据分类结果,把请求映射到不同的"层级"(tier),每个层级可以配置一个或多个模型。
model_list:
- model_name: "smart-router"
litellm_params:
model: "auto_router/complexity_router"
complexity_router_config:
tiers:
SIMPLE: "ollama/qwen2.5:7b" # 简单问题走本地
COMPLEX: "openai/gpt-4o" # 复杂问题走大模型
2.2.2🛡️ 如何集成护栏
护栏集成同样是声明式的。你可以在 config.yaml 里配置使用内置护栏 、第三方护栏 (如 Akto, Straiker),或者自定义护栏。
配置示例(混合使用内置和第三方):
guardrails:
# 使用内置的 PII 检测(快速、确定性)
- guardrail_name: "pii-check"
litellm_params:
guardrail: "presidio" # 内置或第三方
mode: "pre_call" # 在请求发往 LLM 前检查
default_on: true # 对所有请求生效
# 使用 Akto 做基于模型的深度检测(防注入、语义 PII 泄露)
- guardrail_name: "akto-guard"
litellm_params:
guardrail: "akto"
mode: "pre_call"
api_key: "os.environ/AKTO_API_KEY"
关键特性:
-
执行时机 :
pre_call在输入时检查,post_call在输出时检查。 -
策略控制 :可以通过
policies将护栏组合成策略,并精确地附加到特定的团队、密钥或模型上,实现精细化的权限管理。 -
流式处理 :对于流式响应,
post_call护栏默认只能审计,无法阻断。但可以使用async_post_call_streaming_iterator_hook来实时处理每个数据块,实现流式阻断。
💭 针对之前医学 Agent 的落地方案
结合你的场景,可以这样设计:
-
路由层 :定义
medical-qa和medical-triage等model_name。对于"分诊"这类简单意图,可以用启发式路由直接分发给轻量模型;对于"用药咨询"等复杂且高风险的任务,强制路由到能力更强的模型。 -
护栏层:
-
Pre-call:启用 PII 检测(脱敏患者信息),并可以接入一个第三方护栏(如 Straiker)来防御 Prompt 注入。
-
Post-call :对于医学输出,可以使用
Policy Flow Builder配置一个更严格的检查管道,比如先用快速规则过滤,如果通过再调用一个基于模型的护栏进行深度审核。
-
LiteLLM 的优势在于,路由和护栏的配置是分离但可组合的,你可以先让路由跑起来,再逐步叠加护栏策略,验证效果后再全量开启。
2.3 护栏分类
不是必须每次都调用一个独立的模型。护栏的实现方式分几个层次,模型调用只是其中成本最高的一种。
2.3.1🧱 护栏的四种实现方式
1. 规则/正则(零模型调用) 最快、最便宜。用关键词、正则表达式、黑名单匹配。比如检测"ignore previous instructions"这类越狱关键词,或者匹配身份证号、手机号格式。延迟在微秒级,但容易被绕过。
2. 小模型分类器(一次轻量推理) 用 BERT 级别的模型做分类判断,比如判断"这段话有没有害""是不是 Prompt 注入"。模型很小(几千万参数),CPU 就能跑,延迟在毫秒级。你之前看的 SemGuard 就是这类,2270 万参数,延迟 21-40 毫秒。
3. 大模型裁判(一次完整 LLM 推理) 用 LlamaGuard、QwenGuard 这类专门微调的安全模型,或者直接用一个通用大模型做 judge。判断更准,但延迟和成本都高。实测中,一个 20B 的裁判模型单次判定平均需要 12.74 秒。
4. 混合分层(生产环境常用) 先跑规则,不确定的再升级到小模型,还不确定的才调大模型。这样绝大多数请求走快速路径,只有少数可疑请求触发昂贵推理。
2.3.2 🎯 输入护栏和输出护栏的差异
输入护栏通常在请求到达主模型前执行。可以用规则 + 小模型组合,因为输入文本相对短,且需要在低延迟下完成。
输出护栏更复杂。如果主模型是流式输出,输出护栏面临一个两难:
-
逐 chunk 检查:每个 chunk 都调一次模型,成本爆炸,且上下文不完整容易误判
-
等完整输出后检查:失去流式意义,用户要等全部生成完才能看到
-
滑动窗口检查:每累积一定长度(比如一句话)跑一次检查,是折中方案
2.4 常见护栏
工程中最常用的护栏工具,可以按技术分类 分为三类:编程框架、分类器模型、托管 API。
它们的核心差异在于"谁来做判断"------框架用你定义的规则组合,分类器用预训练模型,托管 API 则把判断逻辑封装成一次远程调用。
根据你的要求,以下是加入 Bastion Prompt Protection、PromptShield Guard、Fendrix 和 subcanopy-guard 后的完整护栏对比表格。
📊 主流护栏工具对比(更新版)
| 工具 | 谁做的 | 技术分类 | 输入/输出 | 核心特点 | 速度 |
|---|---|---|---|---|---|
| NeMo Guardrails | NVIDIA | 编程框架 | 两者都支持 | 用 Colang 定义对话流、话题边界、越狱检测,支持多模型 | 较慢,~10x 于轻量方案 |
| Guardrails AI | 开源社区 | 编程框架 | 两者都支持 | Python 验证器"中心",可组合 PII、毒性、格式检查,验证失败自动重试 | 取决于验证器 |
| Llama Guard 3 | Meta | 分类器模型 | 两者都支持 | 开源权重,覆盖 MLCommons 13 类风险,支持 8 种语言 | 一次模型推理 |
| Presidio | Microsoft | 混合检测(规则+NLP) | 主要用于输入(可扩展输出) | 专注 PII 检测与匿名化,支持 40+ 实体类型,可自定义识别器 | 毫秒级(规则部分) |
| PromptGuard (商业版) | 商业公司 | 托管 API | 两者都支持 | 与 OpenAI API 线兼容,一行代码接入,含 7 层检测管道 | 1.4ms(规则层) |
| Azure Prompt Shields | Microsoft | 托管 API | 主要用于输入 | 专防直接越狱和间接注入,按请求计费 | 网络延迟 |
| OpenAI Moderation | OpenAI | 托管 API | 两者都支持 | OpenAI API 用户免费,覆盖仇恨、暴力、自残等类别 | 网络延迟 |
| Meta Prompt Guard 2 | Meta | 分类器模型(开源) | 输入 | Llama 许可免费,86M/22M 两种规格,mDeBERTa 骨干,支持 8 种语言,抗对抗性 tokenization | 一次模型推理 |
| Bastion Prompt Protection | bastionsoft | 混合检测(规则+分类器) | 输入 | 70M 参数,DeBERTa-v3-xsmall 微调,专为 LLM 管道设计,ONNX 部署,无 API 依赖,AUC 0.991(远超 Meta Prompt Guard 的 0.299) | ~5-10ms(INT8 ONNX,CPU) |
| PromptShield Guard | lorthris | 纯本地引擎 | 输入 | 分析传入提示词拦截注入、越狱和系统提示词提取,零遥测、零网络调用,完全本地运行 | <0.2ms |
| Fendrix | fendrixai | 混合检测(规则+启发式+LLM) | 输入 | 三层检测管线:规则匹配(覆盖~75%攻击,零成本)→ 启发式评分(7 个行为信号)→ LLM 裁判(仅处理模糊情况),结果可解释 | ~0.05ms(规则层) |
| subcanopy-guard | subcanopy | 纯规则(无 ML) | 输入 | 滑动窗口测量局部指令密度,结合不连续性和来源风险乘数,纯 Python 标准库实现,无 ML 模型、无 API 调用 | ~0.85ms(p50) |
🔍 几个免费的模型关键定位
Bastion Prompt Protection 是当前检测精度最高的开源选择。它的 70M 模型在四个 held-out 基准上平均 AUC 达 0.991,而 Meta 的 Prompt Guard 2 只有 0.299。INT8 ONNX 构建下单次推理仅 5-10ms,适合作为你的第一道输入过滤。注意它的许可证是 AGPL-3.0,如果作为网络服务运行需要开源对应代码,商业许可可向官方申请。
PromptShield Guard 的核心卖点是极致隐私。所有计算在本地完成,零遥测、零网络调用,对于患者数据不能出网的医学场景很有吸引力。延迟 <0.2ms,几乎不增加感知延迟。它的 Guard Edition 在 Gumroad 上标价 $19,核心代码在 GitHub 开源。
Fendrix 的三层架构 很适合工程集成:第一层纯规则匹配(零成本),第二层启发式评分,第三层才调用 LLM 处理模糊情况。这种设计让它在处理海量流量时成本极低,同时保留了处理复杂攻击的能力。返回结果包含 layer_triggered 和 rule_matches,方便调试和调整策略。
subcanopy-guard 走的是完全无 ML 的纯规则路线。它用滑动窗口测量局部指令密度,在 AgentDojo 基准上以 0.85ms 延迟达到 86.5% 检出率,比 Meta Prompt Guard 2(149ms,1% 检出)快约 130 倍。如果你的场景对延迟极度敏感且不需要应对高度变形的攻击,这是最轻量的选择。
🏗️ 框架 vs 分类器 vs API 的本质区别
编程框架(NeMo、Guardrails AI) 给你的是"乐高积木"。你定义规则、组合检测器、控制流程。适合需要精细策略控制的场景,比如"仅在检测到医疗建议时触发人工审核"。代价是需要工程投入,且性能取决于你调用的底层模型。
分类器模型(Llama Guard) 给你的是一个"训练好的判断器"。你把文本丢进去,它返回 safe 或 unsafe 加上违规类别。适合不想自己写规则、只想快速加一层安全过滤的场景。代价是"黑盒",你无法精确控制它的判断逻辑,且对抗性攻击可能绕过它。
托管 API(PromptGuard、Azure) 给你的是"即插即用的服务"。一行改 URL 就能接入,无需部署和维护。适合快速上线、不想运维的场景。代价是数据要出你的网络,且按量计费。
🎯 对医学 Agent 的选型建议
结合之前的架构讨论:
PII 脱敏(输入侧) :Presidio 是首选。它专门做这件事,支持中文实体(需配置),可以集成到 LiteLLM 的护栏链里。你之前问的 pii-check 底层就是它。
输出安全(输出侧) :Llama Guard 3 可以本地部署,检查模型输出是否包含有害内容(如 S6 专业医疗建议、S7 隐私泄露)。对于医学 Agent,S6 和 S7 是需要重点关注的类别。
首选 Bastion Prompt Protection:精度最高、速度够快、本地部署、无数据外泄。作为输入护栏的第一道防线,配合你已有的 Presidio 做 PII 脱敏,基本覆盖输入侧的主要风险。
PromptShield Guard 作为备选:如果你的合规要求极端严格(任何数据都不能离开服务器进程),它的零网络调用特性最安全。
Fendrix 作为架构参考:它的"规则→评分→LLM"分层思想可以直接借鉴到你的 LiteLLM 网关配置中,用于设计低成本的一级初筛。