如何打造属于你自己的AI软件工程师(像Devin一样)
打造自己的AI软件工程师并非遥不可及
AI软件工程师的概念并非天方夜谭。事实上,已经有多种技术正在逐步降低软件工程的门槛:
- Devin:去年推出的全球首个AI软件工程师,引起业界广泛关注
- Cursor:作为VS Code的替代品,因其集成AI功能而日益流行,大幅提升项目开发效率
- Claude和GPT-4等大语言模型:能够帮助编写代码并修复bug,提供即时技术支持
随着大语言模型推理能力研究的不断深入,软件开发只会变得越来越简单高效。
AI软件工程师与普通大语言模型的区别
普通大语言模型也能编写代码,那么AI软件工程师与之有何不同?
为了更精确地理解两者差异,我们需要明确定义:
AI软件工程师是一种能够查看git仓库中的多个代码文件,并根据具体任务确定需要修改哪些文件的AI助手。
举个例子,假设你正在开发一个AI项目,发现当用户选择Mistral模型时,AI助手无法正常加载。
作为软件工程师,你需要找到含有bug的文件并修复它。(图片来源:作者)
作为软件工程师,你首先需要确定哪个代码文件需要修改以修复这个bug。例如,你可以检查模型加载的文件,看看问题是否出在那里。如果涉及的变量或函数是从其他文件导入的,你还需要检查这些相关文件,寻找bug的可能来源。
普通大语言模型无法解决这类问题,因为我们无法在提问时将所有文件都输入到模型中。我们通常需要自己找到相关文件,然后将其传给大语言模型,请求修复bug。
我请求Claude修复特定代码文件中的bug。(图片来源:作者)
那么,AI软件工程师究竟是什么?
AI软件工程师,就像真实世界的软件工程师一样,通过递增式PR(拉取请求)来修复代码的某些方面。例如,如果我们想创建一个具有增强推理能力的AI助手,第一个PR可能涉及设置AI助手,第二个可能涉及设置训练工作流,依此类推。
每个PR都是扩展代码库的提交。(图片来源:作者)
AI助手需要按顺序为这些PR编写代码,可自主完成或由用户引导。
AI软件工程师执行用户/老板提供的任务的流程。(图片来源:作者)
如何创建AI软件工程师(SWE)?
随着最近DeepSeek模型的发布,你可能好奇大语言模型是否可以通过强化学习(RL)提升软件工程能力。我最近写了一篇关于强化学习技术多功能性的博客,如果你还没看过,强烈推荐阅读。
DeepSeek-R1之后,大量研究宝藏等待发掘。 DeepSeek的强化学习理念比你想象的更具变革性。 ai.gopubby.com
强化学习之所以如此通用,是因为大语言模型能够自主开发解决问题的能力,无需明确指导。
我们能否将同样的方法应用于软件工程任务?
让我们首先定义任务。
任务目标
我们的目标是让AI助手能够根据代码仓库的当前状态和需要完成的任务,自动做出必要的代码修改,就像软件工程师一样。
如何训练AI成为软件工程师
要让AI实现上述功能,我们将使用与DeepSeek提升推理能力相同的强化学习训练流程。
强化学习是一种极具普适性的技术。这意味着在一个领域(如提升推理能力)应用它,可以同时提高在其他领域的表现。因此,DeepSeek用于提升推理能力的方法很可能也会提高其在我们任务上的表现。
但是,通过明确使用软件工程示例来教导它,我们能否取得更好的效果?
要实现这一点,我们首先需要收集数据来训练大语言模型。
数据收集
要训练大语言模型,我们需要收集能够教会它根据以下内容进行修改的数据:
- 代码的当前状态
- 需要修改的功能
从哪里获取这些信息?
Git拉取请求(PR)。
Git PR本质上是将一组更改从一个分支合并到另一个分支的提议。在使用GitHub进行项目开发时,你通常会对仓库进行修改,然后提交这些更改,并附上描述完成任务的提交信息。之后,你会拉取仓库的当前状态,并将你的更改合并到仓库中。
随着仓库顺序变更,我们可以看到状态随时间演变,直到AI助手发起PR。(图片来源:作者)
因此,一个拉取请求包含了我们所需的所有信息——仓库的先前状态、需要完成的任务以及为完成该任务所做的更改。
拉取请求(PR)中包含的所有信息。(图片来源:作者)
如果我们收集公共仓库中的数百万个拉取请求,应该能获得足够的信息,开始教导大语言模型如何根据待完成的任务和代码的旧状态来更改代码。
提示大语言模型
现在我们有了数据集,需要确定如何在训练过程或推理过程中提示大语言模型。
我们希望提供代码的旧状态和需要完成的任务(来自数据集),期望模型输出需要进行的更改。
但整个代码库无法完全上传,因此我们可能决定只提供两类文件:
- 提交前后发生变化的文件
- 未变化但相关的其他文件
考虑到helpers.py发生了变化,test_helpers.py可能被视为相关文件。(图片来源:作者)
我们可以使用大语言模型根据文件名确定未变化但相关的文件。这个想法是让大语言模型不仅知道哪些文件需要更改,还要知道哪些文件不应更改,因此将这一点纳入训练过程对其学习至关重要。
定义奖励函数
谈到具体的强化学习过程,我们如何定义奖励函数来激励大语言模型学习?
我们将以简单的方式定义奖励:量化大语言模型输出代码与PR中文件实际新状态之间的差异。两者越相似,奖励越高。
奖励由预测代码与期望代码输出之间的差异决定。(图片来源:作者)
训练流程
整体过程很简单:将每个数据点输入大语言模型,提取输出,将输出与期望的输出代码进行比较,并根据序列相似性提供奖励。大语言模型调整其策略以优化整体奖励。
如何进一步改进?
课程学习
研究表明,随着强化学习训练循环的进行,逐步增加问题难度有助于大语言模型更有效地学习,就像有助于学生更有效地学习一样。
随着训练的进行,我们向大语言模型展示难度递增的问题。(图片来源:作者)
目前,我们从GitHub的公共仓库中随机抽取PR,但我们可以根据提交的大小(即提交中所做更改的数量)对它们进行排序,假设涉及较少更改的提交比其他提交更容易推理。
或者,我们可以考虑另一种指标来判断每个PR中推理的难度,并按难度递增的顺序排列数据点。
更干净的数据集和奖励函数
数据集的清洁度是强化学习训练结束时提高大语言模型性能的主要瓶颈之一。DeepSeek和其他研究人员已经广泛证明了这一点。
-
数据集:这种方法的一个主要问题是数据本身的清洁度无法保证。理想情况下,我们希望所有PR都代表"良好的软件工程技能",但如果我们从互联网上的公共仓库获取所有PR,这显然是不可能的。
-
奖励函数:如果解决特定问题有多种方法怎么办?如果大语言模型的方法与代码中采用的方法不匹配,即使其方法实际上比仓库中采用的方法更好,大语言模型也会得到负面奖励。这是一个不良信号,无法正确引导大语言模型。
有没有办法改进奖励函数和数据集?如果你有任何想法,我很乐意在评论中看到。不过,暂时就到这里吧 :)
结论
AI软件工程师的概念并非遥不可及,而且很可能很快就会开源,从而为全球软件开发者提供便捷访问。
我们探讨了构建AI软件工程师的一种可能方法。这个过程本身可以通过各种方式变得更加高效。通过强化学习训练大语言模型仍然是一个新兴领域,有许多低垂的果实和巨大的研究潜力。我个人今年正在深入这个领域,如果你们中有人感兴趣,我也推荐你们一同探索。
致谢
本文受到提出SWE-RL方法的论文启发。我添加了一些关于如何进一步改进这一过程的观点。所有图表均由我在Canva上制作。