作者 | 微軟研究院
譯者 | 核子可樂
策劃 | 淩敏
去年 7 月,微軟聯合 GitHub、OpenAI 打造了一個全新的代碼生成 AI——GitHub Copilot,其背後的功臣正是 OpenAI 深度學習驅動平台 Codex。不過,資料顯示,Codex 的準确率大概有 30%。日前,微軟推出 AI 代碼審查工具 Jigsaw,進一步提升 AI 編碼的準确率。
目前,各類可調大型預訓練語言模型(包括 GPT-3、Codex 等)已經能夠根據程式員用自然語言表達的意圖,成功編寫出代碼。這類自動化模型當然有望提升每一位軟體開發從業者的生産效率,但也由于模型自身難以了解程式語義,是以尚無法保證生成代碼的最終品質。
在我們的研究論文《Jigsaw:當大型語言模型牽手程式綜合》(Jigsaw: Large Language Models meet Program Synthesis,文章已被國際軟體工程會議 ICSE 2022 接收)中,我們介紹了一種可以提高這類大型語言模型性能的新工具。Jigsaw 中包含可以了解程式文法及語義的後處理技術,可利用使用者回報不斷提升修正能力。配合多模輸入,Jigsaw 即可為 Python Pandas API 合成代碼。
我們的經驗表明,随着這些大型語言模型逐漸演變為“按意圖合成代碼”的利器,Jigsaw 也将在提高系統準确性方面發揮重要作用。
機器編寫軟體的前景與風險
以 OpenAI 的 Codex 項目為代表的各類大型語言模型,正在重塑程式設計領域的整體面貌。軟體開發者如今在處理程式設計任務時,可以直接對所需代碼片段的功能做出英文描述,Codex 則通過 Python 或 JavaScript 等語言合成出預期代碼。
然而,機器編寫的代碼可能并不正确、甚至無法編譯或運作。是以,Codex 使用者必須在代碼使用前進行審查。
在 Jigsaw 項目中,我們的目标就是讓審查實作部分自動化,幫助 Codex 等大型語言模型按開發者訓示合成代碼、提高生産效率。
假定 Codex 為軟體開發者提供了一條代碼片段,之後開發者可以檢查代碼能否編譯、借此做出初步審查。如果未能編譯,則開發者可以參考編譯器提供的報錯資訊進行修複。而一旦代碼最終編譯完成,開發者則通過輸入 / 輸出(I/O)開展測試,檢查代碼所産生的輸出是否符合預期。
這一階段中,代碼同樣有可能暴露出問題(例如引發異常或産生錯誤輸出),這就要求開發者進一步進行修複。我們證明,這一過程完全可以自動化執行。Jigsaw 将預期代碼的英文描述以及 I/O 示例作為輸入,再将輸入與相關輸出進行配對,最終保證 Python 輸出代碼能夠正确編譯、且可以根據輸入産生符合預期的高品質輸出結果。
在之前提到的論文《Jigsaw:當大型語言模型牽手程式綜合》中,我們在 Python Pandas 上評估了這種方法。Pandas 是目前在資料科學領域中廣泛使用的 API,具有數百個用于操作資料框或行清單的函數。
要讓開發者記住這麼多函數用法顯然太不“人道”,更好的辦法當然是使用 Jigsaw。在它的幫助下,使用者可以通過英語描述預期轉換效果、提供輸入資料框與對應的輸出資料框,之後由 Jigsaw 合成預期代碼。例如,假定開發者希望從下表的“country”列中删除字首“Name:”,可以在 Pandas 通過執行以下操作來實作:
df['c'] = df['c'].str.replace('Name: ', '')

