大模型幻觉控制的提示词策略

通过提示词工程降低 LLM 幻觉率:接地、引用、自检与多模型交叉验证


幻觉的本质

LLM 的幻觉(Hallucination)是指模型生成看似合理但实际上不准确或完全虚构的内容。理解幻觉的本质是有效控制它的前提。

幻觉分类

┌──────────────────────────────────────────────────────────────┐
│                     LLM 幻觉分类                             │
├───────────────────┬──────────────────────────────────────────┤
│  事实性幻觉       │ 生成与真实世界不符的事实                  │
│  (Factual)       │ 例:"爱因斯坦获得 1922 年物理诺贝尔奖"    │
│                  │ (实际是 1921 年)                        │
├───────────────────┼──────────────────────────────────────────┤
│  忠实性幻觉       │ 生成与输入上下文不符的内容                │
│  (Faithfulness)  │ 例:摘要中包含原文没有的信息               │
├───────────────────┼──────────────────────────────────────────┤
│  一致性幻觉       │ 模型自我矛盾                             │
│  (Consistency)   │ 例:前面说 A 是对的,后面又说 A 是错的    │
├───────────────────┼──────────────────────────────────────────┤
│  捏造性幻觉       │ 完全虚构不存在的实体、事件或引用          │
│  (Fabrication)   │ 例:编造不存在的论文、API、库名            │
└───────────────────┴──────────────────────────────────────────┘

幻觉产生的根因

训练数据 ──→ 统计模式学习 ──→ 概率性生成
                │
         不区分"事实"和"模式"
                │
                v
  模型学到了"看起来像对的"的文本模式
  而不是"实际上是对的"的事实知识

一、接地策略(Grounding)

接地(Grounding)是将 LLM 的输出"锚定"到可信的信息源上,而不是让它自由发挥。

策略一:提供参考材料

<system>
你是一个严谨的信息分析助手。
你只能基于提供的参考材料回答问题。
如果参考材料中没有相关信息,必须明确说明"根据提供的材料,无法回答此问题"。
严禁使用参考材料以外的知识。
</system>

<reference_materials>
<document id="doc1" source="annual_report_2025.pdf">
{document_content_1}
</document>

<document id="doc2" source="market_analysis_q4.xlsx">
{document_content_2}
</document>
</reference_materials>

<task>
基于以上参考材料,回答以下问题:
{user_question}
</task>

<constraints>
1. 所有结论必须引用具体的文档来源(使用 [doc_id] 格式)
2. 如果答案需要推理,标明推理依据和推理过程
3. 对不确定的信息标注置信度
4. 不得编造参考材料中不存在的数据或事实
5. 如果不同文档的信息矛盾,指出矛盾并列出两方说法
</constraints>

策略二:RAG + 接地提示

class GroundedRAGPrompt:
    """RAG + 接地提示词模板"""

    TEMPLATE = """<system>
你是一个基于知识库的问答助手。
你的回答必须严格基于检索到的文档片段。
</system>

<retrieved_context>
{context_with_sources}
</retrieved_context>

<question>
{question}
</question>

<answer_rules>
1. 仅使用上述检索结果中的信息回答
2. 每个关键陈述后附加来源引用 [source_N]
3. 如果检索结果不包含足够信息,回答"根据现有信息无法确定"
4. 如果检索结果包含矛盾信息,列出所有说法并标注来源
5. 区分"文档明确陈述的事实"和"基于文档的合理推断"
6. 推断部分必须标记为"推断"并说明推理依据
</answer_rules>

<output_format>
## 回答
[基于文档的回答,每句关键信息附 [source_N] 引用]

## 来源
- [source_1]: {文档标题} - {相关段落摘要}
- [source_2]: {文档标题} - {相关段落摘要}

## 置信度
- 高:文档明确陈述
- 中:基于文档的合理推断
- 低:信息不足,仅为推测
</output_format>"""

    def build(self, question: str,
              retrieved_docs: list[dict]) -> str:
        context = self._format_docs(retrieved_docs)
        return self.TEMPLATE.format(
            context_with_sources=context,
            question=question
        )

    def _format_docs(self, docs: list[dict]) -> str:
        parts = []
        for i, doc in enumerate(docs, 1):
            parts.append(
                f"[source_{i}] ({doc['title']}, "
                f"relevance: {doc['score']:.2f})\n"
                f"{doc['content']}"
            )
        return "\n\n---\n\n".join(parts)

