VeriSkill:大模型自进化程序验证技能,跨模型迁移最高提升43.7%

VeriSkill: A Self-Evolution Framework for Program Verification Skills

论文原文 ↗ 论文发布 解读发布 解读:AI前沿分享

借助大语言模型(LLM)驱动的智能体(Agent)来编写程序,正在从简单的代码补全迈向高可靠的形式化程序验证(Program Verification)。在这一进阶任务中,Agent 不仅要写出可执行的代码,更要生成严格的函数契约(Contracts)、循环不变量(Loop Invariants)、辅助引理(Auxiliary Lemmas)以及相应的工具链调用指令。这些高度专业化的操作往往被封装成“技能”(Skills)。然而,人工编写与维护验证技能极其昂贵,完全依赖通用的技能自进化(Skill Self-Evolution)框架又屡屡碰壁:常规方案习惯于从一次执行失败的轨迹中抓取报错并直接修改 Prompt,但在形式化验证的世界里,底层 SMT 求解器(如 Z3)超时或报错,很多时候根本不是技能本身的缺陷,盲目“打补丁”只会让 Agent 陷入无休止的过拟合甚至语法灾难。

ArXiv URL:https://arxiv.org/abs/2607.27733

为了破解这一死局,研究团队提出了专门面向程序验证的技能自进化框架 VeriSkill。它跳出了通用自进化框架“见错就改”的粗放范式,建立了一整套兼顾“归因诊断、抽象泛化与语义保真”的进化闭环:首先在责任归因中剔除环境和求解器局限带来的伪信号,只捕获真正的技能缺陷;接着将具体的失败诊断签名聚类,提炼出可跨任务复用的程序性经验(Lessons);最后在同模式用例和全局验证集上进行双重可执行校验,只有既显著提升验证成功率又严格保持程序语义不变的更新才会被准入。

实验表明,VeriSkill 在 Dafny、Frama-C 和 VeriFast 三大主流验证工具与多款 Agent 架构上全面超越了无技能基线、人类专家编写技能以及现有的通用自进化算法。更具启发性的是,用单一模型进化出的 VeriSkill 技能,直接迁移至 GLM-5.2、Kimi-K2.7、Qwen3.7-Max、DeepSeek-V4-Pro 等异构后端时,验证通过率普遍提升了 15.3 到 43.7 个百分点。这证明了高质量的形式化验证技能并非特定模型的对抗性 Prompt 补丁,而是能够作为外置程序知识,真正赋予大模型坚实的形式化推演能力。

VeriSkill 框架总览

为什么通用的技能自进化在形式化验证中失效?

在探讨 VeriSkill 的设计细节之前,需要认清形式化验证对 LLM 提出的独特挑战。传统的软件工程任务中,测试用例不通过往往直接映射到代码逻辑的 Bug;但在形式化程序验证中,代码不仅要跑通,还必须被数学级严格证明。用户需要标注前置条件(Requires)、后置条件(Ensures)、修改集(Modifies Clause)以及复杂的循环不变量。当 Dafny 或 Frama-C 抛出验证失败(Verification Condition Failed)时,背后的原因高度异构且极不透明。

通用的 Agent 技能自进化方法,如 Trace2Skill、SkillOpt-Lite 或 EvoSkill,核心逻辑是在执行失败后直接反思轨迹并追加指导规则。这种做法在程序验证领域会引发两大致命问题:

其一,失败归因严重失真。形式化验证工具底层依赖 Satisfiability Modulo Theories (SMT) 求解器。一次验证失败,可能是目标规范本身在数学上不可满足,可能是求解器的启发式搜索触碰了算力或超时边界,也可能是 Agent 偶尔的随机采样失误。这些情况与“技能文档写得好不好”毫无关系。通用自进化算法无法辨别这些外部干扰,往往将求解器的算力瓶颈误判为指导方针有误,诱导 Agent 在错误的演进方向上越陷越深。

其二,反馈信息与程序指导脱节。验证器吐出的错误信息通常是高度局部的底层数学命题不成立(例如“Assertion at line 42 might not hold”)。但导致这个错误的高层原因,很可能是循环不变量的数学推导逻辑存在根本缺陷,或者是缺少了一个关键的归纳引理。直接把底层报错信息贴进技能库,只会堆砌一堆针对特定变量名和具体行号的碎片化规则,既无法指导后续相似结构的逻辑重构,也极易在其他任务中产生冲突。

