大型预训练语言模型时代的自动化程序修复

互联不一般哥 2024-05-17 11:10:31

Automated Program Repair in the Era of Large Pre-trained Language Models

Chunqiu Steven Xia1, Yuxiang Wei1, Lingming Zhang1

1University of Illinois Urbana-Champaign

引用

Xia C S, Wei Y, Zhang L. Automated program repair in the era of large pre-trained language models[C]//2023 IEEE/ACM 45th International Conference on Software Engineering (ICSE). IEEE, 2023: 1482-1494.

论文:https://doi.org/10.1109/ICSE48619.2023.00129

摘要

在这项工作中,我们首次对直接应用LLMs(大语言模型)到APR(自动程序修复)进行了广泛的研究。我们选择了 9 个最新的 LLMs,包括生成模型和填充模型,大小从 125M 到 20B 不等。我们设计了 3 种不同的修复设置来评估使用 LLMs 生成补丁的不同方式:1)生成整个补丁函数,2)填充给定前缀和后缀的代码块,3)输出单行修复。我们将这些修复设置下的LLMs 应用于 3 种不同语言的 5 个数据集,并比较不同的LLMs 修复的错误数量、生成速度和编译率。我们还将LLMs与最新最先进的 APR 工具进行了比较。我们的研究表明,直接应用最先进的LLMs已经可以在我们所有数据集上远远优于所有现有的 APR 技术。在所研究的LLMs 中,APR 存在缩放效应,其中较大的模型往往会获得更好的性能。此外,我们首次展示了错误行后的后缀代码(在填充式 APR 中采用)不仅对于生成更多修复程序而且对于具有更高编译率的更多补丁都很重要。除了补丁生成之外,LLMs还认为正确的补丁比其他补丁更自然,甚至可以用于有效的补丁排名或补丁正确性检查。最后,我们表明基于 LLMs 的 APR 可以通过以下方式进一步大幅提高:1)增加样本大小,2)合并修复模板信息。

1 引言

随着软件程序和系统在日常生活中变得越来越普遍,软件错误也越来越普遍。由于软件系统在医疗保健到交通等领域的广泛采用,这些错误可能会导致危险的安全问题和财务损失。因此,开发人员通常需要花费大量时间和精力来修复软件错误。为了帮助开发人员减少这种手动工作,我们构建了自动程序修复(APR)工具,可以在给定原始错误程序的情况下自动生成潜在的补丁。

在传统的 APR 技术中,基于模板的 APR 已被广泛认为是最先进的技术。这些技术利用通常由人类专家设计的修复模板来修复源代码中特定类型的错误。因此,这些 APR 工具在可修复的错误类型方面受到底层修复模板的限制。为了解决这个问题,研究人员提出了基于学习的 APR 工具,该工具通常将程序修复建模为神经机器翻译(NMT)问题,其目标是将有错误的程序转换为固定的程序。程序。这些基于学习的 APR 工具的核心组件是编码器和解码器对,其中模型旨在通过编码器捕获错误上下文,然后使用解码器自回归生成补丁。因此,这些基于学习的 APR 工具需要包含错误和修补代码对的监督训练数据集,这些数据集通常通过从开源存储库中挖掘历史错误修复来获得。虽然基于学习的 APR 工具在可修复的错误数量和种类上都显示出改进,但它们仍然受到训练数据的限制,这些数据可能包含不相关的提交,并且仅包含有限的错误修复类型,这可能无法推广到看不见的错误类型。

