【论文精读】Agent经典论文!秒解Github Issues?软件工程Agent全解析,为Agent打造专属电脑接口

Konten Video AsliPerluas Video

大家好欢迎大家来到由U2实验室打造的大咖讲AI直播间,我是Tristan。
今天为大家介绍的论文是由普林斯顿大学研究员提出的SWEAgent。
这篇论文为Agent设计了一种更方便理解和操作的电脑接口,取得了相比较单独电脑大猩猩模型或者RAG的方式去解决代码问题更好的效果,实现了瞄解GitHub Issues的功能。

  1. SWEAgent是一个开源的代码辅助编程软件。
  2. 通过在Framework层的一些创新,大幅提升了解决软件工程任务的效果。
  3. 论文也探讨了算法设计和数据集的重要性。
  4. 介绍了Agent的基本概念和如何构建有效的多Agent系统。
  5. ACI的设计理念对提高自动化软件工程的效率有着重要作用。

大家好,我是Tristan。今天论文精读给大家带来的是SWEAgent。那屏幕前的小伙伴不知道有多少使用过像Cursor、WinServe这类代码辅助编程软件。相信使用过的小伙伴一定会对于其中Agent可以自己定位问题、提出解决方案、执行代码解决问题的能力感到印象深刻。

那今天介绍的SWEAgent就是这类软件的一个开源实现。希望通过我们今天的论文精读,大家能够对于其中的算法原理有一个基本的了解,进而帮助大家更好地去设计或者使用这类软件。

好,我们首先来看标题,首先SWEAgent当中的SWE它是Software Engineering的一个缩写。那同时SWE也是一系列工作。在我们今天介绍的SWEAgent之前,还有一个工作叫做SWEBench。这是一个数据集类的工作,作者从GitHub当中大概收集了20多道Python相关的真实线上问题,构成了一个数据集,进而供大家去评估大猩猩模型或者是Agent在软件工程任务上的一个效果好坏。

在此之后就是我们今天要介绍的SWEAgent。它通过在Framework层的一些创新,大幅提升了大猩猩模型去解决这些软件工程任务的一个效果下限。在这篇工作之后,还有一个工作叫做SWEGym。这篇工作呢进一步地提出了一种新的训练方法以及数据构造方法,通过训练的方式再把效果的性能上限去做了进一步的提升。

那SWEAgent的这系列工作也是一个对于算法同学来说很好的参考。我们在解决一个问题的时候,首先要定位这个问题可以被什么样的数据集去比较好的评估,进而去选定数据集以及对应的metric。如果没有对应的一个好的数据集可用的话,我们可能就要去自己构造一个真正能够反映我们所关心问题效果好坏的这样一个场景。

在此之上,我们可以去循序渐进地做一些效果的不断改进或者方法的一个创新。这样的话大家的工作就会比较有传承性,同时也比较容易做出一个研究工作的影响力。

那说完了SWE,我们再来看Agent。首先Agent的概念大家应该都听得很多了。不管是平常听到的一个角色扮演Agent,或者是一个帮助订票的Agent,他们都是Agent。但是在学术领域呢,我们一般指的Agent会是一个狭义的设定。

在这个设定下我会有一个大猩猩模型,同时呢我会有一系列的工具。举例来说,我有一个比方说查询时间的工具叫做time;那同时呢我有一个查询天气的工具叫做weather。我可以把这些工具注册给大猩猩模型。那么当用户的一个query来了,比方说用户问几点了,那这个时候大猩猩模型能够意识到说:“哦,我要去和这个环境去做一个互动来查询一下真实的时间”。

那这个互动的方式就是通过注册给大猩猩模型的这些工具。在这里会去输出一个time,这个时候环境接收到了这样的一个模型输出,它就会去执行一个真正的工具调用。比方说os.time,获取到了我们的系统时间。这个时候环境把这样的一个信号,我们举例来说是12点,返回给大猩猩模型。大猩猩模型拿到了这个信息之后再去组织最终的回答,来告诉用户说:“OK,现在是12点,请问有什么我可以帮您的吗”。

这是最简单的单轮场景。我们这个场景也可能可以进一步地复杂。比方说用户进一步的追问:“上海今天的天气怎么样?”那大猩猩模型可以这个时候进一步的去调weather这个function来告诉环境我需要去查天气。环境去执行了真正的信息查询之后,进一步的把结果返回给大猩猩模型。

讲到这里,有些同学可能会想:“那我是不是如果自己要建一个Agent,我就不断地去堆这个工具列表就好?”那其实答案是不是的。如果我们不断地去在工具单一的Agent下比方说在这个场景里边,我们叫A1,不断地去增加它的工具列表的话,其实这个Agent很快就会出现上下文的超长或者是能力的过载。其实就和人一样,当你给它施加了太多的任务,它一定会爆炸掉的。

在这种场景下,我们就不太适合像左边这样子的一个single Agent的方式去实现。我们一般会怎么做呢?会把它去做一些任务的拆解。举例来说,我除了现在要查天气、要查时间以外,我可能还要去比方说订票,或者是查询一个hotel的信息。这个时候,我们一般会比较推荐使用一个multi Agent的框架,也就是分支,让不同的Agent负责一个不同的垂直领域去解决一个复杂场景的问题。

这个时候当用户问题进来了:“我现在想要去查一下上海人民广场附近最便宜的酒店是哪家?”这个时候假设说还是A1接受到了这样的一个请求,他会发现我不擅长去解决这个问题,他就会去做一个动作,我们一般叫做handoff。或者说大家可以简单理解为就是转交,让专业的人去解决专业的问题。

