07 - RAG检索增强生成

6阶段管线:从用户提问到精准回答的完整RAG流程

一、什么是RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)是一种让LLM"查阅资料再回答"的技术:

类比:传统LLM像"闭卷考试",RAG像"开卷考试"——可以翻书找答案。

二、6阶段RAG管线

                    RAG 6阶段管线
                    ══════════════

  用户提问: "公司的年假政策是什么?"
         │
         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 1: 查询改写 (QueryRewrite)                        │
  │                                                         │
  │  原始: "年假多少天?"                                    │
  │  上下文: 用户之前问了"关于假期"                         │
  │  改写: "公司的年假天数政策规定" (消解代词/补充上下文)   │
  └──────────────────────┬──────────────────────────────────┘
                         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 2: 检索缓存 (RetrievalCache)                      │
  │                                                         │
  │  Caffeine本地缓存, 相同查询直接返回                     │
  │  命中 → 跳到Stage 5                                    │
  │  未命中 → 继续                                         │
  └──────────────────────┬──────────────────────────────────┘
                         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 3: 多查询扩展 + RRF融合                            │
  │                                                         │
  │  LLM生成N个查询变体:                                    │
  │  Q1: "年假政策"                                         │
  │  Q2: "年假天数规定"                                     │
  │  Q3: "假期管理制度 年假"                                │
  │                                                         │
  │  并行搜索: Q1→结果集1, Q2→结果集2, Q3→结果集3          │
  │  RRF融合: 合并三个结果集, 按RRF公式重排序               │
  └──────────────────────┬──────────────────────────────────┘
                         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 4: 重排序 (Reranker)                              │
  │                                                         │
  │  LLM对每个结果打分(1-10):                               │
  │  Doc1: 9分 (高度相关)                                   │
  │  Doc2: 7分 (相关)                                       │
  │  Doc3: 4分 (弱相关)                                     │
  │  按Token预算截断 (保留高分文档)                         │
  └──────────────────────┬──────────────────────────────────┘
                         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 5: 上下文组装 (ContextAssembler)                   │
  │                                                         │
  │  编号引用格式:                                          │
  │  [1] 年假政策规定... (来源: 员工手册.pdf)               │
  │  [2] 假期管理... (来源: 公司制度.docx)                  │
  │                                                         │
  │  + 引用指令: "请根据以上内容回答,标注来源编号"          │
  └──────────────────────┬──────────────────────────────────┘
                         ▼
  ┌─────────────────────────────────────────────────────────┐
  │ Stage 6: 间接注入扫描 + LLM流式生成                     │
  │                                                         │
  │  扫描上下文 → 安全后传给LLM                             │
  │  系统提示词: "只使用检索到的内容回答,不要编造"          │
  │  → 流式生成最终回答 + 来源引用                          │
  └─────────────────────────────────────────────────────────┘

三、RRF多查询融合算法

这是本项目的核心创新之一:

RRF (Reciprocal Rank Fusion) 算法:

  问题: 不同查询变体返回不同的结果集,如何合并?

  查询1结果: [DocA(1), DocB(2), DocC(3)]    ← 排名1,2,3
  查询2结果: [DocB(1), DocD(2), DocA(3)]    ← 排名1,2,3
  查询3结果: [DocC(1), DocA(2), DocE(3)]    ← 排名1,2,3

  RRF公式: score(doc) = Σ 1/(k + rank_i)
           k = 60 (平滑常数)

  DocA: 1/(60+1) + 1/(60+3) + 1/(60+2) = 0.0484
  DocB: 1/(60+2) + 1/(60+1)             = 0.0323
  DocC: 1/(60+3) + 1/(60+1)             = 0.0318

  最终排序: DocA > DocB > DocC

  优势:
  · 不依赖绝对分数,只用排名
  · 对异常值鲁棒
  · 多个查询的"投票"效应提高召回质量

四、混合搜索

项目使用向量语义搜索 + MySQL全文索引的混合搜索:

HybridSearchService:

  用户查询
     │
     ├──→ 向量语义搜索 (Milvus)
  │   │   "年假政策" → embedding → 余弦相似度匹配
  │   │   优势: 理解语义,"年假" ≈ "带薪休假"
  │   │
  │   └──→ 关键词搜索 (MySQL FULLTEXT)
  │       "年假政策" → 分词 → 精确匹配
  │       优势: 精确匹配专有名词、编号
  │
  └──→ 合并去重 (content hash)
      │
      └──→ 返回统一结果集

  去重策略:
  SHA-256(content) 相同 → 保留评分更高的

五、严格RAG模式

反幻觉机制: 在严格RAG模式下,系统提示词会强制要求LLM"只能基于检索到的内容回答,如果检索内容不足以回答,明确说明'根据现有资料无法回答'"。这从根本上防止了LLM编造不存在的信息。

六、面试高频问题

Q: 为什么需要多查询扩展?
A: 用户的提问方式千变万化,单次查询可能匹配不到最佳结果。例如"年假多少天"可能匹配不到文档,但"年假政策规定"可以。多查询扩展用LLM生成多个语义等价但表达不同的查询,扩大检索覆盖面。RRF融合确保被多个查询同时召回的文档排名更高。
Q: RRF相比其他融合算法有什么优势?
A: RRF只依赖排名不依赖分数,这意味着不同检索系统(向量搜索返回余弦相似度,全文搜索返回BM25分数)的结果可以直接融合,不需要分数归一化。此外RRF计算简单高效(O(n)),对异常值鲁棒(一个查询返回的极端高分不会影响整体排序)。k=60是经验最优值。
Q: 如何防止RAG检索到被污染的文档?
A: RetrievedContextScanner在Stage 6对所有检索到的文档内容进行注入攻击扫描(复用输入扫描的正则模式)。如果发现文档中包含"忽略之前的指令"等攻击性内容,直接丢弃该文档,返回"无相关结果"。这防止了攻击者在文档中埋入恶意指令,通过RAG间接注入LLM。