策略三:知识边界声明

<knowledge_boundary>
以下是你可以可靠回答的范围:
- 截至训练数据截止日期的公开知识
- 本次对话中提供的参考材料
- 代码和技术文档中的信息

以下是你不应该回答的范围:
- 实时数据(股价、天气、新闻等)
- 个人隐私信息
- 未经验证的医学/法律建议
- 训练数据截止日期之后的事件

当问题落在不可靠范围内时,你必须:
1. 明确说明你的知识可能不是最新的
2. 建议用户通过权威来源验证
3. 不要编造看似合理的答案
</knowledge_boundary>

二、引用策略(Citation)

强制引用格式

<citation_rules>
你的每个回答都必须遵循以下引用规范:

1. 直接引用:用 [ref:N] 标注来源编号
   例:"全球 AI 市场规模预计达到 X 亿美元 [ref:3]"

2. 间接推断:用 [inferred from ref:N] 标注推断依据
   例:"这意味着增长率约为 15% [inferred from ref:3, ref:5]"

3. 无法引用:用 [no source] 标注
   例:"一般认为... [no source - 常识性判断]"

4. 引用链:如果结论依赖多个来源的组合
   例:"综合 [ref:2] 和 [ref:4] 的数据... [combined: ref:2, ref:4]"

每个回答结尾必须包含引用列表:
## References
- [ref:1]: {来源描述}
- [ref:2]: {来源描述}
</citation_rules>

引用验证

class CitationValidator:
    """引用验证器:检查 LLM 输出的引用是否正确"""

    def validate(self, output: str,
                 source_documents: list[dict]) -> ValidationResult:
        """验证输出中的引用是否有据可查"""
        citations = self._extract_citations(output)
        claims = self._extract_claims(output)
        results = []

        for claim in claims:
            cited_refs = claim.get("references", [])

            if not cited_refs:
                results.append({
                    "claim": claim["text"],
                    "status": "uncited",
                    "severity": "warning"
                })
                continue

            # 检查引用的来源是否支持这个声明
            for ref in cited_refs:
                source = self._get_source(ref, source_documents)
                if source:
                    supports = self._check_support(
                        claim["text"], source["content"]
                    )
                    results.append({
                        "claim": claim["text"],
                        "reference": ref,
                        "status": "supported" if supports else "unsupported",
                        "severity": "error" if not supports else "ok"
                    })
                else:
                    results.append({
                        "claim": claim["text"],
                        "reference": ref,
                        "status": "source_not_found",
                        "severity": "error"
                    })

        return ValidationResult(
            total_claims=len(claims),
            cited_claims=sum(1 for c in claims if c.get("references")),
            supported_claims=sum(
                1 for r in results if r["status"] == "supported"
            ),
            issues=[r for r in results if r["severity"] != "ok"]
        )

    def _check_support(self, claim: str, source_text: str) -> bool:
        """用 LLM 检查来源是否支持声明"""
        response = judge_llm.generate(f"""
判断以下来源文本是否支持给出的声明。

声明:{claim}
来源文本:{source_text}

仅回答 "SUPPORTS" 或 "DOES_NOT_SUPPORT"。
""")
        return "SUPPORTS" in response

三、自检策略(Self-Verification)

策略一:生成后自检

<task>
{original_task}
</task>

<self_verification>
在给出最终答案之前,请执行以下自检步骤:

1. 事实核查:检查你回答中的每个具体事实(日期、数字、名称)
   - 对每个事实标注:[verified] 或 [uncertain]

2. 逻辑一致性:检查回答的各部分之间是否自洽
   - 是否有前后矛盾?

3. 完整性检查:是否回答了问题的所有部分?
   - 列出可能遗漏的方面

4. 来源可追溯性:每个关键陈述是否可以追溯到来源?

5. 幻觉检测:是否存在你不确定的"看似合理但未经验证"的信息?
   - 如果有,明确标注为"未验证"
</self_verification>

策略二:Chain-of-Verification (CoVe)

<task>
{question}
</task>

<cove_process>
请按以下步骤回答:

Step 1: 给出初始回答
[你的初始回答]