那AR拿到这个问题就会发现我可以查询酒店的信息,进而去完成多轮的交互,实现用户最终的一个诉求。我们今天讲到的SWEAgent的这边工作呢整体还是一个Single Agent的框架,后续针对一些类似MetaAgent等等的Multi Agent框架,我们也可以去抽时间再做进一步的讲解。

好,说完了论文的名称,我们再来看论文后续的标题,作者是说“Agent Computer Interfaces让自动化的软件工程成为可能。”这里边一个很核心的概念就是ACI。作者在后续的文章里边也是这样做一个简称ACI的概念。其实是来源于另外一个概念叫做HCI。

简单来说就是Human Computer Interfaces。HCI的概念可能大家还是会很陌生,但它的另外一个称呼我们是经常会听到的,叫做GUI,也就是用户图形界面。简单来说,我们日常用电脑不管是操作微信或者是操作一个PDF的编辑软件,它其实可以通过一些图形化的按钮让我们和真正的函数去实现交互,这就是GUI。

那它对应的另外一个概念呢,实际上是我们也会经常听到的API,也就是当我们去写代码或者是写一个软件工程的时候,会去调用的一个真实接口。GUI的话就是一个对人类更友好的一个图形界面。那顾名思义,这里的Agent Computer Interfaces和ACI呢,就是指的我需要设计一个面向Agent更友好的接口,这就是我们文章标题的整体含义。

好,介绍完了标题,我们来看作者。首先,论文发表的时候,作者都来自于普林斯顿大学。那第一行的四位作者的话也一起合著过很多文章,包括刚才说到的SWEBench或者是SWEGym以及webshop等等。有兴趣的同学呢也可以去做一些延伸的阅读。作者当中的第二行第一位姚舜宇大家应该很多人有听说过,因为他有两篇或者说很多篇比较有代表性的工作,其中react是我们目前做Agent设计很多场景下都会去用的一种planning的方式,那姚舜宇就是这篇工作的一座。

还有一篇工作叫做tree of thought,它通过数搜索的方式来用空间换效果得到了一个比较好的推理效果。Karsic的话是姚舜宇的导师,也是最早去做大模型的人物之一,他之前也参与了在OpenAI的GPT-1的一个训练,也是在这个领域里边比较早的去接触大模型的一个研究者。

作者的最后Offer Press之前也是参与过一个比较有名的大模型工作叫做Blue。那这个工作也是过去几年开源大模型里边比较有代表性的工作之一。整体可以看到整个的作者阵容还是非常豪华的。

说完了作者,我们来看摘要。那在家药里边,作者首先是说大猩猩模型已经在很多自动化的复杂场景里边被应用了。那就像人类呢也会用一些比较强有力的软件应用,比如说这个integrated development environment,这个东西大家说全称可能不太熟悉,但如果我们说它的简称的话可能一下子就会反应过来,其实就是IDE。

那作者是说人类呢会用IDE来去解决一些复杂的问题,我们会觉得LM的Agent其实也代表了一类新的终端用户叫做end user。他有自己的一个需求,同时也有一个特点的能力。如果说我们去给他去专门设计一些软件接口的话,那么他们一定也能够表现得更好。

为此呢我们就去探索了这个接口应该怎么去设计。这个interface design是怎么样去影响大元模型Agent在这类task上的表现的。进而我们去提出了SWE-Agent。SWE-Agent最主要的点呢就是提出了一个Agent Computer Interfaces(ACI)。这个ACI可以怎么样呢?可以帮助我去更好地来编辑代码文件以及在整个代码仓库里面更好地去做一个导览,同时能够去执行一些测试以及说其他的应用程序。

那最终呢,作者在SWEBench以及Human Evil Fix这两个数据集上去做了评估。SWEBench我们刚才有提到,整体是来源于大概12个Repositories,合计大概20道左右的一个题目,整体难度上来说还是非常高的。那Human Evil Fix实际上是Human Evil的一个子集,它大概有160道左右的题目,整体难度上会偏低一些。

我们也可以从作者提到的这个指标上来看到。首先,作者在MATRIX是选择了PATHET1。大家这里可以先简单理解为是任务的通过率,当然这里PATHETK实际上是有一个更复杂计算公式的,我们在后续可以做展开。那通过率在SWEBANCH上是做到了1.52,而在Human Evil Fix上是做到了87.7。这里12.5的指标呢是这边工作推出时的一个指标,后续的版本作者其实也做了一个进一步的提升。

同时,业界也有一些其他的工作不断去改进这里的一个效果,截止到今天这块的一个最新指标应该是能够达到大概50%左右的一个水平。所以大家可以看到整个业界的进展还是非常快的。

那作者又接着说这里呢他横向对比了其他的一些范式。有哪些呢?这里主要指代的是 non-iterative 的 LM,什么意思呢?也就是这里的 RAG 指代的是说当用户提出了一个代码问题,我可以去一个代码仓库里边检索相关的片段,把这个片段作为参考给到大猩猩模型来去做解答。那这一类我们就叫做一个 non-iterative 的大猩猩模型。

最终的话,作者也提供了一些 insight,有关怎么样去设计好一个 ACI 来去提升 Agent 去解决复杂软件工程任务的一表现。

接下来我们看文章的介绍部分。首先第一段是整篇文章的动机。作者在开头就说现在的 Arm Agent 在带有执行反馈的代码生成任务上,已经取得了不错的效果。这里有一个很核心的概念是 Execution Feedback,什么意思呢?我们先看一下传统 Chatbot 的大波形当中是怎么做一个 call 生成任务的。

