RAG 不是“把文档放进向量数据库”这么简单。它更像一套让模型使用外部知识的系统方法:先找到证据,再组织上下文,最后要求模型基于证据生成答案。

理解这套技术可以沿着一条逐步增加检索能力的主线展开:

1
2
3
4
5
关键词检索
→ Naive RAG(稠密向量检索)
→ Hybrid RAG(关键词 + 向量 + Rerank)
→ GraphRAG(预先构建全局关系结构)
→ SAG(查询时动态激活事件关系)

这是一条便于理解的技术路线,不是严格的年代顺序或替代关系。关键词检索至今仍不可缺少;GraphRAG 与 SAG 也不是简单的新旧版本,而是面向结构化约束、多跳关系和跨文档证据的不同设计。

2026 年出现的 SAG(SQL-Retrieval Augmented Generation)提供了一条新的结构化路线:不预先维护全局知识图谱,而是把文本组织成事件与实体,查询时用 SQL Join 临时连接相关事件。本文从关键词检索开始,逐步解释 Naive RAG、Hybrid RAG、GraphRAG 与 SAG 的边界和联系。


一、RAG 解决什么问题

大模型的参数可以记住训练时见过的模式和知识,但存在三个天然限制:

  • 知识有截止时间,无法及时反映业务数据变化;
  • 参数中的事实难以直接修改、删除和授权;
  • 回答来源不透明,出现错误时不容易追溯。

RAG 为模型增加一份可检索的外部记忆。经典 RAG 由参数化的生成模型和非参数化的文档索引组成,最初论文使用稠密向量索引检索 Wikipedia 段落,再让生成模型同时参考问题和检索结果。RAG 原始论文

一个现代 RAG 系统通常包含两条链路:

flowchart LR
    subgraph Offline[离线入库]
        Source[文档 / 数据源] --> Parse[解析与清洗]
        Parse --> Chunk[结构化分块]
        Chunk --> Metadata[元数据与权限]
        Metadata --> Index[全文 / 向量 / 图索引]
    end

    subgraph Online[在线问答]
        Query[用户问题] --> Rewrite[理解与改写]
        Rewrite --> Retrieve[多路召回]
        Retrieve --> Fuse[融合与精排]
        Fuse --> Context[上下文组装]
        Context --> LLM[模型生成]
        LLM --> Answer[答案与引用]
    end

    Index --> Retrieve

RAG 可以缓解幻觉,却不能保证消灭幻觉。如果召回不到正确证据、召回了冲突版本,或者模型忽略了证据,最终答案仍可能出错。因此生产系统要分别评测“检索是否正确”和“生成是否忠于证据”。


二、关键词检索:寻找相同的词

关键词检索本身早于 RAG,也不包含生成阶段,因此严格来说它不是一种 RAG。这里把它放在 Naive RAG 之前,是因为 BM25 等词法检索既是现代 RAG 的重要基础,也是评估向量与结构化检索是否真正带来收益的必要基线。

2.1 倒排索引

关键词检索通常使用倒排索引。正向关系是“文档包含哪些词”,倒排关系则是“某个词出现在哪些文档中”:

1
2
3
redis   → 文档 2、文档 8
timeout → 文档 2、文档 5、文档 9
ERR42 → 文档 8

查询时不需要扫描全部文档,只需读取查询词对应的文档列表,再计算相关性分数。

中文检索还涉及分词、同义词、停用词、大小写、简繁体和领域词典。错误码、型号和专有名词不应被通用分词器拆坏。

2.2 TF-IDF 与 BM25

TF-IDF 的直觉是:某个词在当前文档中频繁出现,但在整个语料中很少出现,那么它更能代表该文档。

BM25 在此基础上加入词频饱和与文档长度归一化:

1
2
3
4
score(D, Q) = Σ IDF(qᵢ) ×
f(qᵢ, D)(k₁ + 1)
─────────────────────────────────────
f(qᵢ, D) + k₁(1 - b + b|D| / avgdl)

不必死记公式,理解三个性质即可:

  • 稀有查询词比常见词贡献更大;
  • 一个词重复出现很多次后,收益逐渐饱和;
  • 长文不会仅因包含更多词而天然占优。

2.3 优点与盲区

