幻觉:LLM 最棘手的问题

大模型的幻觉(Hallucination)——自信地输出错误或虚构的信息——是 2026 年 LLM 生产应用中最大的痛点。Stanford 2026 年 AI Index 报告显示,即使是最先进的模型,在事实性问答中的幻觉率仍有 3-8%,在专业领域更是高达 15-20%。幻觉不是 bug,而是 LLM 生成式架构的特性——但我们可以系统性地缓解它。

一、幻觉的分类

1.1 幻觉类型体系

类型描述示例严重性
事实性幻觉输出与事实不符“爱因斯坦出生于1890年”(实际1879)
来源幻觉虚构引用/出处编造不存在的论文
推理幻觉推理链条中出错正确前提但错误结论
时间幻觉时间线混乱“2024年奥运会在北京举办”
实体幻觉虚构人/组织/产品“微软CEO John Smith”
数值幻觉数字/计算错误“12×13=146”(实际156)
代码幻觉API/函数不存在调用不存在的库函数
自我幻觉虚构自身能力“我可以访问实时互联网”

1.2 幻觉产生的根因

┌──────────────────────────────────────────┐
│           幻觉根因分析                    │
├──────────────────────────────────────────┤
│                                          │
│  1. 训练数据问题                          │
│     ├── 训练数据中的错误信息              │
│     ├── 知识截止日期后的信息缺失          │
│     └── 长尾知识表示不足                  │
│                                          │
│  2. 模型架构问题                          │
│     ├── 自回归生成无法回溯修正            │
│     ├── 注意力机制对事实关注不足          │
│     └── 知识存储与检索机制不完善          │
│                                          │
│  3. 推理机制问题                          │
│     ├── 缺乏事实核查机制                  │
│     ├── 过度依赖模式匹配而非知识检索      │
│     └── 采样温度增加随机性                │
│                                          │
│  4. 交互问题                              │
│     ├── 模型倾向"回答"而非"承认不知道"    │
│     ├── 用户问题中的错误前提引导          │
│     └── 上下文中的错误信息被采纳          │
│                                          │
└──────────────────────────────────────────┘

二、幻觉检测方法

2.1 基于一致性的检测

class ConsistencyBasedDetector:
    """基于一致性的幻觉检测"""
    
    def __init__(self, llm_client, n_samples: int = 5):
        self.llm = llm_client
        self.n_samples = n_samples
    
    def detect(self, query: str, response: str) -> dict:
        """通过多次采样检测一致性"""
        # 1. 对同一问题生成多个回答
        responses = []
        for _ in range(self.n_samples):
            r = self.llm.generate(query, temperature=0.7)
            responses.append(r)
        
        # 2. 提取每个回答中的事实性陈述
        all_claims = []
        for r in responses:
            claims = self._extract_claims(r)
            all_claims.append(claims)
        
        # 3. 检查事实一致性
        consistency_scores = self._check_consistency(all_claims)
        
        # 4. 原始回答的事实性评估
        original_claims = self._extract_claims(response)
        original_scores = []
        
        for claim in original_claims:
            # 该claim在其他回答中出现的比例
            support_count = sum(
                1 for claims in all_claims 
                if self._claim_match(claim, claims)
            )
            original_scores.append({
                'claim': claim,
                'support_rate': support_count / len(all_claims),
                'likely_hallucination': support_count / len(all_claims) < 0.4
            })
        
        hallucination_rate = sum(
            1 for s in original_scores if s['likely_hallucination']
        ) / len(original_scores) if original_scores else 0
        
        return {
            'hallucination_rate': hallucination_rate,
            'claim_scores': original_scores,
            'overall_consistency': np.mean(consistency_scores)
        }
    
    def _extract_claims(self, text: str) -> list:
        """提取文本中的事实性陈述"""
        prompt = f"""提取以下文本中的所有事实性陈述,每条一行:
{text}"""
        result = self.llm.generate(prompt)
        return [line.strip() for line in result.split('\n') if line.strip()]
    
    def _claim_match(self, claim: str, other_claims: list) -> bool:
        """判断claim是否在other_claims中存在"""
        prompt = f"""判断以下陈述是否语义等价:
陈述A:{claim}
陈述B列表:{other_claims}

如果A与B中任一陈述语义等价,返回"是",否则"否"。"""
        return '是' in self.llm.generate(prompt)