Step 2: 针对初始回答中的每个关键事实,生成验证问题
例如:如果你说"X 公司成立于 2015 年",验证问题是"X 公司的确切成立时间是什么?"

Step 3: 独立回答每个验证问题
(不要参考 Step 1 的回答,独立回忆/推理)

Step 4: 对比 Step 1 和 Step 3 的答案
- 一致:标记为 [confirmed]
- 不一致:标记为 [conflict],给出修正

Step 5: 给出最终修正后的回答
</cove_process>

策略三:置信度标注

<confidence_rules>
对你回答中的每个陈述,请标注置信度等级:

[HIGH] - 你非常确定这是正确的(基于明确的训练数据或提供的文档)
[MEDIUM] - 你比较确定,但存在不确定性
[LOW] - 你不太确定,这可能是基于模式推断而非确切知识
[UNSURE] - 你不确定,建议用户通过其他来源验证

标注格式:在陈述后用方括号标注
例如:"Python 3.12 引入了类型参数语法 [HIGH]"
例如:"该 API 的速率限制约为 1000 请求/分钟 [LOW]"

当整体置信度低于 MEDIUM 时,必须在回答开头声明:
"NOTE: 以下回答包含不确定信息,建议通过权威来源验证。"
</confidence_rules>

四、多模型交叉验证(MoA)

Mixture-of-Agents 策略

class MoAVerifier:
    """多模型交叉验证"""

    def __init__(self, models: list[str]):
        self.models = models  # 例如 ["claude-opus", "gpt-4o", "gemini-pro"]

    def verify(self, question: str,
               context: str = None) -> VerificationResult:
        """多模型独立回答 + 交叉验证"""

        # Step 1: 多模型独立回答
        responses = {}
        for model in self.models:
            prompt = self._build_prompt(question, context)
            responses[model] = self._call_model(model, prompt)

        # Step 2: 提取各模型的关键事实
        facts_by_model = {}
        for model, response in responses.items():
            facts_by_model[model] = self._extract_facts(response)

        # Step 3: 交叉对比
        consensus = self._find_consensus(facts_by_model)
        conflicts = self._find_conflicts(facts_by_model)

        # Step 4: 仲裁
        final_answer = self._arbitrate(
            question, responses, consensus, conflicts
        )

        return VerificationResult(
            individual_responses=responses,
            consensus_facts=consensus,
            conflicting_facts=conflicts,
            final_answer=final_answer,
            confidence=len(consensus) / (len(consensus) + len(conflicts))
        )

    def _find_consensus(self, facts_by_model: dict) -> list:
        """找出所有模型一致认同的事实"""
        all_facts = []
        for facts in facts_by_model.values():
            all_facts.extend(facts)

        consensus = []
        for fact in set(all_facts):
            agreeing_models = sum(
                1 for model_facts in facts_by_model.values()
                if self._fact_matches(fact, model_facts)
            )
            if agreeing_models >= len(self.models) * 0.7:
                consensus.append({
                    "fact": fact,
                    "agreement_rate": agreeing_models / len(self.models)
                })

        return consensus

    def _find_conflicts(self, facts_by_model: dict) -> list:
        """找出模型之间矛盾的事实"""
        conflicts = []
        # 用 LLM 检测不同模型回答之间的矛盾
        for model_a, facts_a in facts_by_model.items():
            for model_b, facts_b in facts_by_model.items():
                if model_a >= model_b:
                    continue
                contradictions = self._detect_contradictions(
                    facts_a, facts_b
                )
                conflicts.extend(contradictions)
        return conflicts

    def _arbitrate(self, question, responses, consensus, conflicts):
        """仲裁:综合多模型结果给出最终答案"""
        prompt = f"""以下是多个 AI 模型对同一问题的回答。
请综合分析,给出最可靠的答案。

问题:{question}

各模型回答:
{json.dumps(responses, ensure_ascii=False, indent=2)}

共识事实:{json.dumps(consensus, ensure_ascii=False)}
冲突事实:{json.dumps(conflicts, ensure_ascii=False)}

请:
1. 采用共识事实作为高置信度内容
2. 对冲突事实,分析哪个更可能正确
3. 明确标注不确定的部分
"""
        return self._call_model(self.models[0], prompt)

五、特定场景的幻觉控制

代码生成场景

