@carolineschoi:我今天会在A厅的海报展示区,时间是韩国标准时间下午5点到7点45分。如果你想聊聊合成数据、自博弈或……欢迎来打个招呼!

X AI KOLs Following 论文

摘要

提出锚定自博弈(ASP)方法,通过生成器-修复器自博弈,结合嵌入相似度奖励和参考错误混合,来扩展代码修复监督,在全新基准测试BugSourceBench上,相较于标准自博弈,修复率相对提升24%。

我今天会在A厅的海报展示区,韩国标准时间下午5点到7点45分。如果你想聊聊合成数据、自博弈或强化学习,欢迎来打个招呼! 与优秀的合作者共同完成:@zeynebnkaya @ShirleyYXWu @tengyuma @tatsu_hashimoto @lschmidt3 论文:https://t.co/ei6vq44RE1
查看原文
查看缓存全文

缓存时间: 2026/07/09 15:39

我今天在A厅的海报区,韩国标准时间下午5点到7点45分。如果你想讨论合成数据、自对弈或强化学习,欢迎前来交流!与优秀的合作者 @zeynebnkaya @ShirleyYXWu @tengyuma @tatsu_hashimoto @lschmidt3 共同完成。论文:https://t.co/ei6vq44RE1


面向代码修复的锚定自对弈

来源:https://arxiv.org/html/2607.03523
Zeyneb Kaya · Shirley Wu · Tengyu Ma · Tatsunori Hashimoto · Ludwig Schmidt

摘要

代码修复是语言模型(LM)的一项重要能力:给定一个有缺陷的程序和单元测试,LM必须生成一个通过测试的修复版本。由于代码修复数据有限,我们的目标是利用LM生成缺陷-修复任务来扩展监督。我们提出了生成器-修复器自对弈,其中使用强化学习训练单个模型,使其既能生成缺陷也能修复缺陷。随着修复器能力的提升,生成器会适应并产生更难的缺陷,形成自动化的课程。为了测试这种课程是否能泛化,我们引入了BugSourceBench,这是一个覆盖多种真实缺陷来源的修复基准:人类编写代码中的缺陷、LM生成代码中的缺陷以及人类编辑LM生成代码中的缺陷。在BugSourceBench上,我们发现自对弈会向困难但不真实的缺陷漂移,在合成缺陷上有所改进,但在人类编写的缺陷上性能下降。我们提出了锚定自对弈(ASP),它通过添加一个针对生成的代码嵌入相似度奖励,并在修复器训练中混合参考缺陷,将自对弈锚定在一个小型参考集上。在各类缺陷来源上,ASP实现了最佳的修复率,相对于标准自对弈,平均修复率相对提升了**+24%,绝对提升了+7.0个百分点**,在LM和人类产生的缺陷上均有增益。

关键词:代码修复,程序修复,自对弈,大型语言模型

请参考图注

图1:用于代码修复的锚定自对弈。左图: 在生成器-修复器自对弈中,生成器编辑正确的程序以产生缺陷,修复器修复该缺陷;单元测试奖励缺陷的有效性和修复的正确性。由于单元测试仅验证通过/失败行为,而不验证真实性,自对弈可能向不真实的测试失败缺陷漂移。右图: BugSourceBench 在同一编程任务上评估修复,但改变缺陷来源,涵盖人类编写的缺陷、人类编辑的LM缺陷和LM生成的缺陷。锚定自对弈(ASP)通过将训练锚定在一个小型参考集上来缓解这种漂移,使用嵌入相似度奖励进行缺陷生成,并使用参考缺陷进行修复器训练。

1 引言

