RAG 路由笔记:不是所有问题都该走同一条路
这篇主要讲什么
这一份 PDF 对应 Part 10 ~ Part 11,主题是 Routing,也就是路由。
通俗来讲,路由就是:
先判断这个问题属于哪一类,再决定把它交给哪一套资料、哪一个提示词、或者哪条处理链。
这背后的想法很朴素:
不同问题,适合走不同路径。硬让所有问题共用一套流程,往往会让系统又慢又不准。
1. 逻辑路由:先分类,再分流
原文里举了一个很典型的例子:
把用户问题分到 python_docs、js_docs、golang_docs 这样的不同资料源。
做法是让模型先输出一个结构化分类结果,然后系统根据分类结果,选择对应的数据源。
这件事的重点不在“分类”本身,而在“减少无效检索”。
如果一个 Python 问题被拿去 JavaScript 文档里搜,那后面再怎么生成也没意义。
我个人认为,逻辑路由特别适合下面这些场景:
- 一个系统接了多个知识库
- 不同业务线共用一个问答入口
- 一部分问题该查文档,一部分问题该走工具调用
它本质上是在做第一层筛选。
2. 语义路由:看意思像谁,就走谁
除了显式分类,原文还讲了语义路由。
这个方法不是直接让模型判断标签,而是把不同提示词或者不同路线的“说明文本”也做成向量,再和用户问题做相似度比较。
谁更像,就选谁。
文中举的例子是:
- 如果问题更像物理问题,就走 physics prompt
- 如果问题更像数学问题,就走 math prompt
这和逻辑路由的差别在于:
逻辑路由更像“先给标签,再走分支”;
语义路由更像“看气质更接近哪条路”。
我觉得语义路由很适合边界没那么清晰的场景。因为有些问题很难硬分类,但可以比较“更接近哪种处理方式”。
这份内容的核心思想
我觉得核心思想可以概括成一句话:
RAG 不一定是一个总流程,很多时候更像一个交通枢纽。
用户的问题先进来,然后系统先判断它该去哪,再开始后面的检索和生成。
如果没有路由,系统就容易出现两个问题:
- 什么都搜,成本高
- 到处都搜,结果乱
我自己的理解
路由其实是在解决“规模变大以后怎么办”的问题。
一个很小的 RAG 系统,可能只有一个知识库、一套提示词、一个回答方式,那确实不需要路由。
但只要系统开始变复杂,比如:
- 多个知识来源
- 多种任务类型
- 不同回答风格
- 不同工具链
那路由几乎就变成必需品了。
我自己的看法是:
路由不是高级装饰,而是系统开始变大时的基本组织能力。
我会怎么理解“逻辑路由”和“语义路由”
如果用很通俗的话区分:
- 逻辑路由:像前台分诊,先看你挂哪个科
- 语义路由:像系统自己听你描述后,判断你更像哪个科
前者更稳定、可控、可解释;
后者更灵活,对模糊问题更友好。
真正上线时,我倾向于:
能规则判断的,尽量先规则判断;
规则不够用时,再引入语义判断。
因为这样更容易调试,也更容易查错。
实践里要注意什么
- 路由标签不要设计得太细,不然分类容易抖
- 不同路线之间职责要清楚,不然路由了也没意义
- 最好保留路由结果,方便排查为什么答错
- 对“模糊问题”要考虑兜底策略,别强行分错类
一句总结
这一篇让我最认可的地方是:它提醒我们,RAG 不只是“搜和答”,还要先决定“去哪里搜、按什么方式答”。系统一旦复杂起来,路由就是把混乱变成有组织流程的关键一步。
核心代码实现
方法 1:逻辑路由
1 | def route_by_llm(question): |
方法 2:语义路由
1 | route_templates = { |
方法 3:路由后再执行对应链路
1 | def answer_with_semantic_route(question): |