<anti_hallucination_for_code>
在生成代码时,严格遵守以下规则:

1. API 存在性验证
   - 不要编造不存在的库、函数或方法
   - 如果你不确定某个 API 是否存在,使用注释标注:
     # NOTE: Verify this API exists in version X.Y

2. 版本兼容性
   - 明确标注代码适用的语言/框架版本
   - 不要混用不同版本的 API

3. 参数准确性
   - 不确定函数参数时,提供参数的查询方式:
     # See: https://docs.python.org/3/library/...

4. 导入验证
   - 每个 import 都必须对应真实存在的包
   - 标注需要安装的第三方包:pip install package_name

5. 错误处理
   - 不要假设 API 的错误返回格式
   - 使用通用异常处理,除非你确定具体的异常类型
</anti_hallucination_for_code>

数据分析场景

<anti_hallucination_for_data>
在分析数据时,严格遵守以下规则:

1. 数据来源声明
   - 每个数据点必须标注来源(提供的数据 vs 外部知识 vs 计算得出)

2. 计算透明
   - 展示计算过程,不要只给结论
   - 例如:"增长率 = (120 - 100) / 100 = 20%"

3. 不编造数据
   - 如果缺少数据,说明缺失
   - 不要用"大约"、"估计"来掩盖你在编造数字

4. 统计严谨
   - 相关性不等于因果
   - 小样本不支持强结论
   - 标注样本量和置信区间

5. 可视化忠实
   - 图表数据必须与文字描述一致
   - 坐标轴标注必须准确
</anti_hallucination_for_data>

六、幻觉检测工具链

class HallucinationDetector:
    """幻觉检测器"""

    def detect(self, output: str,
               context: str = None,
               question: str = None) -> list[HallucinationFlag]:
        """检测输出中的潜在幻觉"""
        flags = []

        # 1. 引用验证
        if context:
            unsupported = self._check_unsupported_claims(
                output, context
            )
            flags.extend(unsupported)

        # 2. 内部一致性
        contradictions = self._check_internal_consistency(output)
        flags.extend(contradictions)

        # 3. 已知事实核查(针对常见的高频幻觉模式)
        known_errors = self._check_known_hallucination_patterns(output)
        flags.extend(known_errors)

        # 4. 数值合理性
        number_issues = self._check_number_plausibility(output)
        flags.extend(number_issues)

        # 5. 实体存在性
        entity_issues = self._check_entity_existence(output)
        flags.extend(entity_issues)

        return flags

    def _check_known_hallucination_patterns(self, text):
        """检查已知的高频幻觉模式"""
        patterns = [
            # 虚构的论文引用
            (r'\(\w+\s+et\s+al\.,?\s+\d{4}\)',
             "potential_fake_citation"),
            # 过于精确的统计数据
            (r'\d{1,3}\.\d{3,}%',
             "suspiciously_precise_number"),
            # 虚构的 URL
            (r'https?://[^\s]+(?:arxiv|doi|github)',
             "potential_fake_url"),
        ]
        flags = []
        for pattern, flag_type in patterns:
            matches = re.findall(pattern, text)
            for match in matches:
                flags.append(HallucinationFlag(
                    type=flag_type,
                    content=match,
                    severity="medium",
                    suggestion="Verify this reference exists"
                ))
        return flags

幻觉控制清单

幻觉控制检查清单:
- [ ] 提供了充分的参考材料(接地)
- [ ] 要求所有陈述附带引用
- [ ] 要求标注置信度等级
- [ ] 加入自检步骤(CoVe)
- [ ] 声明了知识边界
- [ ] 禁止编造不存在的实体/引用/数据
- [ ] 对关键结论使用多模型交叉验证
- [ ] 配置了幻觉检测后处理
- [ ] 用户可见的不确定性标注
- [ ] 提供了验证建议(告诉用户如何核实)

参考资料

  • Anthropic 关于 Claude 幻觉控制的技术文档
  • "Chain-of-Verification Reduces Hallucination in LLMs" (Meta, 2023)
  • "FActScore: Fine-grained Atomic Evaluation of Factual Precision"
  • Vectara 幻觉排行榜(Hallucination Leaderboard)
  • RAGAS:RAG 系统的幻觉评估框架

Maurice | maurice_wen@proton.me