构建大型预训练语言模型(LLMs)的最新进展提供了一种替代解决方案,可以应用于程序修复,而无需依赖历史错误修复。虽然 LLMs 通常是 NLP 任务的通用工具(例如 GPT3),但它们也通过代码微调而用于编程语言(例如 Codex和 ChatGPT)。与专门设计的基于学习的 APR 模型不同,LLMs 使用多达数十亿个文本/代码标记以无监督的方式进行训练,并且可用于各种代码任务。最近,AlphaRepair提出利用 CodeBERT(一个在数百万代码片段上预训练的大型代码模型)直接用于 APR。 AlphaRepair 的关键见解是,我们可以直接使用模型在给定周围上下文(包括前缀和后缀)的情况下预测正确的代码应该是什么样子,而不是学习从有错误的代码到固定代码的转换,即填充-风格年利率。利用这个想法,AlphaRepair 展示了最先进的修复结果,无需对错误修复数据集进行微调。虽然 AlphaRepair 比之前基于学习的 APR 有所改进,但它使用的模型(125M 参数)远小于当前最先进的 LLMs (Codex:12B 参数和 GPT-3:175B 参数)。除了 AlphaRepair 之外,研究人员还直接利用 Codex 进行生成 APR,即根据错误之前的上下文(即仅前缀)生成修复。然而,这些研究主要集中在 Codex 上,并且仅在简单编程任务上有 40 个错误的小数据集上进行评估。

当前最先进的LLMs 还包括对代码相关任务的评估,例如代码完成、文档字符串生成和变量/类型预测。然而,这些评估仍然主要集中在 BLEU 分数等 NLP 指标上,这些指标并不能准确衡量生成代码的功能或语义正确性。此外,数据集由手工策划的代码问题组成,这些问题不能准确反映开发人员在现实世界中所从事的项目类型。

我们首次对最近的LLMs 进行了广泛的评估,以修复现实世界的项目。我们设计了 3 种不同的 APR 实验设置:1)完整的函数生成 2)正确的代码填充和 3)单行生成来展示 LLMs 应用于 APR 的不同方式。在我们的研究中,我们包括了两种流行的 LLMs 架构类型(生成模型和填充模型),以展示使用每种类型进行 APR 的优点和缺陷。我们包含具有各种不同参数大小的模型,从 1.25 亿到 200 亿不等。我们不仅评估修复效率的提高,还评估增加模型大小时速度的权衡。总共,我们使用 5 个不同的修复数据集,其中包含真实的开源错误和跨 3 种编程语言的开发人员书面测试,以评估实际设置下的 APR。与现有的用于 APR 的 LLMs应用相比,我们的研究首次将最先进的LLMs 纳入各种数据集和编程语言的填充式和生成式 APR。

总而言之,本文做出了以下贡献。

Dimension。本文弥合了LLMs 的最新进展和一个关键的软件工程问题——APR 之间的差距。本文不仅展示了直接利用LLMs 解决重要 APR 问题的潜力和未来,而且还为最近的LLMs 提供了一个现实的评估场景,这些场景主要针对简单/综合编码问题而不是所研究的实际系统进行评估在 APR 区域。Study。我们使用 9 个不同的近期LLMs 对 5 个不同的修复数据集、跨 3 种不同的编程语言(Java、Python 和 C)进行了广泛的评估。我们使用我们设计的 3 种修复设置对LLMs 进行比较。使用流行的修复数据集,我们进一步将LLMs 与最先进的 APR 工具进行比较。Practial Guidelines。我们的研究首次表明,在广泛研究的 Defects4J 1.2 数据集(和其他数据集)上,直接应用最先进的 LLMs 已经可以大大优于所有现有的 APR 工具,例如,Codex 可以比现有的多修复 32 个错误最佳 APR 技术。在所研究的LLMs 中,APR 存在缩放效应,其中较大的模型往往会提供更强的 APR 结果。此外,我们首次展示了错误行后的后缀代码(在填充式 APR 中采用)不仅对于生成更多修复程序而且对于具有更高编译率的更多补丁都很重要。除了补丁生成之外,LLMs 还认为正确的补丁比其他补丁更自然,甚至可以用于有效的补丁排名或正确性检查。最后,我们表明基于 LLMS 的 APR 可以通过以下方式进一步大幅提高:1)增加样本大小,2)合并修复模板信息。

2 技术介绍

2.1 模型

我们首先描述用于评估的不同LLMs。我们的选择过程从 Hugging Face上托管的流行模型列表开始,Hugging Face 是一个用于托管和部署大型模型的开源平台。我们根据受欢迎程度(本月的下载量)对模型列表进行排序,并选择包含代码作为训练数据的LLMs。此外,我们还从不同组织和类型(如下所述)中挑选模型,以获得多样化的模型集。除了开源模型之外,我们还使用闭源 Codex 模型(只能通过 API 访问),因为它已证明在代码相关任务上取得了令人印象深刻的性能。总共,我们使用 9 个不同的LLMs进行实验。

