迈向更高层次智能化开发之路:写给大模型的2023总结

迈向更高层次智能化开发之路:写给大模型的2023总结_第1张图片

2024新年快乐!

迈向更高层次智能化开发之路:写给大模型的2023总结_第2张图片

由ChatGPT引爆的大模型浪潮从2023年年头热到了年尾,各种学术和行业技术大会的话题几乎都绕不开“大模型”。在软件工程领域,“大模型”话题也是热得发烫,各种代码大模型层出不穷,相关论文如雨后春笋般喷涌而出。街头巷尾、线上线下都在热议大模型是不是要颠覆软件工程了,CTO们和研发效能部都在思考如何回答老板诸如“开发人员能减少百分之几十”、“研发效能能有几倍提升”这样的灵魂拷问。

大模型为我们开启了一个生成式人工智能的大时代,由此也全面打开了软件智能化开发的大门。虽然在数据挖掘、机器学习等智能化技术的加持下,“软件智能化开发”的口号早在十年前甚至更早就被喊出来了,但是软件产业中关于“智能化开发”的广泛感受应该是自大模型特别是ChatGPT横空出世之后才有的。软件工程学术圈中关注于“智能化开发”的团队应该基本上都在拥抱大模型了,我们团队也不例外。在度过最初的迷茫之后,我们对大模型的到来感到兴奋,因为它打开了我们关于“智能化开发”的想象空间。很多原来做不到的(例如函数/方法级代码生成)现在做到了,很多原来不敢想的(例如生成式软件开发)现在可以想了。

热热闹闹的2023年就要过去了,这个热闹有大模型很大的功劳,因此我感觉值得为它写一份年终总结,而主题就是如何迈向更高层次的智能化开发。经过这一年的探索,大模型的软件开发能力已经被人所熟知。在代码级任务(特别是通用领域)上,大模型表现出了全方位的能力,不仅可以生成和补全代码,而且还可以理解、修复和重构代码;在软件测试任务上,大模型在测试用例自动生成特别是单元测试用例自动生成上取得了优异的表现;在知识问答方面,大模型丰富的计算机和软件专业知识使得“全栈工程师”的门槛似乎也不那么高了。由于以上这几个方面的原因,大模型作为一种高效的开发助手的价值已经毋庸置疑了。全面装备大模型助手后,20%-30%的研发效能提升应该是可以预期的。本文希望探讨的是如何在此基础上进一步实现更高层次上的智能化开发支持,例如模块甚至应用级别的生成式开发以及复杂的软件维护任务支持等。为此,本文将谈一下关于大模型软件开发能力现状的几点认识,然后围绕更高层次上的智能化开发支持这一愿景谈几点建议。

需要注意的是,随着大模型的发展,以API和能力(包括机器人等物理世界行动能力)编排为主、融合大模型内容生成能力的新型智能化应用生态也在快速发展,这类应用的发展方向应该是面向最终用户的低代码(零代码)开发以及自然语言编程。而本文主要关注于由专业开发人员参与的企业软件开发,这类开发在未来几十年应该还是会长期存在,从而为各种丰富的智能化应用场景提供专业的信息化基础设施。

迈向更高层次智能化开发之路:写给大模型的2023总结_第3张图片

01 几点认识

迈向更高层次智能化开发之路:写给大模型的2023总结_第4张图片

4月初写过一篇公众号文章《智能化时代的软件工程:拥抱大模型的正确姿势》,其中对于大模型的软件开发能力谈了四个可能的问题,包括:软件开发的规模和复杂性可能会从人机两个方面限制大模型的能力;大模型可能缺少抽象思维能力,同时在精确性上存在不足;软件需求和设计中存在大量难以捕捉的“暗知识”;大模型对于复杂软件系统的长期维护支持能力存疑。如今大半年过去了,这几个观点自以为还是总体上合理的。在此基础上,结合这大半年的一些新的思考和理解再谈几点认识。

01

软件设计是一道迈不过去的槛

迈向更高层次智能化开发之路:写给大模型的2023总结_第5张图片

