本文来源于阿里云社区电子书《AIGC+软件开发新范式》
《AIGC+软件开发新范式》--01.当「软件研发」遇上 AI 大模型(1):https://developer.aliyun.com/article/1537736
高频刚需
我们需要判断什么是软件研发最高频的场景。我这边有一些真实的数据,第一个数据来自 JetBrains 在 2023 年做的一个开发者的生态报告,整理了开发者最耗时的活动,其中可以看到百分之七八十都是编写代码,理解代码及互联网搜索、调试、写注释、写测试。这几个场景实际上就是代码智能工具的功能,像通义灵码这样的产品最核心解决的问题,其实就是最高频的问题。
后面这两个数据是通义灵码线上几十万用户的数据分析。我们现在线上采纳的代码, 73% 来自于补全任务,27% 来自于问答任务的采纳。所以今天大量的 AI 替代人去写代码,还是在 IDE 的行间生成,这是从真实的情况下反映出来的一个结果。后面是使用问答功能的比例,有 76% 的比例是来自于研发问答,剩下的 10% 是代码优化和解释代码等等一系列的代码任务。所以绝大部分的开发者还是在使用我们的工具去问一些常用的研发知识,或者通过自然语言的方式让代码大模型生成一些算法,解决一些小的问题。
其次的 23% 才是我们真正的一些细节的代码任务,这是给大家一个数据洞察。因此我们就有了核心的目标。第一,我们要解决好代码生成的问题,尤其是在行间生成。第二,要解决研发问题的准确度以及专业性问题。
触手所及
我们最终要讲的是打造沉浸式编程体验,我们希望今天开发者绝大部分的问题都可以在 IDE 里面解决,而不是需要跳出。
过去我们的体验是什么?是遇到问题去互联网搜索,或者问问别人,问了一圈以后再自己判断,最终写上代码复制放到 IDE 里面调试编译,不通过了再去查,这样的话就会非常耗时。我们希望能在 IDE 里面直接问大模型,让大模型帮我生成代码,这样体验就很爽。我们通过这样的一个技术选择,解决了沉浸式编程体验的问题。
补全任务是一个性能敏感型任务,它的输出需要在 300 到 500 毫秒,最好不要超过一秒,所以我们有一个小参数模型,它主要是用来生成代码的,而且它的大部分训练语料也来自于代码。它虽然的模型参数很小,但是在代码生成的准确度上非常高。
第二个我们要去做好专项任务,我们还有 20%~30% 实际上的任务是来自于这些,包括注释生成、单元测试、代码优化、运营错误排查等七项任务。
我们目前使用了一个中等参数模型。这里主要考虑的,一是生成效率,二是调优。一个非常大参数的模型,我们调优的成本是很大的,但是在这种中等参数模型上,它本身的代码理解和代码生成效果已经不错了,所以我们选择了中等参数模型
然后在大模型上面,尤其是我们 70% 多的研发问题回答上,我们追求的是高精度,而且追求的是实时的一些知识。所以我们通过一个最大参数的模型,叠加了我们的 RAG 技术,让它外挂了一个近乎于实时的基于互联网的知识库,所以它回答的质量和效果就非常高,并且能大幅消除模型幻觉,提升回答质量。我们通过这样的三个模型支持了整个沉浸式编程的体验。
第二点是我们要实现多端,因为只有覆盖了更多的端,才可以覆盖更多的开发者。目前通义灵码支持 VS code 和 JetBrains,主要解决的是触发问题、展示问题,还有一些交互性问题。
最核心层次下面,我们本地 Agent 服务是一个独立的进程。这个进程跟上面的插件之间会进行通信。这个进程最主要解决的是代码核心的一些能力,包括代码智能补全的部分,会话管理的部分,智能体。
此外,语法分析服务也非常重要,我们要解决跨文件引用的问题等,都需要语法分析。如果我们要做本地的检索增强,我们还需要轻量级的本地向量检索引擎。所以整个后端的服务实际上是通过这样的方式就可以快速的实现扩端。
我们还有一个特色,我们有一个零点几 B 的本地离线的小模型,来实现个别语言的单行补全,这是可以脱网去做的,包括 JetBrains 最近也上了一个跑在本地的小模型。通过这种方式,也会保证我们的一些数据安全隐私问题,比如本地的会话管理、本地的存储,全部都放到了本地电脑上。
知我所想
知我所想对于 IDE 插件这个工具而言,我认为有几点。第一是触发时机,在什么时候触发,对于开发者体验的影响也非常大。比如我在空格的时候要不要触发?IDE 已经生成提示的时候要不要触发?在删除这段代码的时候要不要触发?我们大概有超过 30~50 个场景去梳理,到底在这个场景上要不要进行代码触发,这部分通过规则就可以搞定,只要一点点细心去摸索,去调研开发者体验,就可以解决,这不是很高深的技术。
但是在代码生成长度方面,我们认为是比较难的。因为在不同的编辑区的不同的位置,它生成什么样长度代码,直接影响了我们的体验。如果开发者只是倾向于生成单行代码,带来的问题就是开发者不能理解整个生成的内容,比如生成一个函数,他不知道这个函数到底要干什么,生成一个 if 语句,他不知道 if 语句里边的业务逻辑是什么,就没有办法完整的判断功能单元,影响了他的体验。
我们用一些固定的规则去做,也会导致一个问题,即它会比较死板。所以我们的做法实际上是基于代码的语义信息,通过训练的方式,经由大量的样本,让模型理解了今天在什么场景下应该生成多长,我们实现了由模型自动判断类级别、函数级别、逻辑块级别及行级别的生成力度,我们把它叫做自适应的生成力度决策。我们通过做这项大量的预训练,让模型去感知,从而提升了生成的准确度,这块我们认为也是一个比较关键的技术项。
再往下最关键的就是如何去消除模型的幻觉,因为只有幻觉得到足够的消除,才能够提升我们的采纳率。所以我们一定要实现基于库内的跨文件上下文感知,在这里,我们做了很多的基于代码的语义分析,引用链追踪,相似代码以及动态语言类型推导等。
最关键的就是想方设法的去猜开发者在这个位置补全他可能需要什么样的背景知识,这些东西可能还会涉及到一些语言、框架、用户习惯等,我们通过各种各样的东西将它的上下文获取出来,并且进行优先级排序,把最关键的信息放到上下文里面去,然后给到大模型进行推导,让大模型去消除幻觉。通过这样的技术就可以实现跨文件上下文感知的测试集,我们的准确率从 22% 提升到了66.9%,我们还在不断的去精进提升补全的效果。
最后一个是我们本地的库内检索增强。刚刚其实也说了,上下文感知也只是猜测开发者在触发位置的上下文。更多的场景是今天开发者要问一个问题,让大模型基于本地的库内所有文件去帮我解决一个问题,比如帮我修复一个 bug,帮我增加一个需求,帮我填充一个文件,自动实现增删改查,甚至帮我的 Prompt 文件增加一个新的包的版本,类似这样的需求其实有很多,要实现的话实际上是要给大模型外挂一个检索引擎。因为我们不可能把整个工程的文件全部塞给大模型,因为上下文宽度的影响,我们必须使用到一个技术,叫做本地的库内检索增强。
这个功能就是来实现我们基于库内的自由问答的,在本地去建立一个库内的检索增强服务,我们判断这样的方式对于开发者的体验是最好的,安全性也是最高的。代码不需要上传到云端,就可以完成整个链路。从整个链路上来讲,开发者问一个问题以后,我们就会去代码库提取需求的关键信息进行任务拆解,拆解完了做本地的向量检索召回,然后再做检索的结果合并及重排,以及去企业内部的数据知识库检索,因为企业有统一的知识库管理,是企业级的。最终把全部的信息汇总起来发送给大模型,让大模型去生成和解决问题。
《AIGC+软件开发新范式》--01.当「软件研发」遇上 AI 大模型(3):https://developer.aliyun.com/article/1537710