本文以一个虚构的企业技术知识助手为例,串联 16 项 RAG 相关技术。文中的上线情境、用户反馈、故障调查、检索排名和示例数据均为教学模拟,不代表实际部署或评测结果。
一、总论
最近因为公司需要搭建一个 AI 知识库,我开始系统地学习 RAG 技术。
刚开始觉得应该不难,毕竟现在有很多成熟的框架和工具,搭建一个能根据文档回答问题的系统,似乎并不复杂。
但随着研究深入,发现 RAG 远不止简单的文档检索。
光是相关技术,就有 Naive RAG、Multi-Query、HyDE、Hybrid Search、Reranking、GraphRAG、Agentic RAG 等十几种。
刚开始看这些技术时,最大的困惑不是某一种技术有多难,而是不知道它们之间到底是什么关系。
有些看起来功能差不多,有些可以组合使用,有些又像是对整个 RAG 架构的升级。
于是我开始换一种学习思路:
不再按照技术名称逐个记忆,而是先弄清楚每种技术究竟解决了什么问题。
沿着这个思路,我把 16 种常见的 RAG 相关技术梳理了一遍,发现它们大致可以归为以下几个方向。
| 解决的问题 | 涉及的 RAG 技术 |
|---|---|
| 基础知识检索 | Naive RAG |
| 提高检索覆盖率 | Multi-Query、HyDE、Hybrid Search |
| 优化检索结果排序 | Reranking |
| 解决上下文不完整 | Semantic Chunking、Parent-Child |
| 改善检索和回答质量 | CRAG、Self-RAG |
| 根据问题选择检索策略 | Adaptive RAG |
| 处理复杂知识关系 | GraphRAG |
| 结合数据库查询 | Text-to-SQL + RAG |
| 动态规划与多步检索 | Agentic RAG |
| 多智能体分工协作 | Multi-Agent RAG |
| 检索图片、图表等内容 | Multimodal RAG |
| 优化生成效率 | Speculative RAG |
整理后逐渐发现,这些技术并不是从低级到高级的升级路线,而是围绕不同问题形成的一套解决方案。
有些是对基础 RAG 某个环节的增强,例如 Hybrid Search 和 Reranking;有些则改变了整个系统的运行方式,例如 Agentic RAG。
而且,并不是技术用得越多,系统效果就越好。
这次整理也让我意识到,真正需要掌握的不只是技术原理,更重要的是能够判断:什么时候需要它,为什么需要它,以及它是否真的解决了问题。
配图 01:16 种 RAG 技术的问题分类与相互关系全景图(矢量示意图)
本文如何展开?
为了把这些技术真正串联起来,我选择了一个贯穿全文的例子:
假设我们要开发一个企业技术知识助手,让员工能够直接向 AI 提问,获取公司技术文档中的知识。
从最基础的 RAG 开始,随着需求增加和问题出现,逐步研究不同的解决方案。
例如,最初只是希望 AI 能够使用企业内部知识;接着可能发现相关文档检索不到、检索结果排序不合理、返回的内容缺少上下文。
当这些问题逐步解决后,还可能遇到资料不足、复杂问题需要多次检索、跨文档关系分析等新的挑战。
每遇到一个问题,都按照同样的思路展开:
发现问题 → 分析原因 → 寻找解决方案 → 理解技术原理 → 比较改造效果与代价。
这样既能理解单项技术,也能看到不同技术之间如何互补,以及什么时候才有必要升级架构。
需要说明的是,这 16 项并不全是独立的 RAG 架构,其中也包含检索、分块、数据库查询和生成优化等技术。
本文的重点不是对它们进行严格排名,而是通过一个不断演进的案例,理解它们各自的价值与适用边界。
接下来,就从最基础的问题开始:RAG 到底是什么,为什么我们需要它?
二、RAG 到底是什么?为什么需要它?
1. 从一个实际需求开始
假设一家公司的技术团队准备搭建知识库。
随着项目越来越多,团队积累了不少技术资料,比如开发规范、系统架构设计、接口文档、数据库设计、部署手册,以及历史问题的解决记录。
这些资料虽然都保存着,但真正需要使用时,往往并不方便。
例如,新同事想了解某个系统的架构,需要先找到对应文档;开发人员遇到 Redis 问题,可能要翻阅之前的故障记录;有些问题文档里没有写清楚,还得找熟悉项目的同事询问。
时间久了,知识虽然积累了不少,但查找和使用的成本仍然很高。
于是我们希望做一个更方便的知识库:
团队成员不需要自己翻阅大量文档,只要直接提问,系统就能根据已有技术资料给出答案,并告诉我们答案来自哪里。
例如:
我们的订单系统依赖哪些服务?Redis 故障时应该怎么处理?
现在有了大模型,一个很自然的想法就是:能不能让 AI 帮我们完成这件事?
研究了一下,发现 RAG 正是实现这类知识问答系统的一种常见方案。
那么,RAG 到底是什么?
2. RAG 是什么?
RAG 的全称是 Retrieval-Augmented Generation,中文叫检索增强生成。
名字听起来有点复杂,其实可以简单理解为:
先从知识库中查找相关资料,再让大模型根据这些资料回答问题。
我们可以把它想象成一个熟悉公司技术文档的助手。
当有人提问时,它不会只依靠自己记住的知识回答,而是先去翻阅相关文档,找到有用的内容,再整理成答案。
例如用户问:
我们公司 Redis 是怎么部署的?
普通大模型虽然了解 Redis 的各种部署方式,但不知道公司实际采用哪一种。
而 RAG 系统会先从内部知识库中找到 Redis 部署说明。
假设文档写着:
订单系统使用 Redis 一主两从架构,并部署三个 Sentinel 节点。
系统把这段资料交给大模型,大模型就可以根据文档回答,而不是猜测公司的实际配置。
这就是 RAG 最基本的工作方式。
3. RAG 是如何工作的?
RAG 主要包含三个步骤。
第一步:检索(Retrieval)。
用户提出问题后,系统先从知识库中查找相关资料。
第二步:增强(Augmented)。
将检索到的资料连同用户问题一起提供给大模型,让模型获得回答所需的外部知识。
第三步:生成(Generation)。
大模型根据问题和检索资料,组织语言并生成答案。
整个过程可以概括为:
用户提问 → 检索知识库 → 将相关资料交给大模型 → 生成答案。
4. 资料这么多,RAG 怎么找到相关内容?
理解了基本流程,我们又会产生一个疑问:
公司有几百甚至几千份技术文档,系统怎么知道应该找哪一份?
这就涉及 RAG 中常见的几个基础概念:Chunk、Embedding 和向量检索。
先简单理解:
- Chunk(知识片段):把长文档拆成较小的内容,方便定位。
- Embedding(向量化):利用模型把文字转换成一组能够表达语义特征的数字。
- 向量检索:根据用户问题与知识片段的向量相似度,找到可能相关的内容。
例如用户问:
Redis 热点数据过期,为什么数据库压力会突然变大?
知识库中有一段内容:
Redis 缓存击穿通常发生在热点 Key 失效后,大量并发请求直接访问数据库。
虽然两段文字并不完全相同,但讨论的是相近的问题。
向量检索就有机会把这段资料找出来。
不过要注意,向量相似并不代表内容一定正确,也不代表事实完全一致。
这也是后续需要不断优化 RAG 的原因之一。
5. 我们先有了最基础的 RAG
到这里,一个简单的技术知识助手已经具备了基本工作能力:
用户提出问题,系统检索相关技术文档,大模型参考这些资料生成答案。
这种最基础的方式,通常称为 Naive RAG(朴素 RAG)。
它解决了我们最开始的问题:
让 AI 能够利用技术团队已有的知识,而不是只能依赖大模型自身的通用知识。
看起来,我们已经可以开始使用了。
在这个模拟场景中,随着提问增多,可能出现新的问题:
“这个问题我们之前明明写过文档,为什么 AI 就是找不到?”
这就引出了下一章:知识库明明有资料,为什么 AI 找不到?
三、第一次模拟反馈:明明有文档,为什么搜不到?——Multi-Query RAG
假设技术知识助手进入试用阶段,团队成员提出一个问题:“Redis 数据突然没了怎么办?”AI 却只找到了《Redis 数据类型》和《DEL 命令说明》,没有找到知识库已有的《Key 过期机制》和《内存淘汰策略》。
先看看问题出在哪里
为了让读者看清楚,我们假设检索结果如下(全文所有检索排名均为教学模拟,并非真实测试):
| 用户原话 | 首轮候选 | 实际需要的资料 |
|---|---|---|
| Redis 数据突然没了怎么办? | 数据类型、删除命令 | Key 过期、内存淘汰、持久化恢复 |
为什么明明使用了 Embedding,还是会漏掉?因为“数据没了”可能有很多含义。Embedding 能找语义相关内容,但一次问题表达不一定能覆盖所有相关原因。直接改成“Redis Key 过期”可能找到第一份资料,却又可能漏掉持久化恢复。
最简单的办法是人工给用户推荐关键词,但用户的问法千变万化,维护所有同义表达并不现实。
让模型帮我们生成多个检索问题
这就是 Multi-Query RAG 的切入点:不是让模型直接回答,而是让它先帮检索系统想几种问法。
步骤 1,输入用户原话:
Redis 数据突然没了怎么办?
步骤 2,生成查询:
{
"queries": [
"Redis Key 为什么会自动过期",
"Redis 内存淘汰策略在什么条件下触发",
"Redis 重启后持久化数据如何恢复"
]
}
这里的 queries 是一个查询数组,每一项都用于一次独立检索,不代表已经确认用户遇到的是哪一种故障。
步骤 3,分别检索:第一条命中《Key 过期机制》,第二条命中《内存淘汰策略》,第三条命中《持久化恢复》。系统将这些结果与原始查询的结果合并、去重。
步骤 4,输出候选资料:原来漏掉的三份文档进入候选列表,后续再判断哪些最适合回答。
这次改造没有改变知识库,也没有更换大模型,只是在检索前增加查询改写。收益是扩大覆盖;代价是多次检索和额外模型调用。更大的风险是查询漂移:如果模型误把“数据没了”理解成“数据被黑客删除”,反而会引入无关资料。
因此不能用“检索结果从 3 篇增加到 20 篇”证明成功。应该准备一批有标准相关文档的问题,比较 Recall@K 和噪声数量。
解决之后又遇到了什么?
多查询可能改善模糊问题的检索。再看一个模拟问题:用户只问“Redis 为什么卡”,知识库里却是一份很长的专业性能报告。换几个简短问法仍然不理想。这次需要改变的不只是问法数量,而是查询本身的表达形式。
四、第二次模拟反馈:问题太短,怎么匹配专业长文档?——HyDE
“Redis 为什么卡?”只有几个字。可我们的《Redis 性能分析报告》包含慢命令、事件循环阻塞、网络抖动、客户端连接池等几十页内容。问题与目标文档的表达差异太大。
为什么继续加 Multi-Query 不一定有效?
Multi-Query 可以生成“Redis 延迟高的原因”“Redis 响应慢怎么排查”,但这些仍然是短查询。我们真正想找到的是一段像专业报告那样描述故障现象的内容。
HyDE 的全称是 Hypothetical Document Embeddings,可以理解成“先生成一份假设文档,再用它检索真实文档”。
按步骤走一遍
输入:
用户:Redis 为什么卡?
第一步,生成假设性段落:
Redis 响应延迟可能涉及慢命令、阻塞操作、网络延迟或资源竞争。排查时通常结合命令耗时、客户端连接状态和系统指标进行分析。
第二步,将这段假设文档向量化。注意:这里用于向量检索的是假设文档,不是把假设当成最终答案。
第三步,搜索真实知识库。系统可能命中《Redis 性能分析报告》中“慢命令与连接等待”章节。
第四步,返回真实资料并回答。最终模型应根据真实报告判断,不得把刚才编写的假设内容引用为事实。
为什么可能有效?因为假设段落在术语、篇幅和语言风格上,比“Redis 为什么卡”更接近目标报告。
但它也可能失败:如果模型一开始就假设“Redis 卡是因为网络”,可能遗漏真正与大 Key 或阻塞命令有关的资料。HyDE 的假设是检索桥梁,不是故障诊断结果。
它的成本是多一次生成与向量化;只有在短查询匹配长篇专业文档的测试中确实提升召回,才值得使用。
下一条反馈:版本号为什么会错?
即使自然语言问题更容易找到相关报告,也可能出现另一种情况:用户明确要求“Spring Boot 3.2 Sentinel 配置”,系统却把 Spring Boot 2 的文档排在前面。这不是问法太少,也不是文档太长,而是精确术语与语义相关性之间的矛盾。
五、第三次模拟反馈:版本明明写清楚了,为什么找错?——Hybrid Search
“Spring Boot 3.2 的 Redis Sentinel 怎么配置?”这句话有两个要求:主题是 Sentinel 配置,版本必须符合 3.2。
向量检索可能认为 Spring Boot 2 与 3.2 的配置文档非常相近,因为它们都包含 Redis、Sentinel、连接池等词。可是对开发人员来说,版本差异可能决定配置是否能运行。
先区分两种搜索能力
关键词搜索关注字面表达。BM25 是常见的关键词相关性算法,擅长精确术语、错误码、类名和版本号。
向量搜索关注模型学习到的语义相关性。它能找“热点 Key 失效”和“缓存击穿”这样的不同表达,但对版本、否定、数量等硬条件未必可靠。
既然各有长处,为什么不一起用?
Hybrid Search 的实际过程
输入:
Spring Boot 3.2 Redis Sentinel 配置
第一路:BM25 检索,找到包含“Spring Boot 3.2”“Sentinel”等明确术语的文档。
第二路:Embedding 检索,找到语义相关的 Redis 客户端配置说明。
融合结果:用 RRF 等排名融合方法综合两路候选,而不是简单地把两个分数相加。因为两种检索的分数范围和含义可能不同。
例如模拟结果:
| 文档 | 关键词检索 | 向量检索 | 融合后 |
|---|---|---|---|
| Spring Boot 3.2 Sentinel 指南 | 排名 1 | 排名 3 | 靠前 |
| Spring Boot 2 Sentinel 指南 | 排名 3 | 排名 1 | 仍可能靠前 |
| Redis Sentinel 原理 | 排名 5 | 排名 2 | 作为背景 |
这里必须强调:混合检索不能自动保证版本条件正确。如果版本 3.2 是硬性要求,还应在检索前或检索后用明确的版本字段过滤。
配图 03:Multi-Query 改写多个问法,HyDE 用假设文档检索,Hybrid Search 融合关键词与语义。
到这里我们学到三种“找得更全”的方法,但它们并不是必须同时启用。先确认问题出在问法覆盖、查询表达还是精确术语,再选择方案。
现在正确文档能找到了,为什么还答不好?
假设用户问“Redis 缓存击穿的 Java 实现”,系统找到了那份代码文档,却排在第三名。前两名只有原理和缓存雪崩代码。这次问题已经从“召回不到”变成“候选排序不对”。
六、第四次模拟反馈:正确文档排在第三名,怎么办?——Reranking
假设用户的问题是:
Redis 缓存击穿怎么解决?给我 Java 互斥锁代码。
第一轮结果如下:
| 排名 | 文档 | 是否满足要求 |
|---|---|---|
| 1 | Redis 缓存击穿原理 | 没有 Java 代码 |
| 2 | Redis 缓存雪崩 Java 示例 | 有代码,但问题不同 |
| 3 | Redis 缓存击穿 Java 互斥锁实现 | 同时满足两个要求 |
| 4 | Redis 缓存穿透解决方案 | 主题不符 |
如果系统只取前两篇给大模型,最终答案自然可能缺少代码。
为什么向量检索排不准?
很多向量检索方法会分别将问题与文档压缩成向量,再比较相似度。它擅长快速从大量文档中找到候选,但用户的“缓存击穿 + Java 互斥锁代码”是多个条件共同成立的问题,一个整体相似度不一定能把它判断得很细。
再增加一道精细筛选
Reranking(重排序)的思路是:先快速召回,再精细判断。
输入:完整问题和第一轮检索的例如 20 篇候选。
处理:常见 Cross-Encoder Reranker 把问题与每篇候选一起输入模型,判断它们之间的相关性。与独立向量比较相比,这种联合阅读更有机会识别“击穿”和“Java 代码”是否同时满足。
输出:重新排序后的候选列表。理想的模拟结果是把“缓存击穿 Java 互斥锁实现”从第三名移到第一名。
配图 04:候选文档没有增加,只是改变了排序。
为什么不直接让 Reranker 逐篇检查知识库里的十万篇文档?因为联合评分通常比快速向量召回耗费更多计算。所以常见流程是“快速检索 Top-K → 精排 → 选少量证据”。
这项技术有什么边界?
第一轮根本没找到的资料,Reranker 无法补回来。 它解决的是候选顺序,不是召回缺失。
是否值得增加重排序,要用人工标注的测试问题比较 MRR、NDCG@K、最终答案质量,以及增加的延迟和成本。
即使排序更合理,也可能出现这样的模拟反馈:“互斥锁的代码找到了,注意事项却只返回一句话。”假设对照原文后发现,资料被拆成了多个片段。
七、第五次模拟反馈:为什么找到的片段总是不完整?——Semantic Chunking
知识助手为了方便检索,会把长文档切成小段,也就是 Chunk。这个设计在第二章已经介绍过。
问题是:切得太随意,会把本来完整的知识拆开。
假设《Redis 缓存击穿方案》原文包含:
| 原文顺序 | 内容 |
|---|---|
| A | 缓存击穿为什么发生 |
| B | 为什么选择互斥锁 |
| C | Java 互斥锁代码 |
| D | 锁超时、异常释放、双重检查 |
| E | 下一个主题:缓存雪崩 |
如果机械地每 500 Token 切一次,可能把 B、C、D 分到不同 Chunk。用户命中 B 时,模型只拿到“使用互斥锁”的一句说明,看不到代码和注意事项。
我们先尝试调整固定分块大小
把 500 改成 1000 Token,确实可能减少截断,但新的问题是:较大的块可能混入其他主题,影响检索精度。设置重叠区也只能缓解边界截断,不能保证知识点完整。
因此,我们希望系统识别主题在哪里发生变化。
Semantic Chunking 的思路
Semantic Chunking(语义分块)通常先按句段划分,再比较相邻内容的语义关联程度,在主题变化明显的位置寻找切分边界。
输入:完整的 Redis 缓存章节。
处理:判断“互斥锁原理”“代码示例”“注意事项”属于相近主题,而“缓存雪崩”开始了另一个主题;在合理的长度约束下组织 Chunk。
输出:主题相对完整的片段,例如“缓存击穿:原因与解决方案”和“缓存雪崩:原因与解决方案”。
这里说的是期望的示意结果,不是保证算法一定会如此切分。实际分块效果受模型、阈值、文档格式和长度限制影响。
语义分块是不是最好的分块方式?
不一定。技术手册往往已经有清晰的标题、代码块和章节结构,直接按照这些结构切分可能更可靠。语义相近也不代表业务上必须放在一起。
所以这项技术的意义不是“取代所有固定分块”,而是当机械分块明显破坏主题完整性时,提供一种更合理的边界选择方式。
即使切分边界更合理,仍有一个两难:小块容易精确检索,大块包含完整上下文。能不能让这两件事分别处理?
八、第六次模拟反馈:小块好找,大块好读,能兼得吗?——Parent-Child
用户问:“互斥锁方案有哪些实现注意事项?”
系统命中了“锁超时处理”这个短片段,但完整代码和异常释放说明还在同一章节的其他位置。
我们可以继续增大 Chunk,但如果块太大,检索又容易变得模糊。
改变思路:检索单位和阅读单位不必一样
Parent-Child Retrieval(父子块检索)把一个较大的章节当作父块,把其中的短段落当作子块。
例如:
父块:Redis 缓存击穿完整章节
├─ 子块 A:发生原因
├─ 子块 B:互斥锁原理
├─ 子块 C:Java 代码
└─ 子块 D:超时和异常处理
每个子块保存 parent_id。这个字段表示它属于哪个父块,类似数据库中的关联编号。
输入:用户问“互斥锁异常释放怎么处理?”
第一步:检索短子块,命中“子块 D:超时和异常处理”。
第二步:根据 parent_id 回查所属父块。
第三步:将包含相关代码和说明的父块内容交给大模型;如果多个子块命中同一父块,要去重。
输出:模型可以同时看到原理、代码和注意事项,而不只是孤立的一句话。
配图 05:Semantic Chunking 改进切分边界;Parent-Child 让小块负责检索、大块负责返回。
为什么不每次都返回整本手册?
因为父块过大也会增加无关信息和 Token 消耗,甚至使模型更难定位关键句。父块通常应是合理的段落组或章节,而不是无限扩展到整篇文档。
这两个方法可以互补:Semantic Chunking 解决“怎么切”,Parent-Child 解决“命中之后返回多大范围”。但它们也都不能解决下一个问题:如果检索到的资料本身不够可靠,模型仍然可能答错。
九、第七次模拟反馈:资料看起来相关,却不够回答,怎么办?——CRAG
在这个模拟场景中,用户反馈:“我问 Spring Boot 3 的 Sentinel 配置,AI 给出的依据却是 Spring Boot 2 的说明,而且语气很肯定。”
假设检查后发现,系统完成了召回与 Reranking,Parent-Child 也返回了完整章节,但候选资料都是旧版本。
为什么已有技术解决不了?
Reranking 可以比较候选之间谁更相关,却无法让旧文档自动变成新文档。Parent-Child 能补充上下文,但补充的仍然是旧版本的上下文。
这次的问题是:系统需要先判断这批证据能不能用,而不是找到就回答。
CRAG 在检索后增加一道质量关
CRAG(Corrective RAG,纠错式 RAG)在检索和生成之间增加质量评估与补救机制。
输入:
问题:Spring Boot 3 的 Redis Sentinel 如何配置?
候选 A:Spring Boot 2 Sentinel 配置
候选 B:Redis Sentinel 原理
候选 C:旧项目连接池说明
第一步,评估检索质量。判断候选是否能回答用户指定的版本与配置要求,而不只是主题相似。
第二步,选择处理路径:
| 判断 | 下一步 |
|---|---|
| 证据充分 | 提炼相关内容并回答 |
| 部分相关 | 保留有效片段,补充检索 |
| 明显不适用 | 调整查询,尝试其他获准来源 |
第三步,重新获取证据。例如检索 Spring Boot 3 对应的客户端配置文档,必要时检查版本差异。
第四步,生成答案。若仍缺少足够证据,应该说明无法确认,而不是拼凑出一份确定配置。
输出:更符合版本要求的证据集合,或者明确的证据不足说明。
配图 06:检索结果不合格时,不直接进入生成,而是补检或调整来源。
这样是不是就不会答错了?
当然不是。评估器也可能误判;补检可能引入不可靠资料;多次检索还会增加成本。因此需要限制检索轮数、来源范围和停止条件。
CRAG 与 Reranking 的分工也不同:前者处理检索质量不足时如何补救,后者处理已有候选如何排序。
即使检索阶段有所改善,仍可能出现一个更隐蔽的问题:资料没问题,模型自己把结论说过头了。
十、第八次模拟反馈:有证据也可能乱下结论,怎么办?——Self-RAG
用户问:“Redis Sentinel 故障切换之后,订单系统是不是绝对不会丢数据?”
文档只解释了 Sentinel 如何监控节点、协调故障转移,AI 却回答:“一定不会丢数据。”
这句话并不是检索资料明确支持的事实。检索相关,不代表生成内容就有依据。
我们需要检查什么?
至少要区分四件事:
- 这个问题是否需要检索外部资料?
- 检索到的资料是否与问题相关?
- 生成的每个关键结论是否被资料支持?
- 回答是否真正解决了用户问题?
Self-RAG(自我反思式 RAG)就是围绕这些判断设计的。
Self-RAG 并不是让模型“再想一遍”
原始 Self-RAG 研究通过专门训练,让模型学习使用 Reflection Tokens(反思标记)来表达检索需求、资料相关性、证据支持程度和答案有用性,并利用这些信息指导生成。
用我们的案例来理解:
输入:
问题:Sentinel 故障切换是否绝对不会丢数据?
资料:Sentinel 能协调故障转移,Redis 复制存在异步过程。
候选答案:故障切换后一定不会丢数据。
处理一,检查检索必要性:涉及具体系统可靠性,不能只凭模型记忆下结论。
处理二,检查资料相关性:Sentinel 和复制机制的资料相关,但“能故障转移”不等于“零丢失”。
处理三,检查答案支持度:候选答案中的“一定不会丢数据”缺乏支持,甚至与异步复制风险相冲突。
输出(示意):“Sentinel 可以协调故障转移,但异步复制和故障窗口仍可能存在数据丢失风险;是否满足业务要求需要结合具体配置验证。”
配图 07:检索决策、相关性、答案支持度与有用性是不同的判断。
为什么说它更复杂?
因为原始 Self-RAG 需要专门训练模型,不是简单加一句“请检查答案”就能完整实现。普通工程项目可以用现成 LLM 构建“生成→证据检查→修正”的类似工作流,但不能直接等同于论文原始方法。
而且,模型自评仍可能错。关键结论需要独立测试或人工核验。
CRAG 侧重检索质量的判断与补救,Self-RAG 进一步关注生成过程中如何自我评估。
接下来再考虑一种情况:系统增加多道检查后,即使回答简单概念也要执行复杂检索,可能增加等待时间。
十一、第九次模拟反馈:简单问题也要检索半天,怎么办?——Adaptive RAG
假设一位用户问:“Redis 是什么?”系统先检索,再重排,再检查证据,等了很久才给出一个通用定义。
另一个模拟问题是:“如何设计 Redis 高可用并评估故障风险?”系统却只查一次,就给出一个不完整的方案。
两种问题都走同一条固定流程,显然不合理。
Adaptive RAG 的核心是先选路径
Adaptive RAG(自适应 RAG)根据问题的复杂度或检索需求,选择不同的处理方式。
我们可以设计三条教学示例路径:
| 问题 | 处理路径 | 原因 |
|---|---|---|
| Redis 是什么? | 直接回答 | 通用、稳定的概念 |
| Spring Boot 3 Sentinel 如何配置? | 单次检索 | 需要明确版本资料 |
| Redis 高可用有哪些故障风险? | 多步检索 | 涉及切换、复制、客户端恢复等多个子问题 |
输入:用户原始问题。
处理:先由分类器判断检索需求,输出 no_retrieval、single_retrieval 或 multi_step,再执行对应流程。
输出:简单问题减少不必要的检索,复杂问题获得更充分的检索过程。
配图 08:根据问题选择不同检索路径,而不是所有问题都执行同样步骤。
为什么不能只看问题长短?
“公司现在 Redis 的主节点是谁?”只有十几个字,却必须查询最新的内部状态。相反,一段很长的文字也可能只是让模型解释通用概念。
因此路由不应简单等同于字数判断,还要考虑是否涉及最新信息、企业内部事实以及多跳推理。
原始 Adaptive-RAG 研究使用训练过的复杂度分类器;用规则或现成 LLM 路由是工程借鉴。路由错误可能跳过必要检索,所以要用真实问题评测路由准确率、答案质量和成本。
Adaptive RAG 是选择不同路径,不代表系统已经能自主决定每一步使用什么工具。 接下来,团队开始提出需要跨文档关联的复杂问题。
十二、第十次模拟反馈:三份文档都找到了,为什么关系串不起来?——GraphRAG
用户问:“Redis 故障为什么会影响订单服务?”
假设手动查阅后得到以下资料:
| 文档 | 记录的事实 |
|---|---|
| 订单系统架构 | 订单服务依赖库存服务 |
| 库存系统设计 | 库存服务使用 Redis 缓存 |
| 历史故障报告 | Redis 超时导致库存接口变慢 |
单独检索任何一份文档都可能只得到部分答案。真正的解释需要把三个事实连接起来。
GraphRAG 为什么有价值?
传统文本检索主要寻找“与问题相关的段落”。但这个问题需要的是实体之间的关系路径。
GraphRAG 的一类实现会抽取实体(例如订单服务、库存服务、Redis)和关系(依赖、使用、影响),建立可检索的知识图谱。
第一步,抽取实体:从三份文档识别服务名称。
第二步,抽取关系:
订单服务 --依赖--> 库存服务
库存服务 --使用--> Redis
Redis 超时 --影响--> 库存服务响应
第三步,沿图查找路径:从 Redis 出发,经过库存服务,找到可能影响订单服务的链路。
第四步,回查原文:每条关键关系都应有对应文档作为证据,不能把模型推测的关系直接当事实。
输出:Redis 故障可能通过库存服务影响订单业务,并展示支持该分析的文档。
配图 09:将散落在多份文档中的实体关系连接起来。
它是不是必须用图数据库?
不一定。GraphRAG 是一种利用图结构组织和检索知识的思路,图可以有不同存储方式。Microsoft GraphRAG 还使用社区划分与摘要,支持“过去一年故障主要集中在哪些领域”这样的整体性问题。
但图谱建设也有代价:实体消歧、关系抽取错误、版本变化、更新维护和摘要成本。如果服务依赖关系本来就完整保存在数据库中,直接 SQL 查询可能更准确、更简单。
GraphRAG 能帮我们理解关系,却不意味着它能自动完成动态故障调查。用户接着问:“昨晚订单为什么变慢?能不能自己去查日志和监控?”
十三、第十一次模拟反馈:一次检索不够,能不能根据结果继续查?——Agentic RAG
“昨晚订单系统变慢,是 Redis、MySQL 还是应用程序的问题?”
这已经不是查一份文档的任务。我们可能需要先查监控,再根据监控结果查日志,最后结合历史故障记录判断。
固定流程为什么不够?
如果我们预先写死“查 Redis→查 MySQL→查应用日志”,不论监控显示什么都走一遍,会浪费资源。更重要的是,实际排查的下一步往往取决于前一步的发现。
Agentic RAG 的核心是让 Agent 在授权范围内动态选择检索工具,并根据返回结果决定下一步。
模拟一次完整调查
| 轮次 | 已有信息 | 采取的行动 | 得到的结果(模拟) |
|---|---|---|---|
| 1 | 用户说订单变慢 | 查询订单接口监控 | P95 延迟上升 |
| 2 | 需要定位依赖 | 查询调用链 | Redis 调用等待明显增加 |
| 3 | 怀疑 Redis 相关 | 查询 Redis 指标和日志 | 连接池等待异常 |
| 4 | 需要判断是否为已知故障 | 检索历史故障记录 | 找到相似案例 |
| 5 | 证据仍不够确认唯一根因 | 生成有条件的分析 | 建议进一步核查连接池配置 |
这里的 P95 指 95% 请求的耗时不超过的数值,常用于观察接口慢请求情况。
输入:用户的开放式故障问题。
处理:Agent 选择工具→调用工具→读取结果→判断证据是否充分→必要时继续查询。
输出:带来源、明确不确定性的调查结果,而不是武断认定根因。
配图 10:每一步的结果会影响下一步工具选择。
它和 Adaptive RAG 有什么不同?
Adaptive RAG 通常在预先定义的几条处理路径中选择;Agentic RAG 更强调执行过程中根据中间结果动态规划工具调用。
代价也明显:可能重复查询、选择错误工具、产生高额费用,甚至出现越权操作。因此需要工具白名单、最大轮次、超时、调用日志和关键操作审批。
还要区分:调用监控 API 不一定就是 RAG。只有利用外部知识检索增强生成答案时,才更符合 Agentic RAG 的含义。
到这里,一个 Agent 已经可以动态调查。但如果 Redis、数据库和应用都需要深入分析,单 Agent 的上下文和职责可能变得过重。
十四、第十二次模拟反馈:一个 Agent 忙不过来,怎么办?——Multi-Agent RAG
继续沿用模拟的订单系统故障调查,假设 Redis、MySQL 和应用日志各有大量信息。一个 Agent 不断切换任务,容易遗漏上下文,甚至混淆不同来源的结论。
这时有人提出:“能不能让几个 AI 分头查,最后再汇总?”
先看任务能否真正拆开
我们可以设计一个 Coordinator(协调 Agent),再分配三个专业角色:
| 角色 | 负责的子任务 | 允许检索的资料 |
|---|---|---|
| Redis Agent | 连接池、超时、复制和缓存延迟 | Redis 指标、日志、技术手册 |
| MySQL Agent | 慢 SQL、连接数、锁等待 | 数据库监控和历史记录 |
| Application Agent | 订单接口、调用链、线程池 | APM、应用日志、架构资料 |
输入:“昨晚订单系统为什么变慢?”
第一步,协调 Agent 拆分任务:分别调查 Redis、MySQL 和应用链路。
第二步,专业 Agent 并行检索:每个 Agent 在自己的职责和权限范围内查询资料,并决定是否需要进一步检索。
第三步,返回结构化结果:每个 Agent 给出“观察到的现象、证据来源、可能解释、尚未确认的点”。
第四步,协调 Agent 汇总:对齐时间线,检查三个结论是否冲突,必要时要求补查。
输出(模拟):Redis 连接池等待异常与订单延迟升高同时出现,MySQL 未发现明显慢查询,优先排查 Redis 连接池,但暂不能证明唯一根因。
配图 11:专业 Agent 各自检索,协调 Agent 负责整合与核验。
多 Agent 和三个普通函数并行有什么区别?
三个固定函数并行只是程序并发。Agent 的特点是可以根据自身任务和观察结果,在允许范围内选择后续行动。Multi-Agent RAG 则让多个这样的角色分工协作。
但不要误以为 Agent 越多越好。它会增加协调开销、模型调用、结论冲突和错误传播。若任务简单、单 Agent 已经能稳定完成,多 Agent 可能只会更慢。
所以 Multi-Agent 是解决明确的任务分工问题,不是 Agentic RAG 的必经升级。
十五、第十三次模拟反馈:用户要查真实订单金额,为什么文档检索不行?——Text-to-SQL + RAG
假设知识助手的使用范围扩大,有人提出:“帮我统计上个月各门店有效订单金额,按金额从高到低排序。”
系统检索到《订单表结构设计》和《退款接口说明》,却没有办法给出真实金额。
原因很简单:技术文档描述的是数据如何存储,不是实时业务数据本身。
这次不应该继续优化向量检索
如果数据在 MySQL 里,最直接的办法是查询数据库。Text-to-SQL 是将自然语言转换成 SQL 的技术。
但我们的系统有很多表,用户说的“有效订单金额”也有明确业务含义:哪些订单算有效?退款如何扣除?时间按支付还是下单计算?
如果直接让模型猜 SQL,即使能执行,也可能统计错。
RAG 在 Text-to-SQL 中做什么?
RAG 不负责替代数据库,而是帮助模型找到正确的数据库知识。
输入:“上个月各门店有效订单金额排名。”
第一步,检索 Schema:Schema 指数据库表结构。系统找到 orders、refunds、stores 等相关表,以及关联字段。
第二步,检索指标定义:找到经业务确认的“有效订单金额”口径。例如哪些状态算有效、退款是否扣除。这里不预设具体公司口径。
第三步,生成 SQL:模型依据检索到的表结构与指标定义生成查询语句,而不是凭记忆猜字段。
第四步,执行前校验:检查 SQL 是否只读、是否越权、时间范围是否正确、是否可能造成昂贵查询,必要时通过解析器或白名单限制。
第五步,执行并解释:数据库返回真实统计结果,模型再把结果整理成易读说明。
配图 12:检索 Schema 与指标口径→生成 SQL→校验→执行→解释。
这也能叫 RAG 吗?
Text-to-SQL 本身不是独立的 RAG 架构。 只有当我们通过检索外部 Schema、指标定义或 SQL 示例来增强 SQL 生成时,才是“RAG 增强的 Text-to-SQL”。
例如用户要查固定的“本月销售额”,已经有可靠的业务 API,就直接调用 API,没必要再让 LLM 动态写 SQL。
它的最大风险不是语法,而是业务口径和权限。SQL 执行成功,不等于结果正确。
十六、第十四次模拟反馈:架构图明明在 PDF 里,为什么 AI 看不到?——Multimodal RAG
开发人员问:“Redis 故障切换的架构图在哪里?能结合图解释吗?”
知识助手找到部署手册里的文字,却没有找到那张架构图。因为此前的索引主要面向文本,图片中的节点、箭头和表格结构未必被完整保留。
为什么 OCR 也不够?
OCR(光学字符识别)可以从图片中提取文字。例如它可能读出“应用”“Sentinel”“Redis Master”“Replica”,但读出四个名字不等于理解它们之间的连接关系。
一张架构图的价值往往在箭头和布局;性能图的价值在趋势和坐标;表格的价值在行列关系与单位。这些不能只靠把文字拼接起来。
Multimodal RAG 如何改变检索过程?
Multimodal RAG(多模态 RAG)让图片、表格、页面图像等也参与检索与回答。
常见方法有三种:
方法一:图片描述文本化。 先让视觉模型描述架构图,再将描述建立文本索引。优点是容易接入现有文本 RAG;风险是描述可能遗漏细节。
方法二:多模态 Embedding。 使用能处理文本和图片的模型,将两种内容映射到可比较的表示空间,让文字问题检索相关图片。
方法三:页面图像检索。 将整个 PDF 页面作为图像索引,找到相关页面后交给视觉语言模型读取原图。
我们用第二、三种思路举例:
输入:“Redis 主节点故障后如何切换?给我架构图。”
处理:检索文字说明和图片/页面索引→找到部署手册中的架构图→读取原图与相邻文字→结合资料回答。
输出:解释 Sentinel 故障切换机制,同时附上原始图像及文档页码。
配图 13:文字、表格和图片经过不同处理路径,最终用于有依据的回答。
多模态系统还需要面对图片误读、表格单位丢失、索引成本增加等问题。不能因为视觉模型能“看图”,就认为它能可靠理解所有工程图纸。
对于纯文本知识库,也完全没必要引入这类复杂能力。
十七、第十五次模拟反馈:系统越来越慢,有办法优化生成吗?——Speculative RAG
假设系统增加多种能力后,团队提出这样的反馈:“回答质量可以,等待时间和模型费用却越来越高。”
这时不要马上引入新模型。我们首先要把耗时拆开:检索用了多久?重排序用了多久?Agent 查询了几轮?最终大模型生成用了多久?
只有确认瓶颈在生成阶段,才有必要研究生成优化技术。
Speculative RAG 解决什么问题?
Speculative RAG(推测式 RAG)研究通过多个较小的 Specialist LM(专门模型)并行生成有证据支持的候选答案,再由较强的 Generalist LM(通用模型)验证和选择,以改善某些场景的生成效率与质量。
用 Redis Sentinel 问题来理解:
输入:用户问“Spring Boot 使用 Redis Sentinel 时如何恢复连接?有哪些风险?”检索系统已经找到相关文档。
第一步,准备证据子集:从候选资料中选择不同的支持信息,不必让每个轻量模型都阅读全部长文档。
第二步,并行生成候选:多个 Specialist LM 基于各自证据子集生成带依据的候选答案。
第三步,强模型验证:Generalist LM 检查候选与证据是否一致、是否真正回答问题,再选择更合适的结果。
输出:经过验证的回答,而不是简单对几个模型的答案进行投票。
配图 14:轻量模型并行草拟,强模型负责验证和选择。
它与 Multi-Agent 有什么区别?
Multi-Agent RAG 关注多个自主 Agent 如何分工检索和协作;Speculative RAG 主要关注检索之后的答案生成计算方式,不一定需要自主工具规划。它也不同于常见的 Speculative Decoding(推测解码)。
原始 Speculative RAG 研究涉及专门训练的 Specialist LM;直接用现成大小模型搭建类似工作流,只能算工程变体。
并行也不一定更快。候选生成、传输、强模型验证都有成本。如果问题很简单,反而可能比直接用一个模型更慢。
因此必须比较同一测试集下的端到端延迟、答案正确率和费用,不能只凭论文中的特定实验结果判断生产收益。
十八、总结:学完 16 种技术,实际开发该怎么选?
回头看,我们没有从一开始就设计一套复杂的 RAG,而是跟着技术团队知识助手遇到的模拟问题,一步步增加必要能力。
最初,大模型不知道公司知识,所以引入 Naive RAG。有资料却找不到,就分别研究 Multi-Query、HyDE、Hybrid Search。正确资料排在后面,才引入 Reranking。片段不完整,才考虑 Semantic Chunking 和 Parent-Child。
资料不足时研究 CRAG,答案超出证据时研究 Self-RAG。问题难度不同,考虑 Adaptive RAG;跨文档关系复杂,考虑 GraphRAG;需要动态调查,考虑 Agentic RAG;任务需要明确分工,才考虑 Multi-Agent RAG。
结构化业务数据查询可以用 Text-to-SQL + RAG,图片图表检索可以用 Multimodal RAG,生成确实成为瓶颈时再评估 Speculative RAG。
最值得记住的是问题诊断,而不是技术名单
| 当前系统的问题 | 先检查什么 | 候选技术 |
|---|---|---|
| 资料搜不到 | 召回、查询表达、硬性过滤 | Multi-Query、HyDE、Hybrid |
| 正确资料排名靠后 | 候选排序 | Reranking |
| 回答缺少上下文 | 分块边界、返回范围 | Semantic Chunking、Parent-Child |
| 资料不足还硬答 | 检索质量、证据支持 | CRAG、Self-RAG |
| 简单复杂问题都走同一路径 | 检索策略 | Adaptive RAG |
| 跨文档关系串不起来 | 实体关系和证据 | GraphRAG |
| 需要动态多步调查 | 工具选择和停止条件 | Agentic RAG |
| 多专业任务需要分工 | 任务拆解与协调 | Multi-Agent RAG |
| 需要实时结构化数据 | 数据库与业务口径 | SQL/API、Text-to-SQL + RAG |
| 图片表格无法有效检索 | 多模态索引和原始素材 | Multimodal RAG |
| 生成慢、费用高 | 端到端性能瓶颈 | Speculative RAG |
配图 15:先定位问题,再选择技术,最后验证收益。
怎么判断一次技术升级值不值得?
不要只问“回答是不是更像人了”,而要准备一批有标准答案的真实问题。
可以用 Recall@K 判断相关资料是否进入前 K 个候选;用 MRR、NDCG@K 判断排序是否改善;用答案正确率和证据支持率判断最终回答;再记录延迟和费用。
这些指标解决的是不同问题,不能互相替代。比如 Recall@K 提高了,答案仍可能因为模型误解资料而错误。
本文所有用户反馈、检索排名和示例数据都是为了讲解而设计的模拟案例,并不是已经完成的生产实验。
现在再回到最初的目标:我们希望团队成员不用翻遍所有文档,就能更方便地获取可靠知识。
为了实现这个目标,不需要把所有技术全部装进系统。真正重要的是:遇到什么问题,就研究什么技术;增加什么能力,就验证它带来了什么收益。
这也是我这次系统学习 16 种 RAG 技术后,最重要的一点收获。
参考资料与说明
本文将 16 项相关技术按解决问题的角度整理,其中有些是检索组件、分块策略或数据库查询技术,并非全部是独立 RAG 架构。全文图示为教学示意,不代表真实评测结果。