代码修复是编程工作流中使用的语言模型(LM)的一项重要能力(Xu等人,2022;Jimenez等人,2023)。给定一个有缺陷的程序和配套的单元测试,LM必须生成一个通过测试的修复。然而,高质量的真实世界修复数据有限(Just等人,2014;Widyasari等人,2020;Le Goues等人,2015;Madeiral等人,2019;Oliva等人,2025)。我们探究是否可以利用LM生成缺陷-修复任务用于训练,同时单元测试提供自动验证,从而扩展高质量的代码修复监督。我们研究一个开放式的生成设置,其中LM可以对正确代码应用任意文本编辑。这允许更多样化和自适应的合成数据。理想情况下,随着修复器在训练过程中改进,生成器会产生越来越具有挑战性和真实性的缺陷,形成自动化的课程。我们通过生成器-修复器自对弈(图1)来实现这一想法。使用强化学习训练单个模型交替生成缺陷和修复缺陷。生成器因产生有效、难度适当的缺陷(测试失败)而获得奖励,修复器因产生正确的修复(测试通过)而获得奖励。

生成器-修复器自对弈的一个关键挑战是分布漂移。单元测试验证功能行为,但不验证真实性:许多编辑都可能破坏测试,但很少的编辑能像实际遇到的缺陷那样真实。随着训练的进行,生成器可能向困难但不真实的缺陷漂移,从而在自生成任务上提升修复效果,但在真实世界任务上却下降。先前的工作通过将缺陷生成限制在仓库历史、删除或变异操作中来缓解这一问题(Wei等人,2025;Forrest等人,2009;Allamanis等人,2021)。然而,这限制了合成训练数据的多样性和规模,并且没有解决我们这里考虑的开放式生成设置。

为了评估自对弈是否能在其自身合成分布之外提升代码修复,我们引入了BugSourceBench,一个跨来源修复泛化基准。在LM辅助编程中,修复模型可能遇到来自多种来源的缺陷:人类编写的代码、LM生成的代码以及人类对LM生成代码的编辑。因此,BugSourceBench涵盖了人类编写的缺陷、人类编辑的LM生成缺陷以及来自较弱和较强代码模型的LM生成缺陷。关键在于,BugSourceBench保持修复任务固定,仅改变缺陷来源。

在BugSourceBench上,我们发现标准自对弈表现出分布漂移:它在LM生成的缺陷上有所改进,但在人类编写的缺陷上有所退步。我们提出了锚定自对弈(ASP)(图1),它将自对弈锚定在一个从目标缺陷来源中采样的参考集上。ASP以两种互补的方式使用这个参考集:一个代码嵌入相似度奖励引导生成器生成类似目标的缺陷,而参考缺陷混合则在训练过程中让修复器接触到真实的缺陷。锚定稳定了自对弈并改善了跨来源修复:ASP实现了总体最佳修复率,相对于标准自对弈,平均修复率相对提升了24%,绝对提升了**+7.0个百分点**,在LM生成的缺陷(相对提升100%,绝对提升**+11个百分点**)和人类来源的缺陷(相对提升7.1%,绝对提升**+3.4个百分点**)上均有提升。

我们的贡献是:

  • • 我们提出了生成器-修复器自对弈用于代码修复,并确定了分布漂移作为仅使用单元测试的自对弈的关键失败模式。
  • • 我们引入并发布了BugSourceBench,一个受控的多来源基准,涵盖人类编写、人类编辑LM和LM生成的缺陷。
  • • 我们提出了锚定自对弈(ASP),它通过结合用于缺陷生成的嵌入相似度指导和用于修复器训练的参考混合来减少漂移。

2 问题形式化

我们研究具有单元测试反馈的代码修复。我们的目标是使用单元测试作为正确性信号来训练修复模型,同时评估学到的修复器是否能泛化到真实的缺陷来源。

代码修复。

