乐于分享
好东西不私藏

AI的一致性 ≠ 可信性(关于 AI 应用一致性与稳定性的思考)

AI的一致性 ≠ 可信性(关于 AI 应用一致性与稳定性的思考)
先讲一个我自己踩过的坑。我们有一个每天自动生成的业务报表,里面有一块图表展示当天分时段的交易额曲线。它每天准时渲染,结构一模一样,曲线漂亮,趋势合理,连着跑了很久,没有一个人提出疑问,它保持了完美的一致性。后来我去核对数据源才发现:底层数据仓库里根本没有小时粒度的表。唯一那张表是按天聚合的,时间列的类型就是 Date。跟 DBA 反复确认后,结论很清楚--这块图表每天都在编造数据。它一次都没"波动"过。它只是每天稳定地骗人。这件事把我对"AI 应用一致性"的看法整个改变了。

一、被问错的那个问题

几乎每一个业务方在验收 AI 应用时,都会问同一句话:
"这东西能不能保证每次结果都一样?"
这句话背后的诉求完全正当:我要交付、我要签字、我要担责。但这个问题本身问错了粒度。因为"一致性"不是一个东西。它至少包含四层意思,而每一层的合理要求完全不同。
第一层 事实与数值。报表里的交易额、订单号、商户号。同一份数据两次跑出两个数,这是缺陷,不是个性。必须一致。
第二层 契约与结构。工具返回哪些字段,success 这个状态到底意味着什么。这是接口,不是表达,必须一致。
第三层 路径与策略。先查这个库还是先查那个库,失败之后怎么换路子,不该要求一致,方差在这一层恰恰是能力的来源。
第四层 措辞与风格。同一个结论用什么句式组织,完全不必一致。这就像你反复问同一个人同一个问题,意思相同但表达方式每次都不太一样。
图1 一致性的四层:上两层必须一致,下两层不必
如果不分青红皂白把这四层揉成一句"结果要稳定",最终的结果就是:该守的没守住,不该管的管死了。
我见过团队为了让输出"每次都一样",把温度调到 0、把 prompt 写死、把重规划关掉,最后得到一个既不灵活、也依然会错的系统。因为他们管的是第四层,而出事的是第一层。

二、大部分"AI不稳定",根本不是AI

这是最容易被跳过,代价也最大的一步。我们有一个技术支持场景的日志检索能力,业务同事的反馈是"时好时坏,不知道什么时候能用"。所有人第一反应都是:模型不行,再调调 prompt。实际排查下来,问题是这样一串:某次变更把 Agent 的调用授权删掉了,一个外部连接被软删除,留下了孤儿记录,服务本身被置成了禁用状态。最要命的是,同一个服务在配置库里存在两行重复记录导致能力和授权被劈成了两半,—半挂在已删除的那行上,一半挂在生效的那行上。这件事与模型根本无关。
同一时期还有两个案例。一次是上游推理服务网络不通,连接超时 80 秒,熔断器打开,所有请求直接失败;另一次是某个工具依赖的库没装进后端实际使用的虚拟环境,于是它悄悄退化到了"兜底模式",生成的根本不是人声,而是一段正弦波蜂鸣。
但在用户那一侧,这三件事的体感是同一句话:这个 AI 不靠谱。
所以第一条纪律是:凡是能被确定性复现的故障,都不许记在模型头上。
否则你会拿着一个基础设施缺陷去调 prompt,永远调不好。真正属于 AI 的不确定性,是在环境完全健康,输入完全相同的前提下仍然存在的那部分。绝大多数团队从来没有把这条基线建立起来。

三、六类不确定性,其中一类根本不是方差

