可執行單元校驗:在IDE中提升AI智能體代碼的准確性

代碼爲聘禮 2024-04-03 01:31:29

在開發 IDE 插件 AutoDev 時,我們一直遵循著 Unit Mesh 的基本思想,即 AI 所生成的應該是可執行的單元(Unit)。在底層構建豐富的各類單元/工具, 再結合 DevIns 來構建強大的智能體能力。

在初步完成了 AutoDev 的整體藍圖(MVP)之後,我們開始強化原來的准確性問題,即 AI 所生成的代碼是否可以被編譯器編譯,是否可以被測試覆蓋等。在這些 功能中,我們最想解決的是:AI 所生成的代碼單元是否可執行?

爲什麽是可執行率?從 0.8 到 0.96 的提升

在去年,我們在進行微調試驗的時候,曾經使用 GPT-3.5 API 根據 3000 個場景生成 3000 個 PlantUML 代碼,而後通過調用 PlantUML 編譯器來生成圖片。最終,我們發現在不考慮准確性的情況下, 3000 個代碼中,大概只有 600 個代碼是可以被編譯器編譯的, 即可執行的代碼比例大概是 20%。對于剩下的 600 個數據,我們需要再次調用 GPT-3.5 API 來生成代碼。重複,直到所有生成的代碼都可以被編譯器編譯。

20% 的失敗率對于個人的感知太明顯了,而根據概率論的知識,我們可以通過多次嘗試來提升可執行率。諸如:

執行兩次。1 - 0.2 * 0.2 = 0.96

執行三次。1 - 0.2 * 0.2 * 0.2 = 0.992

執行四次。1 - 0.2 * 0.2 * 0.2 * 0.2 = 0.9984

考慮到成本以及生成式 AI 並沒有那麽聰明,所以我們選擇了執行兩次,即可執行率提升到 0.96。當然了,在一些高 ROI 的價值,大家可以考慮執行三次。

可執行單元校驗

可執行單元校驗是指通過對生成的代碼進行測試和驗證,確保其能夠被編譯器編譯和執行。可執行單元校驗旨在提高生成代碼的准確性和可執行性, 以確保生成的代碼單元符合預期並能夠被有效地使用。

在 AutoDev 中,對應有結合數據庫的 SQL、單元測試、功能代碼生成的功能,所以我們初步設計了以下的校驗機制:

單元測試語法(TODO):檢查生成的單元測試代碼是否符合語言語法規範,確保其能夠被編譯器正確編譯。

單元測試執行:執行生成的單元測試用例,對生成的代碼進行測試,確保其能夠被編譯器正確編譯並執行。

SQL 語法檢驗:根據不同的模型能力生成 SQL 語句,並處理由此産生的錯誤。

SQL schema 檢驗(TODO):結合連接的數據庫,對生成的 SQL 語句進行檢查,確保其符合數據庫的 schema 規範。

功能代碼生成檢驗(TODO):采用測試驅動的檢驗機制,對生成的代碼進行檢查,確保其符合開發需求並能夠被編譯器正確編譯。

前端代碼生成檢驗(TODO):對生成的前端代碼進行檢查,以確保 import、語法等正確。

考慮到單元測試是直接可執行的,因此在 AutoDev 我們是直接執行單元測試( RunService)的,只要 IDE 速度夠快,基本上是能快速檢驗的。通過上述的檢驗機制, 可以有效地提高生成代碼的准確性和可執行性,確保生成的代碼單元符合預期並能夠被有效地使用。

當然了,如果模型能力不夠強,那麽可能會帶來負面的體驗。

實現 AutoDev 的可執行單元校驗

根據上述的思想,我們可以打開看看 AutoDev 中對應功能的實現。

單元測試生成:執行單文件測試

由于,不同語言在對于測試的管理是有差異的,諸如于:

Python 會在 tests 目錄下創建一個 test_*.py 文件。

Java 會在 src/test/java 目錄下創建一個 *.java 文件。

Rust 直接在當前的 *.rs 裏有一個 mod tests。

JavaScript 就什麽奇奇怪怪的都有。

所以,在 AutoDev 中,我們創建了 AutoTestService 接口作爲不同語言的擴展點,以支持不同語言的單元測試執行。其次在執行上:

對于文件級別生成而言,只有在常見的 case 下,生成的單個測試類才能被執行。對于更複雜的測試,基本上就 GG(沒有測試過 GPT 4)。

對于函數級代碼生成而言,效果還是不錯的 —— 畢竟 AutoDev 擁有很強的上下文機制

當然從最終效果來說,在 Java 測試中,AI 生成的諸多 import 函數都是有問題的,對于接受率更差的其它語言來說,效果就更差了。

SQL 生成:獲取錯誤信息

我們在 AutoDev 中設計的 SQL 生成,主要是用來輔助我這種學過多種 SQL 變體,但是 SQL 反而寫得更差的人。其次,也只適用于項目中的 SQL 語句, 即沒有太多的複雜邏輯。

根據不同的模型能力,在 SQL 生成的可執行校驗設計上還是應該所區別的:

修複。即根據錯誤信息,嘗試修複。

重新生成。即重新生成 SQL 語句。

動態處理。尋找合適的阈值,以根據錯誤信息的數量,來決定是否重新生成。

由于是在 IDE 中,並且依賴于項目連接到數據庫,所以我們可以:

獲取所有的表名,以及表的字段信息。

對 SQL 語句進行語法檢查,以及 schema 檢查。

執行 SQL 語句,以確保其能夠正確執行。

如 AI 生成一個不可執行的 SQL,諸如于: SELECT * FROM table where id =;,在 IDE 中,進行語法檢查時,就會返回: Syntax error at position 30: <expression>, ALL, ANY or SOME expected, got ';' 的錯誤。因此,只需要使用 PsiElementVisitor 來遍曆 SQL 語句,然後進行語法檢查即可。最後,如果出現錯誤,就會直接作爲第三次對話,發送給模型。

順便一提,由于還沒有設計沙盒機制,當前並不會讓 AI 直接執行 SQL 語句,而是通過生成 SQL 語句,然後由開發者來執行。這個鍋,必須由開發者來背。

進一步改進和實踐

根據上述的內容,GPT 3.5 對我們進行了一些建議。

爲了進一步改進 AutoDev 的功能和實踐可執行單元校驗,我們可以采取以下措施:

持續優化算法和策略:借助用戶反饋和實際測試結果,不斷優化校驗算法和策略。這包括改進測試生成方法、錯誤處理策略以及代碼檢驗機制,以提高校驗效率和准確性。

增強並行處理能力:利用並行處理技術,同時對多個生成的代碼進行校驗,以加快校驗速度和提高效率。通過合理的並行處理策略,可以更有效地利用計算資源,加速校驗過程。

智能化的重試機制:設計智能的重試機制,針對無法通過初次校驗的代碼,自動進行多次嘗試修複或重新生成。通過分析校驗失敗的原因,動態調整重試策略,提高可執行率。

基于曆史數據的預測優化:利用曆史數據和模型分析,預測哪些類型的生成代碼更可能通過校驗,並優先進行校驗。通過建立預測模型,可以更有效地指導校驗過程,提高整體的校驗通過率。

持續學習和改進機制:建立持續學習和改進機制,不斷收集用戶反饋和校驗結果,進行數據分析和模型更新。通過持續的學習和改進,不斷優化校驗算法和策略,以適應不斷變化的開發需求和環境。

引入沙盒機制:爲了保障安全性,可以考慮引入沙盒機制,限制 AI 直接執行生成的代碼。通過沙盒機制,可以在一定程度上減少潛在的安全風險,確保開發者的數據和系統安全。

加強開發者教育和支持:爲開發者提供相關的教育培訓和技術支持,幫助他們更好地理解和使用 AutoDev 插件。通過培訓課程、文檔資料和技術支持平台,提升開發者的技能水平和使用體驗。

通過以上改進措施的實施和實踐,我們可以進一步提升 AutoDev 插件的功能和性能,提高生成代碼的准確性和可執行性,爲開發者提供更優質的開發體驗。

其它

事實上,我們在 AutoDev 中已經實現了一部分的功能,但是由于時間和精力有限,還有很多功能需要進一步完善和優化。我們將繼續努力,不斷改進和提升 AutoDev ,歡迎大家關注和支持我們的工作:https://github.com/unit-mesh/auto-dev

0 阅读:0

代碼爲聘禮

簡介:感謝大家的關注