2.2 基于来源验证的检测

class SourceVerificationDetector:
    """基于来源验证的幻觉检测"""
    
    def __init__(self, llm_client, search_client):
        self.llm = llm_client
        self.search = search_client
    
    def detect(self, response: str, sources: list = None) -> dict:
        """验证回答中的事实是否有来源支持"""
        # 1. 提取事实性陈述
        claims = self._extract_claims(response)
        
        # 2. 对每个claim进行验证
        results = []
        for claim in claims:
            # 如果有现成来源,在来源中验证
            if sources:
                verification = self._verify_in_sources(claim, sources)
            else:
                # 搜索验证
                verification = self._verify_by_search(claim)
            
            results.append({
                'claim': claim,
                'verdict': verification['verdict'],  # supported | refuted | unverifiable
                'evidence': verification['evidence'],
                'confidence': verification['confidence']
            })
        
        hallucination_claims = [
            r for r in results if r['verdict'] == 'refuted'
        ]
        unsupported_claims = [
            r for r in results if r['verdict'] == 'unverifiable'
        ]
        
        return {
            'total_claims': len(results),
            'supported': len([r for r in results if r['verdict'] == 'supported']),
            'refuted': len(hallucination_claims),
            'unverifiable': len(unsupported_claims),
            'hallucination_rate': len(hallucination_claims) / len(results),
            'details': results
        }
    
    def _verify_in_sources(self, claim: str, sources: list) -> dict:
        """在给定来源中验证claim"""
        prompt = f"""判断以下陈述是否被来源文本支持。

陈述:{claim}

来源文本:
{chr(10).join(f'[{i+1}] {s[:500]}' for i, s in enumerate(sources))}

判断:
- "supported":来源支持该陈述
- "refuted":来源与该陈述矛盾
- "unverifiable":来源无法验证该陈述

返回判断和依据。"""
        
        result = self.llm.generate(prompt)
        
        if 'supported' in result.lower():
            verdict = 'supported'
        elif 'refuted' in result.lower():
            verdict = 'refuted'
        else:
            verdict = 'unverifiable'
        
        return {
            'verdict': verdict,
            'evidence': result,
            'confidence': 0.8
        }
    
    def _verify_by_search(self, claim: str) -> dict:
        """通过搜索验证claim"""
        search_results = self.search.search(claim, top_k=3)
        return self._verify_in_sources(claim, search_results)

2.3 基于模型置信度的检测

class ConfidenceBasedDetector:
    """基于模型内部置信度的幻觉检测"""
    
    def __init__(self, model):
        self.model = model
    
    def detect(self, prompt: str) -> dict:
        """通过logits分析检测幻觉"""
        # 1. 获取模型输出和logits
        with torch.no_grad():
            outputs = self.model.generate(
                prompt, return_logits=True, output_scores=True
            )
        
        # 2. 计算每个token的置信度
        token_confidences = []
        for i, (token, score) in enumerate(
            zip(outputs.tokens, outputs.scores)
        ):
            # softmax得到概率
            probs = torch.softmax(score, dim=-1)
            token_prob = probs[token].item()
            token_confidences.append(token_prob)
        
        # 3. 分析低置信度区域
        low_confidence_threshold = 0.5
        low_conf_regions = [
            {'position': i, 'token': outputs.tokens[i], 'confidence': conf}
            for i, conf in enumerate(token_confidences)
            if conf < low_confidence_threshold
        ]
        
        # 4. 计算整体置信度指标
        avg_confidence = np.mean(token_confidences)
        min_confidence = np.min(token_confidences)
        
        return {
            'avg_confidence': avg_confidence,
            'min_confidence': min_confidence,
            'low_confidence_tokens': len(low_conf_regions),
            'hallucination_risk': 'high' if avg_confidence < 0.6
                                else 'medium' if avg_confidence < 0.8
                                else 'low',
            'low_conf_regions': low_conf_regions[:10]  # 前10个低置信度token
        }