那举例来说,我现在有一个 user,他可能提出了一个代码生成任务的请求比方说:“帮我写一个除法的函数。”当模型收到这个请求之后呢,自己就去做代码的生成。那这里边举例来说,模型就生成出一个除法的实现的一个函数。我要省略一下具体函数的内容,给到用户。

在整个的过程当中其实是非常的简短的,并且是单次交互就可以完成的。带有 execution feedback 的形式呢,它会多一步,也就是我会有一个 code interpreter,我们也叫做代码的编译器。在这种情况下,同样是用户去问:“我想要让你帮我生成一个除法的函数!”大猩猩模型首先生成的函数,它会给到一个代码的编译器。

编译器会先帮它去做一些检查,然后来看看有没有问题。如果有问题的话,会把一个信号返回给 LM。举例来说,某些过程当中的一些实现是有问题的,那 LM 就可以基于这样子的一个反馈去做下一轮的迭代生成,再给到我的一个代码解释器里。这个同样的代码解释器再去 check 看看这一次的回答有没有问题。

直到说我 CI 已经不去报错了,这个时候 LM 再把这个回答最终返回给用户。这样一种形式我们就叫做带有执行反馈的一个代码生成任务。

那紧接着作者又说,但是呢,Agent 去执行一些更复杂的代码任务,比方说软件工程的时候,现在还没有被很充分的探索。因为前边的这类 task,一般局限于一个单一的代码编程任务。但是我们的软件工程一般会有一个整个项目的概念,可能会面临更复杂的多文件的处理等等的一些复杂的难题。

那为了解决这些编程任务呢,LM 一般是会需要用一些现成的这些执行工具。这里边作者提到了 Linux Shell 以及说像刚才我们提到的一个 code interpreter,这里对应到 python 那就是一个 python 的解释器。

虽然是这样子,作者又提到说当我们人类去解决这些复杂的软件工程问题的时候,我们一般会用一些更加复杂的程序,比如说 VSCode。这些 VSCode 类的代码辅助编程软件一般都会有一些非常强大的工具以及插件来辅助我们去做更高效的代码编程。

进而做着受启发于人类和电脑的一个交互,也是我们前面有提到的 HCI,他就提到说我们想看看 LM Agent 能不能也能够从一个更好的接口设计里边去取得一个更好的编程效果。

这里边,作者是说一个 better design interfaces 我们对应的也就是下图里的这个部分。这个图里边,我们可以看它核心分三个环节。首先最左边的就是 Agent 自身,最右边的话是我们 Agent 可以去触达到的一些最原子的能力,这里统一的以一个 computer 来去做封装。

那 computer 里边会有什么呢?首先是有一系列的代码相关的程序相关的一个终端,我可以去执行比方说一个 cd 或者是一个 vim 的程序。同时,我会有对应的一个文件管理系统来告诉模型我现在整个 workspace 里边是有什么样子的文件存在的。

那介于中间的这个 Agent Computer Interface 其实就是去嫁接说我 Agent 到底应该看到一个什么样子的这个力度的接口。作者在这里边叫做 LM Friendly Commands,他表达的概念就是类似于我们 Terminal 里边人类去用的时候可能最原始的是一些 CD,或者说我要去编辑一行具体的这个文件的话我需要打开然后去跳转到某一行然后去启动编辑。

那这里边的话对于 Agent 是否说这些最原子能力是最好的,那可能不是的。这里边作者后边会去讲他们的实验的发现,这是一个环节。

另外一个环节就是作者提到说给到或者说我们的环境给到 Agent 的 feedback 它是否足够友好的。因为我们自己日常在去做代码编程的时候,经常会看到一些非常长的,例如报错的片段。

人类去看的时候,其实一般是会直接去定位对自己的 debug 最有帮助的那一个部分。但是如果我们原封不动的把这个错误信息给到 Agent 的话,它很有可能直接就充满了它的上下文长度,导致超长没有办法继续往下去做执行。

我们接着看,然后作者又花了一个段落的篇幅大概去讲了说我如果给到原子能力的话,到底会有什么样的问题,或者说我们这里叫做 Linux shell 的问题具体是什么。作者就举了一个例子,forexample,它是说我们现在的这个最原始的 Linux command 是没有给到 Agent 一个很基础的去编辑一个代码片段的这样一个工具的,同时呢也不能去给到一个很有效的一个编辑反馈。

这个问题就会导致说我的 Agent 在去执行这些代码任务的时候非常低效,同时也会大幅度的伤害我的模型效果。那紧接着作者又在下一个段落去提说 OK,那我应该怎么去解呢?这里边就抛出了一些基本的概念。

首先作者是说它的 ACI 的方法去 offer 了一些很基本很简单的 action 来去能够让模型不管是做查看或者是说做搜索,以及说去做文件的编辑。

同时呢,这个 ACI 的概念还会去配置了一些这个 guardrails,我们也叫比方说防护栏的手段去避免 agent 来犯一些很常见的或者是人类也会犯的这些错误,进而能够让 agent 去更高效地来做代码的一些修改以及编辑任务。

那再往下的话,作者基于上边提到的这些方法又去画一个段落的篇幅去介绍了消融的一些结果。首先整个消融实验是在 SWEBench Lite,我们叫做一个 SWE 子集的版本上去做了这个实验。

那这30个用例的子集是 SWEBench 里面相对难度要低一些的一个 task,也是帮助大家能够针对自己的一些算法设计或者是参数配置去做一些 tuning 来找到一个最合适的配置,作为自己最终的算法的一个设计。同时这里边作者也提到说自己的这个方法可以相比较 baseline 去解决更多的一个代码问题。

