前阵子手上在核一份系统操作手册,几十页,每一步都配着界面截图,活不难,就是枯燥——逐条比按钮名字对不对、菜单藏在第几层、哪些字段是只读的。我图省事,把截图和旧手册一起丢给 AI,让它对着找差异,前面几十条改得挺准,我一度觉得这活可以交出去了。

出问题是在中段。它给我补了一条完整的操作步骤,语气笃定,术语用得比原手册还规范,界面上根本没有那个按钮。我照着改了两处,直到在系统里点不下去才发现——那条步骤从第一步到第四步都是编的,中间还贴心地提醒我"保存后需等待约 3 秒生效"。

那种感觉不是"AI 好笨",是它编得比我写得还顺。当天下午我又试了一次,问某个功能藏在第几层菜单,它答得同样流畅,同样错;而我之所以会信,恰恰是因为答得太流畅了。

这篇想说的是:幻觉不是它偶尔犯迷糊,是它干活的方式本身带出来的东西,原理层面改不了,能改的只有外面那层流程。所以下面一半讲它为什么会编,一半讲我在外面套了什么,以及哪些办法看着有用其实没用。

先说结论

  • 幻觉不是 bug,是它的工作方式。它每写一个字都在算"下一个最像样的词",而"最像样"和"是真的"是两件事,这两件事在大部分时候刚好重合,所以平时看不出问题。
  • 把 temperature 调到 0 治不了这个。它只是让输出变得稳定,包括稳定地错;如果你要复现一个错误,这倒是很方便。
  • 真正管用的是把"回忆"换成"查"。数字、日期、版本号、按钮名这类东西,一律不让它凭记忆说,这一步的收益比后面所有技巧加起来都大。
  • "降到人类水平"这个靶子本身是歪的。人的事实错误率没比它低多少,人强在两点:会说"我记不清",以及说出口的每句话背后有可查的来源。
  • 最后一道闸必须是人。医疗、法律、钱、安全参数、署名发布的内容,系统只能出初稿,判断权不能交出去。

它是怎么编出来的

要理解这事,先接受一个事实:它没有"查"这个动作。你问它一个问题,它不是去某个地方找答案,而是根据前文一路往下接,每一步都挑当前概率最高的那个词,接完一句接下一句,中间没有任何一处停下来问自己"这话有依据吗"。

这个机制在大多数时候够用,因为语言里"最可能的词"往往也是"对的词",尤其是在它学过很多遍的领域。可一旦问到了它没学过、或者学歪了的地方,概率高就不等于事实为真——它还是会接着往下写,只是这次写出来的东西没人兜底。

有个实验你三十秒就能自己试:让它列某个小领域的参考文献。期刊名、年份、卷号、页码,格式全都对,作者名字看着就像那个圈子里的人,你拿去搜,查无此文。它不是存心骗你,它只是把"一篇论文长什么样"这个模式复现得特别好,而模式里不包含"这篇论文真的存在"这一项——那一项不在它的训练目标里。

这个坑我做文档时踩过一次,后来凡是它给的出处,我都会随手搜一下,十次里有两次搜不到。

所以看到角标别急着信,点开看一眼原句。引用是给人核的,不是给人安心的。

这也解释了一个反直觉的现象:它错得越具体,越难被发现。含糊的错误你一眼就看出来,"我记得大概是……"这种话没人会当真;带数字、带书名、带日期的错误反而有说服力,因为它符合你对"专业回答"的想象,而你也没法逐条去验。

另一个常被忽略的因素是频率。训练数据里出现得多的事实,它稳得很,问它 HTTP 的默认端口是多少基本不会错;出现得少、或者只在某一年的某篇文档里出现过一次的细节,它就只剩模式可依了,而模式能保证"格式对",保证不了"值对"。所以它出错的地方是长尾,不是常识——这也意味着,越是冷门、越是你们公司内部的东西,越容易翻车。

还有个时间维度。它的知识停在某个日期上,之后的变动它不知道,但不知道这件事它自己不会说;你问一个新的价格、新的版本号、新出的政策,它会用旧的那套推一个出来,推得还挺像,语气也不打折。

