大家好,我是阿里云通义灵码团队的张昕东,今天很高兴能和大家分享一些关于人机协同的有趣话题。我们这次的讨论主要围绕如何提升人机协作的效率,以及当前的协同现状,帮助大家更好地理解我们在这个领域的努力和未来的方向。
在分享之前,我想先提一下现在大模型和AI辅助编码的热潮,很多企业都在追求提升研发的效率,我将从企业对研发效能的需求出发,探讨一下AIGC(生成式人工智能)对软件开发的深远影响,接着再讲讲我们团队在这个协同模式下所做的一些努力,最后展望一下未来的发展。
AIGC对软件开发的影响
我们的团队一直在关注如何提升研发效能,尤其是结合最近的AIGC浪潮,我们总结了三大核心影响。
第一,人员技能。 说实话,员工的技能水平在任何行业都是影响效能的关键。在开发领域更是如此。一个经验丰富的开发者的效率可能是初级程序员的十倍。新手可能会在思考代码如何写、查找问题上花费更多时间,而大模型可以帮助他们迅速提升到中级水平。同时,资深开发者借助AIGC能更快找到并修复问题,也能更好地提升自己的技术能力。
第二,协同消耗。 每个团队成员都有各自的专长,有的负责产品设计,有的做前端或后端,还有的负责测试。想象一下,如果100个人一起工作一天,完成的任务远没有100人日的效果。不同角色之间的信息传递常常会出现误差,而这种协同消耗会影响整个团队的效率。我们希望AI能发展成一个超级助手,能高效处理独立任务,机器之间的沟通会更顺畅,人与AI之间的交流也会更加精准。
第三,成本控制。 成本管理一直是企业的重中之重。开发中,沟通和编码的成本占据了很大一部分。有调查显示,开发者每天花70%的时间在处理琐碎事务上,比如增删改查。如果能把这些时间释放出来,团队就能把更多精力投入到创新和业务思考上,这将大幅降低研发成本,提高竞争力。
总的来说,企业在软件研发中面临四大挑战,但这些挑战同时也是智能化的机会。我们期待着大模型的Copilot和Agent模式能够显著提升研发效率,并通过全天候的响应能力和标准化管理流程来提高协作效率。
比如,在本地运行代码时遇到错误,大家通常会把错误信息复制到搜索引擎中,查找解决方案。这个过程往往需要反复几次才能找到答案。而有了嵌入式的编码助手,用户可以通过简单的自然语言提问,直接在IDE中解决问题,大大提高了效率。
以我们的通义灵码为例,灵码在报错信息中加入了一个Lingma图标,用户只需点击一下,就能自动收集错误堆栈和相关代码上下文,并把这些信息发送给模型,生成的修复代码也能直接应用到代码库里,这样的设计极大提高了研发效率。此外,其他的补全和问答功能也在不断提升我们的工作效率。
最后,企业最关心的数字资产问题也不能忽视。我们常常听到“屎山代码”这样的抱怨,但每段代码在初写时都不是“屎山”。那么,为什么代码会变得混乱呢?主要是因为企业未能有效沉淀优质的代码和文档,开发规范和运维手段没有同步。而AIGC的浪潮正好促使企业更加重视无形资产的管理,把知识通过SFT、RAG等方式赋予大模型,形成良性循环。
总的来看,大模型时代为软件研发带来了两大改变。
第一,研发知识传递的方式发生了变化。 现在企业的知识大多依靠口口相传,新人接手项目时通常只能通过口述、代码注释和运维脚本来熟悉工作。而大模型的介入,使得整个DevOps流程更加流畅,企业可以将知识注入到大模型中,让一线员工和管理者都能使用这些工具,生成的新代码、新文档又会回流到知识库中,形成良好的循环。
第二,AIGC带来了新的人机协同模式。 这一模式可以分为三个阶段:第一个是Copilot,主要是提升人机高频协作的效率,解决具体的任务;第二个是Agent,解决需要多角色协作的复杂任务;第三个是Facilitator,AI在这个阶段能承担更多的决策角色,人类则更多负责创新和目标设定。
回顾人机协同的演进,感觉就像人类历史的发展,部落时代需要生存,首领分配任务,而随着社会的发展,信息的传递和管理变得更加高效,就像今天的AI模型在帮助我们提升工作效率。
未来的研发领域,人机协同的模式还有很大的发展空间,我们期待着能与大家一起探索更多的可能性。
提升通义灵码效果的实用技巧
首先,我们得承认,输入的长度限制让我们无法一次性提供所有的背景信息。即便是最顶尖的长上下文模型,也无法在每次问答时把所有研发知识都输入进去。而且,如果上下文过长,关键信息可能会被稀释,这对像代码补全这样的性能要求高的场景来说,真的是不可接受。
说到推理速度,除了代码补全这种需要即时反馈的场景,做多轮交互的 Agent 时,也要求模型能迅速推理,给出当前阶段的输出。
模型偶尔会出现幻觉或错误输出,这在所难免。一旦错误率超过某个临界点,用户体验就会大打折扣,开发效率也会直线下降,AI 辅助反而成了负担。而在 Multi-Agent 迭代时,如果某个 Agent 输出错误格式,那影响可大了。如果多次重试还是不行,流程就可能失败。
再说说协同惯性,这其中既有人的因素,也有模型本身的问题。一方面,人类还在适应从个人编程到辅助编程的转变。你可能发现,很多人对 AI 的介入表示抵触,这或许是因为 AI 还不够稳定,需要更高质量的模型来打破这种心理障碍;
另一方面,很多时候人类无法给出模型完整的上下文和清晰的需求。即便是熟悉 Prompt 写法的人,也常常一句话就模糊了需求。人们习惯与人沟通,期待对方能理解并追问,从而澄清意图。而大模型也需要如此,得反复揣摩用户的输入。就像孔子曾经多次阅读竹简,磨断了连接竹简的绳子,难道不就是在强调理解的重要性吗?大模型也得通过追问来揣摩用户的真实意图。不过,有时候即使有心,Prompt 的组织也很困难。就拿我最近遇到的问题来说,现象复杂,人类推理也有对错,想在找到缺陷前给 AI 提供合适的 Prompt,确实不容易。
结合这些挑战和需求,我们认为目前人机协同模式仍处于 Copilot 模式的快速发展阶段,各种插件和工具如雨后春笋般涌现。而 Agent 模式也开始显露头角,最近在解决实际问题的 SWE-bench 榜单上,lingma-agent 拿到了第一。这种榜单的排名变化很快,相信几个月内就能突破 50%。在 Agent 和研发领域,学术界的进展比较迅速,各公司也在一些演示场景上取得了进展。我相信不久的将来,模型突破一定的瓶颈后,商业化产品将迅速推出,真正赋能每个开发者。

