评估AI编程助手中的Solidity支持能力
AI代码助手(如GitHub Copilot、Continue.dev和Tabby)正显著提升软件开发效率。然而,这些工具对Solidity语言的支持普遍不足。为此,我们开展了以下工作:
- 为本地化、隐私保护的AI代码助手Tabby和Continue.dev添加Solidity支持
- 开发定制化代码补全评估框架CompChomper,用于评测不同模型在Solidity代码补全中的表现
我们还评估了截至2024年8月的主流代码模型在不同量化级别的表现,并与ChatGPT和Claude进行对比。结论是:本地模型在特定补全任务上优于甚至超越大型商业模型。
AI助手的改进
在Trail of Bits,我们既审计也编写大量Solidity代码,并积极采用各种提升效率的工具。一旦AI助手开始支持本地代码模型,我们立即着手评估其效果。遗憾的是,无论是工具还是模型层面,对Solidity的支持都相当欠缺——因此我们提交了一些改进请求。
我们为Continue.dev和Tabby添加了Solidity支持。这项工作还涉及向上游项目tree-sitter-wasm贡献Solidity支持,以惠及其他使用tree-sitter的开发工具。
我们乐于为其他AI代码助手添加支持;如有需求,请联系我们。
哪种模型最适合Solidity代码补全?
未被纳入基准测试的技术往往得不到关注,Solidity在大型语言代码模型中的处境正是如此。现有的代码评估基准几乎都不包含Solidity(即使包含22种语言的MultiPL也缺少Solidity)。可用数据集的质量也参差不齐;我们检查过一个开源训练集,其中包含大量扩展名为.sol的垃圾文件,而非真正的Solidity代码。
我们希望提升大型语言代码模型对Solidity的支持。但在改进之前,必须先进行测量。那么,主流代码模型在Solidity补全方面的表现如何(截至2024年8月)?
直接公布结论:我们测试的最佳商业模型是Anthropic的Claude 3 Opus,最佳本地模型则是参数量最大的DeepSeek Coder模型。对于某些代码补全任务,本地模型甚至优于大型商业模型。
我们还发现:
- 量化到4位的大型模型在代码补全上优于同类型的小型模型
- CodeLlama几乎肯定从未接受过Solidity训练
- 在Ollama中,CodeGemma对此特定用例的支持存在隐性问题
评估代码补全
编写一个好的评估非常困难,编写完美的评估几乎不可能。出于必要性和对LLM评估的深入理解,我们创建了自己的代码补全评估框架CompChomper。
CompChomper简化了在关注任务上评估LLM代码补全能力的过程。您可以指定用作数据集的git仓库和要测量的补全风格。CompChomper提供预处理、运行多个LLM(本地或通过Modal Labs云端)和评分的 infrastructure。尽管CompChomper仅针对Solidity代码进行过测试,但它基本与语言无关,可轻松用于测量其他编程语言的补全准确性。
更多关于CompChomper的技术细节,请参阅其源代码和文档。
测试内容
我们最初评估了流行的小型代码模型,但随着新模型不断出现,我们忍不住添加了DeepSeek Coder V2 Light和Mistral的Codestral。完整测试模型列表包括:
- CodeGemma 2B、7B(Google)
- CodeLlama 7B(Meta)
- Codestral 22B(Mistral)
- CodeQwen1.5 7B(Qwen Team,阿里巴巴集团)
- DeepSeek Coder V1.5 1.3B、6.7B(DeepSeek AI)
- DeepSeek Coder V2 Light(DeepSeek AI)
- Starcoder2 3B、7B(BigCode Project)
我们还评估了每个模型的多种变体。完整权重模型(16位浮点数)通过HuggingFace Transformers本地服务,以评估原始模型能力。GGUF格式的8位量化(Q8)和4位量化(Q4_K_M)版本由Ollama服务。这些模型是开发者实际可能使用的,测量不同量化水平有助于我们理解模型权重量化的影响。
为了形成良好基线,我们还评估了GPT-4o和GPT 3.5 Turbo(OpenAI)以及Claude 3 Opus、Claude 3 Sonnet和Claude 3.5 Sonnet(Anthropic)。
部分行补全结果
部分行补全基准测量模型完成部分代码行的准确性。使用场景包括输入函数调用时,希望模型自动填充正确参数。以下是部分行补全的视觉表示:假设您刚输入了require(,哪个模型会插入正确的代码?
|
|
图1:蓝色是提供给模型的前缀,绿色是模型应编写的未知文本,橙色是提供给模型的后缀。此处正确补全应为msg.sender == _ownerAddress);。
部分行补全结果中最有趣的发现是,许多本地代码模型在此任务上优于大型商业模型。这或许可以通过更好的提示工程改变(我们将发现更好提示的任务留给读者)。
图2:流行编程LLM的部分行补全结果。在此测试中,本地模型表现显著优于大型商业产品,前几名由DeepSeek Coder衍生物主导。我们测试的本地模型专门针对代码补全训练,而大型商业模型则针对指令跟随训练。(最高分=98)
整行补全
整行补全基准测量模型在给定前一行和下一行的情况下完成整行代码的准确性。使用场景包括输入函数名称后,希望LLM填充函数体。这种基准常用来测试代码模型的"中间填充"能力,因为完整的前后行上下文缓解了使代码补全评估困难的白空格问题。以下是此任务的视觉表示。
|
|
图3:蓝色是提供给模型的前缀,绿色是模型应编写的未知文本,橙色是提供给模型的后缀。此处正确补全应为:require(msg.sender == _ownerAddress);。
大型模型在此任务中领先,Claude3 Opus以微弱优势击败ChatGPT 4o。然而,最佳本地模型与最佳托管商业产品非常接近。本地模型的能力差异很大;其中,DeepSeek衍生物占据前列。
图4:流行编程LLM的整行补全结果。虽然商业模型略胜本地模型,但结果极为接近。(最高分=98)
我们的发现
总体而言,最佳本地模型和托管模型在Solidity代码补全方面表现相当不错,且并非所有模型都表现相同。我们还发现,对于此任务,模型大小比量化水平更重要,更大但更量化的模型几乎总是击败更小但量化更少的替代方案。
表现最佳的是DeepSeek coder的变体;最差的是CodeLlama变体(明显从未接受Solidity训练)和通过Ollama运行的CodeGemma(以这种方式运行时似乎存在某种灾难性故障)。
看到我们的结果后,可能会有人得出结论认为LLM可以生成优秀的Solidity代码。请不要这样做! 代码生成是与代码补全不同的任务。我们认为,除智能自动补全外,将AI辅助用于任何其他用途仍然存在严重风险。如前所述,LLM中的Solidity支持往往是事后才考虑的,且训练数据匮乏(与Python等语言相比)。尚未创建过的模式或结构还无法由LLM可靠生成。这不是假设性问题;我们在审计过程中遇到过AI生成代码中的错误。
一如既往,即使对于人工编写的代码, rigorous testing、验证和第三方审计也是不可替代的。
下一步计划
现在我们既有一套适当的评估方法,也有性能基线,我们将对这些模型进行微调,以提升它们在Solidity上的表现!这个过程已经在进行中;一旦微调完成,我们将立即向大家更新经过Solidity语言微调的模型。
如果您喜欢这篇文章,请分享至: Twitter | LinkedIn | GitHub | Mastodon | Hacker News