Skip to content

01 - RAG 全链路详解

RAG 完整流水线

┌─────────────────────────────────────────────────────────────────┐
│                        RAG 全链路                               │
│                                                                 │
│  ┌─────────────────── 离线阶段(建索引)──────────────────────┐  │
│  │                                                           │  │
│  │  文档 → 分块(Chunking) → 向量化(Embedding) → 存入向量数据库│  │
│  │                                                           │  │
│  │  ┌──────┐   ┌──────────┐   ┌──────────┐   ┌───────────┐ │  │
│  │  │ PDF  │   │ Chunk 1  │   │ [0.1,0.3 │   │  Vector   │ │  │
│  │  │ MD   │──▶│ Chunk 2  │──▶│  0.7,...] │──▶│  Database │ │  │
│  │  │ HTML │   │ Chunk 3  │   │ (1536维)  │   │           │ │  │
│  │  └──────┘   └──────────┘   └──────────┘   └───────────┘ │  │
│  │  文档加载    文本分块       向量嵌入       向量存储        │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  ┌─────────────────── 在线阶段(查询)───────────────────────┐  │
│  │                                                           │  │
│  │  用户提问 → 向量化 → 检索 → 重排 → 组装 Prompt → LLM    │  │
│  │                                                           │  │
│  │  "退款政策?"                                               │  │
│  │      │                                                    │  │
│  │      ▼                                                    │  │
│  │  ┌──────────┐  ┌──────────┐  ┌────────┐  ┌────────────┐ │  │
│  │  │ Embedding│  │ 向量检索  │  │ Rerank │  │ LLM 生成   │ │  │
│  │  │ 查询向量化│─▶│ Top-K   │─▶│ 重排序  │─▶│ 基于文档   │ │  │
│  │  │          │  │ 最相似   │  │ 精排    │  │ 回答用户   │ │  │
│  │  └──────────┘  └──────────┘  └────────┘  └────────────┘ │  │
│  │                                                           │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1. 文档分块(Chunking)

为什么要分块?
┌────────────────────────────────────────────────────────┐
│  一篇 10 万字的文档塞不进 LLM 的上下文窗口              │
│  就算塞得下,相关的信息也会被稀释,影响回答质量           │
│  → 切成小块,只检索最相关的几块                         │
└────────────────────────────────────────────────────────┘

分块策略:

  1. 固定大小分块 (Fixed Size):
  ┌───────────────────────────────────────────────┐
  │  █████████████████████ │ ████████████████████ │ ...
  │   Chunk 1 (500 token)  │  Chunk 2 (500 token) │
  │         ┌──overlap──┐  │                      │
  └───────────────────────────────────────────────┘
  简单,但可能把句子切断

  2. 按句子/段落分块 (Semantic):
  ┌─────────────────┐ ┌──────────────────┐ ┌────────┐
  │  第一段的完整内容  │ │  第二段的完整内容  │ │ 第三段  │
  │  保持语义完整性    │ │                  │ │        │
  └─────────────────┘ └──────────────────┘ └────────┘
  保持语义完整,大小不均匀

  3. 递归分块 (Recursive):
  先按 \n\n 分段 → 太长再按 \n 分行 → 还太长按句号分
  ┌──────────────────────────────────────────┐
  │  尝试 \n\n → 每块太长?                    │
  │    → 尝试 \n → 每块太长?                  │
  │      → 尝试 。→ 每块太长?                 │
  │        → 强制按字数切                     │
  └──────────────────────────────────────────┘
  LangChain 默认使用此策略

  参数建议:
  ┌──────────────────────────────────────────────┐
  │  chunk_size:    500~1000 token               │
  │  chunk_overlap: 50~200 token(保留上下文)    │
  │                                              │
  │  太小: 丢失上下文,检索碎片化                  │
  │  太大: 噪音多,检索精度下降                    │
  └──────────────────────────────────────────────┘

2. 向量嵌入(Embedding)

把文本变成数字向量,语义相近的文本距离相近

  "今天天气真好"     → [0.12, 0.85, 0.33, ...]  ─┐
  "天气不错啊"       → [0.13, 0.82, 0.35, ...]  ─┤ 语义相近
                                                   │ → 向量距离近
  "明天有会议"       → [0.91, 0.15, 0.67, ...]    │
                                                   │ 语义不同
                                                   │ → 向量距离远

  向量空间可视化(降维到2D):

            天气好 ●  ● 天气不错        ← 聚在一起
                     ● 今天很晴

                              ● 明天开会
                                ● 下周有会议     ← 聚在一起

            ● 退款政策
              ● 如何退货                        ← 聚在一起


  常用 Embedding 模型(2025年):
  ┌──────────────────────────────────┬────────┬──────────────────────┐
  │  模型                            │ 维度   │ 特点                  │
  ├──────────────────────────────────┼────────┼──────────────────────┤
  │  nvidia/NV-Embed-v2 (开源)       │ 4096   │ MTEB 榜首,可自部署   │
  │  Cohere embed-v4                 │ 1024   │ 多语言最强,API 可用  │
  │  OpenAI text-embedding-3-large   │ 3072   │ 无需自托管的稳定选择  │
  │  BGE-M3 / GTE-Qwen2 (开源)      │ 1024+  │ 中文效果好,可自部署  │
  │  Voyage AI voyage-3              │ 1024   │ 代码/文档检索好       │
  └──────────────────────────────────┴────────┴──────────────────────┘
  注: text-embedding-3-large 在 MTEB 约 64 分,NV-Embed-v2 超过 70 分

3. 向量检索