关键词检索特别适合:

  • 错误码、订单号、API 名称和产品型号;
  • 法条原文、专有名词和精确短语;
  • 用户已经知道目标词汇的站内搜索;
  • 需要低成本、低延迟和容易解释的场景。

它的主要问题是“词不一样就可能找不到”。例如查询“服务为什么没有响应”,文档写的是“请求超时”,二者含义接近但词面重合很少。查询改写、同义词词典和学习型稀疏检索可以改善这个问题,但会增加复杂度。


三、Naive RAG 与向量检索:寻找相近的含义

3.1 为什么称为 Naive RAG

今天工程语境中的 Naive RAG,通常指最基础的“分块、向量化、Top-K 召回、拼接上下文、生成回答”流程:

1
2
文档 → Chunk → Embedding → 向量索引
问题 → Embedding → Top-K Chunk → LLM → 回答

“Naive”不代表它没有价值,而是说明其检索单元通常彼此独立,缺少查询改写、多路召回、精排、父子 Chunk、关系扩展和迭代检索等增强机制。对于单跳事实和语义问答,它仍然是必须建立的基线。

3.2 Embedding 与相似度

Embedding 模型把问题和文本映射为高维向量:

1
2
q  = Encoder(query)
dᵢ = Encoder(chunkᵢ)

再用余弦相似度、点积或欧氏距离寻找最接近的问题片段。语义相似的句子即使没有共享关键词,也可能落在相近的向量区域。

1
2
3
“接口一直没返回”
↓ Embedding
“HTTP 请求发生超时”

向量数据库不是理解知识的模型。它主要负责保存向量、元数据和原文引用,并高效完成近邻搜索。真正决定语义空间的是 Embedding 模型。

3.3 ANN 索引

对所有向量做精确比较的成本会随数据量增长。生产系统常使用近似最近邻搜索(ANN),用少量精度交换显著的速度和内存收益:

索引 核心思路 特点
HNSW 构造多层近邻图并逐层搜索 召回率高、查询快,内存占用较大
IVF 先聚类,再搜索少量候选分区 适合大规模数据,需要训练与调参
PQ 将向量分段量化压缩 大幅节省内存,但会损失精度
Flat 与全部向量精确计算 结果精确,适合小数据或作为评测基线

ANN 参数调优必须同时观察 Recall、P95/P99 延迟、内存和并发吞吐,不能只比较单次查询速度。

3.4 Naive RAG 的常见失败

  • 精确标识符不稳定:Embedding 未必能可靠区分 ERR_4012 与 ERR_4021;
  • 相似不等于相关:主题相似的片段不一定包含回答所需事实;
  • 分块破坏语义:表头、上下文或限定条件被切到另一个 Chunk;
  • 长尾领域漂移:通用模型不理解内部缩写和特殊术语;
  • 时间与权限缺失:只按相似度搜索,可能召回过期版本或无权访问的数据;
  • 多跳能力有限:独立排序 Chunk 不会主动连接散落在不同文档中的证据。

所以向量搜索前应先应用租户、ACL、时间、语言和文档状态等硬过滤;无法用于过滤的权限信息不能只写进正文。


四、Hybrid RAG:让精确匹配与语义召回互补

关键词和向量检索不是替代关系。常见做法是两路并行召回:

flowchart LR
    Q[查询] --> BM25[BM25 关键词召回]
    Q --> Dense[稠密向量召回]
    BM25 --> Fusion[RRF / 加权融合]
    Dense --> Fusion
    Fusion --> Rerank[Cross-Encoder / LLM 精排]
    Rerank --> TopK[Top-K 证据]

4.1 为什么不能直接相加分数

BM25 分数和向量相似度的量纲、范围与分布不同,直接相加往往没有稳定含义。常见融合方法包括:

  • 归一化加权:分别归一化后设置业务权重;
  • RRF:只利用每路结果的名次,降低分数标定差异;
  • 学习排序:使用点击、标注或问答反馈训练融合模型;
  • 查询路由:错误码问题提高关键词权重,概念问题提高向量权重。

RRF 的简化形式为:

1
RRF(d) = Σ 1 / (k + rankᵣ(d))

它易实现、无需训练,是混合检索的可靠起点。

4.2 召回与精排分工

