大模型的快速发展带来了 AI 应用的井喷。统计 GPT 使用情况,编程远超其他成为落地最快、使用率最高的场景。如今,大量程序员已经习惯了在 AI 辅助下进行编程。数据显示,GitHub Copilot 将程序员工作效率提升了 55%,一些实验中 AI 甚至展示出超越普通程序员的能力。目前 AI 在编程领域所扮演的角色,更多的还是一个「效率工具」——以 Copilot 的形式帮助提高编程效率。
那么 AI 编程的下一步是什么?我们认为,是理解并生成复杂代码集、从而实现真正的软件自动化开发。如果 AI 能够像人类程序员一样,在大型复杂软件项目的代码集上工作,并且能有效地与人类工程师分工协作,生成几十万上百万行代码,这意味着对软件行业的根本性颠覆。
如纳德拉在 Github Universe 2023 上所说,"当你向一个组织引进 Github Copilot,工作流程将发生改变。当销售人员开始写代码,这个组织就变了,它会以代码的速度前进。现在有了 Copilot 和代码的速度,从根本上改变了数字经济。包括汽车、金融、制药... 每家公司都是家数字公司,也是家软件公司。"
本文我们将分享所看到的这一令人期待的趋势,并深入探讨 Code Agent 发展的机遇与挑战。
相较于其他很多领域还在探索如何与 AI 结合,AI 编程是有明确商业价值的刚需,因而吸引了大量巨头及创业公司关注。Stack Overflow 在其去年 5 月发布的开发者调研报告显示如下:
最受开发者欢迎的 AI 编程工具
目前主要使用场景
据不完全统计,过去一年,市场中涌现的 AI 编程工具多达几十种。在此我们先对市场上的主流产品做个简要总结,方便读者对发展现状有个直观的了解。
海外和国内的互联网巨头几乎都在这个赛道推出了相关产品。
创业公司的产品分为两类,一类是通用 AI 编程,跟巨头的产品重合度高;另一类聚焦垂类,在某个领域/功能做得深入。
通用AI编程
聚焦垂类的AI编程
除了如上的通用 AI 编程项目外,还有一些聚焦垂直行业或聚焦编程中某个具体环节的初创公司。包括
聚焦电商网站创建:Mintlify
聚焦前端开发:V0.dev,Durable,Enzyme
聚焦为开发者提供丰富的代码模板:Seeka
聚焦代码分析和修改:Adernaline
产品切入点
通过概览 AI 编程领域的主要项目,可以看到目前主流的产品趋势还是做 Code Copilot——即作为工具,辅助人类提升编程效率,而其中最具主导地位的是 Github Copilot,同时其他巨头也纷纷入局。在这样一个巨头林立的领域,初创公司目前主打的切入点主要有如下几种:
免费/开源
提供更加 AI native 的编程环境;
聚焦特定领域/环节的代码进行优化,提升在某个垂直领域的竞争力
面向未来,有两个关键问题:AI 编程会朝什么方向发展? AI 会不会取代人类码农的工作,实现完全的」软件开发自动化"?
在去年 10 月召开的 AI Engineer Summit 上,Swyx 分享了他眼中未来程序开发领域生产力提升 1000 倍的图景(如下图)。
我们目前正处于第一个阶段:在这个阶段,AI 大幅加速人类程序员工作效率,就好像一个人长了多只手,能够以更少的人力完成更多的工作。展望未来,AI 编程的下个 10x 阶段,是他称之为「AI Product Engineer"的阶段,AI 可以完成大部分工作,人类只需要在几个关键环节参与协作及决策。而在更远的未来,AI 编程的终极图景,便是「AI Engineer Agent」, 届时,软件工程领域已经是 AI 主导的天下,AI Agent 可以互相协同完全自主地完成一个复杂项目。
我们持类似的观点。下面我们将深入讨论,AI 编程什么时候从作为工具的 Copilot 走向真正自主决策的 Agent?从自动代码补全到自动软件开发,这其中存在哪些 Gap、最核心要攻克的难关是什么?我们将从软件工程的核心出发,分享对这个问题的思考。
现代软件工程经历了从早期瀑布流到最近 25 年中的敏捷开发模式,其成功的原因之一是代码和功能的不断积累。正是这种不断地快速迭代和积累,让软件工程成为人类社会中发展最快、复杂度最高的产业之一。未来如果 AI 编程自动开发成为主体,这种通过迭代和积累实现增量开发的模式会有什么改变呢?
目前由 AI 驱动的 Code Copilot 已经可以从零开始构建相对简单的软件代码集,但跟在现有大型代码集上修改和扩充的「增量开发」难度非常不同。从零开始构建新的代码集相对容易,人进行总体规划分模块,AI 只是编些功能定义明确的代码,其中的实现相对局部、复杂性低。对于大规模的复杂项目,尤其是需要长期演化和发展的大型代码集,这种近乎一次性的构建方式是完全不够的。用户不断提出需求,要求改进现有功能和实现新的功能;代码长期下来会变得僵化,需要重构。这些涉及对现有代码的深入了解和大量复杂细节,人类程序员也是需要很长时间熟悉代码,很多时候是团队协作。
比如,在大型代码集上修改和扩充的任务相当复杂,几乎修改任何一个功能都会涉及多个模块。代码分散在众多不同的源文件和函数中,如何找到分散在各处的相关代码、对其进行修改和扩充,同时不破坏已有的软件功能是一个非常复杂的任务。相比一次性地重写整个代码集,增量的开发模式复杂度要高出几个数量级。
普林斯顿学者最近在 Swe-bench(https://arxiv.org/abs/2310.06770)中研究了用大模型解决增量开发需求的效果。他们从知名的开源项目里找了 2 千多个案例,发现大模型只能解决其中的 4%。
大型软件项目的代码集规模远远超出 AI 目前 context 长度,未来也很难期待 AI 能够把代码集完整地装入内存。即便 context 长度可以无限扩展,它的编程能力仍受限于模型的推理能力。基于目前 Transformer 架构,仍然很难想象 AI 可以一次性地重新生成上百万行的复杂代码集。即便推理能力支持,其性价比是否真的支撑落地应用,也是一个巨大的问题。
一次性生成大型代码集的方法不仅非常脆弱,而且很不经济,其背后深刻的悖谬之处在于:一旦有人创造出能以增量式开发的 AI 自动软件开发系统,它在可靠性和经济性上一定会显著优于一次性生成整个代码集的系统。从系统演化的角度,不断优化积累的系统是唯一最终能够存活下来的系统,就像自然界最终选择的基因演化机制一样。
从这个角度,我们可以提出一个大胆假设:在未来很长一段时间里,即使 AI 完全替代了人类码农,实现了全自动的软件开发,也仍然会采用今天主流软件工程的增量开发模式,每次专注于一项具体的开发任务,对代码集的一部分进行修改和扩充。
基于这个假设,我们认为,AI要想在编程领域真正替代人,最需要解决的是如何能像人类一样在软件这个不断积累的」增量「系统中工作。这需要 AI 对现有大型复杂代码集的理解,并在此基础上进行修改、扩充、测试等工作。
上文提到,AI 要想在编程领域替代人类,必须要能在复杂代码集上做增量工作。而如何能够实现 AI 对复杂代码集的理解、并在此之上让 AI 接手呢?我们从软件开发的基本结构出发,分析实现这一功能所面临的主要挑战与突破点。
软件开发的三个阶段
对于一个独立的开发任务,无论新功能开发、现有功能改进、代码部分或全局重构、bug fix 等等,几乎所有开发任务都包含三个阶段:
1)定义任务:Spec
这个阶段的交付是需求文档(Spec)。Spec 具体描述任务的结果,即从软件的用户或维护者的视角看来,任务完成后软件系统有什么具体的改变,包括交互界面、系统行为和性能等。Spec 的核心是把 Why 转化成 What。
2)设计实现方案:Design Doc
这个阶段的交付是开发设计文档(Design doc)。Design Doc 描述需要对功能的哪些节点进行何种修改,并把一个任务分解为多个不同的步骤。Design Doc 把 PM 看到的产品的 What 转变成架构的 What,同时讲清楚架构要如何实现(How)。Design Doc 最后一般会包含开发计划(Dev plan)。
3)实现:代码及测试
这个阶段的交付是代码集的最终完成和测试。根据开发设计文档的规划,逐步完成代码,去跟外部 API 和底层操作系统对接,从而驱动软硬件完成任务。
AI在各阶段的作用
每个阶段的特点不同,AI 起的作用相应的不一样。
1)Spec。Spec 是把用户的需求转化成软件任务的过程。这个环节涉及到大量与人的交互,包括市场调研、反复沟通理解确认用户需求,目前这个环节靠人来做效率是最高的。
2)Design Doc。这是真正有竞争力的环节,也是AI自动生成软件的核心挑战所在。挑战的核心在于规模——如果规模很小,只是一次性任务,AI 目前的能力已经可以做到每次都从零开始生成代码,不需要设计。但如上文所述,软件真正产生价值的地方在于长时间积累的复杂系统,如何让 AI 理解现有的架构、并在此基础上进行增量工作,有很大难度。
用一个简单的例子类比,让 AI 在现有的系统上增加个新功能,就好比要给一个城市增加地铁系统。其中涉及大量对现有城市交通状态的理解与规划,需要考虑全局的交通效率、做路线规划和资源分配,每个节点的变化都牵扯到其他一些节点的,不是单独增加一个地铁站就可以的。对应到代码集,系统级代码非常复杂,有很多相互关联的复杂函数调用、全局变量等约束及边界条件。
AI要解决这个问题,需要的是一个「全局地图」——一个能够让 AI 可以快速定位每个变动对于全局影响的「地图」。一旦有了这个全局地图,AI 就能快速地理解代码、确定变化范围开始工作了。
3)Coding。实现阶段是对各模块的代码和测试。AI 核心需要解决两个问题:
其一是对于开发环境的理解。任何代码最终都要落在具体的平台上,在哪个操作系统上、用什么编程语言、如何编译、代码管理、部署等等……这些都要求 AI 要对平台有深入的了解,就像人类工程师一样。人类工程师所掌握的,远远不止对编程语言的理解,而是对这一整套适配环境的理解。
其二是自动测试和 Debug 的能力。代码生成后,需要测试它是否正确地工作,有问题要能够找到问题所在。这是一个完整的 Code Agent 必需的能力之一。
对于 AI 来说,构建理解复杂代码集所需的「全局地图」,关键是把针对代码集的 RAG(retrieval-augmented generation)做好。目前 Transformer 架构的大模型,没有 RAG 很难做好增量开发场景下的代码生成。RAG 主要解决以下几个问题:
定位需求相关代码。
因为把整个代码集全部塞给大模型并不现实,所以当给定了一个需求,首先要找到代码集中需要修改的相关代码(也就是代码集的一个子集),这里很多时候会涉及多个文件。需求的描述有时候并不会指明具体的 file、class 或者 function,而是对业务模块的描述。比如,如果我们有这样一个需求:」在登录流程中加上 2FA 验证「,RAG 需要找到当前代码集里和登录相关的代码。
提供其他任务相关信息。
有些情况只依赖这些相关代码是不够的。比如说,一些其他信息(如变量的类型信息等),对生成代码的正确性和质量可能会有很大影响。很多用户希望新代码能尽量调用已有的一些函数,而不是另起炉灶完全重写。而这些很有可能并没有包含在相关代码里,这就需要 RAG 去提供这类信息。
定位受影响代码,并做修改。
当大模型生成了新的代码后,因为它推理能力不足,生成的代码可能没有考虑到对整个代码集的影响,这样生成的代码一般是不完全或错误的。这个时候需要 RAG 去找到整个代码集中所有被当前修改影响的区域,然后再对那些代码区域进行修改。
RAG 模块通常包含几种不同信息的查询服务,基本可以分为两大类:一类是依赖于程序分析的技术来构建的查询,会提供调用关系(call graph)、数据流(data flow)、符号表(symbol table)、file、class、function 等信息。另外一类是利用大模型和向量数据库去构建关于代码集的语义索引。这两部分合在一起就代表了对相关代码集的深度理解,或者说就是相关代码集的全局地图。有了这个地图,加上大模型自身已有的通用编程能力,就可以在增量开发领域生成更好的代码。
代码的可维护性是 AI 编程的一个有趣的问题。
考虑自动软件开发系统的工作方式,AI 是否会像人类个体一样参与大型软件项目?是否需要和人类协作共同开发一个代码集?AI 写的代码未来由谁来维护?从机器人和自动驾驶的发展历史来看,开发人机协作的系统远比开发一个全自动的系统困难很多。如果 AI 生成的代码需要由人类工程师来维护,这个模式对自动软件开发系统提出了更严峻的挑战。
主要的困难来源于代码复用。对于大型复杂软件项目,人们往往通过代码复用来降低开发的工作量。代码复用带来的好处是维护成本,同样的功能只需要实现一遍,同一个 bug 只需 fix 一处,Don『t duplicate yourself 一直是软件工程的一个金科玉律。复用的代价是会引入一些难以预期的复杂 bug,对测试提出了更高的要求。但尽可能地避免组合爆炸仍然是人类软件工程的智慧。
AI 编程可能存在一种比较极端的新的可能性:如果代码都是 AI 生成的,而 AI 修改自己生成的代码或者重新生成代码都比人类要高效得多,那么是否可以放松复用的要求,同时也降低测试的复杂度?只要不需要人类维护 AI 生成的代码,也许更低的复用性未必会降低代码集的可维护性,甚至可能产生 bug 更少的代码。
AI 编程整个赛道还在非常早期。虽然巨头已经纷纷杀入,但这个领域很难完全垄断。
目前 GitHub 只是在开源领域占据了主要市场份额,但目前绝大多数代码是以私有形式存在的。代码是很多企业的核心资产,大量企业需要定制化的私有部署,因而未来的竞争格局极大可能是多头而非寡头市场。GitHub Copilot 作为面向所有开发者、所有语言、所有项目的通用 AI 编程工具,在未来很长一段时间的重心都会是做「最大公约数」——即最通用、受众最大的功能。但对于很多具体场景和需求,它提供的产品可能不够尖锐。
举两个例子:上文所说的增量开发场景下理解整个代码集的问题,在目前就没有被很好地解决(SWE-Bench 的研究也一部分验证了这个现实)。另一个例子是针对 Legacy 系统的维护,许多企业内部存在着大量 legacy code,这些 code 不开源,经过常年积累,已经沉淀了许多商业机密,推倒重来需要耗费极其昂贵的成本,日常维护又消耗很多人力,是 AI 非常适合发挥作用的场景。
我们认为,AI 编程的未来是 Code Agent,让 AI 越来越多地介入软件工程的各个环节,自动开发。跟所有 AI Agent 一样,做好 Code Agent 的关键,在于构建世界模型以及 Agent 的经验积累和学习能力。
构建世界模型
面对一个复杂系统,Code Agent 需要将项目相关的所有信息提供给 AI,让 AI 有个全局地图。这个「世界模型」用什么样的方式提供给 AI——文本、图片、还是多模态?
多模态的发展让人与 Agent 沟通的方式更加丰富。GPT-5 对多模态的支持,可以用架构图和设计图帮助 AI 建立对复杂系统的理解,应该比文本和代码的沟通带宽高很多。在许多场景中,综合运用多模态的方式相比单纯的文本会大大提升沟通效率。未来 Agent 对于多模态的应用能力,是竞争中很关键的一环。能够根据不同场景灵活运用多模态的 Agent 将更具竞争力。
Code Agent 的经验积累和学习能力
一旦被提供了复杂系统的信息,AI 需要记住它。如何让 AI 记住世界是什么样子的,需要为 AI 建立好一套记忆体系——做好大模型记忆的存储、管理、调用等。
同时,AI 还需要在此基础上不断学习,进行抽象和提炼,从而提升自己的设计和编程能力。人脑的学习过程非常复杂,认知科学还没有完全研究清楚这个问题。目前很难从人脑的角度,对 Agent 如何持续学习提出一个终极解决方案。但我们知道,现阶段大模型与人脑学习有个很大的差距。人脑是一边做一边学,但大模型的训练过程(即学习过程)和推理过程是分开的。这导致大模型在训练后,只能离线学习而不能在线学习。因此 Agent 提供方需要解决离线学习到在线学习之间的时间差。
目前针对这两个问题,主流的解决方案是通过 RAG,提供一个外挂的 Memory,做推理过程中的知识和经验积累。因而在 RAG 方向上建立技术优势,然后转换成更好的产品效果和体验,也成为了一个重要的竞争点。RAG 本身有很高的技术复杂度,而代码领域的 RAG 可能是所有应用领域中最复杂的,会有很多有挑战的子场景需要解决。即使是市占率很高的 GitHub,也很难短时间把大部分问题解决掉,这便给了创业公司机会。
当然,RAG 只是目前最主流的一种解决方案,未来在记忆与学习能力上是否会出现更新、更有效的做法,非常值得关注和期待。