Back to Blog

RAG详解

RAG(Retrieval Augmented Generation),即 检索增强生成 ,是目前最常用的 AI 问答方案之一。其核心思想包含两个步骤: 检索(Retrieval) :从资料库中检索与用户问题相关的内容 生成(Generation) :基于检索到的内容来生成答案 假设要构建一个能回答公司产品问题的...

RAG 工作机制详解——一个高质量知识库背后的技术全流程

一、RAG 概述

1.1 什么是 RAG

RAG(Retrieval Augmented Generation),即检索增强生成,是目前最常用的 AI 问答方案之一。其核心思想包含两个步骤:

  1. 检索(Retrieval):从资料库中检索与用户问题相关的内容
  2. 生成(Generation):基于检索到的内容来生成答案

1.2 为什么需要 RAG

假设要构建一个能回答公司产品问题的智能客服,最直接的想法是:把产品手册随问题一起发给大模型。但这种方法在文档量很大(上百页甚至上千页)时会有严重问题:

问题说明
上下文窗口限制每个模型只能存储一定量的信息(上下文窗口大小),文档过长会导致模型”读了后面忘了前面”
推理成本高输入越多,成本越高,每次回答都要带上整本手册
推理速度慢输入越多,模型需要消化的内容越多,输出越慢

1.3 RAG 的解决思路

RAG 的核心改进是只把文档中相关的内容发给模型。例如在一份上百页的产品手册中,可能只有 3 个片段与用户问题相关,RAG 只需把这 3 个片段发给模型,而不是整个文档。

二、RAG 整体流程

RAG 流程分为两个部分:

┌─────────────────────────────────────────────────────────────────┐
│                        RAG 完整流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌─────────────────────┐         ┌─────────────────────┐       │
│   │   数据准备部分        │         │   回答部分           │       │
│   │  (提问前执行)       │         │  (提问后执行)       │       │
│   └──────────┬──────────┘         └──────────┬──────────┘       │
│              │                              │                  │
│              ▼                              ▼                  │
│   ┌─────────────────────┐         ┌─────────────────────┐       │
│   │  1. 分片 (Chunking) │         │  3. 召回 (Retrieval) │       │
│   └──────────┬──────────┘         └──────────┬──────────┘       │
│              │                              │                  │
│              ▼                              ▼                  │
│   ┌─────────────────────┐         ┌─────────────────────┐       │
│   │  2. 索引 (Indexing) │         │  4. 重排 (Reranking) │       │
│   └─────────────────────┘         └──────────┬──────────┘       │
│                                               │                  │
│                                               ▼                  │
│                                     ┌─────────────────────┐     │
│                                     │  5. 生成 (Generation)│     │
│                                     └─────────────────────┘     │
└─────────────────────────────────────────────────────────────────┘

三、数据准备部分

3.1 分片(Chunking)

分片是将文档切分为多个片段(Chunk)的过程。

常用分片方式

  • 字数分:如每 1000 字一个片段
  • 段落分:一个段落一个片段
  • 章节
  • 页码

分片粒度没有绝对标准,需根据实际场景调整。

3.2 索引(Indexing)

索引包含两个步骤:

  1. 使用 Embedding 模型将每个片段文本转换为向量
  2. 片段文本 + 对应向量存储到向量数据库

索引的本质流程:

文档片段 → Embedding模型 → 向量 → 存入向量数据库

四、核心概念详解

4.1 向量(Vector)

向量是数学中的基本概念,代表一个有大小有方向的量,通常用数组表示。

向量维度:数组中数字的个数

一维向量:[1]、[-3]
二维向量:[1, 2]、[-1, 2]
三维向量:[1, 2, 3]、[-1, 2, -3]

维度与可视化

  • 1维向量 → 一维坐标轴
  • 2维向量 → 二维坐标平面
  • 3维向量 → 三维立体空间
  • n维向量 → 无法可视化,但在 RAG 中通常使用几百到几千维的向量

维度越大,向量包含的信息越丰富,RAG 中使用高维向量是为了提高检索准确性。

4.2 Embedding(嵌入)

Embedding 是将文本转换为向量的过程。

核心特性:语义相近的文本,转换后的向量也相近。

示例(二维向量):

文本向量
khuatcoung喜欢吃水果[1, 2]
khuatcoung爱吃水果[1, 1]
天气真好[-3, -1]

前两句话的向量非常接近,说明语义相近;“天气真好”距离较远,语义不相关。

当用户询问”khuatcoung喜欢吃什么”时,先将问题做 Embedding,然后根据向量相似度找出语义相近的文本。

