Skip to content

RAG 深度实战指南

RAG 不只是"检索+生成"这么简单——每个环节的设计选择都会直接影响产品效果。

前置阅读

本文是 AI 应用架构模式 中 RAG 章节的深度扩展。如果你还不了解 RAG 的基本概念,建议先阅读该章节。

RAG 全景架构

┌─────────────────────────────────────────────────────────────┐
│                     RAG 完整流程                              │
│                                                             │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐ │
│  │ 数据提取  │ → │ 文档分块  │ → │ 向量化   │ → │  索引    │ │
│  │ Ingestion│   │ Chunking │   │Embedding │   │ Indexing │ │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘ │
│       ↑              离线处理阶段                     │       │
│       │         ─────────────────────────────        │       │
│       │              在线查询阶段                     ↓       │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐ │
│  │ 最终生成  │ ← │ 重排序   │ ← │ 检索     │ ← │ 查询理解 │ │
│  │Generation│   │ ReRank  │   │Retrieval │   │  Query   │ │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

每个环节都有大量细节和最佳实践。下面逐一深入。


第一步:数据提取(Ingestion)

为什么数据提取是 RAG 的地基?

"Garbage In, Garbage Out"——如果文档解析质量差,后面的分块、检索、生成全部受影响。

多格式文档解析方案

文档格式解析难度推荐方案关键挑战
纯文本/Markdown直接读取编码问题
PDFPyMuPDF + 版面分析表格、多栏、扫描件
Word(.docx)python-docx嵌套表格、样式继承
HTML/网页BeautifulSoup + 正文提取噪音(导航、广告)
PPT中高python-pptx文本框分散、图表
扫描件/图片OCR(PaddleOCR/Tesseract)识别准确率、版面还原
表格数据专用表格解析跨页表格、合并单元格

PDF 解析的深水区

PDF 是 RAG 中最常见也最棘手的格式:

PDF 解析的四大难点:

1. 多栏布局
   ┌──────────┬──────────┐
   │ 第一栏    │ 第二栏    │   → 文本提取顺序容易错乱
   │ 的内容    │ 的内容    │
   └──────────┴──────────┘

2. 表格
   ┌────┬────┬────┐
   │    │    │    │   → 单元格关系容易丢失
   ├────┼────┼────┤
   │    │    │    │
   └────┴────┴────┘

3. 跨页内容
   ─────── 第 5 页 ───────
   ...这段话在这里开始但是
   ─────── 第 6 页 ───────
   在下一页才结束...      → 内容被截断

4. 扫描件
   [图片形式的文字]        → 需要 OCR,准确率有限

解析方案选型

你的文档是什么类型?

    ├── 纯数字化 PDF(文本可选中)
    │     ├── 简单排版 → PyMuPDF / pdfplumber
    │     └── 复杂排版(多栏/表格) → 版面分析模型

    ├── 扫描件 PDF
    │     ├── 中文为主 → PaddleOCR
    │     └── 英文为主 → Tesseract / Azure Doc Intelligence

    └── 混合型 PDF
          └── 文档智能解析服务(Azure/AWS/阿里云)

结构化数据提取

对于包含结构化信息的文档(合同、报告、表单),建议提取后转为结构化格式:

原始 PDF 内容(非结构化):
"甲方:XX科技有限公司
 合同金额:人民币 500,000 元
 期限:2026年1月1日至2026年12月31日"

        ↓ 结构化提取

{
  "party_a": "XX科技有限公司",
  "amount": 500000,
  "currency": "CNY",
  "start_date": "2026-01-01",
  "end_date": "2026-12-31"
}

第二步:文档分块(Chunking)

为什么分块如此关键?

分块质量直接决定检索质量:

分块太大:
  ┌──────────────────────────────────┐
  │ 大量不相关的内容被检索出来         │   → 噪音多,模型被干扰
  │ 包含了用户需要的信息               │
  │ 还有更多不相关内容                 │
  └──────────────────────────────────┘

分块太小:
  ┌────────┐
  │ 信息不  │   → 上下文丢失,无法理解完整语义
  └────────┘
  ┌────────┐
  │ 完整   │
  └────────┘

合适的分块:
  ┌───────────────────┐
  │ 完整的语义单元      │   → 信息完整,噪音少
  │ 包含必要的上下文    │
  └───────────────────┘

七种分块方法对比

方法原理优势劣势适用场景
固定大小按字符/Token 数切割简单快速语义割裂快速原型验证
句分隔按句号/换行切分保持句子完整粒度太细短文本、FAQ
递归分割按层级分隔符递归切分较好的语义保持需要调参通用场景(推荐起步)
专门分块按 Markdown/LaTeX 标题切分利用文档结构依赖格式结构化文档
语义分割按语义相似度切分最佳语义完整性计算量大高质量需求
滑动窗口固定窗口 + 重叠避免边界信息丢失数据冗余需要上下文连续性
LLM 分块用 LLM 理解文档结构后切分最智能成本高高价值文档