把环境噪声剥掉之后,剩下的可以分成这么几类:
采样方差—同样的输入,不同的措辞,可以降低,但消不掉。
语义方差—说法不同,意思相同,基本无害。
路径方差—工具调用的顺序和次数不同。多数时候无害,偶尔失控。我们遇到过用户只要一张图,系统生成了十二张。也遇到过一个工具在同样参数下被连续调用五次,每次都失败。
契约方差—返回的字段、维度时有时无。这是自动化真正的杀手。我们踩过一次:同一个分析接口,同样的请求,有时按业务维度返回,有时悄悄退回默认的按日聚合。上层拿到数据照样往下走,报表照样生成,只是维度全错了。
接地失败—也就是编造数据源不存在,却给出了数字。
环境方差—授权、连接、依赖、网络。前面说过了,这不该叫方差,这叫缺陷。
这里有一个必须澄清的认知:编造和方差是两回事。
方差可以靠重试收敛,但编造不能—重试只会给你第二个编造。
开头那个每天准时编造的分时图表就是最好的例子,它百分之百一致,也百分之百虚假。最后我们的处理不是"让它更准",而是把那块图表连同它的渲染依赖一起删掉。因为底层根本没有能支撑它的数据源,留着它就是留着一个允许系统发挥想象的位置。
顺便说一个技术细节免得有人把架构建立在错误假设上:即使把温度调到 0,大模型也不保证逐位可复现。批量推理下,浮点累加的顺序会随批次大小变化;混合专家架构里专家还有容量上限,同一批次的 token 要竞争名额,谁被挤掉取决于你和谁被打包在一起。“温度调 0”就确定了是个幻觉。

四、手工业和工业,都从不承诺"一样"

其实这件事,和人说话表达意思是一个逻辑。同样一件事,你今天讲和明天讲用的词不会完全相同,但意思是一个意思。没有人会因此说你"不稳定"。
再往前看一步,手工做一百个皮包,总有那么几个是不太一样的。画家也不可能两次画出完全相同的一幅画。凡是没有被机械化的生产,方差就是内生的。但这个类比要小心用,因为它有一个反转:手工的方差是显性的,AI的方差是隐性的。一百个手工包摆在那儿,你一眼就能看出这只的针脚和那只不一样。方差长在表面上,它自己会喊出来,你不会误判。
AI恰恰相反。报表的格式、排版、图表样式、措辞,每次都一模一样,外观是完全统一的,方差全藏在数字里。
开头那块分时曲线就是这样。它之所以能连着骗很久,正是因为它看上去和"对的时候"没有任何区别。
图 2 手工的方差长在表面,AI 的方差藏在统一的外观之下
而且,针脚不齐不影响皮包装东西,维度取错了报表的结论直接是反的。所以这个类比在"表达层"完全成立,到了"事实层"就会失效。
不过手工业还给了我们另一个更有价值的提示:手工业也是有验收标准的,只是那个标准从来不叫"相同",而叫"合格"。
皮匠交货照样要验:针脚密度、皮料等级、有无瑕疵、边油是否均匀。画家接约稿,也有一条水准线。那就是公差带。手工业压根没承诺过"每个都一样",它承诺的是"每个都落在合格区间内"。
有意思的是,工业时代也是同一个答案。现在有一种说法:要求 AI 输出高度一致,是工业化和互联网时代的思维惯性。这句话对了一半。但我想为工业化说句公道话—成熟的工业思维,从来没有假设过零件是确定性的。它假设方差必然存在,然后用公差带、抽检、统计过程控制去管理它。六西格玛这整个学科,做的事情就是统计地控制方差,而不是消灭方差。没有哪个工程师会认为两个零件的尺寸能完全相同,他们只关心两件事:是否落在公差带内,以及过程能力指数够不够。
所以真正的"惯性"不是"想要一致性"。真正的惯性是:期待一致性由元件本身提供,而不是由元件周围的系统提供。
按这个标准把大模型当成一个有公差的元件,在它外面套上检验工装、量具和夹具,这恰恰是最正统的工业思维,而不是对它的背离。
于是两头就接上了:手工业验的是"合格",工业验的是"公差带内"。没有一个承诺过"完全相同"。唯独到了 AI 这里,大家忽然开始要求"一样"了。
于是就有了那个最关键的分配决策:需要完全确定性的部分,要么继续用程序化处理,要么接受方差。这句话看起来朴素,但它是整个问题的枢纽。它意味着你必须逐个位置地回答:这里的不确定性,我是要消灭它,还是要管理它?

