Stories

Detail Return Return

【論文解讀】用於代碼處理的語言模型綜述 - Stories Detail

1.簡要介紹

在這項工作中,論文系統地回顧了在代碼處理方面的最新進展,包括50個+模型,30個+評估任務和500個相關工作。論文將代碼處理模型分解為由GPT家族表示的通用語言模型和專門預訓練的代碼模型,通常具有定製的目標。論文討論了這些模型之間的關係和差異,並強調了代碼建模從統計模型和rnn到預訓練的transformer和LLM的歷史轉變,這與NLP所採取的過程完全相同。還討論了特定於代碼的特性,如AST、CFG和單元測試,以及它們在訓練代碼語言模型中的應用,並確定了該領域的關鍵挑戰和潛在的未來方向。

2.代碼處理的語言模型的評估

在過去的十年裏,軟件工程界提出了各種評估任務來評估代碼模型。CodeXGLUE將大多數此類任務合併整合為一個單一的基準測試,包括代碼理解任務,如克隆檢測、缺陷檢測和序列到序列的生成任務,如代碼修復、代碼翻譯、程序合成和代碼摘要。然而,在Chen等人(2021)引入HumanEval和Codex之後,text-to-code的合成成為NLP社區關注的焦點,並已成為評估LLM的標準任務(圖2)。因此,論文首先簡要介紹了每一個傳統任務以及預訓練語言模型的應用,並在圖3、4中提供了每個任務的相關工作的全面列表。然後,回顧了評估指標,並更詳細地研究了程序合成。最後,論文還討論了存儲庫級評估的最新趨勢。在附錄A中,列出了每個下游任務的基準測試。

2.1 代碼處理的下游任務
根據軟件工程中的自定義,論文根據代碼的輸入/輸出方式對代碼的評估任務進行分類,並將這些任務分為五類:text-to-code, code-to-code, code-to-text, code-to-patterns和text-to-text。這種分類法與NLP中的理解-生成二分法交織在一起,因為每個類別可能同時包含理解和生成任務。

2.1.1 text-to-code
Text-to-code 任務以文本作為輸入,並輸出代碼。 - Code retrieval旨在檢索給定的自然語言查詢的相關代碼,或從未註釋的語料庫中挖掘並行文本代碼對。這個任務通常是通過計算查詢代碼和候選代碼的嵌入之間的相似性度量來完成的,而由雙向語言模型產生的上下文嵌入——如BERT——已經被證明是非常有用的。 - Code synthesis 旨在生成給定一個自然語言描述的代碼(通常是一個函數或一個方法)。這個任務可以看作是使用生成模型而不是檢索模型的代碼檢索的更新版本。統計機器翻譯(SMT)和神經機器翻譯(NMT)模型通常使用增強的解碼器,利用編程語言獨特的語法規則,且已被廣泛應用於這項任務。然而,基於transformer架構的預訓練語言模型通過即使沒有特定任務的微調直接生成自迴歸語言建模風格的源代碼,改變了遊戲規則。論文將在3.3中更詳細地討論這個任務。 - Text-to-SQL是代碼合成的一種特殊情況(也可以説是更容易的),其中模型的任務是從自然語言查詢中生成SQL命令。由於SQL的結構化特性(與Python和C等通用語言相比)以及在數據管理中的廣泛應用,它一直是一個特別感興趣的話題。 - Math programming這也是代碼合成的一種特殊情況,其中需要一個語言模型,通過生成將由外部解釋器執行的代碼來解決數學推理問題。該任務從數值計算中抽象出了推理過程,因此對評估LLM具有特別的意義。

