GPT-4:我寫(xiě)的代碼你敢用嗎?研究表明其API誤用率超過(guò)62%
語(yǔ)言建模的新時(shí)代已經(jīng)到來(lái),大型語(yǔ)言模型(LLM)能力非凡,不僅能理解自然語(yǔ)言,甚至能根據(jù)用戶需求生成定制代碼。
因此,越來(lái)越多的軟件工程師選擇查詢大型語(yǔ)言模型來(lái)解答編程問(wèn)題,比如使用 API 來(lái)生成代碼段或檢測(cè)代碼中的 bug。相比于搜索 Stack Overflow 等網(wǎng)絡(luò)編程論壇,大型語(yǔ)言模型可為編程問(wèn)題檢索到更加合適的定制版答案。
LLM 的速度很快,但這也掩蓋了其代碼生成中的潛在風(fēng)險(xiǎn)。從軟件工程的角度看,即便已經(jīng)有許多研究成果問(wèn)世(涉及避免句法錯(cuò)誤以及提升對(duì)生成代碼的語(yǔ)義理解等方面),LLM 的生成代碼能力的穩(wěn)健性和可靠性還沒(méi)有得到透徹的研究。
不同于網(wǎng)絡(luò)編程論壇的情況,LLM 生成的代碼沒(méi)有得到社區(qū)同行的審查,因此可能出現(xiàn) API 誤用問(wèn)題,例如在文件讀取和變量索引中缺少邊界檢查、缺少文件 I/O 關(guān)閉、交易完成失敗等。即使生成的代碼樣本可以執(zhí)行或者能正確執(zhí)行功能,誤用也可能導(dǎo)致產(chǎn)品出現(xiàn)嚴(yán)重的潛在風(fēng)險(xiǎn),比如內(nèi)存泄漏、程序崩潰、垃圾數(shù)據(jù)收集失敗等。
更糟糕的是,提出這些問(wèn)題的程序員還是最容易受到打擊的人,因?yàn)樗麄兏锌赡苁?API 新手,無(wú)法辨別生成的代碼段中的潛在問(wèn)題。
下圖展示了一個(gè)軟件工程師向 LLM 詢問(wèn)編程問(wèn)題的示例,可以看到 Llama-2 能給出句法正確、功能正確、語(yǔ)法對(duì)齊的代碼段,但卻存在不夠穩(wěn)健可靠的問(wèn)題,因?yàn)槠渲袥](méi)有考慮到文件已存在或文件夾不存在的情況。
因此,在評(píng)估大型語(yǔ)言模型的代碼生成能力時(shí),必須考慮代碼的可靠性。
在評(píng)估大型語(yǔ)言模型的代碼生成能力方面,大多數(shù)現(xiàn)有基準(zhǔn)關(guān)注的重點(diǎn)是所生成代碼的執(zhí)行結(jié)果的功能正確性,這意味著只要生成的代碼能夠滿足用戶的功能需求,用戶就能接受。
但在軟件開(kāi)發(fā)領(lǐng)域,代碼光是能正確執(zhí)行可不夠。軟件工程師需要的是代碼能正確且可靠地使用新 API,長(zhǎng)期運(yùn)行也不會(huì)有潛在風(fēng)險(xiǎn)。
此外,當(dāng)前大多數(shù)編程問(wèn)題的范圍都與軟件工程相距甚遠(yuǎn)。其數(shù)據(jù)源大都是網(wǎng)上的編程挑戰(zhàn)賽網(wǎng)絡(luò),比如 Codeforces、Kattis、Leetcode 等。盡管成就非凡,但這還不足以為實(shí)際應(yīng)用場(chǎng)景的軟件開(kāi)發(fā)工作提供幫助。
為此,加州大學(xué)圣迭戈分校的 Li Zhong 和 Zilong Wang 提出了 RobustAPI,該框架可以評(píng)估大型語(yǔ)言模型生成的代碼的可靠性和穩(wěn)健性,其中包含一個(gè)編程問(wèn)題數(shù)據(jù)集和一個(gè)使用抽象語(yǔ)法樹(shù)(AST)的評(píng)估器。
論文地址:https://arxiv.org/pdf/2308.10335.pdf
其中數(shù)據(jù)集的目標(biāo)是創(chuàng)建一個(gè)接近真實(shí)軟件開(kāi)發(fā)的評(píng)估設(shè)置。為此研究者從 Stack Overflow 收集了有關(guān) Java 的代表性問(wèn)題。Java 是最流行的編程語(yǔ)言之一,得益于其一次編寫(xiě)到處運(yùn)行(WORA)的特性,被廣泛用于軟件開(kāi)發(fā)。
對(duì)于每一個(gè)問(wèn)題,研究者都提供了詳細(xì)的描述和相關(guān)的 Java API。他們還設(shè)計(jì)了一套用于調(diào)用大型語(yǔ)言模型來(lái)生成代碼段及相應(yīng)解釋的模板。
研究者還提供了一個(gè)評(píng)估器,其能使用抽象語(yǔ)法樹(shù)(AST)分析所生成的代碼段并將它們與預(yù)期的 API 使用模式進(jìn)行比較。
研究者也按照 Zhang et al. (2018) 的方法將 AI 使用模式形式化地表示成了結(jié)構(gòu)化的調(diào)用序列。這種結(jié)構(gòu)化的調(diào)用序列能表明可以如何正確使用這些 API 來(lái)消除潛在的系統(tǒng)風(fēng)險(xiǎn)。從軟件工程的角度看,任何違反這種結(jié)構(gòu)化調(diào)用序列的現(xiàn)象都將被視為失敗。
研究者從 Stack Overflow 收集了 1208 個(gè)真實(shí)問(wèn)題,其中涉及 24 個(gè)代表性的 Java API。研究者也進(jìn)行了實(shí)驗(yàn)評(píng)估,其中不僅實(shí)驗(yàn)了閉源的語(yǔ)言模型(GPT-3.5 和 GPT-4),也實(shí)驗(yàn)了開(kāi)源的語(yǔ)言模型(Llama-2 和 Vicuna-1.5)。對(duì)于模型的超參數(shù)設(shè)置,他們使用了默認(rèn)設(shè)置,未進(jìn)行進(jìn)一步超參數(shù)調(diào)節(jié)。他們也設(shè)計(jì)了兩種實(shí)驗(yàn)形式:零樣本(zero-shot)和單樣本(one-shot),即分別在 prompt 中提供零個(gè)或一個(gè)演示樣本。
研究者全面分析了 LLM 生成的代碼并研究了常見(jiàn)的 API 誤用情況。他們希望借此讓人們了解 LLM 在生成代碼時(shí)誤用 API 的重要問(wèn)題,同時(shí)這項(xiàng)研究也能為 LLM 的評(píng)估提供一個(gè)新的維度,而不只是常用的功能正確性。此外數(shù)據(jù)集和評(píng)估器還將開(kāi)源。
本論文的貢獻(xiàn)總結(jié)如下:
- 提出了一種用于評(píng)估 LLM 代碼生成的可靠性和穩(wěn)健性的新基準(zhǔn):RobustAPI。
- 提供了一個(gè)完善的評(píng)估框架,其中包括一個(gè)由 Stack Overflow 問(wèn)題構(gòu)成的數(shù)據(jù)集和一個(gè)使用 AST 的 API 使用情況檢查器。研究者基于此框架分析了常用 LLM 的性能表現(xiàn),包括 GPT-3.5、GPT-4、Llama-2 和 Vicuna-1.5。
- 全面分析了 LLM 生成代碼的表現(xiàn)。他們總結(jié)了每種模型常見(jiàn)的 API 誤用情況,并指出了可供未來(lái)研究改進(jìn)的方向。
方法概覽
RobustAPI 是一個(gè)用于全面評(píng)估 LLM 生成代碼的可靠性和穩(wěn)健性的框架。
下面將描述構(gòu)建該數(shù)據(jù)集時(shí)的數(shù)據(jù)收集過(guò)程和 prompt 生成過(guò)程,然后將給出 RobustAPI 中評(píng)估的 API 誤用模式并討論誤用的潛在后果,最后還將給出用 RobustAPI 檢測(cè) API 誤用情況的靜態(tài)分析,其中使用的方法是抽象語(yǔ)法樹(shù)。
結(jié)果發(fā)現(xiàn),相比于關(guān)鍵詞匹配等基于規(guī)則的方法,新方法能以更高的準(zhǔn)確度評(píng)估 LLM 生成代碼的 API 誤用情況。
數(shù)據(jù)收集
為了利用軟件工程領(lǐng)域的已有研究成果,研究者構(gòu)建 RobustAPI 時(shí)立足的起點(diǎn)是來(lái)自 ExampleCheck (Zhang et al. 2018) 的數(shù)據(jù)集。ExampleCheck 是用于研究網(wǎng)絡(luò)問(wèn)答論壇中常見(jiàn) Java API 誤用情況的框架。
研究者從該數(shù)據(jù)集選取了 23 個(gè)常見(jiàn)的 Java API,如下表 1 所示。這 23 個(gè) API 覆蓋 5 個(gè)領(lǐng)域,包括字符串處理、數(shù)據(jù)結(jié)構(gòu)、移動(dòng)端開(kāi)發(fā)、加密和數(shù)據(jù)庫(kù)操作。
prompt 生成
RobustAPI 還包含一個(gè) prompt 模板,可使用數(shù)據(jù)集中的樣本來(lái)填充。然后研究者收集 LLM 對(duì)該 prompt 的響應(yīng),再通過(guò)一個(gè) API 使用檢查器來(lái)評(píng)估其代碼可靠性。
在該 prompt 中,首先會(huì)給出任務(wù)介紹和所需的響應(yīng)格式。然后,如果執(zhí)行的實(shí)驗(yàn)是少樣本實(shí)驗(yàn),則還會(huì)給出少樣本的演示。下面是一個(gè)示例:
演示樣本
演示樣本已被證明有助于 LLM 理解自然語(yǔ)言。為了透徹地分析 LLM 的代碼生成能力,研究者設(shè)計(jì)了兩種少樣本設(shè)置:?jiǎn)螛颖緹o(wú)關(guān)演示和單樣本相關(guān)演示。
在單樣本無(wú)關(guān)演示設(shè)置中,為 LLM 提供的演示示例使用的 API 是無(wú)關(guān)的。研究者假設(shè)這種演示示例能消除生成代碼中句法錯(cuò)誤。RobustAPI 中使用的無(wú)關(guān)示例如下:
在單樣本相關(guān)演示設(shè)置中,為 LLM 提供的演示示例使用的 API 與給定問(wèn)題所用的 API 一樣。這種示例包含一對(duì)問(wèn)題和答案。這種演示示例中的問(wèn)題并不包含在測(cè)試數(shù)據(jù)集中,而且研究者人工修正了其中的答案以確保其中不存在 API 誤用情況并且答案和問(wèn)題的語(yǔ)義很好地對(duì)齊了。
Java API 誤用
研究者為 RobustAPI 中的 23 個(gè) API 總結(jié)了 40 條 API 規(guī)則,它們?cè)谶@些 API 的文檔中得到了驗(yàn)證。這些規(guī)則包括:
(1) API 的守衛(wèi)條件,這應(yīng)該在 API 調(diào)用之前進(jìn)行檢查。舉個(gè)例子,在 File.createNewFile () 之前應(yīng)檢查 File.exists () 的結(jié)果。
(2) 所要求的 API 調(diào)用序列,即應(yīng)當(dāng)以一定順序調(diào)用 API。比如,應(yīng)在 File.write () 之后調(diào)用 close ()。
(3) API 的控制結(jié)構(gòu)。比如,應(yīng)把 SimpleDateFormat.parse () 包含在 try-catch 結(jié)構(gòu)中。
下面給出一個(gè)例子:
檢測(cè) API 誤用情況
為了評(píng)估代碼中 API 使用的正確性,RobustAPI 可根據(jù) API 使用規(guī)則檢測(cè) API 誤用情況,其做法是從代碼段中提取調(diào)用結(jié)果和控制結(jié)構(gòu),如下圖 2 所示。
代碼檢查器首先會(huì)檢查生成的代碼段,看這段代碼是某個(gè)方法中的一段代碼,還是來(lái)自某個(gè)類的一個(gè)方法,以便它可以封裝該代碼段并使用其構(gòu)建抽象語(yǔ)法樹(shù)(AST)。
然后該檢查器會(huì)遍歷該 AST 并按順序記錄所有的方法調(diào)用和控制結(jié)構(gòu),這會(huì)生成一個(gè)調(diào)用序列。
接下來(lái),該檢查器會(huì)將這個(gè)調(diào)用序列與 API 使用規(guī)則進(jìn)行比較。它會(huì)推斷每個(gè)方法調(diào)用的實(shí)例類型,并將該類型和方法用作鍵來(lái)檢索相應(yīng)的 API 使用規(guī)則。
最后,該檢查器會(huì)計(jì)算這個(gè)調(diào)用序列和 API 使用規(guī)則之間的最長(zhǎng)公共序列。
如果這個(gè)調(diào)用序列和預(yù)期的 API 使用規(guī)則不匹配,則該檢查器就報(bào)告出現(xiàn)了 API 誤用。
實(shí)驗(yàn)結(jié)果
研究者在 4 個(gè) LLM 上評(píng)估了 RobustAPI:GPT-3.5、GPT-4、 Llama-2 和 Vicuna-1.5 。
實(shí)驗(yàn)中所使用的評(píng)估指標(biāo)包括:API 誤用率、可執(zhí)行樣本百分比、總體 API 誤用百分比。
實(shí)驗(yàn)的目的是試圖回答以下問(wèn)題:
- 問(wèn)題 1:這些 LLM 在解答真實(shí)世界編程問(wèn)題時(shí)的 API 誤用率是多少?
- 問(wèn)題 2:無(wú)關(guān)的演示樣本會(huì)對(duì)結(jié)果產(chǎn)生什么樣的影響?
- 問(wèn)題 3:正確的 API 使用示例能降低 API 誤用率嗎?
- 問(wèn)題 4:為什么 LLM 生成的代碼無(wú)法通過(guò) API 使用檢查?
具體的實(shí)驗(yàn)過(guò)程請(qǐng)參閱原論文,這里給出研究者得到的 5 個(gè)發(fā)現(xiàn):
發(fā)現(xiàn) 1:當(dāng)前最佳的大型語(yǔ)言模型對(duì)真實(shí)世界編程問(wèn)題的答案普遍存在 API 誤用問(wèn)題。
發(fā)現(xiàn) 2:在所有包含可執(zhí)行代碼的 LLM 答案中,57-70% 的代碼段都有 API 誤用問(wèn)題,這可能給生產(chǎn)帶來(lái)嚴(yán)重后果。
發(fā)現(xiàn) 3:無(wú)關(guān)樣本示例無(wú)助于降低 API 誤用率,但會(huì)觸發(fā)更有效的答案,這能有效地用于對(duì)模型性能的基準(zhǔn)評(píng)測(cè)。
發(fā)現(xiàn) 4:某些 LLM 可以學(xué)習(xí)正確的使用示例,這能降低 API 誤用率。
發(fā)現(xiàn) 5:GPT-4 包含可執(zhí)行代碼的答案數(shù)量最多。對(duì)于基準(zhǔn) API,不同的 LLM 的誤用率趨勢(shì)也不同。
此外,研究者還在論文中展示了一個(gè)基于 GPT-3.5 的典型案例:模型在不同的實(shí)驗(yàn)設(shè)置下有不同的反應(yīng)。
任務(wù)是要求模型幫助使用 PrintWriter.write API 將字符串寫(xiě)入一個(gè)文件。
在零樣本和單樣本無(wú)關(guān)演示設(shè)置下,答案稍有不同,但都出現(xiàn)了 API 誤用問(wèn)題 —— 沒(méi)有考慮例外情況。在給模型提供了正確的 API 使用示例后,模型學(xué)會(huì)了如何使用 API 并給出了可靠的代碼。
更多細(xì)節(jié)請(qǐng)參閱原論文。