news 2026/10/2 20:11:54

14 所有问题都丢给 RAG?面试官想听的是「Query 路由」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
14 所有问题都丢给 RAG?面试官想听的是「Query 路由」

面试官:"你们那个知识库问答,用户每问一句,你都去向量库捞一遍?"

候选人:"对啊,先检索 top-k,把资料塞进 Prompt,再让模型答。"

面试官:"那用户说'你好'、说'你会说英语吗'、说'3 加 5 等于几',你也去捞一遍?"

候选人:"……也能捞,就是浪费点。"

面试官:"那用户问'今天上海天气怎么样',你库里压根没这条,模型给你编一个,用户信了,算谁头上?"

候选人:"……"

这道题的胜负手就四个字:Query 路由。

大多数同学做 RAG,脑子里只有一条线:"来一个问题 → 检索 → 生成"。但真实的生产系统里,用户发来的每一句话,并不都该走检索这条道。有的该直接答、有的该调工具、有的该干脆拒答。"这一句该怎么处理",就是 Query 路由干的活。

这篇把它讲透:为什么要路由、路由分几条道、三档实现方案怎么选、Java 里怎么写、路由错了怎么兜。


一、为什么"每句话都检索"是个坑

先把代价说清楚,不然你会觉得路由是"过度设计"。

第一,烧钱。检索不是免费的。用户问题要先过一遍 embedding 模型(一次 API 调用或一次 GPU 推理),再去向量库做相似度搜索。这两步都有延迟、都有账单。用户只是想打个招呼,你却在背后默默算了一次向量。

第二,添乱。检索出来的 top-k 文档,是"向量最相似"的,不是"真正相关的"。用户问"你们公司几点上班",向量库可能捞出一堆语义相近但毫不相干的段落,全塞进上下文反而成了噪声,把模型带偏。上下文里垃圾越多,答错概率越大。

第三,答不了。有些问题压根不该查库。今天是几号、现在几点、这个订单发到哪了、这台机器负载多少——这些是实时、外部的信息,知识库里没有。硬走 RAG,模型只能编。幻觉的一大来源,就是"让模型去回答它根本拿不到的东西"。

一句话:RAG 是给"有据可查"的问题准备的,不是万能钥匙。


二、Query 路由:把一句话分到四条道上

路由的本质,是先判意图,再选链路。

一条典型的四岔路:

1.直接回答(Direct):寒暄、闲聊、通用常识、礼貌用语。不查库,直接让模型答,命中缓存就更快。

2.检索增强(RAG):关于知识库、内部文档、业务资料的问题。走"检索 → 拼上下文 → 生成"。

3.工具调用(Tool):实时数据、精确计算、查订单、发消息。走 Function Calling。

4.拒答兜底(Refuse):越界、敏感、拿不准。明确说"这个我答不了",而不是硬编。

面试官问"你们怎么做路由",其实是在问:你有没有意识到,"检索"只是众多处理链路里的一条。


三、三档实现方案,按成本排

方案一:规则 + 关键词(零成本,覆盖 60%)

最简单也最稳。用关键词、正则、长度、疑问词来粗筛。

