乐于分享
好东西不私藏

如何确保 AI 不编数字?——反幻觉的五层防御体系

如何确保 AI 不编数字?——反幻觉的五层防御体系

去年,一家做汽车零部件的企业用 ChatGPT 搭了一个「智能经营分析」。上线第一周,老板问:「上个月刹车片毛利率多少?」

AI 回答:「62.3%。」

老板很高兴,截图发到管理群:「我们刹车片毛利率不错!」

财务总监看了一眼,脸都绿了。实际毛利率是 34.7%。AI 编了一个数字——而且编得像模像样,精确到小数点后一位。

这件事让我意识到:问数助手如果不能保证数字是真的,老板就不会信任它。一次假数据,毁掉的是整个系统的信用。


LLM 为什么喜欢编数字?

LLM 的本质是「预测下一个词」。当你问它「上个月刹车片毛利率多少」,它不是在「查数据」,它是在「根据训练数据中见过的制造业毛利率范围,猜一个听起来合理的数字」。

给 LLM 真实的查询结果,它能好好说话。让它自己「想」一个数字,它一定会编。

所以反幻觉的第一原则是:

永远不要让 LLM 产出数据。数据必须来自数据库。LLM 只负责「翻译」——把查询结果翻译成人话。


五层防御体系

我们设计了五层防御,层层拦截。每层的防御对象不同。

┌────────────────────────────────────────────┐│ 第一层:SQL 安全沙箱                       ││ ← 拦截非法 SQL、注入、高危查询语句          │├────────────────────────────────────────────┤│ 第二层:结果校验                           ││ ← 拦截异常极值、不合规脏数据                │├────────────────────────────────────────────┤│ 第三层:事实锚定                           ││ ← 拦截AI虚构编造数据、脱离业务事实          │├────────────────────────────────────────────┤│ 第四层:交叉验证                           ││ ← 拦截前后逻辑矛盾、多表数据不一致          │├────────────────────────────────────────────┤│ 第五层:置信度标注                         ││ ← 标注可信度,提示老板数据误差风险          │└────────────────────────────────────────────┘

第一层:SQL 安全沙箱(拦截非法 SQL)

这一层在第 10 篇已经讲过,这里快速回顾。

防御对象:AI 生成的 SQL 中包含非法操作(DROP、DELETE)或语法错误。

防御手段

  • 白名单:只允许 SELECT
  • 语法检查:错误 SQL 直接拒绝
  • 行数限制:单次查询最多 5,000 行

效果:拦截 100% 的非法 SQL 执行。


第二层:结果校验(拦截异常数据)

SQL 执行完了,返回了结果。但结果可能是「合法但不对」的。

防御对象:数据本身有问题。比如 SAP 里有一条测试数据,金额 99,999,999 元。

防御手段

  • 范围校验
    :毛利率应在 -100% 到 100% 之间。如果返回 150%,拒绝。
  • 数量校验
    :老板问「上个月」,应该返回 1 个月的数据。如果返回 12 行,可能时间范围写错了。
  • NULL 检测
    :如果关键字段(如 revenue)大量为 NULL,说明 JOIN 方式有问题。

实例
python if result['gross_margin'] > 100 or result['gross_margin'] < -100: return "数据异常,已标记待人工复核"

效果:拦截约 80% 的数据异常。


第三层:事实锚定(拦截 AI 编造)

这是反幻觉的核心层。

防御对象:AI 在生成答案时,添加了查询结果中没有的数据。

防御手段:在 Prompt 中强制 AI「只使用提供的查询结果,不添加结果中没有的数字」。

具体的 Prompt 写法:

严格规则

  • 你只能使用下面「查询结果」中出现的数字
  • 如果某个信息在查询结果中不存在,请说「该数据暂不可用」
  • 不要推测、估算、或补充任何数字
  • 不要使用「大约」「估计」「可能」等模糊词修饰具体数字
    `

但还是不够。 LLM 有时候还是会「不小心」加戏。

于是我们加了一个后置校验:AI 生成答案后,自动提取答案中的所有数字,和查询结果中的数字对比。如果出现查询结果中不存在的数字,标记为「可能的幻觉」。

效果:拦截约 90% 的 AI 编造行为。


第四层:交叉验证(拦截逻辑矛盾)

防御对象:AI 说的数字之间互相矛盾。

比如 AI 说「毛利率 41.2%,环比下降 3.8pp」——如果上期是 45.0%,那 45.0% - 41.2% = 3.8pp,这没问题。

但如果 AI 同时说「毛利率 41.2%」和「毛利额 1,200 万」「收入 3,250 万」——那 1,200 / 3,250 = 36.9%,不是 41.2%。

防御手段:自动计算答案中相关数字的一致性。

python if answer contains revenue and gross_profit: computed_margin = gross_profit / revenue * 100 if abs(computed_margin - stated_margin) > 1.0: flag_inconsistency()

效果:这层能发现约 60% 的逻辑矛盾(很多矛盾是隐性的,不好自动化检测)。


第五层:置信度标注(告诉老板不确定性)

前面四层防守之后,仍有少量数字可能存在不确定性。最后一层不是「拦截」,是「坦白」。

在答案中标注置信度:

上个月西装毛利率 41.2%,环比下降 3.8pp。
置信度:🟢 高(数据源:SAP 销售模块,T+1 同步,已校验)

远达商贸预计下季度采购量约 2,000 套。
置信度:🟡 中(基于历史采购趋势推算,非确认订单)

效果:老板看到黄色置信度,就知道这个数字需要人工确认。不会被 AI 的「自信语气」误导。


五层防御的拦截率

防御层
拦截对象
单层拦截率
累计漏过率
SQL 沙箱
非法 SQL
100%
结果校验
异常数据
~80%
20%
事实锚定
AI 编造
~90%
2%
交叉验证
逻辑矛盾
~60%
0.8%
置信度标注
剩余风险
(不拦截,标注)

五层之后,大约 99.2% 的幻觉会被拦截或标注。 剩下 0.8% 的漏网之鱼,通过人工发现后反馈到 Prompt 中持续优化。


一个重要的心态

反幻觉不是为了做到 100% 无错误。那是不可能的。

反幻觉的目标是:让老板建立对 AI 的合理信任。

  • 他知道 AI 不会编数字(因为有事实锚定)
  • 他知道 AI 如果编了数字会被发现(因为交叉验证)
  • 他知道不确定的数字会被标注(因为置信度标注)
  • 他知道最重要的是:数字错了,不是 AI 在骗他,是数据源头有问题

信任来自透明,不来自完美。