在准备这个 PPT 的时候,我思考如何把这些优化手段整理起来。经过思考,虽然现在的大模型能力强大,但在解决现实问题时却显得力不从心。大模型的优势在于积累了丰富的知识和经验,甚至比整个团队写的代码还多;但短板在于与人交互时,难以对齐上下文,影响了效果。这就像老中医问诊一样,虽然他经验丰富,但门诊时间有限,只有几分钟的时间去了解患者的背景和需求,并给出解决方案。因此,在开发工具时,我们得想办法提供足够的上下文,以提升效果。
传统中医的诊疗手段包括“望闻问切”,而人机交互也类似。
“望”就是让模型能从提示词中获取足够的信息。由于无法将所有背景信息一次性输入,我们就得人工提取一些有价值的信息,给模型提供浓缩的内容。
“闻”则是让模型更贴合用户的习惯。有时生成的内容并不是不对,而是过于普通,无法解决用户特定上下文中的问题,得对症下药。
用户的需求往往比较模糊,可能只是一句话。这是因为他们习惯于与人沟通,期待对方能理解并追问,从而明确需求。大模型也需要对用户的输入进行深入理解,就像孔子多次阅读竹简,努力揣摩每个细节一样,模型也需要通过反复的追问来理解用户的意图。
“切”的部分,我想探讨一下未来 Multi-Agent 和 AI 程序员之间的交互模式。拥有长记忆和长上下文的 Agent,能够突破现有的限制,大幅提升效果。之所以称之为“晴空一鹤”,一方面是想表达跳出限制、效果飞速提升的意思,另一方面“晴空一鹤”出自于“晴空一鹤排云上”,指向未来 AI 程序员将运行在云端。这也希望人类程序员能够从繁琐的事务性任务中解放出来,放心地交给 AI。