2.1.2 Code-to-Code
Code-to-Code的任務以代碼作為輸入,並輸出代碼。 - Code search是一個類似於代碼檢索的任務,與後者的不同之處僅在於,輸入是一個現有的代碼片段,通常使用與目標不同的編程語言。 - Code completion旨在完成一個帶有其前綴的代碼片段。這本質上是應用於代碼的語言建模,相關技術已經逐步引入: n-gram、RNN和transformer。然而,由於編程語言的結構化性質,許多早期研究發現語法輔助統計模型表現更好,神經模型直到2018年之後才成為主導地位(直觀概述見圖3)。 - Code translation 旨在將一段代碼(通常是一個函數或方法)翻譯成另一種編程語言。代碼翻譯和跨語言代碼搜索之間的關係類似於代碼合成和text-to-code檢索之間的關係,SMT/MNT模型也被廣泛應用於這項任務。代碼合成在幫助程序員編寫代碼片段方面很有用,而代碼翻譯是遷移用過時語言編寫的舊項目的一種重要技術。然而,作者還沒有看到這樣的應用程序,因為即使是最強大的語言模型的上下文窗口也是相當有限的。 - Code repair 也被稱為bug修復,旨在修復一個有問題的代碼。與代碼翻譯一樣,它也是一項傳統的序列到序列的生成任務,關於這個主題目前已有大量的研究。 - Cloze test是在bert式預訓練興起之後,最近提出的代碼處理任務。由於編程語言的獨特語義,這個測試經常選擇幾個關鍵字,如min和max。 - Code infilling是另一項最近提出的任務,在fill-in-the-middle預訓練開始流行之後。它是代碼完成的泛化,空白不僅給出了左邊的上下文,還給出了右邊的上下文。但是,它與填空測試的不同之處在於,填空測試的目標只是一個標記,而代碼填充的目標可以是整行甚至多行,這需要一個解碼器來自動迴歸生成。 - Obfuscation指重命名標識符(例如變量、方法和類)的過程,例如為通用名稱,如var_1、var_2或x、y。它是病毒檢測、知識產權保護和代碼縮放方面的重要技術。去混淆是指反向過程,即從混淆的程序中恢復有意義的標識符名稱。混淆對語言模型的應用很少,因為它可以很容易地靜態地實現,但去混淆近年來已經成為人們更感興趣的話題,並被用作代碼語言模型的預訓練目標 - Unit test generation旨在為一個給定的程序生成單元測試。在Codex和其他代碼LLM出現之前,該領域中幾乎所有的工作都採用了非神經方法(見圖3)。然而,在LLM的時代,這項任務越來越重要,因為研究表明,目前評估LLM的程序綜合能力的單元測試可能不夠充分 - Assertion generation是一個與單元測試密切相關的任務。給定一個程序和一組單元測試,這個任務的旨在生成斷言(在軟件工程中也稱為預言),以使用單元測試來評估程序。這個任務通常沒有被NLP社區注意到,因為用於評估LLM的程序綜合任務通常涉及獨立的、競爭風格的方法,這樣簡單地斷言程序輸出和預期答案之間相似就足夠了。 - Mutant generation旨在為突變測試生成給定程序的變體,與單元測試生成和斷言生成密切相關。給定的一組單元測試和斷言沒有檢測到的變體表明需要額外的測試用例或更好的斷言。最近,屏蔽源代碼中的標記並從屏蔽語言模型的輸出中對它們進行採樣已經成為這項任務的常用方法。Papadakis等人(2019年)就這一主題進行了調查。 - Fuzzing旨在改變一組給定的單元測試,以生成新的測試用例,這是另一個與測試軟件相關的任務。雖然最近有許多關於模糊目標深度學習庫的工作,但很少有人使用語言模型來進行這一過程(見圖3)。 - Type prediction旨在預測動態編程語言的類型,如Python和JavaScript。它已被用作代碼語言模型的預訓練目標其中它通常被簡化為一個二進制標記任務,以預測代碼中的哪些標記是標識符。

2.1.3 Code-to-Text
Code-to-Text任務以代碼作為輸入,並輸出文本。 - Code summarization 也被稱為文檔字符串生成,其旨在為一個給定的代碼段(通常是一個函數或方法)生成一個自然語言描述。這與代碼合成相反,SMT/NMT技術也有同樣的應用。 - Code review旨在自動化同行代碼評審的過程,並可能有多種形式。許多早期的工作將其定義為一個二進制分類任務,即在提交時接受或拒絕更改,而另一些工作則利用信息檢索技術從現有的評論池中推薦評論。然而,隨着生成模型變得越來越強大,研究人員還將直接生成評論作為一項序列到序列的學習任務進行了研究。 - Identifier prediction是預測代碼中的標識符名稱的任務。由於這些名稱被認為包含重要的語義信息,該任務已被用於代碼摘要,以及預訓練代碼模型

2.1.4 Code-to-Patterns
Code-to-Patterns任務要對代碼進行分類。 - Defect detection預測輸入代碼是否有問題,這是一個標準的單句分類任務。 - Clone detection預測兩個代碼片段是否會相互克隆。在軟件工程中,有四種類型的代碼克隆,其中最具挑戰性的識別類型是語義克隆,即具有相同功能的語法不相同的代碼。由於該任務可以看作是一個兩句分類任務,BERT風格語言模型得到了廣泛的應用 - Code classification 由Mou等人(2016)推廣,旨在預測一個預定義的標籤集內的一個代碼片段的功能。一個非常相似的任務是作者識別,它可以預測輸入代碼的作者。這兩個任務都是標準的單句分類任務。 - Code reasoning是最近引入的評估LLM的任務,通常作為一般評估基準的一個子集,如MMLU。該任務要求模型對代碼或算法進行推理,並回答以多項選擇題形式編寫的相關問題,其範圍可能從概念理解到數值計算和複雜性分析。

2.1.5 Text-to-Text
Text-to-Text以文本作為輸入,並輸出文本。 - Document translation是與代碼相關的文檔的自動翻譯。由於機器翻譯的模型、數據集和提示策略在NLP中非常豐富,論文沒有詳細介紹這項任務。 - Log parsing旨在分析由軟件產品產生的系統日誌,例如將日誌解析為結構化模板或從原始日誌中查找異常。

2.2 評價指標
在2.1中提到的任務中,理解任務在形式上與自然語言理解任務相似,並同樣通過準確性、F1和平均倒數秩(MRR)等指標進行評估,而標識符預測等短生成任務也通過精確匹配的準確性進行評估。Code-to-text的任務使用文本生成的公共指標進行評估,如BLEU 。 另一方面,對涉及代碼生成的任務的評估則更為複雜。大多數早期的工作都評估了語法的正確性,即可以成功解析的生成的百分比。Chen等人(2018)反對此類指標,並建議進行參考文獻匹配,即與參考文獻完全相同的代的百分比。Ren等人(2020)提出了CodeBLUE,這是BLEU的一種變體,通過評估抽象語法樹(AST)和數據流的重疊,考慮代碼語法和語義。 然而,隨着這些年代碼生成模型變得越來越強大,這些基於內容重疊的指標已經不夠用了,因為功能相當的代碼片段在詞法形式上可能會有很大不同。因此,研究人員將注意力轉向了功能正確性。此類指標的一個流行示例是pass@k,由Kulal等人(2019年)提出並由Chen等人(2021年)完善,它是模型通過k個生成樣本中任何一個的程序的所有單元測試的機會的無偏估計值。這個度量可以推廣到passn@k,它將模型提交的數量限制為n,但允許通過k個樣本輸入中給出的單元檢驗進行過濾。

