AI 自动生成代码是一种使用机器学习技术来生成程序代码的方法。通过对大量的程序代码进行训练,机器学习模型可以学习到程序代码的语法和结构,从而能够自动生成符合要求的程序代码。
这种方式极大的提高了研究者的开发效率,特别是在重复性高、逻辑简单的任务中。同时,自动生成的代码还可以减少人为错误的发生,提高代码的可读性和可维护性。
然而,现有的代码生成方法或工具在处理简单需求的场景时表现较好,如行级代码补全和初级的函数级代码生成。但在复杂的函数级代码生成、深入的问题分析和软件系统设计方面,它们的表现尚有不足。
本文中,来自北京大学李戈教授团队的最新研究通过融入规划和合作的方法论,使大型模型在原有基础上能够应对更复杂的需求,并进一步提高代码生成的质量。
总结而言,在论文《Self-planning Code Generation with Large Language Model》中,他们探索了基于规划的代码生成方法,提出一种使用大型语言模型(LLM)进行 self-planning 来生成代码的简洁方案。在多个代码生成数据集上,self-planning 代码生成的性能明显优于直接生成的方法。
在另一篇论文《Self-collaboration Code Generation via ChatGPT》中,该研究提出了一种名为 self-collaboration 框架,其目的是通过合作和交互方法来增强大模型的问题解决能力。与直接利用大模型代码生成相比,self-collaboration 代码生成的相对性能提高了 29.9%-47.1%,达到了最先进的性能,甚至超越了 GPT-4。
接下来我们看看每项研究的具体内容:
论文 1:Self-planning Code Generation with Large Language Model
尽管大型语言模型在代码生成方面展现了令人瞩目的能力,在解决人类提供的复杂意图(intent)时仍面临挑战。人类通常通过规划来分解复杂问题,并在实施前制定解决方案。因此,作者将规划引入到代码生成中,以帮助模型更好地理解复杂意图并降低问题解决的难度。
论文地址:https://arxiv.org/pdf/2303.06689.pdf
本文提出了一种结合大型语言模型的自我规划(self-planning)代码生成方法,它由两个阶段组成,即规划阶段和实施阶段。具体而言,在规划阶段,语言模型从 intent 出发,结合上下文学习(Incontext Learning),规划出解决步骤。然后进入实施阶段,模型在解决步骤的指导下逐步地生成代码。
Self-planning 代码生成在多个代码生成数据集上进行了严格的评估,结果表明,与直接利用语言模型进行代码生成的方法相比,Self-planning 具有明显的优势,性能提升显著,凸显了 self-planning 在代码生成任务中的重要价值。
下面具体介绍一下 self-planning 代码生成方法。
Self-planning 代码生成
在规划阶段,利用 LLM 的能力,通过 Incontext Learning 进行自我规划。给定一个提示,由
元组串联而成,,其中 表示人类的 intent,
表示 plan,表示两者的串联。plan 是对子问题的调度,它从 intent 中抽象和分解出来,intent 被设定为
。在推理过程中,测试时 intent 将被添加在提示之后,将被送入 LLMs ,后者将试图为新的 intent 做规划,从而得到测试时的 plan。
请注意,这里 是一个相当小的数字,意味着仅通过注释几个演示规划的例子就可以实现自我规划。
在实施阶段,将 plan附加到 intent 上,作为模型 的输入,得到最终代码 。
以上两个阶段可以被形式化为下列公式:
通过条件独立假设进一步简化
,因此:
下面通过演示示例进一步理解这个过程。
在 planning 阶段,人类提供了一个 intent,即 “找到第 n 个斐波那契数,并且它也是素数”。可以看出 LLM 能够从 intent 中抽象出两个子问题,即 “生成斐波那契数列” 和 “确定一个数字是否为素数”,并规划四个步骤来组合解决这些子问题。
然后进入实施阶段,作者将 plan 附加到 intent 中,然后喂给 LLM。LLM 在步骤的导航下生成代码,而且它还能够将 “判断是否是素数” 包装成一个子函数并正确调用它。
如果将这个 intent 直接交给 LLM 生成代码,LLM 无法理解 intent 是多个问题的组合;它知道要写一些关于 “素数” 和 “斐波那契” 的内容,但实际上它生成了一些混乱的代码,即它列举了前五个正确的样本,然后计算斐波那契数,完全忽略了检查是否是素数的要求。
实验结果
在代码测试通过率指标下,相比与直接生成,self-planning 达到了 10.9% 到 26.7% 的相对提升。相比之下,CoT 的提升没有 self-planning 大,这里CoT 的定义是具体的推理步骤,CoT 的抽象程度与被视为人类思维抽象的代码相当,所以生成一个准确和足够详细的 CoT 的难度几乎与直接生成代码的难度相当。
最后作者通过提供 ground-truth code 来生成了一些 ground-truth planning,使用 ground-truth planning 来生成代码的相对提升超过 30%,这个结果大约是 self-planning 的一个上限(实际上是偏小的),但也说明了 planning 的方法是非常有潜力的。
为了验证 self-planning 方法的有效性,作者进行了定性评价的案例研究。如下图三个案例证明了 self-planning 和直接代码生成的性能。
在案例 1 中,LLM 的任务是 “给定一个整数数组 nums,找到 nums 的任何非空子数组的最小和”。LLM 直接生成的代码只考虑了子数组中的一个子集,而 self-planning 代码生成则确保没有一个子集被忽略。
在案例 2 中,LLM 的任务是 “接收一个整数作为输入并返回这个整数的特殊阶乘.”,利用 LLM 直接生成的代码,只是以递归的方式实现了标准阶乘,忽略了特殊阶乘的定义。相反,self-planning 代码生成通过使用子函数来实现标准阶乘,然后调用这个子函数来构造特殊阶乘。
在案例 3 中,LLM 的任务是 “给定三角形三条边的长度,返回该三角形是否为直角三角形”。self-planning 代码生成更全面,因为它通过应用勾股定理来计算不同边的斜边,而直接生成代码只考虑单一判断直角三角形的情况。此外,此方法还测试了了输入的边是否形成了一个三角形。
总之,在这些案例中,直接生成代码方法只解决了用户 intent 的一个有限方面,这往往会导致生成不正确的代码。相比之下,self-planning 的代码生成方法首先将 intent 转换为 plan,然后系统地解决 plan 的每一个解决步骤,降低了代码生成的复杂性,往往能够产生更全面的细致的程序。
结论
本文研究了基于规划的代码生成方法,并提出了一种使用大型语言模型(LLM)进行 self-planning 来生成代码的简洁方案。在多个代码生成数据集上,self-planning 代码生成的性能明显优于直接生成的方法。总之,规划是一种非常有潜力的处理复杂性的方法。
论文 2:Self-collaboration Code Generation via ChatGPT
大型语言模型(LLMs)在多项任务上的表现已经非常接近人类的水平,是否能让大型语言模型像人类一样组成团队合作完成更加复杂的任务?第二篇文章介绍了一种 self-collaboration 的技术,通过角色指令让多个大型语言模型扮演不同的角色组成软件开发团队,在无需人类参与的情况下以合作和交互的方式完成代码生成任务。
论文地址:https://arxiv.org/pdf/2304.07590.pdf
代码生成被广泛认为是提高软件开发自动化和最终质量的关键技术。然而,现有的代码生成方法通常集中在软件开发过程的单个阶段(即编码阶段),而没有考虑对降低复杂性和确保质量保证至关重要的其他阶段。软件开发中多个阶段的组织和实施需要团队合作。
为此,本文提出了一种使用大型语言模型 (简称为:大模型) 进行代码生成的 self-collaboration 框架。具体来说,大模型通过角色指令扮演不同的角色组成团队,在无需人参与的情况下以合作和交互的方式处理代码生成任务。根据 self-collaboration 框架,作者组建了一个由三位 ChatGPT 扮演角色(分析师、程序员和测试员)组成的初等团队,分别负责软件开发的分析、编码和测试阶段。实验结果表明,与直接利用大模型代码生成相比,self-collaboration 代码生成的相对性能提高了 29.9%-47.1%,达到了最先进的性能,甚至超越了 GPT-4。
本文所提的方法通过将软件开发的多个阶段与代码生成结合,旨在提高最终代码的质量和可维护性。通过利用 ChatGPT 等 LLMs 的潜力,可以为模型间合作和交互提供更强大的支持,从而促进虚拟团队在处理复杂软件开发任务方面的成功。这种多阶段、模型堆叠的自合作框架为自动代码生成提供了一种新的、更高效的方法,有助于推动软件开发领域的创新和进步。此外,这项工作还可以作为未来研究各个领域的自我合作方法以及开发更先进、更专业的虚拟团队来处理更复杂任务的基础。
下面具体介绍一下 Self-collaboration 框架以及在该框架基础上按照软件开发方法论组建虚拟团队的实例。
Self-collaboration 框架
给定需求,利用大模型执行 Self-collaboration 以生成输出 y。该任务定义为。Self-collaboration 框架由两部分组成:分工和合作。
在分工部分,作者运用先验知识将复杂任务分解为一系列阶段 并构建一些不同的角色,这些角色基于大模型和角色指令。每个角色 负责一个或多个阶段 。
众所周知,大模型对上下文非常敏感,因为它们在训练时,被要求根据前面的文字预测后续文字。因此,一种广泛使用的方式是通过指令或提示来控制大模型的生成。作者采用特定类型的指令为大模型分配身份和职责,被称为角色指令。具体来说,作者要求大模型扮演与其职责紧密相关的特定角色并且传达这个角色应该执行的详细任务。
使用角色指令的优势在于它们仅需要在交互开始时被提供一次。在随后的交互中,传达的只是意图,而不是指令和意图的组合。因此,角色指令提升了后续沟通合作的整体效率和清晰度。
在合作部分,作者关注于促进在 self-collaboration 框架内承担不同角色的大模型之间的有效交互。每个大模型在其指定角色指令的指导下,通履行其分配的职责为整体任务做出贡献。随着阶段的进展,大模型与其他大模型交流他们的输出,交互信息并输出。
利用角色指令,可以有效控制大模型的输出格式。结合语言模型的基础方面,这可以初步建立大模型之间的通信。
合作部分可以形式化为:
其中是阶段的输出,表示 前提阶段的输出,表示对应的角色。请注意,如果阶段
之间的关系不是线性关系,self-collaboration 框架可以并行化。计算被视为合作,其中角色 与每个前面阶段的角色合作生成。输出随着阶段 的进展迭代更新:
其中 是一个更新函数。 完成后,得到最终输出。为了促进有效合作,作者建立了一个消息共享池,每个角色从中获取所需的信息以完成各自的任务 。算法 1 给出了 self-collaboration 框架的完整算法。
实例化
为了实例化 Self-collaboration 框架,作者将软件开发方法论中的经典瀑布模型引入到 Self-collaboration 代码生成中。根据瀑布模型,软件开发是一个多阶段过程,其中一系列阶段依次进行。作者选择了三个阶段应用于代码生成,分别是:分析、编码和测试阶段。该过程从一个阶段流向下一个阶段,如果发现问题,则返回到上一个阶段进行修改。为此,作者建立了一个初等的三人团队来生成代码,由分析师、程序员和测试人员组成,负责分析、编码和测试阶段,如图 1(右)所示。具体来说,作者使用 ChatGPT 的角色指令来扮演以下角色:
分析师:分析师的目标是制定高层次的 plan 并专注于指导程序员编写程序,而不是深入研究实现细节。给定需求,分析师将分解为几个易于解决的子任务,以方便程序员直接实施,并制定概述实施主要步骤的 plan。
程序员:作为该团队的核心角色,程序员将在整个开发过程中接收来自分析师的 plan 或来自测试人员的测试报告。因此,作者通过角色说明将两项主要职责分配给程序员:1. 编写满足指定要求的代码,遵守分析师提供的 plan。2. 修复或细化代码,考虑到测试人员反馈的测试报告反馈。编码器角色指令的详细信息如图 2 所示。
测试员:测试人员获取程序员编写的代码,随后记录包含各个方面的测试报告,例如功能性、可读性和可维护性。与直接生成测试用例相比,作者认为生成测试报告更符合语言模型的倾向,无论是交流的输入端还是输出端。
作者仅在阶段编码时更新输出,并且此开发过程在测试人员确认 满足要求时结束。
实验结果
作者将 self-collaboration 代码生成与各种最先进(SOTA)方法进行比较,实验结果表明,self-collaboration 框架显著提高了基础大模型的性能。值得注意的是,即使是一个简单的三人团队(包括分析师、程序员和测试员),基于 ChatGPT (GPT-3.5) 的 self-collaboration 代码生成在四个代码生成基准测试中也取得了最佳性能,甚至超过了 GPT-4。与 ChatGPT (GPT-3.5) 相比,self-collaboration 框架提供的改进是巨大的,相对增幅从 29.9% 到 34.6% 不等。
值得注意的是,self-collaboration 代码生成对与扩展测试用例相关的数据集(即 HumanEval-ET 和 MBPP-ET)产生了更显著的改进。这表明 self-collaboration 可以有效地帮助基础大模型生成更高质量的代码。这种增强可能归因于合作团队可以考虑更广泛的边界条件和解决常见错误的能力。考虑到基础大模型本身的差距,将 self-collaboration 框架应用于更强大的模型,例如 GPT-4,将产生更好的结果。
作者进一步研究了仅使用自然语言描述的代码生成,这种设置更贴近实际的软件开发。在此设置下,作者比较了由 self-collaboration 框架实例化的初等团队中每个 ChatGPT 角色的表现,如表 2 所示。
实验结果表明,与仅使用程序员角色相比,无论是二位角色还是三位角色组建的团队,性能都有显著提高。程序员 – 分析师 – 测试员团队在 HumanEval 和 HumanEval-ET 基准测试中取得了最好的成绩,相对改进分别为 40.8% 和 47.1%。相比之下,编码器 – 测试员团队在 MBPP 和 MBPP-ET 基准测试中获得了最高性能,相对改进分别为 36.7% 和 39.4%。分析师在 MBPP 和 MBPP-ET 基准上的表现不佳可能是由于 MBPP 的要求相对简单,所以对规划较少(但是随着问题的复杂化,规划是不可或缺的一部分)。此外,MBPP 中各种任务的大量测试用例偏离了人类典型的书写习惯和推理过程,例如程序返回不常用的数据格式而而没有任何自然语言提示。因此,作者认为应该定制特定任务的团队以实现最佳结果。
此外,作者展示了一个 self-collaboration 代码生成示例,如图 3 所示。
1. 分析师进行全面分析并制定 plan 以解决整体需求。对于这个需求,分析师首先将其拆分为几个易于解决的子任务,然后根据子任务给出一些高层次的 plan。
2. 程序员根据给定的要求以及设计的拆分和高层次 plan 实现代码。显而易见,已实现代码中的每个子模块都与拆分和高层次 plan 几乎一一对应。
3. 测试员为实现的代码编写详细的测试报告,找出其中的错误。在这份测试报告中,测试人员指出所实现的代码可能会导致从列表中删除重复元素,从而可能导致某些边缘测试用例失败。因此,建议从实现的代码中删除行 “lst = list (set (lst))”。
4. 程序员随后根据测试报告中提供的反馈完善了代码。在编码器提供的修改后的代码中,整合了测试报告中的建议,并同时删除了 “lst = list (set (lst))” 行。
5. 测试员评估修改后的代码,确认没有任何问题,至此代码生成过程结束。在最后一次交互中,测试员确认修改后的代码已经通过所有测试,满足要求。
总之,self-collaboration 框架在代码生成任务中表现出显著的性能提升,与单一角色相比,多角色团队能够更有效地处理各种问题和挑战。这种方法为自然语言处理和代码生成领域提供了新的研究方向,值得进一步探讨和优化。未来的工作可能包括对更多角色和更强大模型的探索,以及将 self-collaboration 框架应用于其他自然语言处理任务。
结论
在本文中,作者提出了一种 self-collaboration 框架,其目的是通过合作和交互方法来增强大模型的问题解决能力。具体而言,作者探索了 ChatGPT 在促进基于团队的代码生成和合作方面的软件开发过程中的潜力。为此,作者组建了一个由三个不同的 ChatGPT 角色组成的初等团队,目的是全面解决代码生成任务。为了评估 self-collaboration 框架的有效性和泛化性能,作者针对各种代码生成基准进行了广泛实验。实验结果提供了大量证据支持 self-collaboration 框架的有效性和普适性。作者认为,使模型能够组建自己的团队并合作完成复杂任务是实现人工通用智能(AGI)的关键一步。