完全開源的代碼大模型OpenCoder來了,躋身性能第一梯隊

AIxiv專欄是機器之心發佈學術、技術內容的欄目。過去數年,機器之心AIxiv專欄接收報導了2000多篇內容,覆蓋全球各大高校與企業的頂級實驗室,有效促進了學術交流與傳播。如果您有優秀的工作想要分享,歡迎投稿或者聯繫報導。投稿郵箱:liyazhou@jiqizhixin.com;zhaoyunfeng@jiqizhixin.com

本文的共同第一作者是墨爾本大學計算機科學碩士黃思明和複旦大學計算機科學碩士程天豪。OpenCoder 項目是二人在 INF 實習期間與 M-A-P 開源項目合作的成果,由 INF 主導,M-A-P 積極參與,通訊作者為汪自力與褚崴。來自 INF 參與者包括:郝嘉然,桑治劉一漢,徐陽,汪自力,褚崴,徐盈輝,漆遠。來自 M.A.P 的參與者包括:張舸,張晨晨,柴林政,J.Yang, J.H.Liu。其餘合作者有:J.K.Liu;袁瑞峰;付傑;劉乾,Tiktok 研究員;張兆翔,中國科學院自動化研究所研究員。

代碼大型語言模型(CodeLLM) 在代碼生成、推理任務和智能代理系統等多個領域已變得不可或缺。儘管開源的代碼大模型性能正逐步接近專有模型的水平,但適合進行科學研究的高質量 CodeLLM 仍然非常稀缺,尤其是數據清理流程、合成數據、模型訓練流程全部可複現的全方位開源 CodeLLM。這一稀缺性源於多種挑戰,包括資源限制、倫理考量、保持競爭優勢等需求。

為彌補這一差距,研究團隊推出了 OpenCoder,這是一系列能力達到第一梯隊的 CodeLLM,不僅在性能上可與領先模型媲美,還為研究社區提供了全方面的構建細節。不同於大多數以往的工作,OpenCoder 不僅公開了模型權重和推理代碼,還提供了可重覆的訓練數據、完整的數據處理流程、嚴謹的實驗消融結果以及詳細的訓練細節,為科學研究開放了全面的資源。

研究團隊發現構建高質量 CodeLLM 的關鍵因素有:(1) 數據質量至關重要,代碼預訓練數據需要精細的啟髮式規則清洗與文件粒度的去重(2)預訓練數據中添加互聯網網頁中召回的代碼相關語料(3)在退火和監督微調階段使用高質量的合成數據。

OpenCoder 團隊希望通過更高的開源程度,讓研究人員深入瞭解代碼大語言模型的各個細節,使 OpenCoder 不僅成為強大的模型,更成為開放的基礎平台,加速研究進展,推動代碼 AI 的可複現發展,縮小開源社區與工業界之間的差距。

  • 論文標題:OpenCoder: The Open Cookbook for Top-Tier Code Large Language Model

  • 論文鏈接:https://arxiv.org/abs/2411.04905

  • 項目主頁:https://opencoder-llm.github.io/

  • 模型/數據集下載:https://huggingface.co/OpenCoder-LLM

  • 代碼倉庫:https://github.com/OpenCoder-llm/OpenCoder-llm

預訓練階段

預訓練數據構成了大型語言模型能力的基礎。在開源社區中,The Stack v2 (Lozhkov et al., 2024a) 提供了一個有價值的代碼數據集,有力地支持了代碼語言模型的訓練。然而,The Stack v2 的訓練數據部分質量不足,無法使語言模型達到頂尖性能。

為此,研究團隊提出了 RefineCode,這是一種高質量、可複現的數據集,包含了 9600 億個標記 (token),涵蓋了 607 種編程語言,並融入了 130 多條語言特定規則及其自定義權重分配。該數據集由兩部分組成:原始代碼和代碼相關的網頁數據。