最后一点容易混:幻觉和撒谎不是一回事。撒谎要有意图,得先知道真相再决定说假的,它没有这一步,它是真的"以为"自己说的是对的。这也意味着你没法通过态度判断它靠不靠谱——语气和正确性之间,没有相关性。

这一点在代码上尤其明显:它编出来的一个函数,参数名、返回值、异常处理、甚至注释里的单位,全都自洽,你读一遍挑不出毛病,因为自洽本来就不需要真实——它是一个封闭的、自己跟自己说得通的世界,只有真跑一次,才会跟外面撞上。

所以我改了个顺序:先跑,再读。

AI 幻觉产生链路示意图:提问经过逐词续写直接输出结果,中间缺少事实核查环节
缺的那一环不在模型里,只能从外面补

两类幻觉,第二类更坑

日常遇到的幻觉基本能分成两种,危害程度差得挺远。

类型表现常见场景坑在哪
事实性幻觉跟真实世界对不上编文献、编法条编号、编 API 参数和默认值、把营收说成一个"看起来合理"的数你还知道自己该去查,警惕性通常在
忠实性幻觉跟你给的材料对不上让它总结二十页文档,总结出一条原文没有的结论;给两张对照表,它把一行的值安到另一行上你以为它有依据,其实没有,而且它还在引用

第二类麻烦得多,因为它发生在"我以为它有依据"的时候。你明明把材料递过去了,它也在老老实实地引用段落,看起来每一步都有出处——但那个出处撑不住那句话,而你不会每一句都回原文核一遍。

举个常见的:让它从一段日志里摘时间线,它可能给你三条,格式齐整,顺序也对,其中一条的时间戳是它自己推算的,日志里压根没有那一行。你如果只看结果不看原文,这条会一直留在文档里,然后被下一个人当成事实引用走。

所以我现在拿到一份总结稿,头一件事不是读,是抽查它给的引用能不能对上原文,对不上就整段推倒,不问原因。

还有个更隐蔽的版本:给它两份文档做对比,它把两份的内容搞混,然后基于混淆的结论一路往下推,推理过程看着完全成立,前提是错的。这种错没法靠"读起来顺不顺"筛掉,因为顺不顺跟对错根本无关,甚至是反向的——越顺越容易过审。

奇怪的是,给了材料之后错误率不一定降。材料一长,它得从里面挑相关的段落,挑的时候它倾向于"平均"整份材料,把不该混的说法混在一起;材料里正好没有答案时,它还会从相邻段落借一个意思填上。有材料不等于有依据,这两件事中间还隔着一道工序。

比这更难缠的是上下文污染:你顺手贴进去一段自己也不确定的资料,它会当既定事实继承下来,而且在后面几轮里反复引用这一段,越引越像真的。错的东西一旦进了上下文,就会被当成前提,而前提是不会被它自己质疑的。

"让它再想想"为什么不管用

常见的自救办法是让它自己检查一遍,"你再核对一下刚才的回答",或者"逐条确认有没有依据"。这招有点用,但用处有限,原因很直接。

检查和生成用的是同一个东西。它在生成时没想到"这里可能没依据",检查时同样想不到,同一个盲区看两遍还是盲的。你能捞回来的,主要是那些前后矛盾、明显对不上的地方——而那类错误本来你自己也能看出来,不需要它帮忙。

多采样投票也是同样的道理。同一个问题问五遍取多数,这招对"算错"这类随机性错误有效,对"它稳定地记错了一个事实"完全无效:五次会一致地错,然后你还会因为"五次都一样"而更相信它——投票把一个错误升级成了共识。

这两个补丁我留着,是因为它们便宜,不是因为我信它们——真正的防线得建在外面,让错误在走出去之前被别的环节挡住,而不是指望它自己回头看出一件它当初压根没意识到的事。

能自己发现的问题,本来就不是最难的那类。真正要防的是你当时压根没起疑心的错,那类错只能靠工序挡,靠"再想一遍"是挡不住的。

让它查,别让它回忆

四层里这一层收益排第一,也容易被跳过——因为它不是"技巧",是改流程,改流程就麻烦。

抑制 AI 幻觉的四层做法示意:查询代替回忆、引用标注出处、代码校验输出、允许回答不知道
四层都在外面,所以得叠着用

