自纠正RAG(Retrieval-Augmented Generation with self-correction)是在标准检索增强生成流程末尾增加验证与重写环节的一种架构。标准RAG先召回文档再生成,若召回内容本身不准确,模型就会顺着错误前提编造答案。自纠正RAG要求模型在给出初稿后,把答案拆成若干事实陈述,重新去向量库或搜索引擎里查找支撑证据,通过比对判断答案是否站得住脚。如果证据不足或相互冲突,系统会让大模型基于新检索结果二次生成,从而形成生成、验证、纠正的闭环。

自纠正RAG的核心运作原理
自纠正RAG的运转依赖三个子模块:初稿生成器、声明抽取器和验证检索器。初稿生成器与普通RAG中的生成模型无异,负责根据首次检索结果输出回答。声明抽取器通常是一个轻量大模型或规则脚本,把长篇回答切分为原子化的事实语句,例如将“李白出生于碎叶城,在蜀中长大”拆成“李白出生于碎叶城”和“李白在蜀中长大”两条。验证检索器针对每条声明构造查询,去知识库拉取相关段落,再交由判别模型计算声明与证据之间的矛盾分数。
矛盾分数的计算可以采用自然语言推断(NLI)模型,也可以让大模型输出“支持、中立、反对”三分类。当反对比例超过阈值,例如三分之一的声明被证据反对,就判定初稿不可信,进入纠正分支。纠正分支会把原问题与冲突证据一并交给生成模型重写,同时限制模型不得沿用被推翻的论断。这种机制相当于给大模型配备了事实复核员,把一次性生成变成可回滚的迭代过程。
从系统角度看,自纠正RAG把“检索”从生成前的前置步骤变成了生成后的质量闸门。它并不要求首次检索绝对精准,而是容忍一定噪声,用后续验证来过滤。实验表明,在医疗和法律问答中,引入生成后验证能把事实错误率降低两到四成,代价是额外增加一次检索与推理开销。对于准确率优先的场景,这种交换往往是划算的。
声明抽取与验证查询的构造方法
声明抽取的质量直接决定验证效果。若抽取过粗,多条事实揉在一起,验证器难以定位错误;若过细,又会放大检索负担。实践中常用提示词让模型按“主谓宾”结构输出独立句子,并附带原文出处编号。下面是一段用于声明抽取的简化提示与调用示例,使用Python配合OpenAI兼容接口:
import openai
def extract_claims(answer_text):
prompt = "请将下面的回答拆分为独立的事实陈述,每行一条,不要添加新信息:n" + answer_text
resp = openai.ChatCompletion.create(
model="gpt-4o-mini",
messages=[{"role":"user","content":prompt}]
)
lines = resp.choices[0].message.content.strip().split("n")
return [ln for ln in lines if ln.strip()]
answer = "爱因斯坦获得过1921年诺贝尔物理学奖,他提出了相对论。"
claims = extract_claims(answer)
print(claims)
验证查询的构造要避免直接拿整句声明去搜,因为声明里常含结论性表述,不利于匹配证据。更好的做法是抽取声明中的实体与关系,生成“实体+属性”的短查询。例如针对“李白出生于碎叶城”,可构造“李白 出生地 碎叶城”去知识图谱或文档库检索。若系统接的是向量库,则把声明改写为疑问句式如“李白的出生地是哪里”更能召回相关段落。查询改写模型可以用小规模的T5或规则模板实现,不必每次都调大模型。
验证阶段还需处理证据冲突的置信度问题。不同来源权威性不同,官方文档应比论坛帖子权重高。可给检索结果打来源权重,再计算加权矛盾分。当高权重来源反对而低权重来源支持时,仍应判为不可信。这一设计能防止模型被大量低质网页带偏,也是自纠正RAG相比单纯多次生成更稳健的原因。
落地实现与常见误区
在现有RAG管线中加自纠正层,推荐把验证做成异步可跳过分支。正常流量下只跑标准RAG,当答案长度超过一定值或用户显式点“核实”时才触发验证,以控制成本。下面给出一个最简闭环伪代码,展示如何根据验证结果决定是否重写:
def self_correct_rag(question, retriever, generator, validator):
ctx = retriever.search(question, top_k=5)
draft = generator.generate(question, ctx)
claims = extract_claims(draft)
conflict = 0
for claim in claims:
ev = retriever.search(claim, top_k=3)
label = validator.judge(claim, ev)
if label == "oppose":
conflict += 1
if conflict / len(claims) > 0.33:
new_ctx = retriever.search(question + " " + " ".join(claims), top_k=8)
return generator.generate(question, new_ctx)
return draft
常见误区之一是认为自纠正RAG可以完全消灭幻觉。实际上若知识库本身缺失关键事实,验证器也会因检不到证据而误判为中立,从而放过错误。因此它必须配合覆盖率较高的知识源,或显式提示“无证据时标记未知”。另一个误区是把验证模型和业务生成模型混用,导致模型为自己的输出辩护。验证最好用独立模型或规则,保持评判视角分离。
还有团队在落地时给每次生成都强制跑三遍验证,造成延迟翻倍却未显著提升质量。正确做法是按场景分级:闲聊机器人可关闭纠正,专业问答开启严格模式。同时把验证日志落盘,统计哪些类问题常被判冲突,反向优化首次检索的召回策略,才能让自纠正RAG越用越准。