Chapter 01

RAG 是什么:原理与架构全景

检索增强生成(Retrieval-Augmented Generation)如何解决大模型的知识局限与幻觉问题

大语言模型的根本局限

GPT-4、Claude、Gemini 等大语言模型(LLM)在海量文本上训练,掌握了广博的世界知识。但它们有两个无法回避的天然缺陷,这两个缺陷直接催生了 RAG 技术的诞生。

知识截止日期(Knowledge Cutoff)

  • 训练数据有时间截止点,GPT-4o 截止 2023 年底
  • 无法回答昨天发生的新闻、最新政策、实时价格
  • 企业私有文档(合同、手册、内部知识库)完全不在训练集中
  • 重新训练成本极高,每次更新需数百万美元

幻觉问题(Hallucination)

  • 模型会自信地生成听起来合理但实际错误的内容
  • 引用不存在的论文、错误的法律条款、虚构的历史事件
  • 根本原因:模型是在预测"合理的下一个词",而非在查询真实知识
  • 高风险领域(医疗、法律、金融)中幻觉代价极高
核心动机

RAG 的核心思路是:在模型生成答案之前,先从外部知识库中检索相关文档片段,把这些片段作为上下文(Context)塞入提示词,让模型基于真实的文档来回答问题,而不是凭记忆"猜测"。

RAG 的精确定义

RAG
Retrieval-Augmented Generation,检索增强生成。由 Meta AI 在 2020 年论文《RAG for Knowledge-Intensive NLP Tasks》首次提出,将检索系统与生成模型结合,让 LLM 能够动态访问外部知识。
知识库 (Knowledge Base)
存储结构化或非结构化文档的数据源,可以是 PDF 文件集合、网页内容、数据库记录等。通过 Embedding 模型转换为向量后存入向量数据库。
检索器 (Retriever)
负责在知识库中查找与用户问题最相关文档片段的组件。可以是稠密检索(向量相似度)、稀疏检索(BM25 关键词匹配)或两者混合。
生成器 (Generator)
接收"问题 + 检索到的文档上下文"后生成最终答案的 LLM。有了真实的上下文支撑,幻觉率大幅降低,且答案可被溯源验证。
增强 (Augmented)
Generation 过程被外部知识"增强",即生成时不再仅依赖模型参数中的隐式知识,而是结合动态检索到的显式文档内容。

RAG 完整流程图解

一个典型的 RAG 系统包含两个阶段:离线索引阶段在线查询阶段

离线索引阶段(Index Pipeline)

Load文档加载
Split文档分块
Embed向量编码
Store写入向量库

在线查询阶段(Query Pipeline)

Query用户提问
Embed问题向量化
Retrieve向量检索 Top-K
Augment构建 Prompt
GenerateLLM 生成

理解这两个阶段是掌握 RAG 的第一步。离线阶段构建知识索引,在线阶段实时检索并生成——两个阶段相互独立,可以分别优化。

最简 RAG 代码示例

下面用最直观的方式展示 RAG 的核心逻辑,不依赖任何框架:

# 最简 RAG 示例:手动实现核心流程
import numpy as np
from openai import OpenAI

client = OpenAI()

# ── 离线索引阶段 ──────────────────────────
# 1. 知识库文档(实际场景来自 PDF/数据库等)
documents = [
    "Python 由 Guido van Rossum 于 1991 年创建,以简洁易读著称。",
    "RAG(检索增强生成)由 Meta AI 于 2020 年提出,解决 LLM 幻觉问题。",
    "向量数据库专门存储高维向量,支持近似最近邻(ANN)搜索。",
    "Transformer 架构由 Google Brain 在 2017 年论文 Attention Is All You Need 中提出。",
]

def embed(text: str) -> list[float]:
    """调用 OpenAI Embedding API 将文本转为向量"""
    resp = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return resp.data[0].embedding

# 2. 将文档编码为向量(离线完成,存入向量库)
doc_embeddings = [embed(doc) for doc in documents]
doc_matrix = np.array(doc_embeddings)  # shape: (4, 1536)

# ── 在线查询阶段 ──────────────────────────
def retrieve(query: str, top_k: int = 2) -> list[str]:
    """向量相似度检索:余弦相似度 Top-K"""
    q_vec = np.array(embed(query))
    # 余弦相似度 = 点积(向量已归一化)
    scores = doc_matrix @ q_vec
    top_indices = np.argsort(scores)[:-top_k-1:-1]
    return [documents[i] for i in top_indices]

def rag_answer(question: str) -> str:
    """RAG 完整流程:检索 → 增强 Prompt → 生成"""
    # 3. 检索相关文档
    contexts = retrieve(question, top_k=2)
    context_text = "\n".join([f"- {c}" for c in contexts])

    # 4. 构建增强后的 Prompt
    prompt = f"""根据以下背景知识回答问题。只基于提供的背景,不要编造信息。

背景知识:
{context_text}

问题:{question}
答案:"""

    # 5. LLM 生成
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )
    return resp.choices[0].message.content

# 测试
answer = rag_answer("RAG 是谁提出的,解决什么问题?")
print(answer)
# → RAG(检索增强生成)由 Meta AI 于 2020 年提出,主要解决 LLM 的幻觉问题。

RAG 的三个演进阶段

RAG 技术自 2020 年提出以来,经历了从简单到复杂的演进,学术界将其分为三代:

代际 名称 核心特征 典型工具 局限性
Gen 1 Naive RAG 固定分块 → 向量检索 → 直接生成 LangChain 早期版本 检索精度低,上下文冗余
Gen 2 Advanced RAG 查询改写、混合检索、Reranker、滑动窗口分块 LlamaIndex 0.9+ 流程复杂,调参困难
Gen 3 Modular RAG 模块化编排、自适应检索、Agent 决策、图检索 LlamaIndex 0.10+, LangGraph 工程复杂度高

Naive RAG:简单但够用

最基础的 RAG 实现:把文档切成固定大小的块,用向量相似度找最近的 Top-K,直接拼到 Prompt 里。实现简单,对于文档质量高、问题清晰的场景已经相当有效。

Advanced RAG:精度与召回的平衡

在 Naive RAG 基础上引入多种增强技术:

Modular RAG:像搭积木一样构建 RAG

将 RAG 流程拆解为独立可替换的模块(搜索模块、记忆模块、融合模块、路由模块等),通过 Agent 动态编排,根据问题类型选择最优路径。这代表了 2024-2025 年的主流方向。

学习建议

对于大多数业务场景,Advanced RAG 已经足够。Modular RAG 适合需要处理多种类型问题(数据库查询、代码生成、文档检索并存)的复杂系统。不要过度工程化。

RAG vs 微调:何时用哪个

维度 RAG 微调(Fine-tuning)
知识更新 实时,只需更新向量库 需要重新训练,成本高
答案溯源 可追溯到具体文档 无法溯源,黑盒
启动成本 低,数小时搭建 高,数千至数万美元
适合场景 知识密集型问答、文档检索、客服 特定风格/格式、专业领域语言模式
幻觉控制 强,有文档约束 弱,仍可能幻觉
常见误区

RAG 和微调并不互斥。最佳实践是:用 RAG 处理知识访问,用微调调整模型的输出风格与格式。两者结合往往效果最优。

RAG 的适用场景

本章总结