RAG 完整流程拆解:从文档到智能回答的每一步

RAG 完整流程拆解:从文档到智能回答的每一步


一、什么是 RAG?为什么它如此重要?

RAG(Retrieval-Augmented Generation,检索增强生成) 是当前大语言模型(LLM)应用落地的核心技术之一。它的本质很简单:给大模型装上一个"外脑"

纯 LLM 存在三大痛点:幻觉(编造虚假信息)、知识冻结(训练数据有截止日期)、以及私有数据盲区(不了解企业内部文档)。RAG 通过将外部知识库与 LLM 结合,让模型在回答问题时能够"查资料",从而生成基于事实的答案。

RAG 的工作流程分为两个主要阶段:

  1. 索引阶段(Indexing):离线预处理文档,构建可检索的知识库

  2. 检索与生成阶段(Retrieval & Generation):在线响应用户查询,检索相关知识并生成答案


二、Step 1:文档解析(Document Parsing)

2.1 为什么文档解析是 RAG 的"第一道关卡"?

文档解析是整个 RAG 流程中最容易被忽视,却最关键的环节。如果这一步出了问题,后续的所有优化都将事倍功半。

原始文档格式多种多样:PDF、Word、PPT、网页、扫描件、图片等。每种格式都有其独特的挑战:

文档类型 主要挑战
PDF 文本提取不准确、表格行列关系混乱、多栏排版错位
扫描件/图片 需要 OCR 识别,手写体、低质量扫描导致识别错误
网页 HTML 标签噪音、导航栏/广告等无关内容混入
PPT 图文混排复杂、幻灯片顺序与逻辑结构不一致
表格 跨页表格断裂、表头与数据分离

2.2 文档解析的核心任务

文档解析的目标是将各种格式的原始文档转换为干净、结构化、可检索的文本。主要包含以下步骤:

  1. 格式识别:判断文档类型(PDF/HTML/DOCX 等)

  2. 内容提取:提取正文、标题、表格、图片说明等

  3. 结构还原:保留段落层级、列表关系、表格结构

  4. 噪音过滤:去除页眉页脚、广告、导航栏等无关内容

最佳实践:对于 PDF 文档,最可靠的做法是先将其转换为 Markdown 等结构化格式,再进行后续处理。

2.3 常用工具推荐

  • 开源方案:Unstructured、Marker、PDFPlumber、PyMuPDF

  • 商业方案:Firecrawl(网页)、Azure Document Intelligence(PDF/OCR)

  • OCR 引擎:Tesseract、PaddleOCR、Azure Read API


三、Step 2:分块(Chunking)

3.1 为什么要分块?

LLM 的上下文窗口是有限的,我们无法将整本书或几百页的 PDF 一次性塞进模型。同时,Embedding 模型也有输入长度限制(通常为 512 或 1024 tokens)。因此,必须将文档切分成更小的"块"(Chunk)。

但分块不是简单的"一刀切"------分块策略直接决定了 RAG 系统的检索质量 。研究表明,不同的分块策略可能导致高达 9% 的召回率差距

3.2 主流分块策略详解

策略一:固定大小分块(Fixed-Size Chunking)

最简单粗暴的方式:设定一个固定长度(如 1000 字符),达到上限就切分。

复制代码
# 伪代码示例
chunks = []
chunk_size = 1000
for i in range(0, len(text), chunk_size):
    chunks.append(text[i:i+chunk_size])

优点 :实现简单、速度快、块大小可预测 缺点:完全无视语义边界,可能切断句子、段落甚至表格

适用场景:快速原型验证(MVP)、结构均匀的内容(如新闻文章)

策略二:递归字符分块(Recursive Character Splitting)⭐ 推荐默认方案

这是目前80% 的 RAG 应用的首选方案。它按照优先级尝试在"自然边界"处切分:

  1. 先尝试按 段落\n\n)切分

  2. 段落太长则按 \n)切分

  3. 行太长则按 句子.)切分

  4. 句子太长则按 单词(空格)切分

  5. 最后按 字符 切分

复制代码
# LangChain 示例
from langchain_text_splitters import RecursiveCharacterTextSplitter
​
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,        # 目标块大小(tokens)
    chunk_overlap=50,      # 重叠量(约 10-20%)
    separators=["\n\n", "\n", ". ", " ", ""]  # 优先级分隔符
)
chunks = splitter.split_documents(documents)