2.3 程序合成
隨着代碼模型的發展,研究人員逐漸將注意力轉向程序合成的實際任務。CONCODE是該領域的早期數據集之一,它包括超過100K個Java方法,並被納入CodeXGLUE基準測試的子網。自2021年以來,該社區已經見證了大量針對這項任務的數據集。其中大多數,包括APPS,HumanEval和MBPP,重點關注Python,但最近的工作也將HumanEval擴展到其他編程語言。DS-1000是一個更現實的Python數據集,它專注於數據科學庫,如NumPy和SciPy,而一些數學推理基準也已被轉換為編程任務,包括MathQA-Python和GSM8K-Python。

2.4 存儲庫級評估
2.1和圖3中討論的大多數評估任務都僅限於單個文件,甚至是單個函數,因為跨文件代碼建模提出的挑戰超出了大多數現有語言模型的能力。然而,最近,位置插值技術已經將LLM的上下文窗口擴展到數十萬token,使將整個存儲庫中的代碼建模評估上下文化成為可能。一些工作研究了利用存儲庫級上下文的代碼完成,Liu等人(2023)提出引用本來評估這些系統。最近,Bairi等人(2023)研究了存儲庫級API遷移和時間編輯等更具挑戰性的任務,Jimenez等人(2023)引入了相應的基準測試,SWE-bench。

3.通用語言模型

由於語言模型擴展到數千億參數,它們中的許多已經證明了重要的編碼能力,即使它們不是專門為代碼設計或訓練的。由CodeX首創,研究人員還發現,對代碼進行持續的預訓練,可以顯著提高語言模型在代碼方面的性能。