我们选择的 LLMs 参数大小范围从 125M 到 20B。表一列出了LLMs概述。列 Model 是模型名称,Parameters 表示模型参数的数量,Training Dataset 表示用于预训练的数据集(N.R. 未发布),Type 是指模型可以执行的 APR 类型(填充式或生成式)。

1)生成模型:

GPT-Neo、GPT-J、GPT-NeoX 这三个模型都是 GPT-3 转换器架构的开源实现。在我们的实验中,我们使用具有 125M、1.3B 和 2.7B 参数的 GPT-Neo 模型。GPT-J 和 GPT-NeoX 是更大的模型,具有 6.7B 和 20B 参数。这些模型在 The Pile 上进行训练,这是一个 800GB 的数据集,结合了 22 个不同的基于文本的数据集,其中 7.6% 包含开源 Github 代码。Codex 为代码生成而设计的基于12B 参数GPT-3 的模型。Codex 使用在自然语言语料库上训练的 GPT-3 权重进行初始化,然后在包含 159GB 代码文件的大型语料库上进行微调。

2)填充模式

CodeT5基于T5 架构的220M参数模型,专为代码相关任务而设计。CodeT5 通过将 CodeSearchNet与 BigQuery 的 C/C 数据集相结合,使用跨度预测目标对 8 种不同编程语言的 835 万个函数进行训练。INCODER 一种为代码填充而设计的模型,采用因果屏蔽目标。INCODER 接受了开源 Github/GitLab 代码 (159 GB) 和 StackOverFlow 问题与解答 (57 GB) 的培训。我们使用1.3B和6.7B参数版本。Codex 除了使用Codex作为生成模型之外,我们还使用最近添加的后缀功能来执行代码填充。由于Codex不是开源的,我们不知道模型如何执行填充。

2.2 基于LLM的补丁生成

在我们的研究中,我们为APR设计了三种设置:1) 完整的函数生成——输入是有缺陷的函数,目标是输出修补后的函数。2) 正确的代码填充——错误位置已知,目标是根据错误函数的前缀和后缀生成正确的替换代码。3) 单行生成——提供错误位置并通过单行更改修复错误。单行生成使用正确代码填充中的错误子集。我们将这种情况分开,因为许多故障定位技术提供了单个代码行粒度的排名。更重要的是,填充式LLMs 和生成式LLMs都可以应用于此设置,从而可以直接比较两者。我们现在描述每个设置的不同输入。

1)完整的函数生成:

对于此设置,初始输入是原始的 buggy 函数。我们的目标是使用生成模型来自回归生成 buggy 函数的整个修补版本。然而,直接向 LLMs 提供有缺陷的函数没有作用,因为每个 LLMs 都没有针对 APR 进行预先训练(即不知道目标是生成修补函数)。因此,为了方便直接使用LLMs 进行APR,我们使用特定的提示来使模型能够执行few-shot学习。这使得LLMs 能够识别任务并通过完成提供的输入来生成修补函数。我们在这里注意到,完整函数生成的任务没有假设 1)错误的位置和 2)所需的错误或修复的类型。因此,LLMs 需要找出该函数存在bug的原因,并提供补丁来修复该bug。

图1 用于完整函数生成的 APR 输入

图 1 显示了由两个示例错误修复组成的输入(一个是我们制作的,另一个来自目标错误所在的同一项目/数据集),以演示任务和输出的预期格式。首先,我们遵循先前的研究 [32] 并从任务描述开始:为有缺陷的函数提供修复。这以自然语言描述了我们希望LLM执行的任务。这是一个 Python 示例,我们使用 Python 注释格式 作为此描述的前缀(我们根据错误代码的语言使用其他注释前缀)。然后,我们提供一个示例错误和补丁对。在图 1 中,该示例是一个计算斐波那契数的函数。我们为示例 buggy 和固定函数添加 Buggy Function 和 Fix Function 前缀,以为模型提供额外的上下文。对于我们的第二个示例,我们遵循相同的提示风格,并从错误所在的同一项目中选择一个有错误和已修补的函数对。这样我们就可以为模型提供一些项目中使用的编码风格的示例。最后,我们通过添加我们想要修复的错误来完成提示。

