工业级大模型学习之路013:RAG零基础入门教程(第九篇):RAG幻觉治理
一、RAG 幻觉的本质与治理框架
1.1 什么是 RAG 幻觉?
RAG 幻觉是指大模型生成的回答中包含了检索上下文中不存在的、未经证实的或错误的信息。即使检索到了正确的信息,大模型仍然可能编造内容,这是 RAG 系统从 "能用" 到 "好用" 的最大障碍。
2026 年最新行业数据:
- 未经优化的 Naive RAG 系统平均幻觉率高达 35%-50%
- 经过完整优化的工业级 RAG 系统幻觉率可控制在 5% 以下
- 金融、法律、医疗等高风险领域要求幻觉率低于 1%
1.2 RAG 幻觉的科学分类(2026 工业界标准)
根据幻觉产生的来源和表现形式,RAG 幻觉可以分为三大类,每一类的解决方法完全不同:
| 幻觉类型 | 定义 | 典型表现 | 占比 | 主要解决方法 |
|---|---|---|---|---|
| 事实性幻觉 | 编造上下文中不存在的事实、数据、时间、人物等 | "根据文档,RAG 技术于 2021 年提出"(实际是 2020 年) | 60% | 提示词约束、引用增强生成 |
| 引用幻觉 | 错误标注引用来源,或编造不存在的引用 | "根据文档 [3],..."(但文档 [3] 中没有相关内容) | 25% | 引用校验、后处理过滤 |
| 上下文外幻觉 | 回答中包含了检索上下文之外的信息 | 回答中混入了大模型训练数据中的知识 | 15% | 拒绝回答机制、知识边界控制 |
1.3 生成侧幻觉产生的三大根本原因
很多人误以为幻觉都是检索不准导致的,但实际上超过 60% 的幻觉是在生成阶段产生的。
原因 1:大模型的 "补全本能"
大模型的训练目标是 "预测下一个 token",它天生倾向于生成连贯、流畅的文本。当检索到的信息不完整或模糊时,大模型会自动 "补全" 缺失的部分,即使这些补全的内容是错误的。
示例:
- 检索上下文:"RAG 技术由 Meta 公司于 2020 年提出"
- 大模型生成:"RAG 技术由 Meta 公司的 Lewis 等人于 2020 年在 ACL 会议上提出"
- 问题:上下文中并没有提到 "Lewis 等人" 和 "ACL 会议",这些都是大模型编造的
原因 2:检索 - 生成断裂
检索模块和生成模块是两个独立的组件,它们之间缺乏有效的反馈通道。生成模块无法判断哪些检索结果是相关的,哪些是噪声,它会平等地对待所有输入的上下文。
示例:
- 检索结果中包含了 3 个相关文档和 2 个不相关文档
- 大模型可能会从不相关的文档中提取信息,甚至将不同文档的信息错误地融合在一起
原因 3:指令遵循能力不足
尤其是本地部署的 7B 级小模型,指令遵循能力相对较弱。即使你在提示词中明确要求 "只使用参考资料中的信息",大模型仍然可能会使用自己训练数据中的知识。
示例:
- 提示词:"请只根据以下参考资料回答问题,不要使用你自己的知识"
- 参考资料:"苹果公司成立于 1976 年"
- 大模型生成:"苹果公司成立于 1976 年,由史蒂夫・乔布斯、史蒂夫・沃兹尼亚克和罗纳德・韦恩创立"
- 问题:参考资料中并没有提到三位创始人的名字
1.4 2026 工业界标准幻觉治理框架
经过多年的实践,工业界已经形成了一套成熟的 "从源头到结果" 的全流程幻觉治理框架:
源头控制 → 过程约束 → 结果校验 → 闭环迭代
- 源头控制:优化检索质量,确保输入生成模块的上下文是准确、完整、相关的
- 过程约束:通过提示词工程、引用增强生成等技术,约束大模型的生成行为
- 结果校验:对生成的回答进行自动校验,过滤掉幻觉内容
- 闭环迭代:收集幻觉样本,持续优化检索和生成模块
今天我们将重点学习过程约束和结果校验这两个生成侧的核心环节。
二、从零构建可信生成模块
2.1 第一步:工业级反幻觉提示词工程
提示词工程是成本最低、效果最好的幻觉抑制方法。一个好的反幻觉提示词可以将幻觉率降低 40% 以上。
2.1.1 反幻觉提示词的四大核心原则
- 命令式语气:使用 "你必须"、"禁止你"、"严格按照" 等命令式词汇,避免使用 "请"、"希望你" 等请求式词汇
- 明确边界:清晰地告诉大模型什么可以做,什么不可以做
- 结构化输出:要求大模型按照指定的格式输出,减少自由发挥的空间
- 后果说明:明确告诉大模型如果违反规则会有什么后果
2.1.2 2026 工业界标准反幻觉提示词模板
这是经过腾讯、字节跳动等大厂验证的反幻觉提示词模板,可直接复用:
def _build_anti_hallucination_prompt(self, question, context_docs):
"""构建工业级反幻觉提示词"""
context = "\n\n".join([f"[{i+1}] {doc['text']}" for i, doc in enumerate(context_docs)])
prompt = f"""【系统指令】
你是一个严谨、可靠的知识问答助手。你的唯一任务是根据提供的参考资料回答用户的问题。
你必须严格遵守以下所有规则,违反任何一条规则都是严重错误:
1. 【绝对禁止编造】严禁编造任何事实、数据、时间、人物、事件或引用。所有回答必须完全基于参考资料中的内容。
2. 【信息不足时拒绝回答】如果参考资料中没有足够的信息来回答问题,或者你对答案不确定,必须明确回答:"抱歉,参考资料中没有足够的信息来回答这个问题。"
3. 【禁止使用外部知识】绝对不能使用你自己训练数据中的任何知识,只能使用提供的参考资料。
4. 【必须标注引用】回答中的每个事实性陈述都必须标注对应的参考资料编号,格式为[数字]。例如:"RAG技术于2020年提出[1]。"
5. 【引用必须准确】标注的引用编号必须对应参考资料中确实包含该信息的文档。
6. 【保持客观中立】只陈述参考资料中的事实,不要添加任何个人观点、推测或解释。
【参考资料】
{context}
【用户问题】
{question}
【回答要求】
- 回答要简洁、准确、有条理
- 每个事实都必须标注引用
- 如果信息不足,直接拒绝回答,不要尝试猜测
- 不要提及"参考资料"、"根据文档"等字样,直接给出答案和引用
【你的回答】"""
return prompt
2.1.3 提示词优化技巧
- 降低温度参数:将
temperature设置为 0.1 或更低,减少生成的随机性 - 限制最大生成长度:避免大模型生成过长的回答,减少编造的机会
- 使用少样本学习:在提示词中加入 1-2 个正确回答的示例,引导大模型遵循规则
- 负向提示:明确告诉大模型不要做什么,例如:"不要编造任何没有在参考资料中出现的信息"
2.2 第二步:引用增强生成(Citation-Enhanced Generation)
引用增强生成是目前工业界最有效的幻觉抑制技术,它可以将幻觉率降低 70% 以上。它的核心思想是:强制大模型在生成每个事实时都标注对应的引用来源,让每个陈述都有据可查。
2.2.1 引用增强生成的工作原理
- 在提示词中要求大模型为每个事实性陈述标注对应的参考资料编号
- 大模型生成回答时,会自动在每个事实后面加上 [1]、[2] 等引用标记
- 后处理阶段可以验证这些引用是否准确,过滤掉编造的引用
2.2.2 实现引用解析与校验
我们需要实现一个引用解析和校验模块,自动检查大模型生成的引用是否准确:
import re
def _parse_and_validate_citations(self, answer, context_docs):
"""
解析并校验回答中的引用
:param answer: 大模型生成的回答
:param context_docs: 检索到的上下文文档
:return: 校验后的回答,过滤掉无效引用对应的内容
"""
# 提取所有引用编号
citation_pattern = re.compile(r'\[(\d+)\]')
citations = citation_pattern.findall(answer)
if not citations:
return answer
# 转换为整数
citations = [int(c) for c in citations]
# 校验每个引用是否有效
valid_citations = []
for c in citations:
if 1 <= c <= len(context_docs):
valid_citations.append(c)
# 如果没有有效引用,返回信息不足
if not valid_citations:
return "抱歉,参考资料中没有足够的信息来回答这个问题。"
# 过滤掉无效引用对应的内容(简化版,实际项目中可以更精细)
# 这里我们只保留有有效引用的句子
sentences = re.split(r'(?<=[。!?])', answer)
valid_sentences = []
for sentence in sentences:
if not sentence.strip():
continue
sentence_citations = citation_pattern.findall(sentence)
if not sentence_citations:
# 没有引用的句子,直接丢弃
continue
# 检查句子中的引用是否至少有一个有效
has_valid = any(int(c) in valid_citations for c in sentence_citations)
if has_valid:
valid_sentences.append(sentence)
if not valid_sentences:
return "抱歉,参考资料中没有足够的信息来回答这个问题。"
# 重新组合有效句子
validated_answer = "".join(valid_sentences)
# 移除无效引用标记
for c in citations:
if c not in valid_citations:
validated_answer = validated_answer.replace(f"[{c}]", "")
return validated_answer
2.2.3 引用格式优化
为了让引用更清晰易读,我们可以在回答的末尾添加引用来源的详细信息:
def _add_citation_sources(self, answer, context_docs):
"""在回答末尾添加引用来源的详细信息"""
citation_pattern = re.compile(r'\[(\d+)\]')
citations = citation_pattern.findall(answer)
if not citations:
return answer
# 去重并排序
citations = sorted(list(set([int(c) for c in citations])))
# 生成引用来源列表
sources = ["\n\n---\n**引用来源:**"]
for c in citations:
if 1 <= c <= len(context_docs):
doc = context_docs[c-1]
source_info = f"[{c}] {doc['metadata'].get('source', '未知来源')}"
if 'page' in doc['metadata']:
source_info += f",第{doc['metadata']['page']}页"
sources.append(source_info)
return answer + "\n".join(sources)
2.3 第三步:拒绝回答机制
拒绝回答机制是防止幻觉的最后一道防线。当检索到的信息不足以回答用户的问题时,大模型应该明确拒绝回答,而不是编造内容。
2.3.1 信息不足的判断标准
我们可以从两个维度判断信息是否足够:
- 检索得分阈值:如果所有检索结果的得分都低于某个阈值,说明没有找到相关信息
- 上下文相关性:如果检索到的上下文与用户问题的相关性低于某个阈值,说明信息不足
2.3.2 实现拒绝回答机制
在 RAGSystem 的 query 方法中添加信息不足的判断逻辑:
def query(self, question, top_k=5, stream=False):
print(f"\n用户问题:{question}")
# 1. 高级检索
retrieved_docs = self.retriever.advanced_search(
query=question,
top_k=top_k,
retrieval_method="sentence_window",
window_size=5
)
# 2. 重排序
reranked_docs = self.retriever.reranker.rerank(question, retrieved_docs, top_k=top_k)
# 【新增】信息不足判断
if not reranked_docs:
return "抱歉,知识库中没有找到相关信息,无法回答您的问题。"
# 检查最高得分是否低于阈值
min_relevance_threshold = 0.5 # 可根据实际情况调整
if reranked_docs[0]["rerank_score"] < min_relevance_threshold:
return "抱歉,知识库中没有找到足够相关的信息,无法回答您的问题。"
print(f"✅ 检索到 {len(reranked_docs)} 个相关文档,最高得分:{reranked_docs[0]['rerank_score']:.4f}")
# 3. 构建反幻觉提示词
prompt = self._build_anti_hallucination_prompt(question, reranked_docs)
# 4. 生成回答
if stream:
return self.llm.generate(prompt, stream=True)
else:
answer = self.llm.generate(prompt, temperature=0.1, max_new_tokens=1024)
# 5. 解析并校验引用
validated_answer = self._parse_and_validate_citations(answer, reranked_docs)
# 6. 添加引用来源
final_answer = self._add_citation_sources(validated_answer, reranked_docs)
print(f"回答:{final_answer}")
return final_answer
2.4 第四步:自我反思与事实校验
自我反思是一种进阶的幻觉抑制技术,它让大模型先检查自己的回答是否符合上下文,然后再输出。这种方法可以进一步将幻觉率降低 15%-20%。
2.4.1 自我反思的工作流程
- 大模型根据上下文生成初步回答
- 大模型对自己的回答进行反思和检查,判断每个事实是否都有上下文支持
- 如果发现幻觉内容,自动修正或删除
- 输出最终的修正后的回答
2.4.2 实现轻量化自我反思
为了避免增加太多延迟,我们实现一个轻量化的自我反思模块:
def _self_reflection(self, answer, context_docs):
"""
轻量化自我反思:让大模型检查自己的回答是否符合上下文
"""
context = "\n\n".join([f"[{i+1}] {doc['text']}" for i, doc in enumerate(context_docs)])
reflection_prompt = f"""【反思任务】
请检查以下回答是否完全基于提供的参考资料。
如果回答中有任何内容不在参考资料中,或者引用标注错误,请指出并修正。
如果回答完全正确,请直接返回原回答。
【参考资料】
{context}
【待检查的回答】
{answer}
【反思要求】
1. 逐句检查回答中的每个事实
2. 标记出所有没有在参考资料中出现的内容
3. 修正错误的引用标注
4. 返回修正后的回答,不要添加任何其他内容
【修正后的回答】"""
corrected_answer = self.llm.generate(reflection_prompt, temperature=0.1, max_new_tokens=1024)
return corrected_answer
2.4.3 性能与效果的平衡
自我反思会增加一次大模型调用,使响应时间增加一倍。因此,我们可以根据实际情况选择是否开启:
- 高风险场景(金融、法律、医疗):强制开启
- 普通场景:可以关闭,或只对得分较低的回答开启
- 性能敏感场景:可以使用更小的模型来做反思
2.5 集成到完整 RAG 流水线
现在,我们已经实现了所有生成侧优化技术,将它们集成到完整的 RAG 流水线中:
def query(self, question, top_k=5, stream=False, enable_reflection=False):
print(f"\n用户问题:{question}")
# 1. 高级检索
retrieved_docs = self.retriever.advanced_search(
query=question,
top_k=top_k,
retrieval_method="sentence_window",
window_size=5
)
# 2. 重排序
reranked_docs = self.retriever.reranker.rerank(question, retrieved_docs, top_k=top_k)
# 3. 信息不足判断
if not reranked_docs or reranked_docs[0]["rerank_score"] < 0.5:
return "抱歉,知识库中没有找到足够相关的信息,无法回答您的问题。"
# 4. 构建反幻觉提示词
prompt = self._build_anti_hallucination_prompt(question, reranked_docs)
# 5. 生成初步回答
answer = self.llm.generate(prompt, temperature=0.1, max_new_tokens=1024)
# 6. 解析并校验引用
validated_answer = self._parse_and_validate_citations(answer, reranked_docs)
# 7. 自我反思(可选)
if enable_reflection:
validated_answer = self._self_reflection(validated_answer, reranked_docs)
# 8. 添加引用来源
final_answer = self._add_citation_sources(validated_answer, reranked_docs)
print(f"✅ 回答生成完成")
return final_answer
三、效果测试与参数调优:量化验证幻觉抑制效果
3.1 设计幻觉测试集
为了准确评估幻觉抑制效果,我们需要设计一个专门的幻觉测试集。测试集应该包含以下三类问题:
- 有明确答案的问题:知识库中有明确、完整的答案
- 答案不完整的问题:知识库中有部分相关信息,但不足以完整回答
- 完全没有答案的问题:知识库中完全没有相关信息
示例测试集:
HALLUCINATION_TEST_SET = [
# 有明确答案的问题
{"question": "RAG技术是由哪家公司在哪一年提出的?", "ground_truth": "Meta公司,2020年"},
{"question": "JVM的堆内存分为哪几个代?", "ground_truth": "年轻代、老年代、元空间"},
# 答案不完整的问题
{"question": "RAG技术的优缺点是什么?", "ground_truth": "优点:减少幻觉、支持动态知识更新;缺点:检索延迟高、上下文长度有限"},
# 完全没有答案的问题
{"question": "火星上有多少个探测器?", "ground_truth": "信息不足"},
{"question": "苹果公司的最新手机型号是什么?", "ground_truth": "信息不足"}
]
3.2 使用 Ragas 进行自动化幻觉评估
Ragas 是目前最权威的 RAG 评估框架,它的Faithfulness(忠实度)指标专门用于衡量幻觉程度。Faithfulness的取值范围是 0 到 1,值越高表示幻觉越少,生产环境要求Faithfulness ≥ 0.85。
3.2.1 实现 Ragas 评估脚本
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy
from datasets import Dataset
def evaluate_hallucination(rag_system, test_set):
"""
使用Ragas评估幻觉抑制效果
"""
questions = []
contexts = []
answers = []
for test_case in test_set:
question = test_case["question"]
questions.append(question)
# 获取检索上下文
retrieved_docs = rag_system.retriever.advanced_search(question, top_k=5)
context_texts = [doc["text"] for doc in retrieved_docs]
contexts.append(context_texts)
# 获取RAG系统的回答
answer = rag_system.query(question)
answers.append(answer)
# 构建Ragas评估数据集
dataset = Dataset.from_dict({
"question": questions,
"contexts": contexts,
"answer": answers
})
# 执行评估
result = evaluate(
dataset=dataset,
metrics=[faithfulness, answer_relevancy],
llm=rag_system.llm,
embeddings=rag_system.retriever.bge_embedding
)
return result
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)