三、幻觉缓解策略

3.1 RAG 增强

class RAGHallucinationMitigator:
    """RAG 增强缓解幻觉"""
    
    def __init__(self, llm_client, retrieval_client):
        self.llm = llm_client
        self.retrieval = retrieval_client
    
    def generate(self, query: str) -> dict:
        """RAG增强生成"""
        # 1. 检索相关文档
        docs = self.retrieval.search(query, top_k=5)
        
        # 2. 构建RAG Prompt
        prompt = self._build_rag_prompt(query, docs)
        
        # 3. 生成回答
        response = self.llm.generate(prompt)
        
        # 4. 后验证
        verification = self._verify_response(response, docs)
        
        return {
            'response': response,
            'sources': docs,
            'verification': verification,
            'hallucination_risk': verification['hallucination_rate']
        }
    
    def _build_rag_prompt(self, query: str, docs: list) -> str:
        return f"""请基于以下参考资料回答问题。如果资料中没有答案,请明确说明"根据现有资料无法回答"。

## 参考资料
{self._format_docs(docs)}

## 回答规则
1. 只使用参考资料中的信息
2. 每个事实性陈述必须标注来源 [1], [2] 等
3. 如果资料中有矛盾信息,指出矛盾
4. 不确定的信息要标注"可能"
5. 资料中未涉及的信息不要编造

## 问题
{query}

## 回答"""

3.2 自我验证机制

class SelfVerificationGenerator:
    """自我验证生成机制"""
    
    def __init__(self, llm_client):
        self.llm = llm_client
    
    def generate_with_verification(self, query: str) -> dict:
        """带自我验证的生成"""
        # Step 1: 初步生成
        initial_response = self.llm.generate(query)
        
        # Step 2: 自我事实核查
        fact_check = self._self_fact_check(query, initial_response)
        
        # Step 3: 如果发现幻觉,修正
        if fact_check['has_issues']:
            corrected = self._correct_hallucinations(
                query, initial_response, fact_check
            )
        else:
            corrected = initial_response
        
        # Step 4: 最终验证
        final_check = self._final_verification(query, corrected)
        
        return {
            'response': corrected,
            'initial_response': initial_response,
            'fact_check': fact_check,
            'final_verification': final_check,
            'corrections_made': fact_check['issues_found']
        }
    
    def _self_fact_check(self, query: str, response: str) -> dict:
        """自我事实核查"""
        prompt = f"""请对你自己的回答进行事实核查。

问题:{query}
你的回答:{response}

请逐句检查:
1. 每个事实性陈述是否准确?
2. 是否有编造的信息?
3. 是否有不确定但表述为事实的内容?
4. 数字和日期是否正确?

对每个可能的问题,标注:
- 陈述内容
- 问题类型(错误/编造/不确定)
- 修正建议

如果一切正确,返回"无问题"。"""
        
        result = self.llm.generate(prompt)
        
        has_issues = '无问题' not in result
        issues = []
        if has_issues:
            # 解析问题列表
            issues = self._parse_issues(result)
        
        return {
            'has_issues': has_issues,
            'issues_found': issues,
            'raw_check': result
        }
    
    def _correct_hallucinations(self, query, response, fact_check):
        """修正检测到的幻觉"""
        prompt = f"""请修正以下回答中的事实性错误。

原始问题:{query}
原始回答:{response}
检测到的问题:{fact_check['raw_check']}

修正规则:
1. 修正所有检测到的事实性错误
2. 不确定的信息添加"据我所知"等限定词
3. 无法确认的信息直接删除或标注"需查证"
4. 保持回答的连贯性和有用性

修正后的回答:"""
        
        return self.llm.generate(prompt)