五、不是所有事都需要 AI

上一节最后那句分配决策,值得单独展开——因为它决定了AI到底该被放在哪里。如果某件事特别需要一致性,那就用工作流去做,或者干脆用过去那套手段去做。不是所有事务处理都需要 AI 介入。
这不是保守,而是因为两者的成本结构正好是反的:
传统程序:执行确定性极便宜,枚举分支极贵。
AI:吸收枚举到的变化极便宜,保证不变量极贵。
所以判据不是"把难啃的骨头交给 AI、简单的交给程序",而是把枚举成本高的部分交给 AI,把保证成本高的部分留给程序。
图 3 条形越长代表成本越高——两者的贵法正好相反
落到一个具体任务上,可以拆成四段:
意图识别:输入是无边界的自然语言 → 交给 AI
规划与动态调整:分支空间无法穷举,失败了要换路子 → 交给 AI
执行:必须确定、幂等、可审计 → 留给程序
校验:必须独立于执行者 → 留给程序
一句话概括:AI 决定做什么,程序决定怎么做。
图 4 意图与规划交给 AI,执行与校验留给程序
第四条尤其要强调:校验绝不能让同一个 AI 自评。前面那个语音工具就栽在这里它自己判断自己执行成功,于是持续报告 success,而用户一次都没听到声音。自评,等于让考生改自己的卷子。
那么 AI 真正的价值在哪里?
在于把过去那些必须预先穷举的复杂分支代码,变成运行时的逻辑组合。
传统方式下系统的能力上限等于开发者预先想到的情况。每多一种边缘场景,就多一条分支成本是线性甚至超线性增长的。做过老系统的人都知道,那些几百行的 if-else 不是写出来的,是被一个个线上问题逼出来的。而 AI 能处理你没想到的情况。这是它真正不可替代的地方——不是它写代码更快,而是它让你不必事先想全。但这里有一个必须诚实说出口的代价:你用可枚举性,换来了覆盖率。传统代码你可以读完所有分支,然后论证"它不会做某件事"。AI 做不到这一点,你只能用约束和校验去限制它的行为空间,没法靠阅读去证明它的行为边界。
这也正是后面那把卡尺不是可选项的原因:放弃了"读代码即证明",就必须用"统计即证明"补上。这是这笔交易的对价。
最后还有一个动态的视角,我觉得很多人误解了:工作流不是 AI 的对立面,AI 是工作流的发现器。
一个新问题刚出现时,路径是不清楚的让 AI 去探索,这时高方差完全可以接受,因为你本来就不知道正确路径是什么。
跑一段时间之后,某些路径会稳定下来、反复出现、被验证有效。这时就该把它固化成确定性的工作流,让这一段的方差归零,同时把 AI 释放出去处理更长的长尾。
我们自己就做过这件事:原本要靠模型在对话里推断该调哪个工作流、该用哪个角色,后来直接改成一个下拉框:选中工作流,自动绑定角色。这一处的不确定性不是被管理了,是被拿掉了。
AI 负责开路,工作流负责铺路。一个健康的系统应该持续地把跑通的路沉淀成路。

六、怎么管:五种手段,对号入座

第一 收缩定义域。也就是上一节说的那件事:不是管理不确定性,而是删除它。这是最有效、也最常被忽略的一招。判据很简单——每一处让模型自由发挥的地方,都要问一句:这里的自由,有价值吗?没价值,就用程序钉死。
第二 契约校验。在边界上校验返回结构对不上就判失败,而不是静默地当成功。它真正的价值是把静默失败变成响亮失败。
第三 接地约束。针对编造,强制引用可回放的来源,模板里不给不存在的数据源留位置,这一类靠重试没用。
第四 预算与幂等。针对路径方差生成十二张图,同一个工具连调五次,修法都不是在 prompt 里叫它"别乱来",而是配额限制和重复调用的硬阻断。路径方差用预算约束,不用说服。
第五 可逆性闸门。按爆炸半径分配:草稿由人过目,正式发送必须校验通过。同一个模型,两套公差,并不矛盾。

