幻觉:AGI 之路的隐形地雷

当智能体开始"说话",它就不可避免地会"说错话"。幻觉(Hallucination)——即模型生成看似合理但与事实不符的内容——是 AGI 领域最棘手的安全问题之一。在聊天场景中,幻觉可能只是一次尴尬的回答;但在智能体场景中,幻觉可能导致错误的工具调用、误导性的决策建议,甚至危险的实际操作。

本文将从幻觉的根源出发,系统性地介绍检测、缓解和修复策略,帮助你构建更可信赖的智能体系统。

一、幻觉的根源:为什么会"胡说八道"

1.1 训练数据层面

大模型的幻觉根源深植于其训练过程中:

训练数据的噪声:互联网数据包含大量错误信息、过时信息和矛盾信息。模型在学习时,不可避免地吸收了这些噪声。当它"回忆"某个事实时,可能提取的是错误版本。

知识截止日期:模型的训练数据有截止日期,但世界在不断变化。模型可能自信地回答一个已经过时的事实——比如一个已经废弃的 API 方法。

长尾知识稀疏:对于常见话题,训练数据丰富,模型表现可靠。但在长尾领域(冷门技术、小众领域),训练数据稀疏,模型更容易通过"编造"来填补空白。

1.2 推理机制层面

自回归生成的本质缺陷:模型逐 token 生成文本,每一步都基于前面的内容。一旦早期生成了一个错误的前提,后续内容会围绕这个错误前提展开,形成"幻觉级联"。

缺乏知识边界感知:模型不知道自己"不知道什么"。它没有可靠机制来判断某个问题是否超出了自己的知识范围,因此倾向于对任何问题都给出回答,而不是说"我不知道"。

概率而非检索:模型生成的是"最可能"的答案,而非"最准确"的答案。在需要精确事实的场景中,这种差异就表现为幻觉。

1.3 智能体场景的特殊幻觉

在智能体场景中,幻觉有了新的表现形式:

  • 工具参数幻觉:模型编造不存在的参数值,或混淆不同工具的参数格式
  • 工具结果误解:工具返回了正确结果,但模型在解读时加入了自己的"想象"
  • 调用链幻觉:模型声称调用了某个工具但实际没有,或编造工具调用的返回结果
  • 上下文遗忘幻觉:在长对话中,模型"忘记"了早期确认的事实,生成与之前矛盾的内容

二、幻觉检测:从规则到模型

2.1 基于规则的检测

最基础的检测层是规则匹配:

import re
from typing import List, Tuple

class RuleBasedHallucinationDetector:
    def __init__(self):
        self.rules = [
            # 数字一致性检查
            self._check_number_consistency,
            # 实体引用检查
            self._check_entity_reference,
            # 日期合理性检查
            self._check_date_validity,
            # 自相矛盾检查
            self._check_self_contradiction,
        ]
    
    def _check_number_consistency(self, 
                                   claim: str, 
                                   sources: List[str]) -> List[Tuple[str, float]]:
        issues = []
        # 提取声明中的所有数字
        claim_numbers = set(re.findall(r'\d+\.?\d*', claim))
        
        for source in sources:
            source_numbers = set(re.findall(r'\d+\.?\d*', source))
            # 检查声明中的数字是否在来源中出现
            for num in claim_numbers:
                if num not in source_numbers:
                    issues.append((
                        f"数字 '{num}' 在来源中未找到",
                        0.7  # 置信度
                    ))
        return issues
    
    def _check_entity_reference(self, 
                                 claim: str, 
                                 entities: dict) -> List[Tuple[str, float]]:
        issues = []
        # 检查声明中提到的实体是否存在于已知实体库
        claim_entities = self._extract_entities(claim)
        for entity in claim_entities:
            if entity not in entities:
                issues.append((
                    f"实体 '{entity}' 不在已知实体库中",
                    0.6
                ))
        return issues
    
    def _check_date_validity(self, claim: str) -> List[Tuple[str, float]]:
        issues = []
        dates = re.findall(r'\d{4}年\d{1,2}月\d{1,2}日', claim)
        for date_str in dates:
            # 检查日期是否合理(如未来的日期、不可能的日期)
            try:
                from datetime import datetime
                d = datetime.strptime(date_str, '%Y年%m月%d日')
                if d.year < 1900 or d.year > 2100:
                    issues.append((f"日期 '{date_str}' 不合理", 0.8))
            except ValueError:
                issues.append((f"日期 '{date_str}' 格式无效", 0.9))
        return issues
    
    def _check_self_contradiction(self, 
                                   claim: str, 
                                   history: List[str]) -> List[Tuple[str, float]]:
        issues = []
        # 简化的矛盾检测:检查是否与历史声明中的数字/日期矛盾
        for prev in history:
            prev_numbers = set(re.findall(r'\d+\.?\d*', prev))
            claim_numbers = set(re.findall(r'\d+\.?\d*', claim))
            # 如果同一话题但数字不同,可能存在矛盾
            overlap = self._semantic_overlap(prev, claim)
            if overlap > 0.5:
                if prev_numbers != claim_numbers and prev_numbers and claim_numbers:
                    issues.append((
                        f"与历史声明可能矛盾: 之前说 {prev_numbers}, 现在说 {claim_numbers}",
                        overlap * 0.8
                    ))
        return issues

