一、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 工业界标准幻觉治理框架

经过多年的实践,工业界已经形成了一套成熟的 "从源头到结果" 的全流程幻觉治理框架:

源头控制 → 过程约束 → 结果校验 → 闭环迭代
  1. 源头控制:优化检索质量,确保输入生成模块的上下文是准确、完整、相关的
  2. 过程约束:通过提示词工程、引用增强生成等技术,约束大模型的生成行为
  3. 结果校验:对生成的回答进行自动校验,过滤掉幻觉内容
  4. 闭环迭代:收集幻觉样本,持续优化检索和生成模块

今天我们将重点学习过程约束结果校验这两个生成侧的核心环节。

二、从零构建可信生成模块

2.1 第一步:工业级反幻觉提示词工程

提示词工程是成本最低、效果最好的幻觉抑制方法。一个好的反幻觉提示词可以将幻觉率降低 40% 以上。

2.1.1 反幻觉提示词的四大核心原则
  1. 命令式语气:使用 "你必须"、"禁止你"、"严格按照" 等命令式词汇,避免使用 "请"、"希望你" 等请求式词汇
  2. 明确边界:清晰地告诉大模型什么可以做,什么不可以做
  3. 结构化输出:要求大模型按照指定的格式输出,减少自由发挥的空间
  4. 后果说明:明确告诉大模型如果违反规则会有什么后果
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 提示词优化技巧
  1. 降低温度参数:将temperature设置为 0.1 或更低,减少生成的随机性
  2. 限制最大生成长度:避免大模型生成过长的回答,减少编造的机会
  3. 使用少样本学习:在提示词中加入 1-2 个正确回答的示例,引导大模型遵循规则
  4. 负向提示:明确告诉大模型不要做什么,例如:"不要编造任何没有在参考资料中出现的信息"

2.2 第二步:引用增强生成(Citation-Enhanced Generation)

引用增强生成是目前工业界最有效的幻觉抑制技术,它可以将幻觉率降低 70% 以上。它的核心思想是:强制大模型在生成每个事实时都标注对应的引用来源,让每个陈述都有据可查

2.2.1 引用增强生成的工作原理
  1. 在提示词中要求大模型为每个事实性陈述标注对应的参考资料编号
  2. 大模型生成回答时,会自动在每个事实后面加上 [1]、[2] 等引用标记
  3. 后处理阶段可以验证这些引用是否准确,过滤掉编造的引用
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 信息不足的判断标准

我们可以从两个维度判断信息是否足够:

  1. 检索得分阈值:如果所有检索结果的得分都低于某个阈值,说明没有找到相关信息
  2. 上下文相关性:如果检索到的上下文与用户问题的相关性低于某个阈值,说明信息不足
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 自我反思的工作流程
  1. 大模型根据上下文生成初步回答
  2. 大模型对自己的回答进行反思和检查,判断每个事实是否都有上下文支持
  3. 如果发现幻觉内容,自动修正或删除
  4. 输出最终的修正后的回答
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 设计幻觉测试集

为了准确评估幻觉抑制效果,我们需要设计一个专门的幻觉测试集。测试集应该包含以下三类问题:

  1. 有明确答案的问题:知识库中有明确、完整的答案
  2. 答案不完整的问题:知识库中有部分相关信息,但不足以完整回答
  3. 完全没有答案的问题:知识库中完全没有相关信息

示例测试集

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
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