Skip to content

RAG 检索增强生成:从基础架构到高级范式

摘要: 围绕检索增强生成(RAG)技术体系,从基础三段式架构(检索-增强-生成)出发,逐层拆解文档解析与Chunking策略、向量数据库选型与BM25+向量混合检索、Embedding模型对比及Reranking精排机制,并深入分析上下文注入方式与引用溯源策略。在此基础上,系统介绍了GraphRAG、Agentic RAG和Multi-hop RAG三种高级范式的核心原理、架构差异与适用场景,为构建生产级RAG系统提供从预处理到高级检索的完整技术路线参考。

1. RAG 基础架构 — 检索 + 增强 + 生成三段式

核心思想

让 LLM 在生成答案之前,先去外部知识库"翻资料",用检索到的真实信息来增强回答的准确性和时效性。

figure

1.1 为什么需要 RAG?

大语言模型存在几个根本性局限:

问题说明示例
知识截止训练数据有截止日期,不知道训练后的事件"2025年诺贝尔奖得主是谁?"无法回答
幻觉(Hallucination)模型会自信地编造不存在的事实捏造论文标题、虚构 API
私有知识盲区企业内部文档、个人笔记不在训练数据中"公司内部保险理赔流程是什么?"
缺乏溯源无法告知答案的来源出处用户无法验证信息可信度

RAG 的解决方案:不靠模型记忆,靠实时检索。 就像考试时允许你翻课本——你不需要把所有知识背下来,只要知道怎么查找就行。

1.2 RAG 三段式架构

RAG 的完整流程分为三个阶段,我们可以用一条管线来表示:

                            RAG 完整架构
================================================================================

  ┌──────────┐     ┌──────────────────────┐     ┌──────────────────────┐
  │          │     │                      │     │                      │
  │  用户查询 │────>│  ① 检索 (Retrieval)   │────>│  ② 增强 (Augmentation)│
  │  "Q: ..." │     │                      │     │                      │
  │          │     │  从知识库中找到最相关   │     │  把检索结果嵌入到     │
  │          │     │  的文档片段(Chunks)   │     │  Prompt 的上下文中    │
  └──────────┘     └──────────────────────┘     └──────────┬───────────┘
                     ▲                                  │
                     │  ┌─────────────────┐              │
                     │  │  向量数据库       │              │
                     │  │  (Vector Store)  │              │
                     │  │  ┌───┐ ┌───┐   │              │
                     │  │  │C1 │ │C2 │   │              │
                     │  │  │C3 │ │...│   │              │
                     │  │  └───┘ └───┘   │              │
                     │  └─────────────────┘              │
                     │                                  ▼
                     │                       ┌──────────────────────┐
                     │                       │                      │
                     └───────────────────────│  ③ 生成 (Generation) │
                          返回 Top-K 相关     │                      │
                          文档片段            │  LLM 基于「用户问题  │
                                             │  + 检索到的文档」     │
                                             │  生成最终答案          │
                                             └──────────┬───────────┘


                                                ┌──────────────┐
                                                │  最终答案     │
                                                │  + 引用来源   │
                                                └──────────────┘

三个阶段详细拆解:

阶段一:检索 (Retrieval)

  用户问题 ──> 查询预处理 ──> Embedding ──> 向量相似度搜索 ──> Top-K 文档
              (改写/扩展)       (向量化)      (cosine/Dot)       (K=5~20)

  直观理解:把问题变成一个"搜索向量",去知识库中找离它最近的 K 个文档片段。

阶段二:增强 (Augmentation)

  Top-K 文档 ──> 排序/过滤 ──> 拼接到 Prompt ──> 构建增强后的上下文
                (Reranking)

  直观理解:把找回来的资料整理好,"粘贴"到给 LLM 的 Prompt 里。

阶段三:生成 (Generation)

  增强 Prompt ──> LLM 推理 ──> 生成答案 ──> 附加引用

  直观理解:LLM 阅读你提供的资料后,回答用户的问题,并标注信息来源。

1.3 一个具体的例子

假设用户问:"公司年假政策是什么?"

步骤 1 — 检索:
  Query "公司年假政策" → Embedding → 向量搜索
  → 找到最相关的 5 个文档片段:
    - Chunk 23: "员工入职满1年享有5天年假..."  (相似度 0.92)
    - Chunk 47: "年假跨年可累计,最多累计..."   (相似度 0.88)
    - Chunk 15: "请假流程需在OA系统中提交..."   (相似度 0.79)
    ...

步骤 2 — 增强:
  构建 Prompt:
  """
  请根据以下文档回答用户问题:

  文档1: 员工入职满1年享有5天年假...
  文档2: 年假跨年可累计,最多累计...
  文档3: 请假流程需在OA系统中提交...

  用户问题:公司年假政策是什么?
  请基于以上文档回答,并标注引用来源。
  """

步骤 3 — 生成:
  LLM 输出:
  "根据公司政策,年假规定如下:
   1. 入职满1年的员工享有5天年假【来源:文档1】
   2. 年假可跨年累计,上限为15天【来源:文档2】
   3. 需通过OA系统提交请假申请【来源:文档3】"

1.4 RAG vs 微调(Fine-tuning)

专家建议:对于知识更新场景,RAG 是首选。微调更适合改变模型的"行为模式"(如语气、输出格式),两者可以互补使用。

这是两个解决"模型不知道"问题的主流方案,但思路完全不同:

维度RAG微调(Fine-tuning)
原理外部检索,不改模型参数修改模型权重
知识更新即时(更新数据库即可)需要重新训练
成本低(只需 embedding + 向量存储)高(需要 GPU 训练)
可解释性高(可追溯来源)低(知识融入权重,不可追溯)
适用场景知识密集型、频繁更新的知识风格/格式/行为调整
幻觉控制强(答案被检索结果约束)弱(可能学到错误知识)

2. 检索前处理 — Chunking 策略、文档解析

检索的质量,有一半取决于"前置处理"做得好不好。如果文档切得太碎(失去上下文)或太大(检索不精确),都会严重影响后续效果。

2.1 文档解析(Document Parsing)

在切分之前,首先要从各种格式中提取出纯文本,文档解析 Pipeline 具体如下:

  PDF     ──┐
  Word    ──┤
  HTML    ──┤                              ┌──────────────┐
  Markdown──┼──> 格式解析器 ──> 纯文本 ──>  │  文本清洗    │
  PPT     ──┤   (Parser)                  │ - 去掉页眉页脚│
  Excel   ──┤                              │ - 合并断行    │
  图片     ──┤  OCR 识别 ──────────────>  │ - 统一编码    │
  (扫描件)──┘                              └──────┬───────┘


                                          清洗后的纯文本
                                          (Ready for Chunking)

常见文档解析工具:

工具/库适用格式特点
PyPDF2 / pdfplumberPDF基础 PDF 文本提取
UnstructuredPDF/Word/HTML/PPT/图片一站式文档预处理,支持 OCR
LlamaParsePDF(尤其是复杂表格)LlamaIndex 出品,专为 RAG 优化
Azure Document Intelligence多格式云服务,表格识别强
MarkerPDF → Markdown开源,识别质量好
Docling (IBM)PDF/Word/PPT/HTML保留文档结构,输出 Markdown/JSON

关键注意事项:

  • 表格处理普通 PDF 提取常常把表格变成混乱文本。需要用专门的表格识别工具。
  • 图片中的文字:扫描件 PDF 需要 OCR。多模态模型可以直接理解图片,但成本更高。
  • 排版结构:保留标题层级(H1/H2/H3)对后续切分有帮助——结构化的文档更容易切出语义完整的片段。

2.2 Chunking 策略(文档切分)

Chunking 是 RAG 中最容易被低估的环节,切分策略直接影响检索的相关性和生成答案的完整性。

2.2.1 固定大小切分(Fixed-size Chunking)

最基础的方法:按固定字符数切分,加上重叠(Overlap)窗口。

  • 优点:简单、快、易于实现。
  • 缺点:可能在句子中间切断,丢失语义完整性。
固定大小切分示例 (Chunk Size=500, Overlap=50)

  原文: "...人工智能技术正在深刻改变世界。从2010年代深度学习兴起,
         到2020年代大语言模型的爆发,每一次技术浪潮都带来了..."
         [共 1500 字]

  切分结果:
  ┌──────────────────────┐
  │ Chunk 1: [0:500]     │ ← 字符 0~500
  │     ...               │
  │     ...深度学习兴起,  │
  └──────────────────────┘
           ┌──────────────────────┐
           │ Chunk 2: [450:950]   │ ← 字符 450~950 (重叠 50 字)
           │   深度学习兴起,...    │
           │   ...大语言模型的...  │
           └──────────────────────┘
                    ┌──────────────────────┐
                    │ Chunk 3: [900:1400]  │ ← 字符 900~1400
                    │   大语言模型的爆发... │
                    │   ...                 │
                    └──────────────────────┘
                              ┌──────────────────────┐
                              │ Chunk 4: [1350:1500] │
                              │   ...                 │
                              └──────────────────────┘

推荐参数:

场景Chunk SizeOverlap说明
短问答(FAQ)256~512 tokens10%~20%小片段足够定位答案
一般知识检索512~1024 tokens10%~20%通用场景
长文档理解1024~2048 tokens15%~25%需要完整上下文
代码检索按函数/类按需不要用固定大小切代码!

tokens vs 字符:英文 1 token ≈ 0.75 词 ≈ 4 字符;中文 1 token ≈ 1.5~2 字符。用 token 计数更准确,因为 LLM 按 token 计费。

2.2.2 语义切分(Semantic Chunking)

核心思路:在语义边界处切分,而不是按字符数。

语义切分 vs 固定大小切分

  原文段落:
  "## 第一章:深度学习基础

  深度学习是机器学习的一个分支,它使用多层神经网络来学习数据的层次化表示。
  与传统机器学习不同,深度学习可以自动从原始数据中提取特征,无需手工设计。

  ### 1.1 神经网络

  神经网络由多个神经元层组成,每一层都对输入进行非线性变换..."

  差的分割(固定大小,在句子中间切断):
  Chunk A: "...它与传统机器学习不同,深度学"
  Chunk B: "习可以自动从原始数据中提取特征..."

  好的分割(沿语义边界):
  Chunk A: "## 第一章:深度学习基础\n\n深度学习是机器学习的一个分支..."
          [完整的段落,包含标题]
  Chunk B: "### 1.1 神经网络\n\n神经网络由多个神经元层组成..."
          [完整的子节,自包含]

