除了常规的文本翻译、上下文对话等自然语言理解功能,以ChatGPT和GPT-4为代表的大型语言模型(LLMs)的另一大亮点就是其强大的编程代码生成能力。通过海量代码数据的预训练,LLMs几乎可以在任意的编程场景中,根据用户给定的要求来生成伪代码,甚至是可以直接运行的代码。很多人开始讨论ChatGPT会不会直接代替底层程序员的话题,例如哈佛大学计算机教授Matt Welsh在2023年计算机协会(ACM)大会上提到,他认为ChatGPT会在三年后取代底层程序员的工作。但实际情况是,对于复杂的编程任务,LLMs一次性生成正确的代码仍然是非常具有挑战性的任务,LLMs可能会受自身生成"幻觉"的影响,导致生成的代码中含有很多bug。
目前解决这类问题的常用方法是设计针对代码生成的指令微调方法来优化LLMs,但是这种方法的成本太高,模型仍需要从大量数据中学习针对特定任务的代码修复能力。本文介绍一篇来自谷歌研究院和UC伯克利合作完成的工作,本文提出了一种Self-Debug方法来教会LLMs进行"小黄鸭调试法(rubber duck debugging)"。
论文链接:https://arxiv.org/abs/2304.05128
小黄鸭调试法:又称橡皮鸭调试法、黄鸭除虫法(Rubber Duck Debugging)是可在软件工程中使用的一种调试代码的方法。方法就是在程序的调试或测试过程中,操作人耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感与发现矛盾。--参考维基百科
经过Self-Debug处理后的LLMs,可以在没有任何关于代码正确性或错误消息的反馈的情况下,仅通过观察审视已生成的代码来识别其中的bug。作者在多个代码生成基准上对Self-Debug方法进行了评估,包括文本生成SQL语句、不同编程语言之间的转换(例如C++转换到Python)以及单元测试代码生成等,实验结果表明,Self-Debug方法在代码生成领域达到了SOTA性能,相比先前的基线方法性能提升了约2~3%。
一、引言
自从ChatGPT爆火以来,鉴于其在代码生成领域的亮眼表现,很多程序员已经开始从原本的“面向对象编程”逐渐转变为“面向ChatGPT编程”,尤其是当遇到一些陌生的编程场景时,使用ChatGPT来辅助进行编程可以显著提升程序员的工作效率。但是如果想完全依靠LLMs来完成一个具体的编程任务,难度还是相当大的。因为人类程序员也无法保证自己一次性写好的代码不出问题。先前使用深度学习方法来生成代码的常用做法是先让模型根据用户输入的需求采样多个代码版本,然后通过重排序等技术从多个候选代码中选取最佳的代码。进入大模型时代,用户通过与LLMs以对话的形式来产生代码,但是基于生成式的模型都不可避免的含有错误内容,想要对模型进行修复就必须进行额外的微调训练,这势必会带来高昂的修复成本。
受近来LLMs中常见的In-Context Learning等技术启发,本文作者想到,能否采用一种无需微调模型的方法,仅通过几条精心设计的指令来引导大模型自己发现生成代码中的错误,并进行修改,作者将这一过程称为Self-Debug。Self-Debug底层基于GPT-3家族系列中的code-davinci-002模型,可以实现包括文本到SQL、代码转译等多种代码生成任务,由于其无需使用类似人类反馈式的方法进行指令微调,仅通过自身审视以及根据执行结果来进行自我反馈,大大降低了开发代码生成LLMs的成本。
二、本文方法
下图展示了本文提出的Self-Debug方法的整体流程,总体分为三个步骤,模型首先根据问题表述以及单元测试(部分任务提供)信息来生成代码(step1 code generation)。然后通过执行代码(step2 code execution)和解释代码(step3 code explanation)来共同生成调试反馈信息,当反馈消息表明预测正确或达到最大调试次数时,Self-Debug调试过程终止,当任务没有提供单元测试时,Self-Debug可以仅通过代码解释信息来进行自我调试。
2.1 使用Self-Debug执行Text-to-SQL任务
文本生成SQL任务的目标是根据给定的问题和数据库信息来生成对应的SQL语句,下图展示了一种生成SQL查询的样例。
LLMs会根据已提供的数据库信息和相应的需求来产生SQL语句。
但是如何对SQL语句进行判断和调试呢?由于在SQL场景中,单元测试不可用,因此如何判断生成的SQL语句是否正确极具挑战性。如下图所示,Self-Debug在解决这类问题时会分为三步,第一步是提示LLMs来总结当前需求并推断出该需求所要返回的查询值类型,在这里则需要返回当前SQL查询所涉及的表列数。第二步执行SQL查询并将返回的表再送入模型中以进行代码解释。代码解释会对每个SQL子句进行分析和描述,返回表中包含的列数以及SQL查询的高级含义。
第三步,模型将推断得到的SQL解释和问题描述进行比较,来判断当前生成SQL查询的正确性。反馈信息通常是一句简单的指示语句,例如使用“So the SQL prediction above is wrong. Please fix the SQL”来指示错误,使用“So the SQL prediction above is correct”来表示正确,当模型判断SQL生成正确或者达到最大调试轮数时,Self-Debug过程终止。
2.2 使用Self-Debug执行代码转译任务
对于代码转译任务,其目标是将一种编程语言的代码直接翻译成另一种语言,下面展示了将C++ 代码转换为Python代码的一个示例,任务的输入是一段C++ 代码和附带的单元测试,如下图所示,模型首先生成对应的Python代码,并将预测的Python代码进行单元测试,如果单元测试不通过,才开始使用Self-Debug生成反馈信息。
对于代码转译任务,作者使用TransCoder数据集进行实验,下图为TransCoder数据集提供的输入和输出代码以及二者之间对应的单元测试。
但由于单元测试并不是在所有情况都提供,因此Self-Debug重点对所预测得到的代码生成解释,来引导LLMs进行自我调试,这个调试过程非常类似于“小黄鸭调试”,程序员会将自己所写的代码逐行的向小黄鸭进行解释。通过描述代码实现并将其与问题描述进行比较,人类程序员通常能够在没有额外指导的情况下识别出代码中的错误,本文表明,LLMs也具有类似的能力,特别是在单元测试不可用的情况下。
三、实验效果
本文使用code-davinci-002[1]进行实验,并将最大调试轮数设置为10。作者首先选取了一些专门针对代码生成任务微调的文本模型,例如Graphix-T5和LEVER,由于Spider数据集中包含了超过10K样本的训练数据,作者首先将这些模型在Spider上进行了微调。此外,对于基于提示的方法,作者选取MBR-Exec[2]和Coder Reviewer[3]参与对比实验,这些方法也仅需提示而无需任何额外的训练,实验对比结果如下表所示。
上表左侧展示了本文方法与其他对比方法在文本到SQL生成任务上的对比,由于在该任务中没有提供单元测试,Self-Debug可以将基线方法的生成性能提高2-3%。在上表右侧中展示了本文方法在代码转译任务上的性能表现,在仅通过代码解释进行自我调试时,Self-Debug可以提升2-3%的性能,而当单元测试可用时,单元测试和代码解释同时作用,Self-Debug可以提升高达12%的生成准确率,这表明,高效的利用单元测试可以显著提高LLMs调试代码的性能。
此外,作者对本文方法在不同初始样本数量时的性能进行了消融实验,如上图(a)所示,Self-Debug在8个初始样本时就可以达到82.5%的生成准确率,这与基线方法使用16个样本时的精度相当,证明Self-Debug可以在提升生成准确率的同时提升样本效率。在图(b)中,作者测试了本文方法在不同难度任务上的性能对比,可以看到Self-Debug在困难问题上的性能提升更加明显,提升精度可以达到9%。
四、总结
本文提出了一种称为自我调试(Self-Debug)的大模型代码调试方法,它能够使LLMs在无需人工指令和外部反馈的情况下对所生成的代码片段进行错误识别和修复。这一过程非常类似于人类程序员常使用的“小黄鸭调试法”,Self-Debug可以在多种代码生成任务上得到非常可观的性能增益,同时也可以提高模型的样本效率。Self-Debug的成功也启发我们,可以从人类所擅长的技能中获取灵感,并迁移到LLMs中,使其拥有更强大的语义理解和推理能力,激发出大模型在各种领域中的更大潜能。
参考
[1] M. Chen, J. Tworek, H. Jun, Q. Yuan, H. P. d. O. Pinto, J. Kaplan, H. Edwards, Y. Burda, N. Joseph, G. Brockman, et al. Evaluating large language models trained on code. arXiv
preprint arXiv:2107.03374, 2021
[2] F. Shi, D. Fried, M. Ghazvininejad, L. Zettlemoyer, and S. I. Wang. Natural language to code translation with execution. In Proceedings of the 2022 Conference on Empirical Methods in Natural Language Processing, 2022.
[3] T. Zhang, T. Yu, T. B. Hashimoto, M. Lewis, W.-t. Yih, D. Fried, and S. I. Wang. Coder reviewer reranking for code generation. arXiv preprint arXiv:2211.16490, 2022.
作者:seven_