3.1 現成的語言模型
大型語言模型通常按照縮放定律在數萬億標記上進行預訓練,如此數量的文本數據通常是一個不同的組合,由不可忽略的部分代碼組成。例如,Pile包括從GitHub 800GB原始數據集中抓取的95GB代碼,而多語言預訓練數據集ROOTS在其1.6TB數據中也包含跨越13種編程語言的163GB的代碼。作為兩個最大的開源預訓練數據集,它們支持了許多具有編碼能力的語言模型。例如,Chen等人(2021)報道了GPT-J在HumanEval上的優秀表現,而Scao等人(2022)報道了GPT-NeoX和BLOOM的在HumanEval上類似結果。LLaMA的預訓練數據集包括來自GitHub的328GB代碼,在HumanEval上獲得了23.7的 pass@1表現,其後繼者LLaMA 2(獲得了更高的分數,為29.9分。 另一方面,閉源模型總體上表現得更好。LaMDA和PaLM,其預訓練數據集分別包含12.5%和5%的代碼,達到14.0和26.2 pass@1表現,而GPT-4的記錄為驚人的67.0(Bubeck等人報告的早期版本(2023)為82),直到最近都一直高於任何預訓練或為代碼教學的專門模型。 最近,總體趨勢是根據修正後的尺度法則,用更大的數據集訓練更小的模型。例如,baichuan2是在2.6T token上訓練的13B模型,而Qwen是在3Ttoken上訓練的14B模型。他們在HumanEval上分別達到17.1和32.3 pass@1。事實證明模型小至1.3B可以獲得的編碼能力相當於更大的模型,同時保持合理的性能一般文本處理,甚至取得一些應急能力如鏈推理。他們的模型Phi-1.5在ChatGPT生成的教科書數據的21B標記和從堆棧溢出和細化網絡過濾後的網絡數據的100B標記上進行訓練,並在HumanEval上獲得41.4 pass@1的性能。這些模型的確切性能如表1所示。

3.2 帶有關於代碼的額外預訓練的語言模型
隨着開創性的基準HumanEval,Chen等人(2021)用Codex啓動了LLM時代,這是在100B額外代碼token上預訓練的GPT-3,是最早的數十億個代碼模型之一。在他們的工作之後,其他研究人員也將他們的LLM專門研究代碼處理,並進行了額外的預訓練。Chowdhery等人(2022年)在7.8B額外代碼token上訓練PaLM以獲得PaLM-Coder,在HumanEval和MBPP(表1)上取得了新的最先進的表現,這些技術後來才被其繼任者PaLM 2-S*打破,PaLM 2的最小版本在未披露的代碼量上進一步訓練。同樣,Lewkowycz等人(2022年)在arXiv論文和數學內容的38.5Btoken上訓練PaLM,而Rozière等人(2023年)在超過500B代碼token上訓練LLaMA 2以獲取Code LLaMA,其在HumanEval上的性能超過了除GPT-4之外的所有先前的LLMs(表1)。Liu等人(2023)通過多任務微調(MFT)進一步訓練Code LLaMA,引入CodeFuse-CodeLLaMA,達到74.4 pass@1,甚至超過了OpenAI發表的GPT-4。 雖然幾乎所有這些模型都是經過CLM預訓練的transformer解碼器,但正如論文在前文中提到的,在此過程中已經引入了一些架構修改。所有這些模型都使用了預範數,GPT-J引入了並行注意,後來被PaLM、GPTNeoX和Phi-1.5所採用。PaLM將MQA和RoPE引入LLM中,RoPE現在被大多數語言模型使用,包括GPT-NeoX、兩代LLaMA、Qwen和baichuan 2 7B版。而BLOOM和13B版的baichuann 2則採用ALiBi進行位置嵌入,而LLaMA 2和Code LLaMA則採用GQA代替MHA或MQA。在後文中,論文展示了專門對代碼進行預訓練的專門模型也密切跟蹤了這些工作進步。

4.用於代碼處理的特定語言模型

隨着GPT和BERT等預訓練的transformer在自然語言處理方面取得了顯著的成功,這種模型架構、學習範式和訓練目標很快被軟件工程社區採用,來製造用於代碼理解和生成的專門模型。在本節中,論文首先回顧用於預訓練代碼語言模型的常用數據集,然後通過它們的模型架構深入到複雜的代碼lm家族:僅編碼器模型、編碼-解碼器模型、僅解碼器模型、UniLM和擴散模型。最後,論文還説明了當前在NLP中應用最近技術的趨勢,如指令調優和強化學習進行代碼處理。表3提供了這些預訓練模型的概述。

4.1 代碼訓練數據集
雖然用於預訓練語言模型的文本數據通常是從網絡中獲取的,但必須經過細緻的、經常是積極的預處理,代碼數據自然是來自GitHub存儲庫的整個公共文檔。更好的是,它們提供了現成的質量指標,如star或fork的數量(儘管Allal等人(2023年)表明,star數與下游性能的相關性較差)。因此,引入了許多大規模的代碼預訓練數據集,包括CodeSearchNet、CodeParrot和the Stack,分別總計20GB、50GB和3TB的代碼文檔(表2)。

雖然這些數據集是用於訓練代碼模型的,但需要注意的是,代碼最終是自然語言的一種特殊形式,因為大多數編程語言的詞彙表都是英語的一個小子集。此外,高質量的代碼經常與自然語言的註釋或文檔交織在一起,這也使模型能夠獲得一般文本表示的某些知識。事實上,在CodeSearchNet中的6.5m函數中,有2.3M與自然語言文檔配對,允許模型對這些雙態數據進行顯式訓練。 與自然語言相比,從GitHub抓取代碼的另一個副產品是提交歷史,它包括提交前的代碼、提交後的代碼和描述提交的短消息,這些消息可以鬆散地作為語言模型的指令。Muennighoff等人(2023)利用這個特性,構建了一個2GB的數據集CommitPackFT,其中包含742K個代碼指令數據樣本,避免了構建自然語言指令所需的大量人工勞動。 除了雙態訓練和指令微調之外,最近構建代碼數據集的另一個趨勢是使用ChatGPT等強大的模型來綜合數據。雖然這種方法最初是為生成自然語言的指令數據而提出的,但Gunasekar等人(2023年)更進一步,合成了Python教科書和編碼練習的1Btoken來預訓練1.3B模型,在HumanEval上實現了與在大得多的數據集上訓練的大得多的模型相當的最先進結果。

4.2 編碼器
預訓練過的transformer編碼器,如BERT、RoBERTa和ELECTRA,在自然語言理解任務方面取得了令人印象深刻的結果,這些方法在出現後很快就被引入到代碼處理中。Kanade等人(2020)在一個代碼語料庫上覆制了BERT的訓練程序,以產生CuBERT,展示了其優於LSTM和未預訓練的transformer的優越性能。另一方面,Feng等人(2020),用MLM和ELECTRA’s RTD訓練Code BERT。他們還利用了CodeSearchNet中的顯式文本代碼對,並分別使用它們作為BERT輸入中的第一和第二段。當使用CodeBERT初始化普通transformer的編碼器部分,用於序列到序列的生成任務,如代碼摘要時,他們觀察到比未預訓練的基線有適度的性能提高。 除了這些標準的訓練目標外,還引入了許多專門為代碼設計的輔助目標。GraphCodeBERT和SynCoBERT都從源代碼提取圖(數據流圖和抽象語法樹)和訓練模型預測節點之間的類型關係,而SynCoBERT和Code-MVP也添加類型推理的預訓練階段標記的形式。另一個共同的目標是對比學習: SynCoBERT和Code-mvp在輸入的不同視圖(如代碼、註釋、AST和轉換代碼)之間的對比,而DISCO通過混淆等語義保留轉換構建正樣本對,通過注入人工bug構建負樣本對。

4.3 編碼器-解碼器
在NLP中,預訓練過的transformer編碼器-解碼器,如T5和BART,在過去幾年的語言建模方面也留下了顯著的進步。例如,T5將所有文本任務統一為序列到序列格式,並在GLUE和SuperGLUE上取得新的記錄。與僅編碼器模型相比,編碼器-解碼器自然更強大,因為它們可以用於條件文本生成,而它們的編碼器部分總是可以用於執行需要僅編碼器架構的任務,如迴歸。 受編碼器-解碼器體系結構的這些優點的啓發,許多這樣的模型已經被提出用於代碼處理。PyMT5和Mastropaolo等人(2021年)在代碼語料庫上覆制了T5的預訓練和多任務微調過程,而Ahmad等人(2021年)引入了PLBART,這是一種基於Java、Pyhton和自然語言組合的655GB數據的預訓練的BART。Lachaux等人(2021)認為,對於編程語言來説,MLM可能太容易了,因為標識符名稱經常在單個上下文窗口中多次出現,並提出了一個去模糊預訓練目標,即模型被訓練將混淆代碼轉換回其原始形式。與此方法相關的是,我們注意到,有意義的變量名也被發現對大型語言模型的代碼生成過程有積極的影響。 基於這些早期工作,Wang等人(2021)提出了CodeT5,即1)T5的原始跨度損壞;2)標識符標記(標識代碼輸入中的每個標記被標記為標識符或非標識符);3)屏蔽標識符預測(跨度損壞的特殊形式,所有標識符都被屏蔽);4)text-to-code和Code-to-text的生成。它的繼任者CodeT5+從UL2獲得靈感,並引入因果語言建模(CLM),以及基於文本代碼匹配的其他對比目標。 AlphaCode也訓練多個目標,編碼器用MLM訓練,解碼器用CLM進行架構修改,如淺編碼器和深度解碼器、多查詢注意,並且比CodeT5大得多(高達41B參數)。NatGen,另一方面,預訓練的“歸化”目標類似於去混淆:語義等效但不自然的代碼由預定義操作生成如循環轉換、死代碼注入,變量重命名,模型預訓練將這些不自然的代碼轉換回原始形式。作者注意到,其中一些模型是建立在以前的工作之上的。例如,NatGen是用CodeT5初始化的,而CodeT5+的最大版本是從僅解碼器模型CodeGen初始化來的。 除了這些一般的預訓練目標外,一些工作還訓練了transformer編碼器-解碼器,重點是代碼翻譯,這是transformer模型在代碼中的自然應用,因為transformer架構最初是由Vaswani等人(2017)用於機器翻譯(MT)提出的。然而,與自然語言不同的是,跨兩種或兩種以上人類語言的並行語料庫數量豐富,關於代碼的並行數據很少。為了解決這個問題,Roziere等人(2020)提出了編碼器,首先用XLM,然後用這個編碼器初始化vanilla transformer,繼續預訓練去噪自動編碼和翻譯,而其後續工作也利用語言獨立的中間表示來增強這一過程,論文將在下文中更詳細地討論。 除了訓練數據和目標外,這些模型大多保持了NLP社區提出的原始架構,如表3所示。例如,基於BART的模型使用後歸一化和可學習的絕對位置嵌入,而基於T5的模型使用其簡化的相對位置嵌入和預向量化。