软件工程经典著作告诉我们,软件开发是一个逐步精化的过程,从初识需求开始不断通过“what”到“how”的转换逐步细化解决方案,直至得到最终的代码实现。这其中包含了我们一般意义上的需求分析和软件设计两大阶段。但事实上,需求分析也是一种设计过程,只不过在高层需求分析时考虑的更多是如何根据上一层目标向人、流程、设备以及计算机软硬件等各种系统元素分配职责;而到了软件设计阶段则主要关注于如何确定软件的组成单元(组件、模块等)、各自的职责以及相互之间的关系。此外,现代软件开发十分强调结构化思维,即:以分解加抽象的基本思想为指导、以模块化设计为手段应对软件的复杂性并应对长期演化的需要。虽然结构化方法似乎是个老古董了,但后续的面向对象开发、基于组件的开发以及基于微服务的开发等更新的开发方法其实都在不断强化这种结构化思维。

那么大模型卓越的代码生成能力是否能让我们从需求出发、跳过设计直达软件开发的最终产物—代码呢?从目前的情况看,这个问题的答案大概率应该是“否”,原因包括以下几点。首先,即使目前最乐观的估计也承认开发人员还是要以“代码审核员”的身份帮大模型把关以确保代码的正确性(顺便接过“背锅”的责任),如果没有良好的结构化设计作保障,开发人员估计也很难分工合作来理解代码并作出审核结论(试想开发人员如何理解一个长达数万或数十万行代码且全无模块化设计的模块)。其次,大多数软件都需要充分考虑长期演化的需要,好的设计可以让软件的修改尽量局部化并控制其影响范围(试想一个平稳运行已久的软件如果让大模型重新生成一遍是否还能平稳运行)。最后,软件设计还需要确保系统满足性能、可靠性等多方面的非功能性质量要求(特别是对于分布式系统),这些主要取决于设计方案而非实现代码的质量。

02

当前大模型在软件设计能力上

还比较弱

迈向更高层次智能化开发之路:写给大模型的2023总结_第6张图片

大模型到目前为止很大程度上还是一种黑盒的存在,我们无法准确知晓它各方面的实际能力,但我们还是可以从多个方面侧面揣摩一番。

首先,软件需求和设计中存在大量难以捕捉的“暗知识”。这个观点在4月初的文章中其实已经提过了。需求分析和软件设计过程中存在大量的决策,每一个决策所涉及的知识包括目标、约束、候选项、权衡决策依据及结果等。这些一般都不会完整和规范记录。即使有一些需求和设计知识存在文档记录,通常也很难与代码建立精确的映射与关联。在这种情况下,我们很难收集足够多关于需求分析和软件设计决策的数据供大模型学习和训练。

其次,大模型平面化的代码学习方式使其难以学习到抽象的软件设计知识。大模型的代码生成能力建立在基于大量代码的预训练(通过预测下一个token)以及有监督微调的基础上。代码数据所提供的信息是平面化的(缺少软件抽象),并且仅反映最终结果(缺少决策过程),因此不足以支撑大模型学习到抽象的软件设计知识。那么大模型能否通过“阅读”大量的代码“领悟”到代码背后的抽象设计呢?我感觉很难,原因有二。第一,有经验的开发人员很多时候也难以仅凭借代码悟透背后的设计原理和思考,否则就不会发生那么多看不懂代码四处求助甚至寻找原作者的情况(华为的同事跟我讲过一个这方面的故事)。第二,大模型以token及其关联关系为中心的学习方式不足以使其捕捉到复杂的设计结构知识。虽然大模型在各种文本生成任务上表现出了一定的“模式”学习能力,但可能主要还是体现在token之间的关联上,而软件设计结构可能更加复杂和立体(例如多个模块的职责分配与协作关系、一些隐藏的横切设计影响等)。