实现方法:

  1. 按段落/标题切分:以 Markdown 标题(#, ##)或双换行作为切分点。
  2. 按句子切分 + 合并:先按句子切,然后合并相邻句子直到接近 Chunk Size 上限。
  3. Embedding 相邻性切分:计算相邻段落的 Embedding,在"语义跳变"处切分。
基于 Embedding 的语义切分

  1. 将文档按句子拆分: [S1, S2, S3, S4, S5, S6, S7, S8, ...]
  2. 计算每个句子的 Embedding 向量
  3. 计算相邻句子的余弦相似度:

     S1   S2   S3   S4   S5   S6   S7   S8
     │     │     │     │     │     │     │
     0.85  0.91  0.88  0.42  ←跳变!  0.87  0.90

                         在这里切分(语义发生了变化)

  4. 在相似度低于阈值的地方切分

LlamaIndex 的 SentenceWindowNodeParser 是一个很好的实现参考:它按句子切分,但检索时会带回前后窗口的句子。

2.2.3 递归字符切分(Recursive Character Splitting)

LangChain 的 RecursiveCharacterTextSplitter 是最常用的方法。它按照优先级从高到低尝试切分符:

递归切分优先级(中文环境)

  1. "\n\n"    — 段落分隔符(最高优先级,尽量在段落边界切)
     │ 如果段落还是太大...
  2. "\n"      — 行分隔符
     │ 如果还是太大...
  3. "。"      — 中文句号
     │ 如果还是太大...
  4. ";"      — 中文分号
     │ 如果还是太大...
  5. ","      — 中文逗号
     │ 如果还是太大...
  6. 字符级    — 强制按字符切分(最后手段)

  目标:尽量在更"自然"的边界切分,保持语义完整。

代码示例(Python):

python
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "。", ";", ",", " "]
)
chunks = splitter.split_text(document)

2.2.4 高级切分策略

策略原理适用场景代表工具
Agentic Chunking用 LLM 判断每个句子的最佳归属高精度需求自定义实现
Small-to-Big检索用小粒度段,生成时带回大粒度段兼顾检索精度和上下文完整性LlamaIndex
Multi-representation每个段落生成摘要,用摘要做检索,原文做生成长文档、非结构化数据LangChain Indexing API
Propositions将每个段落拆分为原子性命题(一句话一个事实)高精度事实检索学术前沿

3. 检索 — Vector Database、混合检索、Embedding 选择、Reranking

检索是 RAG 的核心引擎。从技术栈角度看,检索涉及三个关键决策:用什么向量库、用什么 Embedding 模型、用什么检索策略。

3.1 Vector Database(向量数据库)

3.1.1 什么是向量数据库?

普通数据库按"精确匹配"查询(WHERE name = '张三'),向量数据库按"语义相似"查询:"找和这句话意思最接近的文档"。

关系型数据库 vs 向量数据库

  关系型数据库:
    Query: "找到价格=100的商品"  → 精确匹配 → {"id": 42, "price": 100}

  向量数据库:
    Query: "适合冬天穿的保暖外套" → Embedding → [0.12, -0.34, 0.88, ...]

                                  相似度搜索(ANN: 近似最近邻)

                                  [羽绒服, 棉衣, 加厚卫衣, ...]

核心概念:

概念说明
Embedding Vector文档/查询的数值化表示,通常 768~4096 维
相似度度量Cosine Similarity(最常用)、Euclidean Distance、Dot Product
ANN(近似最近邻)牺牲少量精度换取极快速度的搜索算法(HNSW、IVF、PQ)
Collection/Index向量的逻辑分组,类似关系库中的"表"
Metadata Filtering基于标签/日期的预过滤(如"只看2024年的文档")

3.1.2 主流向量数据库对比

向量数据库选择矩阵:

  轻量 / 本地                         重量级 / 云原生
  ──────────────────────────────────────────────────────────────>
  Chroma    Qdrant    Weaviate    Milvus    Pinecone

  嵌入到 app 中       单机部署          分布式集群      全托管云服务
  零配置              高性能            海量数据       零运维
  Python 优先         Rust 核心        10亿+向量      $$

选择建议:原型阶段用 Chroma,上线用 Qdrant 或 Milvus,不差钱且不想运维用 Pinecone。

数据库类型特点最佳场景GitHub Stars
Chroma嵌入式 / 轻量极简 API,Python 原生,零配置原型开发、小项目15K+
Qdrant单机 / 集群Rust 编写,高性能,过滤强,支持量化生产环境、中等规模20K+
Weaviate单机 / 集群GraphQL 接口,内置模块化(可内置 Embedding)企业应用、多模态11K+
Milvus分布式集群CNCF 项目,云原生,支持 100 亿级向量海量数据、大规模生产30K+
PineconeServerless 云服务全托管,零运维,弹性伸缩不想管基础设施商业产品
FAISS库(非数据库)Meta 出品,极致性能,纯内存高吞吐离线检索30K+

3.1.3 向量搜索的基本流程

  向量检索流程
  ┌─────────────────────────────────────────────────────────┐
  │                                                         │
  │  1. 索引阶段(离线,一次性)                               │
  │                                                         │
  │  文档 ──> Chunking ──> Embedding ──> 存入向量库          │
  │                                         │               │
  │                           ┌─────────────┘               │
  │                           ▼                             │
  │                     ┌──────────┐                        │
  │                     │ VectorDB │                        │
  │                     │ [768 维] │                        │
  │                     │ [768 维] │                        │
  │                     │ [768 维] │  ← 百万/亿级向量        │
  │                     │  ...     │                        │
  │                     └──────────┘                        │
  │                                                         │
  │  2. 查询阶段(在线)                                     │
  │                                                         │
  │  查询 "如何请假" ──> Embedding ──> [768 维向量]          │
  │                                        │                │
  │                                        ▼                │
  │                              ┌─────────────────┐       │
  │                              │ 相似度计算        │       │
  │                              │ cosine(query, d) │       │
  │                              │ Top-K=5          │       │
  │                              └────────┬────────┘       │
  │                                       │                 │
  │                                       ▼                 │
  │                              [Doc23, Doc47, Doc15, ...] │
  │                              score: 0.92, 0.88, 0.79   │
  └─────────────────────────────────────────────────────────┘