相似度计算方法:

  余弦相似度 (Cosine Similarity) — 最常用

  sim(A, B) = A · B / (|A| × |B|)

  ┌──────────────────────────────────────────┐
  │           B                              │
  │          ╱                               │
  │         ╱  θ (夹角越小越相似)             │
  │        ╱                                 │
  │  ─────╱───────── A                       │
  │                                          │
  │  cos(0°) = 1.0   完全相同                │
  │  cos(90°) = 0.0  完全无关                │
  └──────────────────────────────────────────┘

向量数据库:
  ┌────────────────┬─────────────────────────────────┐
  │  Pinecone      │ 云端托管,开箱即用               │
  │  Weaviate      │ 开源,支持混合搜索               │
  │  Milvus        │ 开源,大规模场景                 │
  │  ChromaDB      │ 轻量级,适合原型开发             │
  │  pgvector      │ PostgreSQL 扩展,运维简单        │
  │  Qdrant        │ Rust 写的,性能好,Go SDK 完善   │
  └────────────────┴─────────────────────────────────┘

检索流程:
  查询: "退款要几天?"

     ▼ Embedding
  [0.2, 0.8, 0.5, ...]

     ▼ ANN 近似最近邻搜索
  ┌──────────────────────────────────────────────┐
  │  Top-3 结果:                                 │
  │  1. "退款将在 7 个工作日内到账"   score: 0.92 │
  │  2. "申请退款后可在订单页查看进度" score: 0.87 │
  │  3. "退货地址是..."            score: 0.61  │
  └──────────────────────────────────────────────┘

4. 重排序(Rerank)— 提升精度的关键步

为什么需要 Rerank?

  Embedding 检索是 "粗排"(快但不够精确)
  Rerank 是 "精排"(用更复杂的模型重新打分)

  ┌──────────────────────────────────────────────────────┐
  │                                                      │
  │  粗排 (Embedding):  Top-20 候选                       │
  │     │                                                │
  │     ▼                                                │
  │  精排 (Rerank):     对 Top-20 重新打分                │
  │     │               用交叉编码器 (cross-encoder)      │
  │     ▼               考虑 query 和 doc 的深层语义关系  │
  │  Top-5 最终结果                                       │
  │                                                      │
  │  为什么不直接用 Rerank?                               │
  │  → 太慢! 交叉编码器需要对每个候选逐一打分              │
  │  → 先用 Embedding 快速缩小范围,再用 Rerank 精排      │
  │                                                      │
  │  常用 Rerank 模型:                                    │
  │  • Cohere Rerank                                     │
  │  • Voyage Rerank                                     │
  │  • BGE Reranker (开源)                                │
  │  • Cross-Encoder (sentence-transformers)             │
  └──────────────────────────────────────────────────────┘

5. 高级 RAG 优化策略

┌──────────────────────────────────────────────────────────────┐
│                     RAG 优化技术                              │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  1. HyDE (假设性文档嵌入):                                    │
│     查询 → LLM 先生成一个"假答案" → 用假答案做检索            │
│     效果: 假答案和真文档在向量空间更接近                       │
│                                                              │
│  2. 查询改写 (Query Rewriting):                               │
│     "退款要多久" → LLM 改写成多个版本:                        │
│     • "退款处理时间"                                          │
│     • "退款到账周期"                                          │
│     • "退款需要几个工作日"                                     │
│     分别检索后合并结果 → 提高召回率                             │
│                                                              │
│  3. 混合搜索 (Hybrid Search):                                 │
│     向量搜索 (语义) + 关键词搜索 (BM25) 结果融合              │
│     ┌─────────────┐   ┌─────────────┐                       │
│     │ 向量搜索     │ + │ BM25 搜索   │ → 融合排序             │
│     │ (语义相关)   │   │ (关键词匹配) │                       │
│     └─────────────┘   └─────────────┘                       │
│                                                              │
│  4. 父子文档检索 (Parent-Child):                               │
│     小块用于检索(精确匹配)                                   │
│     命中后返回大块(保留上下文)                                │
│     ┌──────────────────────────────────┐                     │
│     │ 父文档 (大块,给 LLM 读)          │                     │
│     │ ┌──────┐ ┌──────┐ ┌──────┐     │                     │
│     │ │子文档1│ │子文档2│ │子文档3│     │                     │
│     │ │(检索) │ │(命中!)│ │(检索) │     │                     │
│     │ └──────┘ └──────┘ └──────┘     │                     │
│     └──────────────────────────────────┘                     │
│                                                              │
│  5. 多步推理 (Self-RAG / CRAG):                               │
│     LLM 评估检索结果是否有用                                   │
│     没用 → 重新检索或放弃                                     │
│     有用 → 生成回答 → 自我验证                                │
│                                                              │
└──────────────────────────────────────────────────────────────┘

6. 2025 年 RAG 新趋势

┌──────────────────────────────────────────────────────────────┐
│                   RAG 技术演进(2025)                        │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Agentic RAG(主流趋势)                                      │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  传统 RAG: 用户问 → 检索 → 生成(被动、固定流程)        │  │
│  │  Agentic RAG: Agent 主动规划检索策略                    │  │
│  │    • 判断是否需要检索(简单问题直接回答)                 │  │
│  │    • 决定检索哪个知识库                                  │  │
│  │    • 检索结果不够好时自动重新检索                        │  │
│  │    • 多跳推理:多轮检索逐步组装答案                      │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
│  层次化检索(KohakuRAG / RAPTOR)                             │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  文档 → 章节 → 段落 → 句子  四级树结构                   │  │
│  │  检索时根据问题粒度选择合适层级                           │  │
│  │  提升多粒度问题的召回精度                                 │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
│  多模态 RAG(新方向)                                         │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  文本 + 图像 + 表格 跨模态联合检索                       │  │
│  │  适合: 产品手册、技术文档、财报等混合内容                  │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
└──────────────────────────────────────────────────────────────┘

下一节: 02 - Go 实现 RAG