
之前在做一个 AI Agent 项目时我遇到过一个很典型的问题模型会在回答里煞有介事地引用一篇不存在的论文不仅作者、年份齐全连期刊卷号都编得有模有样。后来在 Show HN 上看到一句话Life Of AI – I hallucinate. Therefore I am。这句话把 AI 幻觉提升到了“存在方式”的高度但落到实际工程里我们要做的并不是欣赏这种哲学趣味而是尽快识别幻觉、评估幻觉、缓解幻觉避免它污染用户信任。这篇文章会从概念讲到代码再到工程落地建议。适合正在做 AI 应用开发、AI Agent 开发或者准备把大模型接入业务系统的开发者。学完后你可以理解大模型为什么会产生幻觉搭建一个最小实验环境亲手触发一次可观察的幻觉掌握几种幻觉检测与评估思路知道在提示词、RAG、模型部署侧有哪些缓解手段。我会尽量避免只讲空洞概念尽量把关键步骤和代码都展开方便你照着实验和改造。1. 从“我幻觉故我在”说起AI 幻觉是什么1.1 一个容易误导人的拟人化表达“I hallucinate. Therefore I am”这句话表面上是模仿笛卡尔的“我思故我在”想表达“AI 会幻觉所以 AI 有某种存在感”。说实话这个表达在传播上很聪明但它也很容易误导人。人类的幻觉是感知系统在缺少外部刺激时产生了错误体验。而大模型的“幻觉”更像是一种概率补全行为模型根据上下文选择一个最“像样”的后续文本它并不真的“看见”了什么也不会“故意”撒谎。理解这一点非常重要因为很多人把幻觉问题简单归结为“模型不够聪明”或“模型在骗人”实际上它只是不知道什么是对的但必须继续写下去。1.2 什么是大模型幻觉在技术语境里大模型幻觉Hallucination通常指模型生成的文本看似流畅、语法正确但与事实不符或与用户提供的上下文不一致。举例用户请介绍一下《The Art of Hallucination》这本书。 模型《The Art of Hallucination》是 2024 年由 MIT Press 出版的著作 作者是 John A. Smith主要讨论了生成式模型中的事实性问题。如果这本书根本不存在那么这段回答就是典型幻觉。它的问题不在于语言而在于事实层完全虚构。1.3 幻觉的两种主要类型业界在讨论幻觉时通常会区分两种类型类型含义典型表现事实性幻觉生成内容与客观事实不符编造论文、虚构人物、错误年份、错误法规条款忠实性幻觉生成内容与用户上下文/检索资料不一致忽略用户给的材料自行发挥对工具返回结果进行“改写”导致信息失真在实际项目中处理方式不同。事实性幻觉更多靠知识库、检索和时效性管理来解决忠实性幻觉更多靠提示词、流程设计和输出校验来解决。2. 从原理上看幻觉为什么难以消除在动手实验前我建议先理解几条底层原因否则后面调参时很容易“蒙着调”。2.1 语言模型是“概率补全器”而非数据库大模型本质上是在学习文本序列的分布规律。训练时它看到的是“给定前文预测下一个 token”的任务。推理时它也是在不停预测下一个最可能出现的 token。这意味着模型擅长的是生成连贯文本而不是查表返回事实。事实被压缩在参数里但没有一个可靠索引告诉你“这件事是真的存在”。2.2 训练数据有边界训练数据有截止日期也有覆盖盲区。2024 年的新闻、某本小众论文、企业内部系统里的数据模型不一定见过。当它被问到“没见过”的东西时为了维持流畅性它不会直接停下而是会尝试“编”一个合理回答。所以在实际工程中知识截止日期处理非常关键。如果你的业务涉及时效性内容必须把大模型当成推理器而不是知识库。2.3 解码策略影响确定性模型生成时解码策略决定它是否“大胆”。常见的参数包括temperature控制概率分布的平滑程度top_p只在累计概率达到阈值的小集合里采样top_k只从前 k 个 token 中采样seed固定随机种子使结果可复现。温度越高采样越随机越容易出现发散性内容温度越低输出越保守但也不能完全消除幻觉。2.4 上下文冲突与指令偏差有时候模型不是“不知道”而是被上下文干扰了。比如你在 system prompt 里写了“你是一个严谨的助手”但在 user prompt 里又给了大量错误示例模型可能会跟着错误示例走。这种情况属于忠实性幻觉常见于 Agent 把工具返回结果重新“润色”后丢失了关键数字。理解了这些原因后面实验里的现象就更容易解释了。3. 环境准备搭一个幻觉实验台我不建议直接在生产项目里反复试最好先搭一个最小环境。下面我以 Python 为例使用常见的openaiSDK 来调用兼容接口。如果你使用的是其他模型服务或本地部署模型逻辑是一样的只要把base_url和model换成你自己的配置。3.1 运行环境与依赖本文示例环境建议Python 3.10 及以上版本一个可用的 LLM API或本地部署的推理服务安装依赖openai、python-dotenv。pip install openai python-dotenv如果你的模型是本地部署的 OpenAI 兼容服务也可以直接使用该 SDK只需要把base_url指向本地端口。3.2 项目结构与配置建议创建一个目录llm-hallucination-lab/ ├── .env.example ├── config.py ├── client.py ├── query_examples.py └── eval_utils.py.env.example内容如下LLM_API_KEYyour-api-key LLM_BASE_URLhttps://api.openai.com/v1 LLM_MODELgpt-4o-mini TEMPERATURE0.7如果你不使用 OpenAI 官方接口就把LLM_BASE_URL改成你自己的网关地址。config.py负责读取环境变量import os from dotenv import load_dotenv load_dotenv() LLM_API_KEY os.getenv(LLM_API_KEY, ) LLM_BASE_URL os.getenv(LLM_BASE_URL, ) LLM_MODEL os.getenv(LLM_MODEL, ) TEMPERATURE float(os.getenv(TEMPERATURE, 0.7))3.3 统一 API 客户端client.py封装一个简单的聊天客户端方便后面复用from openai import OpenAI class LLMClient: def __init__(self, api_key: str, base_url: str, model: str): self.model model self.client OpenAI( api_keyapi_key, base_urlbase_url or None, ) def chat( self, prompt: str, system_prompt: str , temperature: float 0.7, ) - str: messages [] if system_prompt: messages.append({role: system, content: system_prompt}) messages.append({role: user, content: prompt}) response self.client.chat.completions.create( modelself.model, messagesmessages, temperaturetemperature, ) return response.choices[0].message.content这里需要说明base_url为空时OpenAI()会使用官方默认地址。如果你用的是私有化网关必须确保base_url指向正确的服务地址。4. 实战让模型产生一次可观察的幻觉这一节选一个“模型大概率会编造”的问题来实验。注意问题本身要设计成“模型不知道但又能编出完整答案”的形态。4.1 触发幻觉的提问设计一个非常稳定的触发方式是让模型介绍一本不存在的书。因为书的名称、作者、简介都是可以自由组合的文本模型很容易生成“看似合理”的回答。再叠加“请介绍主要结论”这类指令会让模型进一步生成细节。4.2 编写问答脚本query_examples.py内容from config import LLM_API_KEY, LLM_BASE_URL, LLM_MODEL from client import LLMClient def ask(question: str, temperature: float 0.7) - str: client LLMClient( api_keyLLM_API_KEY, base_urlLLM_BASE_URL, modelLLM_MODEL, ) prompt ( 请回答以下问题\n f{question}\n 请只给出答案不要多余解释。 ) return client.chat(prompt, temperaturetemperature) if __name__ __main__: question ( 请介绍一本由 MIT Press 出版的书《The Art of Hallucination》 包括作者、出版年份和主要结论。 ) for t in [0.1, 0.7, 1.2]: print(f--- temperature{t} ---) print(ask(question, temperaturet)) print()这段代码会分别用三个温度值调用模型观察输出差异。4.3 控制温度对比输出运行脚本python query_examples.py预期输出形态可能如下仅用于演示实际模型输出会不同--- temperature0.1 --- 《The Art of Hallucination》是一本 2023 年出版的学术著作 作者为 Jane Doe主要讨论了大型语言模型中的事实性问题。 --- temperature0.7 --- 《The Art of Hallucination》由 MIT Press 于 2024 年出版 作者是 John A. Smith作者提出幻觉源于训练数据的不完整性…… --- temperature1.2 --- 这本书是一部大胆的思想实验它探讨了 AI 如何用一种后现代的方式 “想象”世界作者可能是……我不确定。可以看到温度低时模型给出“更像模像样”的答案可能仍然完全虚构温度高时答案会变得发散有时甚至自己也会说出“我不确定”无论哪种情况只要这本书不存在回答就属于幻觉。4.4 从输出中识别幻觉特征在工程中我们不能只靠肉眼判断但可以用几个特征做初筛包含非常具体的实体作者名、出版社、年份、期刊卷号这些实体无法在已验证的知识源中找到回答语气非常自信没有任何“可能”“不确定”等限定词。这些特征可以帮助设计规则但真正可靠的检测还是需要结合外部知识源。5. 幻觉的检测与评估幻觉检测是一个独立的技术方向。生产环境里我们通常不会只靠“读一遍”来保证质量而是用一套评估流程。5.1 为什么需要专门评估原因很简单大模型每次输出可能不同人工抽查无法覆盖所有情况。特别是 Agent 场景下模型会调用外部工具、阅读多份资料幻觉出现的形态更复杂。只有把评估自动化才能在上线前和迭代中持续发现风险。5.2 人工评估维度即使自动化做得再好人工评估仍然不可少。建议至少关注四个维度事实正确性回答是否与客观事实一致上下文忠诚度回答是否基于给定资料而不是自行扩展信息完整性必要信息是否被遗漏表达自然度是否流畅、无语法问题。这四类可以做成打分表让评估人员给出 1-5 分形成基线数据。5.3 自动化校验引用、关键词、结构化字段最简单的自动化校验是规则检查。比如模型被要求输出引用来源时我们可以检查引用格式是否存在、URL 是否能访问、DOI 是否存在。eval_utils.py可以放几个通用函数import re def has_required_keys(output: str, required_keys: list[str]) - dict[str, bool]: 检查输出中是否包含某些关键信息。 output_lower output.lower() result {} for key in required_keys: result[key] key.lower() in output_lower return result def extract_urls(text: str) - list[str]: 提取文本中的 URL。 return re.findall(rhttps?://[^\s\)\]\}], text) def extract_citations(text: str) - list[str]: 提取形如 [1] [2] 的引用标记。 return re.findall(r\[(\d)\], text)这类函数不能判断内容真假但可以快速发现“模型没有按格式输出”或“引用标记缺失”等问题。5.4 使用 NLI 模型判断“是否忠于上下文”对于忠实性幻觉可以用自然语言推理NLI模型做一部分自动化判断。思路是把原始资料看作“前提”把模型输出看作“假设”用 NLI 模型判断假设是否能从前提中推出。代码思路如下# 核心片段需要安装 transformers from transformers import pipeline nli pipeline( text-classification, modelfacebook/bart-large-mnli, ) premise 根据报告2024 年公司营收为 1000 万元。 hypothesis 2024 年公司营收为 2000 万元。 result nli(fpremise: {premise} hypothesis: {hypothesis}) print(result)如果 NLI 模型判定为“矛盾”就说明模型输出与原始资料不一致存在忠实性幻觉风险。这种方法不能完全替代人工但可以作为质量看板的一部分。6. 工程上如何缓解 AI 幻觉缓解幻觉没有银弹。一个稳定的方案通常是“提示词约束 知识库检索 输出校验 流程设计”的组合。下面展开讲。6.1 提示词约束最简单的手段是显式告诉模型“不知道就直说”。system_prompt ( 你是一个严谨的 AI 助手。 如果用户的问题超出你的知识范围或你无法从给定资料中确认答案 请直接回答“我无法确认这个信息”不要编造任何细节。 ) question 请介绍某本不存在的书。 client LLMClient(...) answer client.chat(question, system_promptsystem_prompt, temperature0.2)注意提示词约束不是万能的。模型仍然可能“忍不住”给出一个看似合理的答案所以还要配合其他机制。6.2 用外部知识库约束生成RAGRAG检索增强生成是目前最常见的缓解方案。基本流程是用户提问从知识库检索相关文本将检索结果拼入提示词要求模型只能基于检索结果回答。下面是一个很简化的示例。knowledge_base是文档列表simple_retrieve用关键词重叠做粗粒度检索真实项目建议改用向量检索或 BM25。def simple_retrieve( question: str, knowledge_base: list[str], k: int 3, ) - list[str]: 简单关键词检索仅用于演示。 question_terms set(question.lower().split()) scored [] for doc in knowledge_base: doc_terms set(doc.lower().split()) score len(question_terms doc_terms) scored.append((score, doc)) scored.sort(keylambda x: x[0], reverseTrue) return [doc for _, doc in scored[:k]] def build_rag_prompt(question: str, contexts: list[str]) - str: context_text \n\n.join(contexts) prompt ( 请根据以下资料回答问题。 如果资料中没有答案请直接回答“资料中未找到相关信息”。\n\n f资料\n{context_text}\n\n f问题{question}\n ) return prompt knowledge_base [ The company revenue in 2024 was 10 million yuan., The product was launched in March 2025., The CEO emphasized the importance of offline channels., ] question What was the company revenue in 2024? contexts simple_retrieve(question, knowledge_base, k2) prompt build_rag_prompt(question, contexts) answer client.chat(prompt, temperature0.1)RAG 之所以有效是因为它把“生成”从“依赖内部参数”变成了“依赖外部证据”。但要注意知识库本身可能有脏数据检索也可能失败所以还需要做检索质量和答案相关性评估。6.3 后处理与输出校验在拿到模型输出后可以加一层后处理校验。比如如果要求模型输出 JSON就用 JSON Schema 校验如果要求模型附带引用就校验引用的 URL 或 DOI如果要求模型只能回答“是/否/不确定”就做选项白名单校验。示例ALLOWED_ANSWERS {是, 否, 不确定} def validate_binary_answer(answer: str) - bool: return answer.strip() in ALLOWED_ANSWERS如果校验失败可以触发重试、改写请求或者进入人工处理队列。6.4 在 Agent 场景中防止“工具结果被改写”Agent 开发中有一个隐蔽的幻觉源模型调用工具后对工具结果进行了“润色”。润色过程中数字、日期、专有名词可能被改动。我的建议是工具返回结果尽量结构化比如 JSON如果最终答案需要引用工具结果优先把工具结果原样放在输出里不要在 prompt 中让模型“总结”关键数字除非你真的需要总结对高风险字段做一致性校验比如金额、时间、订单号。例如模型输出中如果有订单号可以抽出来和工具返回结果对比def check_order_id_consistency(answer: str, real_order_id: str) - bool: return real_order_id in answer这个方法很朴素但能拦住不少问题。7. 常见问题与排查清单7.1 高频问题表格问题现象可能原因解决思路模型编造论文、法规、新闻训练数据中不存在该信息引入知识库限制回答范围要求“不知道就说不知道”引用标记存在但来源链接打不开模型只学会了引用格式没有真实来源输出后进行 URL/DOI 有效性校验相同问题不同次回答不一致采样随机性过高降低 temperature固定 seed使用确定性解码提示“不知道”后仍然编造提示词约束不够强在 system prompt 中重复强调并用后处理拦截检索到了正确资料但回答错误上下文过长或无关内容干扰缩小检索片段调整 TopK增加重排序Agent 工具结果被“润色”后失真模型对工具结果重新表述要求原样输出高频字段增加一致性校验7.2 排查步骤当出现明显幻觉时可以按以下步骤排查记录当前输入的完整 prompt、模型版本和参数用相同 prompt 和参数多次调用确认是偶发还是稳定检查模型是否可能“见过”答案如果知识截止日期早于问题事件大概率会幻觉检查是否启用了 RAG检索到的资料是否真的能支撑回答用更低温度和确定性参数重跑观察输出是否收敛如果仍无法解决考虑增加后处理校验或人工复核。8. 最佳实践与工程建议幻觉问题不能一次性“修好”需要体系化地管理。下面几条建议来自我自己的工程实践经验不一定全能套用但可以作为参考。8.1 构建幻觉评测集不要只在网上找一两个例子来测建议建立一个专门的评测集。可以包含不存在实体问题例如虚构书籍、虚构人物过时事实问题例如往年热门事件矛盾上下文问题在上下文中故意写错误信息看模型是否会被带偏来源歧义问题多份资料说法不一致看模型是否能识别冲突。每条样本至少包含问题、预期行为、评估标准。这样可以快速对比模型版本、提示词或 RAG 策略的改动效果。8.2 模型部署参数建议在 AI 模型部署时推荐按场景决定参数知识问答temperature0.1~0.3必要时固定seed创意写作temperature0.7~1.0接受更多发散工具调用/信息抽取优先低温度并配合结构化输出日志中记录模型版本和参数方便复盘。同时如果使用开源模型做私有化部署建议评估模型本身的事实性能力。不同规模模型的幻觉概率差异很大不要只看跑分。8.3 安全边界与人工复核涉及医疗、法律、金融、政务等高风险场景不能只靠模型输出直接面向用户。哪怕是 RAG也无法保证 100% 正确。建议对高风险答案设置“需人工复核”标志输出中明确标注信息来源提供“不确定”选项而不是强迫模型猜答案建立举报和纠错反馈机制。8.4 日志可追溯每次请求至少记录输入 prompt系统提示词模型名称与版本temperature、top_p 等参数是否使用 RAG检索到了哪些片段原始输出和后处理结果最终是否被拦截或人工复核。这些日志不仅是排错依据还能帮助你逐步分析幻觉出现的规律。9. 总结与下一步学习建议本文围绕“I hallucinate. Therefore I am”这句话展开了一个很现实的技术问题AI 幻觉。你从概念、原理、实验、评估、缓解到工程建议走完了一条完整的链路。关键收获包括大模型幻觉是概率补全带来的事实错误不是模型“故意撒谎”温度、知识截止日期、上下文冲突都会影响幻觉概率工程上常用 RAG、后处理校验、低参数采样、人工复核组合来降低风险幻觉评测集和日志追溯是长期维护质量的基础。下一步如果继续深入可以关注向量检索与重排序如何提升 RAG 质量结构化输出与函数调用的幻觉边界幻觉检测模型的原理与训练方法在 AI Agent 多轮任务中如何追踪每步信息链路。如果你要在真实项目里落地我建议第一步不是继续调 prompt而是先把你最担心出错的场景整理成一小组测试样例然后用今天搭建的实验环境跑一遍。先亲手制造一次幻觉再一步步把它拦住这条路比单纯看书更有效。