我们的 Transformers 代码代理击败 GAIA 基准!
摘要
经过一些实验,Transformers Agents在构建Agent系统方面的表现给我们留下了深刻印象,因此我们想看看它到底有多好!我们使用使用该库构建的代码Agent在GAIA基准测试中进行了测试,GAIA无疑是最困难、最全面的Agent基准测试……结果我们名列前茅!
本博客文章中使用的 `transformers.agents` 框架现已升级为独立库 smolagents!这两个库的API非常相似,因此切换很容易。请访问 此处 阅读 `smolagents` 介绍博客。
GAIA:Agent的严峻基准测试
什么是Agent?
一句话概括:Agent是任何基于大型语言模型(LLM)的系统,它可以根据当前用例的需求调用或不调用外部工具,并根据LLM的输出迭代执行后续步骤。工具可以包括从网络搜索API到Python解释器的任何内容。
用视觉类比来说:所有程序都可以被描述为图。先做A,再做B。if/else语句是图中的分支,但它们不改变图的结构。我们将**Agent**定义为LLM输出会改变图的结构的系统。Agent决定调用工具A或工具B,或者什么都不做;它决定是否再运行一步:这些都会改变图的结构。您可以将LLM集成到固定工作流中,例如在LLM judge中,但它不是Agent系统,因为LLM的输出不会改变图的结构。
以下是执行检索增强生成的两种不同系统的图示:一种是经典的,其图是固定的。另一种是Agent式的,图中的一个循环可以根据需要重复。
Agent系统赋予了大型语言模型超能力。欲了解更多详情,请阅读我们之前关于Transformers Agents 2.0发布的博客文章。
GAIA是Agent最全面的基准测试。GAIA中的问题非常困难,并突出了基于LLM的系统面临的一些困难。
这是一个棘手问题的例子
2008年画作“乌兹别克斯坦刺绣”中展示的水果,哪些曾出现在1949年10月为后来被用作电影“最后一次航行”浮动道具的远洋客轮提供的早餐菜单上?请以逗号分隔列表的形式给出这些水果,并根据它们在画作中从12点钟位置顺时针排列的顺序进行排序。请使用每种水果的复数形式。
你可以看到这个问题涉及到几个难点
- 以受限格式回答。
- 从图像中读取水果的多模态能力
- 需要收集几条信息,有些信息依赖于其他信息
- 图片中的水果
- 用作“最后一次航行”浮动道具的远洋客轮的身份
- 上述远洋客轮的1949年10月早餐菜单
- 上述要求正确的解决路径需要使用多个链式步骤。
解决这个问题既需要高层次的规划能力,也需要严谨的执行力,而这正是LLM难以应对的两个领域。
因此,它是Agent系统的一个极佳测试集!
在GAIA的公开排行榜上,GPT-4-Turbo的平均得分未达到7%。排名第一的提交(之前)是基于Autogen的解决方案,它采用复杂的多Agent系统,并利用OpenAI的工具调用函数,达到了40%。
让我们来挑战他们。🥊
构建合适的工具 🛠️
我们使用三种主要工具来解决GAIA问题
a. 网页浏览器
对于网页浏览,我们主要重用了Autogen团队提交中的Markdown网页浏览器。它包含一个存储当前浏览器状态的`Browser`类,以及几个用于网页导航的工具,如`visit_page`、`page_down`或`find_in_page`。这个工具返回当前视口的markdown表示。使用markdown大大压缩了网页信息,这可能会导致一些遗漏,与截图并使用视觉模型等其他解决方案相比。然而,我们发现该工具总体表现良好,且使用或编辑起来不会过于复杂。
注:我们认为将来改进此工具的好方法是使用selenium包而不是requests来加载页面。这将允许我们加载javascript(许多页面没有javascript无法正常加载)并接受cookie以访问某些页面。
b. 文件检查器
许多GAIA问题依赖于各种类型(如.xls、.mp3、.pdf等)的附件。这些文件需要正确解析。我们再次使用了Autogen的工具,因为它运行得非常好。
非常感谢Autogen团队开源了他们的工作。使用这些工具,我们的开发过程加快了几周!🤗
c. 代码解释器
我们不需要这个,因为我们的Agent天生就能生成并执行Python代码:详见下文。
代码Agent 🧑💻
为什么选择代码Agent?
正如Wang et al. (2024)所示,让Agent以代码形式表达其行为相比使用JSON等字典式输出具有多项优势。对我们而言,主要优势在于**代码是一种高度优化的方式,能够表达复杂的行为序列**。可以说,如果存在比我们当前编程语言更好、更严谨地表达详细行为的方式,那它早就成为一门新的编程语言了!
请看他们论文中给出的这个例子:

它突出了使用代码的几个优点
- 代码动作比JSON**更简洁**。
- 需要运行4个并行流,每个流包含5个连续动作?在JSON中,您需要生成20个JSON对象,每个都在其单独的步骤中;而在代码中,只需1个步骤。
- 平均而言,该论文显示代码操作所需的步骤比JSON少30%,这相当于生成的token也减少了30%。由于LLM调用通常是Agent系统的主要成本,这意味着您的Agent系统运行成本大约降低了30%。
- 代码能够重用通用库中的工具。
- 在基准测试中,使用代码能获得更好的性能,原因有二:
- 这是一种更直观的表达行为的方式
- LLM的训练数据中包含大量代码,这可能使它们在代码编写方面比JSON编写更流畅。
我们在agent_reasoning_benchmark的实验中证实了这些观点。
从我们最近构建transformers Agent的实验中,我们还观察到其他优点:
- 在代码中将元素存储为命名变量要容易得多。例如,需要存储工具生成的这张石头图片以供以后使用?
- 在代码中没问题:使用“rock_image = image_generation_tool(“一块石头的图片”)”将把变量存储在变量字典中名为“rock_image”的键下。之后,LLM可以通过再次引用“rock_image”在其任何代码块中使用其值。
- 在JSON中,你必须做一些复杂的变通来创建一个名称来存储这张图片,以便LLM以后知道如何再次访问它。例如,将图像生成工具的任何输出保存为“image_{i}.png”,并相信LLM以后会理解image_4.png是它在内存中前一个工具调用的输出?或者让LLM也输出一个“output_name”键来选择存储变量的名称,从而使你的动作JSON的结构复杂化?
- 代理日志的可读性大大提高。
Transformers Agents CodeAgent 的实现
大型语言模型(LLM)生成的代码直接执行起来可能非常不安全。如果你让LLM在没有防护措施的情况下编写和执行代码,它可能会产生幻觉:例如,你的所有个人文件都需要被《沙丘》传奇的副本擦除,或者你唱歌《冰雪奇缘》主题曲的音频需要分享到你的博客上!
因此,对于我们的Agent,我们必须确保代码执行安全。通常的方法是从上到下:“使用功能齐全的Python解释器,但禁止某些操作”。
为了更安全,我们更倾向于反其道而行之,**从头开始构建一个LLM安全的Python解释器**。给定LLM提供的Python代码块,我们的解释器从`ast` Python模块给出的代码的抽象语法树(AST)表示开始。它逐个执行树节点,遵循树结构,并在遇到任何未经明确授权的操作时停止。
例如,一个`import`语句将首先检查该导入是否明确地列在用户定义的`authorized_imports`列表中:如果不在,则不执行。我们包含一个默认的内置标准Python函数列表,其中包括`print`和`range`。除了用户明确授权的任何内容,都不会被执行。例如,`open`(如`with open("path.txt", "w") as file:`)是不允许的。
当遇到函数调用(`ast.Call`)时,如果函数名是用户定义的工具之一,则使用调用的参数调用该工具。如果是之前定义并允许的其他函数,则正常运行。
我们还进行了一些调整,以帮助LLM使用解释器:
- 我们限制了执行中的操作数量,以防止LLM生成代码中的问题导致的无限循环:每次操作,计数器都会递增,如果达到某个阈值,执行就会中断。
- 我们限制了打印输出中的行数,以避免用垃圾信息淹没LLM的上下文长度。例如,如果LLM读取了一个1M行的文本文件并决定打印每一行,那么在某个时候,这个输出将被截断,从而防止Agent的内存爆炸。
基本多Agent编排
网页浏览是一种上下文非常丰富的活动,但大多数检索到的上下文实际上是无用的。例如,在上面的GAIA问题中,唯一重要的信息是绘画“乌兹别克斯坦刺绣”的图片。围绕它的任何内容,比如我们找到它的博客内容,对于更广泛的任务解决通常是无用的。
为了解决这个问题,使用多Agent步骤是有意义的!例如,我们可以创建一个管理者Agent和一个网络搜索Agent。管理者Agent应解决更高层次的任务,并向网络搜索Agent分配特定的网络搜索任务。网络搜索Agent应仅返回其搜索的有用输出,这样管理者就不会被无用信息淹没。
我们正是在我们的工作流程中创建了这种多Agent编排
- 顶层Agent是一个ReactCodeAgent。它天生支持代码,因为其动作以Python形式编写和执行。它可以使用以下工具:
- `file_inspector` 用于读取文本文件,可选的 `question` 参数用于不返回文件的全部内容,而只返回其对特定问题的基于内容的答案。
- `visualizer`专门用于回答图像相关问题。
- `search_agent` 用于浏览网页。更具体地说,这个工具只是一个Web搜索Agent的封装,Web搜索Agent是一个JSON Agent(JSON对于严格顺序的任务仍然很好用,比如网页浏览中你向下滚动,然后导航到新页面等等)。这个Agent反过来又可以使用网页浏览工具。
信息网络搜索
向下翻页
在页面中查找
- …(完整列表在此行)
这种将Agent嵌入为工具是一种幼稚的多Agent编排方式,但我们想看看它能走多远——事实证明,它能走得相当远!
规划组件 🗺️
现在有各种各样的规划策略,我们选择了一个相对简单的预先规划工作流。每N步我们生成两样东西:
- 我们已知的事实总结,或者我们可以从上下文和需要发现的事实中推断出来
- 基于新的观察和上述事实摘要,解决任务的分步计划
参数N可以针对目标用例进行调整,以获得更好的性能:我们为管理器Agent选择了N=2,为网络搜索Agent选择了N=5。
一个有趣的发现是,如果我们不提供计划的先前版本作为输入,分数反而会上升。一个直观的解释是,大型语言模型(LLM)通常会强烈偏向于上下文中可用的任何相关信息。如果计划的先前版本存在于提示中,LLM很可能会大量重用它,而不是在需要时重新评估方法并重新生成计划。
事实摘要和计划都被用作生成下一步行动的额外上下文。规划鼓励LLM通过将所有达到目标的步骤和当前事务状态呈现在其面前,从而选择更好的执行路径。
结果 🏅
我们在验证集上取得了44.2%的成绩:这意味着Transformers Agent的ReactCodeAgent现在总体排名第一,比第二名高出4个百分点!**在测试集上,我们取得了33.3%的成绩,排名第二,领先于微软Autogen的提交,并且在难度最高的Level 3问题上获得了最佳平均分数。**