3.2 BM25 + 向量混合检索(Hybrid Retrieval)

3.2.1 纯向量检索的盲区

向量检索按"语义相似"工作,但有些情况下会失效:

场景问题示例
精确关键词"AK-47" 和 "步枪" 语义相似但不同用户搜索 "AK-47",可能返回 "M16 步枪"
专有名词罕见名词未被模型充分学习公司内部产品代号 "Project-X"
数字/代码Embedding 对精确数字不敏感"Error code 500" vs "Error 502"
短查询短查询信息量不够,向量表达能力弱"请假"(只有一个词)

3.2.2 BM25:经典的关键词检索

BM25 是搜索引擎的经典算法(TF-IDF 的现代改进版),按关键词匹配工作。
BM25 检索原理(简化)

  给定查询 "年假 政策"
  
  对每个文档,BM25 考虑三个因素:
  1. 词频(TF):"年假" 在文档中出现几次?
  2. 逆文档频率(IDF):"年假" 在整个语料库中是常见词还是稀有词?
  3. 文档长度归一化:长文档不会仅因为"更长"而获得更高分

  BM25 分数 = Σ (IDF × TF × (k1+1)) / (TF + k1×(1-b+b×docLen/avgDocLen))

  优点:擅长精确匹配、专有名词、数字
  缺点:不懂近义词、不懂语义("年假"和"带薪休假"对 BM25 是完全不同的)

3.2.3 混合检索架构

将 BM25 和向量检索的结果融合,取两者的交集/并集。混合检索 (Hybrid Retrieval) 架构示意如下:

                    用户查询: "2024年的销售报告"

            ┌────────────┴────────────┐
            ▼                         ▼
    ┌───────────────┐        ┌───────────────┐
    │  BM25 检索     │        │  向量检索       │
    │  (关键词匹配)   │        │  (语义匹配)     │
    │               │        │               │
    │  结果:        │        │  结果:         │
    │  Doc A (0.82) │        │  Doc C (0.91)  │
    │  Doc B (0.75) │        │  Doc A (0.85)  │
    │  Doc E (0.68) │        │  Doc D (0.78)  │
    └───────┬───────┘        └───────┬───────┘
            │                         │
            └────────────┬────────────┘


              ┌─────────────────────┐
              │  融合策略:           │
              │                     │
              │  1. RRF (Reciprocal │
              │     Rank Fusion)    │
              │  2. 加权求和        │
              │  3. 级联过滤        │
              └──────────┬──────────┘


              最终排序结果:
              Doc A (融合分最高)
              Doc C
              Doc D
              Doc B
              ...

融合策略详解:

策略公式优点缺点
RRF(推荐)score = Σ 1/(k+rank)无需调参,效果稳定不区分检索器权重
加权求和score = α×BM25 + (1-α)×Vector可调权重需要校准分数尺度
级联过滤BM25 初筛 → 向量精排速度快可能漏掉纯语义相关的文档

最佳实践:大多数生产环境使用 RRF 融合。α 值(向量权重)通常设为 0.7~0.8(即偏向语义搜索)。

3.3 Embedding Model 选择

Embedding 模型是 RAG 的"翻译官"——把文本翻译成向量。选对模型事半功倍。

3.3.1 评估维度

维度说明
检索精度MTEB(Massive Text Embedding Benchmark)排行榜上的分数
向量维度维度越高表达能力越强,但存储和搜索成本也越高
最大输入长度能否一次嵌入长文本(通常 512~8192 tokens)
多语言支持中文场景需要中文优化模型
推理成本本地推理 vs API 调用,速度和费用
领域适配通用模型 vs 领域微调模型(医疗、法律、代码)

3.3.2 主流 Embedding 模型

Embedding 模型选型指南 (2025-2026)

  API 服务(省心,有成本)           本地部署(免费,需 GPU)
  ─────────────────────────────────────────────────────────────>
  OpenAI        Cohere         BGE         GTE         E5
  text-embed    embed-v3       bge-m3      gte-Qwen2   multilingual
  
  voyager-2     1024 维        1024 维     2048 维     1024 维
  3072 维       (效果极好)     (中文最强)  (阿里)      (微软)
  (默认选择)
模型维度最大长度中文支持MTEB 排名类型
OpenAI text-embedding-3-large30728192中等Top 5API
OpenAI text-embedding-3-small15368192中等Top 15API(便宜 5 倍)
Cohere embed-v31024512Top 3API
BGE-M3(智源)10248192极好Top 10开源
GTE-Qwen2-7B(阿里)358432768极好Top 3开源(较大)
E5-mistral-7b(微软)409632768Top 5开源(较大)
Jina embeddings v310248192Top 15API/开源

BGE-M3 是由北京智源人工智能研究院(BAAI)推出的一款开源通用向量嵌入模型,名字中的 M3 代表其三大核心亮点:多功能(Multi-functionality)、多语言(Multi-linguality)和多粒度(Multi-granularity)。它在 RAG(检索增强生成)和语义搜索领域被广泛应用。