2.2 基于模型的检测

更高级的检测方案使用专门的模型来判断幻觉:

自一致性检查:让模型对同一问题生成多个回答,检查它们之间的一致性。高度不一致的回答更可能包含幻觉。

def self_consistency_check(model, question: str, n: int = 5) -> dict:
    """通过多次采样检测一致性"""
    responses = []
    for _ in range(n):
        resp = model.generate(question, temperature=0.7)
        responses.append(resp)
    
    # 提取关键事实并比较
    key_facts = [extract_key_facts(r) for r in responses]
    agreement_score = calculate_agreement(key_facts)
    
    return {
        "responses": responses,
        "agreement_score": agreement_score,
        "hallucination_risk": 1 - agreement_score,
        "consensus_facts": find_consensus(key_facts)
    }

交叉验证:用另一个模型(或同一模型的不同 prompt)来验证声明的真实性:

def cross_verify(claim: str, verifier_model) -> dict:
    """使用验证模型检查声明"""
    prompt = f"""请验证以下声明是否准确:
    
声明:{claim}

请搜索你的知识库,判断这个声明:
1. 是否准确
2. 是否包含编造的信息
3. 是否有遗漏的重要上下文

输出格式:
- 判定: [准确/部分准确/不准确/无法验证]
- 理由: [详细说明]
- 修正: [如果不准确,给出正确版本]
"""
    result = verifier_model.generate(prompt, temperature=0.1)
    return parse_verification_result(result)

2.3 基于检索的验证

RAG(检索增强生成)不仅是缓解幻觉的手段,也是检测幻觉的工具:

def retrieval_based_verify(claim: str, knowledge_base) -> dict:
    """通过检索知识库验证声明"""
    # 1. 从声明中提取关键信息
    key_entities = extract_entities(claim)
    key_facts = extract_facts(claim)
    
    # 2. 在知识库中检索相关文档
    search_results = knowledge_base.search(
        query=" ".join(key_entities + key_facts),
        top_k=5
    )
    
    # 3. 检查声明是否与检索结果一致
    support_score = 0
    contradiction_score = 0
    
    for result in search_results:
        similarity = semantic_similarity(claim, result.content)
        if similarity > 0.8:
            support_score += similarity
        elif has_contradiction(claim, result.content):
            contradiction_score += 1
    
    return {
        "support_score": support_score,
        "contradiction_score": contradiction_score,
        "verdict": "likely_hallucination" if contradiction_score > support_score else "likely_accurate",
        "sources": search_results
    }

三、幻觉缓解:从架构到策略

3.1 RAG:最有效的缓解手段

RAG 通过将外部知识注入模型上下文,显著降低幻觉率。但 RAG 本身也有坑:

检索质量决定生成质量:如果检索到的文档不相关或不准确,RAG 反而可能加剧幻觉。

优化检索的几个策略

class RobustRAG:
    def __init__(self, retriever, reranker, model):
        self.retriever = retriever
        self.reranker = reranker
        self.model = model
    
    def generate(self, query: str) -> str:
        # 第一步:多路检索
        results_dense = self.retriever.dense_search(query, top_k=20)
        results_sparse = self.retriever.sparse_search(query, top_k=20)
        
        # 第二步:融合排序
        merged = merge_results(results_dense, results_sparse)
        reranked = self.reranker.rerank(query, merged, top_k=5)
        
        # 第三步:过滤低质量结果
        filtered = [r for r in reranked if r.score > 0.5]
        
        if not filtered:
            # 无可靠来源时,明确告知模型
            return self.model.generate(
                f"问题:{query}\n注意:未找到可靠参考资料,请基于你的知识回答,"
                f"并在回答中明确标注哪些部分未经验证。"
            )
        
        # 第四步:构建防幻觉提示
        context = "\n\n".join([f"[来源{i+1}] {r.content}" for i, r in enumerate(filtered)])
        prompt = f"""基于以下参考资料回答问题。严格遵守以下规则:

1. 只使用参考资料中的信息
2. 如果参考资料不足以完全回答问题,明确说明哪些部分缺少信息
3. 不要编造任何不在参考资料中的具体数字、日期或人名
4. 在关键事实后标注来源编号

参考资料:
{context}

问题:{query}

回答:"""
        
        return self.model.generate(prompt, temperature=0.1)

3.2 约束解码

通过干预模型的生成过程来减少幻觉:

事实约束采样:在生成涉及事实性内容(数字、日期、人名)时,降低温度参数;在生成创意性内容时,适当提高温度。