第一阶段需要从大规模语料中快速“多找一些”,强调 Recall;第二阶段让更昂贵的 Cross-Encoder 或 LLM 同时阅读查询与候选片段,强调排序精度。

1
2
3
4
5
百万级 Chunk
→ BM25 Top-100 + Vector Top-100
→ 融合去重约 120 条
→ Rerank Top-10
→ 上下文压缩与引用

Top-K 并非越大越好。无关内容会增加 Token 成本、稀释关键证据,甚至让模型受到错误片段干扰。


五、知识图谱与 GraphRAG:寻找相互连接的事实

5.1 从文本到图

知识图谱通常将知识表示为实体、关系和属性:

1
2
3
(Alice) -[任职于]-> (Company A)
(Company A) -[收购]-> (Company B)
(Company B) -[开发]-> (Product C)

它擅长回答关系型问题:

  • 某人与哪些项目有关?
  • 两家公司通过什么事件连接?
  • 某故障影响了哪些服务和客户?
  • 一个结论依赖哪几条跨文档证据?

典型 GraphRAG 会从文本中抽取实体、关系与事实,构建图并进行社区发现,再结合原始文本生成社区摘要。查询时可以从实体向邻居扩展,也可以用社区摘要回答“整个语料的主要主题是什么”一类全局问题。Microsoft GraphRAG 明确区分 Local、Global、DRIFT 和基础向量搜索模式。Microsoft GraphRAG 论文 · GraphRAG 查询文档

5.2 图检索带来的能力

  • 显式保留跨文档关系,支持多跳搜索;
  • 可从实体、关系、时间或类型施加结构化约束;
  • 路径比纯向量距离更容易解释和审计;
  • 社区和层级摘要有利于回答全局性问题;
  • 可以将检索结果扩展到直接语义不相似但存在关系的证据。

5.3 工程代价

图不是免费的“高级向量库”。它引入了新的质量和运维问题:

  • 实体抽取错误会制造不存在的节点;
  • 同名消歧、别名合并和实体规范化很难;
  • 二元三元组可能拆散一个完整事件的时间、地点和参与者;
  • 文档更新后要同步修改节点、边、社区和摘要;
  • 索引阶段需要大量模型调用,Microsoft 也提醒标准 GraphRAG 索引可能消耗大量 LLM 资源;
  • 图路径存在不代表它与当前问题相关,仍需要文本证据和精排。

因此 GraphRAG 更适合关系密集、多跳和全局归纳问题。FAQ、错误码手册或简单事实查询,混合检索通常更直接。


六、SAG:查询时才激活关系

6.1 SAG 是什么

本文的 SAG 指 SQL-Retrieval Augmented Generation,不是泛指 Search-Augmented Generation。它由 2026 年的论文提出,目标是补足向量 RAG 的多跳能力,同时减少全局知识图谱的构建和维护成本。SAG 论文 · SAG Benchmark

SAG 的关键变化是知识表示方式:

  • 每个 Chunk 被整理为一个语义完整的事件;
  • 一个事件关联多个带类型的实体;
  • 事件与实体保存为普通表和索引;
  • 查询时以共享实体作为 Join Key,连接相关事件;
  • 连接只服务于当前查询,不持久化为全局图;
  • 最终证据仍映射回原始 Chunk,便于引用。

假设两段文档分别表达:

1
2
3
4
5
事件 E1:Alice 在 2025 年加入 Company A,负责 Project X。
实体:Alice、Company A、Project X、2025

事件 E2:Project X 使用 Database Y,曾因连接池耗尽发生故障。
实体:Project X、Database Y、连接池耗尽

查询“Alice 负责的项目为什么发生故障”时,查询本身与 E2 的词面和向量语义未必足够接近。SAG 可以先命中 E1,再通过共享实体 Project X Join 到 E2,组成当前查询所需的两跳证据链。

6.2 为什么称为动态超边

普通知识图谱常把关系拆为二元三元组。一个“甲公司于某日在某地收购乙公司”的事件,可能被拆成多条边,事件边界和限定条件容易丢失。

SAG 将一个完整事件以及参与该事件的多个实体视为一条潜在超边:

1
event ↔ {entity₁, entity₂, ..., entityₙ}

