-玛尔塔在哪里---我们如何从-AI-推理中的不确定性中去除
“玛尔塔在哪里?”:我们如何从 AI 推理中的不确定性中去除
一种流行的技巧是将 LLM 的生成能力与形式验证器相结合,即专门为某些问题提供保证解决方案的软件。关键洞察是 LLM 可能擅长将混乱、模糊的需求翻译成精确的形式规范。形式验证器擅长找到满足这些规范解决方案。通过结合它们,我们得到一个可以理解你想要什么并且保证它确实提供你所需要的东西的系统:最近,AWS 正在使用这个技巧来为实时聊天建立“护栏”。
这在实际中是如何工作的?不幸的是,这些基本动态的解释通常发生在更大的、更复杂的背景下,比如强化学习或 数学证明。今天,我们将使用 Alloy 来演示这种混合方法,Alloy 是一种易于阅读的轻量级语言,即使是初学者也能轻松理解。我们不会像通常的数学论文和 难以理解的 基准,我们将解决一个更具相关性的挑战,灵感来源于一周一次的字谜出版物:

原始谜题:5 辆车(1-5),5 个女孩(A-E),5 个名字,以及 4 个陈述:玛塔是谁,她的车是什么?[“Settimana Enigmistica”中的原始谜题首先在这篇 LinkedIn 帖子中讨论;然后作者对图片进行了修改和翻译。正如我们在下面的提示中所展示的,纯文本形式的情景显然是可能的。]
我们有:5 辆(1-5)停放在 5 个女孩(A-E)面前,以及 5 个名字(Laura,Giovanna,Bianca,Franca,Marta);我们不知道哪辆汽车是由哪个女孩停放的,但女孩们对这种情况说了些什么。我们的任务是回答这个看似简单的问题:哪个女孩的名字是 Marta,她的汽车是什么?
虽然比博士级思考更接近海滩级,但解决方案位于复杂性的甜蜜点。它可以提供关于 LLM 和形式方法的入门知识,不受其他主题的污染,也不需要广泛的领域知识:我们保留了现实世界问题的所有基本成分,但简化了设置。
提示、屏幕截图和 Alloy 代码可在这个开源仓库(所有测试都是在 2025 年 8 月的一周内进行的,主要推理循环是在 Claude Desktop 上使用 Opus 4.1 完成的)中找到。
人工智能和人类都各自努力
关于我们的谜题的一个有趣的事实是,尽管它只需要“海滩级思考”,但顶级模型并不明显擅长它。上传原始图片并提示 Opus 4.1 寻找解决方案,模型错误地假设 C 穿着裤子:那么我们如何信任它的结论——Marta 是女孩 A,她的汽车编号是 5?
当我们尝试比较模型时,事情变得有趣。我们通过文本描述抽象出这个谜题*,但大型语言模型(LLMs)仍然无法达成共识:DeepSeek 的 4.1 答案(A 和 2)与 Opus 给出的答案不同;Opus 自己的答案通过文本提示(A 和 2)与上面的 Opus 不同,而 ChatGPT5又有另一种观点(A 和 5)。
这正是使这个谜题成为一个极好的激励性例子的原因:人类在这个组合推理方面很吃力(作业问题:你花了多长时间解决它?),但前沿模型的优势并不明显。我们如何对上述任何答案建立信心?我们如何与人工智能进行推理而不是完全委托整个过程?
将推理视为“排除可能性”
复杂的推理挑战通常可以通过那位著名侦探的建议来解决:“当你排除了不可能的情况后,那么无论多么不可能,剩下的就是真相”。我们不必一次性解决整个问题,可以将我们的谜题视为三个主要事物的组合:
-
一个初始情况,随机将女孩映射到汽车和标签。
-
一组由相同女孩提出的约束,以陈述的形式:这些陈述将使某些映射成为不可能。
-
最后一种情况,女孩们被重新映射到名字和汽车上。
我们最初的知识与这种现实相兼容:

女孩和汽车名字的可能分配:Franca (A, 1),Laura (B, 2) 等。[图片由作者提供]
但还有这个(以及更多):