Embedding 模型:这不是 GPT-4、DeepSeek 等通用大模型,而是专用的 Embedding 模型。两者成本差异巨大。

常用 Embedding 模型排行榜:MTEB Leaderboard

4.3 向量数据库

向量数据库是专门用于存储和查询向量的数据库,为向量操作做了大量优化,并提供向量相似度计算等函数。

向量数据库表格结构(至少包含两列):

原始文本向量
khuatcoung喜欢吃水果[1, 2, 3, …]
今天天气不错[-1, 0, 5, …]

我们需要存储原始文本,因为最终返回给大模型的是原始文本,向量只是中间结果。

五、回答部分

5.1 召回(Retrieval)

召回是从所有片段中搜索与用户问题相关片段的过程。

完整流程

用户问题 → Embedding模型 → 问题向量 → 向量数据库 → Top 10 相关片段
  1. 用户问题发给 Embedding 模型,转换为向量
  2. 向量发送给向量数据库
  3. 向量数据库返回 10 个与问题最相似的片段

10 这个数字不是固定的,可以是 15、20 等,具体取决于场景。

5.2 向量相似度计算

向量数据库通过计算向量相似度来判断哪些片段与用户问题最相关。

三种主流方法

(1)余弦相似度(Cosine Similarity)

计算两个向量之间夹角的 cosine 值:

  • 夹角越小 → cosine 值越大 → 相似度越高

(2)欧式距离(Euclidean Distance)

计算两个向量之间的直线距离:

  • 距离越小相似度越高
    B
   /|
  / |
 /  |  ← 欧式距离
/   |
A————

(3)点积(Dot Product)

通过代数方式计算两个向量的相似度,既考虑方向关系,也考虑长度:

  • 向量方向一致 → 点积为正且越大 → 相似度越高
  • 向量方向相反 → 点积为负
  • 向量垂直 → 点积为 0
    B
   /
  /  ← 投影
 /
A———   ← 投影距离

计算方法:A 向 B 投影,投影距离 × 投影距离 = 点积值

5.3 重排(Reranking)

重排是从召回阶段返回的 10 个片段中,再精选出 3 个最相关的片段。

为什么需要两阶段筛选?

阶段使用方法成本速度准确率
召回向量相似度(余弦/欧氏/点积)
重排Cross-Encoder 模型

类比公司招聘

  • 召回 ≈ 简历筛选:从成千上万份简历中快速挑出 10 份看起来最优秀的(粗筛)
  • 重排 ≈ 面试:从 10 人中仔细挑选出最优秀的 3 人入职(精筛)

5.4 生成(Generation)

将以下内容一起发送给大模型:

  1. 用户原始问题
  2. 重排后筛选出的 3 个相关片段

大模型根据提供的内容生成最终答案。

六、完整链路回顾

6.1 提问前准备

┌──────────┐     分片      ┌──────────┐    索引      ┌──────────┐
│  文档资料  │ ──────────→ │  片段列表  │ ──────────→ │向量数据库│
└──────────┘              └──────────┘              └──────────┘

                                                    存储片段+向量
  1. 对相关资料进行分片
  2. 将所有片段发送给 Embedding 模型,生成对应向量
  3. 将向量存入向量数据库

6.2 用户提问后

┌─────────┐                    ┌────────────┐                    ┌─────────┐
│用户问题  │ ──Embedding──→  │  向量数据库  │ ← 10个相似片段 ←   │ Embedding│
└─────────┘                    └──────┬─────┘                    │  模型   │
                                      │                          └────┬────┘
                                      ↓                                 │
                               ┌────────────┐                          │
                               │  Cross-Encoder │                       │
                               │    (重排)      │                       │
                               └──────┬───────┘                          │
                                      │ Top 3                            │
                                      ↓                                  │
                               ┌────────────┐                           │
                               │   大模型    │ ← 用户问题 + 3个片段       │
                               │  (生成答案) │                           │
                               └────────────┘

详细步骤

  1. 用户问题 → Embedding 模型 → 问题向量
  2. 问题向量 → 向量数据库 → 返回 Top 10 最相似片段
  3. 10 个片段 → Cross-Encoder 模型 → 精选 Top 3
  4. 用户问题 + 3 个片段 → 大模型 → 最终答案
商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。本文采用 CC BY-NC-SA 4.0 - 非商业性使用 - 相同方式共享 4.0 国际 进行许可。

Comments

Notes, questions, and follow-ups are welcome here.

Comments are temporarily unavailable because WALINE_SERVER_URL or PUBLIC_WALINE_SERVER_URL is not configured.