论文阅读-自动程序修复-Automated Program Repair in the Era of Large Pre-trained Language Models(2023)

本文研究了如何直接应用预训练语言模型进行自动程序修复,结果显示最新LLMs在修复复杂漏洞上超越传统方法,可用于补丁排名和检查。实验设计了多种修复设置,评估了不同模型在实际项目中的效果,指出结合模板信息和样本大小能提升性能。
摘要由CSDN通过智能技术生成

一 论文背景

        本文作者发现了“现有的传统和基于学习的APR技术面临着有限的修补程序种类的问题,无法修复复杂的漏洞。最近的研究人员直接利用大型预训练语言模型(LLMs)进行APR,而不依赖于任何漏洞修复数据集。然而现有的工作要么没有包括最先进的LLMs,要么没有在实际数据集上进行评估。

         所以本文作者的创新点:首次对直接应用LLMs进行自动程序修复进行了广泛研究。研究选择了9个最新的LLMs,包括生成和填充模型,范围从125M到20B不等。研究设计了3种不同的修复设置,评估了使用LLMs生成补丁的不同方式。(最先进的LLMs+在实际数据集上进行评估。)

        研究结果:

        ·直接应用最新的LLMs可以在所有数据集上显著优于所有现有的自动程序修复技术。

        ·LLMs还可以用于有效的补丁排名或补丁正确性检查。

        ·通过增加样本大小和结合修复模板信息,可以进一步大幅提高LLM-based APR的性能。

二 introdution

(一)研究现状

1.LLMs是以无监督的方式训练的,可以用于各种代码任务。最近,AlphaRepair提出了利用CodeBERT直接进行APR的方法,而不是学习从有错误的代码到修复代码的转换。AlphaRepair通过这种方法展示了最先进的修复结果,而无需在错误修复数据集上进行微调。

2.直接利用Codex进行生成式APR,即根据错误之前的上下文生成修复代码。然而,这些研究主要集中在Codex上,并且仅在一个包含40个简单编程任务错误的小数据集上进行评估。(之前读过这篇论文)

3.现有的LLM模型主要评估代码相关任务,如代码补全、文档生成和变量/类型预测,但评估仍主要集中在NLP指标上,不准确衡量生成代码的功能或语义正确性。

4.数据集由手工策划的代码问题组成,不准确反映开发人员在实际项目中的工作。

(二)本文主要贡献

1.对最近的LLMs进行了首次广泛评估,用于修复现实世界的项目。

2.设计了三种不同的APR实验设置:1)完整函数生成,2)正确代码填充和3)单行生成,展示了LLMs在APR中的不同应用方式。

3.包括了两种流行的LLM架构(生成模型和填充模型),以展示使用每种类型进行APR的优点和缺点。

(三)背景知识介绍

主要的语言模型有单向语言模型和双向语言模型:

1、单向语言模型即Transformer的Decoder模块。就是正向预测,即已知前面的文本信息预测下一个字。更适合生成任务,而现在主流的大模型例如ChatGPT、LLAMa所执行的所有任务均可以被归类为生成任务。这种模型通常用于诸如序列标注、命名实体识别和文本分类等任务。

2、双向语言模型就是可以利用上下文信息来预测。最主流的双向语言模型BERT,是最主流的掩码语言模型或自编码语言模型,主要基于Transformer的Encoder模块实现

自动程序修复(APR)

技术:

目前广泛使用的自动程序修复技术主要是基于专家手工指定的模板和基于学习方式的程序修复。
1)基于模板修复方式:比较依赖于专家手工制定的模板,而模板获取通常较难,且难以准确的设计:
2)基于学习的方式则需要依赖于大量的标注数据集,标注数据集的获取成本很高,也会对效果带来一定的影响。

发展:

1、传统基于专家手工指定模板和规则
2、借鉴NMT方法,基于可学习的神经网络,训练修复模型,如Seq2Seq、Transformer等
3、基于预训练大模型,做有监督微调或者不训练模型直接做zero-shot、few-shot等任务,如代码专项模型:starcoder、codex、codeBert等

三 实验方法

作者设计了三种不同的APR设置

3.1生成整个修复函数:将有bug的函数直接输入给模型,然后模型输出修复后的数据。

Fig. 1: APR input for complete function generation

        天真地向llm提供有bug的函数是行不通的,因为每个LLM都没有针对APR进行预训练(即,它们不知道目标是生成一个补丁函数)。因此,为了便于直接使用llm进行APR,我们使用了特定的提示,使模型能够进行few-shot学习。这允许llm通过完成提供的输入来识别任务并生成补丁函数。我们在这里注意到,完成函数生成的任务没有假设1)错误的位置和2)所需的错误或修复的类型。因此,LLM需要弄清楚函数为什么bug,并提供补丁来修复bug

        图1显示了由两个错误修复示例组成的输入(一个由我们制作(为模型提供额外的上下文),另一个来自相同的目标错误来自的项目/数据集,为模型提供项目中使用的编码风格的一些示例)和一个我们想要修复的bug.

3.2 正确的代码填充:函数内的错误位置是已知的的。目标是在给定有bug函数的前缀和后缀的情况下生成正确的替换代码。参考掩码语言模型思路:将错误代码行视为mask(在前缀和后缀之间放置的一个填充令牌)然后使用掩码语言模型对mask位置进行预测,得到正确代码输出,掩码语言模型可以利用双向的上下文信息。

