ML-Enhanced Code Completion 提升开发者生产力

2022年7月26日 由 Maxim Tabachnyk, Staff Software Engineer 和 Stoyan Nikolov, Senior Engineering Manager, Google Research 发布

快速链接

×

更新 — 2022/09/06: 本文已更新,删除了关于观察到的上下文切换减少的声明,该声明无法通过统计显著性确认。

日益增长的代码复杂性对软件工程的生产力提出了关键挑战。 代码补全 一直是帮助缓解 集成开发环境 (IDEs) 中这种复杂性的重要工具。 传统上,代码补全建议是通过基于规则的 semantic engines (SEs) 实现的,这些引擎通常可以访问完整的代码仓库并理解其语义结构。 最近的研究表明,大型语言模型(例如,CodexPaLM) 能够提供更长和更复杂的代码建议,因此,涌现出了有用的产品(例如,Copilot)。 然而,由机器学习 (ML) 驱动的代码补全如何影响开发者的生产力,除了感知到的生产力 和接受的建议之外,仍然是一个开放的问题。

今天,我们将介绍如何结合 ML 和 SE 开发一种新型的基于 Transformer-based 的混合语义 ML 代码补全,现在可供内部 Google 开发者使用。 我们将讨论如何通过以下方式组合 ML 和 SE:(1) 使用 ML 重新排序 SE 单个 token 的建议,(2) 使用 ML 应用单行和多行补全,并使用 SE 检查正确性,或 (3) 使用 ML 对单个 token 的语义建议进行单行和多行延续。 我们将 10k+ Google 员工(在三个月内跨八种编程语言)的混合语义 ML 代码补全与对照组进行比较,发现暴露于单行 ML 补全时,编码迭代时间(构建和测试之间的时间)减少了 6%。 这些结果表明,ML 和 SE 的结合可以提高开发人员的生产力。 目前,3% 的新代码(以字符衡量)现在是通过接受 ML 补全建议生成的。

用于代码补全的 Transformers

一种常见的代码补全方法是训练 transformer 模型,该模型使用 self-attention 机制进行语言理解,以实现代码理解和补全预测。 我们将代码视为类似于语言,使用子词 token 和 SentencePiece 词汇表表示,并使用在 TPUs 上运行的 encoder-decoder transformer 模型来进行补全预测。 输入是光标周围的代码(约 1000-2000 个 token),输出是一组用于完成当前行或多行的建议。 序列是使用解码器上的 beam search (或树状探索) 生成的。

在 Google 的 monorepo 上进行训练期间,我们会屏蔽掉一行的剩余部分和一些后续行,以模拟正在积极开发的代码。 我们在八种语言(C++、Java、Python、Go、Typescript、Proto、Kotlin 和 Dart)上训练单个模型,并观察到所有语言的性能都有所提高或相等,从而无需专用模型。 此外,我们发现约 0.5B 参数的模型大小可以在高预测精度、低延迟和资源成本之间取得良好的平衡。 该模型受益于 monorepo 的质量,而 monorepo 的质量是通过指南和审核来强制执行的。 对于多行建议,我们迭代地应用单行模型,并使用学习到的阈值来决定是否开始预测下一行的补全。

Encoder-decoder transformer 模型用于预测代码行的剩余部分。

使用 ML 重新排序单个 Token 建议

当用户在 IDE 中键入内容时,会同时从 ML 模型和 SE 交互式地请求代码补全。 SE 通常只预测单个 token。 我们使用的 ML 模型会预测多个 token 直到行尾,但我们只考虑第一个 token 以匹配 SE 的预测。 我们识别出也包含在 SE 建议中的前三个 ML 建议,并将其排名提升到顶部。 然后,重新排序的结果将作为 IDE 中用户的建议显示。

实际上,我们的 SE 在云中运行,提供开发人员熟悉的语言服务(例如,语义补全、诊断等),因此我们将 SE 与执行 ML 推理的 TPU 放在相同的位置运行。 SE 基于一个内部库,该库提供具有低延迟的类似编译器的功能。 由于设计设置,请求是并行完成的,并且 ML 通常更快(约 40 毫秒的中位数),因此我们不会为补全增加任何延迟。 我们观察到实际使用中的质量显着提高。 对于 28% 的接受的补全,由于排名提升,补全的排名更高,而在 0.4% 的情况下,补全的排名更差。 此外,我们发现用户在接受补全建议之前键入的字符数减少了 >10%。

检查单个/多行 ML 补全的语义正确性