具體來說,團隊主要從 GitHub 上收集原始代碼(截至 2023 年 11 月),並結合了 The Stack v2 中的非 GitHub 數據。此外,代碼相關的網頁數據主要來源於網頁語料庫。研究團隊設計了一個複雜的數據處理流程來生成代碼預訓練語料庫,包含預處理、去重、轉換、過濾與數據重配比。

  • 預處理:排除超過 8MB 的文件,以避免將非文本文件納入數據集,同時僅保留 607 種編程語言相關文件。

  • 去重:首先通過 SHA256 哈希進行精準去重,其次通過 MinHash+LSH 進行模糊去重,優先保留 star 數更高的文件

  • 轉換:進行敏感信息識別檢測

  • 過濾:根據 130 多項啟髮式過濾規則,進一步篩選高質量代碼文件,確保數據的高質量

  • 數據重配比:在確認保持原始分佈的情況下,對 HTML 和 Java 兩類數量較為龐大的編程語言進行下采樣

  • 在以上一整套針對代碼清洗流程後,RefineCode 保留了約 730B 的 token 數量

OpenCoder 首次提出一套針對不同編程語言的詳細過濾規則,並將代碼、調整參數完全開源。啟髮式規則設計準則如下:1) 過濾掉 self-contained 程度過低的代碼;2) 過濾掉邏輯結構差或結構極簡的文件;3) 移除顯著偏離標準代碼格式的文件。

可以注意到,當使用 PCA 對比 The Stack V2 和 RefineCode 的 codebert embedding 時,觀察到這兩個數據集之間有明顯的區別。具體而言,在圖 3 中,The Stack V2 數據顯示出更多的離群點,而 RefineCode 的嵌入則更為緊密地聚集。此外,通過對離群數據的分析,OpenCoder 發現這些離群點通常表現出許多低質量的特徵,例如純文本註釋、僅包含十六進製數據,以及缺乏計算邏輯的極短代碼,這些特徵會擾亂預訓練數據集的分佈,最終影響預訓練的效率。

OpenCoder 同樣從 Common Crawl 數據集中收集高質量代碼相關數據,通過三輪 FastText 訓練、召回、手工網頁標註,最終成功獲取了 330G 代碼相關網頁數據。

OpenCoder 採用了 WSD(Warmup, Steady, Decay)學習率調度策略,以在不同訓練階段中確保模型的穩定性與高效性。在訓練初期,模型通過 2000 步的 warmup 階段逐步提升學習率,達到峰值後進入穩定階段,保持較長時間的固定學習率。最後,在退火階段逐步降低學習率,實現模型的快速精細調優。在退火階段中,除原始分佈 RefineCode 外,OpenCoder 加入了算法相關語料庫,同時合成了高質量代碼段與代碼教科書兩種形式的數據,通過添加算法相關數據以及對算法知識進行反復改寫來進一步增強來提高模型的代碼邏輯能力。

指令微調階段

1. 數據組成

除開源代碼指令數據 (Evol-Instruct, Infinity-Instruct, MCEVal) 外,OpenCoder 從 wildChat,ShareGPT 中采樣了代碼相關的真實用戶指令數據。此外研究團隊還獨立合成了大規模多樣指令數據、教育意義指令數據集與外部庫調用指令數據集,進一步增強了指令微調數據的質量與多樣性。

2. 兩階段訓練策略

OpenCoder 在指令微調期間使用了兩階段的訓練策略。在微調過程的第一階段,重點是廣泛的真實用戶指令與計算機科學理論相關知識。第一階段的微調使 OpenCoder 能夠理解和響應各種真實的用戶需求。這些指令涵蓋了計算機科學的各個方面,從基礎編程到高級算法設計,再到複雜的數據結構操作。由於涵蓋了廣泛的代碼相關指令,OpenCoder 在處理不同類型的編程問題時表現出卓越的適應性,能夠靈活應對多種場景下的編碼需求。

另一個顯著優勢是提升了模型的泛化能力。面對用戶的不同表述和習慣用語,OpenCoder 能夠快速理解意圖並生成適切的解決方案。這種廣覆蓋的訓練使模型不僅在特定任務上表現出色,還能在多樣化的編程需求中提供準確、高效的幫助。

在指令微調的第二階段,OpenCoder 使用高質量的下遊任務相關數據進行訓練,確保模型接觸到現實世界中維護良好、格式規範的代碼實例,且能在具體下遊任務中表現出色。這種兩階段的微調方法使模型在理論知識和實際編程任務上都表現出色,避免了只關注某一方面的局限性。

消融分析

1File-level 去重是代碼數據去重的最優選擇

