当大模型开始规划合作,一个模型打造软件开发团队,代码生成性能狂升
机器之心 2023-05-11 04:32 发表于北京
机器之心专栏
机器之心编辑部
近年来,代码生成在学术界和工业界都取得了很大进展,特别是大型语言模型(LLM)展示了令人印象深刻的代码生成能力,吸引了各个领域的关注。本文介绍了两篇关于代码生成的研究。
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 所示。
测试员:测试人员获取程序员编写的代码,随后记录包含各个方面的测试报告,例如功能性、可读性和可维护性。与直接生成测试用例相比,作者认为生成测试报告更符合语言模型的倾向,无论是交流的输入端还是输出端。
作者仅在阶段编码时更新输出,并且此开发过程在测试人员确认 满足要求时结束。