Specula 团队在 SIGOPS 博客发布了 SysMoBench。这个评测集用 11 个真实并发和分布式系统,测试主流 LLM 能不能从代码里生成 TLA+ 规格。

这里最有意思的地方,不是模型会不会写 TLA+。

更尖锐的问题是:它写出来的规格,和 Etcd、ZooKeeper、RedisRaft 这类真实系统的代码行为是不是一致。

这件事把“AI 会形式化方法”拉回了代码现场。会编译、能跑 TLC,只能说明模型掌握了语法和一部分建模套路。对分布式系统团队来说,错的规格比没有规格更麻烦,因为它会制造一种“已经验证过”的错觉。

SysMoBench 真正测的是代码一致性

TLA+ 可以粗略理解成一种给并发和分布式系统写数学规格的语言。它常被用来描述状态、动作和不变量,再交给 TLC 这类工具检查模型有没有跑出坏状态。

但工程里的难点从来不只是“写出一个漂亮规格”。难点是把真实代码抽象成模型时,哪些状态能省,哪些动作不能合并,哪些实现细节必须保留。

SysMoBench 的评测路径比较直接。每个任务提供源码、trace 采集 harness 和 invariant 模板,让模型生成 TLA+ 规格后进入四阶段检查。

阶段检查对象回答的问题
syntaxTLA+ 是否能解析编译模型会不会写对语法
runtimeTLC 是否能运行模型是否写出可执行模型
conformancetrace 与规格动作是否一致模型是否贴合真实代码行为
invariant关键性质是否成立模型是否保住系统性质

结果分化很明显。

主流 LLM 在 syntax 上接近满分。也就是说,TLA+ 的表层形式已经不是最大问题。runtime 开始拉开差距,但真正的断层在后两项:conformance 平均约 46%,invariant 平均约 41%。

这组数字不该被写成永久排名。原文也说明,模型更新很快,leaderboard 会滚动变化。

但它至少说明一件事:今天很多模型可以写出“像 TLA+ 的东西”,却还不能稳定写出“像这份代码的 TLA+ 规格”。

这也是评估 AI 工具时容易踩的坑。只看 syntax 和 runtime,会得到偏乐观的结论;把 conformance 和 invariant 放进来,问题才露出来。

教科书协议和真实实现之间,差一个 recvset

SysMoBench 里最能说明问题的例子,来自 ZooKeeper Fast Leader Election。

真实 ZooKeeper 代码里,每个 server 的 recvset 是一个按 sender 做 key 的 map。同一个 peer 在新 round 发来新的 vote,旧 vote 会被覆盖。

Claude Sonnet 生成的规格却把它写成集合累加:recvVotes' = recvVotes \cup {newVote}

这个写法很像教材里的“累积投票证据”。问题是,它不符合 ZooKeeper 的实现。规格会同时保留同一个 sender 的新旧 vote,后续 quorum 计数就可能进入真实代码不会出现的状态。

还有一类错误更隐蔽:把多步代码合并成一个原子 guard。

ZooKeeper 收到更高 electionEpoch 的消息时,真实代码会先提升本地 logicalClock,再处理消息。LLM 生成的 HandleNotification 却用 guard 直接禁掉这类消息。

模型看上去写得更简洁,实际删掉了选举轮次里必经的中间状态。

这就是“会背协议”和“会贴实现”的差别。

Raft 论文附录里的 TLA+ 规格可以解释协议思想,但不能自动等同于 Etcd 的实现规格。Etcd 怎么拆动作,ZooKeeper 怎么更新结构,RedisRaft 怎么落状态,这些细节才是工程建模的硬骨头。

对形式化方法工程师来说,这个差别很实际。评审模型输出时,不能只问“这是不是 Raft/Zab/FLE 的合理抽象”,还要追问“这是不是当前仓库这段代码的抽象”。

失之毫厘,谬以千里。形式化规格里的一个 map 被写成 set,就足够把验证带到另一条路上。

对工程团队:看 trace,不只看 demo

SysMoBench 对两类人最有用。

一类是分布式系统和形式化方法工程师。它给出的动作建议很具体:把模型输出放到 trace 里验,不要停在“能编译、能跑 TLC”。如果某个 action 在真实执行窗口里对不上,就先修模型抽象,而不是急着讨论 invariant 是否漂亮。

另一类是评估 LLM 或代码 agent 的技术负责人。采购或内部选型时,可以把 conformance、invariant、trace replay 能力放进验收项。短期内,不必因为一个模型能生成 TLA+ demo 就迁移流程;更合理的做法,是先在团队已有系统上跑小规模 harness,看它能不能反复读代码、跑 trace、修规格。

SysMoBench 的 Transition Validation 方法也很务实:从真实运行采集 trace,把 trace 切成 pre_state / action / post_state 窗口,再让 TLC 逐动作验证规格能否完成同样转移。

这比“模块能不能跑”更接近工程问题。它可以直接指出:哪个 action、在哪个状态窗口、和真实代码失配。

但 SysMoBench 不是全自动判官。

现实约束影响
trace 覆盖不足没跑到的路径无法评估
状态抽象有损例如把 log 简化成 logLen 和 logLastTerm 后,中间 entry term 的检查会变难
新系统接入要人工工作仍需写 harness、invariant 模板和 Transition Validation 模块

所以它更像高质量工程评测框架,不是“一键把仓库变成形式化规格”的流水线。

原文还提到一个重要边界:Claude Code、Codex 等代码 agent 在当前任务上表现更强,Specula 自身也声称在现有 SysMoBench 任务上达到完整 conformance 和 invariant 分数。

这不能推出“LLM 注定不能建模”。更准确的判断是:单次提示生成规格还不够。能读仓库、跑 trace、修规格、再验证的 agent,才更接近工程可用形态。

接下来要看的也不是谁短期登顶。

更关键的变量有三个:新系统接入成本能不能降下来,trace 覆盖能不能系统化扩展,agent 的高分能不能迁移到没见过的大型代码库。

如果这三点没有改善,榜单再好看,也只能说明模型更会解当前这套试卷。对工程团队来说,真正该买账的是可迁移的建模闭环,不是一次漂亮生成。