推荐参数:400-512 tokens 的块大小,10-20% 的重叠量(约 50-100 tokens)

优点 :保留文档结构、适应多种内容类型、性能稳定(Chroma 研究显示召回率可达 88-89%) 缺点:块大小不均匀,对批量处理略有影响

策略三:语义分块(Semantic Chunking)

语义分块不再依赖固定长度,而是根据内容主题的转换来决定切分点。具体做法是:

  1. 将文档按句子拆分

  2. 为每个句子生成 Embedding

  3. 计算相邻句子的相似度

  4. 当相似度低于某个阈值时,在此处切分

复制代码
from langchain_experimental.text_splitter import SemanticChunker
​
semantic_splitter = SemanticChunker(
    embeddings=embeddings,
    breakpoint_threshold_type="percentile",  # 或 "standard_deviation"
    breakpoint_threshold_amount=95
)
chunks = semantic_splitter.split_text(document_text)

优点 :语义连贯性好、能检测细微的主题转换、召回率可提升 2-9% 缺点:计算成本高(每个句子都要 Embedding)、需要调参、处理速度慢

适用场景:对检索精度要求极高、预算充足、文档主题转换微妙的场景(如研究论文)

策略四:页面级分块(Page-Level Chunking)

以 PDF 页面为单位进行切分,每页作为一个 Chunk。

优点 :在 NVIDIA 2024 基准测试中取得了最高准确率(0.648)和最低方差 缺点:仅适用于有分页的文档,页面内容长度差异大

策略五:Late Chunking(延迟分块)🔥 2024-2025 新兴技术

传统分块先切分文档再 Embedding,导致每个 Chunk 失去了全局上下文。Late Chunking 颠覆了这个顺序:

  1. :将完整文档输入 Transformer,生成 token 级别的 Embedding(此时每个 token 都包含了全文上下文)

  2. :再按边界切分,对每个 Chunk 内的 token Embedding 做平均池化

这样,即使 Chunk 中出现了代词"它",其 Embedding 也能知道"它"指代的是前文提到的"柏林"。

复制代码
import requests
​
data = {
    "input": [
        "Berlin is the capital and largest city of Germany...",
        "Its more than 3.85 million inhabitants make it...",
    ],
    "model": "jina-embeddings-v3",
    "task": "retrieval.passage",
    "late_chunking": True,  # 关键参数
}

3.3 分块策略选择决策树

一句话总结

  • 起步:递归字符分块(512 tokens + 10-20% 重叠)

  • 优化:根据文档类型和查询模式,尝试语义分块或 Late Chunking

  • 高价值场景:考虑 LLM-Based 或 Agentic 分块

3.4 分块的常见陷阱

  1. 块太小:200 字符以下的块几乎无法承载有效语义

  2. 块太大:跨主题的块会稀释 Embedding 的表达能力

  3. 忽视文档结构:表格切断了表头、代码切断了函数体

  4. 丢弃元数据:文档标题、章节名、页码等元数据对检索至关重要

  5. 一刀切:不同类型的文档应使用不同的分块策略


四、Step 3:Embedding 向量入库

4.1 什么是 Embedding?

Embedding 是将文本转换为高维向量的过程。语义相近的文本在向量空间中的距离也更近。通过这种方式,我们可以用数学方法衡量两段文本的"相似度"。

4.2 Embedding 模型选择

模型 维度 特点 适用场景
text-embedding-3-small (OpenAI) 1536 速度快、成本低 通用场景、预算敏感
text-embedding-3-large (OpenAI) 3072 精度更高 对质量要求高
BGE-M3 (BAAI) 1024 多语言、开源 中文场景、私有化部署
jina-embeddings-v3 (Jina AI) 1024 支持 Late Chunking 长文档、跨语言
E5-mistral-7b-instruct (Microsoft) 4096 指令式 Embedding 复杂查询

选型建议

  • 英文内容:OpenAI text-embedding-3-largetext-embedding-3-small

  • 中文内容:BGE-M3、Jina-embeddings-v3

  • 私有化部署:BGE 系列、GTE 系列

4.3 向量数据库选型

向量数据库负责高效存储和检索高维向量。常见选择:

数据库 特点 适用场景
Pinecone 全托管、易用 快速上线、不想运维
Milvus/Zilliz 开源、高性能、可扩展 大规模数据、企业级
Qdrant 开源、Rust 编写、高性能 自托管、低延迟
Weaviate 开源、GraphQL 接口 需要复杂查询
Chroma 轻量、易集成 原型开发、本地测试
pgvector PostgreSQL 扩展 已有 PG 基础设施
Redis 内存级速度 需要极低延迟

