基本信息
这是24年4月发表在arxiv上的一篇文章
博客创建者
武松
作者
Junjielong Xu, Ying Fu, Shin Hwei Tan, Pinjia He
From:The Chinese University of Hong Kong, Shenzhen (CUHK-Shenzhen)
标签
大语言模型、程序自动修复、软件错误定位
1. 摘要
大型语言模型( large language models,LLMs )在自动程序修复( automatic program repair,APR )方面取得了不错的效果。然而,Decoder-only的LLMs (如 GPT-4 )的next token prediction训练目标与当前填充式方法(infilling-style)的掩码连续词预测(masked span prediction)目标不一致,这阻碍了LLMs充分利用预训练知识进行程序修复。此外,当使用相关artifacts(例如,测试用例)作为输入时,虽然一些LLMs能够端到端的定位和修复缺陷,但现有的方法将其视为单独的任务,需要先进行错误定位再用LLMs在定位位置生成补丁。这种限制阻碍了LLM的灵活性。
在本文中,本文研究了一种新的方法来使LLM适应APR。本文的核心见解是,LLM的APR能力可以通过简单地将输出与它们的训练目标对齐,并允许它们在不首先执行错误定位的情况下对整个程序进行优化(refinement)来大大提高性能。基于这一认识,本文设计了D4C,用于直接使用LLM进行APR。D4C可以正确修复Defects4J中的180个缺陷,每个补丁只需采样10次。该方法优于SOTA APR方法10%的完美错误定位,并减少了90%的补丁采样数量。文章主要贡献在于:
- 认为基于任务进行目标对齐对于充分挖掘LLM的预训练能力至关重要,于是将程序修复问题重定义为程序增强问题;
- 验证了直接优化整个代码比先定位后修复的方法效果更好;
- 提出D4C程序修复框架,将LLM直接用于APR,且效果比现有流程更好。
2. 方法
2.1 方法架构图
![](https://img-blog.csdnimg.cn/direct/df90c44e66f245bb8a43c339a0fca2ba.png)
![](https://img-blog.csdnimg.cn/direct/0f1e0986c2414f8cadbb47bb46e161b8.png)
![](https://img-blog.csdnimg.cn/direct/908c555089d74279879311d600d58aa9.png)
![](https://img-blog.csdnimg.cn/direct/86bcc4d80b6d46448a0afa8cb5333e98.png)
本文基于对以往方法的分析,有以下两点Insights,并基于这些Insighs做出了改进:
- 对齐Decoder-only LLMs的输出目标可以提高APR性能;
- 向LLMs的Prompt提供错误程序相关补充信息,并同时进行定位和修复,可以提高APR效果。
2.2 方法描述
文章主要出于两个考虑:一是作者认为使用Decoder-only LLM的方法,其输出目标和训练阶段目标不一致,会导致性能下降;二是现有的将LLM用于APR的方法,都将APR过程分阶段进行,即先定位后修复,在这个过程中LLM仅被用于对特定的位置生成修复代码。作者认为这种做法一方面受到前置的定位算法的影响(定位错误),另一方面是时间开销,对所有位置生成修复代码将花费大量时间成本(受限于LLM的推理速度);三是程序报错信息对LLM的推理有帮助。
作者构建这个框架,主要包含几个部分:one-shot提示语构建,利用文档信息和错误测试用例信息作为补充,程序并不经过微调,也无需关于错误位置的先验知识。
2.2.1 问题定义
将APR任务建模为一个代码补全(code completion)任务,该任务旨在基于bug程序和相关工件生成一个完整的精化程序。这与以往基于LLM的APR方法将APR任务视为填空任务(code infilling)不同。具体来说,D4C的优化目标可以形式化地写为:
![](https://img-blog.csdnimg.cn/direct/ef2c485f80a84a2b8807a54653ff9517.png)
而现有基于填空的方法为:
![](https://img-blog.csdnimg.cn/direct/9936f1ece6804b8ab9b19e2026bbb648.png)
D4C与以往方法在任务建模上存在差异的原因在于,D4C旨在利用CLM(Causal Language Modeling,因果语言模型)为目标训练的的Decoder-only LLM的预训练能力,而填充式APR旨在利用MLM(Masked Language Modeling,掩码语言模型)为目标训练的Encoder-only LLM或Encoder-Decoder LLM的预训练能力。
2.2.2 程序补充信息(Artifacts)处理和Prompt构建
过去研究表明,程序补充信息有助于LLM提高APR的性能。在本文中,作者使用以下几种信息作为补充参与Prompt构建:
- 描述代码的通用目的及其输入输出数据类型的程序文档或注释;
- 失败测试用例的输入和期望输出;
- 失败测试用例的错误信息,对应于buggy代码。
作者使用这些信息基于人类调试程序的过程:具体来说,在人为的程序修复过程中,我们首先需要直观地了解函数的目的,因此我们参考了相关的代码文档或者函数级别的注释。然后,我们想知道什么输入可以复现这个缺陷。因此,我们将检查相关的失败测试用例和错误信息。最后,在没有其他开发人员(即,在橡皮鸭调试的情况下)的沟通或确认的情况下,我们只能使用这些补充信息来同时定位和修复缺陷。因此作者使用这些补充信息构造缺陷报告(bug report),以促使LLM修复缺陷程序。
文章的Prompt模板如下:
![](https://img-blog.csdnimg.cn/direct/a939b465a90e4dfc9dc0451f70157c94.png)
2.2.3 程序补丁生成(Patch Generation)和结果验证
-
模型选择
选用闭源模型GPT-4以及开源模型Mixtral-MoE。 -
补丁生成
由于D4C只需要生成最多10个候选Patch(少于传统方法可能动辄数百个),因此没有引入对Patch进行排名的方法,因此在候选Patch正确性的验证上可以节省大量时间。作者提出也不应该用LLM生成结果的困惑度(Perplexity)来进行排名。然后对D4C生成的至多10个Patch,在源程序的测试环境进行测试,通过所有测试用例即认为是合理的(Plausible)Patches。最后,还需要人工进一步判断是否这些Plausible patches中的真正正确的patch。(因为在APR中可能出现在测试用例上过拟合的问题,即“面向测试用例编程”)
3. 实验
主要进行三个实验,baselines的对比实验、验证作者insights的实验以及消融实验。
3.1 数据集
- Defects4j:一个广泛使用的APR基准测试程序包含了来自17个开源仓库的835个真实缺陷;由于众多论文均使用Defects4j进行实验验证性能,因此对比实验基于Defects4j进行。
- DebugBench:一个新的用于对抗数据泄漏(数据集代码数据已经作为LLM的训练数据)的调试基准(通过GPT - 4在源数据中植入bug),它包含来自Java、C + +和来自Leet Code的Python3共4253个bug。DebugBench没有受到数据泄露的威胁,作者使用它对Insights进行验证。
3.2 指标
遵循以往的工作,作者使用正确补丁的数量来评估APR的有效性。具体来说,如果一个补丁可以通过所有的单元测试,那么它将被认为是一个合理的补丁(Plausible patch)。如果这个补丁真正解决了问题,而不是过拟合的情况(只通过了提示语中提供的失败测试),那么它将被确认为是一个正确的补丁。在作者的评估中,遵循先前的研究,人工确定一个合理的补丁是否真正地解决了缺陷。
3.3 实验结果及分析
3.3.1 对比实验
Baselines:AlphaRepair、Repilot、RAP-Gen、FitRepair、ChatRepair。
![](https://img-blog.csdnimg.cn/direct/d76fba40519d49b6b3a6c1d7ee13839e.png)
所有Baseline方法虽然都使用了LLM作为主要组件,且Encoder和Decoder型都有涉及,但都是infilling-based且多阶段修复的方法。作者没有将D4C与从头训练的基于深度学习的APR方法进行比较,目的是验证D4C在基于LLM的方法中的有效性。
由对比实验结果看到,本文所提出的D4C在错误程序修复数量上超过了以往的infilling-based LLM方法,验证了目标对齐和直接预测(不进行错误定位)的有效性。另一方面,采样数量也大幅降低,可以节省大量的采样时间。
3.3.2 Insights验证实验
![](https://img-blog.csdnimg.cn/direct/ea28a80080db466aa6ee87cfd9fd3615.png)
该实验通过重新构建prompt模板,验证作者的两个Insights的有效性,即目标对齐和计入程序补充信息且不分阶段修复。使用困惑度(Perplexity)作为指标衡量模型表现,较低的困惑值表明模型在预测给定序列时更有信心。具体来说,通过计算CLM目标函数的损失来度量困惑度。由于LLM是为了最小化CLM目标而训练的,因此测量困惑度是评估生成内容是否与训练语料分布一致的最直接的方法。
由第一行,其中Hunk表示infilling-based的方法,即没有进行目标对齐,Func表示让模型直接输出整个refined后的函数(即直接做生成,CLM),不需要定位和填空。可以看到后者的困惑度更低,验证了作者第一个Insight的正确性。
由第二行和第一行对比,Mask和Report表示是否加入错误程序的补充信息形成错误报告(Bug Report)。可以看到后者困惑度更低,因此也验证了第二个Insight的正确性。
3.3.3 消融实验
![](https://img-blog.csdnimg.cn/direct/1fd49cca66fc482880140b5d9ac916b9.png)
文章的消融实验主要验证加入错误程序补充信息的有效性,其中Mask表示不加入任何补充信息。可以看到,加入补充信息对效果的提升较为显著。另外,程序注释的作用不如失败测试样例和错误信息的作用大。
另一方面,还验证了参数敏感性,即Patch的采样次数和LLM输出的Temperature的参数变化对性能的影响。在采样次数为10和Temperature为1的时候,效果是最好的。
3.4 讨论
这部分主要讨论文章方法可能存在的一些威胁,外部威胁(External Threats)主要包括在修复效果的指标上,需要人工审查修复后的代码是否真正正确,人工的过程就有主观性,因此这个过程采用了第三者来解决两人审查结果的分歧。内部威胁(Internal Threats)主要包括Defects4j数据集潜在的数据泄露问题,但文献研究表明这种泄露问题在APR任务中并不严重,且在对比实验中的所有Baselines均基于该数据集进行,而Insights验证实验使用的数据集是没有泄露风险的最新的数据集DebugBench。
另外文章举了一个例子,表示生成的patch可能存在过拟合的问题:
![](https://img-blog.csdnimg.cn/direct/2f41f093a26142dcb97472b613fd5b8c.png)
另外还有一个案例说明本文方法的可靠性:
![](https://img-blog.csdnimg.cn/direct/af4ddc2bd7b245ccb48cc7d43e0b4d7c.png)
4. 总结
4.1 亮点
- 考虑了不同架构模型的预训练特点,针对所使用模型的预训练方式来设计对齐的输出方式;
- 怀疑了一般的APR流程:错误定位-》寻找Patches-》用Patch替换原出错程序块。
4.2 不足
- 创新性或欠缺,工作量主要集中在prompt工程上;
- 端到端地直接用LLM能力做修复,是否导致整个程序语义、结构或风格的改变以及其影响文中未讨论。
4.3 启发(下一步工作)
- 在使用预训练模型的过程中,可以考虑具体任务和所使用模型的训练策略是否一致(是否存在gap),从而选取更适合任务的模型;
- 在错误定位方面,也可以引入LLM。
5. 相关知识链接
- 论文链接
- BibTex
@misc{xu2024aligningllmsflfreeprogram,
title={Aligning LLMs for FL-free Program Repair},
author={Junjielong Xu and Ying Fu and Shin Hwei Tan and Pinjia He},
year={2024},
eprint={2404.08877},
archivePrefix={arXiv},
primaryClass={cs.SE},
url={https://arxiv.org/abs/2404.08877},
}