阅读笔记 Resolving Crash Bugs via Large Language Models: An Empirical Study
Resolving Crash Bugs via Large Language Models: An Empirical Study
用大预言模型来给出具体的解法,本文使用一步步给出引导来使大模型更好用(提示引导,提示模板)
摘要
崩溃错误会导致程序出现意外行为甚至终止,需要优先解决。然而,崩溃错误往往与复杂的根源有关,包括源代码中的问题和外部环境因素(如第三方库依赖性)。因此,手动解决崩溃错误既具有挑战性又耗费人力,研究人员提出了各种自动定位和修复崩溃错误的技术。
ChatGPT 是最近出现的一种大型语言模型(LLM),因其在不同领域的卓越性能而备受关注。本研究首次对 ChatGPT 解决现实世界崩溃错误的能力进行了调查,重点关注其在定位和修复代码相关和环境相关崩溃错误方面的有效性。具体来说,我们初步评估了 ChatGPT 在一次迭代中通过基本提示解决崩溃错误的基本能力。我们发现,与环境相关的崩溃错误相比,ChatGPT 在解决代码相关的崩溃错误方面表现更佳,而其主要挑战在于定位不准确。此外,我们还探索了 ChatGPT 在各种高级提示方面的潜力。采用角色扮演提示可有效提高解决能力,而持续互动则有助于 ChatGPT 获取相关知识,从而提高整体效率。此外,通过激发 ChatGPT 的自我规划能力,它可以有条不紊地通过主动询问调查每个可能导致碰撞的环境因素,最终找出碰撞的根本原因。基于我们的研究结果,我们提出了 IntDiagSolver,这是一种交互方法,旨在通过与 ChatGPT 等 LLM 的持续交互,促进崩溃错误的精确解决。在多个 LLM 上对 IntDiagSolver 进行评估后发现,包括 ChatGPT、Claude 和 CodeLlama 在内的多个 LLM 在崩溃错误解决的准确性上都得到了一致的提高。
引言
崩溃错误通常被认为是关键问题,因为它们可能会导致程序意外终止并干扰用户的正常操作 [1],[2]。解决崩溃错误耗时耗力,因为崩溃错误通常有多种原因,包括代码问题(如源代码中的错误)和环境问题(如不适当的操作系统版本、硬件配置或第三方库依赖关系)[3]。其中,对于由代码错误引起的崩溃错误(即与代码相关的崩溃错误),已有很多人致力于对其进行自动定位[4]、[5]、[6]和修复[7]、[8]、[9];而对于由环境问题引起的崩溃错误(即与环境相关的崩溃错误),由于潜在原因的空间很大,现有技术主要依赖于采用 Stack Overflow(SO)等在线问答论坛的类似解决方案[3]、[10]、[11]。
ChatGPT [12] 是 OpenAI 最近开发的一种大型语言模型 (LLM),它在数学 [13], [14], 教育 [15], [16] 和自然语言处理 [17], [18] 等多个领域都表现出卓越的能力。特别是,由于在文本和代码语料库中进行了预训练,ChatGPT 在软件工程任务(如软件理解 [19]、[20] 和代码生成 [21]、[22]、[23] 等)中也显示出了良好的效果。因此,已经出现了一些研究 ChatGPT 修复错误能力的初步工作。例如,Dominik 等人[24] 比较了 ChatGPT 和现有的基于学习的技术在修复代码相关错误方面的能力;Xia 等人[9] 结合了 ChatGPT 的对话能力,利用 ChatGPT 多轮修复代码相关错误。尽管这些研究显示了 ChatGPT 在修复错误方面的巨大潜力,但他们的评估仍然集中在一个相当简单的场景上。首先,这两项研究都只考虑了与代码相关的崩溃错误(例如,主要是简单算法的程序错误)、首先,它们都只考虑了与代码相关的崩溃错误(例如,QuixBugs [25]中玩具程序中的简单算法错误),因此不清楚 ChatGPT 在解决真实世界软件中与环境相关的崩溃错误时表现如何;其次,它们要么向 ChatGPT 提供了真实的错误位置,要么只提供了一小部分可能存在错误的代码,因此没有充分发掘 ChatGPT 对崩溃错误的故障定位能力;第三,它们主要通过固定的小范围提示与 ChatGPT 进行交互,尚未探索不同交互策略下的不同提示如何影响 ChatGPT 解决崩溃错误的能力。
为了填补这些知识空白,我们首先进行了一项综合研究,通过探索 ChatGPT 在定位和修复与代码相关和与环境相关的崩溃错误方面的有效性,并使用一系列不同的提示来研究 ChatGPT 解决现实世界中崩溃错误的能力。特别是,我们探索了 ChatGPT 在以下情况下解决崩溃错误的能力:(i) 单轮交互中仅包含简单指令的基本提示;(ii) 包含不同提示模板和多轮提示的高级提示。我们分别回答了以下两个研究问题。
- 问题 1(基本提示):ChatGPT 使用基本提示定位和修复代码相关和环境相关崩溃错误的效果如何?
- 问题 2(高级提示):高级提示如何提高 ChatGPT 解决崩溃错误的能力?
- 问题 2.a(提示模板):不同的提示模板如何影响 ChatGPT 解决崩溃错误的能力?
- 问题 2.b(多轮提示):多轮提示如何影响 ChatGPT 解决崩溃错误的能力?
根据我们对 100 个实际崩溃错误(即 50 个与代码相关的崩溃错误和 50 个与环境相关的崩溃错误)的研究结果,我们有以下主要发现。首先,我们发现 ChatGPT 在解决与代码相关的崩溃错误方面比解决与环境相关的崩溃错误更熟练;其次,我们发现故障定位而非修复是 ChatGPT 解决崩溃错误的瓶颈。第三,我们发现与 ChatGPT 的持续互动有助于获取相关知识,从而提高其解决效率。此外,我们发现角色扮演的提示也很关键,因为它们不仅能提高解决结果,还能激发 ChatGPT 的主动提问能力,从而进行自我规划。这使得 ChatGPT 能够通过逐步本地化有效地指导解决过程。
根据我们的研究结果,我们进一步提出了一种 IntDiagSolver 方法,用于指导与 LLM 的交互,从而更准确地解决崩溃错误。我们针对与代码相关和与环境相关的崩溃错误,分别提出了不同的提示模板,强调崩溃上下文的不同组成部分,并提出了不同的多轮交互策略。此外,我们还设计了一种策略,使 LLM 能够指导修复过程,这对于崩溃错误知识有限的初学者来说是有益的。然后,我们通过回答以下研究问题,在一个包含 41 个崩溃错误的小型数据集上对我们提出的方法进行了评估。
- 问题 3(IntDiagSolver 的评估):IntDiagSolver 在解决崩溃错误方面表现如何?
- 问题 3.a(IntDiagSolver 的有效性):IntDiagSolver 能在多大程度上有效解决崩溃错误?
- 问题 3.b(IntDiagSolver 的通用性):IntDiagSolver 在解决崩溃错误方面的有效性在多大程度上可以在不同的 LLM 中推广?
结果表明,IntDiagSolver 持续提高了解决四个最新 LLM 的代码相关和环境相关崩溃错误的准确性,在定位方面有 13.5% 到 133.0% 的大幅提高,在修复方面有 17.1% 到 258.8% 的大幅提高。值得注意的是,在 ChatGPT 上,成功修复的环境相关崩溃错误数量从 0/30 提高到 16/30,令人印象深刻。这些发现为今后的工作提供了宝贵的见解和实用指南。
贡献总结
- 第一项实证研究广泛考察了 ChatGPT 在定位和修复崩溃错误方面的能力,包括与代码相关和未探索的环境相关的错误。
- 大量发现和见解揭示了基于 ChatGPT 的崩溃错误解决方法的局限性、优势以及各种提示设计的影响。
- 第一种方法 IntDiagSolver 可以指导与 LLM 的交互,从而更有效地解决崩溃错误。
实验设置
Benchmark
以前的研究[9]、[26]、[27] 通常使用 QuixBugs[28] 作为基准数据集,调查 LLM 在解决错误方面的潜力。然而,该数据集有其局限性:(i) 它只针对源代码错误引起的崩溃错误,而忽略了环境问题引起的错误,而环境问题普遍存在,有时对开发人员来说更具挑战性[29], [30];(ii) 该数据集只包含 40 个相对简单场景下的错误,如基本算法程序,无法捕捉现实世界中崩溃错误的复杂性。虽然存在其他错误修复数据集,如 Defects4j [31]、ManySStuBs4J [32] 和 UnifiedBugDataset [33],但它们都侧重于与代码相关的错误。
为了全面评估 ChatGPT 在解决崩溃错误方面的有效性,我们将分析范围扩展到了代码相关问题和环境相关问题。利用 SO 线程,我们创建了一个包含各种真实世界崩溃错误的基准,充分利用了 SO 与真实世界崩溃错误的一致性及其关于错误代码的目的和依赖性的丰富上下文信息。
建立数据池。根据先前的研究[2]、[3],我们重点关注 Java 程序中普遍存在的崩溃错误[10]。为了构建我们的基准,我们根据以下纳入标准从 SO 数据转储[34]中选择高质量线程:(1) 线程标题或标签中包含关键字 “Java”;(2) 线程标题或标签中包含关键字 “异常 “或 “错误”;(3) 线程中包含已接受的答案;(4) 线程中至少有一个问题获得了赞成票;(5) 线程中包含具体的错误症状(即代码或堆栈跟踪),以确保有足够的上下文来理解崩溃错误;(6) 线程中至少包含一种常见的 Java 异常类型(如 NullPointerException)。此外,为了收集标准-6 的常见 Java 异常类型的完整列表,我们根据Libraries.io 数据集 [36] 和 JDK 1.8 [37],从 Maven Central [35] 系统解析了 35,773 个 Java 库。此外,考虑到大多数 LLM 只支持有限长度的文本输入,我们进一步加入了两个排除标准。(7) 鉴于 ChatGPT 使用的输入长度有限(即 1,000 个 token),因此过滤掉问题过长的线程。(8) 过滤掉有图片内容的线程。这样,我们收集了 67,248 个与崩溃错误相关的 SO 线程作为线程池。
高质量的样本选择。为了确保基准的代表性,同时最大限度地减少人力,我们从中随机抽取了 100 个线程。两位作者使用预定义的标准对每个线程进行独立评估。只有被两位评估者一致评为高质量的线程才被纳入最终基准,线程中被接受的答案被视为相应崩溃错误的基本真实解决方案。需要注意的是,如果线程只提供了模糊的答案(如故障排除提示或一般修复方向)而没有详细的解决方案,则视为低质量线程。考虑到我们的研究既包括与代码相关的崩溃错误,也包括与环境相关的崩溃错误,我们继续进行抽样和评估,直到每种类型都有 50 个合格的 SO 线程,即总共有 100 个崩溃错误。
LLM配置
在我们的研究中,我们主要利用 ChatGPT 进行第一部分实验(RQ1 和 RQ2)。我们选择了 gpt-3.5-turbo 模型。与 GPT-4 相比,这种选择是由于其更快的响应和成本效益所驱动的。
RQ1:基础提示
在本研究问题中,我们研究了 ChatGPT 在定位和修复代码相关和环境相关崩溃错误方面的能力,并对我们构建的基准进行了基本提示。
A:解决代码相关的错误
基本概念:与代码相关的崩溃源于程序代码实现过程中的错误,与环境无关。描述通常由三部分组成:错误代码、崩溃信息和崩溃上下文(代码意图or程序使用的环境)。
- 错误代码(B 代码):这种代码片段会引发崩溃,通常包含语法或语义错误,导致意外的程序行为。
- 崩溃信息 (Cra-Info) :该部分包括异常类型、错误信息和崩溃跟踪。异常类型表示错误的性质,如除以零。错误信息提供了可读的错误描述。崩溃跟踪提供崩溃时程序执行的堆栈跟踪,有助于定位错误。
- 崩溃背景 (Cra-Cont) :这一部分描述了更广泛的崩溃背景,包括症状、潜在原因、相关输入、错误代码的目的、配置或可能导致错误的依赖关系。这些细节对于复制崩溃和掌握其根本原因至关重要。
这三个部分为崩溃错误提供了不同程度的细节,并有特定的进展。错误代码提供了导致崩溃的代码段,这对确定错误的根本原因至关重要。崩溃信息有助于确定错误的位置和原因。崩溃上下文提供了错误的自然语言描述,为理解错误行为和潜在原因提供了更高层次的视角。
设计:我们评估了 ChatGPT 在基准测试中定位和修复 50 个代码相关崩溃错误的能力。提示设计。我们设计了一系列与 ChatGPT 交互的提示模板(Basic-Prompt1 至 Basic-Prompt-4),涵盖了不同层次的信息粒度。
- 基本提示-1:这是我的代码:[B-CODE]我遇到了异常,我该如何解决?
- 基本提示-2:这是我的代码:[B-CODE] 我收到 [CRA-INFO],我该如何解决?
- 基本提示-3: [CRA-CONT] 这是我的代码:[BCODE] 我收到 [CRA-INFO],如何解决?
- 基本提示-4: [CRA-DES(崩溃描述)] 这是我的错误行:[LOC] 如何解决?
交互程序。对于基准测试中每个与代码相关的崩溃错误,我们将其描述分为三个部分,并使用特定的提示让 ChatGPT 参与,逐步提供信息。
- 我们使用的是基本提示-1,其中只包含错误代码。
- 如果不能准确修复,我们就尝试使用 Basic-Prompt-2 ,其中包含额外的崩溃信息。
- 如果错误仍未解决,我们就使用提供崩溃上下文的 BasicPrompt-3。
- 如果崩溃错误仍未得到正确解决,我们就使用 Basic-Prompt-4 来精确定位错误代码行 (LOC),即需要修改的实际代码行。这简化了 ChatGPT 的任务,使其只专注于修复崩溃错误,而无需定位,从而让我们能够探索模型的修复能力。
我们记录并分析了 ChatGPT 对每个提示的反应,将其与相应的地面实况解决方案进行了比较,并评估了定位和修复的正确性(见第 III-A3 节)。判断由两位作者独立完成。如果判断不同,则由第三位作者进行补充判断。最终注释结果根据多数原则确定。结果,定位和修复的卡帕系数[39]分别为 0.89 和 0.92,几乎完全一致。
可靠性保证。为确保实验的可靠性,我们采取了多项预防措施。首先,我们为每次互动都启动了一个新的 ChatGPT 会话,以避免先前对话可能造成的偏差。此外,我们在使用不同机器的多个账户上进行了实验,以尽量减少环境变量的影响。此外,考虑到 ChatGPT 的非确定性,我们在实验中让两个独立的评估者同时与 ChatGPT 互动,以获取每个提示的回复。随后,我们评估了两位评估者的回答,并比较了他们关于定位和修复正确性的结论。在意见不一致的情况下,我们会使用相同的提示进行第三次评估,以确定回复的准确性,评估过程采用少数服从多数的决策方式。值得注意的是,只有一小部分查询(6%,50 项中的 3 项)需要进行第三次评估才能达成共识。
衡量标准:对于每个提示,我们都对 ChatGPT 的响应进行了人工检查,并分别进行了定性分析,以评估其本地化和修复能力。在本地化评估中,如果 ChatGPT 确定要修改的代码行与基准中确定的故障代码行相匹配,则认为 ChatGPT 的响应是正确的。在修复评估中,要求 ChatGPT 提供与基准匹配的准确代码补丁才算正确。为了提高定位精度的清晰度,我们还记录了 ChatGPT 为每个崩溃错误提供的解决方案的数量,并将正确率计算为所提供解决方案的正确率与总解决方案的比率。此外,我们还记录了每个崩溃错误的代码长度,以检查其对 ChatGPT 定位和修复能力的影响。
结果我们收集了 ChatGPT 对不同提示的回复,并对回复内容进行了人工分析。对于与代码相关的崩溃错误,ChatGPT 的回复可能包括几个方面,如确认代码功能、解释错误信息、确定潜在原因、提供文本修复、展示修复后的代码、讨论替代方案以及提供警告。但是,并非所有的回复都会涉及每个方面,而且也不一定会探讨其他原因和解决方案。
表 I 展示了 ChatGPT 解决代码相关崩溃错误的能力的实验结果。通过多方面的分析,我们得出了以下主要结论:
整体解决能力。表 I 中的实验结果表明,ChatGPT 在修复与代码相关的崩溃错误方面具有很大的潜力。具体来说,当提供完整的崩溃描述信息时,ChatGPT 能够正确定位 50 个崩溃错误中的 42 个(84.0%),并修复了其中的 38 个(76.0%)。此外,ChatGPT 还为大多数已修复的崩溃错误提供了唯一且明确的答案,只有 7.9%(38 个已修复崩溃错误中的 3 个)的崩溃错误提供了多种可能的解决方案。
发现 1:ChatGPT 在解决与代码相关的崩溃错误方面表现出色,在错误定位和修复方面都很熟练。
上下文信息影响。首先,ChatGPT 能够仅使用错误代码中的信息来解决与代码相关的错误。在表 I 中,当只给出带有 Basic-Prompt-1 的错误代码时,ChatGPT 能够正确定位和修复 40% 的崩溃错误(50 个错误中的 20 个)。这表明,错误代码对于 ChatGPT 解决与代码相关的错误至关重要。
此外,表 I 显示,提供更有效的崩溃描述信息大大提高了 ChatGPT 定位和修复崩溃错误的能力。值得注意的是,定位和修复崩溃错误的数量同时增加,这表明有效的崩溃描述有助于 ChatGPT 提高错误定位的准确性。
ChatGPT 的响应和对两个具体案例的分析突出了异常类型和错误信息在崩溃定位中的关键作用:崩溃错误 68199510 [40] 和 65084069 [41](崩溃错误的 SO 线程 ID)。在这两个案例中,ChatGPT 都提供了特定环境的解决方案,导致错误解决。这是因为异常类型 NoClassDefFoundError 和 NoSuchMethodError 通常与环境问题相关。
此外,在与代码相关的崩溃错误中,完整的堆栈跟踪相对不那么重要。在崩溃错误 22928450[42]的案例中,当只提供错误代码、崩溃上下文和异常类型时,ChatGPT 生成了正确的修复方案。然而,用缺乏异常类型的堆栈跟踪来代替异常类型信息,导致 ChatGPT 无法准确定位该崩溃错误。因此,为了提高修复效果,在提供崩溃描述信息时应使用自然语言明确强调异常类型信息。
崩溃上下文也能提高 ChatGPT 的本地化能力,其中包括程序的目的、崩溃发生时的症状(如调用了哪个函数,或哪个应用程序段未能产生正确的输出)、程序正常运行时的症状,以及用户自己的测试信息和修复问题的无效尝试。
发现 2:提供更有效的崩溃描述信息可显著提高 ChatGPT 定位代码相关错误的能力。异常类型和错误信息对于精确定位至关重要,而自然语言描述中的附加上下文则能进一步提高其性能。
本地化与修复。在有完整描述的查询中,只有 7.1%(42 个中的 3 个)可以正确定位,但无法准确修复。此外,在向 ChatGPT 提供真正的错误代码行后,7 个最初无法定位的崩溃错误中有 4 个被成功修复。这些结果表明,ChatGPT 的解决瓶颈主要在于定位。如果它能准确定位崩溃错误,就能成功修复绝大多数崩溃错误。从表一所示的结果来看,只有 8.0%(50 个中的 4 个)的崩溃错误在能够定位故障线的情况下仍无法修复。
发现 3:解决与代码相关的崩溃错误的主要瓶颈在于定位而非修复。
代码长度的影响。如表 I 所示,在具有复杂错误代码(超过 50 行)的崩溃错误中,13 个错误中只有 2 个(15.3%)可以仅凭错误代码正确定位。然而,如果包含崩溃信息和崩溃上下文,则可分别成功定位另外 4 个崩溃错误。在需要使用 Basic-Prompt-4 对错误行进行本地化和修复的 4 个崩溃错误中,有 3 个包含超过 50 行的代码。
发现 4:较长的代码会导致较差的定位能力,因此需要额外的崩溃描述信息来实现有效的定位。
B. 解决环境相关的代码问题
1) 设计:图 1(b) 显示了基准测试中与环境相关的崩溃错误示例。与我们针对代码相关崩溃错误的设置类似(见第 III-A2 节),我们也研究了 ChatGPT 在不同粒度下处理环境相关崩溃错误的能力。但是,由于并非每个环境崩溃描述都包含代码片段,而且环境相关崩溃错误的根本原因与代码实现本身无关,因此我们仅根据自然语言描述和非自然语言信息(即代码片段和崩溃信息)来区分环境崩溃。对于每个与环境相关的崩溃错误,我们最初只提供非自然语言信息,并使用 Basic-Prompt-2 评估 ChatGPT 的性能。如果无法实现准确修复,我们将提供完整信息,以便使用 Basic-Prompt-3 进行后续尝试。
2) 指标:我们通过人工评估来评价 ChatGPT 对每个崩溃错误进行本地化和修复的能力。在本地化评估中,如果 ChatGPT 找到了导致异常的正确原因(如库版本问题或依赖关系缺失问题),我们就认为 ChatGPT 的定位是正确的。在修复评估中,我们要求制定具体的修复计划(例如,升级或降级到特定的库版本)。此外,还将记录在提供多种解决方案的情况下正确定位的崩溃错误数量,以及 ChatGPT 答案的精确度。评估所采用的仲裁方法与代码相关崩溃错误的实验设置一致,环境相关崩溃错误的定位和修复卡帕系数均为 0.97,表明两者几乎完全一致。
3) 结果:与代码相关的崩溃错误相比,ChatGPT 在解决与环境相关的崩溃错误方面的能力有所下降,具体表现为定位和修复准确率较低,提供的候选解决方案较多,这表明 ChatGPT 在错误定位方面存在固有的不确定性。
根据表 I 所列的结果和我们对具体实例的详细分析,我们可以从不同方面得出几个结论(结论 5-8)。
整体解决能力。表 I 显示,ChatGPT 可以成功识别 42 个与代码相关的崩溃错误和 32 个与环境相关的崩溃错误,并提供了完整的崩溃描述。此外,在准确定位的回复中,32 个回复中有 21 个(65.6%)无法提供单一明确的解决方案。在某些情况下(如崩溃错误 28097042 [43] 和 24305296 [44]),ChatGPT 对同一崩溃错误给出了五个或更多可能的解决方案,导致命中率较低。与代码相关的崩溃错误不同,完整的堆栈跟踪对于环境相关的崩溃错误诊断更为重要,因为它包含了大量与环境相关的信息。
发现 5:与代码相关的崩溃错误相比,ChatGPT 在解决与环境相关的崩溃错误方面表现出较低的熟练度,这是因为它无法精确定位根本原因,从而产生了多种不精确的候选解决方案。
定位与修复。与解决代码相关崩溃错误时的观察结果不同,有 10 个具有完整崩溃描述的实例被成功定位,但仍未修复(解决代码相关崩溃错误时只有 3 个实例)。这是由于 ChatGPT 在提供多种解决方案时,倾向于只识别与环境相关的崩溃错误的潜在根源(如权限、版本或 IP 地址问题),而不是在解决方案中提供具体的修复步骤。因此,如何引导 ChatGPT 提供明确的修复策略是一个有待进一步探索的难题。
发现 6:ChatGPT 在提供与环境相关的崩溃错误解决方案方面缺乏针对性。
上下文信息的影响。表 I 显示,提供错误代码和崩溃信息可成功识别出 60%(50 个中的 30 个)与代码相关的崩溃错误。增加崩溃背景信息只能成功定位 12 个错误。通过错误代码和崩溃信息处理与环境相关的崩溃错误,只能识别出 14%(50 个中的 7 个)此类错误,其中只有 10%(50 个中的 5 个)能成功修复。然而,加入崩溃上下文后,本地化的成功率大幅提高到 64%(50 个中的 32 个),修复环境相关崩溃错误的成功率提高到 40%(50 个中的 20 个)。与代码相关的崩溃错误相比,这凸显了崩溃上下文对环境相关崩溃错误修复的重要性。然而,利用 ChatGPT 解决与环境相关的崩溃错误具有挑战性,因为崩溃上下文的主观性及其对自然语言的依赖性,从而对提问者的熟练程度提出了更高的要求。
发现 7:与代码相关的崩溃错误不同,环境相关崩溃错误的修复在很大程度上依赖于崩溃上下文。
我们还发现,当崩溃描述中不包含相关环境信息时,ChatGPT 无法推理和定位错误原因。例如,在崩溃错误 49871007 [45] 的案例中,异常描述和堆栈跟踪只提到了 Resteasy 3.1.4.Final。然而,需要修改的实际库版本是 javax.ws.rs-api,而 Resteasy 3.1.4.Final 是 JAX-RS-API 2.1 规范的实现。在这种情况下,ChatGPT 无法有效地推理和定位原因。
发现 8:当崩溃描述中不包含相关环境信息时,ChatGPT 无法推理和定位崩溃错误的原因。
考虑到版本问题在与环境相关的崩溃错误中的高频率和影响(在我们的基准中占 50 个中的 19 个),我们对这些问题进行了专门分析。我们注意到,ChatGPT 通常会建议升级到最新版本,以修复与库版本相关的崩溃错误,例如错误 24305296 [44]。但是,对于升级或降级到特定版本的库才是解决办法的情况(例如,错误 43320334 [46] 和 37771758 [47]),ChatGPT 无法提供正确的版本号。
发现 9:ChatGPT 通常建议升级到最新版本,以解决与库版本相关的问题。
高级提示
在本节中,我们将深入探讨高级提示,以此提高 ChatGPT 处理崩溃错误的能力。值得注意的是,我们在此主要关注与环境相关的崩溃错误。强调与环境相关的崩溃错误源于 RQ1 中的发现,该发现已经证明 ChatGPT 在解决与代码相关的崩溃错误方面表现出色,即使使用的是基本提示。
为了实现我们的目标,我们进行了实验,研究高级提示的两个关键方面:提示模板和多轮提示。具体来说,我们的目标是改进单轮交互的提示模板设计(详见第 IV-C 节),并通过促进多轮场景中的连续交互来提高解决性能(详见第 IV-D 和 IV-E 节)。此外,我们还打算通过对涉及 10 个不同案例的用户研究进行深入分析,来强调我们的交互方法的效果和意义。这 10 个案例的具体细节将在第 IV-A 节中提供,而评估指标将在第 IV-B 节中解释。
A.学习例子
为了加强 ChatGPT 与环境相关崩溃错误的交互,我们选择了 10 个不同的案例,这些案例尽管在 RQ1 中提供了完整的崩溃描述,但仍未得到修复。这些案例包括依赖版本问题、配置设置问题、网络问题和用户权限问题。表 II 列出了每个案例的详细信息。这 10 个案例将用于有关每个子问题的具体实验和分析。
B.性能指标
我们招募了两名至少有三年编程经验的参与者来评估 ChatGPT 在实验中的反应。与问题 1 一样,他们首先评估了定位和修复的准确性。为了减少 ChatGPT 固有随机性的影响,我们对每个案例进行了三次试验。因此,准确度指标是根据所有 30 次试验中成功定位和修复的比例计算得出的。此外,他们还根据预定义的陈述(见下文),使用 4-point Likert scale [48](1-不同意;2-有点不同意;3-有点同意;4-同意)对答案的有用性、简洁性和交互性进行评分。对于每个查询,所有评分结果均由两名参与者通过讨论共同确定。
- 有用性:ChatGPT 可以提供有用的解决方案,帮助参与者解决崩溃错误,包括详细解释问题的根本原因和全面的解决方案。
- 简明性:ChatGPT 可以提供清晰准确的解决方案,而不会出现冗余信息。
- 互动性:多轮对话流畅,不会忽略之前的上下文。
C. RQ2.a:提示模板
提示设计的质量直接影响到 LLM 输出的准确性和有效性。以往的研究表明,提示模板对 ChatGPT 的响应有很大影响[49]。因此,我们需要进一步探索如何改进提示模板设计,以提高 ChatGPT 修复环境相关崩溃错误的性能。本节将重点讨论如何设计高质量的提示模板,并介绍相应的实验设计和结果。
1) 设计:在实验经验的基础上,我们从文献[50]中汲取灵感,为与环境相关的崩溃错误设计了三种不同的提示模板。
- 多种解决方案—提示:请向我展示所有可能的解决方案。
- 角色扮演—提示:我要你扮演故障定位和程序修复专家。您将能够提供详细的解决方案来修复给定的程序崩溃。
- 思维链提示:请逐步修复。
首先,我们探讨了 ChatGPT 能否通过利用多解提示(Multi-Solution-Prompt)来促进所有可能解的生成,从而产生以前无法实现的正确解。
从文献[51]、[52]和[53]中得到启发,我们发现角色扮演提示和思维链提示的实施可以显著提高 ChatGPT 的定位和修复效率。将上述提示与 Basic-Prompt-3 相结合,我们使用这些提示对 10 个研究案例进行了对比实验。为了减少对 ChatGPT 随机性的担忧,我们对每个查询运行了三个独立请求,并使用指标对答案进行了评估。
2) 结果:各种提示模板的实验结果见表三。与基本提示相比,多解决方案提示允许 ChatGPT 提供更多的解决方案,提高了找到正确解决方案的可能性,但却降低了简洁性。思维链提示也面临类似的问题,它引入了大量冗余信息,导致简洁性得分低至 0.2,而不是帮助 ChatGPT 获得更准确的端到端解决方案。多解决方案和思维链提示提高了定位和修复的有效性,但牺牲了简洁性,相比之下,角色扮演提示在单轮交互中表现出色。它的修复准确率比基本提示高出 0.23,有用性得分高出 1.23,而且更加简洁。
此外,ChatGPT 识别崩溃错误根本原因的能力也有所提高。例如,在崩溃错误 30322026 中,前两个提示虽然也提到了 Smack 版本的问题,但并没有指出 Smack 版本与 Android 项目不兼容是根本原因,而 ChatGPT 的角色扮演提示则指出了根本原因。因此,我们得出以下结论:
发现 10:角色扮演提示大大提高了 ChatGPT 定位和修复崩溃错误的能力。
D. RQ2.b:多轮提示
我们探索了多轮交互,以增强 ChatGPT 的崩溃错误定位和修复能力。我们的假设是,用户与 ChatGPT 之间的持续互动可以产生更精确的响应,最终提高性能。
1) 设计:为了验证我们的假设,我们设计了实验来测试在两种情况下对研究案例中 ChatGPT 的回复提供反馈的有效性。
- 最初的答案没有准确定位崩溃错误(如崩溃错误 37771758)的根本原因。
- 最初的答复确定了崩溃错误的根本原因,但提供的解决方案过于笼统,没有提供具体的解决步骤(例如,崩溃错误 51370703 和 30322026)。
对于第一种情况,我们设计了 “新解决方案提示“(New-Solution-Prompt)来要求提供新的解决方案;对于第二种情况,我们使用了 “改进提示“(Refinement-Prompt)来要求提供解决方案的具体细节。
在尝试过程中,我们发现 Refinement-Prompt 可以获取大多数问题的详细解决方案。但是,对于与库版本相关的问题,Refinement-Prompt 无法获得需要升级或降级的具体版本号。因此,我们针对此类问题设计了专门的提示,需要有针对性地提问。针对每个崩溃错误,我们在实验中同时使用了基本提示和角色扮演提示。
- 新解决方案提示:我已经尝试了上述解决方案,但问题依然存在。
- 您能给我一些新的解决方案吗?改进-提示:请提供有关上述解决方案的更详细信息。
- 版本-提示:哪个版本的 [库 1] 与我的项目/[库 2] 版本兼容?
结果根据对研究案例的具体分析和表 III 所示的结果,我们可以得出以下结论(结果 10-12),每个结论都有详细分析。
发现 11:持续与 ChatGPT 互动有助于进一步提高其定位和修复崩溃错误的能力。
表 III 显示,与单轮互动相比,连续互动提高了模型的定位和修复准确性,以及实用性和简洁性评分。值得注意的是,即使在连续交互中使用基本提示,结果也超过了最有效的单轮角色扮演提示。这凸显了连续互动的有效性。
发现 12:”角色扮演-提示 “的使用大大提高了 ChatGPT 保持上下文连贯性的能力,减少了遗忘先前上下文的情况,从而提高了解决和交互性能。
表 III 中的实验表明,在多轮互动中使用角色扮演提示在所有指标上都优于基本提示。这表明角色扮演提示有助于 ChatGPT 更好地理解上下文并生成更准确的回复。此外,它还将交互得分从 3.37 显著提高到 3.63。这一改进可归因于角色扮演提示帮助 ChatGPT 保持了上下文的一致性,避免了重复以前的解决方案。
发现 13:ChatGPT 似乎掌握了官方文档中讨论的有关库版本的知识。但是,它需要有针对性的提问才能激活相应的知识。
根据对崩溃错误 51370703 进行的试验,可以得出上述结论,作为对发现 9 的补充。举例来说,如果我在持续交互过程中询问 “我应该使用哪个版本的 SLF4J?”,ChatGPT 可能只会建议更新到最新版本,甚至建议使用 1.8 版,就像在崩溃错误中使用的那样。但是,如果我提出 “在我的项目中,哪个版本的 SLF4J 与 Logback 1.2.3 兼容?”的问题,它可能会让我了解到 Logback 1.2.3 版本需要 slf4j-api 1.7.x 版本。
E. 问题 2.b:通过自我规划加强多轮提示
通过上述分析,我们发现 ChatGPT 即使使用角色扮演提示和思维链提示,也很难一次性准确定位崩溃错误的根本原因。这妨碍了它提供有针对性解决方案的能力。正如第 IV-D 节和发现 13 所讨论的,ChatGPT 拥有解决许多崩溃错误的知识,但获取这些知识需要特定的方法。持续互动和有针对性的提问要求提问者从潜在的解决方案中找出真正的原因,这就提出了很高的要求。此外,由于提问者没有提供足够的背景信息,限制了 ChatGPT 提供有针对性的解决方案(调查结果 8),而且提问者可能无法确定崩溃错误的综合环境背景的相关方面。
为了克服这些挑战,我们授权 LLM 通过持续的主动询问来积极调查潜在的导致碰撞的环境因素,并逐步指导解决过程。利用 LLM 的自我规划能力 [54],ChatGPT 针对可能导致崩溃的各种环境因素制定了调查计划,并根据其诊断意义进行了优先排序。ChatGPT 会积极向用户询问具体细节,逐步找出根本原因,并提供有针对性的解决方案。这一目标是通过主动询问提示来实现的,该提示旨在激发 ChatGPT 主动提问。
1)设计与结果: 我们利用角色扮演提示使 ChatGPT 能够进行主动询问。我们改进了提问方法,以避免过于笼统的询问,并防止开发人员同时面对多个问题而不知所措。这包括指定某些问题类型和提供一个示例,以引导 ChatGPT 的提问更有针对性和可操作性。由此产生的提示激发了 ChatGPT 的主动提问,促进了自我规划。
ActiveQ-Prompt:我想让你担任程序异常修复专家。您将能够提供详细的解决方案来修复给定的程序异常。此外,请使用苏格拉底式提问法帮助进行准确诊断。但请注意,问题中的信息应尽可能具体。例如,…另外,每次只提一个问题,从您认为最重要的问题开始。
在评估 ActiveQ-Prompt 的性能时,我们注意到 ChatGPT 仍可能同时产生多个问题,尽管指示一次只能问一个问题。为了解决这个问题,我们在随后的互动中引入了 AskOneQ-Prompt,强调根据问题的重要性优先处理连续的单个问题询问。
AskOneQ-Prompt:注意,每次只能问一个问题,从你认为最重要的问题开始。
通过使用这种方法,ChatGPT 能够根据问题的优先级一次提出一个问题,从而引导开发人员找到有针对性的解决方案。以编号为 30322026 的崩溃错误为例,ChatGPT 利用 ActiveQ-Prompt 和 AskOneQ-Prompt 提出了以下问题:
我的第一个问题是:您在这个项目中使用的 Smack 库是什么版本?
在提供相应信息后,部分 ChatGPT 的回复如下:
要解决这个问题,可以尝试使用专为 Android 设计的 Smack 库版本,如 assmack-androidextensions:4.4.4’orsmack-android:4.4.4’.
根据所提供的答案,ChatGPT 显然准确地指出了错误的根本原因,即所使用的 smack-java7:4.1.0 库与 Android 环境不兼容。此外,ChatGPT 还建议将正确的库版本作为详细的解决方案。
发现 14:采用主动询问提示来激发自我规划的主动问题,增强了 ChatGPT 主动指导修复过程的能力。这有助于找出崩溃错误的根本原因,对新手用户尤其有益。
方法:INTDIAGSOLVER
基于我们的实验结果和研究发现,我们推出了 IntDiagSolver,这是一种通过与 LLM 持续交互来解决崩溃错误的新方法。图 2 概述了我们的方法。值得注意的是,IntDiagSolver 并不与任何特定的 LLM 绑定,可以根据需要进行调整。
概念解释。用户提供的提示在黄色框内,并附有碰撞细节和说明。不同提示的详情可参考 RQ1 和 RQ2 中列出的提示模板。法律硕士提供的回复在蓝色框内,可分为问题和解决方案。问题可以有多个,但突出问题要求将有助于 ChatGPT 生成具体问题(见第 IV-E 节)。解决方案可以是粗略的,也可以是详细的(包括优化解决方案),并附有修复崩溃错误的具体步骤。验证是指绿色方框中的维修尝试结果,目前为人工验证。菱形框中的决定表示选择,目前基于人工判断。
解决与代码相关的崩溃错误。要解决与代码相关的崩溃错误,主要挑战在于准确诊断崩溃错误的根本原因(参见发现 3)。因此,利用 “思维链 “策略将解决过程分为诊断和修复阶段是有益的。这一策略需要部署提示,引导 LLM 识别出错误线路,随后强调精确定位的信息,以便进行高效修复。此外,强调异常类型和提供全面的崩溃背景有助于提高解决效率(参见发现 2)。
与环境相关的崩溃错误解决。在解决与环境相关的崩溃错误时,用户可以选择让 LLM 指导修复过程。这对崩溃错误知识有限的初学者很有帮助,而经验丰富的开发人员可能不需要 LLM 的积极指导。此外,版本问题也会带来独特的挑战,这一点在第 III-B 节和发现 13 中已有讨论。如果用户选择不依赖 LLM 的指导,则应仔细检查初始解决方案,以识别任何版本问题。在这种情况下,应利用版本提示来获取具体细节。另外,普通的细化提示也足以获得具体的解决方案细节。
验证过程。验证应在收到 LLM 的详细解决方案后进行。如果解决方案能够修复崩溃错误,则将获得最终的正确解决方案。否则,应利用新的解决方案提示来获取新的解决方案。这一过程需要进行最多次数的尝试(例如,在我们的设置中为 3 次)。
未来工作。未来,我们的目标是建立一个端到端的自动化插件工具,以完成整个交互过程。该工具将自动进行崩溃错误类型分类、提示生成、LLM 响应分析和验证—在运行环境中执行修复尝试并提供自动反馈。实际实施可以沿用现有的基于 LLM 的交互式程序修复方法 [9]。
VI.问题 3:对 intdiagsolver 的评估
为了评估 IntDiagSolver 的有效性和可推广性,我们进行了使用该方法解决崩溃错误的实验。最初,我们通过将 IntDiagSolver 与 ChatGPT 集成来进行实验,ChatGPT 基于 GPT-3.5,我们在 RQ1 和 RQ2 中使用了 ChatGPT(详见第 VI-A 节)。由于 IntDiagSolver 是在 RQ1 和 RQ2 的基础上开发的,因此我们的目标是确定它在解决这些研究中发现的挑战和以前未解决的崩溃错误方面的功效。此外,我们还扩展了实验范围,通过将 IntDiagSolver 与各种 LLM(包括开源和闭源的先进 LLM)集成来评估 IntDiagSolver 的泛化能力(第 VI-B 节)。这样,我们就能评估 IntDiagSolver 在不同 LLM 中的性能表现。
A. RQ3.a: Effectiveness of IntDiagSolver
在本研究问答中,我们评估了 IntDiagSolver 在使用基于 GPT-3.5 的 ChatGPT 解决崩溃错误方面的有效性,并将其与使用基本提示的基线方案进行了比较。
1) 设置:实验设置包括 LLM 配置、基准和指标。
- LLM 配置。我们使用与 RQ1 和 RQ2(第二节)相同的配置,将 gpt-3.5-turbo 模型 [12] 作为 GPT-3.5。由于模型的非确定性,我们利用基本提示和 IntDiagSolver 对每个崩溃错误进行了三次单独运行。如果任何一次运行都产生了积极的结果,则认为试验成功。按照第 III-A2 节中概述的结构,每次运行都会启动一个新的 ChatGPT 会话,以消除之前对话历史的任何影响。
- 基准。从第 II-A 节中最初的 100 个崩溃错误基准中,我们特意选择了未修复的实例(见表 I),尽管我们收到了完整的崩溃描述。这一选择形成了一个完善的基准,包括 11 个与代码相关的崩溃错误和 30 个与环境相关的崩溃错误,共计 41 个案例。
- 指标。本实验的指标与第 III-A4 节中介绍的指标一致。此外,为了评估持续交互的有效性,我们记录了实现最终正确定位或修复结果所需的交互轮数。如果在第一轮中获得了正确的定位信息,那么后续未获得正确修复信息的尝试仍计入一轮。
2) 结果:结果表明,在解决与代码相关的崩溃错误和与环境相关的崩溃错误方面都有很大改进,定位精度分别提高了 133.0% 和 179.1%。值得注意的是,由于基本提示没有成功修复,因此无法计算精确度。
在处理与代码相关的崩溃错误时,又有 4 个崩溃错误得到了有效的定位和修复。其中 3 个是通过在后续交互中强调错误行来修复的,而在最初的崩溃描述中强调异常类型则有助于定位。在与环境相关的崩溃错误方面,改进更为显著:准确定位的错误增加了 13 个,成功修复的错误增加了 16 个。此外,有 14 个崩溃错误是通过反复交互解决的,这凸显了我们的 IntDiagSolver 框架的功效。
B. 问题 3.b:IntDiagSolver 的通用性
在本研究问答中,我们采用与研究问答 3.a 相同的基准和指标(第 VI-A1 节),评估 IntDiagSolver 在另外三个 LLM 上的通用性。
1) 已研究过的 LLM:我们选择了三个最先进的 LLM:两个闭源模型(GPT-4 [55] 和 Claude [56])和一个开源模型(Codellama-34b [57])。GPT-4 是 GPT 系列的最新版本,也是 GPT-3.5 的后继版本,是首屈一指的通用 LLM。Anthropic 开发的 Claude [56] 是一个闭源模型,在 HumanEval 数据集 [58] 上的性能仅次于 GPT-4 和 GPT-3.5 [59]。Codellama-34b [57]是 Llama2 的增强版,通过额外的特定代码训练,被公认为领先的开源代码 LLM。为了确保实验的一致性,我们对所有研究的 LLM 都采用了统一的方法,即通过网络界面进行人工交互。
2) 结果:表 IV 展示了 IntDiagSolver 显著的通用性,与基本提示相比,它有效提高了各种闭源和开源 LLM 对代码相关崩溃错误和环境相关崩溃错误的解决能力。然而,作为最先进的 LLM,GPT-4 的整体改进幅度不大,与环境相关的崩溃错误定位精度提高了 13.1%,而与代码相关的崩溃错误定位精度则没有提高。此外,与代码相关的崩溃错误相比,所有模型在解决与环境相关的崩溃错误方面都有更显著的提高(提高 26.9% 到 66.8%),这反映了与环境相关的崩溃错误的复杂性(如研究结果 1 和 5 所述)。我们在第四节中的努力主要针对与环境相关的崩溃错误,从而获得了更明显的改进。此外,一个值得注意的趋势是,与定位精度相比,修复精度有了大幅提高(提高了 2.2% 到 182.2%),这凸显了在修复阶段及时增强的有效性。
相关工作
A. LLM for 软件工程
近年来,LLM 在数学[13]、[14]、教育[15]、[16]和自然语言处理[17]、[18]等多个研究领域获得了相当多的关注。在软件工程(SE)领域,从代码生成 [21]、[22]、[23] 和代码总结 [19]、[20] 到软件维护任务(包括漏洞检测 [38]、[60]、测试生成 [61]、[62] 和程序修复 [7]、[26]、[9]、[63]、[64]),LLMs 已被广泛应用于各种任务,证明了它们的潜力。这种广泛的 SE 应用源于它们在大量代码和文本数据上的强大训练,从而增强了语言和代码理解能力。
B. LLMs for 解决崩溃bugs
软件崩溃是软件开发中的一个持久挑战,它推动了崩溃再现 [65]、[66]、崩溃定位 [67]、[68]、[69] 和崩溃修复 [2]、[3]、[10] 等领域的研究。为解决与代码相关的崩溃错误,人们对自动定位 [4]、[5]、[6] 和修复 [7]、[8]、[9] 进行了研究。与此相反,与环境相关的崩溃错误由于其来源多种多样,通常依赖于在线问答论坛(如 SO)提供的解决方案 [3]、[10]、[11]、[70]。
最近关于软件工程中 LLM 的调查[71]、[72]探讨了它们的应用、性能和挑战,包括错误定位和程序修复。关于 ChatGPT 在解决代码相关错误方面潜力的初步研究 [26]、[9]、[63] 主要集中在有固定提示的简单场景。相比之下,我们的研究:(i) 将解决过程分为两个阶段:定位和修复,从而与现有研究有所区别;(ii) 全面评估了 ChatGPT 在解决来自 SO 的真实世界崩溃错误方面的有效性;(iii) 探讨了在各种交互策略中使用不同提示的效果;(iv) 将与代码相关的问题扩展到外部环境因素导致的崩溃错误,而这一点在之前的研究中受到的关注有限。
C. Prompt Engineering for 软件工程
提示工程是一门新兴学科,它针对 LLM 在不同领域的各种应用优化提示。该领域的方法包括 “快速提示”(Few-Shot Prompting)[73]、”思维链提示”(CoT)[52]、[53]、”思维树提示”(ToT)[74]和 “知识提示”(Knowledge Prompting)[75]。在软件工程领域,提示工程增强了各种任务中的 LLM。研究人员利用思维链提示改进了代码生成[76]、[77],探索了论证和任务分解策略以更好地生成单元测试[61],并将思维链提示与静态分析相结合以更有效地检测漏洞[60]。此外,知识提示与思维树方法相结合,在数据库诊断中推进了 LLM [78]。在本研究中,我们探索了各种提示模板和先进技术,以有效解决崩溃漏洞。为此,我们提出了 IntDiagSolver,利用知识提示来解决崩溃错误。它遵循 “思维链提示”(Chain-of-Thought Prompting)原则,将整个过程分为两个阶段(定位和修复),并涉及 LLM 的多轮交互。
验证的威胁
该研究使用了来自 SO 的 100 个 Java 相关崩溃错误的数据集,这可能会限制其普遍性。为了解决这个问题,研究人员特意选择了现实世界中的各种崩溃错误,包括代码和环境相关问题。之所以把重点放在 Java 崩溃错误上,是因为它们在程序修复研究中非常普遍和重要[3],[10],而且之前的研究[63]已经表明 LLMs 可以跨编程语言迁移,从而减少了与语言相关的问题。为了提高未来研究的普适性,考虑来自各种编程语言和软件系统的更大和更多样化的数据集可能是有益的。
在我们的探索性研究(RQ1 和 RQ2)中,GPT-3.5 的使用可能会限制我们研究结果的推广性以及 IntDiagSolver 方法对其他模型的适用性。为了解决这个问题,在 RQ3 中,我们在 GPT-4 和其他 LLM 上测试了我们的方法,巩固了我们的初步发现,并表明了对其他模型的潜在适用性。此外,RQ2 中的一个潜在威胁是仅使用 10 个案例进行交互探索,这可能会带来偏差。不过,评估阶段的实际测试表明,该方法在更广泛的案例范围内具有良好的有效性(表 IV)。
由于 ChatGPT 反应的随机性,可能会影响实验的可靠性和有效性。为了减轻这种影响,我们进行了多次试验,并仔细记录了所有 ChatGPT 交互,以提高透明度和可重复性[79]。一个潜在的威胁是 SO 基准的数据泄露风险。尽管 ChatGPT 没有公开其训练数据,但之前的研究[61]和我们自己与地面实况的比较结果表明,即使作为最先进的 LLM,ChatGPT 也没有仅仅记住我们研究中使用的数据。
结论
本研究对 ChatGPT 在定位和修复软件崩溃错误方面的有效性进行了实证调查。它还研究了增强交互的策略,以提高错误解决的准确性和效率。利用实验结果,我们介绍了 IntDiagSolver,这是一种在与 LLM 一起解决崩溃错误时优化交互过程和提示设计的方法。结果表明了 ChatGPT 的重要作用,通过优化流程显著提高了解决的准确性和效率。总之,本研究为开发人员提供了一种使用 LLM 解决崩溃错误的新方法,为优化与这些模型的交互提供了启示。