OpenCoder 在全量 Github 上 485 百萬個 Python 文件上進行了 repo-level,file-level 的去重處理,並在相同參數下訓練了兩個 1.5B 大小的 LLM。首先 repo-level 去重保留的 token 數量近乎是 file-level 的三倍,其次從下遊數據集性能表現發現 file-level 去重效果顯著優於 repo-level

對於 repo-level 的去重,進一步研究發現約有 52B 文件存在完全相同的另一份文件,且約 68B token(約佔數據的 68.4%)可以被進一步 file-level 去重,這說明了 repo-level 去重並不充分。綜上,對於大規模代碼數據集,首先執行精確去重,其次進行文件層面的 MinHash 去重是一種高效且節省 CPU 的方案。

2. 高質量合成數據對於性能提升至關重要

在退火階段訓練過程中,研究團隊消融了高質量合成數據的影響。從下遊 Benchmark 性能可發現,當高質量訓練數據被移除後,模型性能明顯下降,這表明高質量數據在退火階段具有顯著的有效性。

3Github Star 數並不是好的過濾標準

從直覺角度講,更高 Star 的代碼往往具有更清晰的註釋,更優秀的代碼組織方式。研究團隊訓練了兩個 1.5B 的 LLM,其中一個使用原始數據訓練,另一個則使用 GitHub 星級(星級 >=5)過濾後的數據進行訓練,二者的 Benchmark 表現如下圖所示:

可以發現使用原始數據訓練的 LLM 優於使用過濾數據訓練的 LLM,這一結果與 SantaCoder 的研究結果一致。此外,研究團隊進一步展示了這兩個 LLM 的訓練損失,可以觀察到使用過濾數據訓練的 LLM 的損失低於使用原始數據訓練的 LLM。對此現象,研究團隊推測使用星級作為過濾信號能夠提升數據質量,但相較於原始數據,數據的多樣性有所限制。通過對二者數據分佈的可視化分析,團隊進一步驗證了星級過濾顯著影響了整體數據分佈,削弱了數據多樣性這一推斷。

此外,通過人工檢查被過濾部分的數據可以發現其仍包含大量結構良好且具有算法豐富性的代碼。因此,研究團隊認為星級作為過濾標準並非最佳選擇。

4. 兩階段 SFT 方法在 Benchmark 和實際應用中取得雙重收益

研究團隊在 1.5B 模型上驗證了兩階段 SFT 的收益。通過觀察發現,Stage 1 的數據展現出顯著的多樣性,但平均質量相對較低。相比之下,Stage 2 的數據由高質量的代碼特定 SFT 數據組成。該兩階段 SFT 策略使得模型在 Stage 1 中獲得廣泛的能力,隨後在 Stage 2 中針對代碼相關任務進行針對性提升。此外,類似於 Chatbot Arena,研究團隊採用包含近 400 個人工創建樣本的 Code Arena 測試集,以模擬真實環境中的用戶代碼相關提示。Code Arena 以 GPT-4 作為基準,並用 GPT-4 來判斷哪個大語言模型(LLM)具有更好的響應能力,報告的結果為相對於 GPT-4 的勝率。結果展示了兩階段 SFT 訓練策略在下遊 Benchmark 上與體現真實應用能力的 Code Arena 上皆有收益。

評估結果

OpenCoder 模型在 HumanEval、MBPP 兩主流模型評估任務上顯著超過了現有開源模型,驗證了其數據處理流程與合成數據的有效性。

為了檢驗 OpenCoder 的代碼生成能力,研究團隊在多個基準上將它與其他流行的開源模型(如 StarCoder2 、Qwen2.5-Coder 等)進行了比較,包括 HumanEval、MBPP、BigCodeBench 和 LiveCodeBench。結果表明,OpenCoder 在這些評估中達到了開源模型的一流水準。

此外,在多語言代碼生成評估基準 MultiPL-E ,綜合多語言代碼評估基準 McEval 和多語言代碼調試基準 MdEval 中,OpenCoder 表現也同樣突出,證實了其出色的多語言性能。

實際使用

以下是由 OpenCoder-8b-Instruct 生成的貪吃蛇 demo。使用的 prompt 為 「Write a greedy snake game with randomly generated obstacles using pygame」。可以看到生成的代碼可以不經過任何修改正常運行,且符合 prompt 中的設計要求。

© THE END