基于预训练语言模型的文本生成算法:检索增强生成(Retrieval-Augmented Generation, RAG)解码策略详解
字数 3370 2025-12-19 14:25:28
基于预训练语言模型的文本生成算法:检索增强生成(Retrieval-Augmented Generation, RAG)解码策略详解
好的,作为一个无所不知的大神,我随机为您讲解“检索增强生成”算法。它是在传统自回归生成基础上,引入外部知识库来增强生成质量的关键技术。以下是详尽的讲解:
第一步:算法背景与核心问题定义
- 传统生成模型的局限性:像GPT这样的纯自回归语言模型,其知识完全固化在庞大的静态模型参数中。这导致两个核心问题:一是模型可能生成“事实性错误”(幻觉),因为其参数记忆的知识可能过时或不准确;二是模型无法获取和引用训练数据之外的、最新的或特定领域的海量信息。
- 检索增强生成的提出:RAG的核心思想是“开放知识”,将生成过程分为“检索”和“生成”两阶段。在生成每个(或一组)答案时,模型会实时从一个外部知识库(如维基百科、内部文档)中检索相关文档,然后将检索到的文档作为上下文,与原始问题一起输入给生成模型,从而产生答案。这使模型具备了“查阅资料”的能力。
- 问题形式化:给定一个查询(query)q,目标是生成一个文本答案 a。RAG通过结合一个大型非参数知识库(通常是文档的向量化索引 D = {d₁, d₂, ..., dₖ})和一个参数化的生成模型 M(如BART、T5、GPT)来实现。
第二步:算法架构与核心组件拆解
RAG是一个两阶段流水线,其架构如下图所示(概念示意):
外部知识库 (D)
↓ (索引构建)
向量检索索引
↑
[查询 q] → 检索器 (Retriever) → 检索到Top-K相关文档 z
↓
[文档 z] + [查询 q] → 生成器 (Generator) → 答案 a
让我们深入每个组件:
-
检索器 (Retriever):
- 作用:给定查询 q,从知识库 D 中找出最相关的一组文档 z。这本质上是一个稠密向量检索问题。
- 实现:通常使用一个“双编码器”架构。
- 查询编码器 Eq:将查询 q 编码为一个稠密向量表示 v_q。常用预训练的BERT或RoBERTa的
[CLS]向量。 - 文档编码器 Ed:将知识库中的每个文档 d 预先编码为稠密向量 v_d,并存储到向量索引(如FAISS)中。
- 查询编码器 Eq:将查询 q 编码为一个稠密向量表示 v_q。常用预训练的BERT或RoBERTa的
- 检索过程:在检索时,计算查询向量 v_q 与所有文档向量 v_d 的相似度(通常用点积或余弦相似度),返回相似度最高的 K 个文档 {z₁, z₂, ..., zₖ} 作为检索结果。这个过程通常称为“最大内积搜索”。
-
生成器 (Generator):
- 作用:以检索到的文档 z 和原始查询 q 为条件,生成最终的文本答案 a。
- 输入构造:将检索到的文档(通常经过截断或选择)和原始查询拼接成一个增强的输入序列。常见格式为:
“问题: {q} 上下文: {z} 答案:” - 模型:通常使用一个序列到序列的预训练模型,如BART或T5。生成器负责理解融合后的上下文,并生成流畅、准确的答案。
第三步:核心工作流程与数学描述
RAG将生成概率建模为对检索文档的边缘化:
-
联合概率模型:生成答案 a 的概率,是所有可能的相关文档 z 贡献的积分(或求和)。
- 公式:p(a|q) = Σ_z p_η(z|q) * p_θ(a|q, z)
- p_η(z|q):这是检索器的分布,表示给定查询 q 时,文档 z 的相关性概率。通常用softmax在文档相似度上计算:p_η(z|q) ∝ exp(v_q · v_z)。实践中,由于知识库巨大,我们通常只取Top-K个文档来近似求和。
- p_θ(a|q, z):这是生成器的分布,表示在给定查询 q 和检索文档 z 的条件下,生成答案 a 的概率。这是一个标准的自回归生成过程:p_θ(a|q, z) = Π_{t=1}^{|a|} p_θ(a_t | a_{<t}, q, z),其中 a_t 是答案的第 t 个词。
-
两种生成模式:
- RAG-Sequence:这是上述公式的直接实现。生成器在生成整个答案序列 a 时,都依赖于同一个检索到的文档 z。即先根据 p_η(z|q) 采样或选取一个文档 z,然后由生成器基于这个固定的 z 生成完整的 a。
- RAG-Token:在生成答案的每一个词时,都可以重新“查阅”不同的文档。其概率公式为:p(a|q) = Π_{t=1}^{|a|} Σ_z p_η(z|q, a_{<t}) * p_θ(a_t | a_{<t}, q, z)。这允许模型在生成不同部分时融合不同来源的知识,但计算开销极大。通常用近似方法,例如每个token生成时使用相同的Top-K文档集,但允许生成器动态关注不同的文档。
第四步:训练策略详解
RAG的训练是端到端的,同时优化检索器和生成器。
- 训练数据:需要“问题-答案”对 (q, a) 的数据集。对于开放域问答,答案 a 通常简短。对于知识密集型任务,检索到的“支撑文档”(即包含答案的文档)是监督信号的一部分。
- 目标函数:最大化训练数据中真实答案的边际对数似然。
- 损失函数:L = - log p(a|q) = - log [ Σ_{z∈Top-K(q)} p_η(z|q) * p_θ(a|q, z) ]
- 这个损失函数同时包含检索器参数 η 和生成器参数 θ 的梯度。通过反向传播,可以同时学习如何找到相关文档,以及如何利用这些文档生成答案。
- 训练技巧:
- 困难负样本挖掘:在检索器的相似度计算中,除了正例文档(包含答案的文档),还需要加入负例文档。简单的随机负例效果有限,通常需要加入“困难负例”——那些与查询语义相似但不包含正确答案的文档,这能迫使检索器学会更精细的匹配。
- 知识库的预索引:文档编码器 Ed 可以固定(用预训练的BERT),也可以在训练中微调。如果微调,需要对知识库进行定期重新编码和索引,计算量较大。
第五步:推理/解码过程
推理时,我们通常不会对所有的 z 进行求和(因为计算量太大),而是采用高效的近似:
- 检索:用训练好的检索器,针对查询 q 从知识库 D 中检索出相似度最高的 K 个文档 {z₁, z₂, ..., zₖ}。K 是一个超参数,如5、10。
- 生成:将检索到的每个文档 z_i 分别与查询 q 拼接,输入生成器,得到 K 个候选答案的生成概率 p_θ(a|q, z_i)。
- 聚合:
- 对于RAG-Sequence,可以选择使 p_η(z_i|q) * p_θ(a|q, z_i) 最大的那个 (z_i, a) 对作为最终输出。更简单直接的做法是,只取检索分数最高的文档 z_top1,然后由生成器基于 z_top1 生成答案。
- 对于更高质量的生成,可以使用重排序:先用生成器为每个检索到的文档 z_i 生成一个候选答案 a_i,然后训练一个小的判别器模型对所有 (q, z_i, a_i) 三元组进行打分,选择综合分数最高的作为最终答案。
第六步:算法优势、挑战与应用
-
优势:
- 事实准确性高:答案来源于具体的、可追溯的文档,减少了模型“捏造”事实的可能。
- 知识可更新:只需更新外部知识库,无需重新训练庞大的生成模型,就能让模型获得最新知识。
- 可解释性:生成的答案可以关联到源文档,提供了参考依据,增强了可信度。
- 减少偏见:知识来源可控,可以减少模型从训练数据中学到的固有偏见。
-
挑战:
- 检索质量是关键瓶颈:如果检索器找不到相关文档,生成器“巧妇难为无米之炊”。
- 上下文长度限制:生成器(如Transformer)有输入长度限制,当检索到多篇长文档时,需要进行有效的选择和压缩。
- 计算延迟:相比纯生成模型,增加了检索步骤,延迟更高。
- 文档粒度与噪声:如何划分和索引文档(段落、篇章),以及如何处理检索文档中的无关信息(噪声),是工程上的挑战。
-
应用:
- 开放域问答
- 知识密集型对话系统
- 长文档/报告生成
- 事实核查
- 作为大语言模型(如ChatGPT)的插件,为其提供实时、准确的领域知识。
总结:检索增强生成(RAG)将信息检索与文本生成巧妙结合,通过“检索-阅读-生成”的范式,有效解决了大语言模型在事实性和知识更新上的痛点。其核心在于训练一个能与生成端协同优化的、强大的稠密向量检索器,并通过端到端的训练,使系统学会如何查找并利用外部知识来生成更优质的文本。