大部分幻觉不是"它不会",是"我让它凭记忆答了"。凡是答案落在这几类里的,一律走工具查——数字、日期、版本号、ID、价格、法条编号、人名、界面上的按钮和菜单名、API 的字段名和默认值。模型只负责组织语言和推理,不负责当数据库。

判断标准很土:这句话如果我得百度一下才敢确认,就不该让它凭记忆说。按这条卡,我手上八成的活都能改成分工模式——它做归纳、做措辞、做结构,事实部分走查询,查完再由它缝进句子。

这条卡下来,能凭记忆答的空间很小,剩下的基本都是可以查的。麻烦的从来不是想不想查,是把"先查再说"变成习惯。

举个我现在的做法。写一篇技术文,我不再让它"介绍一下某功能",而是先把文档抓下来丢进去,让它只做两件事:从这段材料里挑出和问题相关的句子,以及把这些句子重新组织成通顺的表达。前者可核,后者不用核——因为句子的意思不是我编的,是原文的。

顺带说,能算的也别让它算。加减乘除、日期差、单位换算,交给计算器或代码,一次调用的事,比它"心算"可靠一个量级。它算错了不会报错,会给你一个同样工整、同样有说服力的结果。

给材料,还要逼它指出处

查不到现成的,就把材料塞进上下文。这一步大家都会做,但多数人只做了一半:塞了材料,没要求它指出处。

要补的那半句是:每一句结论后面标出它来自哪一段,标不出来就删掉,或者说"材料里没提到"。加了这句之后,输出会变短,也会变难看,因为总有一部分内容会直接变成"资料不足"。

那正是你要的结果。难看的输出比漂亮的幻觉值钱,至少你知道自己缺什么。

引用的粒度也得抠,要细到句子,不能粗到"文档 A"。粗粒度的引用等于没引用——它只要说"来自文档 A"就过关了,而文档 A 里可能有三十页。

再进一步,是让程序去核,而不是让它自己核。把引用的原文和结论那句话一起交给一个校验步骤,只问"这段原文支持这句话吗",只接受两个答案,中间态一律算不支持。这一步是整条链上唯一真正能压住"看起来有出处其实没有"的手段,因为它换了一个视角看同一份输出,而不是让原班人马再想一遍。

能交给代码验的,别指望它自觉

结构化输出比自然语言好验太多。同一件事,让它写一段话,你得读三遍才知道有没有问题;让它吐一个固定结构,程序一秒就能卡住,而且不会累。

字段在不在、类型对不对、枚举值有没有越界、数值在不在合理区间、外键指向的东西存不存在,这些全是代码能判的。凡是代码能判的,就不该写成"请注意准确性"去求它,那等于把可执行的检查降级成一句请求。

// 别让它输出一段话,让它输出一个能被程序卡住的结构
{
  "answer": "string",
  "cited_spans": [3, 7],      // 只能填材料里的段落编号,填别的直接判失败
  "confidence": "high | low",
  "unsupported": ["string"]   // 材料里找不到依据的部分,单独列在这里
}

末尾那个字段是我夹带的私心:逼它把"我没依据的地方"单列出来。它列得不一定准,但把话说在明处,总比埋在一段流畅的正文里强,至少你有了一个可以抽查的抓手。

代码也一样。它写的脚本能不能跑、跑出来的数对不对,执行一遍就知道,这是核实手段里相当便宜的一种。可惜常被跳过——很多人拿到代码看一眼"语法没错"就用了,然后在一个月后发现那个数一直是错的。

给它留一条说"不知道"的路

这一层容易被跳过,但少了它,前面三层都白做,因为你会亲手把它逼回编造。

模型的默认倾向是给答案,因为训练里"拒答"通常被当成失败,而"给一个像样的回答"被当成成功。你越强调"要准确""要详细""要覆盖全",它越不敢说不知道,最后就用编来满足你。你给的每一条"必须答全"的要求,都在给它加压力。

所以要在提示里明确写一句,而且语气要写得像真的允许,不能是"尽量别这样"。我现在用的是:材料里没有的,直接写"材料未提及",不要推测,不要补全,这一条不算失败。就这么一句,比前面那些"务必准确"管用得多。

这句话我头一回写进去的时候还觉得别扭,好像提前给它找退路。用了两周才发现,它说"材料未提及"的那几次,恰好都是我自己也没把握的地方。