它在存储中只是事件表、实体表和关联表;当查询沿“事件 → 实体 → 其他事件”扩展时,相关超边才被激活。论文将其称为 query-time dynamic hyperedges。

6.3 索引与查询流程

flowchart TB
    subgraph Indexing[离线索引]
        Chunk[原始 Chunk] --> Extract[LLM 提取完整事件与类型化实体]
        Extract --> EventTable[(Event 表)]
        Extract --> EntityTable[(Entity 表)]
        Extract --> Incidence[(Event-Entity 关联表)]
        Chunk --> Vector[(向量索引)]
    end

    subgraph Querying[在线查询]
        Query[问题] --> Seeds[向量检索 + 查询实体识别]
        Seeds --> Join[SQL 按共享实体扩展]
        Join --> Candidates[压缩候选事件集]
        Candidates --> Select[LLM 最终选择]
        Select --> Source[映射回原始 Chunk]
        Source --> Generate[回答与引用]
    end

    Vector --> Seeds
    EventTable --> Join
    EntityTable --> Join
    Incidence --> Join

这里的 SQL 不负责理解自然语言。它负责确定性地执行实体过滤、关联和有界扩展;Embedding 负责找到没有精确词面重合的种子,LLM 负责事件实体抽取、查询理解和最终候选选择。三者各自解决不同问题。

6.4 SAG、Naive/Hybrid RAG 与 GraphRAG 对比

维度 向量 / 混合 RAG GraphRAG SAG
核心检索单元 独立 Chunk 实体、关系、社区与文本 完整事件、实体与原始 Chunk
跨文档关联 弱,依赖迭代检索或模型推理 预先构建的全局图 查询时按共享实体 Join
多元关系 隐含在文本中 常被拆成二元边 一个事件对应多实体超边
增量写入 简单 可能需要实体合并和图维护 以追加事件和关联记录为主
全局主题归纳 较弱 社区摘要较强 论文重点不在全局摘要
精确约束 依赖元数据过滤 图查询 SQL 过滤与 Join
索引成本 Embedding 为主 实体关系抽取、聚类与摘要 每个 Chunk 做事件实体抽取
典型优势 单跳语义与精确查询 关系、路径和全局问题 动态增长语料中的多跳证据

SAG 不是“只用 SQL 替代向量检索”,也不是简单地把 RAG 与 GraphRAG 并排运行。它仍使用向量召回种子,但把跨 Chunk 的关联组织为关系表,并在查询时激活。

6.5 如何看待实验结果

论文在 HotpotQA、2WikiMultiHopQA 和 MuSiQue 三个多跳问答数据集上比较 BM25、向量检索和多种结构化 RAG。其报告称,在统一使用 BGE-Large-EN-v1.5 Retriever 与 Qwen3.6-Flash Reader 时,SAG 的平均 Recall@5 和问答 F1 分别为 90.07% 与 72.96%;在多跳要求更高的 MuSiQue 上,Recall@5 为 80.36%。论文实验与完整结果

这些数字值得关注,但暂时不能直接推出“SAG 已在所有企业知识库场景优于其他方案”:

  • 论文仍是较新的预印本,结论主要来自作者团队;
  • 三个主要数据集都是英文百科式多跳问答;
  • 实验语料规模为数千到一万余 Passage,不等于真实超大企业语料;
  • 产品文档、代码、表格、对话和中文实体的表现尚需单独评测;
  • 指标对模型、分块、候选预算和评测脚本非常敏感;
  • LLM 抽取和最终选择是系统效果的重要组成部分,不是纯 SQL 带来的收益。

更稳妥的判断是:SAG 展示了“用关系数据库保存轻量事件结构、在查询时动态恢复多跳关系”的可行性,而不是宣告向量检索和知识图谱已经过时。

6.6 潜在局限

  1. 抽取成本:论文的离线阶段对每个 Chunk 进行一次结构化 LLM 调用,成本仍高于纯向量入库。
  2. 实体一致性:别名、同名实体和错误类型会直接影响 Join 的准确率。
  3. 热门实体爆炸:沿“公司”“中国”等高频实体扩展可能产生大量候选,需要类型、度数和预算限制。
  4. 事件粒度依赖分块:一个 Chunk 同时描述多个事件,或一个事件跨越多个 Chunk 时,“一块一事件”的假设会受到挑战。
  5. 关系语义较轻:共享实体能说明事件相连,但不自动说明连接与问题相关。
  6. 全局分析不是强项:语料主题、趋势与社区概览仍可能更适合 GraphRAG 的层级社区摘要。
  7. 权限传播:跨 Chunk Join 前必须执行文档级 ACL 过滤,不能让无权访问的事件成为桥接节点。
  8. 模型稳定性:托管模型升级和非确定性会让抽取、选取与论文复现实验出现差异。

