神经代码智能——利用深度学习理解、生成和优化代码——对整个社会具有巨大的变革潜力。在自然语言与程序设计语言之间架起桥梁的这一领域,过去几年里已经吸引了两个研究社区内研究者的重大关注。本综述提出了一个系统性和按时间顺序的代码智能进展回顾,涵盖了50多个代表性模型及其变体、20多类任务,以及超过680项相关工作的广泛覆盖。我们遵循历史进程,追溯不同研究阶段(例如,从使用循环神经网络建模代码到大型语言模型时代)的范式转变。同时,我们突出了不同阶段中模型、任务和评估的主要技术转变。对于应用,我们也观察到一个共同演化的转变。它从最初努力解决特定场景,通过在其快速扩展期间探索多样化的任务数组,到目前专注于解决越来越复杂和多样化的实际挑战。基于我们对发展轨迹的考察,我们进一步调查了代码智能与更广泛的机器智能之间的新兴协同作用,揭示了跨领域机会,并阐明了代码智能在各个领域的重大影响。最后,我们深入探讨了这一领域相关的机会和挑战,并阐明了我们对最有前途的研究方向的见解。与本综述相关的一个持续动态更新的项目和资源已经在https://github.com/QiushiSun/NCISurvey 发布。
代码是人类创造的一种优雅的语言,通过高度的抽象替代了自然语言(NL)的多样形式[1]。作为人类与机器之间的传输管道,它最终被转化为特定的程序1,代替人类努力完成各种任务,其特点包括精确性、逻辑性、模块化和可激发性。与“大代码”[2, 3]的可用性快速融合的深度学习技术引领了神经代码智能的出现。这一领域将神经方法应用于理解、生成和操作代码,已经获得了研究社区的重大关注。图1展示了近年来累积的出版统计数据2,展示了对这一领域的日益增长的兴趣和重大努力。值得注意的是,这一领域超越了学科界限,跨越了自然语言处理(NLP)[4]、软件工程(SE)[5]、机器人学[6]等领域。此外,代码的独特二元性,将人类可读的语义与可执行性结合在一起,使得这一领域的研究成为人工智能与现实世界之间的关键桥梁,为通向人工通用智能[7]的道路奠定了基石。这些研究的核心是“软件自然性”[8]的基础概念,它认为编程语言(PL),很像人类语言,其特点是可预测和重复的模式,可以有效地建模。从宏观角度来看,这些人造语言的处理技术的进步在很大程度上反映了在NLP[9]中观察到的演变。
具体来说,在一个以统计[10, 11, 12]和概率[13]建模为特征的简短初始时期之后,神经代码智能的学习范式已经从最早的词嵌入技术过渡到大型语言模型(LLMs),大致分为三个主要的演化阶段:
代码的神经语言模型。这个时期见证了将深度学习应用于代码处理的早期但富有成果的努力。这一时期设计的方法主要依赖于发展完善的循环[14]或卷积[15]结构来建模代码。值得注意的是,它们不仅利用了代码的文本信息,还巧妙地将从代码结构(如抽象语法树ASTs)中提取的结构信息整合到建模过程中[16, 17],与神经语义解析的原则紧密对齐[18, 19, 20]。 同时,由于代码片段可以表示为连续向量,这一时期发展的技术也被称为代码嵌入[21]。最具代表性的技术,如code2vec[22]和code2seq[23],通过将ASTs的路径嵌入到向量空间中,捕获了代码的语义和结构信息,使得神经方法能够应用于多种场景。
代码预训练模型(CodePTMs)。具有多层Transformer架构[26]的预训练语言模型[24, 25]建立了一个“预训练”和“微调”学习范式[27]。在此之后,出现了许多关于如何构建CodePTMs的研究。这些模型,如CodeBERT[28]、CodeT5[29]和PLBART[30]等,长期以来一直占据着代码智能主流方法的地位,并引发了研究兴趣的激增——在2020年CodeBERT发布后,图1中可以观察到arXiv论文的急剧增加。在预训练阶段,它们从大量GitHub代码数据中学习通用的上下文感知表示,以及代码的结构信息(例如,ASTs)。随后,它们在特定于任务的代码数据或NL-PL对上进行微调,显著提高了各种代码相关任务的性能。这种方法标志着与以前的学习范式的转变,其中CodePTMs不再需要为每个任务单独建模,而是通过在相对较小的标注数据集上微调来适应不同的场景。
代码的大型语言模型(CodeLLMs)。最近的研究表明,通过增加其参数或训练数据量[31, 32],可以持续提高模型在下游任务上的表现。继GPT-3[33]和PaLM[34]等通用LLM在学术界和工业界的成功之后,像Codex[36]这样的模型在代码智能领域掀起了新的研究浪潮——在2022年末ChatGPT-3首次亮相后,图1中可以观察到相关论文的显著增加。这一阶段还见证了学习范式从特定任务的微调转变为提示[37]和上下文中学习[38],以及将代码智能的应用从仅限于代码相关任务扩展到更广泛的实际场景。
意识到代码智能的发展
显著反映在为代码设计的语言模型的演变中,我们在图2中呈现了代表性工作的时间顺序总结,概述了神经代码智能发展轨迹。它为本文提供了一个框架,概述了该领域内技术进步的概览。在这一时间线的基础上,我们采用了一种新的视角,通过模型、应用、评估和更多方面的范式转变,探索代码智能中这些令人兴奋的进展。我们彻底调查了文献,并提炼了各个时代研究之间的关键发现、技术和相互联系。此外,我们扩大了视野,探索了其他领域与代码智能的整合,讨论了代码生成如何协助机器推理、代码训练如何增强模型的数学能力,以及代码如何作为一种媒介提供了解决典型NLP任务的新方法。我们还探索了广泛的现实世界跨领域应用,包括编码助手、数据科学、自治代理和AI4science。
与本综述相关的GitHub项目正在积极维护中,地址为https://github.com/QiushiSun/NCISurvey,其中包含了构建本文所用的所有资源,以及全面的阅读列表以帮助读者进一步探索。我们希望这将有助于该领域的持续发展。
本综述的后续部分组织如下。第2节首先回顾了基础知识。然后,我们检查了使用神经语言模型处理代码的经典且关键方法,以及对典型代码相关任务的介绍。第3节深入探讨了在预训练和微调范式内代码智能的演变,提供了这一时期技术的全面回顾和讨论,以及它们对未来研究的影响。第4节探讨了在大型语言模型时代的研究进展,同时回顾了在NL2Code方面的进展,并对代表性模型和基准进行了彻底讨论。第5节调查了代码智能与机器智能其他领域之间的协同作用。第6节讨论了代码智能在现实世界场景中的应用,展示了其实际效用。第7节从模型架构和实际应用的双重视角,进行了开放性问题的双向讨论,并分享了我们认为值得未来研究方向。最后,第8节总结了本文的洞见和发现。
代码大模型
近年来,公共代码库中大量源代码的可用性显著促进了深度学习技术在源代码上的应用[3]。在“软件自然性”[8]的概念下,为处理文本而设计的神经语言模型可以自然地应用于代码。结合软件工程对自动化代码处理不断演变的需求,神经代码智能经历了繁荣的发展。通过将代码片段概念化为语言序列,序列神经架构,如LSTM[14],自然适用于代码理解和生成[39, 40]。然而,必须认识到,与自然语言句子不同,程序包含显式和复杂的结构,这为建模代码引入了更多的机会和可能性。随后,出现了代码嵌入,可以定义为代表代码中固有概念的数值序列。这一发展对未来代码智能研究产生了开创性和长远影响。
在本节中,我们首先向读者提供有关代码结构的初步信息,随后回顾了一些基于它的经典建模方法。随后,我们介绍了一系列经典、重要且持续探索的代码相关任务。
继预训练语言模型[27]在NLP领域取得显著成功之后,代码智能社区迅速整合了它们的架构和学习范式,导致了CodePTMs的大量增长。继神经语言建模时代之后,这标志着代码智能的一个繁荣时期,它保留了代码结构洞察力的同时,纳入了基于变换器的模型。代码语言模型的构建经历了一个主要的范式转变,其特点如下:
架构:多层变换器[176]已成为模型主干的实际选择,摆脱了为每个任务从头开始构建模型或依赖于定制特征工程的做法。
训练数据:预训练主要在从GitHub[177]收集的大量未标记数据上进行,较小部分的标记数据通常用于使模型适应各种下游任务。
这一阶段的发展反映在图3中显示的三个主要分支上。在本节中,我们将首先对代表性CodePTMs及其变体进行系统回顾,随后深入讨论它们的其他方面。 (1) 将预训练的变换器应用于代码代表了一项开创性的举措,有效地解决了以前遇到的不得不从头开始为每个任务建模的困境。此外,它证明了在大量未标记代码的语料库上进行预训练,随后进行特定任务的微调,可以显著提高所有下游任务的性能。(2) 第2.1节提到的各种代码特征在预训练过程中被利用,以增强模型对代码结构的感知。然而,这种结构的显式建模并非没有代价;由于显式结构建模导致模型内部机制的改变,使CodePTMs难以在不同任务之间泛化。(3) 利用代码结构为解释和分析CodePTMs提供了一个额外的视角。与它们的自然语言对应物相比,研究人员越来越意识到利用这些结构来分析模型行为。随着我们进入大型语言模型的时代,这样的研究仍处于初级阶段[254, 255]。
大型语言模型(LLMs)时代:新的前沿
代码智能领域已经因大型语言模型(LLMs)[256, 257, 258]的迅速进步而发生了显著变化,这标志着一个新时代的到来,并带来了新的机会[259]。除了展现出新兴能力[260]之外,典型的LLMs,如PaLM [34]、LaMDA [261]和BLOOM [262],天生就具备了编程能力。这种内在能力源自于它们的预训练数据,通常是包含大量代码语料库的多样化混合物。例如,常用的数据集如ROOTS [263]和Pile [213]语料库包含了大量的代码数据;Pile包含了800GB中的95.16GB GitHub数据,而ROOTS包含了1.6TB中的163GB。这种大量包含代码的做法使得这些模型能够学习和理解编程概念、语法和语义,从而使它们具备了在各种编程语言和任务中生成和解释代码的能力。
机器智能中的协同作用
继我们围绕代码生成和理解进行了详细的探索之后,在本节中,我们将深入探讨与机器智能其他方面的一些协同作用。具体来说,我们将从三个角度进行讨论:基于代码生成的新推理范式、通过代码训练增强的数学能力,以及通过代码扩展的语言模型的多维能力。
要点总结:(1) 代码生成与符号求解器与LLM推理的融合代表了解决数值任务的一次突破性转变。通过使用可执行代码替代自然语言作为推理的媒介,它不仅克服了持续存在的计算限制,还增强了模型的可解释性和泛化能力。(2) 尽管理论基础尚未建立,但通过代码训练增强LLM的数学能力的能力已经通过实证显示,并且逐渐在社区内被接受。(3) 采用代码作为中间表示可以显著提高处理多样化NLP任务的效率和多样性。通过超越传统的基于文本的处理,以代码为中心的方法,通过构建统一的模式,可以处理先前方法难以解决的复杂和多样化的输入和输出形式。
现实世界应用
在完成对模型、算法和数据的回顾之后,我们将焦点转向讨论它们的现实世界应用和当前发展。起初,我们的讨论围绕代码处理和结构化数据,突出两个主要领域:(1) 在软件工程(SE)中直接应用代码的语言模型,旨在桥接NLP和SE社区之间的差距[5];(2) 探索使用CodeLLMs增强数据科学研究。随后,我们深入探讨混合场景,包括(1) 通过应用代码智能构建代理,以及(2) 利用代码智能支持AI4Science研究的新兴领域。
结论
在本文中,我们提供了代码智能整个演化轨迹的系统综述,从源代码上深度神经网络的初步应用到LLM时代的突破,进行了全面的考察。在这一过程中,我们深入探讨了不同时期研究之间的相互联系,围绕模型、任务和应用的范式转变进行了详细的讨论和分析。此外,我们还探索了代码学习与机器智能其他方面的协同作用,以及现实世界中长期存在和新兴的应用。记住我们见证的发展路径和从我们讨论中获得的洞察,我们还确定了代码智能未来研究的几个有前景的方向。鉴于语言模型的同时进步和软件开发需求的不断演变,我们相信这一领域在未来几年将继续繁荣发展。我们希望本综述论文中提供的文献回顾、讨论、经验和资源将促进社区未来的研究。