中文场景首选:BGE-M3(轻量)或 GTE-Qwen2(精度优先)。如果用 API,Cohere embed-v3 对中文支持较好。

3.3.3 Embedding 的使用注意事项

查询 vs 文档 Embedding

  许多 Embedding 模型区分"查询模式"和"文档模式":

  文档侧(离线索引时):
    "员工入职满1年享有5天年假" ──> [embed_document] ──> [768 维向量]

  查询侧(在线检索时):
    "年假几天?" ──> [embed_query] ──> [768 维向量]
       ↑                                ↑
    注意:查询和文档应该用不同的编码方式!

  原因:查询通常是短句/关键词,文档是长段落。如果同一个模型处理,
  查询向量可能"漂移"到与文档向量不同的子空间。

  带有"指令前缀"(Instruction-tuned Embedding):
    查询:embed_query("Represent this sentence for searching relevant passages: 年假几天?")
    文档:embed_document("年假政策:员工满1年享有...")

3.4 Reranking(重排序)

Reranking(重排序) 是指对初步检索出来的文档或文本块(Chunks)进行重新评分和排序的过程。它通常作为检索增强生成(RAG)或智能搜索系统中的“精排”环节,能够大幅提升最终输入给大语言模型(LLM)的内容精度。

3.4.1 为什么需要 Reranking?

在海量知识库中进行搜索时,系统通常遵循“先快后准”的两阶段策略

  1. 初筛(召回):使用向量检索或关键词匹配(如 BM25),从数百万条数据中快速捞出前 100 条可能相关的文档。这一步速度快,但不够精准。
  2. 重排(Reranking):使用专门的 Reranker 模型,将这 100 条结果与用户提问进行深度的语义比对,计算出极其精确的“相关性得分”,最后重新排序并选出最相关的 Top-K(例如前 5 条)喂给 LLM。

向量搜索的 Top-K 结果是"粗筛",因为:

  1. Embedding 是压缩表示,会丢失细节信息
  2. 相似度分数是全局计算的,不理解查询的具体意图
  3. 片段之间没有比较——排第二的可能其实比第一更相关

Reranking 是精排用一个更强的模型对 Top-K 候选重新打分

检索的两阶段架构

  第一阶段:粗筛(高召回)                   第二阶段:精排(高精度)
  ─────────────────────────               ────────────────────────
  从 100 万份文档中                      从 50 个候选中
  快速捞出 50 个候选                      精确找出最相关的 5 个

  方法:向量搜索 + BM25                   方法:Cross-Encoder Reranker
  特点:快、召回率高                      特点:慢但准、理解上下文
  耗时:~10ms                            耗时:~200ms(对 50 个文档)

3.4.2 Bi-Encoder vs Cross-Encoder

这是理解 Reranking 的关键概念:

Bi-Encoder(双编码器)              Cross-Encoder(交叉编码器)
─────────────────────────          ──────────────────────────────

  文档 ──> Encoder ──> Doc Vec      查询+文档 ──> Encoder ──> 相关分
  查询 ──> Encoder ──> Query Vec    (拼接在一起输入)      0.95
  
  然后计算:                              │
  score = cosine(Query Vec, Doc Vec)    │
    │                                   特点:
    │                                   • 查询和文档一起过模型
  特点:                               • 完全交互,精度极高
  • 文档向量可预先计算并存储             • 无法预先计算,每次都要推理
  • 检索时只需计算相似度,极快           • 慢 ~100 倍
  • 精度有损(压缩表示)                • 成本高

类比理解:

  • Bi-Encoder = 先给每个学生打分(标准化考试),再比较分数
  • Cross-Encoder = 派出一个面试官,一个一个地和学生深入交谈后打分

3.4.3 主流 Reranking 模型

模型特点语言速度
Cohere Rerank v3商业最强,支持多语言100+ 语言快 (API)
BGE-Reranker-v2-m3智源开源,中文好多语言中等
Jina Reranker v2多语言,效果好100+ 语言中等
mxbai-rerank轻量开源英文为主
ColBERT / colbertv2延迟交互,介于 Bi 和 Cross 之间英文较快
开源 / 自部署模型(推荐私有化知识库使用)
这些模型通常基于交叉编码器(Cross-Encoder)架构,直接将 Query(查询)和 Document(文档)拼接输入,虽然计算开销大,但语义理解精度极高。
  • BGE 系列 (BAAI):由北京智源人工智能研究院开发,包含 bge-reranker-largebge-reranker-v2-m3 等。其中 M3 版本强化了多语言和中英混合场景,是目前中文开源社区最受欢迎的模型之一。
  • Qwen 系列 (阿里通义千问):如 qwen3-rerank,依托阿里强大的底座能力,支持长文本和多语言,是目前性能顶尖的开源/API选择。
  • GTE 系列 (阿里):例如 gte-rerank-v2,针对自然语言处理中的重排序进行了专门优化。
  • Jina Reranker:由 Jina AI 提供(如 jina-reranker-v2),以极长的上下文处理能力和多语言支持闻名,适合复杂的文档检索。
  • Cohere v3 (开源版本):Cohere 开源的版本,性能表现优异。
  1. 商业闭源 API(免部署、开箱即用),适合不想维护 GPU 硬件、追求极致效果的企业应用。
  • Cohere Rerank:全球公认重排序效果最好的 API 之一,支持 100 多种语言,常作为评测各类重排模型的行业基准。
  • 通义千问 Rerank API:阿里云百炼平台提供的模型服务,集成方便,具备顶尖的问答检索与语义相似度排序能力。
  • Bocha Reranker (博查):国内优秀的语义排序模型,参数量小但推理速度快,性价比高。