最后,从目前业界专家的实践探索来看,大模型扮演的更多仍然是原子任务编码实现的角色。从一些业界专家的实践经历看,通过持续的迭代式引导和反馈,大模型可以生成几百行代码左右规模的小应用或模块。进一步还可以将大模型用于更大规模的软件开发中,并实现70%-80%左右的代码生成。看起来大模型表现已经很不错了,但其中的关键在于设计和集成几乎完全都是人在掌控。这类实践的一般过程是:开发人员仔细考虑设计分解并针对每一个局部编码任务求助于大模型并提供所需的上下文信息,在大模型生成代码之后进行检查并提供反馈,并最终将大模型生成的代码集成到完整项目中。在此过程中,开发人员需要按照一种类似于演进式设计的思维逐步推进迭代过程,并判断某个任务到了何种粒度上适合求助大模型(在一些大粒度任务上直接求助大模型可能得到的效果并不好)。由此可见,虽然大模型实现了较高的代码生成比例,但设计规划、上下文信息提取、代码集成都是由人完成的,而大模型更多是完成一个要求明确、信息齐备(不需要再去了解相关需求、设计或更大范围内的代码上下文信息)的独立编程任务。

03

维护型任务是对大模型的

一大考验

迈向更高层次智能化开发之路:写给大模型的2023总结_第7张图片

当前企业面临的开发任务很多都是维护型任务。一方面,很多企业的软件产品已经存在多年,还在不断维护和扩展;另一方面,即使是全新的产品开发,迭代化的开发过程也使得开发人员需要考虑如何在已有的实现基础上进行演进式开发。从任务类型看,一般企业会认为存在两类任务,即维护已有代码和添加新代码。但即使是所谓的“添加新代码”(例如添加一个新特性),也需要考虑如何将“新代码”嵌入到已有的软件架构和代码代码上下文之中,具体而言就是要在既有的软件设计方案和实现代码基础上确定需要修改和添加代码的地方(可能不止一处)并控制其变更影响(通过变更影响分析和回归测试等),因此很大程度上也是维护型任务。

这种维护型任务是对大模型的一大考验。支持维护型任务意味着大模型需要在理解软件项目已有的业务和技术背景知识的情况下帮助开发人员定位需要修改和添加代码的位置(即传统的特征定位和缺陷定位所关注的)并在相应的位置生成代码。如前所述,大模型擅长完成相对独立的编程任务,但不擅长这种依赖于复杂上下文的开发任务(例如依赖开发人员精心准备每个局部编码任务所需的上下文信息)。随着大模型所支持的提示窗口的扩大,也许我们可以将更多的项目代码和文档作为提示提供给大模型,但大模型可能也很难充分消化吸收,特别是对于代码和文档量巨大的大规模企业软件项目。此外,前面也提到,由于大量需求和设计相关知识的缺失,事实上我们也很难以一种自动化的方式为大模型提供完成维护型任务所需要的业务和技术背景知识。

迈向更高层次智能化开发之路:写给大模型的2023总结_第8张图片

02 一些建议

迈向更高层次智能化开发之路:写给大模型的2023总结_第9张图片

大模型当前的代码生成能力可以用两头弱、中间强来概括。两头弱是指大模型一方面软件设计能力不足,难以帮助开发人员进行软件设计方案的规划和任务分解;另一方面精确性不足,在代码生成的“最后一公里”(即让代码完全满足开发要求)上还需要人工审核和确认。中间强是指大模型擅长在给定明确的局部编码任务及所需上下文信息的情况下生成大致可用(即人工审核后稍加修改即可使用)的代码。此外,大模型在复杂软件项目的维护型任务上存在难以准确获得所需的项目上下文信息的问题。而人类程序员则比较擅长通过多种渠道(阅读代码和文档、开展系统运行试验、组织会议和讨论)获取所需的上下文信息,并进行按需抽象(根据当前任务灵活决定所需要考虑的信息及其抽象化程度)。

当前大模型在软件开发领域的应用状况可以从两个层面去看,即普通程序员和超级个体。对于普通程序员而言,将大模型助手用于软件开发各个环节并按需获得代码推荐和开发知识已经逐渐成为一个普遍的实践。对于超级个体而言,掌握了很强的分析和设计能力的专家型开发者能够在大模型的帮助下成为以一当十的超级程序员和全栈工程师。这也体现了Kent Beck所说的,大模型使得过去的职业技能中90%的价值变为0,但也会让剩下的10%的价值被放大1000倍。随着这样的超级个体的增多,普通程序员的需求量可能会减少。

