LLM的幻觉问题
> **本文适合谁**
LLM 的幻觉问题:为什么 AI 会一本正经地胡说八道
本文适合谁
准备把 LLM 接入实际系统的开发者。幻觉不只是"偶尔说错话",它在 Agent 场景下可以导致严重的系统性故障。这篇告诉你幻觉是什么、为什么无法完全消除、以及如何在系统设计层面设立防线。
幻觉(Hallucination)是 LLM 固有的结构性问题:模型生成了与事实不符的内容,但表现得非常自信。
以下是一个典型案例。要求 ChatGPT 提供关于微服务架构的论文引用,它会给出一个格式完全符合学术规范的引用:
Zhang, W., & Liu, H. (2021). Dynamic service mesh orchestration in cloud-native microservices. IEEE Transactions on Cloud Computing, 15(3), 412-428.
作者名字有,期刊名有,年份有,卷号期号页码全齐。但去 IEEE 数据库搜索,这篇论文根本不存在。
1.1 为什么需要先理解幻觉的本质
很多开发者把幻觉当作"模型质量问题",期待更好的模型会修复它,或者觉得"偶尔说错话"无关紧要。
这两个认知都是错的。
幻觉不是 Bug,是 LLM 工作方式的必然副产品。 更好的模型能减少幻觉,但无法消除它。在 Agent 系统中,幻觉的危害会被放大许多倍。不理解这一点,就无法做出正确的系统设计决策。
1.2 幻觉是什么:三种类型
幻觉大概可以分三种类型。
事实性幻觉:编造不存在的事实。
这是最常见的类型。虚假的论文引用是典型例子。还有:给出错误的历史日期、捏造不存在的公司产品、引用从未说过这句话的名人名言、描述某个 API 的不存在的参数。
这类幻觉最危险,因为细节越充分,越不容易被识破。
忠实性幻觉:没有忠实原文。
让模型做摘要或翻译,它可能悄悄改变了原文的意思——不是因为理解错了,而是它在"补全"时引入了原文没有的信息,或者丢失了关键细节。
如果用 LLM 处理合同文本或技术文档,这类幻觉可能导致严重错误。
内在幻觉:和输入信息矛盾。
给模型一段文档,让它基于文档回答问题,它可能给出与文档内容直接矛盾的答案。这在 RAG(检索增强生成)系统里尤为需要注意——你已经给了它正确信息,但它仍然可能"选择"用自己的推测来回答。
LLM 幻觉的三种类型:事实性、忠实性、内在
1.3 为什么会幻觉:从训练目标看根源
1.3.1 训练目标的根本局限
理解幻觉的根源,要回到 LLM 的本质:LLM 做的事情,从技术上说,是"根据上下文预测下一个最可能的 token"。
它不是在查数据库,不是在做事实核查,是在根据训练时见过的大量文本,判断下一个词应该是什么。
当被问到"这篇论文的引用格式是?"时,模型不会去 IEEE 数据库查询。它在做的是:一个关于微服务的论文引用,通常长什么样?作者名字通常是什么格式?期刊名通常叫什么?然后生成了一个在格式上完全符合"论文引用"模式的文本——即使内容是假的。
这个机制无法通过简单的技术修复来消除:只要训练目标是"续写"而不是"核实",在事实知识边界上就必然存在幻觉风险。
1.3.2 三个具体原因
训练数据里有错误。 互联网上的文字不全是事实,模型见过大量错误信息、过时信息、虚构内容。这些都成了它的"知识"。
没有内置的事实核查机制。 模型生成每个 token 时,没有一个步骤是"去确认这句话是否属实"。它只是在做概率最大化。
模型倾向于完成任务而不是承认无知。 RLHF 训练让模型学会了给出用户想要的答案。如果用户问了一个模型不知道答案的问题,说"不知道"可能不如给出一个看起来合理的答案更受人类评分者青睐。这在无意中强化了模型"编造合理答案"的倾向。
幻觉产生的三个根本原因(左)及其对应的缓解方案(右)
1.4 幻觉对 Agent 的危害:为什么危险被放大
1.4.1 在普通对话 vs Agent 场景中,幻觉的危害差距很大
在一般写作场景中,幻觉顶多让用户多查一次。但在 Agent 系统里,幻觉的危害可以被放大很多倍。
Agent 的工作模式是:LLM 生成参数 → 调用工具 → 用工具返回结果继续生成 → 再调用工具……
如果 LLM 在生成工具调用参数时产生幻觉:
# 假设 Agent 需要查询用户信息
# 正常情况下,LLM 应该生成:
tool_call = {
"function": "get_user_info",
"parameters": {"user_id": "12345"} # 来自上下文的正确 ID
}
# 但如果 LLM 幻觉了一个不存在的 user_id:
tool_call = {
"function": "get_user_info",
"parameters": {"user_id": "99999"} # LLM 编造的 ID
}
# 工具调用失败,或者查到了错误的用户
更糟的场景:Agent 调用了一个写操作的工具(发邮件、修改数据库、触发支付),参数是幻觉生成的。此时工具调用"成功"了,但结果是错的,还没有报错提示,后续流程继续基于这个错误结果运行。
1.4.2 幻觉的传播性
在多步骤的 Agent 任务中,第一步产生的幻觉会成为第二步的输入,第二步的错误会在第三步继续放大。没有明确的错误信号,整个推理链可能在一个错误的基础上越走越远,直到在某个关键节点产生明显的失败结果——但此时已经执行了很多步骤,回滚代价很高。
这就是为什么做 Agent 开发时,不能无条件相信 LLM 的输出,尤其是涉及调用副作用工具(写操作)的时候。
1.5 缓解幻觉的方法
没有办法完全消除幻觉。这是 LLM 的结构性问题,不是 bug,是其工作方式的副作用。但以下几种方法可以显著缓解。
1.5.1 方法一:RAG——给模型提供真实文档
RAG(Retrieval-Augmented Generation,检索增强生成)的根本逻辑是:与其让模型从训练记忆中"回忆"事实,不如在 Prompt 中直接提供事实来源。当模型有了可靠的参考文档,它在生成答案时就有了"锚点",不需要凭空捏造。
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com"
)
def answer_with_rag(question: str, retrieved_docs: list[str]) -> str:
"""
这段代码在做什么:
把检索到的真实文档注入 Prompt,让模型基于文档回答
而不是依赖模型的"记忆"
"""
context = "\n\n".join(retrieved_docs)
response = client.chat.completions.create(
model="deepseek-chat",
max_tokens=1024,
messages=[
{
"role": "system",
"content": (
"你是一个准确的信息助手。"
"请基于以下文档内容回答问题。"
"如果文档中没有相关信息,请明确说明'文档中未提及'。"
"不要使用文档以外的知识。"
)
},
{
"role": "user",
"content": f"参考文档:\n{context}\n\n问题:{question}"
}
],
temperature=0
)
return response.choices[0].message.content
# 你应该看到:回答严格基于提供的文档,不会捏造文档中没有的内容
为什么有效:文档提供了事实锚点,模型的幻觉空间大幅缩小——它不需要"回忆",只需要从文档中提取信息。
注意:即使使用 RAG,仍然可能出现内在幻觉(模型与文档矛盾)。要在 Prompt 中明确指示"如果文档中没有,请说没有",并在关键场景验证答案是否真的来自文档。
1.5.2 方法二:工具调用——让模型获取实时准确信息
查论文就调用学术数据库 API,查价格就调用电商 API,查天气就调用天气 API。不要依赖 LLM 的"记忆",让它用工具拿真实数据。
这是 Agent 系统设计的一个核心原则:需要精确事实的地方,用工具,不用记忆。
1.5.3 方法三:多步验证——先给答案,再自我验证
def verified_answer(question: str) -> dict:
"""
这段代码在做什么:
让模型分两步工作:先回答,再审查自己的回答
这种"自我批评"的方式能明显降低幻觉率
"""
response = client.chat.completions.create(
model="deepseek-chat",
max_tokens=1024,
messages=[
{
"role": "user",
"content": f"""请完成以下两步:
第 1 步:回答问题 "{question}"
第 2 步:检查你的回答,识别其中可能不准确或需要验证的具体陈述,
标注置信度(高/中/低)
如果你对某个事实不确定,请在第 2 步中明确指出。"""
}
]
)
return response.choices[0].message.content
# 你应该看到:模型不只给出答案,还会标出哪些地方不确定
为什么有效:要求模型显式思考自己哪里可能出错,会触发不同的推理路径,往往能识别出原始回答中的漏洞。
1.5.4 方法四:降低 Temperature
Temperature 越高,模型越"发散",越倾向于生成新奇但可能不准确的内容。对事实要求高的场景,把 Temperature 设成 0 或接近 0,让模型走最保守的路径。
1.5.5 方法五:Prompt 约束——明确允许说"不知道"
system_prompt = """你是一个准确的信息助手。
行为规范:
- 只陈述你有把握的事实
- 如果不确定某个信息,请说"我不确定,建议你去验证"
- 不要编造具体的数字、日期、人名、论文引用等细节
- 宁可回答不完整,不要回答不准确
- 对于可能过时的信息,主动说明"这是截止到我训练数据的情况,请核实最新信息"
"""
这个方法效果有限,但比没有好。模型被明确指示可以说"不知道"之后,幻觉率会有所下降。
1.6 好的系统设计 vs 差的系统设计
差的做法:把 LLM 当成可信赖的事实来源,直接展示模型的回答,没有任何验证机制。
好的做法:把 LLM 当作"博学但偶尔会自信地说错话"的组件来设计系统。
可靠的 Agent 系统需要防线:
- 重要事实通过工具调用或 RAG 提供,而不是依赖模型记忆
- 涉及副作用的工具调用,在执行前加一层验证
- 让模型解释推理过程,不只是给答案(Chain of Thought 有助于暴露错误)
- 对输出结果有格式校验和语义校验
1.7 不同场景下的幻觉风险等级
| 场景 | 风险等级 | 原因 | 推荐防线 |
|---|---|---|---|
| 创意写作、头脑风暴 | 低 | 事实准确性不是核心要求 | 无需特殊处理 |
| 普通问答助手 | 中 | 用户可能直接采用错误信息 | Prompt 约束 + 不确定性提示 |
| 知识库问答(RAG) | 中 | 内在幻觉风险 | 明确引导基于文档回答 + 引用来源 |
| 代码生成 | 中高 | 生成不存在的 API/库 | 运行验证;让模型说明依赖版本 |
| 医疗/法律信息 | 高 | 错误信息可能直接伤害用户 | 必须有人工审核;明确说明"非专业建议" |
| Agent 工具调用参数 | 高 | 幻觉参数导致错误执行 | 参数验证;写操作需人工确认 |
| 财务/交易操作 | 极高 | 错误执行不可逆 | 禁止直接执行;所有操作需双重确认 |
1.8 小结
幻觉是 LLM 的结构性问题,不会随着模型进步完全消失,只会逐步减少。
| 类型 | 特征 | 高发场景 |
|---|---|---|
| 事实性幻觉 | 编造细节,听起来很真实 | 引用来源、日期、数字 |
| 忠实性幻觉 | 悄悄改变原文意思 | 摘要、翻译、文档处理 |
| 内在幻觉 | 与已提供信息矛盾 | RAG 系统、基于文档问答 |
缓解策略优先级:RAG/工具调用(提供真实数据锚点)> 多步验证 > 降低 Temperature > Prompt 约束
把 LLM 当作"博学但偶尔会自信地说错话"的组件来设计系统——充分利用它的能力,同时对它的输出保持合理的不信任和验证机制。这种设计心态,是构建可靠 Agent 的起点。