更重要的是评估。如果你只测准确率,系统一定会被优化成"永远敢答",因为拒答在准确率上是零分,编一个在准确率上还有概率得分。一个永远敢答的系统,在真实场景里比老实说不知道的系统危险得多,只是它的分数更好看,所以这种系统更容易被留下来。

评估集不用一上来就搞几百条,我先从三十条起手:一半有标准答案,另一半材料里压根没有答案,跑两轮就知道该往哪儿补——没有这把尺子,前面所有调整都只能凭感觉,而凭感觉调的方案,通常是在把一个错误换成另一个。

所以我现在的评估集里必须有一批"资料里没有、正确行为是拒答"的题,每次改动前后都跑。同时看两个数:错答率,和该拒答时真拒了的比例——少看一个都不行,只看前者会养出敢答的系统,只看后者会养出什么都不干的系统。

几个流传很广但基本没用的办法

下面这几条我自己都试过,也见过不少人在用。不能说完全无效,但期望值要放低,别指望它们解决问题。

做法实际情况
在提示里写"不要编造""务必准确"几乎无效。它在生成的时候没有核查自己的能力,这句话进不了它当前的判断
把 temperature 调到 0减少随机波动,但事实性错误照样有,而且变得更稳定、更容易复现
让它自我反思一轮能捞回明显矛盾,捞不回同一个盲区里的错,因为检查和生成共享同一套判断
换一个更大的模型幻觉少一些,不归零,也换不来"知道自己不知道"这种能力
提示词写得特别长,堆十几条约束边际收益很快变负。约束之间会打架,打架时它挑哪条执行你控制不了

约束打架这事我碰到过一回:同一段提示里既要"回答简洁",又要"覆盖所有情况",它最后给了一段两行字的摘要,把四种情况压成一句话,看着确实简洁,漏掉了两种——它不会告诉你这两条要求没法同时满足,它只会挑一条执行,然后交给你一个看起来合格的结果。

共同点是:这些办法都在试图让它"更努力地想",而幻觉的根源不在努力程度,在于它根本没有"核对"这个环节。往一辆没有刹车的车上加马力,没什么意义,只会让你更晚发现撞墙。

我踩的坑:看起来在防,其实没防住

这几条都是我以为自己做对了、后来发现漏了一环的,共同特征是"防线的形状有了,但挡不住东西"。

#现象原因与修法
1加上了引用,看着很正规。抽查三条,两条撑不住那句话我只检查了"引用存在",没检查"引用是否支持这个结论"。存在性和支持性是两回事,前者程序一秒能查,后者要另跑一步
2上了检索之后错误变少,但错的那几条更可信了检索没覆盖到的时候,它会把不相关的片段硬套上去,而且这次它"有出处"。无据可依时的正确行为是拒答,不是凑一段
3评估跑分很漂亮,上线还是出事评估集全是标准问题,没有"应该拒答"的负样本。指标只奖励敢答,系统就往那个方向长
4以为多问几遍取一致能提高可靠性对系统性记错无效,还会让你因为"五次都一样"而更信任它。投票治不了共同的盲区

第一条我印象很深,因为引用这个动作本身会给人安全感——看到角标就默认核对过了。实际上它只是把"编内容"升级成了"编内容加编出处",从外面看反而更专业,这比单纯编内容危险。

那到底能不能降到人的水平

这句话我听过很多遍,但它没法当目标用,因为没说清楚对标人的哪一项——是错得更少,还是错的时候更诚实,还是错了好发现。把指标拆开看会清楚很多。

指标人模型
事实错误率不低。记忆偏差、以讹传讹、把两件事记串看领域,公认的常识范围里其实差不多
说错时的语气多数会带"我记不太清""好像是这样"通常同样笃定,甚至更笃定
错误能否被当场发现多数能。人有上下文、有犹豫、有身份可追很难。幻觉和真话在文本形态上一模一样

差距主要在后两行,不在第一行。所以该优化的不是"错得更少",是"错的时候别那么笃定,并且让人查得出来"。前一个目标在现有架构下很难验收,后一个目标每做一点都能立刻看到效果。