另一个女孩和汽车名字的可能分配:Franca (A, 1),Marta (B, 2) 等。[图片由作者提供]
我们可以想象,每次我们添加一个女孩的陈述,我们就会消除一些可能的最终方案。换句话说,随着我们逐步限制可行解的集合,我们增加了对这种情况的了解(这个基本洞察与认识论逻辑和信息理论相同)。事实上,第一条陈述,“女孩 A 声称 Laura 不在她旁边,而 A 的车现在在 Bianca 前面”,排除了我们的第一个场景,因为在那里 Laura 就在女孩 A 旁边。
枚举场景是一项繁琐且容易出错的任务,即使是对于 LLM 来说也是如此。Alloy 的魔法在于它们的声明性。我们不必自己编写推理代码,而是声明我们知道什么(传统证明中的前提,在这种情况下是陈述),以及要找出什么(一个定理,Marta 的车),然后让 Alloy 做剩下的工作:通过经过验证的方法探索巨大的概念空间,这样我们就可以专注于谜题的忠实翻译以及(重要!)Alloy 找到的实例的解释。
现在劳动分工应该是清晰的:不是 LLM(或我们)直接解决问题,而是我们用 Claude 将英语需求翻译成 Alloy 代码,然后使用 Alloy 生成解决方案,最后,我们作为人类来检查它们。
从 LLM 到 Alloy 再返回:推理循环
我们现在的提示策略更加微妙。我们不再要求 Claude 直接给出解决方案;相反,我们的提示引导它根据我们的初始场景生成 Alloy 代码。我们不再“一次性”给出解决方案,我们现在处于一个良性循环中,生成越来越复杂的代码,并根据 Alloy 的输出验证我们是否越来越接近正确答案:

与 Claude 和人类一起进行推理循环 [图片由作者提供]
结果是我们的 起始代码,它包含了主要成分,但还没有约束。现在,由于繁琐的翻译已经完成,很容易滚动查看定义:Girl,Car,和 Name 作为我们的主要“签名”(即对象集合),以及 Girls A-E 的初始位置是对 Cars 1-5 的映射。我们目前还不知道谁拥有什么,除了现在没有人拥有他们前面的车:
// No girl is initially standing in front of her own car
// Girl A (position 1) does not own Car1, B does not own Car2, etc.
A.owns != Car1
B.owns != Car2
C.owns != Car3
D.owns != Car4
E.owns != Car5
我们在这里暂停一下,来强调两个伟大的 Alloy 功能:首先,代码清晰地映射到逻辑语句,就像可以在数学证明和非正式推理中找到的那些——即使你以前从未见过 Alloy 的语法,这些语句也应该很明显(代码注释是你的朋友!)。其次,内置的 UI 有助于可视化我们的进度,因为它描绘了在所有满足约束的可能现实中选择的 实例:例如,这是一个可能的分配(Giovanna 是 C):

Alloy UI 中的起始实例 [ 作者截图 ]
再次执行它,我们可能会得到 另一个,然后又是另一个:由于我们在这个阶段的知识有限,多个分配 都是可能的:现在是时候开始消除一些了!
让我们请 Claude 修改我们的初始代码,并添加女孩 A 的陈述。这个循环的伟大之处在于我们还可以根据不完整但合理的推理来编码“健全性检查”。这不仅对 LLMs 有好处,对人类智能也有好处:能够结合“局部”约束既是对 Alloy 模型的单元测试,也是直接参与谜题的互动。
现在我们将 Girl A 的陈述作为一个约束添加。然后添加一个检查,确认以下映射现在不再允许:Franca (A, 1),Laura (B, 2)。如果我们现在运行代码,没有找到反例,这证明了我们成功排除了不希望配置:
pred InvalidConfiguration {
// Girl A is named Franca and owns Car1
A.name = Franca
A.owns = Car1
// Girl B is named Laura and owns Car2
B.name = Laura
B.owns = Car2
}
check { not InvalidConfiguration } for 5 Int
现在我们知道了这个技巧,我们的 AI 助手可以生成包含女孩所有陈述的脚本。当我们运行它时,这是我们得到的实例:

Alloy UI 中的最终模型(Marta 是女孩 A,在 5 号车里)作者提供的截图
多亏了几次迭代和可解释、可证明的推理,我们现在可以确定 ChatGPT5 做对了:Marta 是 5 号车中的女孩 A,ChatGPT 提供的映射是正确的(你可以通过比较 聊天结果 与上面的实例来验证它——顺便说一句,这也证明了一个有趣的事实,即:无论 Marta 的映射如何,其他女孩是否也被唯一确定?)。
现成的推理
拥有独立可计算的概念表示的一个很好的副产品是,现在我们可以在 Alloy 的 符号 空间中探索谜题的潜在机制,而不是完全依赖于 潜在 空间中的不透明映射。
例如,我们可以轻松地确认解决方案是唯一的:在 Alloy UI 中,如果你尝试获取一个新的实例,一个警告 指出没有其他实例可用。但我们也可能探索现有边界之外,并移除所有服装信息:解决方案会改变吗?(在运行之前尝试回答!)结果证明,正确的解决方案仍然是一个有效的实例(家庭作业问题:为什么必须是这样?),但这次 UI 确实可以产生多个有效实例:正如预期的那样,约束较少,(可能)解决方案更多。
我们可以轻松操作的符号空间也非常适合检查人工智能的工作,人工智能的工作永远不应该被当作理所当然。首先,检查 Opus 在一开始通过 错误解析图像 得到的解决方案。我们可以轻松地更改女孩 C 的服装(即 C.wears = Trousers)并再次尝试:由于没有解决方案,得出的(令人沮丧的)结论是 Opus 的原始推理是错误的——可以说是“正确”的,但却是基于“错误”的原因。
第二个例子来自 Claude 添加 的用于检查唯一性的内容(即:在所有有效配置中 Marta 是 A 和 5)。从理论上讲,这是一个很好的补充,但在实践中,这个检查并没有发挥作用:
assert MartaUniqueSolution {
// In all valid configurations, Marta is
// always the same girl with the same car
all g1, g2: Girl |
(g1.name = Marta and g2.name = Marta) implies
(g1 = g2) // Marta is always at the same position
}
不匹配是明显的,并且由于 Alloy 的清晰语法,很容易识别:“在所有有效配置中”是一个对所有实例(可以说是“元语言”)的量词,而“所有 g1…”则是对实例 内部 的女孩进行量词。
再见,太空牛仔们
与 AlphaGeometry 等尖端系统类似,我们通过与 Claude 进行推理(实际上,是一个证明)解决了演绎问题,而不是完全委托这个过程。
LLM 在英语和形式语言之间进行映射:Alloy 易于阅读,但有时编写起来很繁琐,所以 Claude 的代码生成能力派上了用场。另一方面,人类可以专注于检查形式设置是否正确(检查通常比最初做起来更容易!)。然后,Claude 和人类将组合推理委托给一个强大、经过验证的求解器进行实际演绎。
虽然我们的海滩级证明似乎并不重要,而且从 Claude 那里复制粘贴很快就会变得乏味,但这个简单的例子展示了形式方法与代码生成和一些(人类或代理)监督相结合时的力量。现实世界系统使用更表达性的语言,运行更紧密、自我改进的循环,并针对更严肃的证明,但今天许多直觉可以转移到它们身上。
当然,解决海滩或博士逻辑谜题并不是这种混合系统唯一的用例。像 Alloy 这样的语言在软件程序建模中非常流行,因此,它们为未来分布式系统在实施工作开始之前就能以低成本设计和验证提供了可能。作为非常实际的例子,AWS 臭名昭著地投资于验证他们的云产品,而 Bauplan为他们的数据目录原语提供了一个 Alloy 模型。
与 50 年前许多人的预测截然不同,似乎日复一日,我们终于越来越接近莱布尼茨的梦想:
如果出现争议,两位哲学家之间的争论将不再需要,就像两位计算者之间的争论一样。因为只要他们拿起铅笔,坐在算盘前,就可以对彼此说:让我们计算。
致谢
感谢 Federico Bianchi、Aldrin Montana、Patrick John Chia 对这篇文章先前草稿的初步反馈。在撰写这篇博客的英文部分时,没有使用或伤害任何 LLM。
如果你关心验证、模拟和系统及基础设施设计中的 AI,你将喜欢在Bauplan工作:我们正在招聘!

浙公网安备 33010602011771号