这里的 baseline 作者也提到说它指代的是直接用一个默认的 Linux shell,也就是我对原子的能力不去做任何的处理,直接喂给 agent 来用它达到的效果。

那最终的作者也提到说,虽然我的 ACI 也就是整个 agent 去使用电脑的中间接口是基于 GPT Turbo 的这样一个模型去做调试的,但呢他会发现我的整个设计如果迁移到 cloud 上的模型也是能够取得不错效果的。那潜台词就是我的这套方法是有分化性的,而并不是说只能 for 一个模型去使用。

在段落的最后呢,作者做了一个总结,这里边是说我们的贡献有两处。那首先呢,我们提出了一种新的接口形式来去帮助 agent 更好的去做电脑的操控;同时呢第二点是说我们构建了并且评估了同时现在也是开源了一个 SWEAgent 的整个项目。

这个项目不像之前的工作可能独立的去探索一些不管是工具的使用,或者是说一些prop 的调整,再或者是一些互动的代码执行的这种 setting,而是一个集大成者,把这些基本的优势元素都去整合了起来去构建成了最终的 ACI 的 framework。

那最后作者也说,我这样子的一个大语言模型为中心的互动的这些因素,对于说下游的任务表现都是有一个非常好的正向的帮助作用的。我们接着来看第二个章节。第二个章节的第一段呢,作者再一次的去引出了 ACI,当然这一段呢整体其实和前言的介绍部分是有一些重叠的,所以新增的信息量并不是很多。

那简单来说,其实也就是这张图。首先作者是说那对于人类来说,我可以去使用一些比较高级的复杂的这种 IDE,类似 VSCode 或者 PyCharm 等等的这些软件来去做更高效的代码编程。

那么对于 LM Agent 来说,他也应该有一个自己的类似 IDE 的东西,作者在这里面叫 ACI。那相当于是重申了一遍说 ACI 的一个必要性。那紧接着作者又去提到说我 Agent 和需要的一个最优的编辑器和人类需要的是有什么差异呢?

这里边作者有提到说大猩猩模型,它是不具备一个视觉的理解能力的。我们现在都知道有一些模型其实原生的多模态也能够做到和单模态相比较接近的一个效果了,所以这个能力项的缺失未必目前是一个必然的一个结论;其实还是有一些模型在多模态和单模态的兼容上是做得不错的。

但同时作者又提到说,对于人类来说,在使用这些 IDE 的时候,其实是可以有一个很好的不管是格式的检查,或者说是一些快速定位的工具来帮助用户能够更好地去找到自己的问题,以及修改对应的问题。同时这里边还提到说人类其实是可以非常灵活地去排除掉一些不必要的信息的。

我们在前面有提到说,写程序的时候,可能会很容易触发一些 error 的报警,但是人类一般是能够很精准地找到说哪几行是我所需要的信息,进而忽略到其他。但是对于大猩猩模型来说,它可能需要把整个的错误都给喂进去。那一旦一个问题的错误是非常长,比如说超过了64K或者128K,那可能现有的模型绝大部分的都无法去做进一步的 cover。

那这里边其实也提出了一个 agent 设计的理念里边非常关键的因素就是 context window 的 management。对于一个复杂的 agent 系统,我们一般都会面临着上下文到底如何做管理的这样一个挑战,可能不同的框架也会给出一个不同的设计。

OK,我们接着往下看,作者是从哪里去切入的呢?作者是说到最终他通过他认为一个更好的设计的 ACI 应该帮助大猩猩模型去更好的理解当前应用的一些状态,以及说之前做过的一些改动以及历史,去避免一些无关的 context 来进入到我当前轮的观察。

那最终来说的话,这里边作者提到说我的 ACI 实际上,它会第一在给什么指令到 agent 的时候会有一些设计,同时它也会去专门来看我的 environment 的状态,应该比方说提取哪些或者说给哪些给到模型,进而避免说很容易执行了两三轮可能整个长度就超长的一个问题。

那再进一步的话,作者是提到了说我是怎么做的。这里边的话也基本上就是整个段落末尾的两个关键点。首先也没别的这个更神奇的方法,我就是 manually 的去检查我 agent 到底哪些表现不好,那我就对症下药去解决对应的问题就好。

第二的话,也是用一个很暴力的手段,就是我去做一些 research 来看看一个最终的最佳配置会是什么样子的。所以也可以看到整个方法其实还是很 intuitive 的,很符合直觉,有什么问题解什么问题,也没有说一些非常灵感从天而降的这样一种状态。

OK,然后我们来看,最终作者也还给出了一些非常经验性的一些 insight,就是他通过这么多的实验最终得到的四点结论。那一个好的 ACI 应该是什么样子呢?首先第一点,就是应该做到足够的 simple,足够的 easy;然后对于 agent 来说不要去引入过多的不必要的一些无关信息。比方说作者这里边说现在很多这些 bash command 的文档包含了大量的这些 options。这块应该经常写代码的同学都会有这样的感触。

我们一般去安装一个新的软件包的时候,只要去比方说刚刚 help 的形式去看,那就会有一长列可能是超过一个屏幕的一些选项到。

这样子也是很容易给 agent 带来一些额外的不必要的困扰的,因为我们知道很常用的可能就是其中的一小部分。那第二的话,作者是提到说 action 应该是精简的同时是非常有效的。那这里边也很好理解,就是我们在执行一些原字化能力的时候,它虽然能够做到动作的最精准控制,但往往也会很繁琐。相信这也是很多同学比方说不太习惯用命令行方式去编程,可能更习惯一个 IDE 的形式。

