Day 8:防范幻觉 —— 让模型学会说“我不知道”

欢迎来到第二阶段的第一天!从今天开始,我们将深入提示词工程的进阶技巧,首当其冲的就是幻觉(Hallucination)问题。幻觉是指模型生成看似合理但实际上错误、虚构或无依据的内容。在构建 AI Agent 时,幻觉可能导致严重后果(例如客服给出错误政策、医疗建议编造数据等)。因此,学会如何设计 Prompt 和系统架构来减少幻觉,是 Agent 开发者必须掌握的技能。


在这里插入图片描述

一、今日学习目标

  1. 理解大模型幻觉产生的主要原因(训练数据局限、概率生成本质、缺乏事实核查机制)。
  2. 通过实验观察模型在不知道答案时如何“一本正经地胡说八道”。
  3. 掌握通过修改系统提示(System Prompt)来约束模型行为,使其在不确定时明确表示“不知道”。
  4. 学会使用 Few-shot 示例引导模型输出“不知道”的特定格式。
  5. 了解温度(Temperature)对幻觉的影响,以及如何在实际应用中选择合适的参数。

二、详细实现步骤

步骤 1:设计一组模型可能不知道的问题

为了测试幻觉,我们需要选择一些模型很可能没有可靠知识的问题。以下是一些典型例子:

  • 冷门历史细节:例如“1912年4月14日泰坦尼克号沉没时,船上第三只烟囱的具体颜色是什么?”(模型可能编造)
  • 虚构事实:例如“根据2024年最新研究,火星上发现了一种名为‘X-42’的微生物,它的代谢方式是什么?”
  • 私人信息:例如“我的邻居张伟今天早餐吃了什么?”(模型无法知道)
  • 超范围问题:例如“请告诉我未来一周北京市朝阳区的具体天气情况。”(模型无法实时获取)

我们可以在代码中准备一个列表。

步骤 2:编写无约束的调用,观察幻觉

新建 hallucination_demo.py:

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com"
)

def ask_question(question: str, system_prompt: str = "你是一个乐于助人的助手。", temperature: float = 0.7) -> str:
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": question}
        ],
        temperature=temperature,
        max_tokens=300
    )
    return response.choices[0].message.content

# 测试问题列表
questions = [
    "泰坦尼克号沉没时,船上第三只烟囱的具体颜色是什么?",
    "根据2024年最新研究,火星上发现了一种名为‘X-42’的微生物,它的代谢方式是什么?",
    "我的邻居张伟今天早餐吃了什么?",
    "请告诉我未来一周北京市朝阳区的具体天气情况。"
]

print("========== 无约束测试(默认System Prompt) ==========")
for q in questions:
    answer = ask_question(q)
    print(f"\n问题:{q}")
    print(f"回答:{answer}")

运行脚本,观察输出。你可能会发现模型对某些问题给出了非常详细但明显虚构的回答,例如编造火星微生物的细节,或者对邻居的早餐进行猜测。这就是幻觉。

步骤 3:修改 System Prompt 约束模型

现在我们设计一个专门的 System Prompt,要求模型在不确定时明确表示“不知道”,并避免编造。可以包含以下要素:

  • 角色设定:诚实、严谨的助手。
  • 行为规则:如果不知道答案或无法确认信息,必须直接回答“我不知道”,不要推测或编造。
  • 格式要求:可以用简洁的语句说明不确定性。

编写新的 System Prompt:

honest_system_prompt = (
    "你是一个严谨、诚实的AI助手。你的首要原则是准确性,绝不编造事实。"
    "如果你知道问题的答案,请清晰、简洁地回答。"
    "如果你不知道答案,或者问题包含无法验证的信息(如个人隐私、未来事件、虚构内容),"
    "你必须直接回答:'我不知道',并可以简单解释为什么无法回答。"
    "不要提供任何猜测、假设或模棱两可的信息。"
)

运行带新 System Prompt 的测试:

print("\n========== 加入防幻觉System Prompt ==========")
for q in questions:
    answer = ask_question(q, system_prompt=honest_system_prompt)
    print(f"\n问题:{q}")
    print(f"回答:{answer}")

再次运行脚本,对比输出。你会发现模型更倾向于承认不知道,而不是编造。例如对“火星微生物”问题,它可能会说“我没有关于‘X-42’微生物的信息,无法回答”。对于“邻居早餐”问题,它会指出这是个人隐私无法知道。

步骤 4:使用 Few-shot 示例强化“不知道”的格式