令 ( x ) 表示一个编程任务,包含自然语言指令、输入/输出规范、约束条件和单元测试套件。给定一个候选程序 ( c ),运行测试会产生一个二元验证器 ( v(x,c) \in {0,1} ),其中 ( v(x,c)=1 ) 当且仅当 ( c ) 通过任务 ( x ) 的所有测试,同时还会产生测试输出 ( o(x,c) ),例如编译错误、断言失败或堆栈跟踪。我们将任务 ( x ) 的有效缺陷定义为一个可执行程序 ( b ),该程序至少失败一个测试:
一个修复模型,或称为修复器,( \pi_F ) 将任务、有缺陷的程序和测试输出映射到候选修复的分布上:
[ y \sim \pi_F(\cdot \mid x, b, o(x,b)). ]
如果修复后的程序通过单元测试,即 ( v(x,y)=1 ),则修复成功。在我们的主要实验中,修复器输出完整的修正程序,而不是差异。

跨缺陷来源评估。

在部署中,缺陷可能来自异构来源:人类程序员、LM编程助手或人类对LM生成代码的编辑。因此,我们在一系列缺陷来源分布上评估修复。对于每个来源 ( s \in \mathcal{S} ),令 ( P_s(\cdot \mid x) ) 表示任务 ( x ) 的有效缺陷的分布。修复器 ( \pi_F ) 在来源 ( s ) 上的修复性能为
[ \mathrm{Perf}(\pi_F;s) = \mathbb{E}{x \sim \mathcal{D}} ; \mathbb{E}{b \sim P_s(\cdot \mid x)} ; \mathbb{E}{y \sim \pi_F(\cdot \mid x,b,o(x,b))} \left[ v(x,y) \right], ]
其中 ( \mathcal{D} ) 是任务上的评估分布。在我们的基准中,( \mathcal{D} ) 是固定保留任务集上的均匀分布,不同的缺陷来源共享相同的基础任务。我们通过对缺陷来源取平均来总结跨来源性能:
[ \mathrm{Perf}
{\mathrm{avg}}(\pi_F) = \frac{1}{|\mathcal{S}|} \sum_{s \in \mathcal{S}} \mathrm{Perf}(\pi_F;s). ]
该标准评估修复器是否在真实的缺陷来源上普遍提升,而不仅仅是在特定生成器诱导的分布上。接下来,我们通过BugSourceBench实例化 ( \mathcal{S} ),这是一个受控的基准,涵盖LM辅助编程中的多个缺陷来源。

3 BugSourceBench:受控缺陷来源评估

我们引入BugSourceBench来评估代码修复方法是否能在真实的缺陷来源上泛化。该基准旨在隔离缺陷来源偏移:所有来源共享相同的编程任务、规范和单元测试,仅在提供给修复模型的有缺陷实现上有所不同。

3.1 基准构建

我们基于BigCodeBench(Zhuo等人,2024)构建BugSourceBench,这是一个强调真实库和API使用的代码生成基准。每个BigCodeBench任务包含(i)自然语言编程指令,(ii)定义正确性的单元测试,以及(iii)通过这些测试的参考实现。我们通过保留原始提示和单元测试,并用有缺陷的程序替换参考实现,将每个任务转换为修复实例。

任务结构。

BugSourceBench的一个示例包含编程指令 ( x )、有缺陷的程序 ( b ) 以及配套的单元测试验证器 ( v(x,\cdot) )。BugSourceBench中的所有有缺陷程序在测试框架下执行,并且至少有一个单元测试失败。在评估时,模型接收 ( (x,b) ) 和单元测试反馈 ( o(x,b) )(例如,失败的测试和截断的错误跟踪),并且必须输出一个通过所有测试的修正程序 ( y )。

缺陷来源。

