使用大型语言模型的自动修补正确性评估

互联不一般哥 2024-06-19 14:08:19

引用

arXiv:2303.00202 [cs.SE]

https://doi.org/10.48550/arXiv.2303.00202

论文:http://arxiv.org/pdf/2303.00202v3

摘要

自动程序修复(APR)技术在修复现实世界中的错误方面显示出越来越有希望的结果。尽管有效,但APR技术仍然面临着过拟合问题:生成的补丁可能是错误的,尽管它通过了所有测试。手动评估可以通过所有测试的生成补丁的正确性是耗时的。为了解决这个问题,已经提出了许多方法来自动评估APR技术生成的补丁的正确性,主要是在交叉验证设置中进行评估。然而,对于由新的或不可见的APR工具生成的补丁,用户在交叉验证设置中隐含地需要手动标记这些补丁的一个重要部分(例如,在10折交叉验证中的90%),然后推断剩余的补丁(例如,在10折交叉验证中的10%)。为了缓解这个问题,在本研究中,我们提出了LLM4PatchCorrect,通过采用大型语言模型对代码进行补丁正确性评估。具体来说,对于由新的或看不见的APR工具生成的补丁,LLM4PatchCorrect无需使用这些工具的标记补丁进行训练,而是直接查询大型语言模型对代码进行预测,以获取正确性标签而无需训练。这样,LLM4PatchCorrect可以减少在构建模型以自动评估新APR工具生成的补丁的正确性时的手动标记工作量。为了向大型语言模型提供关于自动补丁正确性评估(APCA)任务的知识,LLM4PatchCorrect利用了错误描述、执行跟踪、失败测试用例、测试覆盖率以及由现有APR工具生成的标记补丁,然后决定新的或看不见的APR工具的未标记补丁的正确性。此外,LLM4PatchCorrect优先考虑来自现有APR工具的与新APR工具生成的补丁具有语义相似性的标记补丁,以提高LLM4PatchCorrect对新APR工具生成的补丁的准确性。我们的实验结果表明,LLM4PatchCorrect在没有新的或看不见的APR工具的标记补丁的情况下,平均准确率达到84.4%,F1分数为86.5%。

1 引言

自动程序修复(APR)领域日益受到关注,涌现了各种不同的工具。尽管APR取得了显著进展,但目前的工具仍然存在过拟合问题。由于缺乏强有力的程序规范,APR工具通常依赖于测试用例来验证生成的修补程序的正确性。然而,即使通过了所有测试用例,也不能完全保证修补程序的正确性,因为可能无法真正修复程序。若修补程序虽然通过所有测试用例,但在程序规范方面存在问题,则被视为“过拟合”。

在实践中,识别过拟合修补程序对于APR工具至关重要。以从业者Bob为例,他喜欢使用先进的APR工具,但研究表明,这些工具可能生成更多过拟合的修补程序,而非正确的修复方案,导致高误报率。这可能导致开发人员对自动软件工程工具失去信任。因此,降低误报率对于生成和验证APR方法至关重要。

为了解决这一问题,研究人员提出了自动修补程序正确性评估(APCA)方法。这些方法分为动态方法和静态方法。动态方法通过运行测试用例或收集运行时信息进行评估,而静态方法则通过代码模式或特征来判断修补程序的正确性。尽管这两种方法都取得了进展,但各自存在局限性。动态方法耗时,而静态方法虽高效但可能不够精确。

本研究致力于推动静态APCA方法的发展。已经提出了多种静态APCA方法,这些方法从修补程序中提取特征,并从标记数据集中学习正确的模式。然而,以往研究主要使用k-fold交叉验证评估这些方法,这存在一个缺陷:对于新的或不可见的APR工具生成的修补程序,需要大量手动标记,这可能阻碍实际应用。

鉴于新的APR工具不断涌现,我们旨在减轻用户负担,避免手动标记这些新工具生成的修补程序。我们提出是否可以利用现有工具生成的标记修补程序来预测新工具生成的修补程序的正确性。为解决这一挑战,我们引入了LLM4PatchCorrect方法。该方法利用大型语言模型Starcoder-7B来评估修补程序的正确性,无需微调。我们直接利用LLM的预训练目标来进行APCA任务,这种上下文学习方式增强了预测效果。

LLM4PatchCorrect选择语义上相似的修补程序,并整合了缺陷描述、执行跟踪、失败的测试用例和测试覆盖率等指导信息,以增强对修补程序的理解。通过各种指导信息,LLM4PatchCorrect能够提供更准确的预测结果。实验结果表明,LLM4PatchCorrect在两个大规模数据集上显著提高了准确性、F1和AUC分数。

总的来说,本文的主要贡献包括:

强调了一种新颖的APCA任务设置的重要性,其中假设对于新的或看不见的APR工具,没有标记的修补程序可用。这种设置更符合APCA任务的初始目标,即减少手动标记的工作量,并评估方法将嵌入在现有标记数据中的知识转移到未来未标记数据的能力。据我们所知,我们是第一个将先进的LLM引入解决APCA任务的研究。我们为这种具有挑战性设置(即新的或不可见的APR工具没有标记的修补程序)设计了基于LLM的解决方案LLM4PatchCorrect。我们提出了将多样化的指导信息纳入LLM4PatchCorrect,以辅助在修补程序正确性方面做出决策。具体来说,LLM4PatchCorrect考虑了缺陷描述、执行跟踪、失败的测试用例、测试覆盖率以及由现有APR工具生成的标记修补程序。

2 方法

LLM4PatchCorrect旨在利用现有APR工具的已标记补丁来预测由新的或未知的APR工具生成的补丁的正确性。LLM4PatchCorrect的框架如图1所示。它接受目标APR工具生成的补丁作为原始输入(图1中的❶所示),并生成其正确性标签(即干净或过拟合)。具体而言,LLM4PatchCorrect包括以下四个主要步骤:

步骤1:准备测试补丁(图1中的❶)。首先,我们收集由目标APR工具生成的补丁以形成测试集。对于该测试集中的每个补丁,我们向其附加一个文本提示。随后,我们使用LLM的分词器将“文本提示+补丁”组合转换为子词元。步骤2:从训练集中获取相似的补丁(图1中的❷)。对于测试集中的每个测试补丁,我们利用基于对比学习的检索模块从训练集中为每个测试补丁检索出与之语义相似度高的几个补丁。步骤3:获取其他指导信息(图1中的❷)。对于测试集中的每个测试补丁,我们提取测试补丁所针对的错误ID。然后,我们查询错误基准以获取关于该错误的相关信息,包括错误描述、执行跟踪、失败的测试用例和测试覆盖率等。步骤4:LLM推理(图1中的❸)。我们将具有所有指导信息的测试补丁输入LLM进行代码(Starcoder-7B)推断。LLM然后根据输入预测下一个令牌。然后将预测的下一个令牌映射为补丁正确性标签。

图1:LLM4PatchCorrect总体流程框架

2.1 测试补丁准备

建立训练/测试集。在图1的第❶部分中,当使用一种新的先进的自动程序修复(APR)工具来解决检测到的软件错误时,可能会生成许多候选补丁,这些补丁能够通过所有已知的测试用例来确认识别的错误。随后,开发人员必须确定哪个候选补丁是真正正确的并应该被实施。在这项研究中,我们的目标是利用现有APR工具中的已标记补丁,而不是要求开发人员手动标记由新的或未知的APR工具生成的补丁。为了实现这一目标,我们将现有APR工具中的已标记补丁指定为训练集,并将由新的或未知的APR工具生成的补丁指定为测试集。此外,我们将新的或未知的APR工具称为目标APR工具。

激活测试补丁。对于每个测试补丁,我们基于最近的自然语言处理(NLP)进展进行预处理,这可以帮助更好地将通用预训练模型适应特定的下游任务。提示的直觉是将下游任务转换为与预训练阶段类似的形式。对于预训练目标是根据先前的令牌预测下一个令牌的模型,例如GPT-3 [51]和Starcoder [38],提示旨在要求模型根据先前的令牌(补丁内容和演示)预测下一个令牌(即在此任务中是“正确”或“错误”)。为了帮助大型语言模型理解特定任务的信息,提示通过添加一段文本描述来修改输入数据,即提示模板。我们使用以下提示模板用于测试补丁:

{test-patch} 占位符将被测试修补程序内容替换。大型语言模型(LLM)在修补后接收测试修补程序作为输入,并预测下一个标记,指示修补程序是“正确”还是“错误”。这个过程也在图1的❶中呈现。

值得注意的是,如果生成的修补程序不仅通过了所有可用的测试用例,还修复了程序中的错误,那么这个生成的修补程序被视为“干净”(“正确”)。如果生成的修补程序只是通过了所有可用的测试用例,但在与预期程序规范相关的方面仍然不正确,即不适用于程序修复,那么这个生成的修补程序被认为是“过拟合”(“错误”)。由于“过拟合”(或“干净”)这个术语在APCA任务中有特定含义,指的是不正确(或正确)的修补程序,所以它在一般英文文本中的解释可能会有显著不同。为了避免给LLM带来混淆,我们在提示中选择了更为通用理解的术语,如“正确”和“错误”。

令牌化。为了对大型语言模型进行输入令牌化,我们使用它们对应的分词器。这些分词器通常基于字节对编码(BPE)构建,它输出一系列子词序列。BPE可以通过将不常见的长标记拆分为在预训练语料库中频繁出现的子词,从而减小词汇表的大小。此外,BPE被认为有助于缓解词汇外问题(OoV)。