来有一个更 high level 的封装,或者说是我们在做一些训练的时候,像有些很 low level 的框架,可能把这个操作非常细碎的给到我们,虽然是我们获得了更高的自主权,但也是带来了更高的一个学习成本。

那第三的话,是说环境的反馈应该是 informative 以及简洁的,既有效,同时又简洁。简单来说就是言简意赅,不要一些不必要的话,我们不要去过多的带给 agent 来带来困扰。

然后最后的话是说一些 guardrail,我们可以翻译为防护栏或者是一些检查措施,可以去避免整个误差的传播,以及能够去更好的从一些错误当中恢复出来。那这里边其实一般指代的也是说我给到 agent 的工具内部可以实现一些基本的检查。如果说发现我 agent 写的代码有问题,我应该及时把这个 feedback 告诉 agent,而不是说让 agent 自己去一点一点的排查。

那这样子可能原本一两轮就可以解决的事情,可能要拖到一二十轮,也不一定能够得到解决。OK,这四点就是作者最终给出的一个 Best Practice,就是最优的 AACI 的一个设计经验。其实我们仔细看的话会发现,它其实也很适用于对于人类设计的一个产品。就像我们知道 Apple 的创始人 Steve Jobs 之前会说一个很好的产品设计哲学是什么呢?Don't let me think。对,不要让我思考。对于 agent 来说也是,你不要让我过多的思考给我的工具,请做到足够的简单,足够的简洁,并且能够让我一步完成的事情,就不要去通过两步或更多的形式来完成。所以我们会发现 Agent 其实和人还是很像的,我们人类有偏好的东西,对于 agent 来说也是一样的。

好,我们接着来看第三个章节。前面介绍了说整个 SWEAgent 的一个设计理念。我们要去做一个更加 Agent Friendly 的接口,同时我们要去精简它的一个上下文等等。那具体来说,它是怎么做呢?首先作者是说那 ACI 包含几个核心的模块,包括像搜索啊等等的这些工具,我们下面会讲。

同时在每一个执行的 stamp 或者是每一步的过程当中,SWEAgent 它会生成一个 sort 以及一个 command 来去执行和环境的一个互动。这里边也是借鉴了 react 的这么一个设计形式。那什么是 react 呢?react 包括几个要素,它在每个执行的时候首先会去输出一个当前步骤的思考,同时去输出一个我这个 stamp 应该调用什么样子的工具。

那这个工具如果包含有一些入参的话,它还会带有一个 action 的 input。通过这三要素的话去完成一个完整的步骤。那 react 的形式有什么好处呢,其实是有两个点。第一个点的话是我可以通过在每一个步骤的开头强制让模型思考,其实间接的起到了一个 COT 的作用,能够让模型去做三思而后行,先想一想再去输出自己这一步到底要做什么。

那它的效果一定是会比直接输出一个 function 要更高的。那同时 react 的形式还会有第二个隐形的好处,就是我们知道有些模型在刚发布的时候是不一定支持标准的 function code,比方说像 deepseq 的 R1,那它其实刚发布的时候就只支持这种长思考以及正常的问答,是不能够去把它当作一个工具调用模型去使用的。但是如果说我们在 system prompt 里边让它以 react 形式输出,那这个时候,我们其实是可以借助到这些模型在文本上的输出能力,进而去转化为一个 function 的调用。

我们唯一要做的就是在后台层面去撰写一个对 react 格式的一个解析,这样子就可以实现一个曲线救国,间接的把一个非函数调用模型也来当做工具调用的去执行,这是总体的一个介绍。

接下来就是涉及到说我每个工具是怎么样去设计的。首先是搜索和定位,这里边包含了有三个工具。第一个是找到文件,第二个是搜索文件,第三是搜索目录。具体来说,我们也可以看一下作者给到的这个 figure10,那可以看到首先搜索文件的和我们平常 Linux 里边的一个执行范围的操作是类似的,它会快速的去查找某个文件,它的路径在哪里。

那第二个工具叫做 search directory,他会去搜索我整个文件夹里边包含有我所检索这个关键词的文件究竟有哪些。那第三个工具的话是在一个文件内,假如说我已经做了打开我想找到说某些关键词,它对应的行号是什么。比方说这里我会发现在第12行和第15行都包含有 agent 想要检索的信息,那我就把它返回回来。

可以看到这几个工具呢,相比较说我们最原始的 Linux 工具,它其实都做了一定的返回结果的精简,保留一些不必要的系统信息给丢掉,只保留最关键的、最不可减少的部分来给到 agent 去做后续的判断。

好,那这部分就是关于搜索和查询定位。这里边作者也提到一个细节点,假如说一个搜索超过了某一个前面说的数值,这里说的是50,那我们就不会再去把它的结果给展现出来,进而去建议说如果 agent 想要更多,那你就去发起一个更加精准的 query 的检索,而不要用一个很犯的比方一个阅述词不够,那你最好用两个阅述词或者等等的方式来去做限定。

接下来是一个文件的查看器,这里边最主要设计的一个工具是 open,同时呢这里边当我去打开一个文件的时候,最多只展示10行。然后 agent 可以去在这个打开的窗口内去做移动,通过 scroll down 或者是 scroll up 也就是类似我们鼠标的上滑和下滑的滚轮的形式来去做对应位置的调整。同时,我也可以做一个更精准的行号的定位,我可以用一个 goto 直接来指定一个 line number 去做快速的跳转。

这里边作者也通过这个 figure3 的 a 去展示了一个示例。当我打开了一个文件的时候,我只会去展示一个有限的行数,那在这个行可能之上或者之下的信息,如果有过多的信息的话,我会做一定的丢弃来保障我所展现信息的经典性。