圖一:輸入資料框與輸出資料框。Jigsaw從名為“country”的列中删除了多餘部分“Name:”。
在傳統流程中,剛剛接觸 Pandas 的開發者往往需要先熟悉函數及其參數,才能整理出相應的代碼片段;或者是将查詢與示例結果釋出到 Stack Overflow 等論壇上,之後坐等熱心網友的回複。另外,開發者還時常需要結合上下文背景大幅調整響應。相比之下,直接使用英語來描述自己想要的輸入 - 輸出表(或資料框)無疑要友善得多。
Jigsaw 工作原了解析
Jigsaw 首先擷取英語查詢資訊、再配合适當的上下文對查詢進行預處理,由此建構起可被饋送至大型語言模型的輸入。Jigsaw 模型屬于黑箱形式,而且已經使用 GPT-3 及 Codex 完成了評估。
這種設計的最大優勢,在于能夠以即插即用的形式支援各類最新、最好的可用模型。在模型生成輸出代碼之後,Jigsaw 就會檢查其是否滿足 I/O 示例。如果滿足,則模型輸出正确、代碼直接可用。在我們的實驗中,約有 30% 的輸出代碼無需修複、直接可用。但如果代碼有誤,則在後處理階段啟用修複流程。
圖二:所有供大型語言模型(包括GPT-3、Codex等)的輸入都将經過預處理。如有必要,後處理輸出還将被傳回至最終使用者進行驗證和編輯。學習結果則被回報至預處理和後處理機制當中,用以進一步改進 Jigsaw 的修正能力
在後處理過程中,Jigsaw 使用三種轉換來實作代碼修複。其中每一種轉換均由我們在 GPT-3 及 Codex 中觀察到的故障模式所驅動。令人意外的是,GPT-3 與 Codex 的代碼錯誤案例間有着極高的相似性,是以 Jigsaw 在後進行中使用的故障模式對二者都有很大幫助。
通過三種轉換實作代碼修複
變量轉換
我們觀察到,Codex 的輸出中經常會出現不正确的變量名稱。例如,大部分公開代碼會将資料框命名為 df1、df2 等,是以 Codex 也就直接照搬了過來。然而,如果開發人員實際使用的是 g1、g2 等資料框名稱,那麼 Codex 對 df1、df2 的堅持就會引發問題。
另外,Codex 還時常把收到的變量名稱搞混。例如,正确的輸出應該是 df1.merge(df2),但卻被它寫成了 df2.merge(df1)。為了修複這些錯誤,Jigsaw 需要把 Codex 生成代碼中的名稱替換為可用範圍内的一切名稱,直到其滿足 I/O 示例。我們發現,這種簡單的轉換已經足以解決機器代碼中的大多數問題。
參數轉換
有時候,Codex 生成的代碼還會調用預期 API 函數,但其中某些參數卻存在錯誤。例如:
a.) 查詢 - 删除‘inputB’列中的所有重複行
dfout = dfin.drop_duplicates(subset=['inputB']) # Model
dfout = dfin.drop_duplicates(subset=['inputB'],keep=False) # Correct
b.) 将 df 當中 country 列内的所有 CAN 查詢 - 替換為 Canada
df = df.replace({'Canada':'CAN'}) # Model
df = df.replace({'country':{'Canada':'CAN'}) # Correct
為了修複此類錯誤,Jigsaw 會成系統地枚舉一切可能的參數,并以 Codex 生成的函數及參數序列作為起點,直到找出滿足 I/O 示例的組合。
AST 到 AST 轉換
AST(抽象文法樹)就是以樹的形式表示代碼。因為 Codex 這類模型會在句法層級上設計代碼結構,是以可能會生成句法與預期相近、但某些字元存在問題的輸出結果。例如:
a.) 查詢 - 選擇 dfin 中符合條件的各行,要求其 bar 值 60
dfout = dfin[dfin['bar']60] # Model
dfout = dfin[(dfin['bar']60)] # Correct
錯誤——缺少括号會改變優先級次序并引發異常
b.) 查詢 - 計數 df 中重複行的數量
out = df.duplicated() # Model
out = df.duplicated().sum() # Correct
錯誤——需要求和以擷取重複行的總量
為了修複這類問題,Jigsaw 還提供随時間學習的 AST 到 AST 轉換功能。使用者首先自行修複代碼,再由 Jigsaw UI 捕捉編輯結果、把結果推廣到其他适用的轉換場景當中,同時學習轉換知識。随使用次數與轉換次數的增加,Jigsaw 也将逐漸掌握開發者的修複思路。
評估
我們還在多種資料集上評估了 Codex 直出代碼與 Jigsaw 修複後代碼,并測量二者的準确度(即系統能夠産生預期結果的情況,在總體資料集任務中所占的百分比)差異。Codex 直出代碼的準确度大約在 30% 左右,這也與 OpenAI 論文中的觀點相符。Jigsaw 能夠将準确度提高到 60% 以上,如果配合使用者回報、則準确度可以進一步拉升至超過 80%。
展望未來
我們已經釋出了可供公開使用的 Jigsaw 評估資料集。每個資料集中包含多項任務,各項任務分别對應一條英語查詢與一個 I/O 示例。要解決任務,模型需要生成一段 Pandas 代碼,并将提供的輸入資料框映射至相應的輸出資料框。我們希望大家能以這套資料集為基礎,評估并比較更多其他系統。盡管目前部分資料集隻包含英語查詢加 I/O 示例等簡單任務,但 Jigsaw 資料集仍然開創了行業先河。
随着語言模型的不斷發展壯大,我們相信 Jigsaw 将一路為其保駕護航、幫助這些大型模型在更多實際場景内發揮作用。當然,這隻是相關研究領域内的冰山一角,我們還有以下關鍵問題需要解決:
這些語言模型能否通過訓練掌握代碼語義?
Jigsaw 能否內建進更好的預處理與後處理步驟?例如,我們正在研究用表述分析技術改進後處理效果。
I/O 示例對于 Python Pandas 之外的其他 API 是否有效?如果沒有相應的 I/O 示例,我們該如何解決?怎樣才能使 Jigsaw 适應 JavaScript 等語言以及 Python 中的通用代碼?
Jigsaw 目前的輸出結果仍有改進空間,就是說除了用自然語言執行查詢之外,開發者仍需要對輸出進行評估和調查。
這就是我們正在努力探索的幾個有趣方向。随着 Jigsaw 的不斷改進和完善,相信它的自動化能力将在提高程式員生産力方面發揮重要作用。我們也将嘗試把 Python Pandas API 方面的經驗推廣到其他 API 和程式設計語言當中。