4.4 入库流程

复制代码
# 以 Pinecone + LangChain 为例
from langchain_pinecone import PineconeVectorStore
from langchain_openai import OpenAIEmbeddings
​
# 1. 初始化 Embedding 模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
​
# 2. 初始化向量数据库
vector_store = PineconeVectorStore(
    index=pc.Index("my-index"),
    embedding=embeddings
)
​
# 3. 将分块后的文档入库
vector_store.add_documents(chunks)

关键注意事项

  • 为每个 Chunk 保留元数据(文档标题、章节、页码、URL 等),便于后续过滤和溯源

  • 考虑批量入库以提升效率

  • 对于大规模数据,选择支持近似最近邻(ANN)索引的数据库(如 HNSW、IVF-PQ)


五、Step 4:检索(Retrieval)

5.1 检索阶段的工作流程

当用户提出问题时,检索阶段的工作如下:

  1. 查询向量化:将用户问题通过同样的 Embedding 模型转换为向量

  2. 相似度搜索:在向量数据库中查找与查询向量最相似的 Top-K 个 Chunk

  3. 结果返回:将检索到的 Chunk 作为"上下文"传递给 LLM

5.2 检索策略进阶

基础检索:向量相似度搜索

最基础的检索方式,通过余弦相似度或欧氏距离找到最近邻向量。

复制代码
results = vector_store.similarity_search(query, k=5)
进阶检索一:混合检索(Hybrid Search)

纯向量检索有时会遗漏精确匹配的关键词(如产品型号、专有名词)。混合检索结合了两者的优势:

  • 稠密检索(Dense):向量相似度,捕捉语义相关性

  • 稀疏检索(Sparse):BM25/TF-IDF,捕捉关键词精确匹配

通过 RRF(Reciprocal Rank Fusion) 融合两种检索的结果:

复制代码
RRF_score = Σ(1 / (k + rank_i))
进阶检索二:重排序(Reranking)

先通过向量检索召回大量候选(如 Top-100),再用更精确的重排序模型(Cross-Encoder)对候选进行精排,最终选出 Top-K。

复制代码
# 伪代码
candidates = vector_store.similarity_search(query, k=100)  # 粗排
reranked = cross_encoder.rerank(query, candidates, k=5)    # 精排

常用重排序模型:Cohere Rerank、BGE-Reranker、Jina Reranker

进阶检索三:上下文检索(Contextual Retrieval)

由 Anthropic 提出,在 Embedding 之前为每个 Chunk 添加一个由 LLM 生成的上下文摘要,让 Chunk 知道自己"在整篇文档中的位置"。

例如,一个 Chunk 的内容是:

"它的价格在过去一年上涨了 20%。"

添加上下文后变为:

"上下文:本文讨论的是苹果公司 2025 年财报。Chunk:它的价格在过去一年上涨了 20%。"

这样可以显著减少检索失败率,但需要在索引阶段为每个 Chunk 调用一次 LLM,增加了索引成本。

进阶检索四:查询扩展与改写
  • HyDE(Hypothetical Document Embeddings):让 LLM 先根据问题生成一个"假设的理想答案",再用这个假设答案去检索

  • 多查询扩展:让 LLM 将用户问题改写为多个不同表述的查询,分别检索后合并结果

  • 子查询分解:将复杂问题分解为多个子问题,分别检索后综合回答


六、Step 5:LLM 生成(Generation)

6.1 生成阶段的工作流程

检索到的 Chunk 需要与原始问题一起组装成 Prompt,送入 LLM 生成最终答案。

6.2 Prompt 工程

一个典型的 RAG Prompt 模板:

复制代码
你是一个专业的问答助手。请根据以下提供的参考资料回答问题。
如果参考资料中没有相关信息,请明确说明"根据提供的资料,我无法找到答案"。
不要编造任何信息。
​
## 参考资料:
{retrieved_chunks}
​
## 用户问题:
{user_query}
​
## 回答:

关键技巧

  • 明确角色设定:让 LLM 知道它应该扮演什么角色

  • 引用溯源:要求 LLM 在回答中标注信息来源(如"根据文档1...")

  • 拒绝幻觉:明确指示 LLM 在信息不足时拒绝回答

  • 格式要求:指定输出格式(如 Markdown、JSON、表格)