从技术发展的角度看,学术界和工业界可以在大模型的基础上针对软件智能化开发开展很多研究工作,其出发点是通过更好的工具环境(如IDE)降低超级个体的门槛,使得更多的开发人员能达到或接近超级个体的水平。事实上,学术界和工业界已经在围绕这些方面开展研究和实践探索。例如,通过模型微调、检索增强、提示工程、多Agent机制等手段提高大模型的代码生成能力,探索更加接近真实软件项目开发的代码生成能力评测方法以及项目和代码库(repo)级别的代码生成技术等。这里结合最近的思考再谈一下几个方面的建议。

01

在数字化、知识化积累的基础

上迈向更高层次的智能化开发

迈向更高层次智能化开发之路:写给大模型的2023总结_第10张图片

虽然软件开发帮助其他行业实现数字化,但一直以来软件开发自身的数字化程度和知识化积累做得并不好。软件开发的数字化是指建立软件开发制品及其开发过程的数字化和结构化描述,形成一种面向软件开发及其管理的数字化基础设施,例如:规范执行代码提交(commit)的原子性要求并与上游的特征请求、缺陷报告等开发任务建立关联;建立代码克隆检测和管理体系,及时跟踪代码克隆副本的发展变化情况并及时提供一致性维护等方面的预警和建议;构建软件成分分析及供应链追溯体系,保持对供应链依赖及潜在的安全、法律和维护风险的洞察和预警。而软件开发的知识化则是指沉淀关于需求、设计和编码等不同层面决策过程及其结果的知识描述,例如:收集缺陷案例及其修复方式并添加必要的业务和技术决策解释;建立特定领域软件组件库并添加组件描述。一些企业在数字化和知识化积累不足的情况下期望大模型的降临能一下子提高企业的整体智能化开发水平,这可能是不切实际的。事实上,高质量的数字化和知识化积累可以让大模型学习到许多从平面化的代码数据中学习不到的很多深层次知识,或者通过检索增强等手段将知识与大模型的能力相融合。

02

建立面向软件维护的代码数字

孪生及开发知识共享平台

迈向更高层次智能化开发之路:写给大模型的2023总结_第11张图片

在智慧城市、智能制造、智慧农业等领域中,数字孪生已经不是一个新鲜的概念了。通过将物理世界数字化和可视化,人们可以更好地理解和控制物理世界中的管理对象。软件本身就是数字化的,但由于在代码之上还存在许多复杂的高层抽象知识,因此也需要建立一种描述高层知识同时与代码保持双向映射的代码数字孪生。围绕这一点可以发现当前软件开发实践中有两个极端:一个是MBSE(基于模型的系统工程)方法,其特点是一切皆建模而代码自动生成,因此模型自然成为了一种与代码双向映射的高层抽象表示并且具有严格的语法和语义;另一个是敏捷方法,强调可运行的代码胜过文档,通过频繁迭代和反馈不断适应,高层知识很少被系统性记录和利用。

大模型的到来也许可以让我们期待某种折中的出现,即利用大模型出色的记忆、理解和关联能力构建一种知识增强的代码数字孪生。当前,一些企业已经在开发过程中构建所谓的代码地图(code map),即将静态分析得到的代码单元(如模块、文件/类、函数/方法)及其关系(如调用关系、数据流/控制流关系等)持久化保存并将其用于特征和故障定位、测试用例生成、回归测试范围决策、架构看护等不同任务。事实上,这种代码地图可以被视为最基础的代码数字孪生,在其基础上可以利用大模型以及检索增强、内容理解等手段进一步将相关的数字化积累(如历史上的特征添加和故障修复等方面的代码修改案例)和知识化描述(如开发人员提供的关于代码背后的设计意图的说明文字)融入其中。

