作者:思源、一鸣
从程序员到数据工程师,编写程序代码是一项基本功,但是编写冗长代码的过程也极大地花费了开拓者的耐心。比来,有不少关于代码补全工具的爆出,例如,来自美国的 Kite,来自加拿大的 TabNine 等,一韶光得到了不少程序员的关注。但实在很多人还并不知道,在这些国外产品不断被媒体推送的背后,有一款能力更为强大、更早将深度学习运用于代码补全的产品,一款源自中国的工具——aiXcoder,它的研发者们来自于北京大学。
在本文中,机器之心采访了项目总卖力人北京大学打算机科学技能系副教授李戈,请他为读者朋友解读自动代码补全背后的技能,以及 aiXcoder 背后的技能特性和上风。

aiXcoder 官网:https://www.aixcoder.com/#/
aiXcoder 的代码补全效果
我们先看看写 TensorFlow 时的代码补全效果:
如上所示,aiXcoder 在 TensorFlow 的代码环境下能够直接「预测」到模型建立后的一系列代码流程。例如,在定义了 loss 之后须要定义 optimizer,之后须要 train_op、init 方法,然后终极定义模型的保存办法 saver,以及开始运行打算图。这样一个流程基本上是深度学习开拓者所知晓的,但是按照流程写下来非常繁琐。在 aiXcoder 的提示下,开拓速率得到了提升。
aiXcoder 支持 Java、C++/C、Python、PHP、JavaScript 等措辞,以插件的办法集成到现有的 IDE 中,如 Pycharm、Android Studio、VS Code、Eclipse、Webstorm、Sublime 等,插件的背后是一个强大的云端深度学习引擎。
针对开拓者,该产品目前分为社区版、专业版和企业版。社区版是完备免费的,专业版也可以通过分享而免费得到。它们间的不同之处在于模型会不会连续学习,社区版紧张利用事先演习好的公用模型做预测,而专业版则会根据用户的代码习气及构做作进一步的调度。
企业版是 aiXcoder 功能最为强大的版本,它能够在企业内部的私有云中进行支配,并能够利用企业自己的代码来进行模型的优化演习,从而具有更高的准确率和运行性能。
aiXcoder 用起来怎么样
百闻不如一见,机器之心也对 aiXocder 进行了利用测试。
机器之心在 Pycharm 上试用了社区版/专业版,它们都是须要在线推断。不同的地方在于专业版还须要额外的内存,由于每一个 Pro 用户都须要额外的缓冲区来储存模型「学到的」用户习气。当然,Pro 用户的缓冲区是是只有该插件能访问的。
利用体会
一样平常而言,当我们选择 Python 和 PyCharm 时,代码补全就自然用 IDE 自带的工具。利用 aiXcoder 第一个感想熏染是它比自带的补全工具灵巧得多,由于以前的补全紧张表示在 Python 函数或其它包的 API,而 aiXcoder 还会预测变量名是什么、运算是什么、想调用的函数又是什么。
虽然代码补全的推断过程全是在云端完成的,但在我们的利用中,一样平常网络环境乃至 4G 都能有实时的反馈,以是补全速率上基本和 Pycharm 自带的工具差不多。李戈教授表示,目前 aiXcoder 绝大多数都能在 200ms 旁边得到反馈,有部分地区的用户由于网络延迟问题可能会觉得到卡顿,aiXcoder 正在全国各个紧张城市支配做事器,以提升用户体验。同时,aiXcoder 团队也特殊关注模型压缩技能,希望把基于 CPU 的推理运算韶光压缩到可接管的程度,从而推出能够在 CPU 上运行确当地版。
总体而言,aiXcoder 供应的补全功能在预测变量名、函数名或关键字等效果上确实非常灵巧,而且它还会学习开拓者的代码风格与编程模式,因此效果还是挺好的。
如下是自动补全的一些候选,一些函数名称可能是开拓者之间常常利用的,因此得到了推举:
对付一些变量,aiXcoder 可根据变量类型提出该变量可能的操作,比如,对付下图的变量「m」,aiXcoder 提出了一个对字符串进行增加的代码:
比拟测评
aiXcoder 官方也将产品和其他代码补全工具进行了比拟,包括 Kite 和 TabNine 等。
在比拟过程中,aiXcoder 会利用 Kite 或 TabNine 官方供应的示例代码,并测试完成这段代码到底须要多少次按键。结果表明,aiXcoder 较其他插件在效率上提升 1.5 倍以上。
aiXcoder 是如何打造的
能够实现高效代码补全的 aiXcoder,背后有着强大的技能支撑。据李戈教授先容,aiXcoder 很早就试过了措辞模型,将代码视为一种措辞从而直接建模,这就和 Deep TabNine 一样。但是研究者很快创造,只有措辞模型是行不通的,它总会提出一些毫无意义、很不科学的补全建议。为此,aiXcoder 领悟了基于序列的程序代码措辞模型、基于抽象语法树和程序逻辑关系的图神经网络等方法,共同打造一个完全的系统。
为什么直接天生代码是困难的
如果深度学习模型能根据开拓者的意图,以端到真个办法直接天生对应的代码,那么这样的模型会很「优雅」。但是经由研究创造,这样的任务需求是很难实现的,这和任务本身所依赖的数据的性子有关系。
李戈教授从机器学习所依赖的数据性子的角度,对代码天生任务和传统的图像处理任务、自然措辞处理任务的不同,给出一种较为形象化的阐明。
对付图像识别或图像分类任务而言,机器学习的目标是建立一个连续的数据集(图像数据)到一个近乎连续的、有着靠近清晰边界的数据集(标签)之间的映射关系。
这样一来,由于图像数据非常的稠密,而标签集又有足够清晰的边界,那么这就相称于一个标签拥有大量的数据可以学习。这样的映射关系是比较随意马虎建立的,这也是机器学习中和图像干系的任务相对较为随意马虎完成的缘故原由。
对付自然措辞处理任务而言,机器学习须要从一个较为连续的(离散度高于图像)、有着较清晰边界的数据集建立与另一个较为连续的、有着较清晰的边界的数据集之间的映射关系。
而由于自然措辞处理中的文本数据比较图像数据更为稀疏,因此自然措辞处理干系的任务更难取得较好的模型性能。
但是在代码天生方面,从编程者的意图(intent)天生程序代码的问题,可以看做是「程序员意图空间」到「程序代码空间」的映射,个中意图可以是由自然措辞描述的信息。如上图所示,这是从一个较为连续的、有着较清晰边界的数据集,向一个更加离散而没有清晰边界的数据集进行映射。
换句话说,只管代码天生的意图较为清楚,但是实现该意图的代码数据却比较稀疏,而且即便对付相同的意图,其对应的实当代码之间仍存在较大差距,因此这样的任务是非常难学习的。
为此,在 aiXcoder 的实际实现中,对不同运用领域的代码都采取了特定的模型,它们仅利用该领域的数据进行演习。例如,对 TensorFlow 或 PyTorch 等框架也有其特定的代码补全模型。这样做的紧张目的便是加强程序分布的稠密性,在特定领域下,代码分布更加靠近连续性。
可见,根据编程者的「意图」来「直接」天生完全代码是非常困难的,但李戈教授表示,可以用类似的技能来赞助人类程序员来编写代码,我们可以从程序员已经写下的代码中获取程序员的「编程意图」,然后综合剖析代码,的构造信息、变量引用信息、API 序列信息、继续关系信息等等,以自动天生后续代码。然而,在这个过程中,只有措辞模型是远远不足的,还须要对很多其它代码特色进行剖析,才能做好天生式的代码补全。
纯挚的预演习措辞模型又怎么样?
提起代码补全,有些人可能会下意识的认为这仅仅是一个普通的措辞建模任务,模型只须要根据开拓者之前写的代码预测之后的代码即可。因此利用最前辈的预演习措辞模型,再在代码数据上进行微调说不定是一种好方法。
但是李戈教授表示,这样的想法是远远不足的。预演习措辞模型在代码补全任务中效果不佳,紧张是由于代码补全任务本身存在诸多不同于自然措辞剖析任务的寻衅。
首先是代码文本中存在的语义抽象性问题。代码的语义(功能语义)与其字面表示之间存在更大的差距。我们无法根据字面确定代码的准确语义。例如,在代码中,只改变一个字符就有可能完备改变整行代码的功能,因此处理代码的措辞并准确提取其含义比较自然措辞处理任务更棘手。
f = open('word_ids.txt','r')f = open('word_ids.txt','w')
上图所示,在 Python 代码中,打开某个文件时利用「r」和「w」会实现完备不同的功能。
此外,代码的功能语义难以进行详细的表达和刻画,而且代码功能语义的表达办法多种多样。例如,有多种代码的形式文本用于实现某个功能,不能说某一种代码是对的而另一种是错的。
list_a = [] for i in items: result = test(i) list_a.append(result) list_a = [test(i) for i in items]
如图所示,实现 list_a 的代码可以是多种多样的,但措辞模型会将它们学习为完备不同的表征。
同时,代码文本本身的构造非常繁芜。例如,代码的语义与代码构造(如行与行的缩进)之间存在较大的关联性,代码语义依赖于代码构造进行表达。这是预演习措辞模型难以表示的特色。
末了,代码具有蜕变性的特色。代码较自然措辞的迭代速率更快,因此预演习措辞模型不能够及时捕捉蜕变特色。
考虑到代码措辞中的诸多特性,纯挚的预演习措辞模型无法得到非常好的效果。
核心技能
既然单独的措辞模型弗成,那么 aiXcoder 又结合了哪些技能,它又是靠什么来补全代码的?总体而言,aiXcoder 紧张依赖于其特有的对程序代码进行学习的深度神经网络模型,该模型能够对程序的如下几类特色进行剖析:
1. 程序的构造语义特色:程序措辞是一种构造性很强的措辞,程序的构造信息也表示着程序的语义。例如,抽象语法树是对代码进行解析的一种较为通用的构造,它表示了代码的语义特色,aiXcoder 便充分利用了抽象语法树,对程序员已经写下的代码的语义进行解读。
2. 程序元素间的逻辑关系:程序代码的不同元素之间存在着不同的关系,例如程序变量之间的引用关系、类之间的继续关系、方法与参数之间的调用关系等等。程序本身又可以表示为多种图,例如掌握流图、数据流图、调用关系图等等。aiXcoder 借助图神经网络能够对程序元素之间的多种关系进行建模,从而能够对程序元素之间的繁芜关系进行剖析和推理。
3. 程序措辞序列模型:当然,程序措辞也具有与自然措辞相似的一壁,因此可以利用程序标识符之间的序列关系建立程序措辞模型。aiXcoder 也利用了最新的深度学习措辞模型对程序中的序列信息进行建模。
在得到程序代码的各种特色之后,就该把这些特色输入深度神经网络进行剖析了,但这并不随意马虎,由于在输着迷经网络之前须要把这些特色进行向量化表示。在研究过程中,北京大学提出了一系列办理程序措辞身分相量化的办法,并且在国际上最早揭橥了干系的论文,这些都为 aiXcoder 的布局打下了根本。
团队先容
李戈教授所在的北京大学高可信软件技能教诲部重点实验室是海内顶尖的软件科学研究团队,是北京大学打算机软件与理论全国重点学科的紧张支撑,其培植历史可以追溯到 1955 年,至今已有 60 多年的学术沉淀和积累。该团队在著名软件科学家杨芙清院士和梅宏院士的带领下,已经发展为该领域国际领先的研究团队。
基于深度学习的代码剖析与天生一贯是李戈教授的研究方向,也是北大高可信软件技能教诲部重点实验室重点关注的领域,他们从 2013 年开始就开展了基于深度学习的代码剖析研究,从 2015 年开始就将深度学习用于代码天生,是最开始进行干系研究的团队之一。该团队在 AAAI/IJCAI/ACL 等顶会上揭橥过很多代码天生的干系论文,这也是一大笔技能累积。
李戈教授是 aiXcoder 创始人,北京大学打算机科学技能系副教授,CCF 软件工程专委会秘书长,斯坦福大学打算机系人工智能实验室访问副教授。紧张研究方向:程序剖析,程序天生,深度学习。所在研究团队聚焦于基于机器学习概率模型的程序措辞处理,在代码功能剖析、代码自动补全、代码毛病检测等方面取得并保持了国际上领先的研究成果。