首先提到“望”,其实并不是说模型忘记了什么,但有时幻觉可能让人这么觉得。在代码生成过程中,幻觉是常见的,即使是人类程序员在写代码时,也不能只看单个文件的前后文,而是要结合相关文件的理解,以及配合 IDE 的语法分析来进行编码。如果只是看代码的前后文,确实不能怪 AI 幻觉,毕竟“巧妇难为无米之炊”。

解决方案主要是在推理阶段通过提示词将相关代码的引用和定义传达给模型。当然,这个过程还涉及到相似代码库内的 RAG 以及二三方包组件的定义采集。我们在 lingma-agent 的进程中实现了一套类型追踪图索引和毫秒级的关联信息抽取。比如在处理一段代码时,我们需要将 subList 中 ODS 层对象的值抽取出来,赋值给 DWD 层的数据结构 report。通过提前建立的 TTG 索引,以及正在编写位置的上下文,我们能推导出要补全这段代码所需告知模型的两个数据对象的字段信息。这其中还涉及到一些细节,比如如何识别 lombok 的注解,区分字段和方法的公开性。由于现实情况复杂,相关的文件数量也多,我们还会基于一些特征,比如 import 语句、被引用方法的入参和出参对象等信息来减少模型的幻觉概率。
这些方法其实和我们之前做的 LSIF 类似,旨在实现文件定义与引用之间的跳转。我们复用了不少之前的研究成果,构建了一套在线跨文件感知系统。

这套在线跨文件感知系统,不仅适用于代码补全,任何代码生成相关的任务都能使用。比如生成可编译的单元测试时,需要采集当前代码的出入参对象的数据结构,了解需要 mock 的字段和要 assert 的信息;还要知道方法内部引用了哪些外部方法,访问权限如何,是静态还是普通等;当然,最重要的步骤是采集一些库中的单测样本进行学习。而这些工作都是通过 Lingma 进程里的跨文件感知系统来完成的。

为了确保在线推理阶段的准确性,在 SFT 过程中让模型学习同样的提示词和跨文件场景是非常必要的。
通义灵码内部建立了一套完整的离线跨文件数据集构建引擎。其特点是数据结构通用,类似中间语言,所有语言的后处理流程都是统一的,不同语言只需适配一层解析器,接入成本较低。此外,所有解析过程是免编译和文件级独立的,尽管在某些动态特性解析上有所牺牲,但速度非常快,因此只要机器资源充足,能并发处理的数量相当可观,我们自己处理时大约能够达到每小时 2000 万个文件。
整个流程首先进行常规的数据清洗和去重,然后会建立一个元信息索引,将代码文件中的类定义、方法定义、字段定义、文件定义、模块定义等信息解析并提前存储。这些元信息的结构和存储粒度会因语言不同而异,唯一要求是每个元信息索引的文件名在解析引用时能够成功定位,同时元信息中的定义 ID 也必须是完全唯一的。在某些语言场景下,元信息的解析需要分两步进行,例如 Java 的继承,子类需要将父类的公开方法和字段整合到自身的元信息中,并判断是否重载,以此避免在跨文件关联时需要重复查询元信息定义。
接下来的跨文件还原步骤是利用元信息索引,将当前代码文件的外部方法引用与外部方法的定义关联起来,构造出大规模的跨文件还原数据集。这种通用的数据结构在不同任务中发挥了重要作用,跨文件补全数据集的准确率从 21% 提升到 77%,而 Java 单元测试的编译通过率也从 4.9% 提升至 25.6%。同时,语言解析和多语言支持的迭代速度也有了显著提升,节省了大量的计算资源和时间。
AI 助手的未来:赋能研发的新视角

