谷歌公開自家「AI+軟件工程」框架DIDACT:數(shù)千名開發(fā)者內(nèi)部測試,用了都說生產(chǎn)力高
任何一個(gè)大型軟件都不是一開始就構(gòu)思完善的,而是通過開發(fā)人員的一次次改進(jìn)、編輯、單元測試、修復(fù)構(gòu)建錯(cuò)誤、解決代碼審查,再循環(huán)解決問題,直到滿足上線需求后才能把代碼合并到倉庫中。
控制整個(gè)過程的學(xué)問就叫做軟件工程。
軟件工程并非一個(gè)獨(dú)立的過程,而是由開發(fā)人員、代碼審查員、錯(cuò)誤報(bào)告員、軟件架構(gòu)師和各種開發(fā)工具(如編譯器、單元測試、連接器、靜態(tài)分析器)之間的交流組成。
最近,Google公布了自家的DIDACT(Dynamic Integrated Developer ACTivity,動態(tài)集成開發(fā)人員活動)框架,用AI技術(shù)增強(qiáng)軟件工程,將軟件開發(fā)的中間狀態(tài)作為訓(xùn)練數(shù)據(jù),輔助開發(fā)人員編寫、修改代碼,并實(shí)時(shí)了解軟件開發(fā)的動態(tài)。
DIDACT是一個(gè)多任務(wù)模型,在編輯、調(diào)試、修復(fù)和代碼審查在內(nèi)的開發(fā)活動上進(jìn)行訓(xùn)練
研究人員在內(nèi)部構(gòu)建并部署了三個(gè)DIDACT工具,注釋解析、構(gòu)建修復(fù)和提示預(yù)測,每個(gè)工具都集成在開發(fā)工作流程的不同階段。
軟件工程=交互日志
幾十年以來,Google的軟件工程工具鏈都是將與代碼相關(guān)的每個(gè)操作都存儲為工具和開發(fā)人員之間的交互日志。
原則上,用戶可以使用這些記錄來詳細(xì)重放軟件開發(fā)過程中的關(guān)鍵變更過程,即Google的代碼庫是如何形成的,包括每一次的代碼編輯、編譯、注釋、變量重命名等。
Google的開發(fā)團(tuán)隊(duì)會將代碼存放于monorepo(單倉庫,mono repository)中,即包含所有工具和系統(tǒng)的代碼存儲庫。
軟件開發(fā)人員通常在云中客戶端(Clients in the Cloud, CitC)系統(tǒng)管理的本地寫時(shí)復(fù)制(copy-on-write)工作空間中對代碼修改進(jìn)行實(shí)驗(yàn)。
當(dāng)開發(fā)者準(zhǔn)備好將一組代碼變更打包在一起實(shí)現(xiàn)某個(gè)任務(wù)時(shí)(比如修復(fù)某個(gè)bug),需要在Google的代碼審查系統(tǒng)Critique中創(chuàng)建了一個(gè)變更列表(changelist, CL)。
與常用的代碼評審系統(tǒng)一樣,開發(fā)人員與同行評審者會就功能和風(fēng)格進(jìn)行交流,然后編輯CL以解決評審注釋時(shí)提出的問題。
最后,評審員宣布代碼「LGTM?。╨ooks good to me)」,并把CL合并到代碼存儲庫中。
當(dāng)然,除了與代碼評審員的對話之外,開發(fā)人員還需要維護(hù)大量與其他軟件工程工具的「對話」,包括編譯器、測試框架、鏈接器、靜態(tài)分析器、模糊測試工具等。
軟件開發(fā)中涉及的復(fù)雜活動網(wǎng)絡(luò)的說明:開發(fā)人員的活動、與代碼評審員的交互以及對編譯器等工具的調(diào)用。
軟件工程中的多任務(wù)模型
DIDACT利用工程師和工具之間的交互對機(jī)器學(xué)習(xí)模型賦能,通過建議或優(yōu)化開發(fā)人員在執(zhí)行軟件工程任務(wù)時(shí)的行動,來輔助Google開發(fā)人員參與軟件工程過程。
為此,研究人員定義了一些關(guān)于單個(gè)開發(fā)人員活動的任務(wù):修復(fù)損壞的構(gòu)建、預(yù)測代碼審查注釋、處理代碼審查注釋、重命名變量、編輯文件等。
然后為每個(gè)活動定義一個(gè)通用的形式:獲取某個(gè)State(代碼文件)、某個(gè)Intent(特定于某個(gè)活動的注釋,例如代碼評審注釋或編譯器錯(cuò)誤),并生成一個(gè)Action(用于處理任務(wù)的操作)。
其中Action就像一個(gè)迷你編程語言,可以擴(kuò)展為新添加的活動,涵蓋了編輯、添加注釋、重命名變量、標(biāo)記代碼錯(cuò)誤等內(nèi)容,也可以稱這種語言為DevScript。
DIDACT模型的輸入提示為任務(wù)、代碼片段和與該任務(wù)相關(guān)的注釋,輸出為開發(fā)動作,如編輯或評論
狀態(tài)-意圖-行動(State-Intent-Action)的定義形式能夠以通用的方式捕捉不同的任務(wù),更重要的是,DevScript可以簡潔地表達(dá)復(fù)雜動作,不需要像動作發(fā)生后那樣輸出整個(gè)狀態(tài)(原始代碼),使得模型更有效且更可解釋。
比如重命名可能會修改代碼文件中的多處地方,但模型只需要預(yù)測一個(gè)重命名操作即可。
給AI模型配個(gè)程序員
DIDACT在個(gè)人輔助任務(wù)上運(yùn)行得非常好,比如下面的例子中演示了DIDACT在功能完成后的代碼清理工作,先輸入代碼審查員的最終注釋(圖片中標(biāo)記為human),然后預(yù)測解決注釋中提出問題所需要的操作(用diff展現(xiàn))。
給定代碼的初始片段和代碼審查員附加到代碼片段的注釋,DIDACT的Pre-Submit Cleanup任務(wù)生成處理這些注釋的編輯操作(文本的插入和刪除)
DIDACT的多模態(tài)性質(zhì)也產(chǎn)生了一些隨規(guī)模增大而涌現(xiàn)出的全新行為,其中一種能力是歷史增強(qiáng)(history augmentation),可以經(jīng)由提示來啟用這種能力,了解開發(fā)人員最近做了什么可以讓模型更好地預(yù)測開發(fā)人員下一步應(yīng)該做什么。
歷史增強(qiáng)代碼補(bǔ)全的演示
歷史增強(qiáng)代碼補(bǔ)全任務(wù)可以展現(xiàn)這種能力,上圖的例子中,開發(fā)人員添加了一個(gè)新的函數(shù)參數(shù)(1),并將光標(biāo)移動到文檔中(2)。以開發(fā)人員編輯的歷史和光標(biāo)位置為條件,模型通過正確預(yù)測新參數(shù)的文檔字符串條目來完成行(3)。
在難度更大的歷史增強(qiáng)編輯預(yù)測任務(wù)中,模型能夠以歷史一致的方式選擇下一步編輯的位置。
在多個(gè)鏈?zhǔn)降系木庉嬵A(yù)測的演示
如果開發(fā)人員刪除了函數(shù)參數(shù)(1),則模型可以根據(jù)歷史正確地預(yù)測對刪除參數(shù)的文檔字符串(2)的更新(而無需人類開發(fā)人員手動地將光標(biāo)放置在那里),并且在語法上(也可以說是語義上)正確地更新函數(shù)(3)中的語句。
有了歷史后,模型可以明確地決定如何正確地繼續(xù)「編輯代碼過程」,而如果沒有歷史記錄,模型就無法知道丟失的函數(shù)參數(shù)是故意的(因?yàn)殚_發(fā)人員正在進(jìn)行更長的編輯操作以刪除參數(shù))還是意外情況(模型應(yīng)該重新添加參數(shù)以修復(fù)問題)。
除此之外,模型還可以完成更多的任務(wù),比如從一個(gè)空白文件開始,要求模型連續(xù)預(yù)測接下來的編輯操作,直到編寫出一個(gè)完整的代碼文件。
最重要的是,該模型能夠以一種對開發(fā)人員來說很自然的、循序漸進(jìn)的方式輔助編寫代碼:
首先創(chuàng)建了一個(gè)具有導(dǎo)入、標(biāo)志和基本main函數(shù)的完整工作框架;然后再逐步添加新功能,例如從文件中閱讀和寫入結(jié)果,并添加基于用戶提供的正則表達(dá)式來過濾某些行的功能。
結(jié)論
DIDACT將Google的軟件開發(fā)過程轉(zhuǎn)變?yōu)闄C(jī)器學(xué)習(xí)開發(fā)人員助理的訓(xùn)練演示,并使用這些演示數(shù)據(jù)來訓(xùn)練模型,以循序漸進(jìn)的方式構(gòu)建代碼,與工具和代碼審查人員交互。
DIDACT方法補(bǔ)充了Google和其他公司的大型語言模型所取得的巨大成就,可以減少工作量,提高生產(chǎn)力,并提高軟件工程師的工作質(zhì)量。