3.3 多模型交叉验证

class CrossModelVerification:
    """多模型交叉验证"""
    
    def __init__(self, models: list):
        self.models = models  # 多个不同厂商的模型
    
    def generate_verified(self, query: str) -> dict:
        """多模型交叉验证生成"""
        # 1. 每个模型独立生成回答
        responses = []
        for model in self.models:
            r = model.generate(query, temperature=0.0)
            responses.append(r)
        
        # 2. 提取各模型的事实性陈述
        all_claims = []
        for r in responses:
            claims = self._extract_claims(r)
            all_claims.append(set(claims))
        
        # 3. 找出共识陈述和分歧陈述
        consensus = set.intersection(*all_claims) if all_claims else set()
        all_claims_set = set.union(*all_claims) if all_claims else set()
        disputed = all_claims_set - consensus
        
        # 4. 只保留共识陈述
        verified_response = self._build_response_from_consensus(
            query, consensus, responses[0]  # 以第一个模型的回答为模板
        )
        
        return {
            'response': verified_response,
            'model_count': len(self.models),
            'consensus_claims': len(consensus),
            'disputed_claims': len(disputed),
            'agreement_rate': len(consensus) / max(len(all_claims_set), 1)
        }

四、幻觉评估基准

4.1 评估指标

指标计算方式目标
事实准确率事实正确陈述/总事实陈述> 95%
幻觉率虚构陈述/总事实陈述< 5%
来源准确率正确引用/总引用> 90%
拒绝准确率正确拒绝不该回答的问题比例> 95%
过度拒绝率错误拒绝合理问题的比例< 5%
自校准ECE预期校准误差< 0.1

4.2 评估数据集构建

class HallucinationEvalDataset:
    """幻觉评估数据集"""
    
    CATEGORIES = {
        'factual_qa': {
            'description': '事实性问答',
            'examples': [
                {'q': '中国最长的河流是?', 'a': '长江', 'type': 'fact'},
                {'q': '光速是多少?', 'a': '约3×10^8 m/s', 'type': 'fact'},
            ]
        },
        'unanswerable': {
            'description': '无法回答的问题(测试是否承认不知道)',
            'examples': [
                {'q': '2028年的奥斯卡最佳影片是哪部?', 'a': '无法回答', 'type': 'refuse'},
                {'q': '张三的手机号码是多少?', 'a': '无法回答', 'type': 'refuse'},
            ]
        },
        'false_premise': {
            'description': '错误前提问题',
            'examples': [
                {'q': '林黛玉倒拔垂杨柳的故事告诉我们什么?', 
                 'a': '指出前提错误', 'type': 'correct'},
            ]
        },
        'multi_hop': {
            'description': '多跳推理(每跳都可能出错)',
            'examples': [
                {'q': '相对论提出者出生国家的首都人口是多少?',
                 'a': '需推理:爱因斯坦→德国→柏林→人口', 'type': 'reasoning'}
            ]
        }
    }

五、2026 前沿方向

  1. 检索增强自我修正:模型生成后自动检索验证并修正
  2. 事实性训练:用事实核查数据做偏好优化
  3. 知识编辑:直接在模型权重中修正错误知识
  4. 不确定性量化:模型输出附带校准的不确定性分数
  5. 因果推理增强:用因果推理替代模式匹配
  6. 工具增强事实性:自动调用搜索引擎、计算器等工具

结语

幻觉是 LLM 的"原罪"——源于其自回归生成架构和统计学习本质。完全消除幻觉在当前技术范式下不可能,但通过 RAG、自我验证、交叉验证等手段,可以将其控制在可接受范围内。

2026 年的最佳实践是假设模型可能幻觉,设计系统来兜底——就像工程中假设每个组件都可能失败一样。不要信任单一来源的回答,要建立多层验证机制。承认"不知道"比编造答案更有价值——这个原则应该编码进每一个 AI 系统的基因中。

加入讨论

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

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