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