6.3 上下文窗口管理

LLM 的上下文窗口是有限的,需要合理分配:

内容 建议占比
系统提示(System Prompt) 5-10%
检索到的 Chunk 60-70%
对话历史 10-20%
用户问题 5-10%

注意:研究表明,当上下文长度超过约 2500 tokens 时,模型性能会出现"上下文悬崖"(Context Cliff),响应质量显著下降。

6.4 生成优化策略

  1. 父文档检索(Parent Document Retrieval):检索时用小的 Chunk(精度高),但将 Chunk 所属的完整段落/页面传给 LLM(上下文完整)

  2. 摘要 + 详细内容:先让 LLM 看摘要,再看详细 Chunk

  3. 多轮生成:先生成草稿,再让 LLM 自我修正

  4. 流式输出:提升用户体验,让用户无需等待完整响应


七、完整流程图与架构概览


八、2026 年 RAG 的前沿趋势

8.1 Agentic RAG

不再使用固定的检索流程,而是让 AI Agent 动态决定:

  • 是否需要检索?

  • 检索几次?

  • 从哪个数据源检索?

  • 如何组合多个检索结果?

8.2 Graph RAG

将文档转换为知识图谱(实体-关系-实体),结合图遍历和向量检索,解决跨文档、跨段落的复杂推理问题。

8.3 多模态 RAG

不仅处理文本,还支持图片、音频、视频的理解和检索。使用 CLIP 等多模态 Embedding 模型统一表示。

8.4 自适应 RAG

根据问题的复杂度动态选择策略:

  • 简单问题 → 直接回答(无需检索)

  • 中等问题 → 单次检索

  • 复杂问题 → 多轮检索 + 推理链


九、总结与最佳实践 checklist

完整流程回顾

复制代码
原始文档 → 文档解析 → 分块(Chunk) → Embedding → 向量入库 → 用户查询 → 检索 → 重排序 → Prompt 组装 → LLM 生成 → 回答

生产环境 Checklist

阶段 检查项
文档解析 ✅ 是否处理了 PDF/表格/扫描件?<br>✅ 是否去除了页眉页脚等噪音?<br>✅ 是否保留了文档结构(标题层级)?
分块 ✅ 块大小是否在 400-512 tokens?<br>✅ 是否有 10-20% 的重叠?<br>✅ 是否根据文档类型选择了合适的策略?<br>✅ 是否保留了元数据?
Embedding ✅ 模型是否支持目标语言?<br>✅ 向量维度是否与数据库匹配?
检索 ✅ 是否使用了混合检索(Dense + Sparse)?<br>✅ 是否添加了重排序(Rerank)?<br>✅ Top-K 值是否经过调优?
生成 ✅ Prompt 是否包含明确的角色和约束?<br>✅ 是否要求引用来源?<br>✅ 上下文长度是否控制在合理范围?

十、参考资源


相关推荐
云水初9 小时前
【agent篇】RAG 知识库构建避坑指南
开发语言·python·学习·agent·rag
人道领域1 天前
【0-1的agent进阶篇】RAG:从Embedding到检索增强生成的底层逻辑
java·embedding·agent·rag
可乐ea1 天前
Agent 安全实战:提示词注入、权限边界、数据泄露与成本控制
rag·ai agent·提示词注入·tool calling
我爱吃土豆12 天前
从 N-gram 到 BM25:一次知识库关键词检索架构的演进与优化
rag
IPHWT 零软网络2 天前
技术方案分享|AI Agent 赋能 IVR 导航,解决传统语音呼叫系统交互瓶颈
人工智能·通信系统·rag·ivr·aiagent·智能语音·语音导航
番茄炒鸡蛋加糖2 天前
主流 AI 框架 + RAG 落地实战
人工智能·rag·springai
thesky1234562 天前
27届大模型面试准备(三十二):RAG 进阶——从朴素 RAG 到 Agentic RAG 与多模态检索增强
大模型·rag·agentic rag·graph rag·进阶rag·self-rag·corrective rag
AndrewHZ3 天前
【LLM技术全景】RAG 从原理到实战——检索增强生成完整指南
人工智能·深度学习·算法·llm·检索增强·生成式模型·rag
神奇霸王龙3 天前
Agentic RAG 双硬门屠夫:5 旗舰实测
数据库·人工智能·ai·agent·ai编程·ai写作·rag