4.4 解碼器
GPT-3和上下文學習的發現,解碼器transformer模型成為主導語言建模。在代碼處理中也出現了許多類似於CLM預訓練的模型,如GPT-C,CodeGPT,PolyCoder,CodeGen,PyCodeGPT,Pangu-Coder,CodeGeeX,CodeFuse,CodeShell。在這些模型中,已經嘗試了一些替代的訓練目標,如Pangu-Coder中的MLM和掩碼CLM,但發現與CLM-only訓練相比表現不佳。Zan等人(2022)還提出了在草稿上的持續訓練,即模型首先學習生成一個程序的草稿,然後生成實際的代碼。值得注意的是,Gunasekar et al.(2023)提出Phi-1,一個1.3B的小模型在一個只有7B個標記的數據集上訓練,該數據集由6B個來自StackOverfolw的token和ChatGPT生成的1B個合成數據組成,但實現50.6 pass@1HuamnEval和55.5 pass@1 MBPP,可與大(模型大小和訓練數據大小)模型相比,如Code LLaMA或PaLM 2。 儘管Cristofoulou等人(2022)報告了去噪目標在僅解碼器模型中表現不佳,但也有其他工作成功地將去噪或多任務預訓練與解碼器架構結合起來。Incoder,SantaCoder,StarCoder都採用僅解碼器的架構,由填充中間(FIM)目標訓練,也被Fried等人(2023)稱為因果掩碼,它本質上是span corruption,。這些填充目標的一個明顯優勢是,它們為模型注入了在推理時在輸入代碼中間填充空白的能力,而CLM只允許自迴歸生成。然而,如表4所示,與CodeGen等CLM-only模型相比,這些目標也導致下游任務具有更高的性能。 從表3中可以明顯看出,與其他模型架構相比,代碼的僅解碼器模型通常更接近地遵循NLP中的實踐。所有這些模型都使用了預歸一化,而MQA、RoPE和並行注意也被幾個模型所採用。值得注意的是,最新的三種模型——StarCoder、Phi-1和CodeFuse——也使用了閃照注意力來提高模型的吞吐量。

4.5 UniLMs
繼NLP中的UniLM之後,一些代碼處理方面的工作也對這第四族transformer模型進行了代碼方面的預訓練。CugLM通過交替注意掩模進行CLM和MLM + NSP訓練,而UniX編碼器使用CLM、MLM、Span Corruption(前綴LM風格),以及對比學習和文本代碼相互生成等輔助目標來進行訓練。然而,這兩種模型的規模都相對較小,這種體系結構是否適合代碼處理還有待探索。

