04.2 - Self-RAG 与 Corrective RAG
定位: 让 RAG 系统具备"自我反思"和"纠错"能力,在生成过程中评估和修正自己的输出 面试高频度: ⭐⭐⭐⭐ 考查方式: Self-RAG 原理、反思 Token、CRAG 纠错流程、与基础 RAG 的区别
一、这是什么?为什么需要它?
是什么
Self-RAG 和 Corrective RAG (CRAG) 是两种让 RAG 系统具备自我评估能力的进阶架构:
传统 RAG:
检索 -> 生成(一步到位,没有质检)
Self-RAG:
检索 -> 自评(检索质量) -> 按需生成或再检索 -> 自评(生成质量)
CRAG:
检索 -> 评估 -> 如果质量低 -> 纠错(Web搜索/知识库补充) -> 再生成为什么需要自我反思?
传统 RAG 的问题:
检索结果不好 -> 依然被送入生成 -> 模型基于错误信息生成 -> 输出质量差
Self-RAG 的解法:
在"检索 -> 生成"之间加入反思步骤:
1. 检索结果质量自评 -> 不合格就重新检索
2. 生成结果质量自评 -> 不合格就修正
效果:提高输出质量,降低幻觉率二、原理拆解
2.1 Self-RAG 核心机制:反思 Token
Self-RAG 的关键创新是在训练/推理时引入特殊的反思 Token(Reflection Tokens):
生成过程中模型输出反思 Token 来表示对自己的评估:
检索决策 Token:
[Need to Retrieve] -> "需要检索外部知识"
[No Need to Search] -> "可以直接回答"
检索质量 Token:
[Relevant] -> "检索结果与问题相关"
[Irrelevant] -> "检索结果不相关"
[Partially Relevant]-> "检索结果部分相关"
生成质量 Token:
[Support Full] -> "生成内容完全基于检索结果"
[Support Partial] -> "部分支持"
[No Support] -> "生成内容没有检索结果支持"完整流程:
用户输入:"公司年假政策是什么?"
Step 1:判断是否需要检索
LLM 输出:[Need to Retrieve]
-> 执行检索
Step 2:评估检索结果
LLM 输出:[Relevant] 或 [Irrelevant]
-> 如果 [Relevant],进入生成
-> 如果 [Irrelevant],重新检索或拒绝回答
Step 3:基于检索结果生成
LLM 生成回答 + 输出 [Support Full]
-> 表示回答有充分依据2.2 Self-RAG 完整决策流程
+------------------------------------------------------------------+
| Self-RAG 决策流程 |
| |
| 用户查询 |
| | |
| v |
| 是否需要外部知识? |
| +-------------------+ |
| | [No Need] | [Need] |
| | 直接生成 | 检索 |
| | (greeting/已知) | | |
| +-------------------+ v |
| 评估检索结果 |
| +----------------+ |
| | [Relevant] | [Irrelevant] |
| | 基于结果生成 | 拒绝/再检索 |
| +-------+--------+ |
| | |
| v |
| 评估生成质量 |
| +-------------------+ |
| | [Support Full] | [Partial/No] |
| | 输出最终回答 | 修正/拒绝 |
| +-------------------+ |
+------------------------------------------------------------------+2.3 Corrective RAG(CRAG)纠错机制
CRAG 的焦点在"检索结果的纠错"——当检索结果质量不高时,启动纠错流程:
Step 1:检索
检索知识库 -> 得到 Top-K 文档块
Step 2:评估检索质量
+--------------+
| 评估器 |
| LLM/分类器 | -> [置信度高] -> 直接用于生成
| 评估检索 |
| 结果质量 | -> [置信度低] -> 启动纠错流程
+--------------+
Step 3:纠错(置信度低时)
纠错策略:
A. 关键词搜索(去检索全文原文)
B. Web 搜索(从互联网补充)
C. 知识库切换(换一个数据源)
D. 查询重写后重新检索
Step 4:融合与生成
合并原始检索结果 + 纠错后的补充结果 -> 生成回答三、图解全景
Self-RAG vs CRAG 对比
Self-RAG CRAG
========= ====
反思 Token 驱动 检索质量评估驱动
[Need to Retrieve] | 检索
| | |
v | v
检索 检索 | 评估检索质量
| | | |
v v | +-- 高 -> 直接生成
评估检索质量 评估检索 | +-- 低 -> 纠错流程
| | | |
+-- 好 -> 生成 | | +-- Web 搜索
+-- 差 -> 再检索 | | +-- 查询重写
| | | +-- 数据源切换
评估生成 生成 | |
| | | v
+-- 好 -> 输出 | | 融合结果
+-- 差 -> 修正 | | |
输出 | 生成
|
核心:全程自省 核心:检索纠错
训练时引入反思 Token 推理时加入评估步骤四、实战验证
4.1 CRAG 简化实现
python
# CRAG 的简化实现:基于置信度评估
from langchain_openai import ChatOpenAI
class SimpleCRAG:
def __init__(self, retriever, llm, web_search_tool=None):
self.retriever = retriever
self.llm = llm
self.web_search = web_search_tool
def assess_relevance(self, query, docs):
"""评估检索结果与查询的相关性"""
assessment_prompt = f"""
查询:{query}
检索到的文档:{docs}
这些文档与查询相关吗?
只回答:high / medium / low
"""
response = self.llm.invoke(assessment_prompt)
return response.content.strip().lower()
def invoke(self, query):
# Step 1: 初始检索
docs = self.retriever.invoke(query)
relevance = self.assess_relevance(query, docs)
# Step 2: 根据置信度处理
if relevance == "high":
context = "\n".join([d.page_content for d in docs])
else:
# Step 3: 纠错 - Web 搜索
if self.web_search:
web_results = self.web_search.invoke(query)
context = "\n".join([d.page_content for d in docs] + web_results)
else:
# 查询重写后重新检索
rewritten = self.llm.invoke(f"重写查询以提高检索质量:{query}")
docs2 = self.retriever.invoke(rewritten.content)
context = "\n".join([d.page_content for d in docs2])
# Step 4: 生成
final_prompt = f"基于以下信息回答问题:\n{context}\n\n问题:{query}"
return self.llm.invoke(final_prompt)五、面试视角
| 问题 | 答案要点 |
|---|---|
| Self-RAG 的核心创新是什么? | 引入反思 Token(Reflection Tokens),让模型在推理时自评"是否需要检索"、"检索结果是否相关"、"生成是否基于检索结果"。本质是让模型参与自身质量的判断 |
| Self-RAG 和 CRAG 的主要区别? | Self-RAG 需要专门训练(在训练时引入反思 Token),覆盖检索前、检索后、生成后的全链路评估。CRAG 不需要训练,只在推理时加入检索质量评估和纠错流程 |
| Self-RAG 的实践难点? | 1) 需要专门训练支持反思 Token 的模型,不是所有模型都能做;2) 推理时多次调用增加延迟;3) 反思 Token 的可靠性本身是挑战 |
| CRAG 适合什么场景? | 当知识库质量参差不齐、检索结果波动大时。CRAG 的纠错机制(Web搜索/查询重写)能显著提升检索质量。简单地说:知识库不太好时用 CRAG |
📚 相关链接
- **AgenticRAG** — Agent 自主检索的另一种形态
- **评估指标详解** — RAG 质量评估指标
- **HyDE与查询转换** — 查询优化配合纠错
- <- 返回 **进阶RAG索引**