在推理时,ML 模型通常不知道其输入窗口之外的代码,并且在训练期间看到的代码可能会遗漏积极更改的代码仓库中补全所需的最新添加。 这导致了 ML 驱动的代码补全的一个常见缺点,即模型可能会建议看起来正确的代码,但无法编译。 根据内部用户体验研究,这个问题可能会导致用户信任随着时间的推移而受到侵蚀,同时降低生产力。

我们使用 SE 在给定的延迟预算(<100 毫秒的端到端补全)内执行快速语义正确性检查,并使用缓存的 abstract syntax trees 以实现“完整”的结构理解。 典型的语义检查包括引用解析(即,此对象是否存在)、方法调用检查(例如,确认该方法已使用正确数量的参数调用)和可赋值性检查(以确认类型是否符合预期)。

例如,对于编程语言 Go,大约 8% 的建议在语义检查之前包含编译错误。 但是,语义检查的应用过滤掉了 80% 的不可编译建议。 在加入该功能的前六周,单行补全的接受率提高了 1.9 倍,这可能是由于用户信任度提高所致。 相比之下,对于我们没有添加语义检查的语言,我们只看到接受率提高了 1.3 倍。

可以访问源代码的语言服务器和 ML 后端并置在云上。 它们都对 ML 补全建议执行语义检查。

结果

通过 10k+ Google 内部开发人员在其 IDE 中使用该补全设置,我们测得的用户接受率为 25-34%。 我们确定基于 transformer 的混合语义 ML 代码补全完成了 >3% 的代码,同时将 Google 员工的编码迭代时间减少了 6%(置信度为 90%)。 这种变化的大小对应于转换特征(例如,关键框架)的典型影响,这些特征通常只影响一个子群体,而 ML 有可能推广到大多数主要语言和工程师。

| | | | ---------------------------------------- | -------: | | ML 添加的所有代码的比例 | 2.6% | | 编码迭代持续时间缩短 | 6% | | 接受率(对于可见时间 >750 毫秒的建议) | 25% | | 每次接受的平均字符数 | 21 |

在生产中测量的单行代码补全的关键指标,供 10k+ Google 内部开发人员在其八种语言的日常开发中使用。

| | | | ------------------------------------------- | ---: | | ML 添加的所有代码的比例(建议中超过 1 行) | 0.6% | | 每次接受的平均字符数 | 73 | | 接受率(对于可见时间 >750 毫秒的建议) | 34% |

在生产中测量的多行代码补全的关键指标,供 5k+ Google 内部开发人员在其八种语言的日常开发中使用。

在探索 API 时提供长补全

我们还将语义补全与全行补全紧密集成。 当出现带有语义单个 token 补全的下拉列表时,我们会以内联方式显示从 ML 模型返回的单行补全。 后者表示对下拉列表中焦点的项目的延续。 例如,如果用户查看 API 的可能方法,则内联全行补全会显示完整的该方法调用,其中还包含该调用的所有参数。

ML 通过继续作为焦点的语义下拉列表补全来集成全行补全。

ML 提供的多行补全建议。

结论和未来工作

我们展示了如何使用基于规则的语义引擎和大型语言模型的结合来显着提高开发人员的生产力,从而实现更好的代码补全。 作为下一步,我们希望通过在推理时向 ML 模型提供额外信息来进一步利用 SE。 一个例子是可以进行 ML 和 SE 之间的来回长期预测,其中 SE 迭代地检查正确性并向 ML 模型提供所有可能的延续。 在添加由 ML 驱动的新功能时,我们希望注意不仅仅是“智能”结果,而是确保对生产力产生积极影响。

鸣谢

这项研究是 Google Core 和 Google Research, Brain Team 之间为期两年的合作成果。 特别感谢 Marc Rasi, Yurun Shen, Vlad Pchelin, Charles Sutton, Varun Godbole, Jacob Austin, Danny Tarlow, Benjamin Lee, Satish Chandra, Ksenia Korovina, Stanislav Pyatykh, Cristopher Claeys, Petros Maniatis, Evgeny Gryaznov, Pavel Sychev, Chris Gorgolewski, Kristof Molnar, Alberto Elizondo, Ambar Murillo, Dominik Schulz, David Tattersall, Rishabh Singh, Manzil Zaheer, Ted Ying, Juanjo Carin, Alexander Froemmgen, Maxim Kachurovskiy, 和 Marcus Revaj 的贡献。 标签:

快速链接

×

其他感兴趣的帖子

关注我们