2.2 从训练集中活得相似的补丁

从训练集中获取相似修补程序的过程如图2所示。它包括以下四个步骤:

步骤1:利用基于对比学习的修补程序嵌入模型将训练集和测试集中的修补程序转换为向量表示。步骤2:对于每个测试修补程序 x,我们在向量空间中通过计算余弦相似度来衡量距离,检索其在标记训练修补程序中前 k 个最相似的修补程序(即 x1、x2、...、xk)。步骤3:通过提示修改前 k 个最语义相似的修补程序,然后将它们连接起来形成上下文/演示。步骤4:连同其他引导信息,附加到测试修补程序 x 中,最终输入到大型语言模型中。

图2:从训练集中获得相似的补丁

2.3 获取其他指引信息

图3:获取其它指引信息的主要流程

获取额外引导信息的过程如图3所示。首先,当给定一个由新的APR工具生成的测试修补程序时,我们将检查测试修补程序的元数据,以确定新的APR工具正在解决的错误的ID。其次,我们将使用错误ID来收集以下引导信息:1)错误描述:详细描述修补程序意图解决的错误性质;2)执行跟踪:有关有缺陷程序执行的跟踪;3)失败的测试用例:暴露有缺陷程序中故障的测试用例;4)测试覆盖率:所有与错误相关的可用测试用例的行和条件覆盖度指标。 最后,我们将文本描述,如图1中的❷所示,包含到每个信息片段中。例如,对于错误描述,我们使用:

占位符 [] 被替换为从错误基准获得的错误描述。同样,我们利用图1中的❷的文本描述来表示错误描述、执行跟踪、失败的测试用例和测试覆盖率。

对于实现细节,我们依赖于像Defects4J这样的错误基准来从错误ID中获取引导信息。例如,在Defects4J基准中,一旦正确安装,用户可以使用以下简单的代码编译错误、进行测试,并计算测试覆盖率:

执行上述代码后,用户可以在Lang1文件夹中找到错误信息、执行跟踪、失败的测试用例以及测试覆盖率(行和条件)。因此,我们已经获取了测试修补程序的额外信息。

2.4 对补丁正确性的LLM推理

2.4.1 结合多样的导航信息

LLM4PatchCorrect利用了广泛的引导信息。在进行LLM推理之前,我们将每个信息片段连接在一起,然后附加上测试补丁。连接操作如下所示:

C = [S1; S2; ...; Bug; Trace; Case; Coverage; Test-Patch]

这里的“;”表示连接操作。Sj代表训练集中检索到的第j个相似补丁。请注意,每个信息片段都与相应的文本描述一起提示,如图1的❷所示。

2.4.2 上下文学习推理

上下文学习推理可以被视为文本生成问题,其中LLM被冻结。给定连接的最终输入C到LLM,上下文学习推理以最高概率输出下一个标记y作为未标记输入数据C的预测。我们在LLM4PatchCorrect中使用了最近提出的LLM,Starcoder-7B,这是一个开源的多语言LLM作为骨干模型。Starcoder有一系列不同模型大小的变体,最大的变体模型有155亿个参数。借助量化技术,通过使用低精度数据类型如8位整数(int8)来表示权重和激活以减少内存和计算成本,我们能够在12GB GPU(常用GPU卡2080-Ti的GPU内存)上使用任何不超过7B参数的LLM。这表明我们可以使用任何小于7B的LLM。

由于补丁正确性评估任务被制定为二进制分类任务,我们首先计算干净类(即PP_TM(“correct”|C, x))和过拟合类(即PP_TM(“wrong”|C, x))的概率,并归一化这两类的概率。然后,如果过拟合类的概率大于0.5,测试补丁被预测为“过拟合”。否则,被预测为“干净”。我们将由大型预训练模型生成的过拟合类的概率(归一化后)称为预测得分。请注意,如果生成的补丁不仅通过所有可用测试用例,还修复了程序中的错误,则生成的补丁被认为是“干净”(“正确”)。如果生成的补丁只通过了所有可用测试用例,但与预期程序规范仍不符合,则被认为是“过拟合”(“错误”),这对于程序修复是不合适的。因为“过拟合”(或“干净”)这个术语在APCA任务中有着独特的含义,指的是不正确(或正确)的补丁,所以在一般的英文文本中,它的解释可能会有显著差异。为了避免对LLMs造成困惑,我们在计算候选下一个标记的概率时,在文本和代码上下文中选择更为广泛理解的术语,如“正确”和“错误”。

3 实验

3.1 研究问题

在本文中,我们旨在回答以下研究问题:

RQ1:与交叉工具设置中的最新方法相比,LLM4PatchCorrect的表现如何?RQ2:LLM4PatchCorrect的每个组件是如何贡献的?

