【新智元導讀】6 月,IEEE 刊登了一篇對 ChatGPT 代碼生成任務進行系統評估的論文,數據集就是程序員們最愛的 LeetCode 題庫。研究揭示了 LLM 在代碼任務中出現的潛在問題和能力局限,讓我們能夠對模型做出進一步改進,并逐漸了解使用 ChatGPT 寫代碼的最佳姿勢。
有了 ChatGPT,還需要人類程序猿編碼嗎?
上個月,一項發表在 IEEE TSE 期刊(Transactions on Software Engineering)上的研究評估了 ChatGPT 所生成的代碼在功能性、復雜性和安全性方面的表現。
結果顯示,ChatGPT 生成可用代碼的能力差異很大。
其成功率從 0.66% 到 89% 不等,這主要取決于任務的難度、編程語言等多種因素。
論文地址:https://ieeexplore.ieee.org/ document / 10507163
具體來說,研究人員測試了 GPT-3.5 在 5 種編程語言(C、C++、Java、JavaScript 和 Python)中,解決 LeetCode 測試平臺上的 728 個編碼問題,以及應對 18 個 CWE(常見缺陷枚舉)場景的能力。
雖然在某些情況下,AI 能夠生成比人類更優質的代碼,但分析也揭示了,一些 AI 生成代碼的安全性問題。
論文作者、格拉斯哥大學助理教授 Yutian Tang 指出,「AI 代碼生成一定程度上,可以提升開發效率,自動化軟件工程。然而,我們必須認識這類模型優勢和不足,以便合理應用」。
「通過全面的分析,可以發現 ChatGPT 生成代碼過程中,出現的潛在問題和局限性,進而改進生成技術」。
有網友慶幸地發出疑問,所以我還沒有被解雇?另一人對此表示,至少不是今天。
還有人指出,這項研究是關于 GPT-3.5 的評估。要是 GPT-4 早就在編碼能力上大幅提升,Claude 3.5 更是如此。
確實,現在我們有了更好的模型,對于 GPT-3.5 模型的評估,并沒有太大的意義。
總體而言,ChatGPT 在不同編程語言的問題上表現相當不錯 —— 特別是在嘗試解決 2021 年之前 LeetCode 上的編碼問題時。
例如,它能夠為簡單、中等和困難的問題生成可運行代碼,成功率分別約為 89%、71% 和 40%。
然而,當涉及到 2021 年之后的算法問題時,ChatGPT 生成正確運行代碼的能力受到影響。即使是簡單級別的問題,它有時也無法理解問題的含義。
比如,ChatGPT 在生成「簡單」編碼問題的可運行代碼方面的能力,在 2021 年后從 89% 下降到 52%。
而它在生成「困難」問題的可運行代碼方面的能力也在此時間后從 40% 下降到 0.66%。
Tang 對比表示,「一個合理的假設是,ChatGPT 在 2021 年之前的算法問題上表現更好的原因是這些問題在訓練數據集中經常出現」。
接下里,具體看看研究者們對 ChatGPT 進行了哪些方面的評估。
實驗評估評估的整體流程如圖 2 所示。
首先為給定的 LeetCode 問題或 CWE 場景構造合適的提示并發送給 ChatGPT,讓它根據提示和上一輪對話的上下文信息給出響應。
之后,研究人員將模型響應中的代碼片段提交給 LeetCode 平臺,利用其在線判斷功能來檢驗代碼的正確性,CWE 漏洞則使用 CodeQL 進行手動分析。
如果測試結果通過,則生成結束,否則就需要利用 LeetCode 和 CodeQL 的反饋繼續建立新的提示、輸入給 ChatGPT,再次進行代碼生成。
如果 ChatGPT 在對話輪數限制(5 輪)之內始終沒有生成出通過測試的代碼,則認為生成任務失敗。
ChatGPT 生成的代碼在功能上是否正確?
研究動機:
給定提示,ChatGPT 生成相應的文本,這種能力可能會提高開發者的生產力。首先去評估 ChatGPT 在單輪對話中,自動生成功能正確代碼的能力。
研究方法:
- 讓 ChatGPT 閱讀問題描述,在單輪對話中生成相應代碼。(最大對話輪數設為 1)
- 使用 LeetCode 平臺上的編程問題作為數據集,截止研究時,有 2500 個難度不等的問題。
- 將 LeetCode 所有問題分為 2021 年之前(Bef.problems)和 2021 年之后(Aft.problems)兩類,因為 ChatGPT 的訓練數據截止于 2021 年。
- 考慮到 2021 年之前的問題可能已存在于 ChatGPT 的訓練集中,這可能使代碼生成任務退化為簡單的數據庫查詢(即代碼復用)。為了進行全面評估,研究中同時考慮了這兩類問題。
具體而言,研究人員重點關注 LeetCode 上的算法問題,因為算法問題是該平臺上最重要、最多和最多樣化的問題。
Bef.problems 和 Aft.problems 的總數分別為 1624 個和 354 個。此外,兩者的難度分布為難、中、易,比例為 1:2:1。
在所有 Bef.problems 中,作者隨機抽取了 374 個問題,其數量與 Aft.problems 相似,難度分布也與 Aft.problems 相同。
同樣,在 354 個 Aft.problems 和 Bef.problems 中,難、中、易問題的數量比例也是 1:2:1,與 LeetCode 平臺上所有問題的難度分布一致。
此外,研究人員還檢查了 Bef.problems 和 Aft.problems 之間是否存在顯著差異。
如果 Aft.problems 只是 Bef.problems 的重構,那么 ChatGPT 很可能可以輕松解決這些問題,這可能會影響實驗結果在區分時間段方面的可靠性。
論文中,作者總共找到了 142 對問題。然后,再讓 2 名研究生獨立檢查這些問題對。
通過仔細核對和討論,結果發現這些相似的問題要么情景相似,但求解目標完全不同;要么情景和條件不同,但可以使用類似的算法(如動態編程)求解。
經過仔細的人工分析,作者沒有發現在任何情況下,Bef.problems 可以很容易地重新表述為 Aft.problems。
因此,作者認為 Aft.problems 和 Bef.problems 之外,對于每個問題,都要求 ChatGPT 用 5 種不同的語言生成代碼:C、C++、Java、Python3 和 JavaScript。
此外,他們還使用相同的提示模板為每個 <問題、語言> 對創建了相應的提示。
Bef.problems 和 Aft.problems 分別共有 1,870 和 1,770 個提示。由于 ChatGPT 的查詢速度有限,研究者將每條提示輸入一次,要求生成代碼。
然后,研究者將解析后的解決方案,提交給 LeetCode 進行功能正確性判斷,并得到提交狀態,包括接受、回答錯誤、編譯錯誤、超過時間限制和運行錯誤。
它們分別對應于 A.、W.A.、C.E.、T.L.E.和 R.E.。一個問題對應一個唯一的對話,以避免從其他問題觸發 ChatGPT 的推理。
實驗中,作者以狀態率(SR)來評估 ChatGPT 的代碼生成能力。其中 Nc 和 Ni 分別是根據狀態生成的代碼片段數和輸入的提示數。
提示:
所設計的提示模板由 4 個部分組成:它們分別是 <Content>、<Examples>、<Template > 和 < Command>。
<Content> 用自然語言描述問題,<Examples> 顯示功能正確的代碼 <input, output> 對,<Template> 指定生成代碼的方法簽名(method signature),<Command> 要求用特定語言生成代碼。
結果:
表 1 和表 2 顯示,LeetCode 對五種編程語言在兩個時間段、兩種形式下的代碼生成結果、SR 以及相應的相對頻率柱形圖。
由于 Python3 和 JavaScript 都是動態編程語言,因此這兩列不包含 C.E.。
從總體結果來看,ChatGPT 為 Bef.problems 生成的功能正確代碼的 A.率明顯高于 Aft.problems。
具體來說,Bef.problems 的五種語言平均正確率(68.41%)比 Aft.problems 的(20.27%)高出 48.14%。
五種語言在不同階段的代碼生成性能差異顯著,P 值為 0.008,效應大小值為 1。
對于 Aft.problems,總體正確率低于 25%,其中難、中、易問題的正確率分別為 0.66%、13.90% 和 52.47%。
用 Holm-Bonferroni 校正程序調整的 P 值和五種語言不同難度之間的效應大小值分別小于 0.05 和等于 1。
結果表明,面對 Aft.problems,隨著問題難度的增加,ChatGPT 在功能上正確生成代碼的能力明顯下降。
此外,即使是簡單的問題,它也只能正確回答一半。
在這五項 / 四項指標中,W.A.率是所有語言中最高的一項,達到 58%。
此外,每個 W.A.代碼片段平均有 109 個測試用例,而 ChatGPT 生成的代碼只能通過其中的 25%。
難題、中難題和簡單難題的測試用例通過率分別為 20.90%、21.03% 和 38.41%。因此,無論難度如何,生成代碼的語義都與相應問題描述的邏輯有很大差異。
此外,C.E.率和 R.E.率也都達到了 16%,而且難題和中難題的 C.E.率明顯高于簡單難題。
ChatGPT 生成的中難題代碼,更容易出現編譯和運行時錯誤。比如,圖 4 中顯示生成的函數 cmpfunc,在調用前沒有聲明。語法錯誤只占這些錯誤的一小部分(3.7%)。
至于 T.L.E.率,雖然數值不高(6%),但測試用例的平均通過率為 51%,高于 W.A.代碼片段。
T.L.E.問題的難、中、易三個難度級別的測試用例,平均通過率分別為 68%、50% 和 1%(易問題由于其 T.L.E.率接近 0%,可以忽略不計)。
由于 T.L.E.代碼片段的測試用例通過率是部分的,不過生成的代碼中最多還有 6% 在功能上是正確的,盡管它們的時間復雜度可能并不理想。
細分到每種語言,C、C++、Java、Python3 和 JavaScript 的 A.率分別為 15.38%、19.37%、20.17%、23.93% 和 22.51%。
此外,圖 5 顯示了將五種不同語言與每個問題(僅考慮至少有一個正確解決方案的問題)相結合的 A.率分布(接受率分布)。
從圖中可以看出,Medium 語言的平均線和中位線都≤0.5,而 Easy 語言的平均線和中位線都≥0.6。
對于簡單問題 ChatGPT 更容易將生成的代碼泛化到不同的語言中。簡單問題和中等問題的中位數和均值分別為 0.4 和 0.5。
對于 Bef. Problems 問題方面,難、中、易問題的正確率分別為 40.13%、70.95% 和 89.80%,遠高于 Aft. problems,但不同難度之間仍存在顯著差異。
用 Holm-Bonferroni 校正程序調整后的 P 值和難與中、難與易之間的效應大小值分別小于 0.05 和大于 0.9。
五種語言中,中等難度和簡單難度之間的調整后 P 值和效應大小值分別為 0.056 和 0.76。
ChatGPT 在解決 2021 年之前訓練集中可能出現的問題時,表現更好,尤其是中等難度和簡單難度的問題。
解決難題的正確率提高了 40%,但仍低于 50%,這表明 ChatGPT 生成邏輯復雜問題代碼的能力仍有很大的提升空間。
總體正確率下降到 17.03%,難、中、易問題的正確率分別為 32.89%、15.05% 和 6%。
生成的代碼仍能通過平均 112 個測試用例中的 25%。難、中、易問題的測試用例通過率分別為 19.19%、31.12% 和 47.32%。
后兩者都提高了 10%,這表明 ChatGPT 對 Bef. Problems 有更好的理解力。
不過,C.E.率和 R.E.率仍達到 13%,接近 Aft. problems 的 16%,兩個階段之間的 P 值和效應大小值分別為 0.328 和 0.3125,且困難問題通過率最高,中難度問題通過率次之。
編譯錯誤和運行時錯誤與 Aft. problems 類似,例如,圖 6 所示代碼用于重塑給定的二維矩陣,但在第 15 行引發了運行時錯誤,該行為 * returnColumnSizes 分配了錯誤大小的內存。
至此,T.L.E.率降至 1.87%,測試用例平均通過率為 74%。
接下來,再細分到每種語言,C、C++、Java、Python3 和 JavaScript 的 A.率分別為 47.24%、68.63%、76.37%、75.35% 和 74.44%。
后四種語言的 A.率值彼此接近,且大大高于 C(最低級別語言)的 A.率值,至少高出 20%。
圖 7 顯示的是與圖 5 相同的 Bef. Problems。從圖中可以看出,中等題和簡單題的平均線和中位線都≥0.75,而且它們的中位數和平均值之間的差異比之前的 Aft. problems 要小一半。
此外,有難度的平均線和中位線都≥ 0.55。對于 Bef. Problems,ChatGPT 更容易將代碼擴展到不同的語言中。
ChatGPT 接受的問題的人類平均接受率為 55%,而 ChatGPT 未接受的問題的人類平均接受率為 47%。
總而言之,通過實驗,ChatGPT 在功能性正確代碼生成任務上,比起 Aft. problems,更加擅長解決不同編程語言中的 Bef. Problems。
尤其是,前者的平均正確率比后者高出 48.14%。此外,不同的難度也會影響基于 ChatGPT 的代碼生成。
對于兩個階段的問題,ChatGPT 都能生成運行時間和內存開銷小于至少 50% 的人類解決方案的代碼。
無論哪個階段的問題,ChatGPT 生成的代碼出現編譯或運行時錯誤的概率都差不多,平均為 14.23%。
在所有問題中,C++、Java、Python3 和 JavaScript 的 A.率值分別為 44.75%、48.74%、50.00% 和 48.80%,彼此接近,且大大超越 C 的 31.28%。
在這個方面,作者想探究 ChatGPT 支持的多輪對話能力在改進代碼正確性上究竟表現如何?人類能夠「知錯就改」,LLM 可以嗎?
首先,研究人員對 ChatGPT 生成的 157 段代碼的錯誤類型進行了分析,可以大致分為以下幾類:
- 細節錯誤(WD):代碼細節上的錯誤一般源于誤解題意,或者代碼與問題理解不一致,但大體邏輯基本正確,因此這類錯誤很容易被修復。
- 誤解某些內容(MCC):生成代碼沒有滿足給定問題的主要條件,使用的算法合適,但需要修改其核心。
- 誤解問題(MP):指 ChatGPT 完全錯解了題意,這是最難修復的一種情況,代碼需要完全重寫,
將錯誤信息反饋給 ChatGPT 的方式依舊延續了圖 3 所示的格式,包括原始問題、生成代碼片段、LeetCode 的報錯信息以及相應指令。
進行不超過 5 輪的對話修復后,得到了表 5 所示的結果。
可以看到,157 個問題中能通過自動化修復的只有 25 個,其中 16 個屬于簡單模式,困難問題的錯誤答案幾乎不可能被修復。
如果把對話輪數的上限增加到 10 輪呢?結果依舊不樂觀。
從 157 個問題中隨機選出 10 個,結果只有其中 2 個能在 10 輪內成功修復,剩下的 8 個依舊無法通過。這能讓研究人員進一步分析 ChatGPT 很難自動修復的原因。
作者認為,一方面,ChatGPT 缺乏掌握邏輯細節的能力;另一方面,在需要復雜邏輯推理的問題中,生成代碼往往偏離問題的實際含義,這即使對于人類程序員也很難修復。
代碼復雜度代碼的復雜性對于可讀性、可維護性以及整體質量來說,都是一個重要的影響因素。想象一下,如果 ChatGPT 對簡單的排序問題都生成出了你很難看懂的代碼,那會大大拉低使用體驗。
作者利用了 SonarQube 和 cccc 兩個指標來評估 LeetCode 數據集中 Bef.問題的復雜程度,并評估響應生成代碼的循環復雜度(cyclomatic complexity)和認知復雜度(cognitive complexity)。
循環復雜度會計算執行時線性獨立路徑的數量,從而體現源代碼的測試難度。認知復雜度則從人類角度衡量理解、推理一段代碼的難度。
由于以上量化標準不夠直觀,研究人員還同時評估了人類編寫的 C++ 和 Python3 的 LeetCode 問題解答來與 ChatGPT 進行比較。
圖 20 的對比中可以看出,C 代碼的復雜度最高,C++、Java 和 JavaScript 次之并基本處于同一水平,Python3 是最不復雜的,這與我們的固有認知基本吻合。
此外,與人類相比,ChatGPT 生成的代碼雖然復雜度稍高,但差距并不明顯。
隨著 LeetCode 問題難度逐漸升高(表 16),無論是人類還是 ChatGPT,低復雜度代碼的占比都會逐漸降低,復雜度被分類為「高」和「非常高」的占比也隨之逐漸提高,這種趨勢也是類似的。
然而,不好的消息是,ChatGPT 的多輪修復功能似乎沒法讓代碼更簡潔,多數情況下會維持甚至提高代碼的復雜
性,這或許也是多輪修復功能效果不理想的原因之一。
由于 ChatGPT 訓練時可能學習到了各種各樣的內容,包括質量較低、易受攻擊的代碼,因此評估生成代碼的安全性也非常重要。
由于 LeetCode 的算法代碼通常專注于解決特定的邏輯或計算問題,并不涉及管理系統資源、網絡通信等通常有敏感安全問題的操作,因此在這部分的評估中,論文同時采取了兩種路徑。
1) 利用 CodeQL 對 LeetCode 答案的所有 C、C++ 和 Java 代碼進行漏洞檢測,針對 MITRE Top25 中的 5 個 CWE 問題,包括指針和內存相關的共 30 個查詢。
2) 針對 MITRE Top25 中的 18 個 CWE 問題,每個問題提供 3 種上下文場景,給 ChatGPT「挖坑」,要求它補全代碼,再用 CodeQL 自動檢測看是否確實出現了相應問題。
在第一個測試中(表 18),ChatGPT 表現良好,91.8% 的錯誤集中在 MissingNullTest 這一類,其余的漏洞的出現頻次則一般不超過 5 次。
但仍要注意的是,ChatGPT 在 CWE 787,即「越界寫入」問題上表現不佳,這可能會導致潛在的代碼漏洞。
而且,由于這些漏洞的修復比較簡單,因此在給定錯誤信息并要求生成修復代碼后,ChatGPT 也能較好完成任務。
要求 ChatGPT 修復 CWE-787 問題的提示模板
在第二個測試 —— 安全代碼生成方面,ChatGPT 共生成了 2983(99.07%)個有效代碼片段,其中 994 個存在安全漏洞,占比達到 33.32%。
而且,C 語言中的易受攻擊片段的百分比(51.64%)遠遠高于 Python3(17.08%),這有可能是由于 C 代碼本身就對程序的內存安全提出了更高的要求,也可能源于訓練數據中 C 和 Python3 代碼的質量差距。
多輪修復功能依舊表現出色,89.4% 的漏洞都能在給出 CWE 信息后成功解決,比如溢出、數據泄露、不安全內存操作、未經身份驗證訪問等相關問題。
ChatGPT 非確定性ChatGPT 的非確定性輸出如何影響代碼生成?
如下表所示,表 22 和表 23 分別列出了所選算法問題和溫度為 0.7 時的實驗結果。
在溫度為 0 的條件下,10 次試驗中,算法問題和 CWE 代碼場景的非確定性代碼生成統計結果如表 24、表 25 和表 26 所示。
其中表 26 列出了所選的 20 個 CWE 代碼場景。
此外,作者還研究了非確定性對多輪修復過程的影響,修復結果如表 27-32 所示。
溫度設為 0.7,5 次試驗中算法問題的多輪修復過程。
溫度設為 0,5 次試驗中算法問題的多輪修復過程。
溫度設為 0.7,5 次試驗中算法問題的 CWE 多輪修復過程。
溫度設為 0,5 次試驗中算法問題的 CWE 多輪修復過程。
溫度設為 0.7,5 次試驗中安全代碼生成的多輪修復過程。
溫度設為 0,5 次試驗中安全代碼生成的多輪修復過程。
總之,實驗中,當溫度設置為 0.7 時,單輪流程中的代碼生成可能會受到 ChatGPT 非確定性因子的影響,從而導致代碼片段在功能正確性、復雜性和安全性方面出現差異。
要減輕 ChatGPT 在單輪過程中的非確定性,一種可能的策略是將溫度設置為 0。
然而,在多輪修復過程中,無論溫度設置為 0.7 還是 0,ChatGPT 固定的代碼片段在功能正確性、復雜性和安全性方面都可能存在差異。
參考資料:
https://ieeexplore.ieee.org/document/10507163
https://spectrum.ieee.org/chatgpt-for-coding
https://arxiv.org/abs/2308.04838
本文來自微信公眾號:新智元(ID:AI_era)
本文鏈接:http://www.www897cc.com/showinfo-45-5079-0.htmlChatGPT 無法取代人類程序員: IEEE 35 頁論文測出困難編碼正確率僅為 0.66%
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 五糧液濃香酒:勞動節送禮的精致藝術