BugSourceBench包含四种缺陷来源变体,它们反映了LM辅助编程中常见的错误来源。所有变体都基于相同的基础任务构建;只有有缺陷的实现不同。

  • 人类。标注者向每个任务的人类编写参考解决方案中引入缺陷。他们被指示进行1-4处局部编辑,这些编辑保持可执行性,同时导致至少一个单元测试失败。我们鼓励真实的开发者错误,例如差一错误、错误的常量、缺失的边缘情况或API误用,而不是破坏语法的编辑。
  • 人类编辑的LM。为了模拟人在回路中的错误,首先提示 gpt-5-mini 解决该任务,并保留一个可执行但至少一个单元测试失败的不正确程序。然后标注者编辑这个草稿,同时保持其可执行且不正确。这个来源捕获了开发者在修改、集成或部分纠正LM生成代码时可能出现的错误。
  • LM错误(Qwen-7B)。我们提示 Qwen2.5-Coder-7B-Instruct 解决每个任务(不是为了生成缺陷),并保留可执行但至少一个单元测试失败的不正确程序。这个来源捕获了较弱的代码LM在标准代码生成提示下产生的错误。
  • LM错误(gpt-oss-20b)。我们使用相同的程序处理 gpt-oss-20b,从而得到来自较强代码模型的错误。

综合起来,这些变体覆盖了三个真实的缺陷来源系列:人类编写的缺陷、人类编辑的LM缺陷以及未经编辑的LM生成缺陷。由于任务和测试在各来源之间固定不变,BugSourceBench直接衡量修复性能如何随缺陷的起源而变化。

修复接口。

我们使用具有单元测试反馈的完整程序修复接口来评估修复模型。也就是说,模型接收任务描述、有缺陷的程序和截断的测试输出,并返回一个完整的修正程序。在附录A和3中,我们将此接口与没有测试轨迹的完整程序修复以及基于差异的修补进行比较。测试反馈提高了修复性能,而基于差异的修复由于格式不稳定和补丁应用问题通常性能较差。因此,我们在所有主要实验中使用测试轨迹接口。

基准分析。

我们在第A.1节中提供每个来源的示例,并在第A.2节中提供完整的构建细节,包括过滤标准和采样预算。在第A.4节中,我们评估前沿模型在BugSourceBench上的表现,并表明修复与代码生成不同:模型通常能从零开始解决它们无法修复的任务,反之亦然。我们还通过将缺陷归类为粗粒度错误类型,并使用 voyage-code-3 嵌入测量k-NN来源纯度来分析缺陷来源结构。这些分析揭示了系统性的来源相关故障模式以及强组内聚类。BugSourceBench让我们能够测试合成缺陷-修复训练是否能在真实的缺陷来源上提升修复性能,而不仅仅是在特定生成器诱导的分布上。接下来,我们描述生成器-修复器自对弈,然后介绍锚定自对弈(ASP),它通过将自对弈锚定在一个小型参考集上来减少缺陷来源漂移。

4 用于代码修复的自对弈

我们现在描述用于扩展代码修复监督的训练程序。我们首先介绍生成器-修复器自对弈,它使用单元测试结果作为奖励。然后我们展示这种仅基于单元测试的目标可能会向不真实的缺陷分布漂移,并引入锚定自对弈(ASP)来将自对弈锚定到参考缺陷来源。

4.1 生成器-修复器自对弈

对于每个训练任务,我们假设可以访问编程规范 ( x )、单元测试和一个正确的参考实现 ( c^\star )。我们训练一个策略 ( \pi_\theta ) 扮演两个角色:一个生成器 ( G ),将正确的程序编辑成有缺陷的程序;以及一个修复器 ( F ),修复由此产生的缺陷(图1)。我们将相应的角色条件分布记为 ( \pi_G ) 和 ( \pi_F )。生成器采样一个候选有缺陷程序 ( b \sim \pi_G(\cdot \mid x, c^\star) ),然后我们运行单元测试获得测试输出 ( o(x,b) )。如果 ( b ) 在测试框架下执行并且至少有一个单元测试失败,我们称其为有效的。无效的缺陷会受到惩罚,并且不会用于修复器训练。对于有效的缺陷,修复器采样一个或多个候选修复,条件依赖于任务、有缺陷程序和测试输出:( y \sim \pi_F(\cdot \mid x, b, o(x,b)) )。

4.2 正确性和难度奖励

修复器奖励。

修复器因产生正

相似文章