原標(biāo)題ML 增強(qiáng)的代碼完成提高了開發(fā)人員的工作效率
作者:google Research 高級軟件工程師 Maxim Tabachnyk 和高級工程經(jīng)理 Stoyan Nikolov
代碼復(fù)雜性的增加對軟件工程的生產(chǎn)力提出了關(guān)鍵挑戰(zhàn)。代碼完成一直是一個(gè)必不可少的工具,它有助于減輕集成開發(fā)環(huán)境(IDE) 中的這種復(fù)雜性。通常,代碼完成建議是使用基于規(guī)則的語義引擎(SE) 實(shí)現(xiàn)的,這些引擎通常可以訪問完整的存儲(chǔ)庫并了解其語義結(jié)構(gòu)。最近的研究表明,大型語言模型(例如,Codex和PaLM)可以實(shí)現(xiàn)更長、更復(fù)雜的代碼建議,因此出現(xiàn)了有用的產(chǎn)品(例如,Copilot)。然而,機(jī)器學(xué)習(xí) (ML) 支持的代碼完成如何影響開發(fā)人員的生產(chǎn)力,除了感知的生產(chǎn)力和接受的建議,這個(gè)問題仍然懸而未決。
今天我們描述了我們?nèi)绾谓Y(jié)合 ML 和 SE 來開發(fā)一種新穎的Transformer- 基于混合語義 ML 代碼完成,現(xiàn)在可供 Google 內(nèi)部開發(fā)人員使用。我們討論如何通過以下方式組合 ML 和 SE:(1)使用 ML 重新排列 SE 單標(biāo)記建議,(2)使用 ML 應(yīng)用單行和多行完成并使用 SE 檢查正確性,或(3)使用單和通過 ML 對單標(biāo)記語義建議進(jìn)行多行延續(xù)。我們將 10k+ 名 Google 員工(超過 3 個(gè)月的八種編程語言)的混合語義 ML 代碼完成與對照組進(jìn)行比較,發(fā)現(xiàn)編碼迭代時(shí)間(構(gòu)建和測試之間的時(shí)間)減少了 6%,上下文切換減少了 7%(即,離開 IDE)當(dāng)暴露于單行 ML 完成時(shí)。這些結(jié)果表明,ML 和 SE 的結(jié)合可以提高開發(fā)人員的生產(chǎn)力。目前,
Transformers for Completion
代碼完成的一種常見方法是訓(xùn)練 Transformer 模型,該模型使用自注意力機(jī)制進(jìn)行語言理解,以實(shí)現(xiàn)代碼理解和完成預(yù)測。我們處理類似于語言的代碼,用子詞標(biāo)記和SentencePiece詞匯表表示,并使用在TPU上運(yùn)行的編碼器-解碼器轉(zhuǎn)換器模型進(jìn)行完成預(yù)測。輸入是光標(biāo)周圍的代碼(~1000-2000 個(gè)標(biāo)記),輸出是一組完成當(dāng)前行或多行的建議。序列是通過解碼器上的波束搜索(或樹探索)生成的。
在 Google 的monorepo培訓(xùn)期間,我們屏蔽了一行的其余部分和一些后續(xù)行,以模仿正在積極開發(fā)的代碼。我們在八種語言(C++、JAVA、Python/ target=_blank class=infotextkey>Python、Go、Typescript、Proto、Kotlin 和 Dart)上訓(xùn)練了一個(gè)模型,并觀察到所有語言的性能改進(jìn)或相同,無需專用模型。此外,我們發(fā)現(xiàn)約 0.5B 參數(shù)的模型大小可以很好地權(quán)衡高預(yù)測精度、低延遲和資源成本。該模型極大地受益于 monorepo 的質(zhì)量,該質(zhì)量由指南和審查強(qiáng)制執(zhí)行。對于多行建議,我們迭代地應(yīng)用具有學(xué)習(xí)閾值的單行模型來決定是否開始預(yù)測下一行的完成情況。
使用 ML 重新排列單個(gè)令牌建議
當(dāng)用戶在 IDE 中鍵入時(shí),ML 模型和 SE 同時(shí)在后端以交互方式請求代碼完成。SE 通常只預(yù)測單個(gè)令牌。我們使用的 ML 模型預(yù)測多個(gè)標(biāo)記直到行尾,但我們只考慮第一個(gè)標(biāo)記來匹配來自 SE 的預(yù)測。我們確定了 SE 建議中也包含的前三個(gè) ML 建議,并將它們的排名提升到了首位。然后,重新排序的結(jié)果會(huì)在 IDE 中顯示為用戶的建議。
在實(shí)踐中,我們的 SE 在云中運(yùn)行,提供開發(fā)人員熟悉的語言服務(wù)(例如,語義完成、診斷等),因此我們將 SE 配置在與執(zhí)行 ML 推理的 TPU 相同的位置上運(yùn)行。SE 基于一個(gè)內(nèi)部庫,該庫提供類似編譯器的低延遲特性。由于設(shè)計(jì)設(shè)置,請求是并行完成的,而 ML 通常可以更快地提供服務(wù)(中位數(shù)約為 40 毫秒),我們不會(huì)為完成添加任何延遲。我們觀察到實(shí)際使用中的質(zhì)量顯著提高。對于 28% 的接受完成,完成的排名由于提升而更高,在 0.4% 的情況下更差。此外,我們發(fā)現(xiàn)用戶在接受完成建議之前輸入的字符數(shù)減少了 10% 以上。
檢查單行/多行 ML 完成的語義正確性
在推理時(shí),ML 模型通常不知道其輸入窗口之外的代碼,并且在訓(xùn)練期間看到的代碼可能會(huì)錯(cuò)過最近在積極變化的存儲(chǔ)庫中完成所需的添加。這導(dǎo)致了 ML 驅(qū)動(dòng)的代碼完成的一個(gè)常見缺點(diǎn),即模型可能會(huì)建議看起來正確但無法編譯的代碼。根據(jù)內(nèi)部用戶體驗(yàn)研究,隨著時(shí)間的推移,此問題可能會(huì)導(dǎo)致用戶信任度下降,同時(shí)降低生產(chǎn)力收益。
我們使用 SE 在給定的延遲預(yù)算內(nèi)執(zhí)行快速語義正確性檢查(端到端完成<100ms),并使用緩存的抽象語法樹來實(shí)現(xiàn)“完整”的結(jié)構(gòu)理解。典型的語義檢查包括引用解析(即,該對象是否存在)、方法調(diào)用檢查(例如,確認(rèn)使用正確數(shù)量的參數(shù)調(diào)用方法)和可分配性檢查(確認(rèn)類型是否符合預(yù)期)。
例如,對于編碼語言Go,約 8% 的建議在語義檢查之前包含編譯錯(cuò)誤。然而,語義檢查的應(yīng)用過濾掉了 80% 的不可編譯的建議。在加入該功能的前六周,單行完成的接受率提高了 1.9 倍,這可能是由于用戶信任度的提高。作為比較,對于我們沒有添加語義檢查的語言,我們只看到接受度增加了 1.3 倍。
結(jié)果
超過 10k 的 Google 內(nèi)部開發(fā)人員在他們的 IDE 中使用完成設(shè)置,我們測量了 25-34% 的用戶接受率。我們確定基于轉(zhuǎn)換器的混合語義 ML 代碼完成完成了超過 3% 的代碼,同時(shí)將 Google 員工的編碼迭代時(shí)間減少了 6%(在 90% 的置信水平下)。轉(zhuǎn)變的大小對應(yīng)于觀察到的轉(zhuǎn)換特征(例如,關(guān)鍵框架)的典型影響,這些特征通常只影響一個(gè)子群體,而 ML 有可能推廣到大多數(shù)主要語言和工程師。
在探索 API 的同時(shí)提供長補(bǔ)
全我們還將語義補(bǔ)全與全行補(bǔ)全緊密集成。當(dāng)出現(xiàn)帶有語義單標(biāo)記補(bǔ)全的下拉菜單時(shí),我們會(huì)顯示從 ML 模型返回的單行補(bǔ)全。后者表示作為下拉焦點(diǎn)的項(xiàng)目的延續(xù)。例如,如果用戶查看 API 的可能方法,則內(nèi)聯(lián)完整行完成顯示完整的方法調(diào)用還包含調(diào)用的所有參數(shù)。
結(jié)論和未來的工作
我們展示了如何結(jié)合使用基于規(guī)則的語義引擎和大型語言模型來顯著提高開發(fā)人員的工作效率并實(shí)現(xiàn)更好的代碼完成。作為下一步,我們希望通過在推理時(shí)向 ML 模型提供額外信息來進(jìn)一步利用 SE。一個(gè)例子是在 ML 和 SE 之間來回進(jìn)行長預(yù)測,其中 SE 迭代地檢查正確性并為 ML 模型提供所有可能的延續(xù)。在添加由 ML 提供支持的新功能時(shí),我們要注意超越“智能”結(jié)果,但要確保對生產(chǎn)力產(chǎn)生積極影響。
致謝
本研究是 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 和 Marcus Revaj 的貢獻(xiàn)。