2)正确的代码填写

与完整的函数生成不同,函数内的错误位置是未知的。为了正确的代码填充,输入是删除有问题的代码块后的前缀和后缀。为了填写正确的代码,前缀和后缀都可以提供有用的信息。因此,生成模型不适合此任务,因为生成过程仅以左侧的上下文(前缀)为条件。因此,为了正确的代码填充,我们仅使用通过对左(前缀)和右(后缀)代码进行调节来执行生成的填充模型。

图2 APR输入以正确填写代码

图 2 显示了填充任务的示例输入。我们从要修复的目标错误函数开始,并删除有错误的代码块。这为我们提供了仍然正确的前缀和后缀代码。然后我们在前缀和后缀之间放置一个填充标记。该填充标记(例如,)向模型表明这是我们希望生成新代码的位置。然后,模型仅生成代码来填充缺失的块,我们通过将模型输出与前缀和后缀代码片段相结合来获得补丁。

3)单行代码生成:

在单行生成中,提供了错误位置,并且错误只需要单行更改。图 3a 显示了纠正代码填充的类似设置,其中我们提供了前缀和后缀代码,并使用填充模型来生成替换行。与正确的代码填充不同,我们还可以通过仅提供前缀来使用生成模型。图 3b 演示了使用生成模型执行此任务的设置。由于我们知道该错误只需要一行更改,因此我们可以在模型为我们提供一行后停止生成。我们不能使用生成模型来应用相同的策略来正确填充代码,因为这些错误可能需要多行来修复,并且我们不知道何时可以停止生成。此外,当使用生成模型进行单线生成时,由于生成模型的因果性质,我们无法为模型提供后缀代码。我们将其与同一任务中的填充模型进行对比,以证明包含 APR 后缀上下文的效果。

图3 用于单行生成的 APR 输入

2.3 补丁排名和验证

对于所有 3 个修复任务,补丁生成过程是相似的。我们向 LLMs 提供构建的输入,并使用采样为每个错误生成多个补丁。我们使用具有采样温度的核采样。较低的温度意味着模型可能会选择具有更高可能性的标记,从而产生更相似的样本(温度为 0 通过在每个生成步骤中选择最可能的标记来给出确定性结果)。较高的温度使模型更有可能选择可能性较低的标记,从而产生更独特和有趣的样本。对于 APR 这样的问题,如何选择最佳温度值并不明显。对于某些错误,人们可能更喜欢较低的温度值,以便快速达到合理的补丁。对于更严重的错误,更高的温度值可能有助于生成更多独特的补丁以尝试提供修复。对于我们的实验,我们使用之前的工作中使用的默认设置。

平均熵是生成的所有标记的平均熵,而总熵则计算序列的总熵。对于补丁排名,我们首先优先考虑熵较低的补丁。这样,更自然的补丁可以排名更高。之前利用 LLMs 进行 APR 的工作要么使用平均熵要么使用总熵,而没有进行彻底的评估,并且主要集中在补丁排名上。相反,在这项工作中,我们根据经验比较了两种熵计算,并进一步将它们应用于补丁正确性检查。最后,对于生成的每个补丁,我们过滤掉任何具有语法或语义错误的补丁,并根据测试套件验证其余补丁,以识别通过所有测试的补丁。

3 实验评估

3.1 实验设置

研究问题。我们的评估调查了以下问题。

RQ1:不同类型的LLMs 在不同的APR设置下表现如何?

RQ2:直接应用LLMs 进行 APR 与最先进的 APR 工具相比如何?

RQ3:LLMs 可以直接用于补丁排名和正确性检查吗?

RQ4:我们可以进一步提高LLMs 的表现吗?

RQ1 不同LLMs的比较

(1)修复效果