七、如何选择检索方案

不要从“哪种技术最先进”开始,而应先分析问题类型:

问题或数据特征 建议起点
错误码、SKU、合同编号、API 名称 BM25 / 全文检索
自然语言问答、同义表达、概念解释 向量检索
同时存在专有词和自然语言 BM25 + 向量混合检索 + Rerank
已有高质量结构化数据库 SQL / API 工具调用,不必强行转成 Chunk
稳定本体、复杂路径、合规推理 知识图谱 + 原文证据
面向整个语料的主题归纳 GraphRAG 社区与层级摘要
动态增长语料中的事件关联、多跳问答 可试验 SAG
多种问题混合存在 查询分类与多路检索路由

一个务实的演进顺序是:

1
2
3
4
5
BM25 基线
→ 增加向量召回
→ RRF 融合与 Rerank
→ 元数据、ACL、引用和评测闭环
→ 只有多跳失败明确时,再引入图或 SAG

先建立简单基线很重要。没有 BM25 和纯向量结果,就无法判断复杂结构到底解决了什么问题,也无法证明额外成本值得。


八、评测比选型更重要

8.1 建立问题集

从真实业务中收集并标注:

  • 精确词查询;
  • 同义表达查询;
  • 时间、部门、版本等过滤查询;
  • 需要两到四条证据的多跳查询;
  • 无答案问题;
  • 权限隔离问题;
  • 冲突与过期知识问题。

每个问题至少记录参考答案、必要证据 Chunk、允许的数据范围和问题类型。

8.2 分层指标

层级 推荐指标 关注点
检索 Recall@K、MRR、nDCG 正确证据是否被找到及排序
多跳检索 Evidence Recall、链路完整率 所有必要证据是否同时出现
生成 正确性、Faithfulness、引用准确率 回答是否受证据支持
系统 P50/P95/P99、吞吐、Token 与模型成本 是否可用于生产
安全 越权召回率、敏感信息泄露率 ACL 是否在每条路径生效

只测最终答案会掩盖问题:有时模型凭参数记忆答对,但检索完全错误;有时检索正确,模型却忽略证据。二者必须拆开定位。

8.3 SAG 的试验方法

如果要验证 SAG,不建议立刻替换现有检索栈。可以选择一组明确的多跳问题做影子实验:

  1. 固定同一份语料、分块和生成模型;
  2. 建立 BM25、纯向量、混合检索与现有 GraphRAG 基线;
  3. 为 SAG 记录实体抽取准确率、候选扩展量和 Join 深度;
  4. 比较相同 Top-K 预算下的证据链完整率;
  5. 单独统计入库成本、在线延迟和增量更新成本;
  6. 人工检查失败案例是种子未命中、实体未统一、扩展过宽还是最终选错;
  7. 在进入生成模型前执行相同 ACL 过滤并做越权测试。

只有当多跳召回提升在自己的数据上稳定复现,且额外成本和风险可以接受,才值得进入生产架构。


九、总结

理解 RAG 的关键不是记住产品名,而是理解不同检索信号:

  • 关键词检索寻找相同的词,精确、便宜、可解释;
  • Naive RAG 以独立 Chunk 的稠密向量 Top-K 召回为核心,是语义问答基线;
  • Hybrid RAG 同时利用词面、语义和精排,通常是通用 RAG 的生产起点;
  • GraphRAG 寻找显式连接,擅长路径、关系和全局结构,但索引与维护成本高;
  • SAG 将 Chunk 表示为完整事件,以实体为 Join Key,在查询时动态连接证据,为多跳检索提供了轻量结构化新路线。

不存在一种索引能够独自解决所有问题。成熟的知识系统会把全文、向量、元数据、关系和原始证据视为不同层次,并通过真实问题集决定是否需要更复杂的结构。


参考资料