生产工程 · 2025年6月17日 · 4 分钟

RAG 进阶:从 Naive RAG 到 Agentic RAG

Query Rewriting、HyDE、Reranker、Hybrid Search、Self-RAG、Graph RAG——三代 RAG 技术的完整梳理与选型指南。

我之前写过一篇 RAG 入门的文章(《RAG 实战:构建一个私有知识库问答系统》),主要讲最简单的 "向量检索 + LLM" 模式。

用了半年之后发现,Naive RAG 在真实场景中只能解决大约 60% 的问题。剩下的 40% 需要更精细的设计——这也是 RAG 从"简单"走向"复杂"的原因。

这篇文章梳理 RAG 的进阶技术演进路线。

Naive RAG 的问题

先回顾一下最基本的 RAG 流程,以及它的问题:

用户提问 → Embedding → 向量检索 → Top-K 文档 → 拼 PromptLLM 回答

问题 1:检索不准确
  "我买回来的产品有裂痕" → 向量匹配到"产品出厂质检流程"
  (语义相似但不相关——都是讨论产品质量,但目的完全相反)

问题 2:信息不够
  "帮我对比一下 Redis 和 Memcached"
  → 如果两个文档是独立的,分别检索都只有部分信息

问题 3:跨文档推理
  "根据第一季度的销售数据和去年的库存策略,制定今年的采购计划"
  → 需要综合多个文档的信息才能回答,但每个文档单独检索得分都不高

问题 4:检索结果质量差
  Top-3 里可能有两个是噪声、一个是答案
  → LLM 被噪声影响,输出质量下降

解决这些问题就是 RAG 进阶的方向。

进阶技术演进路线

RAG 的进化可以分为三代:

第一代:Naive RAG
  文档 → 切割 → Embedding → 向量检索 → LLM 生成
  缺点:检索精度有限,无法处理复杂查询

第二代:Advanced RAG
  Naive + Query Rewriting + HyDE + Reranker + Hybrid Search
  效果提升:让检索更精准

第三代:Agentic RAG
  Advanced + Self-RAG + Graph RAG + 多步检索
  效果提升:让推理更智能

第二代:Advanced RAG

Query Rewriting(查询改写)

用户的原始问题往往不是最好的检索查询。

用户原始问题:"这个怎么用?"
→ 缺少上下文,向量检索效果差

改写后:"详细描述 Redisson 分布式锁的使用方法"
→ 包含关键词,检索命中率大幅提升

Query Rewriting 可以用 LLM 来做,也可以用小模型快速改写。一个简单的实现:

def rewrite_query(user_query: str, history: list[str]) -> str:
    """用 LLM 把用户问题改写为更适合检索的形式"""
    prompt = f"""基于对话历史,把用户问题改写成适合向量检索的形式。
要求:提取核心实体和问题意图,去除指代。

对话历史:{history}
用户问题:{user_query}

改写后的检索查询:"""
    return llm.generate(prompt)

为什么不直接用 LLM 做检索? Rewriting 和最终回答用同一个 LLM 当然可以,但成本高。实践中用一个小模型(甚至一个规则 + 关键词提取)做改写,大模型只做最终回答,成本结构更合理。

HyDE(Hypothetical Document Embedding)

HyDE 的思路:先让 LLM 根据问题生成一个"假想的完美文档",然后用这个假文档的 embedding 去检索。

用户问题:"红黑树的插入过程是怎样的?"

HyDE 生成假想文档:
  "红黑树的插入过程包括以下步骤:
  1. 将新节点插入到树中,颜色设为红色
  2. 检查并修复红黑树性质
  3. 如果父节点是黑色,插入完成
  4. 如果父节点是红色,需要进一步调整..."

用假想文档的 embedding 检索:
  → 找到更高质量的相关文档

为什么有效?因为问题和答案在语义空间中的位置不同。一个短问题的 embedding 可能偏离目标文档很远,而假想的答案文档更接近真实文档。

实际效果:在某些数据集上,HyDE 可以让 Recall@5 提升 10-15%。但有一个限制——对 LLM 生成假文档的质量有要求,如果假文档本身质量低,反而会降低检索效果。