4.6 擴散模型
目前,transformer架構主導了文本生成,但一些工作也採用了計算機視覺中的擴散模型進行文本生成。最近,CodeFusion也將擴散模型引入代碼建模,並證明了75M擴散模型在3個代碼合成數據集上優於StarCoder、CodeT5+和GPT-3。

4.7 代碼的教學微調和強化學習
在自然語言處理中,對帶有指令前綴的不同任務的訓練模型,即指令微調,已被證明可以解鎖跨任務泛化的能力。首先,這些指令數據樣本是人工編制或眾包的,但後來的研究發現LLM生成的指令已經足夠。 在使用自然語言的這些工作之後,來自代碼社區的研究人員也對他們的模型應用了指令調優。Wang等人(2023)利用InstructGPT生成的20K指令數據微調CodeT5+,獲得InstructCodeT5+。 WizardCoder遵循WizardLM的方法將20K編碼Alpaca樣本演化為一個78K數據集,並使用其微調StarCoder。Pangu-Coder2也使用WizardLM的進化指令從20K代碼Alpaca生成68K指令樣本,但也通過等級響應引入強化學習,以對齊測試和教師反饋(RRTF)。另一方面,OctoCoder採用不同的路徑,使用Git提交歷史作為指令數據來調整StarCoder和CodeGeeX2。最近,CodeFuse也採用了多任務微調,並明確地在其指令數據中引入多個下游任務。這些指令精細化的代碼模型的性能也可以在表4中找到。 在NLP中,另一項與指令微調密切相關的技術是從人類反饋中進行強化學習(RLHF),它在調整LLM與人類價值方面發揮了重要作用。強化學習的優點在於,它可以將不可區分的獎勵信號整合到訓練中,如BLEU和人類偏好,但對齊LLM所需的人類反饋往往涉及大量的註釋工作。相比之下,將強化學習應用於代碼模型具有很天然的優勢,因為編譯器可以用於為語言模型產生的代碼樣本自動生成反饋。 CodeRL就是這樣一個模型,它為每個生成的程序定義了四個反饋級別(即編譯錯誤、運行時錯誤、單元測試失敗、通過)以及由評論家模型估計的細粒度token級反饋。演員模型是CodeT5的擴展,然後用強化算法進行訓練。類似地,CompCoder和PPOCoder分別對CodeGPT和CodeT5進行近端策略優化,而RLTF提出了細粒度的反饋基於錯誤信息和編譯器提供的位置,以及自適應反饋考慮通過測試用例的比例。

5.語言模型的代碼特性

編程語言和自然語言之間的一個主要區別是,前者被人為地定義為精確和明確的,在執行之前需要編譯(或解釋)沒有錯誤。除了CLM、MLM和Span Corruption等詞彙操作之外,這允許在設計代碼的預訓練目標時具有更大的靈活性。在神經網絡被引入主流自然語言處理文獻之前的過去幾年裏,也可以觀察到類似的趨勢,當MT社區的研究人員利用文本的替代觀點,如句法特徵來提高SMT系統的性能。然而,這些特性並不是普遍適用的,甚至不是一致的,經常導致高度複雜的系統(例如,英語詞性標籤集的大小可能從幾十到數百不等)。 然而,編程語言在這些方面的表現要好得多。每個主流編程語言,如C,Python,Java,有現成的編譯器工具包,允許簡單和準確的提取語義如抽象語法樹(AST),語言獨立的中間表示(IR),和輔助信息,如每個token的類型和控制/數據流圖(CFG/DFG)。因此,在基於transformer的代碼語言建模的環境中,許多工作已經將這些特性納入到它們的訓練過程中。

5.1 抽象語法樹和中間表示法
AST是編譯過程中最常見的中間結果之一,其中一個程序被解析為一個操作樹及其操作數樹。在transformer在代碼處理社區普及之前,已經有了InferCode等工作,他們使用基於樹的CNN等特殊網絡架構來處理這些表示,並通過預測子樹進行自監督預訓練。 TreeBERT是將AST引入基於transformer的預訓練-微調框架的首次嘗試之一。這是一個transformer編碼器解碼器預訓練樹MLM和節點順序預測,編碼器採取一組組成路徑作為輸入(每個token是一個路徑,這是其節點的連接表示)而解碼器將代碼作為輸入。然後,樹MLM通過屏蔽路徑表示中的某些節點及其解碼器輸入中相應的碼token來執行,而節點順序預測是通過交換路徑中的節點並使用類似於BERT的[CLS]token進行預測來完成的。 然而,TreeBERT所使用的方法是複雜的,而且規模也不好。後來的工作大多選擇首先將AST處理為文本序列,並將其當作輸入的正常部分。例如,Wang等人(2021),通過深度遍歷處理AST,並與代碼和註釋連接,然後訓練SynCoBERT(與TreeBeERT不同,實際上是一個類BERT的編碼器模型),有四個目標: 1) MLM;2)標識符標記;3) AST邊緣預測(從這些節點表示的點積預測兩個AST節點之間是否存在邊);4)對比學習i)代碼和AST對,以及ii)文本和代碼-AST對。類似地,SPT-Code,一種transformer編碼器-解碼器,以代碼、序列化AST和文本的連接作為輸入,並預訓練1)span corruption;2) codeAST預測(NSP,一個段為代碼,一個段為AST);3)方法名稱生成,一種特殊的span corruption形式,其中一個方法名稱被掩碼。然而,與其他作品不同的是,它們並不將文檔字符串作為輸入中的文本段,而是將代碼中出現的所有方法名連接為一種簡潔的自然語言描述。同樣地,UniXcoder在訓練過程中採用扁平的AST而不是源代碼作為其輸入。 在編譯pipeline中,AST之後通常是獨立於語言的中間表示,如LLVM IR。這些特性獨立於特定的編程語言,使它們成為翻譯中心的候選對象,低資源自然語言機器翻譯中的英語也一樣。Szafraniec等人(2023年)利用這一特性,通過對代碼和IR進行翻譯語言建模以及從代碼生成IR來擴展代碼轉換器。他們還研究了其他目標,如IR反編譯(即從IR生成代碼)和IR透視(即直接從另一種語言的IR直接生成代碼),兩者都顯示了有希望的結果。