接下来聊聊我们为让 AI 更好地适应用户习惯所做的工作。首先,什么时候触发 AI 生成内容是个大问题,生成的结果即使很准确,也可能因为打扰用户而遭到吐槽。因此,在我们研究了超过50种不同的 IDE 场景后,尽量减少在不必要的情况下激活大模型进行补全。因为现在普遍使用的交互方式是那种“幽灵文本”的即时生成方式,如果触发补全,后面的代码就会被推后,这对用户来说是极其重要的。另外,我们还根据编码经验,为不同的代码上下文和 IDE 设定了不同的延迟策略,通过动态实验来找到用户最能接受的触发时机。触发的长度除了给用户设置偏好外,还会根据他们的击键速度、代码上下文等信息,通过小模型进行学习,并对一些特定难度的文件类型进行规则限制。
接下来是关于生成内容的细节,用户希望得到的是大段的代码,并且这些内容需要在一定程度上是正确的,这真的是用户心中所想的吗?其实并不一定。所谓的“副驾驶”,其实是用户希望 AI 能提供必要且适度的帮助。在代码层面上,生成的内容需要符合用户的编码习惯。生成内容过长不仅容易出错,还可能超出用户的预期,阅读成本也会大增。一般来说,一个屏幕能显示大约80行代码,许多用户在看到超过8行的内容时就会觉得阅读困难,从而不倾向于使用这些内容。
因此,我们利用之前提到的通用离线数据中分析得到的代码块信息,在模型的微调过程中,模拟补全,让模型学会用户期待的生成细节。

问答任务同样需要符合用户的使用习惯和团队代码库的特性。我们采用了一种少量示例的方式,比如在生成提交信息时,从用户的代码库中收集一些样本,以适应特定的语言和格式规范。当然,这也可能会遇到一些简单粗暴的提交信息,比如“fix”或者“update”,模型需要避免模仿这些,尽量在贴合用户习惯的同时,提供正确的引导和生成。注释生成的道理也是一样。
另一种方式是通过追问引导词,帮助用户更方便地纠正模型的回答。对于不同的指令性任务,通义灵码提供了多样的追问选项。例如,在代码解释的场景中,灵码会优先生成大约一百字的简短总结,如果用户希望模型能给出更具体的回答,可以点击“详细信息”追问按钮进行互动。
还有一种就是用户自定义需求,相当于自定义提示词。在单元测试生成过程中,用户可以输入企业代码库的单测规范和命名规范,这些信息将被灵码近期上线的功能记住,以更好地适应用户的操作和习惯。
我们的产品设计理念是倾向于减少设置选项,通过插件和模型去感知用户的行为和习惯,尽量避免给用户带来过多的干扰。

关注表面现象和解决简单问题的方式并不够。在代码场景中,问题往往需要对代码库深入洞察,这时提问的方式就变得尤为重要。这里的提问分为两个方面:一是向模型细化需求,二是询问本地环境,召回相关文件。库内检索也叫工作区,它的流程是这样的:根据用户的问题和当前代码库的文件目录树,通过模型分析,进行指代消歧,输出细化后的用户需求和一些关键词。接着,利用本地的向量库召回相关文件,并检索已有的信息进行合并和重排,最终组装成请求大模型的提示。
整个库内检索增强的过程都是在本地进行的,我们在用户本地建立了向量检索库,确保用户的代码安全。
除了库内检索增强,还有企业知识库的检索召回也在进行中,逻辑是相似的。

说到企业知识库的检索,这是企业用户迫切的需求。大家认为 SFT 费用太高,做起来不够频繁,可能还会影响原有效果,因此 RAG 成为了一个比较流行的解决方案。在项目管理的场景中,有很多专有名词需要录入模型,模型还需要学习需求、任务拆分的规范,以及任务指派的逻辑。开发场景的需求量最大,比如开发规范、单测规范和企业内部的组件库,在补全和问答的场景中都希望好好利用 RAG。测试和运维也有需求,比如让模型理解自研的测试框架和内部运维手册等。
现在检索增强的方式越来越受欢迎,似乎大家都倾向于“遇事不决上 RAG”,但要注意的是,RAG 也并不是万能的,它对数据的质量和格式要求较高,并且会影响性能,尤其在补全的场景中,这方面还有很多值得研究和标准化的工作。

通义灵码的企业级检索方案如图所示,我们将为用户提供企业管理后台,以便上传和管理知识文档。灵码则提供了数据分块、代码解析、召回重排和向量化等通用能力,帮助企业实现 RAG 和 SFT 的能力。