def adaptive_temperature(text: str, base_temp: float = 0.7) -> float:
    """根据内容类型自适应调整温度"""
    # 检测是否包含事实性陈述
    fact_patterns = [
        r'\d{4}年', r'\d+%', r'根据.*研究', r'数据表明',
        r'第一名', r'总共', r'证明'
    ]
    
    fact_count = sum(1 for p in fact_patterns if re.search(p, text))
    
    if fact_count >= 2:
        return min(base_temp, 0.2)  # 事实性内容用低温度
    return base_temp

3.3 系统提示工程

精心设计的系统提示能显著减少幻觉:

你是一个严谨的知识助手。请遵循以下原则:

【核心原则】
1. 不确定时说"我不确定",不要编造答案
2. 区分"事实"和"推测",推测时明确标注
3. 引用具体数据时,标注信息来源和时间
4. 如果问题超出了你的知识范围,坦诚告知

【回答格式】
- 确认的事实:直接陈述
- 推测的内容:用"可能"、"据推测"等修饰
- 不确定的内容:明确说"这一点我不确定,建议查阅..."
- 超出范围:说"这超出了我目前的知识范围"

【禁止行为】
- 不要编造论文标题、作者或期刊名
- 不要编造不存在的 API 或函数名
- 不要给出没有依据的具体数字

四、幻觉修复:事后纠正

即使有了检测和缓解措施,幻觉仍可能发生。事后修复是最后一道防线。

4.1 引用验证

对于包含引用的生成内容,自动验证引用的真实性:

class CitationVerifier:
    def __init__(self, knowledge_base, web_search):
        self.kb = knowledge_base
        self.web = web_search
    
    def verify(self, text: str) -> dict:
        # 提取所有引用
        citations = extract_citations(text)
        
        results = []
        for citation in citations:
            # 在知识库中搜索
            kb_match = self.kb.search(citation.claim, top_k=3)
            
            # 在网络上搜索验证
            web_results = self.web.search(citation.claim)
            
            verified = any(
                semantic_similarity(citation.claim, r.content) > 0.7
                for r in kb_match + web_results
            )
            
            results.append({
                "citation": citation,
                "verified": verified,
                "sources": kb_match + web_results
            })
        
        return {
            "all_verified": all(r["verified"] for r in results),
            "results": results
        }

4.2 人类反馈循环

将幻觉检测与人类反馈结合:

def human_in_the_loop_correction(response: str, detector) -> str:
    """人工参与的幻觉修正流程"""
    # 自动检测
    issues = detector.detect(response)
    
    if not issues:
        return response
    
    # 高置信度问题自动标记
    high_confidence_issues = [i for i in issues if i.confidence > 0.8]
    low_confidence_issues = [i for i in issues if i.confidence <= 0.8]
    
    # 高置信度问题直接修正
    for issue in high_confidence_issues:
        if issue.type == "number_error":
            response = replace_number(response, issue.location, issue.correct_value)
        elif issue.type == "entity_error":
            response = replace_entity(response, issue.location, issue.correct_entity)
    
    # 低置信度问题送人工审核
    if low_confidence_issues:
        send_to_human_review(response, low_confidence_issues)
    
    return response

五、评估与监控

5.1 幻觉率指标

建立系统化的幻觉监控:

class HallucinationMonitor:
    def __init__(self):
        self.metrics = {
            "total_responses": 0,
            "flagged_responses": 0,
            "confirmed_hallucinations": 0,
            "hallucination_by_category": {
                "factual": 0,
                "tool_call": 0,
                "context_contradiction": 0,
                "fabricated_reference": 0,
            }
        }
    
    def log_response(self, response: str, 
                     detection_result: dict,
                     human_feedback: dict = None):
        self.metrics["total_responses"] += 1
        
        if detection_result["risk_score"] > 0.5:
            self.metrics["flagged_responses"] += 1
        
        if human_feedback and human_feedback.get("is_hallucination"):
            self.metrics["confirmed_hallucinations"] += 1
            category = human_feedback.get("category", "factual")
            self.metrics["hallucination_by_category"][category] += 1
    
    def get_hallucination_rate(self) -> dict:
        total = self.metrics["total_responses"]
        if total == 0:
            return {"rate": 0}
        
        return {
            "overall_rate": self.metrics["confirmed_hallucinations"] / total,
            "flag_rate": self.metrics["flagged_responses"] / total,
            "by_category": {
                k: v / total 
                for k, v in self.metrics["hallucination_by_category"].items()
            }
        }

5.2 持续改进

幻觉缓解不是一次性工程,而是持续优化的过程:

  • 定期分析幻觉案例:归类幻觉类型,找出模式
  • 更新知识库:将新发现的正确事实加入知识库
  • 优化提示模板:根据幻觉模式调整系统提示
  • 模型版本管理:新模型版本上线前,进行幻觉率回归测试

结语

幻觉是 AGI 发展道路上的结构性挑战,不可能一劳永逸地解决。但通过"检测-缓解-修复"的三层防御体系,我们可以将幻觉率控制在可接受的范围内。

关键不是追求零幻觉——这在当前技术条件下不现实——而是建立一套可靠的监控和纠正机制,让智能体在出错时能被发现、被修正、被预防。信任不是来自完美,而是来自透明和可纠错。

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。