AI- RAG笔记04 -检索优化
Chapter 4 :查询链路上的 RAG 优化
预览
本章套路 用户问题进入 RAG 系统之后,如何被理解、改写、路由、检索、重排、压缩,最终变成更可靠的上下文。
可以把本章理解为:
用户原始问题
-> 查询理解 / 查询重构 / 查询构建 / 查询路由
-> 选择合适的数据源和检索方式
-> 向量检索 / 混合检索 / 元数据过滤 / Text2SQL / Text2Cypher
-> 重排 / 压缩 / 校正
-> 给 LLM 更准确、更干净的上下文
-> 生成答案
分为几个部分
- 混合检索:提高召回质量。
- 查询构建:把自然语言转成结构化查询。
- Text2SQL:让自然语言查询关系型数据库。
- 查询重构与路由:让问题变成更适合系统处理的形式。
- 重排、压缩、校正:优化检索后的上下文质量。
结论:
让 RAG 检索阶段拿到更有用的信息,而不是盲目相信一次向量搜索。
1. 混合检索
混合检索是把多种检索方式结合起来,最典型的是:
稀疏向量检索 + 密集向量检索
稀疏向量
稀疏向量更像“词典 / 倒排索引”:
词项 -> 出现在哪些文档里 -> 权重是多少
它关注的是:
有没有这个词
适合:
- 产品型号
- 人名
- 代码符号
- 专有名词
- 必须精确匹配的关键词
缺点是:不理解语义。
例如“番茄”和“西红柿”可能被当成不同词。
密集向量
密集向量关注的是:
意思像不像
同一个 embedding 模型会把文本映射到同一个向量空间里,语义接近的文本距离更近。
例如:
西红柿炒蛋
番茄炒鸡蛋
家常鸡蛋菜
在语义空间中应该更接近。
缺点是:可能忽略精确关键词,也不太可解释。
为什么要混合
单独使用一种检索方式都有短板:
稀疏检索:精确但不懂语义
密集检索:懂语义但可能漏关键词
混合检索就是:
既看词对不对,也看意思像不像
RRF
RRF 是 Reciprocal Rank Fusion,倒数排序融合。
它不直接比较不同检索器的原始分数,而是比较排名:
一个文档如果在多个检索结果中都排得靠前,它就更可能重要。
RRF 适合融合不同来源的检索结果,因为不同检索器的分数往往不可直接比较。
2. 查询构建
查询构建的核心是:
把用户自然语言问题变成某种结构化查询。
它让 RAG 不只是做语义相似度搜索,还能使用结构化条件。
文本到元数据过滤器
示例:
用户问:时长大于600秒的视频
系统可以把它转换成:
语义查询:视频
元数据过滤:length > 600
然后向量数据库执行:
语义检索 + metadata filter
这就是 SelfQueryRetriever 的作用。
它会让 LLM 根据字段说明,把自然语言拆成:
query string
metadata filter
limit
局限
它对过滤类问题效果比较好,比如:
时长大于600秒的视频
观看次数超过10000的视频
但对排序类问题不一定好,比如:
时间最短的视频
播放量最高的视频
因为这类问题需要:
排序字段 + 排序方向 + 取 top1
普通 metadata filter 不一定能表达完整排序逻辑。
这也是后面查询重构要解决的问题。
文本到 Cypher
Cypher 是图数据库查询语言,类似 SQL 之于关系型数据库。
文本到 Cypher 的思路是:
自然语言问题
-> LLM 根据图谱 Schema 生成 Cypher
-> 图数据库执行查询
-> 返回结果
它和 Text2SQL 的本质一样:都是把自然语言转成结构化查询语言。
3. Text2SQL
用户用自然语言提问
系统生成 SQL
数据库执行 SQL
返回结构化结果
为什么 Text2SQL 需要 RAG
LLM 本身不知道你的数据库结构。
如果直接让它写 SQL,容易出现:
- 幻觉出不存在的表
- 幻觉出不存在的字段
- JOIN 关系写错
- 条件字段用错
- SQL 能执行但语义不对
所以需要给它“开卷资料”。
Milvus 在 Text2SQL 中存什么
这里 Milvus 不是存业务数据,而是存 Text2SQL 的知识库:
DDL 表结构
Q-SQL 示例
表和字段描述
这些不是训练数据,而是运行时检索用的参考资料。
可以理解成:
训练数据:用于改变模型参数
RAG 知识库:用于运行时检索,增强 prompt
在 Text2SQL 里,Milvus 存的是“数据库说明书”和“SQL 参考例题”。
4. 查询重构与分发
查询重构的目标是:
把用户原始问题变成更适合检索或推理的形式。
用户的问题往往不是最好的检索输入。
它可能:
- 太口语
- 太复杂
- 有多个意图
- 缺少关键词
- 和文档表达不一致
- 需要排序、聚合或路由
查询翻译
查询翻译就是把问题改写成更适合系统处理的形式。
例如把:
时间最短的视频
改成结构化指令:
{"sort_by": "length", "order": "asc"}
这比普通自然语言更适合程序执行。
Multi-query
Multi-query 是把一个复杂问题拆成多个子问题。
例如:
刘慈欣在《流浪地球》中如何看待人工智能和未来社会结构?
可以拆成:
《流浪地球》中的人工智能有哪些?
《流浪地球》中的未来社会结构是什么?
刘慈欣对人工智能的观点是什么?
然后分别检索,再合并结果。
Step-Back Prompting
Step-Back 是“退一步问更抽象的问题”。
例如具体问题需要一个物理定律,系统先问:
这个问题背后的通用原理是什么?
再用通用原理回答原问题。
适合需要推理的场景。
HyDE
HyDE 是 Hypothetical Document Embeddings。
它的思路是:
先让 LLM 生成一篇假设性答案文档
-> 把这篇假设文档向量化
-> 用它去检索真实文档
它把:
query-to-document
变成:
document-to-document
适合用户问题很短、关键词不足的场景。
查询路由
查询路由的目标是:
判断这个问题应该交给哪个数据源、检索器、工具或专家链。
比如:
订单问题 -> SQL 数据库
公司关系问题 -> 图数据库
文档问答 -> 向量知识库
川菜问题 -> 川菜专家 prompt
粤菜问题 -> 粤菜专家 prompt
5. 两种路由方式
LLM 路由
LLM 路由是让大模型直接判断分类。
流程:
用户问题
-> LLM 分类
-> RunnableBranch 选择不同 chain
-> 对应专家链回答
优点:
- 灵活
- 能理解复杂意图
- 适合分类边界不清晰的场景
缺点:
- 有 API 成本
- 有延迟
- 分类可能不稳定
Embedding 路由
Embedding 路由不让 LLM 分类,而是用向量相似度。
流程:
先写几段路由描述
-> 把路由描述转成向量
-> 用户问题也转成向量
-> 谁相似度最高,就走谁的 chain
优点:
- 快
- 成本低
- 适合固定路由集合
缺点:
- 依赖路由描述写得好不好
- 不如 LLM 灵活
- 路由集合复杂时容易误判
可以这样记:
LLM 路由:像人工分诊
Embedding 路由:像语义最近邻匹配
6. 检索进阶:重排、压缩、校正
基础检索拿到的结果不一定适合直接喂给 LLM。
常见问题:
- 最相关内容不一定排在最前
- 文档块太长
- 文档里有很多噪声
- 多个 chunk 内容重复
- 检索结果可能不相关
- 检索结果可能过时或错误
所以需要后处理。
重排
重排是:
先粗召回一批文档
-> 再用更精细的方法重新排序
常见方法:
- RRF
- RankLLM
- Cross-Encoder
- ColBERT
RRF
RRF 用多个检索器的排名融合结果。
适合多路召回结果合并。
RankLLM
RankLLM 让 LLM 判断哪些文档更相关。
优点是语义理解强,缺点是贵、慢。
Cross-Encoder
Cross-Encoder 把:
query + document
拼在一起送进模型,直接输出相关性分数。
优点是精度高,缺点是每个候选文档都要单独跑一次,比较慢。
ColBERT
ColBERT 是折中方案。
它分别编码 query 和 document,然后在 token 级别做 MaxSim 匹配。
可以理解成:
不只看整句话像不像,也看每个关键 token 能不能在文档里找到强匹配。
压缩
压缩是:
把检索到的长文档变短,只保留和问题相关的部分。
常见方式:
- 抽取相关句子
- 丢弃不相关文档
- 让 LLM 提取重点片段
在代码中:
基础检索 Top-K
-> ColBERT 风格重排
-> LLMChainExtractor 压缩
-> 返回更聚焦的上下文
你运行后能看到,基础检索结果比较泛,但压缩后明显聚焦到:
AI 生成内容不准确
表达流畅但可能严重错误
内部模式僵化
需要改进推理策略
这说明后处理确实能让上下文更干净。
重复问题
压缩后的结果可能有重复。
原因通常是:
原始分块有 overlap
基础检索召回了相似 chunk
LLM 压缩时提取了相近句子
解决方向:
- 减小 chunk overlap
- 改分块策略
- 对检索结果去重
- 对压缩结果去重
校正检索 C-RAG
C-RAG 是 Corrective RAG。
核心思想:
不要盲目信任检索结果。
先评估检索结果是否真的能回答问题。
流程:
Retrieve 检索
-> Assess 评估
-> Act 行动
行动可能是:
- 检索结果正确:精炼后生成
- 检索结果错误:改写查询或外部搜索
- 检索结果模糊:补充检索
总结
RAG 的关键不只是“检索”,而是“怎么把用户问题变成适合检索的问题”。
基础 RAG 可能只是:
用户问题 -> 向量检索 -> LLM 回答
高级一点的 RAG 会变成:
用户问题
-> 判断意图
-> 改写 / 拆分 / 结构化 / 路由
-> 选择合适检索方式
-> 检索后重排 / 压缩 / 校正
-> 再生成答案
所以本章可以理解为:
Query-time RAG Optimization
也就是查询时优化。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)