OK,再往后的话会是一个文件的编辑器,这里边就是对应了这个 edit command。那这个 command 它包括三个主要的入参,也就是起始的行号、结束的行号,以及我想要替换的文本内容。那我们可以来看图三的 B,这里边就是假设说同样我打开的是向左边的文件,Agent 发现我要对这个文件做修改,他会怎么操作呢?

他会执行一个 edit 的命令,同时把我的起始行号给输入进来,以及结束行号给输入进来,对应的我要去替换的文本也在后边输入,这样就可以去完成在这部分代码片段的一个修改。这样子的话就可以以一种比较简洁的形式,只修改最必要的信息来完成一个最终的调整。

这里边作者又进一步地说到,就像这个人类在使用工具的时候也会用一些比如说格式的高亮来让他们关注到一些格式上的错误。作者呢也给我们的这个 edit 工具去集成了一个叫做 code interpreter 的东西,也就是代码纠错。这样子的话,他可以去告诉 agent,你写的代码可能会有什么样子的问题,进而让 agent 通过这样子的一个 feedback 能够去快速的做自己生成代码的调整,也就是给一个及时的反馈信号。

最终是作者介绍到了整个上下文的管理。这里边的核心其实就是针对我的 prop、我的错误信息、我的历史过程去保持尽可能的简洁。这样子的话会避免在 agent 这种很容易出现30轮、50轮以上的场景去这个导致的一个上下文的爆炸的问题。

那 agent 会接收一些指令文档,并且去展示一些合适的指令的使用方法。同时每一步呢会前面有说到去生成一个思考和动作的形式来完成。那同时这里边作者还提到说 agent 的环境呢他需要去展示电脑的一个输出,用一个图30这里的模板如果没有一个输出是被生成的话,那么具体的信息就会喂给 agent,告诉他说:“哎,你上一个指令成功运行了,但没有去得到任何的输出结果。”那也告诉模型说至少是你的这个动作是做了,但它可能并没有一个显示的输出。在有些动作下也是可以继续往后去做执行的。

那为了进一步去提升这个 context 的相关性,作者呢会说如果超过了最后的5轮以内的这个消息,比如说我的倒数第6轮、第7轮,那他统统都会以一行最简洁的信息做展示。这里边我们待会去跳转看一下这个 figure31 的一个展示,也就是通过整体这样的一个形式来实现我们的一个比较高效的上下文的管理。

接下来我们看一下这个 Figure30,也就是这里相当于首先我有一个 observation,那我同时呢当前是打开了某一个文件,以及说我目前所在的目录是什么样子的,会把这样的一个 workspace 的信息传递给我们的 agent。

同时如果刚才也有提到说,假设我整个环境报错了,那这个时候,或者说我们的 agent 输出是产生了一个错误,那他就会以这样的一个 error message 的模板去返回给 agent,同时让 agent 能够去主动的纠错。

好,以上就是我们的一个实验的设置。首先在数据集维度,主要是在 SWEBench 这个数据上去进行实验,包含了大概294个任务的实例。那些实例是来自12个不同的一些比较流行的 Python 的 repositories。同时,作者也在一个 SW Elite 上边去做了一些 oblation 和一些分析。

SWEBench Lite 是一个相对简单的子集,大概包含30个具体的案例。同时,作者也测试了 SWEAgent 的一个基础的代码编辑能力,使用的是 humanevil 这个数据集里边 fix 的一个子集。

在模型维度上,作者主要是分析了两个这个大猩猩模型,一个是 GPT-4 的 Turbo,另一个是 Cloud-3。那这个模型在去年论文发表的时候也是基本上能力最强的两个模型。同时呢,作者说也实验了很多一些开源的模型,包括 Lama3,然后以及 DeepSeek Coder,但是会发现说它们的表现整体来说还是不是很好。

那有些大猩猩模型主要是它的上下文长度太小了。比如说像 LAMA3 的这个 context window 只有8K,我们知道现在其实大猩猩模型基本上上下文长度128K已经是一个标配,但是在去年的时候其实还有很多模型都是一个8K的标准,所以也再次感慨整个大模型领域的进步的神速。

那这里边,提到像 GPT Turbo 还有 Cloud3 这种模型在去年的时候就已经有了128K和20K的一个 token 长度的上下文的支持。接下来的实验设置的 baseline,作者是对比了两类 baseline:

第一个 baseline 的话是一些非迭代式的,类似 RAG 的这样子的一种形式。在这个 setting 下,作者会用 BM25 的形式来做相关代码文件的检索,然后去找到和我当前 query 是比较有相关性的代码片段。基于这些片段,Agent 可以去生成一个能够解决特定任务的这样的 patch,我们叫补丁包。

第二种 setting 的话是一个使用 shell 的命令行的这样子一种形态。这种我们一般就称作一个迭代式。 但它的工具是没有专门打磨过的,可能是一个最基础的原子能力,那这种情况下,作者把它也当做了一个主要的比较对象。

那在选择的 Matrix 上来说,作者是主要汇报有大概多少的百分比是被解决了,或者我们叫 Parse 1。那这里边的计算方法是我所有的这些测试用例里边,如果把 Agent 去生成的这样一个 Patch 应用到对应的一个代码仓库里边,有多少的用例是成功通过了,是这样子一个指标。

同时,作者也汇报了一个平均的这个金额消耗,因为我们知道作者主要去测的其实是 GPT-4 Turbo 和 Cloud-3 这两个模型呢,其实在收费上来说都不算是最便宜的。如果让他们不加这个预算限制的去做的话,也很有可能会超过一个非常长的轮次,进而导致一个很高额的消费。