责任归因:剥离环境噪声,锁定真正缺陷

针对归因失真问题,VeriSkill 设立的第一阶段是责任归因与过滤(Responsibility Attribution and Filtering)。该阶段的核心目标是建立一道防火墙,阻断一切不应由技能负责的噪音信号进入演进流水线。

当一个验证任务执行失败时,VeriSkill 并不会立刻触发技能重写,而是将任务描述、验证器原始输出、当前技能正文、生成的验证产物、人类编写的参考解以及演进记忆库(Evolution Memory)共同输入归因诊断模块。系统对失败原因进行多维度判定,将其细分为四类:

  1. 任务不可行:规范本身存在数学矛盾或前置约束缺失;

  2. 求解器算力上限:程序标注理论上正确,但触发了 SMT 求解器的未知状态或超时;

  3. 偶发生成失误:技能本身已有明确指导,但模型未严格依循;

  4. 技能缺陷:现有技能在指引推导、断言布局或特定语法结构时缺乏必要的程序性规则。

同时,VeriSkill 会检索演进记忆库中的历史归因记录。如果过往记录显示同类断言报错曾被证实为求解器边界或任务不可满足,算法会果断终止本次反馈,避免历史错误被反复演化。只有被明确确认为“由于技能缺失或误导所致,且有望通过自然语言规则改进”的失败案例,才被赋予通行证,作为真正的学习信号进入下一阶段。这种严格的责任隔离,从源头上保证了演化信号的高信噪比。

模式聚类与经验抽象:将底层报错升维为通用知识

过滤出纯净的失败信号后,如何将孤立的验证报错转化为可迁移的程序指导知识?VeriSkill 的第二阶段是基于模式聚类的经验抽象(Lesson Abstraction via Pattern-Level Defect Clustering)

如果为一个具体的失败案例定制一条修改规则,技能文档很快就会演变成臃肿不堪且互相矛盾的代码片段堆叠。VeriSkill 采取了自底向上的抽象路径:

首先,系统为每个技能缺陷提取结构化的“诊断签名”(Diagnostic Signature)。该签名精准记录了验证在程序的哪个语义节点发生崩溃(例如跨函数调用的非空指针断言)、暴露出当前技能哪方面的欠缺(例如未指导如何将 C 语言宿主环境的空指针检查与 Dafny 语义对齐),以及缺少的程序性指导为何。

随后,VeriSkill 基于诊断签名将相似的失败用例聚类。在同一个模式簇内,算法结合人类正确验证产物所体现的逻辑作为佐证,提炼出通用的经验单元(Lesson)。在生成经验的过程中,VeriSkill 会强制剥离特定代码中的变量名、具体行号等实例级噪声,将其升华为具备通用适用条件的程序性法则。最终生成的每一条经验都会清晰界定两件事:在何种抽象代码模式下必须激活该推导模式,以及在哪些边界场景下坚决不可滥用。这种严谨的经验形态,构成了技能库高质量迭代的基石。

双重可执行验证与语义保真准入机制

经验抽象完成后,不能直接合入主干技能,否则极易出现“修复一个旧 Bug,引入三个新 Bug”的回归风险。VeriSkill 设计了严苛的第三阶段:可执行验证与准入机制(Executable Validation and Admission)

针对候选经验 $\ell_c$,系统首先将其与当前技能 $S_t$ 融合生成候选技能 $S’$。随后,候选技能需要连续闯过两道关卡:

第一道是局部一致性与迁移验证。候选技能不仅要重新运行并解决当初报错的任务归因集 $\mathcal{A}c$,还必须在从未见过的同模式迁移测试集 $\mathcal{T}_c$ 上展现出净正向收益。两者的平均改善幅度指标 $\widehat{\tau}{\mathrm{attr}}(S’)$ 与 $\widehat{\tau}_{\mathrm{trans}}(S’)$ 必须同时达标。若无法通过同模式泛化测试,候选经验将被打回并借助演进记忆进行局部修正,直至满足条件或达到迭代上限。