代码示例(Cohere Rerank):

python
import cohere
co = cohere.Client("your-api-key")

results = co.rerank(
    query="年假如何申请?",
    documents=[chunk1, chunk2, chunk3, chunk4, chunk5],
    top_n=3,          # 返回前 3 个
    model="rerank-v3.5"
)

for r in results.results:
    print(f"Index: {r.index}, Score: {r.relevance_score}")

4. 增强与生成 — 上下文注入方式、引用与溯源

4.1 上下文注入方式

检索到了文档,怎么把它们"喂"给 LLM?这看似简单,其实是影响回答质量的关键。

4.1.1 直接拼接(Naive Concatenation)

最简单的方式:把所有检索到的片段直接拼接到 Prompt 里。

Prompt 模板(直接拼接)

  """
  你是一个知识助手。请根据以下参考文档回答用户问题。
  如果文档中没有相关信息,请如实告知。

  参考文档:
  ---
  [文档 1] {chunk_1}
  [文档 2] {chunk_2}
  [文档 3] {chunk_3}

  用户问题:{user_query}

  请基于以上文档回答,标注引用来源(文档编号)。
  """

优点:简单直接。 缺点

  • 文档之间可能有冲突信息,LLM 不知道该信谁
  • 无关文档(检索噪音)会占用宝贵的 Context Window
  • 文档顺序可能导致 LLM 对靠前的文档给予更多注意力(Primacy Bias)

4.1.2 Map-Reduce / Refine 模式

当检索到的文档太多(超出 Context Window)时使用:

  步骤 1 — Map:每个文档独立总结

  ┌─────────────────┐
  │ Chunk 1 ──> LLM ──> 摘要 1: "年假5天,入职满1年..."
  │ Chunk 2 ──> LLM ──> 摘要 2: "年假可跨年累计..."
  │ Chunk 3 ──> LLM ──> 摘要 3: "OA系统提交请假..."
  │ Chunk 4 ──> LLM ──> 摘要 4: "年假不休视为放弃..."
  │ Chunk 5 ──> LLM ──> 摘要 5: "特殊病假可转年假..."
  └─────────────────┘


  步骤 2 — Reduce:合并所有摘要生成最终答案

  "根据以下摘要回答:{摘要1}\n{摘要2}\n{摘要3}\n{摘要4}\n{摘要5}\n\n问题:{query}"


  Refine 模式(更精细)

  不是并发总结,而是顺序精炼:

  初始回答 = LLM(Chunk1, query)

  回答_v2  = LLM(回答, Chunk2)     ← 用新文档精炼已有回答

  回答_v3  = LLM(回答_v2, Chunk3)  ← 继续精炼

              ...

          最终回答

4.1.3 Metadata 增强

关键原则:永远把最相关、最权威的文档放在前面(或使用更醒目的标记),给 LLM 明确的优先级信号。

给每个检索片段附加元数据,帮助 LLM 更好地判断文档的可信度和相关性。

带 Metadata 的注入 Prompt

  """
  参考文档(按相关性排序):

  [文档 1] 来源:员工手册-v3.2 | 更新日期:2024-06-15 | 相关度:0.95
  内容:员工入职满1年享有5天带薪年假,工作年限每增加1年年假增加1天...

  [文档 2] 来源:OA系统帮助文档 | 更新日期:2024-03-01 | 相关度:0.88
  内容:年假申请方法:登录OA → 人事管理 → 请假申请 → 选择"年假"...

  [文档 3] 来源:2023年旧版手册(注意:可能已过期) | 更新日期:2023-01-01 | 相关度:0.75
  内容:年假制度:入职满1年享有3天年假...

  用户问题:{user_query}
  """

4.2 引用与溯源(Citation & Attribution)

RAG 的一大优势就是"可溯源"。好的引用设计让用户能验证信息的真实性。

4.2.1 引用格式

在 Prompt 中明确要求 LLM 输出引用标注:

System Prompt 中的引用指令

  """
  在回答时,你必须遵守以下引用规则:
  1. 每一条事实性陈述后,标注来源文档编号:例如 [1]
  2. 如果多个文档支持同一事实,列出所有来源:例如 [1][3]
  3. 不要因为任何原因编造不存在于文档中的信息
  4. 如果文档中信息相互矛盾,指出矛盾并告知用户:例如 "文档1和文档3给出了不同的年假天数,可能是版本更新导致的"
  """

回答示例:

根据公司政策,年假规定如下:

1. 入职满1年的员工享有5天带薪年假 [1]
2. 工作年限每增加1年,年假增加1天,上限15天 [1][2]
3. 年假申请需在OA系统中提交 [3]
4. 年假可跨年累计,但累计天数不超过当年应得年假的2倍 [2]

注:2023年旧版手册 [4] 中记载的年假天数为3天,但当前最新版(2024年6月更新)[1] 已调整为5天。

4.2.2 溯源策略对比

策略方法优点缺点
内联引用在回答文本中直接标注 [N]自然、精确需要 LLM 配合
脚注式回答末尾列出来源不打断阅读对应关系不够精确
侧边栏展示UI 侧边栏同步显示来源阅读体验好需要前端配合
高亮联动点击来源高亮对应文本交互性最强实现成本高