5.2 控制流和數據流
雖然AST和IR在某些任務中被證明是有用的信息,但它們本質上是靜態的,就像源代碼一樣,可能無法捕獲僅在運行時顯示的代碼的語義屬性。然而,這種語義包含在諸如控制流和數據流等動態特性中。與AST類似,在預訓練好的transformer出現之前,使用專門的網絡來處理這些信息,如ProGraML使用的消息傳遞神經網絡。然而,與AST不同的是,即使在經過預訓練的transformer占主導地位之後,也很少有工作關注這個方向。 GraphCodeBERT就是這樣一個工作,它創建特殊的token和轉換嵌入的變量,並連接文本和源代碼後變量序列構造輸入模型,定製注意面具代碼和變量段從代碼段和變量段:當且僅當變量從代碼標記中相互識別,而對於變量段內的標記,如果數據流中有從vj到vi的直接邊,vi允許關注vj。模型然後預訓練MLM結合邊緣預測和節點對齊,這兩者都是通過二進制分類的點積兩個標記的表示(一個從代碼段和一個從變量段節點對齊,並從變量段邊緣預測)。

5.3 Type
除了AST、IR和數據流之外,類型信息也被用於幫助語言模型處理代碼。CugLM,例如,使用類型信息在微調期間幫助預測的標記MLM單向(即MLM單向注意掩碼):掩碼token的類型首先預測從最終transformer層的表示,然後token本身預測基於隱藏的表示和預測類型。相比之下,CodeT5和SynCoBERT在他們的預訓練目標中都包含了標識符標記,這可以被視為粗粒度類型預測。 值得注意的是,Wang等人(2022)將上述許多特性集成到Code-MVP中:源代碼、文檔字符串、AST、CFG和通過標識符重命名、循環交換和死代碼插入轉換的源代碼。該模型從GraphCodeBERT初始化,然後使用MLM、細粒度類型預測和不同視圖之間的對比學習進行訓練,如text vs.code、code vs.AST和code vs.CFG。

6.軟件開發中的LLM

隨着語言模型在軟件工程基準上創造了新的記錄,軟件工程技術也在擴大語言模型的邊界,並隨後引導它們進入現實世界的開發週期。

6.1 使用編碼工具擴展的LLM
NLP社區的研究表明,LLM可以學習使用外部工具,如計算器、MT系統和搜索引擎。因此,解釋器已被用於在複雜的推理任務中增強LLM。PAL和PoT都使用Python解釋器進行數值計算,而ViperGPT進一步擴展視覺api從視覺輸入中提取信息並回答相關問題。 除了減輕了抽象推理任務中的數值計算負擔外,解釋器還提供了關於代碼生成過程本身的反饋,以及單元測試。CodeT和TiCoder使用Codex生成單元測試,並針對生成的代碼樣本進行運行,以提高模型在代碼合成方面的性能。類似地,TransCoder-st通過代碼轉換的外部單元測試增強了TransCoder和DOBF。在前文中,論文還證明了單元測試的執行結果可以作為代碼強化學習的自然監督信號。 值得注意的是,在2023年3月,OpenAI還發布了一個針對ChatGPT的解釋器插件,它可以接受來自用户的文件輸入,根據用户指令生成代碼,並通過實時執行提供反饋。一些工作表明,該特性允許GPT-4進行自我調試。 在LLM研究中,一個與工具使用密切相關的主題是規劃作為智能代理,這已被證明在理論上和經驗上都可以提高LLM的能力。Ruan等人(2023)發現,LLM可以計劃使用外部SQL生成器和Python生成器來解決複雜的任務,而CodePlan則證明了它們可以通過自適應規劃來執行存儲庫級編碼。 另一個工作流使用LLM來創建用於代碼生成的多代理系統,如自我協作、ChatDev和MetaGPT。在這些框架中,多個LLM會被提示扮演不同的角色,如程序員、評審員和經理。這些角色相互交互,將代碼生成分解為不同的階段(例如,設計、編碼、測試和文檔化),並協作完成複雜的任務。

