BigCodeBench:下一代 HumanEval
HumanEval 是評估大型語言模型 (LLM) 程式碼生成任務的參考基準,因為它簡化了對緊湊函式級程式碼片段的評估。然而,其在評估 LLM 程式設計能力方面的有效性日益受到關注,主要擔憂是 HumanEval 中的任務過於簡單,可能無法代表真實世界的程式設計任務。與 HumanEval 中面向演算法的任務相比,真實的軟體開發通常涉及多樣的庫和函式呼叫。此外,LLM 在 HumanEval 上的表現容易受到汙染和過擬合問題的影響,這使其在評估 LLM 的泛化能力方面可靠性較低。
儘管已經有一些努力來解決這些問題,但它們要麼是特定領域的、確定性的,要麼是面向 Agent 的(抱歉了 DS-1000、ODEX 和 SWE-bench 💔)。我們認為社群仍然缺乏一個易於使用、能夠廣泛評估 LLM 程式設計能力的基準,而這正是我們關注的重點。
我們很高興地宣佈釋出 BigCodeBench,它可以在無汙染的情況下評估 LLM 解決實際且具有挑戰性的程式設計任務的能力。具體來說,BigCodeBench 包含 1140 個函式級任務,挑戰 LLM 遵循指令並組合來自 139 個庫的多個函式呼叫作為工具。為了嚴格評估 LLM,每個程式設計任務都包含 5.6 個測試用例,平均分支覆蓋率達到 99%。
準備好深入瞭解 BigCodeBench 了嗎?讓我們開始吧!🚀
BigCodeBench 中的任務是什麼樣的?🕵️♂️
BigCodeBench 每個任務都具有複雜的、面向使用者的指令,包括清晰的功能描述、輸入/輸出格式、錯誤處理以及經過驗證的互動式示例。我們避免了分步式的任務指令,認為有能力的 LLM 應該能夠從使用者的角度以開放式的方式理解和解決任務。我們使用測試用例來驗證特定功能。
# We elaborate the above task with some test cases:
# Requirements SetUp
import unittest
from unittest.mock import patch
import http.client
import ssl
import socket
# Start the test
class TestCases(unittest.TestCase):
# Mock the successful connection and assess the response content
@patch('http.client.HTTPSConnection')
def test_response_content(self, mock_conn):
""" Test the content of the response. """
mock_conn.return_value.getresponse.return_value.read.return_value = b'Expected Content'
result = task_func('www.example.com', 443, '/content/path')
self.assertEqual(result, 'Expected Content')
# Mock the failed connection and assess the error handling
@patch('socket.create_connection')
@patch('http.client.HTTPSConnection')
def test_ssl_handshake_error_handling(self, mock_conn, mock_socket):
""" Test handling of SSL handshake errors. """
mock_socket.side_effect = ssl.SSLError('SSL handshake failed')
with self.assertRaises(ssl.SSLError):
task_func('badssl.com', 443, '/test/path')
# More test cases...
BigCodeBench 中的任務利用了來自流行庫的多種函式呼叫。我們不限制 LLM 可以使用的函式呼叫,期望它們能夠選擇合適的函式並靈活地組合它們來解決任務。測試用例被設計為測試框架,用於在執行時檢查預期的程式行為。
為了評估 LLM 的效能,我們使用貪心解碼的 Pass@1,透過精心設計的測試用例,衡量模型使用首次生成的程式碼片段正確解決任務的百分比。這種方法與 HumanEval 和 MBPP 等基準一致。我們透過在 Pass@1 評估期間新增缺失的設定(例如,import 語句、全域性常量)來解決 LLM 傾向於跳過長程式碼提示的問題,我們稱之為校準 Pass@1 (calibrated Pass@1)。
為了更好地理解實現複雜性和工具使用的多樣性,我們將 BigCodeBench 中的任務與一些代表性基準中的任務進行了比較,包括 APPS、DS-1000、ODEX、APIBench、MBPP、NumpyEval、PandasEval、HumanEval 和 TorchDataEval。我們發現,BigCodeBench 需要更復雜的推理和問題解決能力來實現全面的功能。
如任務圖所示,主要目標場景是程式碼補全(表示為 BigCodeBench-Complete
),其中要求 LLM 根據文件字串中的詳細指令完成函式的實現。然而,考慮到多輪對話等下游應用,使用者可能會以更具對話性、更簡潔的方式描述需求。這正是指令調優的 LLM 的優勢所在,因為它們經過訓練可以遵循自然語言指令並相應地生成程式碼片段。為了測試模型是否能真正理解人類意圖並將其轉化為程式碼,我們建立了 BigCodeBench-Instruct
,這是 BigCodeBench 的一個更具挑戰性的變體,旨在評估指令調優的 LLM。
這些任務從何而來?🤔
我們透過系統的“人機協作流程”來保證 BigCodeBench 中任務的質量。我們以 ODEX 作為“種子資料集”開始,該資料集包含來自 Stack Overflow 的簡短但真實的人類意圖和相應的 Python 單行程式碼。我們使用 GPT-4 將這些單行程式碼擴充套件為全面的函式級任務。
接下來,20 位人類專家(其中大多數擁有超過 5 年的 Python 程式設計經驗)自願在一個基於執行的沙箱中指導 GPT-4。他們不斷地指示它優化合成的任務並新增測試用例。然後,這些任務和測試用例在本地環境中進行檢查,在其他 LLM 上進行預評估,並由另外 7 位人類專家進行交叉核對,以確保其質量。
為了確保整體質量,作者們抽樣了一些任務讓 11 位人類專家解決,達到了 97% 的平均人類表現。
大語言模型 (LLM) 在 BigCodeBench 上的表現如何?📊
我們在 Hugging Face Space 和 GitHub Pages 上都託管了 BigCodeBench 排行榜。在這裡,我們以 Hugging Face 排行榜為例。
有趣的是,我們觀察到像 GPT-4 這樣的指令調優 LLM 在 BigCodeBench-Complete
的長提示中會省略必要的 import 語句,導致因缺少模組和常量而任務失敗。這種行為被稱為“模型懶惰”,在社群中有所討論。
與人類表現相比,LLM 在 BigCodeBench-Complete
上的表現明顯較低,在 BigCodeBench-Instruct
上的表現更低。最好的模型(GPT-4o)在 BigCodeBench-Complete
上實現了 61.1% 的校準 Pass@1,在 BigCodeBench-Instruct
上實現了 51.1%。此外,閉源和開源 LLM 之間存在顯著的效能差距。
雖然 Pass@1 是一個衡量整體效能的好指標,但它不夠詳細,無法直接比較模型。受 Chatbot Arena 的啟發,我們使用 Elo 評級來對 BigCodeBench-Complete
上的模型進行排名。這種方法最初用於國際象棋,根據玩家的比賽表現進行排名。我們將其應用於程式設計任務,將每個任務視為一場比賽,每個模型視為一名玩家。Elo 評級的更新基於比賽結果和預期,使用任務級別的校準 Pass@1(0% 或 100%),並排除平局。我們從 1000 的初始 Elo 評級開始,使用最大似然估計進行擬合,並透過 500 次自舉 (bootstrap) 獲得最終分數。我們發現 GPT-4o 以較大優勢領先於其他模型,而 DeepSeekCoder-V2 處於第二梯隊。
為了幫助社群瞭解模型在每個任務上的表現,我們跟蹤瞭解決率,該解決率透過校準 Pass@1 來衡量。在 BigCodeBench-Complete
上,有 149 個任務仍未被任何模型解決,而有 6 個任務被完全解決。對於 BigCodeBench-Instruct
,有 278 個任務仍未被解決,有 14 個任務被所有模型完全解決。大量未解決的任務和少量完全解決的任務表明,BigCodeBench 對 LLM 來說是一個具有挑戰性的基準。
太好了!那麼,我該如何在 BigCodeBench 上評估我的模型?🛠️
我們透過提供一個簡單且使用者友好的評估框架,使社群可以輕鬆訪問 BigCodeBench,該框架可透過 PyPI 下載。該評估框架的原型基於用於 HumanEval+ 和 MBPP+ 基準的 EvalPlus。然而,由於我們的基準測試任務的庫依賴性比 EvalPlus 多樣得多,我們構建了資源限制較少的執行環境,並將其調整為適用於 BigCodeBench 測試框架中的 unittest
。
為了方便評估,我們為程式碼生成和程式碼執行提供了預構建的 Docker 映象。請檢視我們的 GitHub 倉庫,瞭解有關如何使用評估框架的更多詳細資訊。
設定
# Install to use bigcodebench.evaluate
pip install bigcodebench --upgrade
# If you want to use the evaluate locally, you need to install the requirements
pip install -I -r https://raw.githubusercontent.com/bigcode-project/bigcodebench/main/Requirements/requirements-eval.txt
# Install to use bigcodebench.generate
# You are strongly recommended to install the [generate] dependencies in a separate environment
pip install bigcodebench[generate] --upgrade
程式碼生成
建議您使用 flash-attn
來生成程式碼樣本。
pip install -U flash-attn
要從模型生成程式碼樣本,您可以使用以下命令:
bigcodebench.generate \
--model [model_name] \
--subset [complete|instruct] \
--greedy \
--bs [bs] \
--temperature [temp] \
--n_samples [n_samples] \
--resume \
--backend [vllm|hf|openai|mistral|anthropic|google] \
--tp [gpu_number] \
[--trust_remote_code] \
[--base_url [base_url]]
生成的程式碼樣本將儲存在一個名為 [model_name]--bigcodebench-[instruct|complete]--[backend]-[temp]-[n_samples].jsonl
的檔案中。
程式碼後處理
LLM 生成的文字可能不是可編譯的程式碼,因為它包含自然語言行或不完整的額外程式碼。我們提供一個名為 bigcodebench.sanitize
的工具來清理程式碼。
# 💡 If you want to store calibrated code in jsonl:
bigcodebench.sanitize --samples samples.jsonl --calibrate
# Sanitized code will be produced to `samples-sanitized-calibrated.jsonl`
# 💡 If you do without calibration:
bigcodebench.sanitize --samples samples.jsonl
# Sanitized code will be produced to `samples-sanitized.jsonl`
# 💡 If you are storing codes in directories:
bigcodebench.sanitize --samples /path/to/vicuna-[??]b_temp_[??]
# Sanitized code will be produced to `/path/to/vicuna-[??]b_temp_[??]-sanitized`
程式碼評估
強烈建議您使用沙箱,例如 docker
# Mount the current directory to the container
docker run -v $(pwd):/app bigcodebench/bigcodebench-evaluate:latest --subset [complete|instruct] --samples samples-sanitized-calibrated
# ...Or locally ⚠️
bigcodebench.evaluate --subset [complete|instruct] --samples samples-sanitized-calibrated
# ...If the ground truth is working locally (due to some flaky tests)
bigcodebench.evaluate --subset [complete|instruct] --samples samples-sanitized-calibrated --no-gt
下一步是什麼?
我們分享一個長期路線圖,以解決 BigCodeBench 的侷限性,並與社群一起可持續地建設。我們的目標是為社群提供最開放、可靠和可擴充套件的評估,以真正瞭解 LLM 在程式設計方面的基本能力,並找出釋放其潛力的方法。具體來說,我們計劃在以下方面增強 BigCodeBench:
多語言性:目前,BigCodeBench 僅支援 Python,無法輕易擴充套件到其他程式語言。由於函式呼叫大多是特定於語言的,因此在 Python 以外的語言中找到具有相同功能的包或庫具有挑戰性。
嚴謹性:雖然我們在 BigCodeBench 中為基準解決方案實現了高測試覆蓋率,但這並不能保證由 LLM 生成的所有程式碼解決方案都能透過現有測試用例得到正確評估。像 EvalPlus 這樣的先前工作已經嘗試透過基於 LLM 和突變的策略來擴充輸入-輸出對,從而擴充套件有限的測試用例。然而,將 EvalPlus 應用於 BigCodeBench 的測試框架具有挑戰性。雖然 EvalPlus 強調輸入-輸出斷言,但 BigCodeBench 中的大多數測試框架都需要非平凡的配置(例如,模擬補丁)來檢查執行時的預期程式行為。
泛化性:一個關鍵問題是,“模型對未見過的工具和任務的泛化能力如何?”目前,BigCodeBench 涵蓋了常見的庫和日常程式設計任務。在那些使用新興庫(如 transformers 和 langchain)的程式設計任務上對模型進行基準測試會更有趣。
演進性:庫可能會過時或更新,這意味著用於模型訓練的原始碼資料將不斷演變。模型可能不會記住已棄用庫版本的函式呼叫,這給任何依賴於工具的程式設計基準帶來了挑戰,使其難以在沒有定期更新的情況下正確檢驗模型能力。另一個相關問題是由於訓練資料的演變而導致的測試集汙染。
互動性:最近的興趣集中在作為智慧體的 LLM 這一概念上,這被視為通往通用人工智慧的一條路徑。具體來說,LLM 將被置於一個限制較少的沙箱環境中,在那裡它們可以與 Web 瀏覽器和終端等應用程式進行互動。這種環境有助於解鎖自我除錯和自我反思等能力。
我們很高興看到社群的反饋和貢獻,共同長期建設 BigCodeBench 🤗
資源
我們開源了 BigCodeBench 的所有產物,包括任務、測試用例、評估框架和排行榜。您可以透過以下方式找到它們:
如果您有任何問題或建議,請隨時在倉庫中提出問題,或透過 terry.zhuo@monash.edu 或 contact@bigcode-project.org 與我們聯絡。
引用
如果我們的評估對您有用,請考慮引用我們的工作:
@article{zhuo2024bigcodebench,
title={BigCodeBench: Benchmarking Code Generation with Diverse Function Calls and Complex Instructions},
author={Zhuo, Terry Yue and Vu, Minh Chien and Chim, Jenny and Hu, Han and Yu, Wenhao and Widyasari, Ratnadira and Yusuf, Imam Nur Bani and Zhan, Haolan and He, Junda and Paul, Indraneil and others},
journal={arXiv preprint arXiv:2406.15877},
year={2024}
}