我们首先将 LLMs与其他 LLMs 进行比较,以生成合理且正确的补丁。我们首先观察到,与之前的 NLP 研究类似,修复效果存在缩放效应。随着模型大小的增加,生成的正确且合理的补丁数量也会增加。直接查看在同一数据集上训练的 GPT 模型组,我们发现当我们在所有修复数据集上使用更大的模型时,性能持续提高。然而,我们看到 Codex 模型 (12B) 的性能优于最大的模型 (GPT-NeoX (20B))。我们假设这是因为 Codex 是为代码生成而设计和微调的;另一方面,虽然 GPT-NeoX 的训练数据集部分由代码组成,但它是为通用文本生成而设计的。

表1 正确填充 APR 的代码(SH bug)

表2 单行 APR(SL bug)

表1和表2显示了正确的代码填充和单行生成修复任务的结果。与之前的结果类似,我们再次看到随着模型大小的增加,性能提高的缩放效应。与完整的函数生成相比,我们观察到使用正确的代码填充和单行生成的每个模型都能够产生更高的正确修复比例。此外,我们还观察到,在后两种设置中,正确补丁与合理补丁的比率也较高。这表明使用代码填充和单行生成生成的补丁更有可能是正确的修复。性能的提高是因为为了生成完整的函数,模型需要理解给出的提示、定位错误并提供正确的修复。另一方面,当我们在正确的代码填充和单行生成中向模型提供错误位置信息时,它只需要填充或完成部分代码,从而产生更多正确的补丁。在评估 Codex 模型时,这种比较更加直接,Codex 模型是唯一可以执行代码填充和函数生成的模型。我们看到,当执行正确的代码填充时,Codex 能够修复总错误的 40% (62/154),而当要求生成整个函数时,它会下降到 28% (63/225)。

对于表2中的单线生成结果,我们包括生成模型和填充模型。然而,对于生成模型,我们无法为其提供后缀代码片段,因为它们的生成仅依赖于先前的上下文。我们将其与填充模型进行比较,填充模型可以根据前后上下文执行填充。我们观察到填充模型比生成模型表现更好。此外,由于我们能够使用 Codex 的生成版本和填充版本,因此我们可以直接比较仅给出前缀与同时给出前缀和后缀上下文时模型的修复能力。我们看到,当使用原始错误函数中的后缀信息时,Codex 模型能够提高所有修复数据集中正确且合理的修复的数量。这表明,对于修复来说,成功利用有问题的行之后的代码对于修复错误非常重要。

(2)补丁生成速度

接下来我们看看使用 LLMs 生成补丁的速度。从前面的结果分析中我们已经看到,随着模型尺寸的增加,修复性能得到提高。然而,这种性能提升并不是免费的,因为较大的模型需要更长的推理时间。我们仅包含在同一硬件上本地运行的模型(即不包括 Codex,因为它只能通过 API 访问进行访问)。我们发现,随着模型大小的增加,补丁生成速度急剧减慢(在完整函数生成方面,GPT-NeoX 比 GPT-Neo 125M 慢 71 倍)。这证明了使用大型模型时修复效率和时间成本之间的权衡。此外,我们发现,与单行生成和正确的代码填充相比,完整的函数生成需要更多的时间,因为生成整个函数比生成单行或块要耗时得多。这表明,虽然LLMs 有能力一次执行故障定位和修复,但对于现实世界的软件系统,首先使用传统的故障定位技术来查明精确的错误位置,然后再利用它仍然更具成本效益。LLMs 用于更有针对性的补丁生成。

(3)变异速率

我们评估每个 LLMs 生成的补丁的编译率。图 4 显示了所有研究的LLMs 在 Defects4J 1.2 上使用三种修复设置的语法和语义错误率。我们首先观察到,随着模型大小的增加,生成的补丁的总体错误率(句法语义)下降。这重申了之前讨论的LLMs 的缩放效应,并表明较大模型生成的补丁包含较少的错误。接下来我们看到所有使用单行生成的生成模型都会产生大量语法错误。回想一下,使用生成模型时的单行生成仅在 buggy 函数中提供前缀。因此,生成的行很容易引入一些语法错误(例如,添加带有左括号的 if 语句),因为模型不知道后缀代码上下文是什么。另一方面,其他两种设置中产生的语法错误量要低得多。对于完整的函数生成,LLMS 可以在训练期间有效保留语言的语法并生成语法正确的函数。对于正确的代码填充,我们不仅可以得到较低的语法错误,而且还可以实现最低的语义错误。同时拥有前缀和后缀可以为模型提供足够的上下文,从而提高可编译补丁率。