6.2 集成到軟件開發中的LLM
隨着LLM的交互式編碼能力的提高,研究人員也開始將它們集成到軟件開發的每一個過程中。 自動代碼完成是軟件開發中語言模型最早的應用程序之一,因為它們只需要預測下一個token的能力。甚至在語言模型擴展到數十億參數之前,就已經將完成系統和智能代碼等集成到流行的IDE中。 然而,最近,代碼語言模型的應用已經超越了簡單的代碼完成。GitHub Copilot可以説是最流行的人工智能代碼助手之一,具有多種特性,包括代碼生成、漏洞檢測和許可證管理,而CodeFuse還將代碼生成、代碼翻譯、代碼註釋和測試用例生成集成到一個IDE擴展中。然而,隨着代碼語言模型的增大,它們的客户端部署和實時性能也帶來了新的挑戰。 隨着LLM的不斷髮展,在其之上構建應用程序本身也將發展成為一項重要的任務。許多針對此類應用程序的開源框架已經發布,包括LangChain、AutoGPT和WorkGPT。這些框架為開發人員提供了語言模型的抽象,並且正在積極地革新軟件開發的整個過程,即使這個研究正在完成中。

7.結論與挑戰

在這項工作中,論文系統地回顧了使用預訓練的transformer語言模型進行代碼處理的歷史,並強調了它們與在一般領域上預訓練的模型之間的關係和比較。代碼建模的進展通常遵循NLP的歷史進程,從SMT模型到NMT模型,然後到微調經過預訓練的transformer,最後到現實生產中LLM甚至自主代理的few-shot應用。與自然語言不同,代碼的性質使得它很容易從替代視圖中提取輔助信息,並利用解釋器和單元測試來進行自動反饋。

考慮到這一點,作者確定了當前代碼建模開發中所面臨的幾個挑戰。

  • Comprehensive benchmarks to push code LLMs to the next stage.廣泛使用的HumanEval基準測試在代碼LLM的演化中起着關鍵作用。然而,它相對較小,它的記分板已經被操縱到接近完美,這並不能準確地反映現實世界的行為。已經提出了許多其他關於代碼LLM的基準測試,但它們仍然不夠全面,不足以反映生產級別的需求。社區渴望在HumanEval之後有一個新的標準基準測試,以進一步推動代碼LLM的進展到下一個階段。
  • Acquisition of high-quality data.隨着Gunasekar等人(2023)通過基於教科書數據訓練的1.3B模型實現SOTA性能,作者相信,在不久的將來,對於自我監督的預訓練和有監督的微調,訓練數據的選擇和合成數據的利用將更加突出。
  • Integration of code features into language models.正如論文所指出的,CFG和DFG尚未在代碼語言建模中規模使用。少數使用數據流的工作對模型的注意力掩模進行了改變,這嚴重限制了它們的跨任務泛化和縮放能力。作者認為,將這些特性無縫集成到文本輸入中是值得進一步研究的。
  • Application of LLMs in more code downstream tasks.正如論文所指出的,目前對LLM編碼能力的評估主要集中在程序合成上,圖3清楚地顯示了與軟件測試相關的任務(即單元測試生成、斷言生成、變體生成和模糊化)和去模糊化在LLM中的應用很少。此外,由於LLM的上下文窗口目前相當有限,因此諸如程序合成和代碼翻譯等生成任務尚未應用到方法級別之外。在論文中,作者列出了一些關於存儲庫級代碼完成和時間編輯的工作,他們相信LLM在更多存儲庫級任務中的應用將成為未來的熱門研究熱點。
  • Alternative model architectures and training objectives.在表3中,論文展示了許多代碼語言模型都是用特定於代碼的輔助目標進行預訓練的,但這些模型都屬於僅編碼器或編解碼器家族,而僅解碼器模型尚未使用替代目標進行增強。此外,正如Singh等人(2023年)所開創的那樣,作者相信擴散模型將在未來的代碼建模中找到其基礎。
  • Building code LLM ecosystem for fulllife-cycle of software development.雖然學術界已經見證了大量的代碼模型,但大多數都是作為IDE插件部署在編碼階段,而忽略了軟件開發生命週期中的其他階段。在論文中,作者提到了幾個鼓舞人心的例子,希望在軟件開發的整個生命週期中看到更多的代碼LM的應用,從需求分析到DevOps,最終達到像PyTorch和hugging face這樣的全面生態系統
  • Safety and ethics issues related to code LLMs.隨着語言模型的發展,它們也提出了安全問題,包括但不限於數據污染、有害或有偏見的生成、個人信息泄露和幻覺。在軟件開發中,這些模型的部署應該格外謹慎,因為它們生成的代碼可能包含導致災難性結果的安全風險。預訓練數據也成為倫理的一個敏感話題,Kocetkov等人(2022)通過允許開發人員從堆棧中刪除他們的代碼,朝着這個問題邁出了有意義的一步。隨着綜合訓練數據的廣泛應用,研究人員也應該謹慎對待這種做法,因為用人工智能生成的數據訓練人工智能模型的結果還有待大規模調查。

通過本次研究,作者希望提供語言模型在軟件工程中應用的全球視角,並將來自兩個社區的研究聯繫起來。作者相信,目前LLM的激增,最終將轉化為現實世界的應用,並引領人類進入一個更光明的未來。

user avatar y_luoe_hai_61a734cbf3c94 Avatar u_16018702 Avatar u_16640205 Avatar mulavar Avatar mianlengxincidehongjiu Avatar laoqing Avatar yeshan333 Avatar seatunnel Avatar liubo86 Avatar tecdat Avatar digitalocean Avatar chen_5ec331606ce75 Avatar
Favorites 26 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.