Reranker(重排序)

向量检索的第一阶段(初筛)追求速度,返回 Top-100。Reranker 对 Top-100 做精细的交叉编码排序,找出真正的 Top-5。

第一阶段(向量检索):
  100 个候选文档
  速度:~50ms
  精度:60-70%

第二阶段(Reranker):
  对 100 个候选做交叉编码排序
  速度:~500ms
  精度:85-95%

Reranker 比向量检索慢一个数量级,但因为只对 Top-100 做排序,总的延迟增加可以接受。

权衡:加 Reranker 意味着系统多了一个组件(部署成本),每次检索多花几百毫秒。但带来的检索精度提升非常可观。是否值得取决于你的场景——如果用户对答案准确率要求高,值得上。

Hybrid Search(混合检索)

向量检索擅长语义匹配,但词法匹配(关键词精确命中)上的效果不如 BM25。

查询:"支付接口超时设置"

向量检索结果:
  1. "payment gateway timeout configuration" (语义相似)
  2. "超时重试机制的设计" (语义相关)

BM25 检索结果:
  1. "支付接口超时如何处理" (包含完整关键词)
  2. "HTTP 请求超时设置" (部分匹配)

混合检索 = 向量检索 + BM25,然后合并排序。

def hybrid_search(query: str, alpha: float = 0.5) -> list[Document]:
    """混合检索:合并向量相似度和 BM25 分数"""
    vector_results = vector_search(query, top_k=100)
    bm25_results = bm25_search(query, top_k=100)
    
    # Reciprocal Rank Fusion (RRF)
    scores = {}
    for rank, doc in enumerate(vector_results):
        scores[doc.id] = scores.get(doc.id, 0) + 1 / (60 + rank)
    for rank, doc in enumerate(bm25_results):
        scores[doc.id] = scores.get(doc.id, 0) + 1 / (60 + rank)
    
    # 按总分排序
    ranked = sorted(scores.items(), key=lambda x: x[1], reverse=True)
    return [docs[id] for id, score in ranked[:top_k]]

RRF(Reciprocal Rank Fusion)是合并两种排序结果的常用方法,不需要调参,效果好于加权平均。

第三代:Agentic RAG

Advanced RAG 优化了"检索"环节,但检索策略本身仍然是固定的——每次查询,都做一次 embedding → 检索 → 生成。

Agentic RAG 在此基础上增加了检索决策的智能性

Self-RAG:让 LLM 自己决定要不要检索

传统 RAG 是"每次都检索"。但有些问题不需要检索(比如闲聊),有些问题一次检索不够。

Self-RAG 引入两个机制:

反思 token(Reflection Tokens):
  在每个预测阶段,模型输出额外的标记:
  - [检索]:需要检索 → 触发检索过程
  - [不检索]:不需要 → 直接生成
  - [相关]:检索结果与问题相关
  - [不相关]:检索结果不相关
  - [支持]:生成内容被检索结果支持
  - [不支持]:生成内容不在检索结果中

Self-RAG 的训练需要额外标注数据,不是随便一个模型就能用的。但现在的主流模型(GPT-4o、Claude、DeepSeek)已经可以通过在 prompt 中描述这个模式来模拟 Self-RAG 的行为。

Graph RAG:利用知识图谱的 RAG

传统的 RAG 把文档切块嵌入,丢失了文档之间的结构关系。Graph RAG 在此基础上构建知识图谱。

传统 RAG:
  [文档块1] [文档块2] [文档块3] [文档块4]
  (互相独立,没有关联)

Graph RAG:
  ┌─ 实体 A ─→ 关系1 ─→ 实体 B
  │
  关系2          关系3
  │              │
  ▼              ▼
  实体 C ─→ 关系4 ─→ 实体 D

Graph RAG 的处理流程:

1. 实体提取:从文档中提取命名实体(人、组织、概念、产品)
2. 关系构建:识别实体之间的关系
3. 社区检测:把紧密关联的实体和文档聚合成社区
4. 社区摘要:对每个社区生成摘要
5. 查询时:
   第一步:在实体级别检索(找相关实体和关系)
   第二步:在社区摘要级别检索(找相关社区总结)
   第三步:合并结果给 LLM