递归分割最佳实践(推荐起步方案)

LangChain RecursiveCharacterTextSplitter 参数建议:

文档类型        chunk_size    chunk_overlap    分隔符优先级
─────────────────────────────────────────────────────────
技术文档         1000          200            \n\n → \n → 。→ 空格
FAQ/知识库       500           100            \n\n → \n → 。
合同/法律        800           200            \n\n → \n → 。→ ;
聊天记录         300           50             \n → 。
学术论文         1200          300            \n\n → \n → 。

语义分割:解决语义割裂问题

语义分割流程:

原始文档


按句子切分


计算相邻句子的语义相似度


        相似度
    1.0 ─┬──────────────────────────
         │  ██  ██  ██     ██  ██
    0.8 ─┤  ██  ██  ██     ██  ██
         │  ██  ██  ██  █  ██  ██
    0.6 ─┤  ██  ██  ██  █  ██  ██
         │  ██  ██  ██  █  ██  ██
    0.4 ─┤  ██  ██  ██  █  ██  ██  █
         │  ██  ██  ██  █  ██  ██  █
    0.2 ─┤  ██  ██  ██  █  ██  ██  █
         │  ██  ██  ██  █  ██  ██  █
    0.0 ─┴──────────────────────────
         S1  S2  S3  S4  S5  S6  S7
                       ↑          ↑
                   语义断点     语义断点

在相似度低谷处切分 → 自然的语义边界

分块的常见问题与解决方案

问题表现解决方案
分块大小不合适检索结果太泛或太碎根据场景调整 chunk_size
上下文关系被切断"它"指代不明增加 overlap 或用父子索引
语义完整性丢失检索到的内容无法理解使用语义分割
跨页表格被切断表格数据不完整预处理合并跨页表格

第三步:向量化(Embedding)

Embedding 的工作原理

Embedding 将文本转换为数学向量:

"产品经理需要理解用户需求"
        ↓ Embedding 模型
[0.12, -0.34, 0.56, 0.78, ..., -0.23]  (1536 维向量)

语义相似的文本 → 向量空间中距离近:

            ↑ 维度 2

            │     ● "用户需求分析"
            │   ● "需求调研方法"

  ──────────┼──────────→ 维度 1

            │              ● "服务器部署"
            │            ● "Docker 容器化"

Embedding 模型选型

模型维度中文能力最大长度特点
text-embedding-3-large30728191OpenAI 最新,支持维度裁剪
text-embedding-3-small15368191性价比高
bge-large-zh-v1.51024优秀512开源,中文最佳之一
bge-m31024优秀8192多语言多粒度,支持稀疏+稠密
GTE-Qwen2可变优秀131072阿里,超长上下文
Cohere embed-v31024512支持多语言和搜索/分类模式

选型决策要点

你的场景是什么?

    ├── 中文为主
    │     ├── 需要私有化部署 → bge-large-zh / bge-m3
    │     └── 可以用 API → text-embedding-3-large

    ├── 多语言混合
    │     └── bge-m3 / Cohere embed-v3

    └── 英文为主
          ├── 追求效果 → text-embedding-3-large
          └── 追求性价比 → text-embedding-3-small

Embedding 检索的局限性

纯语义检索并非万能,了解其局限有助于产品设计:

局限表现补救方案
关键词盲区搜"型号 XR-7700"找不到混合检索(语义 + 关键词)
否定语义困难"不含"和"含有"向量相近结构化过滤
数值理解弱搜"100万以上"效果差结构化查询
时效性无法理解"最近"的含义元数据时间过滤

混合检索是最佳实践

语义检索 + BM25 关键词检索的混合方案,在绝大多数场景下优于纯语义检索。典型配比是 70% 语义 + 30% 关键词,但需要根据场景调优。


第四步:索引(Indexing)

向量数据库选型

数据库类型适用场景特点
Pinecone云托管快速上线全托管,易用
Weaviate开源/云中大型项目功能丰富,支持混合搜索
Milvus开源大规模高性能,国产
Qdrant开源/云中型项目Rust 编写,性能优秀
Chroma开源原型/小型极简,适合开发
pgvectorPG 扩展已有 PG无需新增组件

父子索引(Parent-Child Indexing)

解决"检索粒度"和"生成粒度"的矛盾:

问题:
  检索需要小块(精确匹配)
  生成需要大块(完整上下文)

解决方案 - 父子索引:

┌──────────────────────────────────────────┐
│  父文档(原始大块)                        │
│  "AI 产品的定价策略需要考虑多个因素。       │
│  首先是推理成本,包括 Token 消耗和          │
│  GPU 算力。其次是获客成本..."              │
├──────────┬──────────┬────────────────────┤
│ 子块 1    │ 子块 2    │ 子块 3             │
│ "AI 定价  │ "推理成本 │ "获客成本..."       │
│ 策略..."  │ Token..." │                   │
└──────────┴──────────┴────────────────────┘

  用子块做检索(精确)
  返回父文档做生成(完整)

用户反馈闭环优化索引

索引优化循环:

用户查询 → 检索结果 → 生成回答 → 用户反馈

                    ┌────────────────┤
                    ↓                ↓
               正向反馈          负向反馈
               (有帮助)        (不准确)
                    │                │
                    ▼                ▼
              提升该文档          分析失败原因
              检索权重            │
                              ┌──┴──┐
                              ↓     ↓
                           文档问题  检索问题
                              │     │
                              ▼     ▼
                          更新文档  调整索引/分块

第五步:重排序(ReRank)

为什么需要 ReRank?

初始检索(召回阶段):快但粗糙
    │  Top 20 结果

ReRank(精排阶段):慢但精确
    │  Top 5 结果

送入 LLM 生成回答

比喻:
  初始检索 = 从图书馆找到 20 本相关的书
  ReRank   = 精选最相关的 5 本放在桌上

ReRank 模型选型

模型中文能力速度部署方式
Cohere RerankerAPI
bge-reranker-v2-m3优秀自部署
Cross-Encoder取决于训练数据自部署
LLM-based Rerank优秀最慢API/自部署

ReRank 的效果提升

典型场景的效果提升:

                      无 ReRank    有 ReRank    提升
                     ──────────   ──────────   ─────
知识库问答 Top-3 命中率   72%         89%       +17%
文档搜索 MRR             0.65        0.81      +25%
FAQ 匹配准确率            80%         93%       +13%

RAG vs Prompt Engineering:如何选择

决策矩阵

             知识是否在模型训练数据中?

           ┌──────┴──────┐
           是            否
           │              │
     知识是否需要更新?    知识量大吗?
     ┌──────┴──────┐    ┌──────┴──────┐
     否            是    否            是
     │              │    │              │
  Prompt 就够    需要 RAG  Few-Shot     必须 RAG
                          也许够

两个关键影响因素

因素Prompt EngineeringRAG
知识时效性依赖训练数据(有截止日期)实时更新
知识专业度通用知识足够领域知识必须外挂

RAG 的局限性与落地挑战

常见失败原因

RAG 失败的五大原因:

1. 上下文整合问题
   检索到的多个片段之间互相矛盾或重复
   → 模型不知道该信任哪个

2. 推理问题
   检索到了正确信息但模型推理出错
   → 模型"有资料但不会用"

3. 响应格式化问题
   信息正确但输出格式不符合要求
   → 需要更强的 Prompt 约束

4. 上下文窗口利用率
   塞了太多无关内容,有效信息被稀释
   → 需要更精准的检索和 ReRank

5. 检索失败
   根本没找到相关文档
   → 分块策略或 Embedding 选型问题

面试高频问题

"你觉得 RAG 可能会在哪些场景失败?"

参考回答

RAG 的失败模式可以分为检索侧和生成侧:

检索侧失败

  • 文档分块不当导致关键信息被切断
  • Embedding 模型对特定领域术语理解不足
  • 用户 query 表述和文档表述差异大(语义鸿沟)

生成侧失败

  • 检索到的上下文互相矛盾
  • 上下文太多,模型"迷失"在大量信息中
  • 模型过度依赖预训练知识,忽略检索结果

应对策略

  • 混合检索(语义 + 关键词)
  • 查询改写/扩展
  • ReRank 精排
  • 上下文压缩
  • 回答引用来源,便于验证

RAG 评估体系

RAGAS 评估框架

RAGAS 四大核心指标:

┌──────────────────────────────────────────────┐
│                                              │
│  1. 忠实度(Faithfulness)                    │
│     回答是否忠于检索到的上下文?                 │
│     → 衡量是否"编造"了上下文中没有的信息         │
│                                              │
│  2. 回答相关性(Answer Relevancy)              │
│     回答是否切中用户问题?                      │
│     → 衡量回答与问题的匹配度                    │
│                                              │
│  3. 上下文精确率(Context Precision)           │
│     检索到的文档中有多少是真正相关的?            │
│     → 衡量检索的精确度                         │
│                                              │
│  4. 上下文召回率(Context Recall)              │
│     回答所需的信息是否都被检索到了?              │
│     → 衡量检索的完整度                         │
│                                              │
└──────────────────────────────────────────────┘

理想状态:四个指标都 > 0.8