这两件事做到了,剩下的错误率就落在一个能接受的区间里。毕竟你要的从来不是一台从不出错的机器,是一台出错时你能发现、能定位、能回滚的机器——这三个动词,比"准确率"实在多了。

顺着这个逻辑,界面上的事就不是小事了。来源链接、置信度、"这一段没有检索到依据"的显式提示,这些看着像装饰,其实都在把不可检测的错误转成可检测的。用户能看见不确定性,才谈得上信任,反过来,藏起来的不确定性迟早会以一次事故的方式还回来。

有些场景不该指望它

医疗诊断和用药、法律意见和条款引用、财务数字和报表、涉及人身安全的参数、署名的对外内容。这几类我的态度很明确:系统只出初稿和检索结果,判断权在人,过程留痕。

我现在的做法是让系统输出"待核清单"而不是"结论":每条附上它引用的原文位置和截图,核过一条才允许进正文,没核的那部分在文档里留着记号。

不是不信任技术,是这些领域的错误代价不对称——编错一个剂量、引错一条法条、少写一个零,代价和"AI 写错一篇博客"根本不在一个量级。代价不对称的地方就该用不对称的流程,而不是用同一套提示词指望它自觉。

如果你只是日常用

上面那些是搭系统的事,听着累。如果只是拿它写东西、查资料、改代码,记住三条就够,成本几乎为零。

第一条,凡是它给你的具体信息,让它一起给来源。给不出来源的,当场当它没说。这条不是为了追究它,是因为"给不出来源"这个动作本身就会让它少编一半——它得先去找,找的过程就在压概率。

第二条,别问"是不是"这种带预设的问题。你问"这段配置是不是因为内核版本太低才不生效",它会顺着你的预设往下编,因为顺着说最像样。换成"这段配置不生效有哪些可能原因",它给的东西会实一大截。

这个差别一句话就能记住:把疑问句换成开放句,它编的空间就小一圈,因为开放句没有唯一一个"顺着说"的方向。

第三条,抽查而不是通读。不要从头读到尾找问题,人读顺了就会放过;盯着带数字、带专有名词、带时间的那几句话,逐条去核。一篇稿子里真正会伤人的通常不超过五句,把这几句核了,剩下的错顶多算不好看。

第四条,别让它替你判断哪些信息算相关。它判断相关性靠的是"这些词经常一起出现",而你要的相关是"这条信息会不会影响这个决定",这两件事在专业场景里经常正好相反,它挑出来的往往是最像的那个,不是最有用的那个。

这三条我用了一年多,没花什么力气,但确实少踩了很多坑;真要再加一条,就是别在它出错之后只骂一句,回头看看那句话凭什么骗过了你,通常是有个环节你本来抬手就能核。

小结

回到开头那个按钮。后来我把手册核对的流程改成:AI 只负责标出"它认为和截图不一致的地方",每条必须附上截图里的原话,我逐条去系统里点一遍。

效率大概只有原来的一半。但它现在编的东西会自己暴露出来——因为编出来的那条,附不出截图里的原话。这个代价我觉得付得值,毕竟我要的是一份能交给同事的手册,不是一份看起来很完整的手册。

回头看,幻觉这事真正要改的是我的预期。我一开始把它当成一个"知道很多的人",所以它的错让我意外;现在我把它的位置摆正:一个特别能写、不太记事、也从不承认自己记不清的助手——它负责产出,事实的部分由流程兜。

写到这儿得说清楚一句:这篇里没有一个办法能把幻觉清零,我也没有。我能做到的只是让它出错的时候,声音小一点,痕迹多一点。

如果你也想在自己那摊活里用起来,建议从一个很小的动作开始:把业务里"绝对不能错"的那几个字段列出来,金额、编号、日期、条款号、参数名,就这几类,先让它们一律走查询、不许模型生成。剩下的事情,慢慢来。

如果你觉得这篇文章不错,有用的话可以点击下面的“赞赏”支持作者,你的支持是我更新的动力(饿饿吃饭)。

  • reward_image1
  • reward_image2
欢迎来到XiaoZou123,这里是一个电脑极客、数码爱好者网站。我平时喜欢关注数码新闻,研究计算机技术。如果你看我头像觉得我是二次元,那我其实还算不上!
最后更新于 2026-11-05