Graph RAG 最大的优势是全局性查询——比如"公司的整体战略是什么",传统的 RAG 只能抓到几个碎片化的段落,Graph RAG 可以通过实体关联找到完整的上下文。

代价是什么?构建知识图谱的成本非常高。微软发布的 Graph RAG 论文中提到,索引一份 100 万字的文档需要调用数千次 LLM API、耗时几十分钟。不是所有场景都值得。

自适应检索的多步推理

最复杂的 Agentic RAG 模式——Agent 可以在多个步骤之间决定如何检索:

步骤 1:分析问题
  "2024 年 Q1 销量最好的产品是什么?"
  → 决定先检索产品列表

步骤 2:检索 + 分析
  找到产品列表 → 发现需要按销量排序
  → 决定检索销售数据

步骤 3:再次检索 + 推理
  得到销售数据 → 计算排名 → 得出答案
  → 决定是否需要额外信息
  → 不需要 → 输出最终答案

这与 ReAct 模式本质相同——Agent 可以通过多轮工具调用(检索工具)逐步逼近答案。区别在于:每一步的"检索"本身也是经过优化的(带 Query Rewriting、Reranker 等)。

如何选择 RAG 方案

你面临的 RAG 问题                                   推荐方案
────────────────────────────────────────────────────────
知识库文档少(< 100 份),问题简单                  Naive RAG
知识库大但问得浅(FAQ 类)                          Naive + Hybrid Search
用户提问表达不准确                                  需要 Query Rewriting
需要精确匹配关键词                                  需要 Hybrid Search (BM25 + 向量)
用户反复问相似问题但用词不同                        需要 HyDE
检索结果不稳定,时好时坏                            需要 Reranker
需要综合多份文档回答                                需要 Graph RAG
单次检索永远不够                                    需要 Self-RAG / 多步推理
公司内部文档,需要精确溯源                          需要 Reranker + Hybrid Search

一个生产级 RAG 系统的完整架构

用户 Query
    │
    ▼
┌──────────────────────┐
│  步骤 1:路由          │
│  是检索问题吗?         │──→ 否 → 直接 LLM 回答
│  需要什么类型的检索?    │
└──────────┬───────────┘
           ▼ 是
┌──────────────────────┐
│  步骤 2Query 处理    │
│  Query Rewriting      │  ← LLM 改写
│  Query Expansion      │  ← 生成多个相关查询
│  HyDE 生成            │  ← 可选
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│  步骤 3:多路检索      │
│  ├─ 向量检索           │  ← Embedding
│  ├─ BM25 关键词检索     │  ← 精确匹配
│  └─ SQL/元数据过滤     │  ← 结构化约束
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│  步骤 4:融合与重排    │
│  RRF 融合             │  ← 多路结果合并
│  Reranker 精排        │  ← 交叉编码器
│  Context Management   │  ← 去重 + 截断
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│  步骤 5LLM 生成      │
│  严格按照检索结果生成    │
│  引用来源              │
│  不知道的说不知道       │
└──────────────────────┘

这个架构看着复杂,但 90% 的场景不需要全部组件。建议的切入路径:

第一步:Naive RAG 跑通(1-2 天)
  能回答基础问题,知道系统能不能跑

第二步:加 Hybrid Search(+1 天)
  解决关键词匹配问题,提升 10-15% 准确率

第三步:加 Reranker(+2 天)
  精排 Top-100 结果,提升 15-20% 准确率

第四步:按需加 Query Rewriting / HyDE / 多步推理
  根据 bad case 针对性优化

不要一开始就追求"完整的 RAG 架构"——大多数场景不需要。从最简单的开始,根据真实 bad case 逐步迭代。

RAG 发展到今天,技术已经相对成熟。真正决定系统上限的往往不是用了多少花哨的技术,而是文档质量用户问题的覆盖度。这和搜索引擎的道理一样——垃圾进,垃圾出。

继续阅读

评论