public class RuleRouter { private static final Set<String> GREETINGS = Set.of("你好", "在吗", "hi", "hello", "嗨"); private static final Pattern ARITHMETIC = Pattern.compile("^\\s*\\d+\\s*[+\\-*/]\\s*\\d+.*"); public Route route(String question) { String q = question.trim().toLowerCase(); // 寒暄:别去查库,浪费 embedding if (GREETINGS.contains(q)) return Route.DIRECT; // 纯算术:交给计算器工具,模型算数不靠谱 if (ARITHMETIC.matcher(q).matches()) return Route.TOOL; // 实时数据关键词:走工具接口 if (q.contains("订单") || q.contains("物流") || q.contains("余额")) { return Route.TOOL; } // 默认:走检索 return Route.RAG; } }

规则路由的好处是快、便宜、可解释,错了能一眼看出是哪条规则的问题。坏处是"死",用户换种说法就绕过去了。

方案二:小模型分类器(低成本,覆盖 85%)

把意图识别当成一个短文本分类任务。两条常见路子:标几百条样本训个小分类器;或者更省事——用 embedding 拿用户问题去和每个意图的"锚点句"算相似度,取最近的意图。

public class EmbeddingRouter { private final EmbeddingModel embeddingModel; // 每个意图准备几句"锚点句" private final Map<Route, List<String>> anchors; // 低于这个相似度,就当"拿不准" private static final double THRESHOLD = 0.35; public Route route(String question) { float[] qv = embeddingModel.embed(question); Route best = Route.RAG; double bestScore = -1.0; for (Map.Entry<Route, List<String>> entry : anchors.entrySet()) { for (String anchor : entry.getValue()) { double score = cosine(qv, embeddingModel.embed(anchor)); if (score > bestScore) { bestScore = score; best = entry.getKey(); } } } // 都不够像 → 退回最稳的 RAG,别乱猜 return bestScore < THRESHOLD ? Route.RAG : best; } private double cosine(float[] a, float[] b) { double dot = 0, na = 0, nb = 0; for (int i = 0; i < a.length; i++) { dot += a[i] * b[i]; na += a[i] * a[i]; nb += b[i] * b[i]; } return dot / (Math.sqrt(na) * Math.sqrt(nb) + 1e-8); } }

这一档性价比最高:延迟只有一次 embedding、成本低、对多数业务准确率够用。锚点句要覆盖真实用户的口语,别拿"标准书面语"去测。

方案三:让大模型自己判(灵活,最贵)

给模型一段"路由提示",用结构化输出(见第 20 篇)保证它稳定吐标签。

private static final String ROUTER_PROMPT = """ 你是意图分类器,只输出一个标签,不要任何解释。 direct = 闲聊 / 寒暄 / 通用常识 rag = 需要查询内部知识库 tool = 需要实时数据或精确计算 refuse = 越界或不该回答 用户问题:%s 标签:""";

代价是每次路由都多烧一次模型调用,延迟和成本双涨。所以大模型路由一般只用来兜底:规则和小模型拿不准的,才交给它。

生产的答案通常是混合:规则先筛(快、覆盖大头)→ 小模型补位 → 边缘问题交大模型 → 结果进缓存,同一句话下次直接命中。


四、路由错了怎么办:兜底比准确更重要

路由不是"对/错"的判断题,是概率判断。再好的分类器也会判错。所以设计路由时,重点不是"怎么不失手",而是"失手了会怎样"。

几条铁律:

-检索为空,要明说。向量库没捞到足够相关的文档,别把空上下文丢给模型硬编。直接回"知识库里暂时没有相关资料",或者转人工。

-路由失败,默认检索。分类器报错、超时、返回未知标签时,落到最稳的那条道(通常是 RAG)。宁可多查一次,也别乱答。

-工具调用要有超时和降级。外部接口会超时、会报错,要设超时、要降级("暂时查不到,请稍后再试"),别让一条慢调用把整条链路拖死。

-拒答要具体。不是冷冰冰的"无法回答",而是"这个问题超出我的知识范围,你可以换个说法,或联系人工"。

还有一点容易被忽略:路由要可观测。上线后要记录每一句走到了哪条道、命中率多少、兜底率多少。否则你根本不知道路由是好是坏。


五、别把"路由"和"查询改写"搞混

这一点面试里常被追问。

查询改写(Query Rewrite):问题还是要走检索,只是先把口语化、指代不清的问法,改写成更适合检索的形式。比如把"它怎么用"改成"XX 功能怎么使用"。它优化的是检索质量。

Query 路由(Routing):决定走不走检索这条岔路。它优化的是链路选择。

一个守在岔路口,一个站在车道里。两者是配合关系:路由决定走检索了,才轮到改写去打磨检索词。


🎯 面试官视角的标准回答

被问"你们怎么做 Query 路由",按这个顺序答,稳:

第一句先给结论——"我们的原则是:不是每个问题都走检索。先判意图,再选链路。"

第二句讲四条道——"兜底是直接回答,比如寒暄和常识;知识类问题走 RAG 检索;实时数据和精确计算走 Function Calling;越界问题直接拒答。"

第三句讲实现——"规则筛一遍打头阵,成本为零;规则拿不准的走 embedding 分类器,一次向量调用就能判;特别边缘的才让大模型兜底,因为它最贵。结果统一进缓存。"

第四句讲兜底——"路由是概率判断,所以关键在设计兜底:检索为空要明说、路由失败默认走检索、工具调用必须有超时降级、拒答要具体。同时全程记日志,保证线上可观测。"

最后补一句区别——"注意路由和查询改写不是一回事:改写是决定'怎么查',路由是决定'要不要查'。"

这五句说下来,面试官就知道你不是"调了个 RAG 就完事"的水平,而是想过链路编排。


踩坑提示

- 别把路由逻辑写死在 Controller 里,抽成QueryRouter接口,方便换实现、方便测试。

- 规则路由的关键词表,一定要拿真实用户日志去迭代,别拍脑袋。

- 缓存 key 别只用原始问题,同一句在不同用户、不同权限下答案可能不同,要带上身份维度。

- 路由判错时,日志里要留原始问题和判定结果,否则线上出问题你无从复盘。

下篇预告:既然检索不是万能的,那"把知识灌进模型"这件事,到底该靠 RAG 还是靠微调?第 15 篇聊这个绕不开的选择题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 20:11:52

PDF转Excel免费的软件有哪些?电脑手机实用工具全攻略

日常办公、整理数据、统计报表时&#xff0c;很多人都会遇到一个难题&#xff1a;拿到的PDF表格无法直接编辑、复制数据&#xff0c;手动录入不仅耗时费力&#xff0c;还容易出错。市面上PDF转换工具五花八门&#xff0c;大多暗藏会员收费、水印限制、上传泄密等问题。今天给大…

作者头像 李华
网站建设 2026/10/2 20:11:34

MySQL日志体系实战:从故障排查到数据恢复的全景指南

MySQL的日志体系经常被忽视&#xff0c;但几乎所有线上问题排查、数据恢复、性能优化都离不开它。这篇文章不按官方文档的顺序讲&#xff0c;而是把我实际工作中用到的日志知识、踩过的坑、以及一些容易被忽略的细节整理出来&#xff0c;从一个偏实战的角度把这些“杂知识”串成…

作者头像 李华
网站建设 2026/10/2 20:11:31

PowerDesigner 建模实战:CDM/PDM、反向工程与DDL同步详解

做数据这一行久了&#xff0c;我越来越觉得&#xff0c;数据库里真正值钱的往往不是业务数据本身&#xff0c;而是那套被反复修改、堆了很多年之后没人说清楚的结构。数据可以重新导入&#xff0c;结构一旦乱了&#xff0c;后面每一个新需求都会变成一次冒险。PowerDesigner 解…

作者头像 李华
网站建设 2026/10/2 20:11:03

工业大模型落地产线异常工单:能力边界与RAG实践

1. 产线异常工单为什么成了工业大模型的"第一块试金石"干了十几年制造业信息化&#xff0c;我见过太多项目死在"期望值管理"上。工业大模型这两年热度飙升&#xff0c;但真正落到产线异常工单这个场景&#xff0c;能跑通闭环的案例屈指可数。问题不在于模型…

作者头像 李华