5. 高级 RAG — GraphRAG、Agentic RAG、Multi-hop RAG

基础 RAG(单次检索 + 单次生成)在许多复杂场景下存在局限。高级 RAG 方法试图解决这些问题。

5.1 GraphRAG(知识图谱 RAG)

5.1.1 基础 RAG 的"关系盲区"

基础 RAG 只能检索孤立的片段,看不到片段之间的关系

基础 RAG 看到的是:

  [片段 A] "张三是 Alpha 项目的技术负责人"
  [片段 B] "Alpha 项目是公司 AI 平台的核心组件"
  [片段 C] "公司 AI 平台部署在 AWS 上"

  LLM 把这三个片段拼接在一起,生成回答。
  
  但它无法回答这样的问题:
  "AI 平台的技术负责人需要向哪些团队汇报?"
  
  因为从三个片段中无法推断出团队汇报关系。

GraphRAG 的解法:先把文档变成知识图谱(节点 + 边),然后基于图谱检索。

文档 → 知识图谱转换

  原始文档:
  "张三是 Alpha 项目的技术负责人。Alpha 项目是公司 AI 平台的核心组件。
   公司 AI 平台由李四担任产品经理,部署在 AWS 上。张三向王五汇报。"

  提取出的知识图谱:

           ┌──────┐
           │ 王五  │
           └───┬──┘
               │ 汇报关系
           ┌───▼──┐      负责        ┌──────────┐
           │ 张三  │──────────────────>│ Alpha 项目 │
           └──────┘                   └─────┬────┘
                                           │ 是...核心组件
                                     ┌─────▼──────────┐
           ┌──────┐   产品经理        │ 公司 AI 平台    │
           │ 李四  │──────────────────>│               │───部署于───> AWS
           └──────┘                   └────────────────┘

5.1.2 GraphRAG 架构

GraphRAG 的流程有两个阶段:

  阶段一:索引阶段(离线)

  文档 ──> 实体识别 ──> 关系抽取 ──> 知识图谱构建 ──> 社区检测
         (NER)        (Relation Extr)  (Nodes+Edges)    (Community)


                                                   ┌──────────────┐
                                                   │  图数据库     │
                                                   │  (Neo4j等)   │
                                                   └──────────────┘

  阶段二:查询阶段(在线)

  用户查询 ──> 图谱搜索 ──> 相关知识 ──> LLM 生成答案
  

              ├── 局部检索(Local Search):从相关实体出发,收集邻居信息

              └── 全局检索(Global Search):对社区摘要进行聚合分析


  全局检索的具体流程:

  1. 将知识图谱划分为社区(Community):紧密相连的节点组
  2. 每个社区生成摘要(LLM):"这个社区主要涉及..."
  3. 查询时:
     a. 向量搜索找到相关社区摘要
     b. 将相关社区的完整信息加载到 Context
     c. LLM 综合社区信息生成答案

5.1.3 GraphRAG 的优劣势

优势劣势
理解实体间的关系和连接索引成本极高(每份文档都要 LLM 提取实体关系)
擅长"总结性"问题(如"三个主题是什么")对简单事实查询可能过度复杂
全局分析能力强图构建质量依赖实体关系提取的准确度
可发现隐藏的关联模式维护和更新图结构较复杂

适用场景

  • 需要理解跨文档关系的问题(如法律案件关联分析)
  • 高层次总结("公司所有项目的技术栈分布")
  • 探索性查询("列举与 AI 平台相关的所有决策人")

代表实现

  • Microsoft GraphRAG:微软开源,最知名的图 RAG 实现,支持全局/局部搜索
  • Neo4j + LangChain:用图数据库存储,结合 LangChain 的 RAG 流程

5.2 Agentic RAG(智能体 RAG)

5.2.1 从"被动检索"到"主动决策"

基础 RAG 是固定的管道:检索 → 增强 → 生成。Agentic RAG 把决策权交给 Agent——让 Agent 自己判断需要检索什么、怎么检索、是否需要二次检索。

基础 RAG vs Agentic RAG

  基础 RAG(固定管道):           Agentic RAG(自主决策):
  ┌─────────────────┐            ┌─────────────────────────┐
  │ 查询 → 检索 → 生成 │            │         Agent Loop        │
  └─────────────────┘            │                         │
                                 │  1. 分析问题             │
                                 │  2. 是否需检索?          │
                                 │     ├─ 是 → 去哪里找?    │
                                 │     └─ 否 → 直接回答      │
                                 │  3. 检索后信息够吗?       │
                                 │     ├─ 够 → 生成答案       │
                                 │     └─ 不够 → 换个方式再找 │
                                 │  4. 答案质量过关吗?       │
                                 │     ├─ 是 → 输出          │
                                 │     └─ 否 → 反思修正       │
                                 └─────────────────────────┘

5.2.2 Agentic RAG 的核心能力

能力说明示例
查询重写将用户原始查询改写为更利于检索的形式"那个蓝色按钮怎么不见了" → "设置页面中蓝色按钮的显示问题"
查询分解将复杂问题拆分为多个子查询"对比 A 和 B 的性能" → Q1: "A 的性能指标", Q2: "B 的性能指标"
工具选择决定用哪个知识库/工具检索"内部文档" vs "代码库" vs "API文档"
迭代检索第一轮检索不够 → 分析缺失 → 第二轮检索"找到了年假天数,但没找到申请流程" → 重新搜索"年假申请"
自我反思检查答案是否回答了问题,信息是否完整"已回答了天数但缺少申请方法,需要补充"
多源融合从不同来源获取信息并整合员工手册 + OA 系统文档 + 最新公告

