RAG检索增强生成——让大模型学会翻书作答:读《Retrieval-Augmented Generation》论文有感
一、大模型的知识困境
作为一个 C++ 工程师,我一直在思考一个问题:为什么大语言模型知道很多东西,但又常常"胡说八道"?
比如,如果你问 GPT-3 "2024年美国总统是谁",它可能会给你一个错误的答案——因为它的知识截止到2021年。更糟糕的是,它可能会编造一个不存在的事实,还说得煞有介事。
这就是大模型的"知识困境":
- 知识过时:训练完成后,参数就被冻结了,无法获取最新信息
- 容易幻觉:经常生成看似合理但实际上错误的内容
- 缺乏可解释性:无法追溯答案的来源
- 专业知识不足:对于冷门或专业领域的知识,模型的准确性大打折扣
这正是《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》这篇论文要解决的问题。
二、RAG 的核心思想
2.1 "开卷考试"vs"闭卷考试"
论文用一个非常形象的比喻来解释 RAG 的核心思想:
闭卷考试:考生只能依靠自己的记忆作答,知识有限且可能不准确。
开卷考试:考生可以查阅参考资料,答案更准确、更可靠。
传统的大语言模型就像参加闭卷考试,所有知识都存储在参数中。而 RAG(Retrieval-Augmented Generation) 则让模型参加开卷考试——在生成答案之前,先从外部知识库中检索相关信息。
2.2 RAG 的架构
RAG 的架构可以概括为"检索器 + 生成器 + 知识库"三位一体:
1 | ┌─────────────────────────────────────────────────────────────────────┐ |
2.3 两个关键组件
1. 检索器(Retriever)—— DPR
使用 Dense Passage Retrieval(DPR) 作为检索器:
- 使用双编码器(bi-encoder)将问题和文档编码到同一个向量空间
- 问题编码:
q = BERT_q(question) - 文档编码:
p = BERT_p(passage)(预先计算并存储在 FAISS 索引中) - 通过点积相似度检索 top-k 相关文档:
score(q, p) = q^T p
2. 生成器(Generator)—— BART
使用 BART-large 作为生成器:
- 将查询和检索到的文档一起输入
- 基于检索到的知识生成答案
- 支持两种模式:RAG-Sequence 和 RAG-Token
三、RAG 的两种变体
3.1 RAG-Sequence(序列级检索)
特点:整个生成序列使用同一批检索文档。
1 | ┌─────────────────────────────────────────────────────────────┐ |
适用场景:答案相对简短,所需知识集中在少数文档中。
3.2 RAG-Token(Token级检索)
特点:每个 token 的生成可以使用不同的检索文档。
1 | ┌─────────────────────────────────────────────────────────────┐ |
适用场景:答案较长,需要整合多个文档的信息。
论文实验表明,RAG-Token 在大多数任务上表现更好,因为它能更灵活地利用不同文档的信息。
四、实验结果
4.1 开放域问答
论文在多个开放域 QA 任务上进行了实验:
| 任务 | RAG-Sequence | RAG-Token | 纯 BART |
|---|---|---|---|
| Natural Questions | 46.2% | 50.3% | 37.5% |
| WebQuestions | 58.8% | 64.3% | 48.9% |
| TriviaQA | 60.5% | 66.5% | 52.0% |
关键发现:
- RAG-Token 在所有任务上都优于 RAG-Sequence
- RAG 显著超越纯 BART 基线(+10%~15%)
- 626M 参数的 RAG 超越了 110B 参数的模型
4.2 知识密集型生成
在知识密集型生成任务上,RAG 生成的文本更具体、更多样化、更真实:
| 评估维度 | RAG | 纯 BART |
|---|---|---|
| 事实一致性 | 更高 | 较低 |
| 多样性 | 更高 | 较低 |
| 具体性 | 更高 | 较低 |
4.3 知识热替换
一个非常有趣的实验:论文测试了 RAG 在知识库更新后的表现。
实验设置:
- 使用旧版维基百科训练 RAG
- 更新维基百科中的某些事实(如某个人的职位变化)
- 不重新训练模型,只更新知识库
- 测试模型能否回答更新后的问题
结果:RAG 能够正确回答更新后的问题,而纯生成模型仍然使用旧知识。
这证明了 RAG 的一个重要优势:无需重新训练即可更新知识。
五、我的实践:用 Python 实现简单的 RAG
作为一个 C++ 工程师,我喜欢用代码来验证理论。让我用 Python 实现一个简单的 RAG 系统:
1 | from openai import OpenAI |
准备一些示例文档:
1 | documents = [ |
测试一下:
1 | query = "埃菲尔铁塔是什么时候建造的?" |
运行结果:
1 | 埃菲尔铁塔建于1887年至1889年。答案来源于:"埃菲尔铁塔位于法国巴黎,建于1887年至1889年,是为1889年世界博览会建造的。" |
再测试一个需要整合多文档信息的问题:
1 | query = "2024年巴黎奥运会期间,游客可以参观哪些著名景点?" |
运行结果:
1 | 2024年巴黎奥运会期间,游客可以参观埃菲尔铁塔和卢浮宫等著名景点。答案来源于: |
可以看到,RAG 系统成功地检索到了相关文档,并基于这些文档生成了准确的答案。
六、RAG 的优势与局限
6.1 核心优势
1. 知识可实时更新
- 只需更新知识库,无需重新训练模型
- 适用于需要及时获取最新信息的场景
2. 减少幻觉
- 答案基于真实文档生成,事实性更强
- 可追溯答案来源,增加可信度
3. 小模型也能有大能力
- 626M 参数的 RAG 超越了 110B 参数的纯生成模型
- 降低了部署成本
4. 可解释性
- 可以清楚地看到答案来源于哪些文档
- 便于验证和调试
6.2 局限性
1. 检索质量依赖于知识库
- 如果知识库中没有相关信息,RAG 也无法给出正确答案
- 需要高质量、全面的知识库
2. 检索速度
- 虽然使用 FAISS 加速,但大规模知识库的检索仍有延迟
- 需要权衡检索速度和召回率
3. 生成质量依赖于检索结果
- 如果检索到错误或不相关的文档,会影响生成结果
- 需要优化检索算法
4. 长文档处理
- 当前 RAG 通常处理短文档(约100词)
- 对于长文档的理解能力有限
七、RAG 的扩展与变体
论文发表后,研究者们提出了很多 RAG 的扩展:
| 变体 | 说明 |
|---|---|
| HyDE | 使用生成器生成假设答案,再用假设答案检索文档 |
| REALM | 使用检索到的文档增强预训练过程 |
| RETRO | 将检索到的文档融入 Transformer 的注意力机制 |
| FiD | 将多个文档的信息融合后再生成答案 |
| ReAct | 将推理和行动(检索)结合起来 |
这些变体在不同场景下各有优势,但核心思想都是"先检索、再生成"。
八、作为工程师的思考
8.1 RAG 对工程实践的启示
作为一个 C++ 工程师,读这篇论文让我有以下几点思考:
1. 模块化设计的价值
- RAG 将检索和生成分离,各自优化
- 这种模块化设计让系统更灵活、更易于维护
2. 参数化 vs 非参数化
- 参数化记忆(模型参数)适合存储通用知识和推理能力
- 非参数化记忆(外部知识库)适合存储具体、易变的知识
- 两者结合可以兼顾效率和灵活性
3. 知识管理的重要性
- 高质量的知识库是 RAG 系统的基础
- 需要建立有效的知识更新和维护机制
8.2 实际应用建议
如果你在项目中需要使用 RAG 技术,我的建议是:
- 明确知识来源:确定你的知识库内容和更新频率
- 选择合适的检索器:根据场景选择 DPR、BM25 或混合检索
- 优化文档分割:合理的文档长度和结构对检索效果至关重要
- 考虑重排序:对检索结果进行重排序可以提升质量
- 监控和评估:建立评估指标,持续监控系统性能
九、总结
《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》这篇论文提出了一种简单而强大的方法,通过将检索和生成相结合,让大语言模型学会"翻书"作答。
核心贡献:
- 首次系统验证了 RAG 作为知识增强方法的有效性
- 提出了两种 RAG 变体(Sequence 和 Token)
- 在多个知识密集型任务上取得了 SOTA 结果
- 证明了知识热替换的可行性
我的核心观点:
- RAG 是大模型的"开卷考试"——通过外部知识增强,让模型的答案更准确、更可靠
- 参数化记忆 + 非参数化记忆是未来方向——两者各有优势,结合使用效果最佳
- 知识管理比模型本身更重要——高质量的知识库是 RAG 系统的基础
对于 C++ 工程师来说,这篇论文的启示是:在构建 AI 系统时,不要只关注模型本身,也要关注数据和知识的管理。一个好的知识管理系统,可能比模型本身更能决定最终效果。
记住:让模型学会"查资料",而不是"死记硬背"。