图4 Defects4J 1.2 的语法和语义错误率

RQ2 与最先进的ARP工具的比较

我们首先将直接使用 LLMs 进行修复的结果与 Defects4J 1.2 上的传统 APR 工具和基于学习的 APR 工具进行比较。表 3显示了我们评估中的顶级基线工具和LLM的正确错误修复数量。最后 3 列显示使用三个 APR 设置中的每一个时生成的正确补丁的数量。然后,我们将为每个模型生成的所有补丁组合在一起(第 2 列),以展示可以针对 Defects4J 1.2 中的 255 个单功能错误获得的修复总数。请注意,这仍然是一个公平的比较 - 先前的 APR 技术通常对每个错误使用 5 小时的超时,同时为 3 个设置中的每一个生成 200 个补丁(即最多 600 个补丁)总共)每个模型的成本不超过 2.5 小时。

表3 Defects4J 1.2 基线比较

我们观察到,与一些最新的 APR 工具相比,某些模型能够实现可比的性能。此外,这个结果是在每个错误仅生成最多 600 个样本时获得的,而先前的方法,尤其是基于学习的工具,可以为每个错误生成最多 5000 个补丁。虽然最有效的模型(Codex)已经可以超越所有现有技术(例如修复 99 个单功能错误),但通过组合所有模型生成的补丁(总计),我们可以实现 109 个单功能错误的正确修复!令人惊讶的结果表明,通过直接将 LLMs 应用于 APR,无需任何特定的更改/微调,与现有基线相比,我们已经可以实现最高数量的正确修复。

图5 Bug 修复 Defects4J 1.2 上的Venn图

图 5 显示了使用 LLMs 生成的独特修复的Venn图,与 Defects4J 1.2 中所有单一功能错误的 3 个最佳性能基线进行比较。我们还将其他基线的所有修复合并到维恩图中的“其他”类别中。我们观察到,通过将所有模型组合在一起,我们可以生成大量独特的错误修复 (36),迄今为止还没有其他工具修复过。由于潜在的数据泄漏问题(在第六节中详细讨论),我们进一步研究 LLMs 是否可以生成与开发人员补丁不完全相同的正确补丁。图 5b 显示了当我们删除与开发人员补丁完全相同的所有修复时,与基线相比,Defects4J 1.2 上的独特错误修复。我们观察到,将所有 LLMs 结合在一起仍然可以实现最高数量的错误修复 (93),其中有 31 个独特的错误修复。

图6 LLMs 生成的独特错误修复

为了展示这些 LLMs 的能力,我们展示了他们产生的一些独特的修复。图6a是INCODER 6.7B模型在正确的代码填充任务下产生的正确补丁。我们在这里看到该函数称为 areEqual,该错误是由于缺少比较两个输入是否具有相同引用的特定情况而引起的。使用前缀(函数名称)和后缀(其他带有返回值的比较语句),模型计算出要在此处插入的正确代码(在继续之前首先检查引用是否相同)。此类代码常见于开源项目中,这些项目使用类似的比较函数,LLMs可以从中学习。事实上,我们在不同的项目中发现了几个类似的比较函数(检查对象是否具有相同的引用),作为一些 LLMs 接受训练的 Pile 数据集的一部分。此外,与通常在单行上工作的传统 APR 工具不同,LLMs 可以生成多行代码以提供正确的修复。

图 6b 显示了 Codex 生成的 Math-69 错误的补丁。此处的函数计算 2 边 2 样本 t 检验的 p 值矩阵。该错误是由函数调用极其接近 1 时的精度误差引起的。这里模型生成了一种计算 p 值的替代方法,该方法比以前稳定得多。这是一个很难修复的错误,因为更改非常微妙,但它不适合传统 APR 中使用的任何常见模板。为了生成正确的修正,模型需要了解函数的目标(p 值计算)并使用统计公式。这两个目标都可以通过 Codex 来实现,因为它不仅接受代码训练,还接受一般文本的训练,其中包含许多 t 检验 p 值计算的描述和示例。这种独特的修复显示了使用 LLMs 进行程序修复的好处,其中也可以利用项目的领域知识。