5.2.3 Agentic RAG 的典型工作流

Agentic RAG 处理复杂查询示例

  用户问题:"我想了解公司年假政策,包括天数和申请流程,
            以及去年的年假还能不能用。"

  Agent 思考路径:
  
  Step 1: 分析 → 这个问题需要三个信息:天数、流程、跨年规则
           → 分解为 3 个子查询
           
  Step 2: ToolCall("search_knowledge_base", query="年假天数 入职年限")
           → 结果:5天起,每年+1天,上限15天 ✓
           
  Step 3: ToolCall("search_knowledge_base", query="年假申请流程 OA")
           → 结果:OA系统 → 人事管理 → 请假申请 ✓
           
  Step 4: ToolCall("search_knowledge_base", query="年假跨年 累计 过期")
           → 结果:可跨年累计,最多累计当年2倍
           → 但不确定"去年年假"的具体状态
           
  Step 5: 反思 → 关于"去年的还能不能用"信息不够
           → ToolCall("search_knowledge_base", query="2024年度年假 2025年 使用期限")
           → 结果:上一年度年假需在次年3月31日前使用完毕 ✓
           
  Step 6: 整合所有信息,生成最终答案,标注来源。

5.3 Multi-hop RAG(多跳检索)

5.3.1 什么是"多跳"?

某些问题需要"跳转"多次才能回答——答案分散在不同文档中,需要链式推理

单跳 vs 多跳

  单跳问题(一轮检索即可):
    Q: "公司年假有多少天?"
    → 检索 "年假天数" → 找到一块相关文档 → 回答

  多跳问题(需要多轮检索):
    Q: "Alpha 项目的技术负责人的直属上级是谁?"
    
    Hop 1: 检索 "Alpha 项目 技术负责人" 
           → 答案:张三
    
    Hop 2: 基于 Hop 1 的结果,检索 "张三 直属上级"
           → 答案:王五
    
    最终回答:Alpha 项目技术负责人张三的直属上级是王五。

5.3.2 Multi-hop RAG 的实现策略

策略一:ReAct 式迭代检索(最常用)

  Agent Loop:
    Thought: 我需要先知道 Alpha 项目的技术负责人是谁
    Action: search("Alpha 项目 技术负责人")
    Observation: 张三是 Alpha 项目技术负责人
    
    Thought: 现在我需要知道张三的直属上级
    Action: search("张三 直属上级 汇报")
    Observation: 张三向王五汇报
    
    Thought: 我已经有了完整的信息链,可以回答
    
    Answer: 王五

策略二:IRCoT(Interleaving Retrieval with Chain-of-Thought)

  检索和推理交错进行:
  检索1 "Alpha 项目" → 推理:"这是一个技术项目"
  → 检索2 "技术负责人 张三" → 推理:"张三管理这个项目"
  → 检索3 "张三 上级" → 推理:"上级是王五"
  → 回答
  
  每一步检索都基于前一步的推理结果来优化。

策略三:Tree-of-Thought + 检索

  同时探索多条推理路径:
                      Q: "谁是谁的上级?"

              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
         搜索"项目组"     搜索"技术部"    搜索"管理层"
              │               │               │
              ▼               ▼               ▼
          张三→李四       张三→王五        张三→赵六
           (不太确定)     (置信度高)      (可能性低)


                       确认答案:王五

5.3.3 Multi-hop RAG 的难点

难点说明缓解方法
错误传播第一跳的检索错误会传导到后续所有步骤每步引入验证步骤;保留多条候选路径
"链断"问题中间步骤无法找到相关信息设计回退策略;提前构建知识图谱
过度检索Agent 陷入无限循环搜索限制最大检索次数(通常 3~5 次)
效率多次 LLM 调用和检索,延迟高并行化独立检索;缓存中间结果

6. 总结

RAG 从简单的"检索+生成"演进为包含智能切分、混合检索、重排序、图谱推理和自主决策的完整体系,技术栈总览:


  层级                技术要点
  ═══════════════════════════════════════════════════════════
  高级 RAG     │  GraphRAG / Agentic RAG / Multi-hop RAG
  ─────────────┼────────────────────────────────────────────
  增强层       │  上下文注入策略 / Map-Reduce / 引用溯源
  ─────────────┼────────────────────────────────────────────
  精排层       │  Reranking (Cross-Encoder)
  ─────────────┼────────────────────────────────────────────
  检索层       │  向量检索 / BM25 / 混合检索 (RRF)
  ─────────────┼────────────────────────────────────────────
  Embedding   │  模型选择 / 维度权衡 / Query vs Doc
  ─────────────┼────────────────────────────────────────────
  预处理层     │  Chunking / 文档解析 / Metadata 标注
  ═══════════════════════════════════════════════════════════

关键要点:

  1. RAG 解决的是 LLM 知识盲区问题,不是"替代"微调,而是互补方案。
  2. Chunking 策略比很多人想象的更重要——差的切分等于差的检索。
  3. 混合检索(向量+BM25)是生产环境的最佳实践。
  4. Reranking 虽然多一步,但质量提升显著,性价比极高。
  5. Agentic RAG 是趋势——让 Agent 自主决定检索策略,而不是固定管道。