生产环境 RAG 评价方法

评估方式适用阶段优缺点
RAGAS 自动评估开发/测试快速但可能不准
LLM-as-Judge开发/测试灵活但有偏差
人工标注评估上线前最准但成本高
用户反馈(点赞/踩)生产环境真实但有偏差
A/B 测试生产环境最可靠的对比方案

评估指标体系

完整的 RAG 评估指标体系:

第一层:检索质量
  ├── 召回率(Recall@K):相关文档是否被检索到
  ├── 精确率(Precision@K):检索结果中有多少是相关的
  ├── MRR:第一个正确结果的排名
  └── nDCG:考虑排序的综合指标

第二层:生成质量
  ├── 忠实度:是否忠于检索上下文
  ├── 准确率:事实是否正确
  ├── 完整性:是否回答了全部问题
  └── 相关性:是否切中问题

第三层:系统性能
  ├── 端到端延迟
  ├── Token 消耗
  ├── 检索耗时
  └── 系统可用性

第四层:业务指标
  ├── 用户满意度
  ├── 任务完成率
  ├── 人工干预率
  └── 留存率

RAG 优化策略

优化路线图

RAG 优化优先级:

Phase 1: 基础优化(1-2 周)
  ├── 调整 chunk_size 和 overlap
  ├── 选择合适的 Embedding 模型
  └── 优化 Prompt 模板
  效果提升:20-40%

Phase 2: 检索优化(2-4 周)
  ├── 引入混合检索(语义 + BM25)
  ├── 添加 ReRank
  ├── 查询改写/扩展
  └── 元数据过滤
  效果提升:15-25%

Phase 3: 高级优化(4-8 周)
  ├── 父子索引
  ├── 语义分块
  ├── 微调 Embedding 模型
  ├── Agent 驱动的多步检索
  └── 用户反馈闭环
  效果提升:10-20%

查询改写策略

用户原始查询可能不适合直接检索:

原始查询:"为什么系统这么慢?"

    ▼ 查询改写
改写 1:"系统性能优化 响应延迟高"
改写 2:"服务器响应时间慢的常见原因"
改写 3:"系统负载过高导致性能下降"

    ▼ 多路检索
合并去重所有检索结果

    ▼ ReRank
精选 Top-K 送入 LLM

利用 Agent 优化 RAG

传统 RAG:
  查询 → 单次检索 → 生成

Agent-RAG:
  查询 → 分析问题 → 制定检索策略

           ├── 子问题 1 → 检索 → 评估结果
           ├── 子问题 2 → 检索 → 评估结果
           └── 子问题 3 → 检索 → 评估结果

                          信息是否充足?
                          ├── 否 → 补充检索
                          └── 是 → 综合生成

知识库问答助手实战案例

案例:企业知识库智能问答

系统架构:

用户提问


┌─────────────┐
│  查询理解     │ ← 意图识别 + 实体提取 + 查询改写
└──────┬──────┘


┌─────────────┐     ┌──────────────┐
│  混合检索     │ ──→ │  向量数据库   │
│              │     │  Milvus      │
│  语义 + BM25 │ ──→ │  ES/BM25     │
└──────┬──────┘     └──────────────┘
       │ Top 20

┌─────────────┐
│  ReRank      │ ← bge-reranker-v2-m3
└──────┬──────┘
       │ Top 5

┌─────────────┐
│  答案生成     │ ← Claude Sonnet + Prompt 模板
└──────┬──────┘


┌─────────────┐
│  引用标注     │ ← 标注答案来源于哪个文档
└──────┬──────┘


用户看到带引用的回答

核心指标看板

知识库问答助手核心指标:

日维度监控:
  ├── 查询量:______ 次/天
  ├── 回答率:______%(未回答 = 检索失败)
  ├── 准确率:______%(人工抽检)
  ├── 平均延迟:______ ms
  └── Token 消耗:______ 万/天

周维度分析:
  ├── Top 10 高频问题
  ├── Top 10 失败问题
  ├── 用户满意度趋势
  └── 知识覆盖率变化

月维度复盘:
  ├── 新增文档数量和质量
  ├── 模型/Prompt 优化效果
  ├── 成本趋势
  └── 与人工客服对比

产品经理的 RAG 决策清单

阶段决策考虑因素
规划是否需要 RAG?知识时效性、专业度、数据量
数据数据源和更新频率?文档格式、质量、合规
分块分块策略?文档类型、检索粒度
检索纯语义还是混合?精度要求、关键词重要性
模型Embedding 和 LLM 选型?中文能力、成本、延迟
评估如何衡量效果?自动评估 + 人工抽检
上线灰度策略?先小范围验证再全量
运营知识库如何维护?更新频率、权责分工

延伸阅读

用 AI 思维做产品