这是一个数据点,支持代码操作效果更好的观点。考虑到它们的效率,我们认为代码操作很快就会取代JSON/OAI格式,成为Agent编写其操作的标准。
据我们所知,LangChain和LlamaIndex目前不支持开箱即用的代码操作。微软的Autogen对代码操作有一些支持(在Docker容器中执行代码),但这似乎是JSON操作的辅助功能。因此,Transformers Agents是唯一将此格式作为核心的库!
下一步
希望您喜欢阅读这篇博客文章!工作才刚刚开始,我们将从以下几个方面继续改进Transformers Agents:
- LLM引擎:我们的提交是用GPT-4o(可惜)完成的,**没有经过任何微调**。我们的假设是,使用微调的开源模型可以消除解析错误,并提高一些分数!
- 多Agent编排:我们目前的编排方式比较简单,如果能实现更无缝的编排,我们可能会走得更远!
- 网络浏览器工具:使用`selenium`包,我们可以拥有一个能够通过cookie横幅并加载javascript的网页浏览器,从而使我们能够访问许多目前无法访问的页面。
- 进一步改进规划:我们正在对文献中的其他选项进行消融测试,以查看哪种方法效果最好。我们计划尝试现有组件的其他实现以及一些新组件。当我们有更多见解时,我们将发布更新!
在接下来的几个月里,请密切关注Transformers Agents!🚀
如果您有任何用例,请随时与我们联系。现在我们已经建立了Agent方面的内部专业知识,我们将很乐意提供帮助!🤝