过去一年我遇到的最扎心的线上事故,不是机器宕机,而是我们做的客服问答机器人一本正经地告诉用户"某款产品已经停产了",还煞有其事地编了个停产年份。实际上它是把两年前的一份内部公告和今年的一条促销信息缝在了一起。用户截图发到群里,一整天我们都在灭火。
那段时间我一直在琢磨怎么治这种"爱说废话"的AI。后来刷到Andrej Karpathy聊AI可靠性的内容,他反复表达过一个观点:今天的大模型像个满嘴跑火车的实习生,聪明是真聪明,但真正的工程难点不是让它更聪明,而是让它在不确定的时候知道闭嘴。他提到的思路里,有一条特别让我在意——把航空领域那套安全标准搬过来。顺着这条线,我去把DO-178系列的来龙去脉翻了个底朝天。这套标准的思想源头,确实要追溯到40年前:1985年,美国航空无线电技术委员会发布了DO-178A,专门规范机载软件的安全性。今天大家经常提的DO-178C,是这个家族的最新版本。
越读越觉得,航空业这帮人早在没有大模型的时代,就解决了一个跟AI幻觉高度同构的问题:怎么在充满不确定性的系统里,构建出可以证明"靠得住"的软件。这篇文章就把我啃下来的东西,以及我拿它改造实际AI系统的过程,原原本本分享出来。
1. 为什么偏偏是Karpathy,偏偏是航空规范
1.1 "爱说废话"已经不只是段子,而是系统性风险
AI幻觉这个词,圈内人都懂。但很多人对它的理解还停留在"AI会编个假诺贝尔奖得主"这种搞笑层面。真实场景里,它带来的是真金白银的损失。我做过的几个项目里,幻觉主要砸在三个地方:
第一是客服场景。模型为了显得"有用",会在不确定时强行补全信息。产品参数记混、活动规则过期、承诺不存在的售后政策,每一条都是舆情炸弹。第二是面向内部员工的知识库助手。它把旧版本流程当成现行流程回答,导致业务部门按错误流程执行,事后追责的时候根本说不清责任边界。第三是内容审核辅助工具。模型在判断一条内容是否违规时,会"脑补"出处和上下文,给出可信但虚假的判定理由。
更麻烦的是,幻觉是随机的。同样一个问题,换个措辞可能就触发,换个上下文版本可能就消失。你没法靠"再训一版模型"根治,因为幻觉不是bug,而是当前架构的固有属性。大模型本质是一个基于概率的续写器,它在生成时并不会逐字验证事实,只是输出"看起来最合理的下一个词"。所谓"爱说废话",其实是它的默认行为。
1.2 Karpathy念叨的"软件正在改变"
Karpathy这一年多的观点我一直有跟。他反复强调的一个事实是:软件2.0时代,程序的行为不再由人一行行写出来,而是从数据里长出来的。这意味着传统软件工程那套"出bug我就修源码"的模型失效了——你没法在几万亿个参数里定位一个"说谎"的if分支。
但他没有停留在"AI不可靠所以别用"的悲观里。他在讲AI工程化的时候,多次提到一个观察:航空业早就习惯了一个事实——你无法证明一个复杂系统绝对安全,你只能通过一套工程纪律,让它的风险落到可接受的范围。这套纪律的核心不是"消灭错误",而是"管理错误"。这个思路,恰恰是对付大模型幻觉的正确姿势。
我顺着这个线索去查航空标准,越查越觉得有意思。原来航空软件的安全实践,早在40年前就开始体系化了,而它面对的问题,跟我们今天面对LLM的问题,底层逻辑惊人地相似。
1.3 40年前的规范,到底管的是什么
1985年发布的DO-178A,是专门针对机载软件(就是控制飞机飞控、发动机、导航的那些软件)的适航标准。后来经过1992年的DO-178B和2011年的DO-178C两次大改,体系更完整了。这个标准要回答一个极其要害的问题:怎么让监管机构相信,你这个软件在天上运行时不会因为软件缺陷把飞机摔了?
注意这个表述——不是"证明软件没有缺陷",而是"提供足够证据,让风险可接受"。因为航空软件同样极其复杂,波音787的机载软件代码量据说超过一千万行,谁也没法证明里面零bug。但商业航空的事实是:致命事故率低到约百万分之一量级。这个可靠性,靠的正是40年前就开始积累的那套方法。
核心就三条:把安全目标层层分解,每个环节都留下可审计的证据,一旦失效就按既定策略保守处理。这三条,翻译到大模型场景,正好对应了治理幻觉的三板斧:约束、溯源、兜底。
2. 航空业40年前就趟过的坑:DO-178C的底层逻辑
2.1 把"正确"重新定义为"安全"
航空软件工程师和我最开始做AI犯的错一样:总想追求"绝对正确"。DO-178C的哲学当头浇了一盆冷水——它的目标不是证明你的软件永远正确,而是证明一个问题:当软件出错时,后果是否被控制在可接受范围内。
这话怎么理解?航空软件分两种失效模式。一种是直接失效:该输出100的时候输出50,这是明面上的错误。另一种是误导性失效:本该输出100,它输出105,系统没报警,但实际状态已经异常了。DO-178C最警惕的其实是后者,因为它会让人做出错误决策还不自知。
想想大模型幻觉,性质完全一样。AI一本正经地编一个不存在的政策条款,比它直接说"我不知道"危险得多。前者是误导性失效,后者是直接失效。所以DO-178C的思维转换给了我很重要的启发:治理AI幻觉,第一优先级不是减少"直接失效"(胡说八道),而是减少"误导性失效"(一本正经地胡说八道)。前者用户还能看出来,后者才是真正的杀手。
2.2 设计保证等级:不是所有代码都配得上同样的谨慎
DO-178C里有个非常务实的机制叫设计保证等级(DAL),从A到E五级。等级A意味着软件失效会导致灾难性后果(比如机毁人亡),对它的验证要求苛刻到令人发指:需求要形式化、测试要MC/DC覆盖率达标、每一层都有独立验证团队。而等级E意味着失效不会影响安全,那要求就很宽松。
这套分级的本质是:把严格的工程投入集中到风险最高的地方去。航空业40年前就明白了,资源永远有限,如果对每一行代码都按最高标准要求,项目根本交付不了。所以先做失效后果分析,再决定每个模块的验证力度。
这个思维迁移到AI系统里,价值极大。我见过很多团队犯两个极端错误:要么对所有AI输出一视同仁地不信任,结果因为误拒太多被用户投诉到下线;要么对所有AI输出一视同仁地信任,结果在高风险场景翻车。正确的做法,是先给AI的每个应用场景定级,再分级上防御措施。
2.3 证据链思维:可靠不是感觉出来的,是记录出来的
DO-178C还有一个让我印象极深的点:它要求全流程可追溯。一条需求,从最初的功能定义,到设计文档,到代码实现,到测试用例,到验证结果,到问题报告,必须形成一条完整的链。监管审计人员随机抽一个需求,你要能把它从源头到验证的全部资料摊开给他看。
这意味着一个残酷的事实:航空软件的可靠性,不是"做"出来的,是"记录"出来的。你开发流程再严谨,如果没有留下成体系的证据,适航审定就是不通过。反过来,就算代码里还有已知问题,只要所有问题都被识别、被评估、被记录,并且证明残余风险可接受,一样可以取证。
这个"证据链"思想放到AI领域,就是一个绝大多数团队都没做到的事:你的模型输出了一个回答,你能不能拿出来——这个回答到底依据了哪些被检索的内容、命中了几号知识条目、经过了哪些规则校验、模型输出的置信度是多少、有没有人审过?我敢说90%的AI应用都答不出来。而这恰恰是治理幻觉的关键抓手。
3. 把航空思维翻译成治理AI幻觉的工程清单
3.1 需求追溯:让每句话都有出处
航空标准里最核心的追踪对象是"需求",在LLM场景里,对应物就是"回答里的事实性断言"。我的做法是:强制要求模型的每一条事实性输出都标注检索来源编号。
具体落地是这样的。我们给知识库的每个文本块预先编号,检索时按相关度排序,取Top-N个文本块。然后在系统提示词里规定:回答问题时,凡是涉及具体事实、条款、参数、流程的句子,必须在句末加括号脚注,标明依据是哪些编号的文本块。比如"该产品支持7天无理由退货(依据[3][7])"。
这一步看着简单,效果却立竿见影。原因在于,要求模型标注来源,会逼它在生成时做一次"自我配对"——如果某个说法找不到对应的检索来源,模型要么乱编一个编号(这种情况还是会出,后面说),要么因为无法配对而倾向于不输出这句话。实测下来,光是这一条,就能砍掉相当一部分无中生有的内容。它相当于给模型的每个断言装了一个"证据钩子",让后续的校验有抓手。
3.2 独立性验证:别让AI自己给自己打对号
DO-178C对A/B级软件有一个硬性要求:验证不能由开发团队自己完成,必须有独立的验证人。为什么?因为人容易对自己的错误盲区视而不见。翻译到AI场景,就是一句话:不能用另一个大模型来验证这个大模型输出的对错。因为同一个训练范式和数据分布下,两个模型往往犯同样的错,你拿一个AI去检查另一个AI,得到的是两个幻觉的互相确认。
那怎么办?我采用的办法是"规则+知识库校验器"。对知识库问答这类场景,答案里的关键实体(产品型号、价格、日期、政策条款编号)是可以用规则引擎精确校验的。我们建了一个轻量的校验层,AI给出回答后,先用正则和实体字典把回答中的结构化信息抽取出来,再回到知识库里做一一比对。比对不一致的直接打回重生成,并附上冲突信息告诉模型哪里错了。
这套办法的适用范围有限,但对结构化程度高的领域非常有效。它能拦截的,正是最危险的"误导性失效"——那些听起来合理但数据对不上的回答。
3.3 保守失效:拿不准的时候,允许说"不知道"
航空中最经典的失效管理原则是fail-safe:当系统处于不确定状态时,默认采取保守行为,把控制权交回给飞行员。对应到AI系统,就是三层兜底:
第一层是置信度阈值。我们给模型的输出接了一个置信度评分(可以用token级别的logprob聚合,也可以让模型自评一个0到1的分数),低于阈值的回答不直接发给用户。第二层是特定触发词。当回答里出现"可能""也许""关于这个我没有确切信息"这类模糊表达,系统判定这是模型在不自信状态下的输出,强制进入确认环节。第三层是兜底转接。对于P0级高风险管理场景(比如医疗建议、法律条款解释、投资建议),一旦进入不确定状态,话术直接切到"我无法确认这个信息,已为你转接人工"。
我还专门设计了一套"阶梯式放弃"话术,比生硬地说"我不知道"体验好很多:先给出相近但可确认的信息,再说明确认不了的内容,最后给用户指一条人工兜底的路径。这套话术几乎就是航空机组的标准沟通培训——承认局限、提供备选、给出下一步。
3.4 配置管理:模型、提示词和数据都要像飞行记录一样可审计
DO-178C对配置管理的要求贯穿整个生命周期:每一个版本的软件、每一份文档、每一次变更,都要记录在案。我用这个思路重新整理了AI应用的"配置单元",一共四件套:
- 模型版本:当前生产环境跑的是哪个模型、哪个权重版本、哪个量化等级,全部登记。
- 提示词版本:把提示词当代码管,进Git仓库,每次修改都留diff记录。改提示词比改代码更隐蔽,出问题的时候想回滚,必须有版本溯源。
- 知识库快照:数据源更新前打快照,保持和模型版本、提示词版本的三者对应关系。换新知识库后模型表现变了,先查三者是否匹配。
- 评估集版本:评测结果要和固定版本的数据集绑定。这个很多人忽略,要评估"这轮改动到底是变好了还是变坏了",必须用同一套评测集,否则对比毫无意义。
这三者版本不一致导致线上事故的例子我见过不止一次。有同行遇到过这种情况:提示词做了微调,知识库同步更新了,但评估集没换,结果上线后幻觉率反而上升,原因根本查不出来——所有变量都变了。有了配置管理,排查问题时就可以像航空失事调查一样,把"飞行记录"完整拉出来回放。
3.5 分层防御:别把信任放在一个篮子里
航空安全里有个著名的模型叫"瑞士奶酪模型":每层防御都像一片奶酪,都有破洞,但只要多层叠加,能同时穿透所有洞的事故就很难发生。对抗AI幻觉也是同样的逻辑,单靠任何一层都堵不住,必须叠:
第一层:检索增强(RAG)本身。让模型基于真实材料回答,缩小自由发挥的空间。 第二层:提示词约束。系统层规定输出格式、引用规则、禁止臆造条款。 第三层:后置规则校验。抽取结构化信息做精确比对。 第四层:置信度阈值和拒绝回答。兜住前面漏掉的不确定情况。 第五层:人工审核队列。高风险回答直接进人工抽检流。
这五层各堵各的漏洞。RAG堵不住模型不看材料硬编,提示词堵不住模型被注入攻击,规则校验堵不住语义层面的错误(逻辑对但意思偏了),置信度堵不住高自信的错误,人工抽检成本高但能给前四层一个收尾的网。层层叠加之后,任何一个单点失守都不会直接变成用户面前的事实错误。
4. 亲测:给智能问答系统做了一次"适航改造"
4.1 改造前的症状诊断
我找了一个自己维护过的知识库问答系统来做实验。这个系统是这样的:内部技术文档知识库,面向售前工程师,问的都是产品参数、兼容性列表、故障处理流程。引入大模型之前直接用关键词检索,准确但生硬;引入RAG之后对话体验好很多,但开始出现幻觉。
改造前我们做了一次症状盘点,典型的错误有六类:
- 参数错误:把A型号的功耗写成B型号的,两者正好差一倍。
- 版本混乱:用2022年的旧文档回答2024年的问题,还说得振振有词。
- 张冠李戴:把同一系列不同型号的特性混在一起说。
- 编造数据:回答"支持的协议栈列表"时,多写了一项产品根本不支持的协议。
- 编造流程:回答售后流程时,把两个不相关的流程拼成了一个。
- 自相矛盾:一段回答里前后矛盾,前面说支持,后面说不支持。
内部评测准召非常难看,更严重的是工程师用户不敢信这个工具了——开始怀疑所有AI输出,好内容也被当成幻觉给弃用。这就不是准确率的问题,而是信任崩塌的问题。
4.2 按DAL思维给场景定级
对照DO-178C的启发,我们做的第一件事不是加防御,而是给所有问题场景分级。我拉了一个问题分类表,按"答错会造成多大后果"来拍:
| 风险等级 | 场景举例 | 防御要求 |
|---|---|---|
| P0 | 合规条款解释、安全操作流程、参数极限值 | 必须带引用编号,规则校验,置信度不足直接转人工 |
| P1 | 产品兼容性、常规参数、价格政策 | 必须带引用编号,置信度不足拒绝回答 |
| P2 | 产品背景介绍、使用方法建议 | 允许自由回答,但不得编造来源和日期 |
这个分级决定了后续的节奏:先把P0场景的防御做到极致,P1做到基本可靠,P2先放着不折腾。航空业40年前就是这么干的——DAL A级模块花70%的验证资源,DAL C级模块过一遍基本的就放行。不搞一刀切。
4.3 三轮迭代的完整记录
第一轮,先上强制引用。系统提示词里加了一段很长的约束说明,核心要求就是:回答涉及具体事实时,必须标注检索来源编号;找不到对应来源的信息,不允许出现在回答里。跑了两周,幻觉率掉了大约六成。代价是回答变得特别"碎",很多工程师用户刚用的时候说"怎么每个句子后面都带个括号,好丑"。但很快反馈就反转了——因为用户发现,带了编号的内容,他们可以直接点过去看原文,不用再被AI的味道迷惑。这个信任感上的增益,远远大于阅读体验上的折损。
第二轮,上规则校验器。我们把知识库里的结构化信息(产品型号库、参数表、价格表、发布日期)抽出来做成一个校验字典。AI回答生成后,后台先跑一轮实体抽取和比对。具体做法是用正则加NER把回答里的型号、数字、日期抽出来,再到字典里查是否存在、是否一致。发现不一致的,把冲突信息回填到上下文里,让模型重新生成一次。这一轮又把幻觉率削掉一半。注意,这里有个很关键的抉择:校验不通过的不能直接给用户看错误答案,也不能只简单返回"系统错误",而是要让模型带着冲突信息重写——它看到自己刚才哪里说错了,往往能自己纠正过来。
第三轮,上置信度阈值和拒绝机制。前两轮做完了,剩下的幻觉样本大多是这种类型:看起来有引用,引用编号也真实存在,但模型对引用的理解是错的。这种语义层面的错误,规则校验器管不了。我们的解法很朴素:把模型自评置信度调出来,低于阈值的答案直接不发,转成兜底话术。阈值怎么定?我们拿一批人工标注过的历史问答做校准,画了一条置信度-准确率曲线,选在"宁可多拦一些也不放错"的位置。这轮结束后,P0场景的幻觉率降到了可接受的极低水平。
4.4 数字说话:改造成效和新增成本
改造前的内部评测,P0场景的事实错误率(也就是"一本正经胡说八道"出现的比例)大约在I2%左右。三轮迭代之后,降到大约1%出头。下降幅度挺明显,但要诚实说,不是零——语义级幻觉没法靠规则层彻底消灭。
更重要的变化是错误结构变了。改造前错误里一大半是"误导性失效"——看起来特别真,不查原文根本发现不了。改造后剩下的错误,基本都变成"直接失效"——比如"这个问题我需要找更权威的来源确认一下"这种明显的不自信输出,或者引用编号对不上(用户一查原文就发现)。这种错误伤害小得多,用户自己就能识别,不会造成系统性误判。
同时新增的成本也要摆出来。延迟:因为多了校验、重写和分级判断,P0场景的平均响应延迟从1.2秒上升到2.8秒。成本:每多一轮校验重写,就多一次模型调用,P0场景的token消耗大约增加了两倍。也算过这笔账:用翻倍的成本换取幻觉率一个数量级的下降,在我们这个业务场景里是划算的。
4.5 踩坑记录:航空思维哪些环节最难受
最难受的是配置管理。航空可以按年来做版本迭代,AI产品一周恨不得发三个版本。把提示词、知识库、模型版本严格绑定、每次变更都留审计记录,听起来很简单,但执行起来极其反人性——工程师改了一版提示词,顺手更新了知识库,评测集没同步,前后数据的可比性就废了。我们后来用CI流程强制约束:发起变更必须同时声明模型版本、知识库快照和评测集版本,缺一不可。这相当于把航空的配置管理纪律一部分搬进了常规开发流程。
其次是独立性验证的成本问题。规则校验器这种"轻量独立验证"还好,如果你试图为每个业务域都建一套独立的语义校验模型,成本基本是失控的。我的取舍是:只在P0级场景做高成本的独立校验,P1级用轻量规则,P2级直接靠RAG和提示词兜住。
还有一个很隐蔽的坑:提示词注入。脚本小子用一段精心构造的输入,让AI忽略"必须引用"的约束,强行吐出没有依据的回答。你用心架好的防御,一个注入就穿透了。后来我们的处理是在网关层统一做输入的注入检测,同时在检索内容里也执行过滤——不让脏数据进上下文。
5. 该抄的抄,不该硬抄的别硬抄
5.1 能直接抄的:四件套
总结这次改造,我认为航空规范里最值得AI团队直接借鉴的四样东西是:分级治理(按失效后果分配防御投入)、证据链(让每一个回答都带可追溯的引用和校验记录)、保守失效(低置信度就拒绝,把直接失效优先于误导性失效处理)、配置管理(版本三件套绑定,让每次变更可回放)。这四样几乎不依赖任何特定技术栈,你用什么模型、什么框架都能落地。
5.2 不能硬抄的:三条边界
第一,不要试图给LLM做形式化验证。航空对DAL A级软件要求形式化验证——用数学方法证明程序逻辑符合需求规格。这在传统软件上可行,在神经网络上是无解的。LLM的行为空间接近无限,你不可能证明它在所有输入下都符合某个形式化规格。硬要往这条路上走,消耗巨大还收效甚微。
第二,不要追求"完全独立的双团队验证"。航空的独立性验证之所以可行,是因为需求是固化的、验证标准是明确的。LLM的验证问题本身都还在演化,两个不同背景的验证团队连"什么算幻觉"都可能吵起来。独立验证在AI场景要做的是"轻量独立"——规则层、知识库层、人工抽检层,各管一段,而不是再造一个平行世界。
第三,不要照搬文档驱动的开发节奏。航空一个功能的文档和证据文件可以比产出的代码厚十倍,那是适航审定的硬性要求。AI业务的迭代节奏不允许这样,真要照搬,团队一周发一个版本都做不到。所以我的原则是:文档只沉淀"变更原因+关键参数+验证结论"三样,其他细节留在代码和配置里。
5.3 小团队落地的务实路线图
如果团队只有两三个人,预算有限,我的建议是从这条线走起:
第一步,P0场景盘点。先花一天把业务问题按后果分级,挑出答错会出事的场景,只做这些。 第二步,强制引用。改一段提示词,让模型输出带检索来源编号,同时把系统设定改成"识别不到来源就明说不知道"。这个改动成本只要一个下午,效果立竿见影。 第三步,建一张关键实体校验表。把你领域里绝对不能错的参数、政策、型号整理成字典,写一个简单的校验函数,对AI输出做一次后置比对。这一步用普通后端工程师半天就能做完,但它能把最危险的那一类错误拦下来。 第四步,加置信度和兜底话术。把"拿不准就闭嘴"变成可执行的话术链路。 第五步,跑了数据之后,再决定要不要上更重的独立校验。
我自己把航空规范啃下来、再翻译成工程语言的过程,最大的体会是:不要指望AI从"爱说废话"变得"永不说谎",这不现实。现实的目标,是把废话变成可控的、可识别的、可追溯的,让系统即使说错,说错的代价也小到可以接受。Karpathy那句"software is changing"背后,写的其实是同一个道理——软件的定义在变,但软件工程最底层的那些东西,证据、纪律、兜底、责任,从来没有变过。40年前的航空规范能救AI,靠的从来不是玄学,正是这些朴素的常识。