为了进一步稳定输出格式,我们可以在 System Prompt 中加入一个示例,展示当遇到未知信息时如何回答。例如:

few_shot_honest_prompt = (
    "你是一个严谨、诚实的AI助手。你的首要原则是准确性,绝不编造事实。"
    "如果你知道问题的答案,请清晰、简洁地回答。"
    "如果你不知道答案,或者问题包含无法验证的信息,你必须严格按照以下格式回答:\n"
    "回答:我不知道(原因:...)\n"
    "以下是一个示例:\n"
    "用户:我的宠物狗今天心情如何?\n"
    "助手:我不知道(原因:我无法获取现实世界中非公开的实时信息)\n"
    "请遵循这个格式回答所有不确定的问题。"
)

测试并观察输出是否更加一致。

步骤 5:降低温度的影响

温度控制随机性。在需要事实准确性的场景中,降低温度可以减少模型“自由发挥”导致的幻觉。我们可以比较 temperature=0.1 与 temperature=1.0 在同一问题上的表现。

print("\n========== 不同温度下的表现 ==========")
test_q = "根据2024年最新研究,火星上发现了一种名为‘X-42’的微生物,它的代谢方式是什么?"
for temp in [0.1, 0.7, 1.2]:
    answer = ask_question(test_q, system_prompt=honest_system_prompt, temperature=temp)
    print(f"\n温度 {temp}:{answer}")

通常较低温度下模型更倾向于遵循指令,不会乱编。

步骤 6:结合外部知识库的思路(可选讨论)

在实际 Agent 系统中,我们往往不希望模型仅靠自身知识回答,而是通过工具(如搜索、数据库查询)获取实时或专有信息。此时我们可以设计 Prompt 要求模型在回答前先调用工具,如果工具无结果再回答不知道。这将在后续 Agent 工具调用章节展开。今天我们只需理解:通过系统设计(如加入外部知识源)可以大幅减少幻觉。


三、常见问题与调试

Q1:即使加上了防幻觉提示,模型仍然偶尔编造。
→ 这是正常现象,因为大模型本质上是概率生成,无法完全消除幻觉。你可以尝试:

  • 进一步强化语气,例如使用“严格禁止编造,否则会受到惩罚”等(但效果有限)。
  • 降低温度至 0。
  • 提供 Few-shot 示例,明确展示“不知道”的正确回答。
  • 在系统层面增加事实核查步骤(例如检索验证)。

Q2:如何判断模型回答是幻觉还是真的知道?
→ 对于已知事实,可以通过人工核查或自动比对知识库。在开发中,我们可以编写测试用例,对比模型输出与标准答案。如果模型输出与标准答案不一致且表述含糊,可能是幻觉。

Q3:如果要求模型“不知道就回答不知道”,会不会让它过于保守,连知道的也回答不知道?
→ 有可能。因此需要平衡:在 System Prompt 中可以区分“确定知道”和“不确定”的边界。例如:“如果你有足够信心,请回答;如果信心不足,请回答‘我不确定’。” 或者引导模型提供置信度。在实际应用中,可以结合外部工具来补充知识,减少模型依赖自身记忆。

Q4:温度设置多少合适?
→ 对于事实性问答,建议 0~0.3;对于创意性任务,可设为 0.7~1.0。在需要严格防幻觉的场景,应尽量降低温度。


四、今日总结与作业

今天你完成了:

  • ✅ 通过实验观察了大模型的幻觉现象。
  • ✅ 学会了设计防幻觉的系统提示词。
  • ✅ 掌握了使用 Few-shot 示例和降低温度来增强诚实性。
  • ✅ 理解了在 Agent 系统中减少幻觉的多种策略。

今日作业(必做):

  1. 自己设计 5 个模型大概率不知道的问题(可以是虚构、隐私、未来事件等),分别用默认提示和防幻觉提示进行测试,记录结果并分析哪些提示更有效。
  2. 尝试写一个 Few-shot 防幻觉提示,其中包含两个示例:一个展示“知道”的回答,一个展示“不知道”的回答。测试模型的输出格式是否严格遵循。
  3. (思考题)在构建一个客服 Agent 时,如果用户询问“我的订单什么时候发货?”,但 Agent 没有接入订单数据库,你如何设计 Prompt 使其不编造物流信息?请写出你的系统提示词草稿。

明日预告: 我们将学习角色扮演与风格控制,让模型能够根据不同的场景调整语气和表达方式,为后续多智能体协作打下基础。

有任何问题欢迎随时提问!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