大多数 RAG 系统的流水线是一条直线:进来什么问题,都切块检索、拼上下文、生成回答。这条直线在演示里没问题,上线后马上暴露出两类尴尬。第一类,不需要检索的问题也被检索了:「帮我总结这段话」「写个周报」甚至「你好」,被硬塞了一堆检索片段,生成质量反而被噪声拉低——上下文里的无关内容会干扰模型(《上下文组装》一篇讲的注意力稀释,这里就是病根)。第二类,该走专用通道的问题走错了通道:「上月销售额多少」需要走结构化数据查询而不是文档检索;「订单 2024031 到哪了」该查业务系统而不是知识库。查询路由(query routing)就是插在用户问题和检索层之间的分流器,这篇讲清它要判断什么、用什么实现、错了怎么办。

路由器要做的三个决策
决策一:检索还是不检索(retrieval necessity)。 问题类型大致分四档:闲聊与元请求(直接回答);创作与改写(无需求检索,检索反而引入偏置);上下文内推理(对话里已给出材料,做摘要/翻译/计算,检索多余);事实与知识型(真正需要外部知识,值得检索)。第四档才进检索流水线。这一步的价值被普遍低估:企业知识库的真实查询里,前三档常常占到两三成,把它们放走,省下的不只是检索成本,更是生成质量。
决策二:走哪条检索通道。 到了「需要检索」这一档,还有分叉:通用文档向量索引、全文/BM25 索引(标识符、型号、错误码类查询该走词法)、结构化查询(Text2SQL 走数仓)、专库(代码库、工单库、产品手册各有索引)。本系列前面几篇准备的弹药——SPLADE 适合改写、BM25 适合精确词、dense 适合语义——在这里汇合成路由依据:查询特性不同,最合适的索引就不同。
决策三:能不能答/要不要澄清。 问题太模糊(「帮我查一下那个东西」)、缺关键参数(「对比一下性能」——和什么比?)、或超出知识库范围时,直接检索是在浪费一次调用,路由器应该触发澄清追问或礼貌拒绝(拒答策略详见《拒答与校验》)。
实现谱系:从规则到 LLM
三种实现按成本递增排列,生产系统常常是三层混合。
规则层(零成本,先拦粗的)。 极短查询、问候语、正则可识别的模式(工单号、纯数字、明确指令动词开头)直接分流。规则层解决的是「明显不需要动脑」的流量,别小看它——很多系统的闲聊流量靠一条 len(query) < 8 就能拦掉大半。
小分类器(毫秒级,管高频分类)。 用一个嵌入模型 + 线性层或小型 BERT 分类头,对「检索/不检索/结构化/澄清」做分类。训练数据从哪来?真实查询日志标注几百条即可起步(这也是为什么查询日志要从第一天就开始攒——《评测集构建》一文会再强调)。分类器的优势是延迟低、成本零、行为稳定可回归测试;劣势是类别体系死了就不会变,边界样本误判率高。
LLM 判断(灵活,管难样本)。 让主模型(或小一档的模型)按结构化输出判断:意图类别、目标索引、是否需要澄清、改写后的检索词。它天然能处理长尾和组合意图,还能顺便把《查询改写》的活干了(分类与改写一次调用完成)。代价是延迟(几百毫秒)和成本,且输出需要 schema 约束与兜底解析。
ROUTE_PROMPT = """你是问答系统的路由器。对用户问题输出 JSON:
{"intent": "chitchat|create|context_reasoning|knowledge",
"index": "docs|lexical|sql|none", # knowledge 时必填
"clarify": null | "需要向用户澄清的问题",
"rewrite": "knowledge 时的检索改写"}
问题类型判断要点:
- 让你写/改/翻译/总结「用户给的内容」→ context_reasoning,无需检索
- 问事实、政策、流程、数据 → knowledge
- 含工单号/型号/错误码 → lexical
用户问题:{query}"""
实践推荐组合:规则层拦明显流量 → 分类器管主干 → LLM 兜难样本。全部流量都进 LLM 判断的架构,延迟和成本都很难看;全部靠规则又挡不住自然语言的长尾。
路由不互斥:并行与融合是合法答案
一个常被架构评审问倒的问题:「路由器把查询分给文档索引还是 SQL 通道——错了怎么办?」解法的思路要转个弯:路由不必是单选题。低置信度的路由可以「并行多路」——同时查文档索引与结构化通道,结果在融合层合并重排(《混合检索》的融合思想上升到通道层);代价是延迟与成本翻倍,所以它只该服务「高价值查询 + 路由不确定」的交集,置信度高的流量仍然单路快跑。并行多路的另一个身份是路由器的评测器:线上对抽样流量做影子并行(双路都查、只采纳一路),对比「单路决策」与「融合答案」的质量差,差值就是路由器的改进空间——比离线评测更贴近真实分布。
澄清追问的设计分寸
决策三触发的澄清追问,产品上有个分寸问题:问一次就够,而且要给选项。「对比一下性能」的澄清不该是一句「您想对比什么?」(用户还得再组织语言),而应该是「您想对比哪个?A. 与上季度 B. 与竞品 C. 与预算目标」——选项式澄清把一次开放式往返压成一次点击。规则:澄清选项必须由系统从上下文猜出来(历史会话、常用维度、可见的数据切片),猜不出选项的模糊问题宁可走「按最常见解释检索 + 答案开头声明假设」——「我按『与上季度对比』来回答,如果您想要其他维度请告诉我」比连环追问的体验好得多。澄清是路由器的逃生门,不是甩锅给用户的接口。
路由层的观测指标
路由器独立成层后要有自己的仪表盘,四个指标起步:通道流量占比(检索/不检索/结构化/澄清——占比突变常对应上游产品变更或路由器回归);路由耗时分布(规则+分类器层应在毫秒级,占比异常说明流量漏进了 LLM 层);漏路由率(生成端触发逃生门二次检索的比例——《Self-RAG》的兜底被触发得越频繁,说明路由器的「检索必要性」判断越不准);坏例回流量(负反馈且上下文为空的 case 数——它们是分类器的下一批训练数据)。四个指标进告警的阈值由基线漂移定,别用拍脑袋的绝对值。
失败代价与降级设计
路由错误的代价是不对称的,设计降级策略前先分清两个方向。漏路由(该检索没检索):模型在没材料的情况下硬答,幻觉直接暴露给用户——这是重罪,伤信任。误路由(不该检索却检索了):多花一次检索的钱,生成被无关上下文带偏,但多数时候模型还能扛住——轻罪。所以路由器的默认倾向应该是宁可误路由、不可漏路由:分类置信度低时落入「检索」这个默认通道,把「不检索」只留给高置信的明显场景。另一个必要件是路由逃生门:生成端发现上下文不足以回答时,能触发二次检索(这其实是《Self-RAG》一篇的核心思想——路由不必一次做对,生成端可以补救)。
监控上,路由器是 RAG 系统里最值得单独观测的一层:各通道流量占比、路由变更前后的回答质量对比、漏路由的坏例(用户点「不满意」且上下文为空的 case)回流进分类器训练集。路由器本身也是个小模型系统,用坏例持续喂养它,比一次性精心设计规则有效得多。
多知识库场景的路由
企业内知识库越来越多之后,路由多了一个维度:库间路由——「报销制度」去 HR 库、「API 用法」去技术文档库、「合同条款」去法务库。实现上它在「检索必要性」判断之后追加一层库选择:规则型(按查询关键词映射,冷启动可用)、分类型(各库抽样本训练,精度高但加库要重训)、或 LLM 判断(给出各库的一句话画像让模型选)。两个工程细节决定体验:库描述的质量——每个库给路由器的一句话画像(「本库收录员工手册与人事制度,涵盖考勤、薪酬、福利」)比库的名字有效得多,描述要随库内容维护;跨库兜底——单库路由错了就全错,高价值场景允许 top-2 库并行检索再融合(「路由不互斥」一节的并行思想),低成本换鲁棒。库间路由的评测:按库分组的测试题各自成组、路由正确率单独统计——它是多库系统里最先要看的指标。
路由器的冷启动与迭代节奏
路由器是个「活组件」,两件事要写进运维节奏。冷启动:日志还没攒够时不要上分类器,规则层加「默认进检索」的兜底就能跑——早期的路由精度靠「宁可多检索」的方向感保证,等真实查询标注到几百条,分类器的第一版才值得训练;急着上 LLM 全量判断是最贵的冷启动方式。迭代节奏:查询分布会漂移(新产品上线、新人群接入),分类器每季度用近期标注重训一次;每次重训都跑同一份评测集对比新旧分类器的混淆矩阵——「哪两类之间的混淆变多了」往往直接对应「哪类查询的表述漂移了」,这比看总准确率有用得多。路由器的回归门禁与检索层共用一套机制(《评测集构建》),路由相关的改动(新增通道、调整规则)必须在评测集上不劣化才能上线。
小结
查询路由常被当成「锦上添花的优化」,但在真实流量下它是质量与成本的 doubly 杠杆:放走不需要检索的两三成流量,既省了检索的钱,又清净了生成端的上下文;把结构化查询和精确词查询导去正确的通道,避免了「用向量库硬查 SQL 能答的问题」这类水土不服。实现上从规则层起步、分类器管主干、LLM 兜长尾,失败方向上宁误路由不漏路由,再配上生成端逃生门兜底——路由不需要完美,需要的是「错了也不至于灾难」。
参考资料
- LangChain: Query Analysis —— 查询分析与结构化输出的官方教程,路由字段的 schema 设计可参考
- 本系列前篇:《查询改写》《Self-RAG:让模型自己决定什么时候检索》《拒答与校验》《上下文组装》
- 提示:路由分类器的训练数据与评估方法,与《评测集构建》中的查询集构建共用一套基础设施
读者留言
COMMENTS 暂无还没有留言,来说第一句?