所以呢,作者也设定了一个 budget,对于我每一个测试用例,我最多不能超过四刀的这样子的一个金额。那也可以看到还是蛮贵的,大概和一个人类一个基础的学生或者是基础的程序员去解决一个问题的价格也并没有便宜到哪去。

那最终,作者提到说在整个设计 SWEAgent 的过程当中呢,他会去找一些手工挑的这些 case 来调整我整个框架或者说是工具的一个设计。对于剩下的这个部分,我差不多也就是我在前面的这些 case 调的差不多了,那剩下的 case 下,我会用一个搜索的方式来找到一个最合适的超参数,完成我最终的一个 SWE 的配置。

好,说完了实验的配置,我们来看最终的实验结果。前面两段的话摘要性总结了一些结论,我们直接来看对应的表格好了。首先是第一个表格,也是整个论文实验的主表。前面也提到了,作者在 SWEBench 还有一个 SWEBench Lite 的子集上分别做了实验。

那么我们可以看到作者提出的这个 SWEAgent 方法取得了一个最好的效果,那其中也对比了两个不同模型,当时看起来还是 GPT-4 Turbo 要比 Cloud-3 稍微好一点。

那在 SW Lite 上,作者也进行了对比,同样的也是取得了一个最优的效果。不过这里我们可以关注一下像是 Iterative 的这种 baseline,也就是我是有一个 shell 的这种工具返回结果作为 feedback 的,那给到模型,它总归是比像 RAG 这种 single path 的形式或者说 non-iterative 的方式效果还是要好不少的。

那这个主表呢,也是验证了作者提出的这样一个框架的优越性。我们再来看第二个 table,作者还在 humanevil 的一个数据集上去做了测试,那同样是得到了一个全方位最优的效果。接着呢,我们来看 Figure 4,这里边作者其实做了一个实验,就是我如果去提大,或者说增大 Path At K 里边的 K 值,也就是我对于每一个测试的实例,我可以让模型多测几次或者说多输出几次结果,那这个次数就是由 K 来控制。

我们可以看到当这个数值去提升的时候,其实最终模型的效果也是不断提升的一个表现,整个相差还是比较明显的,能够从百分之十几的一个数值直接提升到接近35%的一个水准。

那我们再回过来看,作者最终说的一些结论。第一个结论的话是说,人类的使用的接口有时候对于 agent 来说其实不是总是有效的。这里边作者也提到说像我们人类日常用的一些 shell command 提供最原始能力,如 cd、ls、cat,或者是像这种查找类的 grep 或者 find,它其实有时候会容易找到一些不相关的结果或者说是一些过度冗余的一个结果。

为此,作者也去进行了一些对比。我们来看 Figure 5,这里边作者去对比了三种形式。一种叫做 no search,那这种形态下是不给 agent 一个搜索的工具,它需要通过 LS 或者是 CD 的方式不断的自己去做文件夹之内的这些导航,直到你发现最终想要的结果。当然其实这个结果呢我们认为也有点过于简单了,因为原则来说我们即使执行 shell command 它其实也是具备一定的查找功能。

那第二种的话就是这种迭代式的搜索,前面提到的人类的一些工具并不适合 agent。举例来说,人类在使用的一种搜索方式,就是迭代, 比方说用一个 command F 的方式来搜索一个关键词,那我可能人类是一个一个地去做结果之间的跳转。而整体执行效率会相对比较低。

那作者也提到说这种效果的表现下可能也不适合 agent 这种可以理解更长上下文的一个形态。那第三种的话就是作者提出的一个带有总结性质的搜索,他会把搜索的结果去做一定的汇总,尽可能多的一次性喂给模型,同时又不会去引入过多的无关信息。

通过一些实验对比,也会发现这三种不同的方式里边,还是作者提出的这种 summarize 的搜索方式是最适合 agent 的。紧接着作者又说一个非常紧凑的有效的文件编辑,对于模型的效果也是非常关键的。这里边作者进一步的也是做了一些举例,他对比了几种 setting,关于你有没有一个 edit,以及不同的 edit 的形式。我们可以看 figure 6 的这个表格。

首先,没有 edit 的这种方式,它指代的是我假如说用一个 shared command, 比方说每一行的指令说我到底要插入什么样的信息的这种形式下,它叫做 no edit。第二种是 edit without linting,指的就是说我虽然允许你去做一个代码的编辑,但是呢如果你某一个代码片段写错了,我其实是并不会给你去做预警的。

最后一种的话就是作者在文章当中提到的,带有一个代码纠错能力的一个编辑器。当 agent 他自己输出的代码是有问题的时候,我的这个工具会返回一个明确的信号告诉你说你哪里写错了,这个时候 agent 就会去做一个反思,可以说那我现在应该去修复这个问题。

那这三种方式,作者也进行了一个效果的对比,同样的结论也是说我带有一个代码纠错的一个检查功能的编辑函数,它会是最有效的。接着往下看,最后作者也还是对于上一个结论的补充。就是如果你有一个护栏的话,它其实整体是对于相比较没有这种纠错的一个提醒表现的整体效果,会更高。

再之后,我们来看作者对于 agent 行为的一些分析。首先,作者提出的是说第一步 agent 都会倾向于先去复现或者是定位这个问题。我们可以看作者去统计出的这个 figure 7。在这里边,横轴是我们执行的一个轮次,越靠前的话就是越早的轮次。我比方说,我们看第一轮,一般来说 agent 去生成的主要执行行为这个颜色呢,就是 create。