最后一步,我认为这是研发领域的一大突破,也是人机协同模式的下一步,大家对 Agent 的期待很高。
Agent 的概念非常广泛,目前在学术界的研究走在前面。从产品落地的角度来看,我觉得会从单个 Agent 或者两个 Agent 互相配合的模式开始逐步演进。产品化需要稳定的输出、准确的效果、低成本和解决实际痛点。

目前来看,单元测试生成的 Agent、修复缺陷的 Agent 和生成 Demo 应用的 Agent 可能会优先投入使用。例如,SWE-bench 数据集在这个领域非常流行,通义灵码刚刚赢得了这个数据集的第一名,主要集中在几行代码的缺陷修复和需求开发上。现在 SWE-bench light 数据集的解决率已经达到了33%,相信在未来几个月内能够突破50%,而50%-80%可能会是一个关键点,这将推动实际问题的解决方案的出现,大家敬请期待。
相比于多 Agent 解决通用问题,其实在 Copilot 类型的插件背后已经有一些 Agent 的能力在实践了。例如,之前提到的库内 RAG 问答就是一个简单的单 Agent 场景,其他如测试用例生成的 Agent,通过不断运行和解决编译错误的能力,提升测试用例的编译通过率和覆盖率。还有缺陷修复的 Agent,也将在不久的将来为大家提供体验。近期阿里云也推出了 AI 程序员的概念,我们内部通过多 Agent 实现了一个简单的 demo,获取巴黎奥运会赛程并制作成网站,未来已来,大家敬请期待。
未来 AIGC 研发赋能展望

朱熹曾经说过:读书有三到,心到、眼到、口到。我们刚才聊了很多插件方面的努力,属于眼到和口到,而三到中,心到才是最重要的。心到之后,眼和口自然也会到。
通义灵码基于通义大模型,利用高质量的开源数据以及阿里云积累的文档和 API/SDK 数据,训练了多个研发垂直大模型,包括代码补全和研发问答等。然后,通过问答意图识别、习惯学习、提示工程以及跨文件感知强化等能力,形成了灵码这一智能编码插件。目前通义的 qwen2 模型已达到 SOTA,但仍有许多提升空间。我们的目标是更快、更长、更便宜。如果上下文可以再长一些,推理速度再快一些,很多场景就不需要进行 RAG 和相关文件信息的裁剪了,补全的采纳率、生成占比、问答的准确率以及 Agent 的有效率都能得到显著提升。
未来的智能编码,让开发更轻松
我相信,在我们不断提出需求的推动下,模型的进步会变得更加迅速。

在追求“爱斯基模”的同时,我们也不会停下对灵码应用层的打磨。说实话,各厂商的基模型训练数据差异并不算大,真正的竞争在于谁能在研发中运用更成熟的软件工程经验,最能理解开发者的需求,结合大模型来解决这些痛点,谁就能吸引到中国那上千万的开发者。我在智能研发领域已经干了不少年,记得2018年我们尝试将AST的端到端路径进行向量化,旨在解决缺陷定位和代码质量等问题,那时候只是初步探索,提升了大约0.05的F1值。半年后,就看到了许多关于代码向量化的研究论文,如Code2Vec和北大的TreeCNN。
通义灵码起初是阿里云的智能编码插件,早在2020年,我们就利用GPT2建立了代码补全模型,通过大规模的数据处理实现了代码搜索和文档搜索服务,至今在JetBrains IDE中依然可以体验到。最近在FSE的Industry Track上,我们也发布了与代码搜索相关的论文。随着去年大模型的火热,通义灵码正好迎来了发展的风口,目前已经支持JetBrains的全家桶、VS Code和Visual Studio,未来也会有更多的端侧应用上线。无论扩展多少IDE,我们始终将核心服务放在本地灵码进程中,例如跨文件感知索引、问答会话管理、Agent调度流程、向量检索和代码分析等,这样提高了通义灵码在多个平台上的一致性和研发效率。

软件工程已经发展了五十多年,智能编码正处于快速发展中。诗经中提到“陟彼高冈,我马玄黄”,在大模型的助力下,软件研发的智能化确实达到了一个新的高度,未来充满期待。在过去的一两年里,智能编码的应用不仅限于IDE插件和Copilot这样的协作模式,代码大模型的能力结合Copilot和Agent的方式,将能全面提升DevOps研发流程。我很荣幸能和大家一起见证并创造这一历史,携手提升研发的幸福感。