RQ3 补丁排名和正确性检查分析

1)熵:

由于我们使用 LLMs 来生成补丁,因此我们可以计算每个补丁的熵。熵计算生成的样本的自然程度(公式 1)。我们观察到,所有模型的正确且合理的补丁的平均熵值都小于不合理的补丁。换句话说,所研究的LLMs认为正确修复潜在错误的正确补丁比其他补丁更自然。此外,虽然正确补丁和合理补丁之间的熵差异并不像不合理补丁那么大,但我们还发现正确补丁通常比合理补丁的熵要小。最近的工作表明,现有的补丁正确性检查解决方案(即从合理的补丁中识别正确的补丁)在应用于更复杂的补丁时可能会出现数据集过度拟合和性能下降的问题。我们首次证明,通过 LLMs 进行熵计算可以帮助区分正确的补丁和合理的补丁,这表明直接利用 LLMs 熵度量进行补丁正确性检查的前景广阔。

2)补丁排名:

使用每个生成的补丁的熵值,我们执行排序以首先验证具有较高排名(较低熵)的补丁。我们选择了 5 个正确补丁数量最多的LLM来执行此分析。图 7 显示了随着我们增加要验证的补丁数量,使用不同补丁排名策略修复的 Defects4J 1.2 数据集的错误数量。我们看到,与随机挑选补丁进行验证(蓝线)相比,使用熵排名(橙色和绿线)时,我们可以更快地验证正确的补丁。这表明熵可以是一种有效的度量,用于对潜在补丁进行排序,以优先考虑较低熵补丁,以便在更严格的时间限制下进行验证。此外,我们观察到与平均熵相比,总熵的表现稍好。我们假设这是因为无论生成序列的长度如何,熵和都会计算整个序列的熵。因此,与较长的序列相比,较短的序列往往具有较低的和熵;有趣的是,这与传统的 APR 或补丁正确性检查技术一致,这些技术遵循Occam’s razor假设,有利于简单补丁而不是复杂补丁。

图7 在 Defects4J 1.2 上使用不同补丁排名策略时修复的错误数量

RQ4 直接基于LLM的ARP改进

在之前的 RQ 中,我们表明,通过直接应用 LLMs 进行 APR,我们已经可以实现与之前的 APR 工具相当的性能。我们进一步探索提高LLMs 的 APR 能力的可能性。对于此实验设置,我们选择性能最佳的模型(除了 Codex,它已经优于现有的 APR 技术,无需任何进一步扩展)——INCODER 6.7B,并结合修复模板运行更长时间的模型(每个错误 2000 个样本)。我们通过调整我们的填充式修复设置来评估 Defects4J 1.2 中的所有错误,遵循 AlphaRepair(它展示了我们研究中所有设置中的最佳性能),为每个由参考更改的位置生成补丁补丁而不是仅在单个更改位置上。此设置类似于之前基于学习的修复工具,并允许我们在完整的 Defects4J 1.2 数据集上进行比较。此外,根据之前的工作,我们包括对 Defects4J 2.0 单行错误和 QuixBugs-Python 的评估。

我们通过使用原始的 buggy 线应用不同的修复模板。此类模板包括:保留部分前缀或后缀,替换方法调用或参数,以及更改/添加新的布尔条件或运算符到有问题的行。这些修复模板利用原始的越野车线并为模型提供重要的起始代码。我们观察到,如果我们更长时间地应用模型并生成更多样本,我们可以大大提高所有三个数据集中修复的正确错误的数量,并获得与最佳基线获得的结果非常接近的结果。此外,我们可以通过使用简单的修复模板获得进一步的改进,并在所有数据集上实现最高数量的正确修复错误,例如修复 Defects4J 1.2 上的 78 个错误,其中修复了 15 个其他基线工具之前没有修复过的独特错误。这一发现表明,LLMs 不仅在直接用于程序修复时有效,我们还可以将它们与更多领域特定技术(例如简单修复模板)相结合,以进一步提高其性能。

转述:尚也

0 阅读:4

互联不一般哥

简介:感谢大家的关注