第二道是全局验证集评估与语义保真准入(Semantic-Preservation Check)。这是 VeriSkill 区别于其他代码类 Agent 进化的关键技术硬约束。为了通过验证器,大模型往往会产生一种作弊倾向:擅自删改原有业务代码逻辑、加入自欺欺人的空前置条件,或者引入绕过验证的逃生结构。为了彻底杜绝此类伪提升,VeriSkill 引入了语义保真判别函数 $M(x, a)$:

只有当候选技能在独立验证集 $\mathcal{V}$ 上的全局通过率 $\widehat{J}_{\mathcal{V}}(S’)$ 严格优于原技能 $S_t$,并且所有生成的产物 $100\%$ 通过语义保真检查时,修改才被正式并入版本,演化结果与失败模式同时回写演进记忆库;否则回滚至 $S_t$。整个闭环将技能进化从“遇到报错盲目打补丁”,转变成了“归因、抽象、可执行局部验证、带语义保真的全局准入”的严肃工程流程。

全面超越基准:主流验证工具与 Agent 评测

为了衡量 VeriSkill 的真实效能,作者团队在三大权威形式化验证环境(Dafny、Frama-C、VeriFast)上展开了系统性评测。实验覆盖了两组主流的 Agent 与底座大模型组合:Claude Code 搭配 Opus 4.8,以及 Codex 搭配 GPT 5.6 Sol。评估指标采用严格的 PASS 率,即生成产物不仅要被验证工具完备放行,还必须通过前述的语义保真测试。

在与无技能(No Skill)、单次生成的 LLM 技能(LLM Skill)、资深形式化专家手写技能(Human Skill)以及四大通用自进化算法(Skill-Creator、EvoSkill、AutoSkill、SkillOpt-Lite)的全面角逐中,VeriSkill 展现出了压倒性的优势。

实验结果揭示了几个极具深意的技术现象:

首先,未经进化的静态技能表现极不稳定。无论是大模型单次生成的技能,还是由具备七年形式化验证经验的专家手写的指南,在面对大规模多样化基准时往往效果欠佳,甚至在部分子任务中比完全不加技能的 No Skill 基线得分更低。这说明程序验证对指导规则的边界条件要求极其严苛,人类专家主观总结的经验容易产生规则覆盖盲区或带来不适时的干扰。

其次,现有的通用自进化方案难以应对验证场景。EvoSkill、AutoSkill 和 SkillOpt-Lite 尽管相比静态技能有所斩获,但在复杂任务上后劲不足。通用框架由于缺乏语义保真过滤,常常误将模型“通过投机取巧删改业务逻辑来骗过求解器”的代码视为进化成功,从而让技能库染上了有害的退化模式。而 VeriSkill 依靠纯净的归因和准入护栏,在所有测试轨道上均斩获最高分,相较于原始基线取得了极其显著的净增益。

消融实验:三大机制缺一不可

为了定量分析 VeriSkill 内部机制的贡献权重,研究人员在 Dafny 任务(基于 Claude Code / Opus 4.8)上实施了严密的消融实验。每次仅移除一个核心模块,其余环境与评测标准保持完全一致。

实验数据给出了极其鲜明的结果:

当移除第三阶段的可执行验证与准入机制时,模型性能骤降 21.3 个百分点。这是整个框架最核心的降幅点。失去了局部泛化测试和全局语义保真守门,大量针对个案的“有害修改”趁虚而入,迅速劣化了 Agent 的基础推演能力。

当剔除第一阶段的责任归因与过滤时,验证通过率下降了 13.0 个百分点。这强力佐证了初始论断:把求解器超时或任务矛盾当作技能缺陷去强行“学习”,会向系统注入极高浓度的毒性噪声,导致技能修改频频南辕北辙。

而去掉第二阶段的模式聚类与经验抽象同样引发了 8.3 个百分点的性能下跌。缺乏抽象化升维,进化过程就会被琐碎的实例细节所绑架,难以形成具备迁移能力的全局程序规则。

消融数据扎实地证明,归因过滤把控了学习信号的“纯度”,经验抽象保障了知识表示的“广度”,而可执行校验则筑牢了准入准则的“硬度”,三者缺一不可。