七、没有卡尺,就没有公差

工业公差之所以成立,前提是先有卡尺。而 AI 时代,大多数团队想要一致性,却没有量具,只能靠"这次感觉不太行"来判断。
难点在于AI 的输出是高维的,没有一个标量能直接度量。所以必须先降维,把"结果对不对"压成若干条可判定的断言,再对每条断言统计通过率。不可度量的问法是:”这份报表质量好不好?“
可以度量的问法是:
报表中的交易额,是否等于数据库查询结果 → 50 次中 50 次通过;
指定的业务维度字段是否存在 → 50 次中 43 次通过 ← 公差不合格;
引用的数据表是否真实存在于 schema 中 → 50 次中 50 次通过。
图 5 同一份输入重复 50 次,交付的是一个分布,而不是一次结果
Eval 就是 AI 时代的卡尺。这件事会直接改写项目的验收方式:
传统软件的验收:用例通过等于 100%,跑一次就能签字。
AI 应用的验收:跑 N 次,交付的是一个分布。
一次演示通过就验收,在 AI 时代是无效验收。它测的是运气,不是能力。

八、交付与验收:必须声明的四件事

如果要把上面这些落到甲乙双方都能签字的程度,我认为交付时必须明确声明四件事:
公差带:在什么样的输入分布上、重复多少次、通过率下限是多少。
已知失败模式清单:不是一句"可能会出错",而是"它会以这三种方式出错"。
失败时的行为:静默降级、显式报错,还是转人工。
零公差清单:哪些字段、哪些数字、哪些动作,绝不允许出现方差。
第四项是整个验收的锚点。它把"AI 有波动"从一句免责声明,变成了一个有边界的承诺。
而第三项里,藏着一个反直觉但极其重要的结论:失败的可见性,比失败率更重要。
有 5% 概率失败、但每次都响亮报错的系统可以交付;
有 1% 概率失败、却静默给出看似合理结果的系统不能交付。
回到前面那个语音工具:它交付可播放音频的成功率接近 0,却始终报告"执行成功"。真正致命的从来不是那个失败率,而是那句success
最后,工业时代的公差管的是"同一零件的尺寸分布"。AI 时代要管的,是"同一意图的行为分布"。
行为无法用单一标量描述,所以顺序只能是:
先剥离环境噪声 → 再把行为降维成可判定的断言 → 用 eval 当卡尺量出分布 → 才谈得上定公差。
跳过前面三步,直接要求"结果要一致",既得不到一致,也不知道自己离一致还有多远。
而当你真的把这套建起来之后,你会发现自己要的其实从来就不是一致性,你要的是可验证性。
一致性只是它一个很弱的代理指标。"不可靠但可检验"的东西,加一道校验就能收敛;"一致的、看起来很合理的编造",没有任何办法转化成真实。
只能删掉。就像那块每天准时出现,连着骗了很久的分时曲线一样。

附:六个问题,自查你的 AI 应用

要问的问题

怎么办

这个故障能确定性复现吗?

能 → 是基础设施缺陷,不许记在模型头上

这里的方差,是编造吗?

是 → 删掉那个位置,重试没用

这处自由发挥,有价值吗?

没有 → 用程序钉死,或固化成工作流

这件事贵在枚举还是贵在保证?

贵在枚举 → 交给 AI;贵在保证 → 留给程序

我有量具吗?

没有 → 先建 eval,再谈一致性

它失败的时候,喊得够大声吗?

不够 → 先修可见性,再修失败率

声明:文章中部分图片由AI生成!
要了解更多关于支付的故事,请阅读《一本书读懂支付》---扫描下方↓二维码,即可获得!

了解更多AI在软件研发全流程中的革新与实践,请阅读《ChatGPT驱动软件开发》,--扫描下方↓二维码,即可获得!

作者介绍
陈 斌
NETSTARS
首席技术官(CTO)