3.3 单行代码生成;提供了bug的位置,bug只需要修改一行。基于生成式的模型去生成单行,生成单行后就停止生成,然后拼接上后缀代码。

        作者这里应该是尝试了两种方法:

法一:如图3a所示,使用上下文去预测掩码位置的输出

法二:如图3b所示,基于生成式的模型去生成单行,生成单行后就停止生成,然后拼接上后缀代码

3.4 计算每一个补丁的熵值

在3.1-3.4部分介绍了3种生成补丁的方法,紧接着在3.4中记录每个补丁的熵值。熵捕捉了模型生成的样本的自然程度,可以通过计算每个生成的标记的负对数概率来计算。熵值越低,生成的样本越自然。

四 实验评价

RQ1:不同法学硕士的比较:

1.从正确补丁的修复效果方面评价

发现1:当我们在所有修复数据集上使用更大的模型时,性能不断提高

注:图V采用的是第三类:单行APR

发现2:表5中的单行生成结果,我们包括生成模型和填充模型。我们观察到填充模型比生成模型表现得更好。此外,由于我们能够同时使用法典的生成和填充版本,因此我们可以直接比较仅给定前缀与同时给定前缀和后缀上下文时模型的修复能力。

这种现象可能产生的原因是:对于生成模型,我们无法为其提供后缀代码片段,因为它们的生成仅依赖于先前的上下文。有后缀信息正确率会更高。

注:图3和4分别是完整的函数生成APR和正确填充 

发现3:结合上面的图345可以得出结论:与完整的函数生成相比,我们观察到,使用正确的代码填充和单行生成的每个模型都能够产生更高的正确修复与bug总数的比例。

这种现象可能的原因是:使用代码填充和单行生成产生的补丁更有可能是正确的修复。性能的提高是因为对于完整的函数生成(三种方法中只有它的bug位置是未知的),模型需要理解给出的提示(III-B1),定位bug并提供正确的修复。另一方面,当我们在正确的代码填充和单行生成中为模型提供有bug的位置信息时,它只需要填充或完成部分代码,从而产生更多正确的补丁。

2.从正确补丁的修复速度方面评价

图六中,纵轴是不同的模型,横轴:Defects4J 1.2 是一个常用的用于评估自动程序修复工具的数据集,其中包含了78个软件缺陷。而 QuixBugs-Python 是一个基于 Quixey 挑战创建的多语言程序修复基准集,其中包含了40个 Python 编写的软件缺陷。在论文中,这些数据集被用来评估大型预训练语言模型在程序修复任务中的表现。使用3种修复生成设置(CFCISL分别指完整功能、正确填充和单行生成)

发现4:我们增加模型大小时,补丁生成速度急剧减慢。这证明了在使用大型模型时,修复效率和时间成本之间的权衡

发现5:与单行生成和正确的代码填充相比,完整的函数生成需要明显更多的时间,因为生成整个函数比生成单行或块要花费更多的时间。这表明了首先使用传统故障定位技术[46]来精确定位错误位置然后利用llm来更有针对性地生成补丁仍然更具成本效益。对于用LLM来自动修复代码的应用来说,预先定位可以大大提高效率!

3.从每个LLM生成补丁的编译率来评价

发现6:随着我们增加模型的大小,生成的补丁的总体错误率(语法+语义)下降。

发现7:使用单行生成的生成模型都产生了大量的语法错误。回想一下,使用生成模型时的单行生成只提供了有bug的函数中的前缀。因此,生成的行很容易引入一些语法错误(例如,添加一个带有左括号的if语句),因为模型不知道后缀代码上下文是什么。 

        在另外两种设置中产生的语法错误数量要低得多。对于完整的函数生成,llm可以在训练过程中有效地保留语言的语法,并生成语法正确的函数。对于正确代码填充我们不仅可以获得低语法错误可以实现最低语义错误。同时拥有前缀和后缀为模型提供了足够的上下文,从而导致更高的可编译补丁率。(目前我们可以看出的是:如果要兼顾速度和正确率,采用填充是最好的方法。)

RQ2:与最先进的APR工具的比较

将直接使用 LLM 进行修复的结果与 Defects4J 1.2 上的传统(1)基于学习的(2) APR 工具进行比较 。

RQ3: Patch Ranking and Correctness Checking Analysis(一个非常有趣的方面

发现8:我们使用 LLM 来生成补丁,因此我们可以计算每个补丁的熵。熵计算生成的样本的自然程度(公式 1)。表 IX 显示了正确 (C)、合理 (P) 和不合理 (NP) 斑块的平均熵值。首次证明,通过 LLM 进行熵计算可以帮助区分正确的补丁和合理的补丁,这表明直接利用 LLM 熵度量进行补丁正确性检查的前景光明。

发现9:补丁排名:我们选择了 5 个正确补丁数量最多的法学硕士来执行此分析。图 7 显示了随着我们增加要验证的补丁数量,使用不同补丁排名策略修复的 Defects4J 1.2 数据集的错误数量。我们看到,与随机挑选补丁进行验证(蓝线)相比,当使用熵排名(橙色和绿线),我们可以更快地验证正确的补丁。这表明熵可以是一种有效的度量,用于对潜在补丁进行排序,以优先考虑较低熵补丁,以便在更严格的时间限制下进行验证。此外,我们观察到与平均熵相比,总熵的表现稍好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值