Files
2026-05-16 17:16:51 +08:00

597 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: RAG检索增强生成的数学体系
draft: false
tags:
- RAG
- Retrieval-Augmented-Generation
- 检索
- 知识库
- 大语言模型
---
# RAG检索增强生成的数学体系
---
## 一、RAG 的核心问题
### 1.1 语言模型的参数知识局限
**语言模型的参数知识**
语言模型 $P_\theta(y|x)$ 中的知识以**参数权重**的形式存储:
$$\theta \rightarrow \text{参数化的知识} \rightarrow P_\theta(y|x) \tag{1.1}$$
**问题**
1. **知识陈旧**:训练数据有截止日期,无法回答"今天天气如何"
2. **知识不准确**:模型可能产生"幻觉"hallucination生成看似合理但错误的内容
3. **不可追溯**:无法提供答案的来源,用户无法验证
### 1.2 非参数知识 vs 参数知识
**参数知识parametric knowledge**
- 存储在模型权重中
- 通过训练获得
- 难以快速更新
**非参数知识non-parametric knowledge**
- 存储在外部数据库中
- 通过检索获得
- 可以实时更新
**核心思想**
> RAG 将两者结合:让模型学会使用外部检索系统来获取知识,而不是完全依赖参数记忆。
**RAG 标准流水线**
```
文档 → 分块(Chunking) → 编码 → 向量库
查询 → 编码 → 检索 → 重排序(Rerank) → 拼接 → LLM生成
```
**文本分块Chunking**是 RAG 第一步必备流程:
1. **固定长度分块**:按 token 数切分(如 512 tokens
2. **语义分块**:按句子/段落边界切分,保持语义完整
3. **重叠滑动窗口**:相邻块重叠 10%~20%,避免语义割裂
**RAG知识融合边界**:区分「检索知识优先」与「模型原生知识优先」的 Prompt 调控策略。当二者冲突时,优先保证检索内容的事实性,模型原生知识作为补充参考。
### 1.3 RAG 的形式化问题
**定义RAG 目标)**
给定输入 $x$,从外部知识库 $\mathcal{K}$ 中检索相关文档 $z \in \mathcal{K}$,然后基于检索结果生成回答:
$$P(y | x) = \sum_{z \in \mathcal{K}} P(y | x, z) \cdot P(z | x) \tag{1.2}$$
或者使用 top-$k$ 检索近似:
$$P(y | x) \approx P(y | x, z_1, \ldots, z_k) \quad \text{where } z_i = \text{TopK}(x, i) \tag{1.3}$$
**与标准 LM 的区别**
标准 LM$P(y|x)$
RAG$P(y|x, z_{1:k})$ where $z_{1:k} = \text{Retrieve}(x, k)$
---
## 二、检索系统的数学框架
### 2.1 检索任务的定义
**定义(检索任务)**
给定查询 $x$ 和文档集合 $\mathcal{K} = \{d_1, \ldots, d_N\}$,学习一个检索函数:
$$\text{score}(x, d) = s \in \mathbb{R} \tag{2.1}$$
使得相关文档的分数高于不相关文档。
**数学目标**
$$\arg\max_{d \in \mathcal{K}} \text{score}(x, d) \approx \arg\max_{d \in \mathcal{K}} P(\text{relevant}(d, x)) \tag{2.2}$$
### 2.2 稠密检索Dense Retrieval
**稠密检索的核心思想**
将查询和文档都编码为稠密向量,然后在向量空间中做相似度检索。
**定义(编码器)**
- 查询编码器:$q = \text{Enc}_q(x) \in \mathbb{R}^d$
- 文档编码器:$d = \text{Enc}_d(z) \in \mathbb{R}^d$
**定义(相似度分数)**
$$\text{score}(x, z) = \langle q, d \rangle = q^\top d = \|q\| \|d\| \cos\theta \tag{2.3}$$
其中 $\theta$ 是向量夹角。
**使用余弦相似度**
$$s = \frac{q^\top d}{\|q\| \cdot \|d\|} \tag{2.4}$$
### 2.3 双编码器架构
**架构Bi-Encoder**
```
Query x → Enc_q → q ∈ R^d
Doc z → Enc_d → d ∈ R^d
score = q · d
```
**独立编码**
查询和文档使用**独立的编码器**,这使得预计算文档 embedding 成为可能。
**训练损失**
使用对比损失训练编码器:
$$\mathcal{L} = -\log \frac{\exp(\text{score}(q_i, d_i^+))}{\exp(\text{score}(q_i, d_i^+)) + \sum_{j} \exp(\text{score}(q_i, d_j^-))} \tag{2.5}$$
其中 $d_i^+$ 是正例文档,$d_j^-$ 是负例文档。
### 2.4 交叉编码器 vs 双编码器
**交叉编码器Cross-Encoder**
```
[Query; Doc] → CrossEncoder → score ∈ R
```
将查询和文档一起输入,输出它们的相似度分数。
**对比**
| 维度 | 双编码器 | 交叉编码器 |
|------|---------|----------|
| **速度** | 快(预先计算 doc embedding | 慢(实时编码) |
| **精度** | 中等 | 高 |
| **适合场景** | 大规模检索 | 重排序Rerank |
**TF-IDF 公式**
词频-逆文档频率:
$$\text{tf-idf}(t, d) = \tf(t, d) \cdot \log\frac{N}{df_t} \tag{2.5}$$
其中 $\tf(t, d)$ 是词 $t$ 在文档 $d$ 中的词频,$df_t$ 是包含词 $t$ 的文档数。
### 2.5 稀疏检索BM25
**稀疏检索的核心思想**
使用词频统计来表示查询和文档。
**BM25 公式**
$$\text{score}_{\text{bm25}}(x, d) = \sum_{i=1}^n \log\left(\frac{N - df_i + 0.5}{df_i + 0.5}\right) \cdot \frac{tf_i \cdot (k_1 + 1)}{tf_i + k_1 \cdot \left(1 - b + b \cdot \frac{|d|}{\text{avgdl}}\right)} \tag{2.6}$$
其中:
- $N$:文档总数
- $df_i$:包含词 $i$ 的文档数
- $tf_i$:词 $i$ 在文档 $d$ 中的出现次数
- $|d|$:文档长度
- $\text{avgdl}$:知识库内所有文档平均长度
- $k_1, b$:超参数(英文通常 $k_1=1.5, b=0.75$;中文通常 $k_1=2.0, b=0.8$
**优点**:无需训练,可解释性强
### 2.6 混合检索
**混合检索**
结合稠密检索和稀疏检索:
$$\text{score}_{\text{fusion}} = \alpha \cdot \text{score}_{\text{dense}} + (1-\alpha) \cdot \text{score}_{\text{bm25}} \tag{2.7}$$
其中 $\alpha \in [0, 1]$ 是权重。通用场景 $\alpha=0.5$;语义类问题调高稠密权重 $\alpha=0.7$;实体关键词检索调高 BM25 权重 $\alpha=0.3$。
**优势**
- 稠密检索捕捉语义相似性
- BM25 捕捉词汇匹配
- 两者互补
### 2.7 ANN 近似最近邻检索
**问题**:向量库规模庞大(百万/亿级)时,全量计算相似度开销巨大。
**解决方案**近似最近邻ANN检索在精度和速度之间做权衡。
**常用 ANN 算法**
| 算法 | 核心思想 | 特点 |
|------|---------|------|
| **HNSW** | 多层跳表结构,逐层收缩搜索区域 | 速度快,内存占用中等 |
| **IVF** | 倒排索引,将向量聚类后先定位簇 | 构建快,适合动态更新 |
| **PQ** | 乘积量化,将高维向量压缩为短编码 | 内存占用极低,精度依赖码本 |
**HNSW 检索过程**
```
输入:查询向量 q搜索参数 ef, m
输出Top-k 近邻
1. 从最上层开始,在当前层贪心搜索
2. 找到当前层的最近邻后,进入下一层
3. 重复直到最底层
4. 使用 ef 参数做更大范围的贪婪搜索
```
**检索质量评估指标**
- **召回率Recall@k**ANN 返回的 Top-k 中有多少落在真实 Top-k 中
- **QPS**:每秒查询数,衡量检索速度
### 2.8 混合检索的实战流程
```
查询 → 编码 → 并行检索(稠密 + 稀疏)
结果融合RRF 或 加权)
重排序Rerank
Top-k 送入 LLM
```
**倒数排名融合RRF**
$$score_{\text{RRF}}(d) = \sum_{i=1}^K \frac{1}{k + \text{rank}_i(d)} \tag{2.8}$$
其中 $k$ 是常数(通常 $k=60$$\text{rank}_i(d)$ 是文档 $d$ 在第 $i$ 个检索系统的排名。
---
## 三、RAG 的生成框架
### 3.1 序列生成模型
**RAG-Sequence**Lewis et al., 2020
整个生成序列只使用一个检索结果:
$$P(y|x) = \sum_{z \in \mathcal{K}} P(z|x) \cdot \prod_{t=1}^T P(y_t | x, z, y_{<t}) \tag{3.1}$$
**RAG-Token**
每个 token 生成时都可以使用检索结果:
$$P(y|x) = \prod_{t=1}^T \sum_{z \in \mathcal{K}} P(z|x) \cdot P(y_t | x, z, y_{<t}) \tag{3.2}$$
**区别**
- RAG-Sequence整个回答基于同一个检索文档
- RAG-Token每个词可以参考不同的检索文档
### 3.2 生成器的数学形式
**定义(生成器)**
给定查询 $x$ 和检索文档 $z$,生成器 $G$ 输出回答:
$$y = G(x, z) \tag{3.3}$$
典型实现是 seq2seq 模型(如 T5、BART
**注意**:检索文档 $z$ 接到 $x$ 后面作为输入:
$$\text{input} = [x; \text{sep}; z] \tag{3.4}$$
### 3.3 端到端训练的挑战
**问题**:同时训练检索器 $\text{Enc}$ 和生成器 $G$ 非常困难。
**解决方案:两阶段训练**
**阶段 1独立训练检索器**
- 使用对比学习等方法预训练检索器
- 或使用预训练的稠密检索模型(如 DPR
**阶段 2固定检索器训练生成器**
- 冻结检索器参数
- 只更新生成器参数
### 3.4 推理时的 RAG 流程
**Algorithm: RAG Inference**
```
输入:查询 x知识库 K
输出:生成回答 y
1. 检索阶段:
q = Enc_q(x) # 编码查询
scores = [q · d_i for d_i in K] # 计算相似度
top_k = argmax_k(scores) # 取 top-k 文档
2. 生成阶段:
for each retrieved doc z_i:
input_i = [x; SEP; z_i] # 拼接输入
y_i = G(input_i) # 生成回答
p_i = P(y_i | x, z_i) # 计算概率
3. 聚合阶段:
y* = argmax_i P(y_i | x) # 选择概率最高的
# 或者使用 token-level 聚合RAG-Token
```
---
## 四、检索器的训练
### 4.1 对比学习的框架
**定义(对比学习目标)**
对于查询 $q$ 和相关文档 $d^+$、不相关文档 $d^-$,损失函数为:
$$\mathcal{L} = -\log \frac{\exp(\text{score}(q, d^+))}{\exp(\text{score}(q, d^+)) + \sum_{d^-} \exp(\text{score}(q, d^-))} \tag{4.1}$$
**物理意义**:最大化正例的相似度,同时压制负例的相似度。
### 4.2 DPR 的训练
**DPRDense Passage Retrieval**Karpukhin et al., 2020的训练目标
$$\mathcal{L} = -\log \frac{\exp(q \cdot d^+)}{\exp(q \cdot d^+) + \sum_{i=1}^k \exp(q \cdot d_i^-)} \tag{4.2}$$
其中 $\{d_i^-\}_{i=1}^k$ 是 batch 内负例。
**DPR 温度系数**
检索时使用温度参数控制相似度分布的锐度:
$$P(d | q) = \frac{\exp(\text{score}(q, d) / \tau)}{\sum_{d'} \exp(\text{score}(q, d') / \tau)} \tag{4.3}$$
其中 $\tau$ 是温度系数:
- $\tau \to 0$:近似 argmax只返回最相关的文档
- $\tau = 1$:保持原始相似度分布
- $\tau > 1$:分布更平滑,增加检索多样性
**批量负采样**
从同一个 batch 中选取其他查询的正例作为当前查询的负例。
### 4.3 难例挖掘
**难例Hard Negative**
简单的负例(与查询完全不相关)对训练帮助有限。需要挖掘"难例"——与查询相关但不正确的内容。
**方法**
1. **BM25 负采样**BM25 返回的相关文档作为难例
2. **在线难例挖掘**:训练过程中动态选择难例
3. **跨批次难例**:使用其他 GPU 上的正例作为负例
### 4.4 训练中的问题
**问题 1检索器与生成器的目标不一致**
- 检索器优化检索相关性
- 生成器优化生成质量
- 两者可能不匹配
**解决方案**
- 使用生成器的反馈来更新检索器rewards from generator
- 或使用端到端训练但冻结检索器
**问题 2知识库的覆盖度**
如果知识库不包含正确答案,检索无法找到正确文档。
**解决方案**
- 定期更新知识库
- 使用多个知识库
---
## 四、检索器的训练(续)
### 4.5 无监督冷启动方案
**问题**:新知识库没有相关性标注数据,如何启动检索器?
**解决方案:无监督冷启动**
**方法 1反向推理生成伪标签**
```
1. 从知识库中采样文档对 (d_i, d_j)
2. 用预训练语言模型判断:如果 "d_i 相关于 d_j",生成伪标签
3. 用伪标签训练初始检索器
```
**方法 2BM25 作为伪监督信号**
- 用 BM25 检索结果作为"弱标签"
- 假设 BM25 返回的 Top-1 是相关的(噪声较大但可作为起点)
**方法 3批量预训练编码器**
- 在大规模无标注文本上用对比学习预训练编码器
- 再在任务相关数据上微调
**方法 4领域自适应**
- 使用领域内无监督数据做对比学习
- 如医疗领域:医学教科书 + 医学问答对
### 4.6 端到端联合训练
**问题**:两阶段训练的检索器和生成器目标可能不一致。
**联合训练目标**
$$\mathcal{L} = \mathcal{L}_G + \lambda \cdot \mathcal{L}_R \tag{4.4}$$
其中 $\mathcal{L}_G$ 是生成器损失,$\mathcal{L}_R$ 是检索器损失。
**挑战**
- 检索器的梯度难以反向传播(离散的最近邻操作)
- 解决方案:使用软化近似(如软最大相似度)
**REPLUGLesci et al., 2023的做法**
$$P(z | x) = \text{softmax}_z(\text{score}(q, d) / \tau) \tag{4.5}$$
将硬最近邻替换为软概率分布,使检索器可微。
---
## 五、RAG 与 LLM 的上下文适配
### 5.1 LLM 上下文长度适配
**问题**:检索返回的文档可能超出 LLM 的上下文窗口限制。
**主流解决方案**
| 方法 | 核心思想 | 适用场景 |
|------|---------|---------|
| **截断法** | 直接截断到最大长度 | 简单快速,丢失尾部信息 |
| **摘要压缩** | 用 small LLM 将文档摘要后再输入 | 保留核心信息,需额外模型 |
| **分层检索** | 先检索章节,再检索段落 | 大型文档,知识密集型 |
| **令牌平铺** | 将文档分割后并行处理再聚合 | 需模型支持长上下文 |
**摘要压缩的具体做法**
$$z_{\text{compressed}} = \text{Summarizer}(z, \text{max\_tokens}) \tag{5.1}$$
其中 $\text{max\_tokens}$ 是 LLM 上下文能容纳的最大令牌数。
**分层检索流程**
```
1. 文档库预先建立篇章结构索引
2. 检索时先定位相关章节(粗粒度)
3. 再在章节内检索具体段落(细粒度)
4. 只将最相关的段落送入 LLM
```
### 5.2 重排序架构
**背景**:混合检索后返回的候选文档可能存在相关性排序不准确的问题。
**重排序Re-ranking**
```
检索阶段 → 候选文档 Top-100
Cross-Encoder 打分
重排后 Top-k
送入 LLM
```
**Cross-Encoder 的评分公式**
$$\text{score}_{\text{cross}}(x, d) = \text{CrossEncoder}([x; \text{SEP}; d]) \tag{5.2}$$
其中 $[x; \text{SEP}; d]$ 是查询和文档的拼接输入。
**与双编码器的对比**
| 维度 | 双编码器 | Cross-Encoder 重排 |
|------|---------|-------------------|
| **速度** | 快(预先计算 embedding | 慢(实时编码) |
| **精度** | 中等 | 高 |
| **适合场景** | 大规模初筛 | 精确排序 |
**BGE-Reranker** 等模型是典型的 Cross-Encoder 架构,在 HuggingFace 上可直接调用。
---
## 六、RAG 的评估
### 6.1 检索质量的评估
**命中率Hit Rate**
$$\text{HitRate}@k = \frac{\text{正确相关文档出现在Top-k内的样本数}}{\text{总查询样本数}} \tag{6.1}$$
**平均倒数排名MRR**
$$\text{MRR} = \frac{1}{|Q|} \sum_{q \in Q} \frac{1}{\text{rank}(q)} \tag{6.2}$$
**NDCGNormalized Discounted Cumulative Gain**
$$\text{NDCG}@k = \frac{1}{\text{IDCG}@k} \sum_{i=1}^k \frac{2^{\text{rel}_i} - 1}{\log_2(i+1)} \tag{6.3}$$
其中 $\text{IDCG}@k$ 是理想归一化折损累计增益Ideal DCG
### 6.2 生成质量的评估
**端到端评估**
在问答、摘要等任务上评估生成质量:
- Exact MatchEM
- F1 Score
- ROUGE-L
- BLEU
### 6.3 幻觉问题
**RAG 减少幻觉**
RAG 通过提供真实文档作为上下文,显著减少了模型编造内容的幻觉问题。
**但 RAG 不是万能的**
模型仍可能:
1. **误解检索结果**:检索到的文档不包含答案,但模型强行从中提取
2. **忽视不匹配的检索**:检索结果相关但模型没有正确使用
---
## 七、数学公式速查
### 7.1 RAG 核心公式
**RAG-Sequence**
$$P(y|x) = \sum_{z} P(z|x) \cdot \prod_t P(y_t | x, z, y_{<t}) \tag{7.1}$$
**RAG-Token**
$$P(y|x) = \prod_t \sum_z P(z|x) \cdot P(y_t | x, z, y_{<t}) \tag{7.2}$$
### 7.2 检索公式
**余弦相似度**
$$\text{score}(x, z) = \frac{q^\top d}{\|q\| \|d\|} \tag{7.3}$$
**BM25**
$$\text{score} = \sum_i \log\frac{N-df_i+0.5}{df_i+0.5} \cdot \frac{tf_i(k_1+1)}{tf_i+k_1(1-b+b|d|/avgdl)} \tag{7.4}$$
**TF-IDF**
$$\text{tf-idf}(t, d) = \tf(t, d) \cdot \log\frac{N}{df_t} \tag{7.5}$$
### 7.3 DPR 对比损失
$$\mathcal{L} = -\log \frac{\exp(q \cdot d^+)}{\exp(q \cdot d^+) + \sum_j \exp(q \cdot d_j^-)} \tag{7.6}$$
---
## 八、总结
**RAG 的核心价值**
1. **扩展知识边界**:可以接入实时更新的知识库
2. **减少幻觉**:提供可追溯的真实来源
3. **知识可更新**:无需重训练即可更新知识
**关键组件**
| 组件 | 核心方法 | 挑战 |
|------|---------|------|
| **检索器** | 双编码器 + 对比学习 | 检索器与生成器目标对齐 |
| **生成器** | seq2seq 模型(如 T5 | 如何有效融合检索内容 |
| **知识库** | 向量数据库 | 知识覆盖度和更新 |
**RAG 与其他方法的对比**
| 方法 | 知识更新 | 可解释性 | 计算成本 |
|------|---------|---------|---------|
| **参数 LM** | 需要重训练 | 低 | 高(训练) |
| **RAG** | 更新数据库 | 高 | 中等 |
| **Fine-tuning** | 需要重训练 | 低 | 高(训练) |
---
**延伸阅读**
1. Lewis et al., "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks" (NeurIPS 2020)
2. Karpukhin et al., "Dense Passage Retrieval for Open-Domain Question Answering" (EMNLP 2020)
3. Izacard & Grave, "Distilling Dense Retrieval for Open-Domain Question Answering" (TACL 2021)
4. Gao et al., "Precise Zero-shot Dense Retrieval without Relevance Labels" (ICLR 2023)
5. Khattab et al., "Demonstrate- Search-Predict: Knowledge Retrieval + Language Model" (2023)