3.2 RQ1:方法的总体表现

主要结果。我们通过将LLM4PatchCorrect与最先进的APCA方法进行比较来评估其有效性。Tian等人采用了三种表示技术和三种机器学习分类器。在九种变体中,由于空间有限,我们只报告表现最好的组合。对于Cache,我们重用了Cache作者发布的实现。表1至表3展示了包括LLM4PatchCorrect和基线在内的所有方法在准确率、F1分数和AUC方面的有效性。实验结果显示,LLM4PatchCorrect优于所有基线技术。具体来说,LLM4PatchCorrect在准确率、F1分数和AUC方面平均显示了对Tian等人的工作的提升分别为20.9%、13.1%和33.3%。它还在准确率、F1分数和AUC方面平均分别对Cache显示了14.7%、6.8%和30.7%的提升。此外,LLM4PatchCorrect相对于强基线CodeBERT分别在准确率、F1分数和AUC方面取得了10.3%、6.1%和10.1%的显著提升。此外,我们采用准确率和F1分数的加权平均,其中权重为每个APR工具生成的补丁数量。LLM4PatchCorrect仍然优于所有基线。例如,LLM4PatchCorrect在加权平均准确率、F1分数和AUC方面分别比Cache提高了10.2%、4.7%和26.5%。LLM4PatchCorrect在加权平均准确率、F1分数和AUC方面分别比CodeBERT提高了9.2%、5.0%和6.1%。此外,我们进行了LLM4PatchCorrect和所有基线之间的Wilcoxon符号秩检验,以探究这些改进是否显著。结果显示,LLM4PatchCorrect在统计上显著优于所有基线(所有p值均小于0.05)。

表1:LLM4PatchCorrect和基线的精确度

表2:LLM4PatchCorrect和基线的F1分数

表3:LLM4PatchCorrect和基线的AUC分数

此外,我们观察到与其他APR工具相比,SOFix的准确率和F1分数相对较低。这主要是由于测试集中存在显著的不平衡,其中每1个过拟合补丁对应10个正确的补丁,导致标签比例为1:10。这种高度不平衡的测试集不仅对我们的方法构成挑战,也对所有方法构成挑战。

另外,值得注意的是,在执行ODS时,当目标APR工具为jKali(4个失败的测试补丁)、AVATAR(4个失败的测试补丁)、jMutRepair(1个失败的测试补丁)、HDRepair(1个失败的测试补丁)和Cardumen(1个失败的测试补丁)时,我们在执行推理时遇到了一些挑战。因此,在表1-3中呈现的ODS的性能指标仅基于成功测试的补丁进行计算。为了确保公平比较,我们还使用与ODS成功推断的相同的测试集评估LLM4PatchCorrect。由于当目标APR工具为jKali、AVATAR、jMutRepair、HDRepair和Cardumen时存在差异,我们仅在这些APR工具上重新评估LLM4PatchCorrect。表4显示了ODS和LLM4PatchCorrect在相同测试集上的性能。我们的方法始终且显著优于ODS。

表4:与ODS的性能比较

3.3 RQ2:消融实验

方法。为了明确LLM4PatchCorrect的每个组件的贡献,我们进行了消融研究。消融研究基于三组引导信息:

Bug信息:缺陷描述和执行跟踪;测试信息:失败的测试用例和测试覆盖率;已检索的补丁:从现有APR工具(训练集)中检索的补丁。

对于消融研究,我们最初仅使用LLM(Starcoder-7B)而没有任何引导信息。随后,我们将三组引导信息中的每个类别与LLM(Starcoder-7B)结合起来执行APCA任务。最后,我们整合所有引导信息(完整模型)来完成任务。

结果。我们最初研究了集成自缺陷基准的引导信息的影响。如表5所示,平均而言,利用与缺陷相关的信息,包括缺陷描述和执行跟踪,始终在所有指标上带来改进。这些改进相对于仅依赖于大型语言模型(例如Starcoder-7B)表现出最高可达9.6%的相对改进。此外,与测试用例相关的信息(即失败的测试用例和测试覆盖率)也始终相对于仅依赖于大型语言模型带来改进。

此外,我们研究了基于对比学习的补丁检索模块的贡献,该模块从训练集中检索补丁。如表5所示,平均而言,补丁检索模块相对于仅依赖于大型语言模型带来了11.4%、3.9%和84.7%的准确率、F1分数和AUC方面的相对改进。此外,我们发现,来自缺陷基准的引导信息和已检索的补丁相互补充,为LLM4PatchCorrect的完整模型带来了改进的结果。

表5:在所有APR工具的平均情况下,消融研究各组准确率、F1分数和AUC

转述:邹英龙

0 阅读:0

互联不一般哥

简介:感谢大家的关注