这样的一种代码数字孪生事实上也成为了一个软件开发知识共享平台。过去开发人员不愿意写文档和注释,部分原因是价值不明显,例如文档被束之高阁也鲜有更新。但大模型的到来也许会形成一种新的示范效应,即通过各种方式贡献的代码知识能够被大模型充分吸收、利用并造福于其他开发人员。一些业界专家认为,大模型的出现可能会让文档复兴,这一点我是同意的。事实上,对于一些复杂的软件项目而言,大模型能够吸收和沉淀开发人员经过长时间思考后悟出的代码知识并在其他开发人员(甚至包括几个月之后的自己)需要的时候发挥出来从而避免重复思考和重新发明轮子,那就已经善莫大焉了。当然,基于大模型的软件开发知识共享平台还有很多问题和挑战,绝不是建立一个类似wiki的共享平台就足够了。例如,我们需要考虑何种形式(结构化?半结构化?或是无结构?)的知识描述(例如设计意图说明)能够更好被大模型吸收并与代码建立关联、如何让开发知识(例如关于设计决策的描述、代码生成所需的业务和技术上下文)自然融入大模型的代码生成过程等。

03

探索适合软件设计知识学习

的大模型增强方法

迈向更高层次智能化开发之路:写给大模型的2023总结_第12张图片

如前所述,大模型当前对于代码数据的平面化学习方式使其很难学到抽象的软件设计知识。一种可能的解决途径是在折叠和层次化的软件开发数据上进行大模型训练或增强。折叠和层次化是指在平面化的代码数据基础上,在多个不同的设计层次(如组件、模块和类级)上准备抽象的学习数据,例如代码的模块化抽象、模块间关系以及附加的设计描述等。这也有赖于上一条中所提到的开发知识共享平台的作用,例如开发人员对于不同层次上设计决策的解释说明。如果大模型能够学习到不同的层次上的设计精化方法及其决策考虑,那么也许大模型在新的应用开发时也能自顶向下逐层进行设计精化。当然,这其中还有很多值得研究的地方,例如何种高层抽象设计表达(UML图?文本描述?)更有利于大模型进行学习和融合。

迈向更高层次智能化开发之路:写给大模型的2023总结_第13张图片

03 结束语

迈向更高层次智能化开发之路:写给大模型的2023总结_第14张图片

大模型的出现打开了我们关于“智能化开发”的想象空间,也为软件产业提质升级带来了巨大的机会。掌握了很强的分析和设计能力的专家型开发者能够在大模型的帮助下成为以一当十的超级程序员和全栈工程师。为了使更多的开发人员能达到或接近这种超级个体的水平,我们需要考虑如何以大模型为基础迈向更高层次的智能化开发能力。为此,我们需要重视软件设计的作用以及维护型任务所带来的问题和挑战。

对于软件企业而言,应当扎实做好软件开发的数字化和知识化积累,在此基础上利用大模型出色的记忆、理解和关联能力实现更高层次的智能化开发水平。为此,我们需要逐步建立一种描述高层知识同时与代码保持双向映射的代码数字孪生,并使之成为一个软件开发知识共享平台,从而让开发人员通过各种方式贡献的代码知识能够被大模型充分吸收、利用并造福于其他开发人员。同时,我们还需要探索适合软件设计知识学习的大模型增强方法,使得大模型在自顶向下的设计方案规划以及面向复杂项目上下文的代码生成时能够更好地融入和利用软件设计知识。

致谢:

感谢张刚和王昊奋两位好友在生成式软件开发实践以及大模型工作原理等方面的分享,与他们的探讨给了我很多启发。同时也感谢我们团队软件智能化开发组娄一翎老师、刘名威博士后和各位同学这一年以来的具体探索和实践。

作者简介:

彭鑫,复旦大学计算机科学技术学院副院长、教授,中国计算机学会(CCF)杰出会员、软件工程专委会副主任、开源发展委员会常务委员,IEEE高级会员,《Journal of Software: Evolution and Process》联合主编,《ACM Transactions on Software Engineering and Methodology》、《Empirical Software Engineering》、《软件学报》等期刊编委。主要研究方向包括软件智能化开发与运维、人机物融合泛在计算、智能网联汽车基础软件等。

迈向更高层次智能化开发之路:写给大模型的2023总结_第15张图片

欢迎关注我们!

迈向更高层次智能化开发之路:写给大模型的2023总结_第16张图片

你可能感兴趣的:(迈向更高层次智能化开发之路:写给大模型的2023总结)