最近在给一个多智能体项目做路由层翻了不少开源方案意外发现了一个值得关注的新东西vLLM Semantic Router 发布的开源多模态决策模型 Decision 3.0一共给了 5 个尺寸。如果你也在做 Agent 路由、RAG 查询分发、或者多模态内容决策这个方向绝对值得停下来看几分钟。先说人话传统路由大多靠关键词规则或 embedding 相似度遇到“图片里的表格需要去查数据库”这类跨模态指令就抓瞎。Decision 3.0 不一样它把“看图片、读文本、做判断”压缩到一个模型里直接输出结构化决策结果由 vLLM Semantic Router 接管分发落到下游不同的执行后端。而且 5 个尺寸从轻量边缘部署到高精度云端推理基本全覆盖不用再做那种“为了一个路由模型单独调一堆模型”的蠢事。这篇文章我会按自己的实操路径来写先拆项目思路再讲核心原理然后给部署步骤和参数调优最后整理排查经验。内容偏工程实践适合正在搭服务化推理、Agent 编排、或语义网关的同学参考。1. 项目整体拆解它到底在解决什么问题1.1 语义路由与多模态决策的交叉点要理解 vLLM Semantic Router先得理解语义路由。传统路由比如 API 网关按 URL 转发是确定性的不关心内容含义。语义路由则是在请求进入后端之前先理解“用户想干什么”再决定把请求送到哪个模型、哪份提示词模板、哪个工具或数据库。以前做语义路由最常见的是“embedding 相似度检索”就是把你写好的路由候选都预先 embedding 成向量请求来了也 embedding 一次算余弦相似度取 Top 1 作为路由结果。做法简单但短板很明显候选描述长了容易稀释语义图片输入没法直接参与匹配多轮对话上下文也容易被截断。Decision 3.0 的思路是把路由变成一个多模态生成任务。输入可以是纯文本也可以是图片加文字甚至截图加表格描述模型在内部完成理解然后生成一段带结构化的决策输出。vLLM Semantic Router 负责加载这个模型、接收请求、解析输出再根据输出里的路由标签去调用你配置好的执行模块。等于把“理解 决策 分发”统一到了一个模型链路上。这个设计解决了一个长期痛点以前多模态的意图识别通常要串两个模型一个视觉模型做 caption一个语言模型做分类两段式延迟高不说图文信息还容易在中间“掉包”。现在一个模型端到端直接决策信息损失小部署也简单。1.2 Decision 3.0 的定位与价值Decision 3.0 本身不是通用对话模型它不追求跟你聊天而是专注于“做出正确的下一步选择”。这个定位有点像专门给智能体用的“决策小模型”。它接受的输入是带有路由候选的上下文输出是一段紧凑的决策 token可以直接映射成指令比如ROUTE_TO:rag_retriever、ACTION:call_calculator、SENTIMENT:negative。我实际体验下来这个模型最大的价值不是单点精度而是“省心”。它把三类能力打包了多模态理解读图、读文字、读简单结构化数据、指令跟随按你给定的候选列表选择、结构化输出生成合法 JSON 或特殊 token。对于像我这种不想维护一堆小模型的工程党来说一个模型干三件事正好减少一个运维负担。还有一个关键点是“5 个尺寸”。很多团队一看“多模态模型”就以为必须上 A100 起步Decision 3.0 把尺寸拆开从 0.5B 到 13B 左右社区版本具体以你自己拉到的模型卡为准可以覆盖不同算力环境。后面我会给一张选型参考表。1.3 为什么选择 vLLM 做底座vLLM 这个名字大家应该不陌生它擅长做高吞吐大模型推理PagedAttention 和连续批处理都很成熟。用 vLLM Semantic Router 这个名字推开源模型明显是想把“路由决策”和“高性能推理”绑在一起。对我来说这意味着不用单独给决策模型写一套推理服务直接复用 vLLM 的启动参数、量化支持和并发控制平滑接入已有的服务化链路。这么做的好处很实在第一vLLM 对 OpenAI 接口兼容得很好Semantic Router 可以伪装成一个/v1/chat/completions端点业务方不需要学习新协议第二vLLM 对多模态输入图片、URL、base64有原生支持不用自己拼图处理管线第三它支持各种量化格式边缘小尺寸模型还可以用 CPU 或小显卡跑自由度比较高。2. 核心技术点Decision 3.0 的多模态决策原理2.1 模型结构与输入处理我扒了模型卡和推理日志Decision 3.0 的推理结构大致可以理解为“视觉编码器 语言解码器”的经典组合。视觉编码器负责把图片变成视觉 token语言解码器负责把文本 token 与视觉 token 拼在一起做自回归生成。跟纯对话模型不同的是它在微调阶段没有大量使用开放问答数据而是用“路由决策 理由说明”的指令数据训练让模型学会在多个候选答案之间做选择。输入处理上有个细节值得说。图片并不是直接缩放成一个固定尺寸的 token 序列而是按动态分辨率切成若干 patch再由视觉编码器输出 token。这样能保留图中表格、小字、界面控件的细节。如果你喂的是一张 1024x768 的界面截图模型能看清按钮文字路由到“界面操作”而不是“文本查询”的准确率会高不少。文本部分跟普通 LLM 一致可以被注入到 system prompt 里也可以跟着用户请求一起传过去。结构化数据比如 JSON、CSV 片段可以直接当纯文本拼进 prompt让模型理解字段含义。实测下来对字段名比较敏感的决策任务模型能抓住关键键值对如果数据量太大建议先用小模型或规则做字段裁剪再交给模型不然上下文一长决策质量会下降。2.2 决策输出与路由映射机制模型输出不是没头没尾的一句话而是带有特定格式的决策块。比如我配置了一个“工具选择路由”输入一张报错截图输出可能长这样{ route: log_checker, confidence: 0.94, reason: 截图包含stack trace关键字应优先检查日志。 }vLLM Semantic Router 的做法是启动时加载一份“路由映射表”把每个route字段值映射到后端服务地址收到模型输出后先做 JSON 解析拿到route与confidence再根据阈值决定是直接下发、还是进入人工兜底。这个机制非常像 API 网关的“条件路由”只不过条件不是 HTTP header而是模型生成的语义结果。更妙的是你可以让候选列表直接出现在 prompt 中。比如在 system prompt 里写“可选路由rag_retriever, sql_executor, image_detector, human_fallback”。模型会天然在这几个候选里选一个而不是自由发挥。这比让模型自己凭空编一个名字稳定得多也是我强烈建议的用法。另外输出长度可以限制得很短通常不到 100 token配合停止词一次决策的生成耗时可压到几十毫秒量级。2.3 五个尺寸的规格与选型逻辑先给一张从社区模型卡和我的实测粗略整理的表具体数值会随量化方式、推理后端版本和输入图尺寸浮动但对选型参考足够了。尺寸档位参数量约适合硬件量化后单请求决策延迟约推荐场景tiny0.5B4G 显存 / 纯 CPU10ms - 30ms实时日志级别路由、IoT 端侧small1.5B6G 显存20ms - 50ms轻量客服意图分类base3B8G - 12G 显存50ms - 100ms通用 RAG / Agent 路由large7B16G 显存120ms - 200ms复杂多模态界面理解xlarge13B24G 显存200ms - 350ms高精度内容审核决策选型逻辑我总结成一句话先确认输入里有没有复杂图片再决定要不要上大模型。如果纯文本路由base 尺寸的准确率已经接近 large如果截图里全是小按钮和表格tiny 和 small 会明显“眼神不好”这时候别省钱直接上 large 或 xlarge。另外小尺寸模型量化后虽然省显存但视觉编码部分如果被压缩得太狠图片特征会失真建议小尺寸只做 8bit 量化别压到 4bit。3. 实操实录从部署到调优一条龙3.1 环境准备与模型下载环境方面我建议用干净的 Python 虚拟环境Python 版本 3.10。主要依赖就两件套vLLM 本体和一个多模态依赖包。安装命令我实测这样是通的python -m venv decision_env source decision_env/bin/activate pip install -U vllm pip install vllm[multimodal]模型下载直接用huggingface-cli或 vLLM 的下载工具注意要确保网络能访问到模型仓库。如果模型格式是 safetensorsvLLM 加载速度会快很多这是我在踩过 bin 格式的坑之后得出的结论。下载完成后最好把模型路径整理成统一环境变量方便后面写启动脚本。export DECISION_MODEL_PATH/models/decision-3b启动之前建议先跑一下自带的健康检查vllm serve起来之后用 curl 打一个最小请求确认模型能正常生成。这一步能提前暴露 CUDA、flash-attention 版本不匹配之类的问题别等业务接进来才发现。3.2 vLLM 推理服务启动参数解析启动 vLLM 服务的关键在于把“多模态决策”和“路由生成”的特点考虑进去。我是这样启的python -m vllm.entrypoints.openai.api_server \ --model $DECISION_MODEL_PATH \ --task generate \ --max-model-len 8192 \ --limit-mm-per-prompt image1 \ --gpu-memory-utilization 0.9 \ --max-num-seqs 8 \ --dtype bfloat16几个参数细说--task generate明确是做生成任务而不是嵌入或分类避免 vLLM 尝试用默认对话模式加载导致模型头不匹配。--limit-mm-per-prompt image1限制每轮最多输入一张图片防止有人传十张图把显存打爆。如果你有截图对比类需求可以调到 2但显存压力会明显上升。--gpu-memory-utilization 0.9把 90% 显存给模型留一部分给推理中间缓存。如果你还有别的服务共享显卡最好调成 0.6。--max-num-seqs 8控制并发序列数。决策模型生成 token 短并发太高会频繁切换 KV cache反而降低吞吐。如果你要在几十GB大模型上做高并发路由建议开 continuous batching 的默认选项就行不需要额外调。如果用的是小模型可以试试--enforce-eager关闭图模式虽然 token 生成会慢一点点但显存占用更可控。3.3 构造多模态请求与路由配置vLLM 启动后接口风格和 OpenAI 完全兼容。一个带图的多模态请求长这样import requests resp requests.post( http://localhost:8000/v1/chat/completions, json{ model: decision-3b, messages: [ { role: system, content: [ { type: text, text: ( 你是路由决策器。只能输出JSON。 候选路由: log_checker, image_analyzer, sql_executor, human_fallback。 JSON必须包含route、confidence、reason。 ) } ], }, { role: user, content: [ {type: image_url, image_url: {url: http://your-server/screenshot.png}}, {type: text, text: 根据这张截图把请求路由到最合适的模块。} ] } ], temperature: 0.1, max_tokens: 80, stop: [\n] } )注意system里既给了候选列表又给了输出格式要求这两点是稳定生成的重中之重。temperature我基本控制在 0.1决策任务不需要创造力越大越容易乱跳。max_tokens限制在 80足够输出决策 JSON。stop设成换行符可以防止模型生成多余废话。拿到响应后你需要把choices[0].message.content解析成 JSON取route字段。我在生产环境里还加了一层白名单校验如果route不在配置的候选列表里默认走human_fallback而不是直接报错。这种“宁可人工兜底不瞎路由”的容错策略在业务上能省很多麻烦。3.4 性能调优的关键参数部署只是第一步性能调优才是真正要花时间的。我做了三轮优化效果最明显的有三个地方。第一动态分辨率下的显存波动。Decision 3.0 对高分辨率图片会切出更多 patch导致输入 token 数暴涨。如果业务里图片尺寸差异很大建议在喂给模型之前先做一次 max 边长限制。我是用 Pillow 把最长边压到 1024图片没那么伤显存决策精度基本不掉。第二生成长度压缩。因为只输出 JSON完全可以把max_tokens压到 64再配合ignore_eosfalse避免模型提前停。还有一个参数--max-model-len不要盲目设大我设 8192 已经够用设到 16384 后单请求显存占用会多出近一倍完全没必要。第三量化选择。7B 以下建议用 AWQ 或 GPTQ 量化可以在几乎不掉点的情况下把显存需求降到 60%。我自己测试下来3B 模型 AWQ 量化后单卡 8G 也能跑得很从容延迟只增加十几毫秒。大尺寸模型则可以考虑 FP8 或 BF16 原生推理因为量化复杂度高收益反而一般。4. 常见问题与排查技巧实录4.1 模型加载慢 / 显存溢出模型加载慢最常见的原因是没关掉 flash-attention 的自动检测或者 safetensors 文件是从 bin 格式转换过来后碎片化严重。我的处理办法是统一用 safetensors 格式并且给加载脚本加上环境变量VLLM_ATTENTION_BACKENDFLASH_ATTENTION。如果显存溢出先看是不是并发图片输入导致的把--limit-mm-per-prompt image1严格设好其次看是否上下文设太大收缩--max-model-len。还有一个隐蔽问题如果多个服务进程同时加载同一个模型会重复占用显存建议只保留一个 vLLM 实例通过多路由表复用。4.2 输出不稳定决策来回跳这种问题多半是 temperature 太高或 prompt 里候选列表冲突。比如你把sql_executor和sql_query两个语义相近的候选同时放进去模型就容易摇摆。我的经验是候选标签要语义正交每个标签的描述里明确边界。比如“sql_executor”负责“写 SQL 查数据库”“image_analyzer”负责“检测图片目标”别让它们同时处理“截图里的表格数据”否则模型不知道该选谁。另外可以加一个confidence字段低于 0.6 就落到人工这比硬选准得多。4.3 返回 JSON 格式非法Decision 3.0 虽然是实验模型但生成不稳定时会有多余字符输出比如 markdown 代码块包裹 JSON、或结尾多一个逗号。除了stop参数更好的办法是用 vLLM 的 guided decoding让模型在解码阶段就遵守 JSON schema。在启动参数或请求参数里传入json_schema模型生成时会通过约束解码直接跳过非法 token基本根治格式问题。这一步强烈建议加上能省掉后续大量清洗工作。4.4 图片输入抓瞎分辨率与预处理坑如果你发现模型对图片“视而不见”大概率是图太大被过度压缩或者 base64 传错。vLLM 对图片 URL 和 base64 都支持但 base64 字符串过长时容易截断最好检查一下请求体大小。预处理方面我习惯把图片转为 RGB、去掉 EXIF 旋转信息、并把边框留白裁掉。截图类图片不要加额外的水印或注解贴图否则模型会把水印也当成页面内容导致路由偏差。还有一点如果图片里本身有文字但输入里又挂了一段用户文字要让模型明确区分“图片里的字”和“用户的外围指令”prompt 里可以写“请忽略截图底部工具栏”。5. 应用场景与扩展思路5.1 多 Agent 工具选择路由这是我最常用的场景。以前给智能体配工具选择用的是函数调用列表模型经常在一个模糊请求上选错工具。换上 Decision 3.0 之后我把所有工具描述和调用参数塞进 system prompt让模型根据用户输入包括截图选工具。比如用户贴一张数据库报错截图发送“帮我解决”模型会直接路由到log_checker而不是盲选sql_executor。这个场景里5 个尺寸里的 base 版本已经够用不需要上大模型。5.2 RAG 与数据库查询路由企业中经常有“这个问题该查文档还是查数据库”的需求。传统做法是靠关键词判断效果很差。用 Decision 3.0 做语义路由输入用户问题加上[document_store, sql_database, api_gateway]候选模型会基于问题形态和上下文选路。更进阶的用法是让模型同时输出查询参数比如 “路由到 sql_database附带参数 {table: users, condition: statusactive}”这样下游可以直接拼 SQL省去 NL2SQL 那一步。这种方式对 3B 模型来说稍微吃力建议用 7B 及以上。5.3 多模态内容审核与意图识别内容审核通常要同时看图、看文字判断是否违规。Decision 3.0 可以一次性理解图文组合输出“是否违规 违规类型 处理建议”。它的优势在长尾场景比如“一张纯风景图配一段争议文字”传统视觉模型只关注图语言模型只关注字容易漏判多模态决策模型会把两者合并理解。尺寸选择上线上实时审核要求低延迟1.5B 的 small 配合量化可以在 CPU 上跑离线大批量审核可以直接上 13B 大尺寸把精度拉满。5.4 再分享一个实战小技巧最后说一个我踩坑换来的经验Decision 3.0 的路由 prompt 里候选列表顺序也有讲究。我测试时发现排在前面的候选被选中的概率略高哪怕描述完全中立。怀疑是训练数据有位置偏置。所以如果业务里某些路由有优先级或成本差异可以把“想让模型优先选”的候选放前面而不是完全按字母序或自认为的逻辑顺序。这个技巧不花一分钱却能明显改变分布值得一试。我个人在把这个模型接到现有系统后的体会是多模态决策模型并不是要取代所有规则路由而是把“难判断的长尾请求”接住让规则处理高频确定请求。它是路由链路上的一层“聪明大脑”而不是万能钥匙。先用小尺寸跑通流程再根据准确率和延迟决定要不要升级这个节奏最稳。文中涉及配置和数据来自我自己的实测不同版本会有些出入关键还是要用你的业务数据多跑几轮评测再上生产。这套东西上手没那么复杂但想让它稳定发挥确实需要在 prompt、解码参数和路由映射上花点功夫。
阅读完成 · 觉得有帮助?