GPT-4寫(xiě)代碼不如ChatGPT,誤用率高達(dá)62%!加州大學(xué)兩位華人開(kāi)源代碼可靠性基準(zhǔn)RobustAPI
大型語(yǔ)言模型(LLM)在理解自然語(yǔ)言和生成程序代碼方面展現(xiàn)出了非凡的性能,程序員們也開(kāi)始在編碼過(guò)程中使用Copilot工具輔助編程,或是要求LLM生成解決方案。
經(jīng)過(guò)幾版迭代后,目前LLM生成的代碼已經(jīng)很少有語(yǔ)法錯(cuò)誤了,也更貼合用戶(hù)輸入的文本、符合預(yù)期語(yǔ)義,但針對(duì)LLM代碼生成的可靠性和魯棒性仍然缺乏徹底的研究。
代碼的可執(zhí)行并不等同于可靠,軟件的開(kāi)發(fā)環(huán)境、部署環(huán)境都存在很大的不確定性。
如果直接使用LLM生成的代碼,可能會(huì)因?yàn)锳P誤用(misuse)導(dǎo)致更嚴(yán)重的問(wèn)題,例如資源泄漏、程序崩潰;最糟糕的是,使用LLM代碼生成服務(wù)的用戶(hù)大多數(shù)都是新手開(kāi)發(fā)人員,很難識(shí)別出「貌似可運(yùn)行代碼」下的隱藏問(wèn)題,進(jìn)一步增加了漏洞代碼在現(xiàn)實(shí)中的應(yīng)用風(fēng)險(xiǎn)。
現(xiàn)有的代碼評(píng)估基準(zhǔn)和數(shù)據(jù)集主要專(zhuān)注于小任務(wù),例如面試中的編程問(wèn)題,可能不符合開(kāi)發(fā)人員在工作中的實(shí)際需求。
最近,來(lái)自加州大學(xué)的兩位華人研究人員發(fā)布了一個(gè)用于評(píng)估生成代碼可靠性和魯棒性的新數(shù)據(jù)集RobustAPI,包括從StackOverflow中收集得到的1208個(gè)編碼問(wèn)題,涉及24個(gè)主流Java API的評(píng)估。
論文鏈接:https://arxiv.org/pdf/2308.10335.pdf
研究人員總結(jié)了這些API的常見(jiàn)誤用模式,并在當(dāng)下常用的LLM上對(duì)其進(jìn)行評(píng)估,結(jié)果表明,即使是GPT-4,也有高達(dá)62%的生成代碼包含API誤用問(wèn)題,如果代碼被實(shí)際部署,可能會(huì)導(dǎo)致意想不到的后果。
論文相關(guān)的數(shù)據(jù)和評(píng)估器不久后將開(kāi)源。
方法
數(shù)據(jù)收集
為了利用軟件工程領(lǐng)域現(xiàn)有的研究成果,RobustAPI沒(méi)有從零構(gòu)建,而是基于在線(xiàn)問(wèn)答論壇中頻繁出現(xiàn)的Java API誤用數(shù)據(jù)集ExampleCheck
研究人員從數(shù)據(jù)集中選擇了23個(gè)流行的Java APIs,涵蓋了字符串處理、數(shù)據(jù)結(jié)構(gòu)、移動(dòng)開(kāi)發(fā)、加密和數(shù)據(jù)庫(kù)操作等。
然后再?gòu)腟tack Overflow中爬取與上述API相關(guān)的問(wèn)題,只選擇問(wèn)題中包含在線(xiàn)答案的,可以保證RobustAPI是可回答的(answerable),能夠更有效地評(píng)估LLM在「人類(lèi)容易犯錯(cuò)問(wèn)題」上的代碼能力。
收集數(shù)據(jù)后將問(wèn)題轉(zhuǎn)換為JSON格式,包含四個(gè)字段:
1. id,為樣本分配的唯一標(biāo)識(shí)符
2. api,用來(lái)提示大型語(yǔ)言模型問(wèn)題相關(guān)API
3. question,包括問(wèn)題的標(biāo)題和描述
4. origin,樣本的原始URL
提示生成(prompt generation)
研究人員設(shè)計(jì)了一個(gè)提示模板,并用數(shù)據(jù)集中的樣本進(jìn)行填充,再?gòu)腖LMs收集回復(fù)內(nèi)容,并實(shí)現(xiàn)一個(gè)API使用檢查器來(lái)評(píng)估代碼的可靠性。
在少樣本演示下進(jìn)行實(shí)驗(yàn)時(shí),每個(gè)示例都提供回復(fù)的格式,然后在最后放入數(shù)據(jù)集中的問(wèn)題及相應(yīng)API提示,模擬新手用戶(hù)詢(xún)問(wèn)時(shí)提出的問(wèn)題。
LLM在對(duì)話(huà)時(shí)可以識(shí)別特殊標(biāo)簽的結(jié)構(gòu),所以研究人員將問(wèn)題和答案封裝起來(lái)指示LLM生成問(wèn)題的答案。
演示樣本(Demonstration Samples)
為了深入分析LLMs的代碼生成能力,研究人員設(shè)計(jì)了兩個(gè)少樣本實(shí)驗(yàn):
1. one-shot-irrelevant,使用不相關(guān)的API(如Arrays.stream)作為語(yǔ)言模型的提示樣例。
研究人員假定該示例可以消除生成代碼中的語(yǔ)法錯(cuò)誤。
2. one-shot-relevant,使用相同的API作為示例,包括一組問(wèn)題和答案。
JAVA API誤用
研究人員在使用API時(shí),需要充分理解API的使用規(guī)則,以便實(shí)現(xiàn)理想的API效果。
一個(gè)典型的例子是文件操作,通過(guò)RandomAccessFile打開(kāi)和寫(xiě)入文件時(shí),需要注意兩條使用規(guī)則:
1. 讀取文件可能會(huì)引發(fā)異常。
如果在讀取預(yù)期字節(jié)之前達(dá)到緩沖區(qū)限制,API將拋出IndexOutOfBoundsException異常;當(dāng)該文件同時(shí)被其他進(jìn)程關(guān)閉時(shí),API將拋出ClosedChannelException。
為了處理這些異常,正確的實(shí)現(xiàn)應(yīng)該將API包含在try-catch塊中。
2. 使用后應(yīng)應(yīng)該關(guān)閉文件通道,否則的話(huà),如果此代碼片段位于在多個(gè)實(shí)例中并發(fā)運(yùn)行的長(zhǎng)期程序中,文件資源可能會(huì)耗盡,代碼需要在所有文件操作后調(diào)用close API
另一個(gè)容易被誤用的API使用規(guī)則的例子是一個(gè)特殊的數(shù)據(jù)對(duì)象TypedArray,需要開(kāi)發(fā)人員調(diào)用recycle()來(lái)手動(dòng)啟用垃圾收集,否則,即使不再使用此TypedArray,Java虛擬機(jī)中的垃圾收集也不會(huì)被觸發(fā)。
在沒(méi)有垃圾回收的情況下使用該API會(huì)導(dǎo)致未釋放的內(nèi)存消耗,在生產(chǎn)環(huán)境部署后,在大工作負(fù)載和高并發(fā)性下會(huì)降低甚至掛起軟件系統(tǒng)。
在RobustAPI數(shù)據(jù)集中,研究人員總結(jié)了40個(gè)API使用規(guī)則,具體包括:
1. API的保護(hù)條件,在A(yíng)PI調(diào)用之前應(yīng)該檢查,例如File.exists()應(yīng)該在調(diào)用File.createNewFile()之前;
2. API的調(diào)用順序,例如close()的調(diào)用應(yīng)該在File.write()之后;
3. API的控制結(jié)構(gòu),例如SimpleDataFormat.parse()應(yīng)該被try-catch結(jié)構(gòu)所包圍。
檢測(cè)API誤用
現(xiàn)有的評(píng)估LLMs生成的代碼的研究通常使用人工編寫(xiě)或自動(dòng)測(cè)試生成的測(cè)試用例,但即使是高覆蓋率的測(cè)試用例也只能覆蓋語(yǔ)義正確性,無(wú)法模擬生產(chǎn)環(huán)境中的各種意外輸入,無(wú)法對(duì)代碼的可靠性和健壯性進(jìn)行完善的評(píng)估。
為了解決這個(gè)難題,研究人員使用靜態(tài)分析的方法,在不運(yùn)行測(cè)試用例的情況下,通過(guò)代碼結(jié)構(gòu)分析代碼誤用,可以保證對(duì)整個(gè)程序的全面覆蓋,并且比測(cè)試解決方案的效率更高。
為了評(píng)估代碼中API用法的正確性,先從代碼片段中提取調(diào)用結(jié)果和控制結(jié)構(gòu),然后根據(jù)API使用規(guī)則檢測(cè)API誤用。
代碼檢查器(code checker)首先檢查代碼片段,判斷是一個(gè)方法的片段還是一個(gè)類(lèi)的方法,然后就可以對(duì)代碼片段進(jìn)行封裝,并從代碼片段中構(gòu)造抽象語(yǔ)法樹(shù)(AST)。
然后檢查器遍歷AST,按順序記錄所有的方法調(diào)用和控制結(jié)構(gòu),從而生成一個(gè)調(diào)用序列;檢查器將調(diào)用序列與API使用規(guī)則進(jìn)行比較,判斷每個(gè)方法調(diào)用的實(shí)例類(lèi)型,并使用類(lèi)型和方法作為鍵來(lái)檢索相應(yīng)的API使用規(guī)則。
最后,檢查器計(jì)算調(diào)用序列和API使用規(guī)則之間的最長(zhǎng)公共序列:如果調(diào)用序列與預(yù)期的API使用規(guī)則不匹配,則報(bào)告API誤用。
實(shí)驗(yàn)結(jié)果
研究人員使用4個(gè)語(yǔ)言模型(GPT-3.5,GPT-4,Llama-2,Vicuna-1.5)在RobustAPI上進(jìn)行評(píng)估。
將可編譯且包含API誤用的答案除以所有可編譯的答案后,計(jì)算得到各個(gè)語(yǔ)言模型的誤用率。
從實(shí)驗(yàn)結(jié)果上來(lái)看,即便是最先進(jìn)的商業(yè)模型,如GPT-3.5和GPT-4也存在誤用的問(wèn)題。
在零樣本設(shè)置下,Llama的API誤用率最低,不過(guò)大多數(shù)Llama的答案中都不包含代碼。
一個(gè)與直覺(jué)相反的發(fā)現(xiàn)是,雖然OpenAI官方宣稱(chēng)GPT-4比GPT-3.5在代碼生成上的性能提升達(dá)到40%,但實(shí)際上GPT-4的代碼誤用率要更高。
這一結(jié)果也表明,代碼在現(xiàn)實(shí)世界生產(chǎn)中的可靠性和健壯性沒(méi)有得到業(yè)界的重視,并且該問(wèn)題存在巨大的改進(jìn)空間。