作者在文章里边有解释,create 一般是 agent 看到了某一个代码仓库以及对应的 issue 之后,我会先去创建一个能够复现这个 issue 的问题,进而再去走后续的流程。当然,在这个过程当中,作者也提到说他会去使用比方说文件查找类的,也会去尝试看能不能去更快速地定位到这些信息。但我们从统计上来看,更多的还是使用 create 的这个形式。

紧接着,作者又说剩下的轮次呢,大部分都是一种 pattern。什么样子呢?叫做 edit then execute,也就是我出现了问题或者说我找到了问题,那我接下来就去做一定的修改,修改完就去执行。那这个过程不断的去重复,直到 agent 完成这个任务。这其实也是比较符合预期的,因为我们 agent 预期它核心的环节就是在迭代过程当中去修复错误的这样一个过程。

再接着,作者提出说,对于 agent 来说,现在做编辑依然是很有挑战的。我们这里边也可以看一下在这次测试里边大概会有一些多少的比例是294个 task 的实例里边,有185个,也就是超过一半的这些 case 都直接触发了一个格式错误。在这种情况下,如果你的工具能够对错误做一个及时的反馈的话,agent 就能得到一个及时的 feedback 去做修正。

不然的话,对于 agent 的反馈其实就很有限,很容易导致 agent 陷入到一个局部的困难当中,无法跳脱出来。再往下,作者提到说 agent 他们成功的很快,同时失败的很慢。这其实也是一个很符合直觉的就是,会做的同学一定是做很多题,都能够快速解决的,不会做的同学可能是或者说 agent,他持续很多步,可能直接到你设置的上线才会去停止下来。

这里边作者也做了一个统计,绝大部分 agent 成功的个 case,平均可能只需要12步,消耗的金额大概是1.2刀。我们前面有提到作者应该是设置的两刀还是四刀的一个金额,其实距离整个预值还是有一个比较大的空间。

但同时说呢,对于这些失败的 case,平均来说可能会长达21步,也就是他不断的去执行了一个纠错,然后修改,在这样子循环的过程,但最终可能也是 failed 的一个状态。再往下,作者提到说,对于大部分的失败 case,都是取源于一个不正确的实现。这里边我们也可以看一下作者去统计的一个更精细化的图,整个病状图是去分析了我所有错误 case 的一个归因。

这里边占比最大的,我们对应的就是这一条,一个并不正确的实现。那占比第二大的呢,叫做没有能够从 edit 当中恢复出来。什么意思呢?就是我可能做了一次编辑,但不管什么原因,可能是我代码写的问题还是报错了,那我不断的去做修复。修复,但最终还是 failed 的一个状态,触发了我的调用的金额的上限预值。

那占比第三的是一个相对一个 overlay specific implementation,大概指代的是说我时间不够,可能我要修改多处,但可能只修改了一个局部很小的细节。OK,以上部分就是我们的一个实验的结论。

最后,我们来看文章的末尾两个章节。这篇文章也是比较特殊,他把这个 related work 的部分放在了相对靠后的位置。可能一个更常见的位置我们一般会放在整篇文章的第二个 section,但这篇文章是放在了倒数第二个 section。作者的话是对比了两类的相关工作。

其中第一类是在软件工程领域的一个 benchmark,作者是首先对比了 code generation,也提出了说 code generation 的特点是什么。他们是很自洽的,并且具备一个很简短的一个问题描述,以及说对应的 solution 都是非常简单、简洁的。在这类 task 上呢,现在的一些比较好的方法,不管是模型还是模型结合一些工具,基本上是可以实现94.0%的一个效果,可以说整个榜单已经被接近于刷爆的状态。

但是,作者提出呢 code generation 的这种考察其实是不够的。那真正的软件工程问题其实会面临着一个更复杂的挑战。这里边作者也说到,它既涉及到模型的一个 reasoning 能力,同时呢也要去能够去定位软件工程当中的一系列问题,并且去指出一个相关的代码位置,定位不同的代码框文件之间的一个关系。整体来说其实是一个更复杂的这样子一个代码的处理环境。

在往后的,作者还去介绍了关于 LM model based 的一些 agent 的工作。这里边是回顾了一些不同的环境下,大家建设的这些 agent,举例来说可能有一个网页的交互,或者我可以让 agent 去操控不管是搜索引擎,或者是一个更复杂的浏览器的插件来执行购物或者订票的操作,以及说我可以让 agent 更加 high level 的去执行一个电脑的控制,去完善各种应用场景的一个功能实现。同时,在代码生成领域,也就是上面这个章节其实也提到有一些工作已经去做了一些工作的探索。

但是,作者在上面又提到,它们相对是比较孤立的,可能有些去探索我的 property 应该怎么设计,有些去探索说我加了一个这个代码的解释器,能不能带来收益等等。像当然我们今天的 SWEAgent 的这篇其实把这些都系统的整理了起来,来取得了一个更好的效果。

OK,那上边部分就是我们的相关工作。最后作者去做了一个摘要性的 discussion,这里边最核心的其实也就一句话,就是 ACI,它根据大元模型自己的一个优势点,然后来设计了一套更适合他们去使用、解决问题的接口,进而去弥补了他们的短板。

好,以上就是本次的论文分享。希望大家能够从本次的分享当中收获到一些对于 code agent 或者我们叫 software agent 的一些设计原理,未来也能够更好地去做相关算法的设计以及相关软件的使用。

好,再次感谢大家!拜拜,欢迎关注大咖讲 AI 了解更多 AI 资讯。