跨模型泛化:提取出真正的形式化方法论

在 Agent 技能研究中,一个长期存在的担忧是:演化出的技能文档是否只是针对特定模型提示词特性的“对抗性补丁”或过度拟合的 Prompt 调优?如果是这样,技能将很难跨模型复用。

为了解答这一疑问,研究者使用 Codex / GPT 5.6 进化出的技能,在完全不进行任何二次微调的情况下,直接挂载给统一由 Terminus 终端智能体驱动的多款异构大模型进行跨模型测试,包括 GLM-5.2、Kimi-K2.7、Qwen3.7-Max、DeepSeek-V4-Pro 以及专注于代码生成的 Qwen3-Coder。

测试结果显示,VeriSkill 进化出的知识展现出了极强的通用外溢价值:

所有模型在挂载该技能后,Dafny 验证通过率均迎来了爆发式增长,提升幅度介于 +15.3 到 +43.7 个百分点 之间。提升最为显著的往往是那些自身具备较好代码基础、但在形式化验证规则上缺少先验认知的模型;VeriSkill 提供的结构化经验就像一份精准的“外部操作手册”,迅速纠正了这些模型在契约声明和不变量推导上的盲区。而对于推演能力相对偏弱的轻量模型,外置技能同样带来了超过 15 个百分点的坚实提升,尽管其最终受限于指令遵循上限,但依然证明了这套进化框架产出的知识具有客观、通用的方法论属性。

案例剖析:面对同一个 Bug,进化策略有何本质差异?

VeriSkill 相比 EvoSkill 这类通用方案的降维打击能力,在一个经典的 C-to-Dafny 案例中体现得淋漓尽致。

在一段 C 语言底层代码中,原作者为了防止出现内存段错误,在函数入口处写下了一段针对宿主环境的防御性分支判断:if (!ptr) return NULL;

当 Agent 尝试将其转换并证明为 Dafny 规范时,底层验证器频繁报警,指出该分支在形式化语义下无法正常闭环。

通用进化框架 EvoSkill 在捕获这一执行失败后,机械地遵循“贴合源程序控制流”的通用直觉,向技能中打入了一条死板的补丁规则:“遇到指针校验分支,必须在目标语言中严格重建该分支结构”。结果在随后的推理中,Agent 不断在 Dafny 强类型系统里机械臆造多余的保护分支,甚至为了闭合这些无意义分支而编造错误的辅助引理,导致验证持续崩溃。

相反,VeriSkill 的责任归因模块精准识别出:该失败并非单纯的语法遗漏,而是由于 C 语言宿主级防御代码在形式化语义模型中的映射错位;经验抽象模块随即从同类修复中提炼出关键知识:在 Dafny 这类内建类型安全与强契约保障的语言中,宿主级防御分支属于纯运行期保护罩,若其并不携带被验证状态的数据流演化语义,应该将其前置提升为显式的预设契约(Requires),而非在函数体内部机械制造无效的控制流分叉。

正是这种对验证语义本质的深刻剖析,让 VeriSkill 彻底摆脱了浅层表面特征的束缚,做到了真正触及本质的自我提升。

形式化验证与 Agent 自进化的新图景

长久以来,形式化程序验证都被视为计算机科学中最坚固的堡垒之一,它要求极高的数理逻辑功底和繁复的人工干预。VeriSkill 的出现,向我们展示了 LLM Agent 在严谨科学计算领域自我迭代的可行路径:大模型不仅可以通过与编译验证工具的高频交互来纠错,更能够以一种“科学严谨、语义守恒、抽象归一”的工程框架,沉淀并进化出属于自己的高质量形式化推演技能库。

从“遇错乱改”到“严谨归因”,从“打个性补丁”到“提炼抽象知识”,VeriSkill 树立了一个范式:在追求 Agent 自我进化的道路上,通用的强化策略终究需要与硬核的领域科学规则(Domain-Specific Invariants)深度结合。形式化验证所要求的严格性与保真度,不仅没有成为大模型进化的绊脚石,反而成为了阻断幻觉、锚定真实知识的最强滤网。