从本章开始,我们进入本书的第二部分——原理篇。在前三章中,我们分析了大语言模型的核心局限,介绍了RAG技术的诞生与发展,并对比了RAG与微调、长上下文等技术路线。本章将从一个全局视角出发,完整解析RAG系统的工作流程,帮助读者建立对RAG系统的系统性认知。
4.1 RAG的两大阶段:离线索引与在线推理
RAG系统的运行过程可以清晰地划分为两个阶段:离线索引阶段(Offline Indexing)和在线推理阶段(Online Inference)。这一划分不仅是架构设计的基础,也是理解RAG系统性能特征和优化方向的关键。
4.1.1 标准工作流程
Gao等人在2024年发表的RAG综述论文中,将RAG的标准工作流程明确划分为三个核心步骤:
1. 索引(Indexing): 将文档分割为文本块(chunks),编码为向量表示,存储在向量数据库中。
2. 检索(Retrieval): 基于用户查询的语义相似度,从向量数据库中检索最相关的Top-K个文本块。
3. 生成(Generation): 将原始问题和检索到的文本块一起输入大语言模型,生成最终答案。
这一“索引-检索-生成”的三步流程,构成了RAG系统最基本的工作范式,也被称为“Retrieve-Read”框架。Lewis等人在2020年的原始RAG论文中就提出了这一端到端框架:用检索器从知识库中检索文档,然后将检索结果与问题一起输入序列到序列生成器。
[1] Gao et al. Retrieval-Augmented Generation for Large Language Models: A Survey. 2024. arXiv:2312.10997
[2] Lewis et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS 2020. arXiv:2005.11401
4.1.2 离线索引阶段
离线索引阶段是RAG系统的{LQ}准备工作{RQ},在用户查询到来之前完成。该阶段的核心目标是将原始文档转化为可被高效检索的结构化表示。
关键步骤如下:
| 步骤 | 说明 | 数据格式变化 |
|---|---|---|
| 数据清洗与提取 | 从PDF、HTML、Word等格式中提取纯文本 | 多格式 → 统一纯文本 |
| 文本分块(Chunking) | 将长文本分割为更小的文本块 | 长文本 → 文本块列表 |
| 向量化(Embedding) | 使用嵌入模型将每个文本块编码为向量 | 文本块 → 向量 |
| 存储与索引 | 将向量存储在向量数据库中并建立索引 | 向量 → 向量数据库索引 |
LangChain官方文档将索引阶段进一步概括为“Load → Split → Store”三步模式:使用Document Loaders加载数据,使用Text Splitters分割文档,使用VectorStore和Embeddings模型存储和索引分割结果。
LlamaIndex则通过IngestionPipeline概念,使用“转换(Transformations)”来描述索引过程,典型的转换包括文本分割、嵌入计算和元数据提取。
[3] LangChain官方教程. Build a RAG App. python.langchain.com/docs/tutori…
[4] LlamaIndex官方文档. Ingestion Pipeline. docs.llamaindex.ai/
4.1.3 在线推理阶段
在线推理阶段是RAG系统响应用户查询的{LQ}实时工作{RQ}阶段,每次用户发起查询时触发。
| 步骤 | 说明 | 数据格式变化 |
|---|---|---|
| 查询编码 | 将用户查询编码为向量 | 自然语言 → 查询向量 |
| 相似度计算 | 计算查询向量与所有文本块向量的相似度 | 向量 → 相似度分数 |
| Top-K检索 | 选取相似度最高的K个文本块 | 分数 → Top-K文档片段 |
| 提示构建 | 将问题和检索结果合成为结构化提示 | 问题+文档 → Prompt |
| LLM生成 | 大语言模型基于提示生成最终答案 | Prompt → 自然语言答案 |
4.1.4 两阶段特征对比
| 特征 | 离线索引阶段 | 在线推理阶段 |
|---|---|---|
| 执行时机 | 预处理阶段,离线批量执行 | 用户请求时,在线实时执行 |
| 执行频率 | 数据更新时执行(低频) | 每次用户查询时执行(高频) |
| 延迟要求 | 低(可批量、异步处理) | 高(需快速响应用户) |
| 主要计算开销 | 文档解析、分块、嵌入计算 | 查询编码、相似度搜索、LLM推理 |
| 典型耗时 | 分钟到小时级 | 毫秒到秒级 |
| 可优化方向 | 增量索引、并行处理、缓存 | 查询优化、缓存、流式生成 |
理解两阶段的特征差异至关重要:离线阶段的质量决定了在线阶段的上限——如果索引阶段产生了低质量的文本块或向量表示,在线阶段无论怎样优化检索和生成策略,都无法弥补这一缺陷。因此,在后续章节中,我们将用大量篇幅深入讨论离线索引阶段的各项技术。
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
4.2 端到端RAG系统的数据流
4.2.1 完整数据流全景
一个端到端的RAG系统涉及从原始文档到最终答案的完整数据转换链路。理解这一数据流,有助于开发者在各个环节进行有针对性的优化。
完整数据流为:原始文档(PDF/HTML/Word/Markdown)→ Document Loader文档加载与解析 → 纯文本Document对象列表(含metadata)→ Text Splitter文本分块 → 文本块列表(每个chunk含文本+元数据)→ Embedding Model向量化 → 向量表示(如1536维浮点数组)→ Vector Store向量存储与索引 → ===== 离线索引阶段完成 ===== → 用户查询 → Query Encoder查询编码 → 查询向量 → Retriever相似度检索 → Top-K相关文档片段 → Reranker(可选)重排序 → Prompt Builder提示构建 → 结构化Prompt → LLM答案生成 → 最终答案。
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
4.2.2 各环节数据格式详解
| 环节 | 输入格式 | 输出格式 | 关键数据结构 |
|---|---|---|---|
| Document Loader | 原始文件 | List[Document] | Document: page_content(str) + metadata(dict) |
| Text Splitter | List[Document] | List[Document](更小chunks) | chunk文本 + 起始索引等元数据 |
| Embedding Model | 文本字符串 | List[float](向量) | 典型维度:768/1536/3072维 |
| Vector Store | Document + 向量 | 存储记录 | id, vector, metadata, text |
| Retriever | 查询字符串 | List[Document] | 按相似度排序的文档列表 |
| Reranker | 查询 + 文档列表 | 重排序List[Document] | 带相关性分数的文档列表 |
| Prompt Builder | 查询 + 文档上下文 | Prompt字符串 | 结构化模板填充后的文本 |
| Generator | Prompt字符串 | 答案文本 | LLM输出的自然语言字符串 |
[3] LangChain官方文档. python.langchain.com/docs/concep…
[4] LlamaIndex官方文档. docs.llamaindex.ai/
4.2.3 数据流中的关键设计决策
嵌入模型一致性: 索引阶段和检索阶段必须使用同一个嵌入模型。如果两个阶段使用了不同的嵌入模型,生成的向量将处于不同的语义空间,导致检索结果毫无意义。这是RAG系统中最常见的错误之一。
元数据传递: 文档的元数据(如来源、标题、页码、时间戳等)应贯穿整个数据流。元数据在检索结果过滤、引用溯源和答案可信度评估中发挥重要作用。
可选组件的引入时机: Reranker是一个可选但强烈推荐的组件。在数据量较大或对检索精度要求较高的场景中,引入Reranker可以显著提升最终效果。但Reranker会增加推理延迟,需要根据实际需求权衡。
[3] LangChain官方文档. python.langchain.com/docs/concep…
4.3 RAG系统的核心组件拆解
4.3.1 七大核心组件
一个完整的RAG系统由七个核心组件构成,每个组件承担明确的职责:
1. Document Loader(文档加载器): 从各种数据源加载原始数据,转换为统一的Document对象格式。LangChain目前支持189种以上的文档加载器,覆盖PDF、HTML、Word、Markdown、CSV、数据库、云存储等数据源。每个Document对象包含page_content(文本内容)和metadata(元数据)两个字段。
2. Text Splitter(文本分割器): 将长文档分割为适合嵌入模型和LLM上下文窗口的文本块。LangChain推荐使用RecursiveCharacterTextSplitter作为通用文本的默认分割器,它递归使用常见分隔符(如换行符、段落分隔符)进行分割。关键参数包括chunk_size(块大小,如1000字符)和chunk_overlap(重叠大小,如200字符)。
3. Embedding Model(嵌入模型): 将文本编码为固定维度的稠密向量,使语义相似的文本在向量空间中距离更近。常用模型包括OpenAI text-embedding-3系列、BGE系列、E5系列等。索引阶段和检索阶段必须使用同一嵌入模型。
4. Vector Store(向量存储): 存储和索引文档向量,支持高效的相似度搜索。LangChain支持40种以上的向量存储后端,包括FAISS、Chroma、Pinecone、Milvus、Qdrant、pgvector等。
5. Retriever(检索器): 基于用户查询从向量存储中检索最相关的文档片段。核心方法为invoke(query),返回按相似度排序的Document列表。支持多种检索策略,包括相似度检索、MMR(最大边际相关性)检索等。
6. Reranker(重排序器): 对检索器返回的文档列表进行重新排序,将最相关的文档排在前面。通常使用交叉编码器(Cross-Encoder)模型,比双编码器(Bi-Encoder)更精确但更慢。Gao等人在RAG综述中将其归类为{LQ}后检索处理{RQ}的关键技术。
7. Generator(生成器): 基于检索到的上下文和用户问题,生成最终的自然语言答案。通常使用ChatModel/LLM(如GPT-4、Claude等),通过精心设计的提示模板将检索上下文与用户问题结合。
[3] LangChain官方文档. python.langchain.com/docs/concep…
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
4.3.2 Gao et al.综述中的RAG组件分类
Gao等人在2024年的综述中,将RAG框架的基础分为三大部分(tripartite foundation):
Retrieval(检索): 包括索引优化(滑动窗口、细粒度分割、元数据标注)、查询优化(查询重写、查询转换、查询扩展)和嵌入优化。
Generation(生成): 包括后检索处理(重排序、上下文压缩)和LLM微调(使LLM更好地利用检索上下文)。
Augmentation(增强): 包括前增强(在检索前对数据进行增强处理)、中增强(在检索和生成之间进行增强)和后增强(对生成结果进行增强处理)。
该综述还提出了RAG范式的三个演进阶段:Naive RAG(标准的“索引-检索-生成”流程)、Advanced RAG(增加预检索和后检索优化策略)和Modular RAG(模块化设计,可灵活组合不同组件)。本书的后续章节将按照这一演进脉络,逐步深入各项技术细节。
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
4.4 一个最简单的RAG系统实现
4.4.1 Naive RAG的标准实现
根据Gao等人的综述,Naive RAG遵循传统的“Retrieve-Read”框架,是最基本的RAG实现方式。其工作流程可以概括为三个步骤:
第一步(索引):清洗和提取原始数据 → 转换为统一纯文本 → 分割为文本块 → 编码为向量 → 存储在向量数据库。
第二步(检索):将用户查询编码为向量 → 计算与所有文本块向量的相似度 → 选取Top-K最相似的文本块。
第三步(生成):将查询和检索到的文本块合成为提示 → LLM生成答案。
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
4.4.2 LangChain实现示例
LangChain官方教程展示了约50行代码的最简RAG实现,完整覆盖了索引和检索生成两个阶段:
# === 索引阶段 ===
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = WebBaseLoader(web_paths=("https://example.com/article",))
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200)
all_splits = text_splitter.split_documents(docs)
# === 检索和生成阶段 ===
retrieved_docs = vector_store.similarity_search(
"What is Task Decomposition?")
docs_content = "\n\n".join(
doc.page_content for doc in retrieved_docs)
prompt = f"Context: {docs_content}\n\nQuestion: ...\nAnswer:"
response = llm.invoke(prompt)
[3] LangChain官方教程. python.langchain.com/docs/tutori…
4.4.3 LlamaIndex实现示例
LlamaIndex提供了更为简洁的实现方式,核心代码仅需三行:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# 1. 加载数据
documents = SimpleDirectoryReader("data").load_data()
# 2. 创建索引(自动完成分块、嵌入、存储)
index = VectorStoreIndex.from_documents(documents)
# 3. 查询
response = index.as_query_engine().query(
"What did the author do in college?")
LlamaIndex的VectorStoreIndex.from_documents方法内部自动完成了文本分块、嵌入计算和向量存储三个步骤,极大地简化了RAG系统的搭建过程。
[4] LlamaIndex官方文档. Starter Tutorial. docs.llamaindex.ai/
4.4.4 最小组件集合
| 组件 | 必要性 | 说明 |
|---|---|---|
| Document Loader | 必需 | 将原始数据加载为Document对象 |
| Text Splitter | 必需 | 将长文档分割为适合嵌入的文本块 |
| Embedding Model | 必需 | 将文本编码为向量(索引和检索共用) |
| Vector Store | 必需 | 存储和检索向量 |
| Retriever | 必需 | 基于查询检索相关文档(通常由VectorStore提供) |
| LLM / Generator | 必需 | 基于检索上下文生成最终答案 |
| Prompt Template | 必需 | 将检索上下文和用户问题组装为结构化提示 |
| Reranker | 可选 | 提升检索精度,非最简实现必需 |
最简RAG系统需要6个必需组件:Document Loader + Text Splitter + Embedding Model + Vector Store + LLM + Prompt Template。Reranker虽然不是必需组件,但在实际生产环境中强烈推荐引入,因为它通常能带来显著的检索质量提升。
[3] LangChain官方文档. [4] LlamaIndex官方文档.
4.5 RAG系统的评价指标
4.5.1 为什么需要专门的RAG评估
传统的NLP评估指标(如BLEU、ROUGE)主要衡量生成文本与参考文本之间的字面重叠度,无法有效评估RAG系统的两个核心能力:检索质量和生成忠实度。RAG系统需要一套专门的评估框架,能够独立评估检索组件和生成组件的表现,以及端到端的系统性能。
4.5.2 RAGAS评估框架
RAGAS(Retrieval Augmented Generation Assessment)是由Es等人在2023年提出的RAG专用自动化评估框架。其核心设计理念是无需参考答案(reference-free)的自动化评估,通过大语言模型作为评判者来衡量RAG系统的各项质量维度。
RAGAS框架提出了三个核心质量维度,被称为{LQ}RAG Triad{RQ}:
Faithfulness(忠实度): 衡量答案中的所有声明是否都能从检索到的上下文中推断出来。计算方法:使用LLM将答案分解为一组简短陈述,逐一判断每个陈述是否能从上下文中推断得出。Faithfulness = 被支持的陈述数 / 总陈述数。这一指标直接检测幻觉——如果模型生成了上下文中不存在的信息,Faithfulness分数将下降。
Answer Relevance(答案相关性): 衡量生成的答案是否直接回应了用户的问题。计算方法:基于生成的答案使用LLM生成多个潜在问题,计算这些生成问题与原始问题的余弦相似度。注意:此指标不评估事实性,而是惩罚不完整或包含冗余信息的答案。
Context Relevance(上下文相关性): 衡量检索到的上下文是否聚焦,包含尽可能少的不相关信息。计算方法:给定问题和上下文,使用LLM提取回答问题所需的关键句子子集,计算关键句子数与上下文总句子数的比值。这一指标惩罚冗余信息,因为过长的上下文会增加LLM成本且降低效果(即{LQ}Lost in the Middle{RQ}问题)。
[5] Es et al. RAGAS: Automated Evaluation of Retrieval Augmented Generation. 2023. arXiv:2309.15217
4.5.3 RAGAS完整指标体系
根据RAGAS官方文档(2025年更新),完整的RAG评估指标包括:
| 指标 | 评估维度 | 是否需要参考答案 | 说明 |
|---|---|---|---|
| Faithfulness | 忠实度 | 否 | 答案是否忠实于检索上下文 |
| Answer Relevance | 答案相关性 | 否 | 答案是否回应了用户问题 |
| Context Precision | 上下文精确度 | 否 | 检索结果中相关信息的排序质量 |
| Context Recall | 上下文召回率 | 是 | 检索结果是否覆盖了标准答案所需信息 |
| Factual Correctness | 事实正确性 | 是 | 答案的事实准确性 |
| Semantic Similarity | 语义相似度 | 是 | 答案与参考答案的语义相似度 |
值得注意的是,RAGAS框架中的大部分核心指标(Faithfulness、Answer Relevance、Context Precision)都是无需参考答案的,这使得RAG系统的评估成本大大降低。
[5] Es et al. RAGAS. 2023. arXiv:2309.15217
[6] RAGAS官方文档. docs.ragas.io/en/stable/c…
4.5.4 评估层次体系
RAGAS官方文档将AI应用的评估指标分为三个层次:
端到端指标(End-to-End Metrics): 从用户视角评估整体系统性能,如Answer Correctness(答案正确性)、Citation Accuracy(引用准确性)。
组件级指标(Component-Level Metrics): 独立评估系统各部分,如Retrieval Accuracy(检索准确度)、Faithfulness(生成忠实度)。
业务指标(Business Metrics): 与组织目标对齐,如Ticket Deflection Rate(工单拦截率)、User Satisfaction(用户满意度)。
这种分层评估体系确保了开发者可以从不同粒度定位系统瓶颈:如果端到端指标不佳,可以通过组件级指标判断是检索环节还是生成环节出了问题。
[6] RAGAS官方文档. docs.ragas.io/en/stable/c…
4.5.5 标准评测数据集
RAG系统的评估离不开标准化的评测数据集。以下是RAG领域最常用的评测数据集:
问答类数据集:
| 数据集 | 说明 | 规模 | 主要指标 |
|---|---|---|---|
| TriviaQA | 大规模阅读理解数据集 | 95K+问答对 | EM, F1 |
| Natural Questions | Google发布的真实用户查询 | 300K+问答对 | EM, F1 |
| MS MARCO | 微软发布的机器阅读理解数据集 | 1M+查询 | EM, F1, MRR |
| SQuAD | 斯坦福阅读理解数据集 | 100K+问答对 | EM, F1 |
检索类数据集方面,BEIR(Benchmark for Information Retrieval)是由Thakur等人在2021年提出的异构检索基准,包含18个数据集,专门用于零样本信息检索模型的评估,是当前检索模型评测的权威基准。
Gao等人在综述中总结了RAG评估涉及的26个任务、近50个数据集,并讨论了不同评估目标和指标的适用场景。
[7] Thakur et al. BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of IR Models. NeurIPS 2021. arXiv:2104.08663
[1] Gao et al. RAG Survey. 2024. arXiv:2312.10997
本章从全局视角解析了RAG系统的完整工作流程,包括离线索引与在线推理两大阶段、端到端数据流、七大核心组件、最简实现方式和评估指标体系。这些知识构成了理解后续章节的基础。从下一章开始,我们将深入RAG系统的第一个核心环节——离线索引,详细讨论如何构建高质量的知识库。