LLM is Like a Box of Chocolates: the Non-determinism of ChatGPT in Code Generation
Shuyin Ouyang1, Jie M. Zhang2, Mark Harman3, Meng Wang1
1University of Bristol, Bristol, United Kingdom
2King's College London, London, United Kingdom
3University College London, London, United Kingdom
引用
Ouyang S, Zhang J M, Harman M, et al. LLM is Like a Box of Chocolates: the Non-determinism of ChatGPT in Code Generation[J]. arXiv preprint arXiv:2308.02828, 2023.
论文:https://arxiv.org/abs/2308.02828
摘要
本研究探讨了大型语言模型(LLMs)在代码生成任务中的非确定性问题,特别是ChatGPT模型。研究发现,ChatGPT在相同提示下生成的代码存在高度的非确定性,这可能对科学研究的有效性构成威胁。研究通过对三个代码生成基准测试(CodeContests、APPS和HumanEval)中的829个问题进行实证分析,揭示了非确定性的程度。结果显示,不同请求中生成的代码在语义、语法和结构上存在显著差异,且设置温度为0并不能保证代码生成的确定性。此外,研究还分析了编码任务特征与非确定性之间的关系,并比较了GPT-3.5和GPT-4在代码生成中的非确定性。研究结果强调了在基于LLM的研究中考虑非确定性的重要性,并为未来在代码生成任务中使用大型语言模型提供了指导。主要分为引言、方法、实验设计及结果这三部分。
1 引言
语言大模型(LLMs)本质上是非确定性的。这是因为LLMs根据上下文(由一组样本词表示)预测一个词或标记的概率。大型语言模型中的随机性通常来自于文本生成过程中使用的抽样方法,如top-k抽样或核抽样。因此,相同的指令或提示在不同的请求中可能产生完全不同的响应。这种非确定性(即在相同提示下不同请求生成的代码候选不一致)在使用LLM时是一个重要考虑因素。不可靠和不一致的代码片段可能对软件开发过程产生重大负面影响,尤其是在一致性和可靠性至关重要的安全关键应用中。此外,非确定性还影响经验软件工程的可靠性和可复现性。与ChatGPT的其他任务(如问答和文本摘要)相比,代码相关任务中的非确定性威胁更为严重,因为不一致性(尤其是语义不一致性)通常暗示生成代码中的错误。因此,了解非确定性对基于LLM的软件工程任务的影响至关重要。
本文首次系统地对ChatGPT在代码生成任务中的非确定性威胁进行了实证研究。我们选择代码生成任务,因为使用大型语言模型(如ChatGPT)进行代码生成因其令人印象深刻和前沿的性能最近引起了广泛关注。软件工程和机器学习社区已经发表了多篇评估ChatGPT在代码生成能力的文章。我们使用ChatGPT模型在三个广泛研究的代码生成基准(即CodeContests、APPS和HumanEval)上进行了829个编码问题的一系列实验。对于每个代码生成任务,我们让ChatGPT进行五次预测。然后,我们从语义相似性、句法相似性和结构相似性三个方面比较这五个代码候选。我们还探讨了温度(即控制ChatGPT生成文本随机性的参数)对非确定性的影响,以及非确定性与编码任务特征(如编码指令的长度和任务难度)之间的相关性。最后,我们比较了GPT-3.5和GPT-4之间的非确定性。
本研究首次揭示了ChatGPT在代码生成任务中的非确定性威胁。结果显示,超过60%的基准测试中,前五名代码候选没有一个能产生相同的测试输出;在最常用的HumanEval基准测试中,测试通过率的最大差异达到1.00,占问题的48.17%。此外,与普遍观念相反,将温度设置为0并不能保证代码生成的确定性。有趣的是,我们的相关性分析表明,编码指令的长度与语法、结构相似性以及测试通过率呈负相关,意味着更长的描述倾向于产生语法和结构相似性较低、错误较多的代码候选。通过对过去两年发表的76篇基于LLM的代码生成论文的分析,我们发现只有22.4%的论文在实验中考虑了非确定性威胁。我们呼吁研究者在得出结论时考虑非确定性威胁。
本文的贡献包括:
对ChatGPT在三个广泛研究的数据集上的非确定性威胁进行了首次研究,并采用了三种相似性测量方法。研究了温度设置对ChatGPT非确定性的影响,发现零温度并不保证代码生成的确定性。探讨了编码任务特征与非确定性程度之间的相关性,发现指令长度与代码质量呈负相关。分析了过去两年的LLM代码生成论文,发现只有21.1%的论文考虑了非确定性威胁,强调了在实验和结论中考虑非确定性的重要性。我们发布了相关数据、代码和结果,并在论文后续部分详细介绍了研究过程、实验设计、结果讨论以及对软件开发者和研究者的影响。
2 方法
图1展示了实验流程的概览。对于每个代码生成任务,我们首先生成一个包含编码指令的提示(prompt),然后将这个提示输入到ChatGPT以生成代码(零样本学习)。我们调用API五次,让ChatGPT对同一个提示做出五次预测。然后,我们从这五个响应中提取代码,得到五个代码候选。我们的非确定性分析比较这五个代码候选在语义、语法和结构上的相似性。
图1 整体实验方法设计
2.1 提示准备
我们研究的第一步是准备提示。遵循基于LLM的代码生成评估的常见做法,我们要求ChatGPT使用零样本提示为每个代码生成任务生成Python代码。为确保ChatGPT在响应中生成的是代码而非纯自然语言,我们在原始代码生成描述中增加了对Python代码的请求。从API响应中提取代码的一个挑战是,没有明确的信号来区分代码和纯文本,这与ChatGPT的网页聊天窗口不同(即在聊天窗口中,代码以Markdown代码块的形式返回)。为解决这个问题,我们指定生成的代码格式为“Markdown”。因此,对于每个代码生成任务,我们的提示变为“生成Python3代码(Markdown):”加上原始任务描述。
2.2 代码提取与脚本编写
收到ChatGPT的响应后,我们应用代码提取来检索生成文本中的代码。我们直接编译代码,不做任何修改。我们的实验主要在预装了Linux环境的Google深度学习虚拟机实例上运行,所有必要的库都已预装。这样可以最大程度地确保生成的代码在运行时不会因为库未安装而导致导入错误。
2.3 测试用例执行
为了评估ChatGPT生成代码的语义,我们使用适合每个基准测试的测试套件。我们不仅记录每个测试是否通过,还记录每个具体的测试输出,这使我们能够比较即使两者都失败的测试输出的相似性。对于CodeContests和HumanEval数据集,每个问题都有一个3秒的超时值。APPS数据集没有提供默认的超时值,我们也将其设置为3秒。我们使用单线程脚本运行测试,以确保测试用例按顺序执行,避免并发执行可能引起的竞争条件。
2.4 相似性检查
为了衡量代码候选之间的相似性,我们引入了相似性测量工具,评估生成的代码解决方案之间的语义、语法和结构相似性。语义相似性通过比较测试执行输出来衡量。语法相似性通过比较代码之间的文本相似性来衡量。结构相似性通过比较代码候选的抽象语法树(ASTs)来评估。
3 实验设计及结果
3.1 实验设置
研究问题。在本文中,我们研究以下研究问题:
RQ1: ChatGPT在代码生成中对非确定性的敏感程度如何?
Sub-RQ1.1: ChatGPT在语义相似性方面对非确定性的敏感程度如何?
Sub-RQ1.2: ChatGPT在语法相似性方面对非确定性的敏感程度如何?
Sub-RQ1.3: ChatGPT在结构相似性方面对非确定性的敏感程度如何?
RQ2: 温度如何影响非确定性的程度?该研究问题检查并比较了在不同温度选择下,ChatGPT在代码生成中的非确定性。
RQ3: 非确定性与同一预测中生成的顶级代码候选项的相似性如何比较?该研究问题比较了在不同预测中获得的代码候选项与同一预测中获得的代码候选项的相似性。
RQ4: 不同代码生成任务与非确定性程度之间有无相关性?为了理解影响非确定性的因素,该研究问题研究了代码生成特征(例如,代码生成指令的长度和代码生成难度)与我们研究中使用的相似性度量之间的相关性。
RQ5: GPT-4的非确定性与GPT-3.5相比如何?该研究问题比较了GPT-3.5和GPT-4在代码生成中非确定性程度的差异。
评估数据集。实验使用了三个最广泛研究的代码生成基准测试:CodeContests、APPS和 HumanEval。表1展示了每个基准测试的详细信息。
表1 代码生成基准数据集
CodeContests:CodeContests是用于训练AlphaCode的数据集,它包括来自不同来源的编程问题。我们使用其测试集来测试ChatGPT。
APPS:APPS包括10,000个问题(训练集和测试集),具有不同的难度级别(即入门级、面试级和竞赛级)。这个数据集专门设计用于Python程序合成评估。原始测试集包含5,000个代码生成问题,我们随机抽取了500个问题。
HumanEval:HumanEval包含164个手工编写的代码问题。每个问题包括一个函数签名、文档字符串、主体和几个单元测试,平均每个问题有9.24个测试用例。我们使用整个数据集来基准测试我们的实验。
参数设置:
model:使用的模型ID,如'gpt-3.5-turbo'和'text-davinci-003'。我们将此参数设置为'gpt-3.5-turbo'或'gpt-4'。
message:描述对话情况的消息列表,需要填写两个关键值'role'和'content'。在我们的实验中,消息的'role'是'user','content'包含我们用于请求的提示。
temperature:使用的采样温度,介于0和2之间(默认值为1)。较高的值会使输出更随机,而较低的值会使其更加聚焦和确定性。在我们的研究中,我们在RQ3中研究了温度的影响,使用三个温度值:0、1和2。对于其余的RQs,我们使用默认的温度值(即temperature=1)。
top_p:与温度采样相对应的另一种方式,称为核采样,模型考虑具有top_p概率质量的令牌的结果。在我们的实验中,我们不考虑这一点,将此值设置为默认设置(即top_p=1)。
n:为每个输入消息生成多少个聊天完成选择(默认值为1)。此参数专门用于RQ3,用于比较不同请求方式之间的差异。我们选择n=5,因为在方差研究论文中常用的数字是五。我们通过五次请求ChatGPT模型分别生成五个响应,但仅使用每次请求的第一个响应。
评估指标。针对三个方面来测量代码生成非确定性程度:语义相似性、句法相似性和结构相似性。语义相似性通过测试通过率和输出等价率来评估不同代码候选项的功能相似度。句法相似性利用最长公共子序列和莱文斯坦编辑距离来衡量代码的文本相似性。结构相似性通过抽象语法树(AST)的比较来测量代码结构的相似度。这些方法共同为理解和评估代码生成过程中的非确定性提供了一套全面的测量框架。
RQ1 ChatGPT在三种相似性下的非确定性
RQ1.1 语义相似性
实验设计:通过测试通过率和输出等价率(OER)及排除异常的OER来衡量。每个编码问题有五个测试通过率,使用这五个值的方差和最大差异来表示ChatGPT在生成代码的非确定性。还报告了平均值,代表生成代码的平均正确性。对于OER,每个编码问题只有一个值,表示所有五个代码候选项的测试输出相似性。对于每个数据集,报告了不同测量值的分布(图2和图3)。数据集中所有编码问题的平均测量值显示在表2中。最大差异指的是所有代码问题中最大差异的最大值。表2还显示了“最坏情况比例”,即测试通过率最大差异为1或OER为0的问题比例。
图2 RQ1.1:测试通过率方面的语义相似性分布
图3 RQ1.1:测试输出等价率(OER及无异常的OER)方面的语义相似性分布
表2 RQ1.1:语义相似性结果。OER及无异常的OER分别是输出等价率和排除异常的等价率。
实验结果:从图2、图3和表2观察到,ChatGPT在生成语义一致的代码候选项方面非常不稳定。特别是,五个代码候选项中测试输出完全不相等(即OER=0)的任务比例分别为72.73%、60.40%、65.85%。这表明在大多数情况下,ChatGPT根据相同指令生成的代码候选项在语义上完全不同。
表2显示,测试通过率的平均方差不大,介于0.03和0.10之间,这是因为不同代码候选项的测试通过率通常同样糟糕。然而,所有三个数据集的测试通过率最大差异达到1.00,并且在HumanEval中占了48.17%的问题,这是最广泛使用的代码生成基准。
在三个数据集中,HumanEval数据集在测试通过率方面显示出最大的方差,但也在测试通过率方面表现出最佳的正确性。我们怀疑这是因为HumanEval中的编码任务对ChatGPT来说相对容易。不同数据集之间的大差异也凸显了在评估大型语言模型的代码生成性能时使用多个数据集的重要性。
总体来说,ChatGPT生成的代码在不同请求之间的语义差异显著。特别是,在CodeContests、APPS和HumanEval中,没有一个测试输出相等的编码任务比例分别为72.73%、60.40%、65.85%。此外,所有三个数据集的测试通过率最大差异达到1.00,并且在HumanEval中占了48.17%的问题,这是最广泛使用的代码生成基准。
RQ1.2 语法相似性
实验设计:
语法相似性通过代码候选项之间的文本相似性来衡量。在我们的实验中,语法相似性通过最长公共子序列(LCS)和最小编辑距离(LED)两个指标来评估。对于每个编码问题的五个代码候选项,我们使用第一个代码候选项作为参考,并计算参考与其余四个候选项之间的LCS和LED。因此,每个问题有四个LCS值和LED值,每个值指示一个语法相似性。我们使用这四个值的平均值以及最差的值(即LCS的最小值和LED的最大值)来表示每个问题的语法相似性。图4显示了每个数据集中所有问题的LCS和LED分布。表3显示了数据集中所有编码问题的平均和最差LCS和LED值(图中每个条形图内的平均值)。
图4 RQ1.2:句法相似性分布(LCS及LED)。较低的LCS和较高的LED表示句法相似性较低。
表3 RQ1.2:句法相似性(LCS和LED)。较低的LCS和较高的LED表示句法相似性较低。
实验结果:
观察到即使是从相同指令生成的代码候选项,在语法度量上也有很大差异。特别是,CodeContests、APPS和HumanEval的平均LCS分别为0.12、0.14和0.45,表明代码候选项中最长公共子序列的平均比例。
从表3中我们可以看出,CodeContests数据集的LCS最低和LED最大值都发生了。相比之下,HumanEval的LCS最大和LED最小值都发生了。这表明ChatGPT在CodeContests的代码生成任务中在语法上最不稳定,在HumanEval中最稳定。我们将在RQ4中进一步探索不同相似性与代码任务特征之间的相关性。
总体而言,由ChatGPT在不同请求中生成的代码候选项在语法上也有显著差异。平均语法相似性(LCS)对于CodeContests、APPS和HumanEval分别仅为0.12、0.14和0.45。
RQ1.3结构相似性
实验设计:
结构相似性基于代码的抽象语法树(AST)来衡量代码之间的相似性。在我们的实验中,主要通过使用工具pycode_similar和两种不同的设置,即United_Diff和Tree_Diff来测量结构相似性。对于每个编程问题的五个代码候选项,我们使用第一个代码候选项作为参考,并在United_Diff和Tree_Diff设置下计算第一个候选项与其余四个候选项之间的结构相似性。因此,每个问题分别在United_Diff和Tree_Diff下有四个值,每个值表示一个结构相似性测量。我们使用这四个值的平均值以及它们中的最小值(即United_Diff和Tree_Diff的最小值)来代表每个问题的结构相似性。
表4 RQ1.3:结构相似性。
图5 RQ3:结构相似性(UnitedDiff及TreeDiff)
实验结果:
图5显示了每个数据集中所有问题在United_Diff和Tree_Diff下的分布。表4显示了所有编码问题在United_Diff和Tree_Diff设置下的平均值和最小值(图中每个条形图内的平均值)。我们观察到,从相同指令生成的代码候选项在结构上显示出很高的相似性。具体来说,CodeContests、APPS和HumanEval数据集在United_Diff设置下的平均值分别为0.46、0.52和0.69,在Tree_Diff设置下分别为0.60、0.68和0.72,这表明代码候选项之间AST相似性的平均比例。
对于这三个数据集,我们可以从表4中看到,在United_Diff和Tree_Diff下的最小值都出现在CodeContests数据集中。相比之下,这两个设置下的最大值都出现在HumanEval中。这表明,在CodeContests中的代码生成任务中,ChatGPT在结构上最不稳定,而在HumanEval中最稳定。我们将在RQ4中进一步探索不同相似性与任务特征之间的相关性。
总体而言,在UnitedDiff和TreeDiff设置下,代码候选项显示出高度的结构相似性。我们观察到,从相同指令生成的代码候选项在结构上具有高度的相似性。具体来说,CodeContests、APPS和HumanEval数据集在United_Diff设置下的平均值分别为0.46、0.52和0.69,在Tree_Diff设置下分别为0.60、0.68和0.72。
RQ2:温度的影响
实验设计:
默认情况下,ChatGPT的温度设置为1。本研究问题探讨了温度变化是否会影响ChatGPT在代码生成中的非确定性。我们使用与RQ1相同的测量方法。由于篇幅限制,我们仅展示了在CodeContests数据集上的结果,因为在代码生成的不同相似性类型中,ChatGPT在该数据集上的表现最差,这为我们提供了更多观察温度影响的空间。其他两个数据集的结果请见我们的主页。
表5 RQ2:温度的影响。
实验结果:
如表5所示,当温度设置为0时,ChatGPT在所有三种相似性类型上比默认配置(温度=1)有更好的确定性。然而,将温度设置为0并不能完全避免非确定性。以OER为例,仍然有16.36%的问题在五个代码候选项中没有相等的测试输出。这与许多人的信念(和常见做法)相反,即认为将温度设置为0可以使ChatGPT变得确定性。
当温度设置为2时,有趣的是,我们观察到测试通过率的平均方差仅为0.01,低于温度=0和温度=1的情况,且最坏情况的比例仅为0.61%。这是因为较高的温度为ChatGPT带来了过多的创造性,影响了其生成正确代码的能力(从平均测试通过率可以看出)。结果,生成的代码候选项倾向于统一地更差。
总体而言,与广泛持有的信念(和常见做法)相反,将温度设置为0并不能保证代码生成的确定性,尽管它确实在所有三种相似性类型上比默认配置(温度=1)带来了更好的确定性。将温度设置为2倾向于产生统一更差的代码候选项,这可能反常地提高了代码候选项之间的相似性。
RQ3 单次请求与多次请求顶级候选项的非确定性比较
实验设计:
本研究问题比较了两种请求配置下代码候选项的非确定性程度。具体来说,比较了来自单次请求的前5个代码候选项(即同一请求中按预测概率排名的前5名)与来自多次请求的5个顶级代码候选项(每个请求的顶级候选项)的非确定性。
表6 RQ3:不同请求方式的相似性
实验结果:
如表6所示,单次请求中的前5个代码候选项(R1)与多次请求中的5个顶级代码候选项(R2)在非确定性程度上非常相似。这一发现与直觉相反,直觉告诉我们,来自不同请求的5个顶级代码候选项(R2)应该比单个请求中的前5个代码候选项(R1)具有更高的相似性,因为前者是每个请求最佳响应的集合,而后者仅是最佳的前5名。
然而,观察结果表明,单次请求的前5个代码候选项(R1)与多次请求的5个顶级代码候选项(R2)的相似性非常接近。
即对于ChatGPT而言,单次请求中的前5个代码候选项与不同请求中的5个顶级代码候选项在非确定性方面非常相似。
RQ4 编码任务特征与非确定性程度的相关性
实验设计:
本研究问题通过检查编码任务特征与相似性度量值之间的相关性来研究什么影响了ChatGPT在代码生成中的非确定性。使用CodeContests数据集,因为它是唯一一个为每个编码任务提供了多种特征的数据集,包括难度、时间限制和CF评分。难度是一个定性度量,表示解决问题所需的复杂性水平和编程知识与技能。时间限制指的是程序的最大运行时间限制。CF评分是一个定量度量,表示问题相对于Codeforces平台上其他问题的难度水平。此外,我们还考虑了每个编码任务的描述长度(即字符数)。注意,本节仅关注相关性分析,并不旨在得出任何因果结论。
图6 RQ4:编码任务与非确定性之间的相关性。热图上只显示显著的相关性,不显著的相关性(即p值>0.05)用‘-’遮盖
实验结果:
结果显示,对于四个编码任务特征(描述长度、难度、时间限制和CF评分),描述长度与平均测试通过率呈负相关。这意味着描述较长的问题倾向于有更差的测试通过率。我们怀疑这是因为较长的描述可能会降低ChatGPT对编码要求的理解。描述长度还与测试通过率的方差和最大差异呈负相关,这是因为描述较长时,不同的代码候选项在通过率上倾向于统一地更差。然而,描述长度与LCS和United_Diff呈负相关,意味着描述较长的问题倾向于产生在语法和结构上更不一致的代码候选项。
难度等级与测试通过率方差呈正相关,这意味着难度更高的问题在测试通过率上的方差更大。CF评分是唯一与平均测试通过率显著负相关的特征,这表明CF评分较高的代码问题平均测试通过率可能更低。我们还观察到,聚集在同一类型相似性度量中的特征显示出高相关性(p值<0.05),如测试通过率平均值、测试通过率方差和测试通过率最大差异平均值。这也表明我们为每种相似性类型选择的不同度量的可靠性。有趣的是,我们没有观察到语义相似性和语法相似性之间的任何相关性,尽管语法相似性和结构相似性之间的相关性很强。
总体而言,编码任务的描述长度与LCS、United_Diff和测试通过率呈负相关。这意味着编码任务的描述越长,生成的代码在代码语法和结构方面的非确定性越大。生成的代码也倾向于更多错误。
RQ5 GPT-4的非确定性与GPT-3.5相比如何?
实验设计:
本研究问题比较了GPT-3.5和GPT-4在代码生成非确定性程度上的差异。由于GPT-4使用限制和高昂的成本,我们仅在最广泛使用的HumanEval数据集(温度=1)上报告结果,保持默认设置并使用RQ1中列出的所有测量标准。
表7 RQ5:GPT-4与GPT-3.5的非确定性
实验结果:
从表7中,我们观察到GPT-4的非确定性问题同样严重,总体上比GPT-3.5稍差,除了OER相似性外。这是因为GPT-4被认为比GPT-3.5“更具创造性”,而更高的创造性通常意味着更高的非确定性。对于OER,GPT-4的相似性大于GPT-3.5。我们怀疑这是因为GPT-4产生了更多测试通过率为1.0的案例,从而引入了更多相同的测试输出。这一观察并不适用于测试通过率的相似性,因为来自GPT-3.5的代码候选项可能同样不正确。例如,在我们的实验中,对于某个代码任务,GPT-3.5的测试通过率为[0,0,0,0.8,0.8],而GPT-4的测试通过率为[1,1,1,1,0]。GPT-4的OER和OER(无异常)明显高于GPT-3.5,但测试通过率的方差和最大差异略有增加。即GPT-4的非确定性问题同样严重,并且总体上比GPT-3.5稍差。
转述:田方源