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