DLAI-SmolAgent-代码智能体笔记-全-

DLAI SmolAgent 代码智能体笔记(全)

001:课程介绍 🚀

在本节课中,我们将学习如何利用Hugging Face的smolagents库来构建代码智能体。代码智能体是一种能够编写代码来执行一系列动作的智能系统。我们将了解其核心概念、优势以及整个课程的学习路径。

什么是代码智能体?🤖

上一段我们提到了本课程的主题。本节中,我们来看看代码智能体的具体定义。

代码智能体是一种能够编写代码来执行动作序列的智能体。这与编码智能体不同。编码智能体(例如在Winsurf或Cruser中的那些)为你编写代码,然后由你来执行。而代码智能体的核心思想是:让你的大语言模型(LM)为你的智能体编写代码

其核心优势在于,它允许你利用大语言模型的编码能力来编写执行动作的代码。相比于让大语言模型一个接一个地生成函数调用来完成复杂任务,代码智能体可以将所有这些调用整合到一段单一的代码中。

# 代码智能体的核心思想:整合多个步骤
# 传统方式:LM -> 生成步骤1 -> 执行 -> LM -> 生成步骤2 -> 执行 ...
# 代码智能体:LM -> 生成完整代码计划 -> 一次性高效执行

这意味着,你可以让大语言模型一次性规划出完整的行动方案,然后高效地执行,而不是强迫大语言模型一次只向你透露计划的一小步。这种方法被证明更高效,并能产生更可靠的结果。

课程内容概览 📚

了解了代码智能体的基本概念后,接下来我们预览一下本课程将涵盖的核心内容。

以下是本课程的五个主要章节:

  1. 第一课:托马斯·沃尔夫将简要介绍智能体的发展历史,带你了解当前的技术背景。
  2. 第二课:你将学习Hugging Face smolagents,并有机会亲自探索代码智能体的优势。我们还将回顾一些学术成果,展示这种方法带来的效率提升。
  3. 第三课:使用大语言模型生成的代码时,保护系统免受潜在不良影响至关重要。例如,代码可能存在语法错误,或执行可能损害系统的操作。在本课中,你将学习如何使用smolagents的受约束的Python解释器,以及如何在安全的沙箱中执行代码以确保安全。
  4. 第四课:你将看到如何追踪你的智能体,以便调试更复杂的场景。
  5. 第五课:你将学习并构建一个多智能体系统

致谢与支持 👏

最后,我们要感谢为此课程做出贡献的团队。许多人为创建这门课程付出了努力,特别感谢来自Hugging Face的Ike Ha和Albert V Lenova,以及来自DeepLearning.AI的Jeff Ladwig。此外,我们还获得了E2B公司的联合创始人兼CEO Basiklensky的帮助支持,该公司提供了本课程中使用的基于云的安全沙箱。


本节课中,我们一起学习了代码智能体的基本概念,它通过整合大语言模型的编码能力,将复杂任务规划为一段可执行的代码,从而提升效率和可靠性。我们还预览了整个课程的结构,从历史背景、工具使用、安全实践到调试和高级系统构建。在接下来的课程中,我们将深入这些主题,开始动手构建你自己的代码智能体。

002:智能体简史 🧠

在本节课中,我们将学习智能体的基本概念、其能力层级的演变历史,以及推动其发展的关键因素。这为后续深入探讨代码智能体奠定了重要基础。

什么是智能体?

首先,我们来探讨一个核心问题:什么是智能体?这个问题已被讨论数月甚至数年,虽然没有完美的定义,但我们找到的最严谨定义是:AI智能体是一种AI模型的输出会影响程序执行流程的程序

换句话说,大语言模型(LLM)被嵌入到计算机程序中,充当其“大脑”。LLM的决策会驱动这个“载体”朝着用户期望的目标前进。

然而,AI模型对执行流程的影响程度各不相同,“智能体化”并非一个非黑即白的概念。

智能体的能力层级 📊

智能体的能力可以分为多个层级。理解这些层级有助于我们把握其发展脉络。

以下是智能体从低到高的四个能力层级:

  • 第一级(最低层级):LLM的输出仅控制程序工作流中的一个决策点。
  • 第二级(更高层级):LLM可以调用外部工具。
  • 第三级(更高层级):智能体能够决定下一步行动、下一次迭代,甚至程序的停止条件。这被称为多步工作流
  • 第四级(最高层级):一个智能体工作流可以在元级别上创建或启动另一个智能体工作流。

这种能力层级的划分,也反映了自首批LLM发布以来,智能体能力的演进历程。智能体从简单的路由决策(决定程序走向哪个分支),发展到工具调用和多步智能体。

退一步看,我们能赋予LLM的最高层级能力,就是让它编写并执行代码。这正是我们所说的代码智能体,也是本短课程下一课将详细介绍的 smolagents 库的核心功能。

智能体性能的演进趋势 📈

智能体系统的性能与其底层LLM能力的提升浪潮紧密相连。随着通用LLM性能的增长,其规划能力也在增强,使其越来越适合驱动具有更长规划视野的多步智能体。

我们展示的图表是顶尖模型在Gaia基准测试上的得分演变。Gaia是由Hugging Face和Meta推出的基准测试,用于衡量智能体在广泛任务(使用计算机和互联网)上的性能。Gaia中的大多数任务,人类使用标准软件大约需要10分钟来解决。

预测AI系统的未来能力始终具有挑战性,但当我们根据Gaia的过往数据进行推断时,发现我们可能在2026年达到人类水平的表现。这意味着在未来12到18个月内,我们可能会拥有在大量任务上效率与人类相当的智能体系统,这些任务目前人类在计算机上完成大约需要10分钟。当然,前提是我们为它们提供了解决这些任务所需的所有工具。

智能体的发展趋势与协同效应 🤖

另一个值得关注的趋势是,随着LLM能力的增强,智能体越来越不依赖于特定的框架。它们能够越来越多地自主决定下一步该做什么,而无需特定的脚手架帮助或手工设计的框架。

例如,现在在许多情况下,你可以加载一个视觉语言模型,给它看一张屏幕截图,让它决定点击哪里或在键盘上输入什么,而无需过多指导。结果是,你获得了一个可以在许多用户界面上无缝操作,并能集成到广泛系统和智能体库中的智能体。

另一个有趣的协同效应出现在机器人领域。由于计算机工具和物理电子设备命令之间的API差异不大,多模态LLM的广泛能力意味着,就像我们的智能体能够根据截图决定做什么一样,控制机器人的LLM也可以越来越多地仅基于其摄像头获取的视频图像来决定下一步行动。越来越多的模型驱动AI智能体实际上是在计算机界面数据和物理世界数据的混合体上进行训练的。

如何训练智能体?🎯

最后,让我们简要谈谈如何训练智能体。直到最近,许多团队和公司还在推动对LLM进行特定的微调,即所谓的“函数调用微调”。这通常包括训练LLM调用一组在训练时给定的预定义工具。

虽然这种方法训练出的LLM能够以预期的格式和正确的参数编写工具调用,但像DeepSeek或Qwen这样的LLM现在已经足够强大,即使没有经过特定训练,仅通过提示词中的几个示例,也能编写工具调用。

在2025年初,智能体LLM面临的主要挑战仍然是在多步骤上进行规划和推理的能力。这正是强化学习和最近一波推理模型有望介入并改变游戏规则的地方。

我们预计,LLM的持续改进和针对智能体的特定训练方法的发展,将把智能体系统推向性能和可靠性的新高度,以至于我们将看到智能体系统在现实生活中的应用越来越多。因此,学习本课程是一个明智的决定。

003:代码智能体入门 🚀

在本节课中,我们将学习代码智能体的核心概念,了解它们与传统工具调用智能体的区别,并通过一个冰淇淋卡车采购的实战案例,演示如何使用Hugging Face的smolagents框架构建一个高效的代码智能体。


概述

Hugging Face开发了一个名为smolagents的智能体框架。smolagents是一个轻量级框架,抽象层级有限,易于使用。重要的是,在smolagents中,代码智能体被设计为一等公民。

代码智能体的核心思想

现在,我们来学习smolagents的核心思想。这种智能体用代码来编写它们的行动。为了理解原因,让我们先看看标准的ReAct循环。

这是目前大多数智能体的工作方式。它们遵循一个名为“ReAct”(思考与行动)的原则。因此,它们的行动遵循一个循环:思考 -> 行动 -> 观察行动对环境产生的结果,这个循环不断重复,直到完成用户给定的任务。

让我们举个例子。如果我让一个智能体告诉我斯坦福的天气。

  1. 智能体会先思考:它需要调用天气API。
  2. 然后行动:调用天气工具。
  3. 观察工具调用的结果:目前天气晴朗。
  4. 在第二步中,它会再次思考:现在需要返回答案了。它将行动,使用最终答案工具,返回天气晴朗。

但行动是如何发生的呢?这就是代码智能体与其他智能体的真正区别所在。

代码行动 vs. JSON/文本行动

如果我们放大第一步中采取的行动,以下是JSON或文本智能体的做法:

  • 它会先思考:我需要调用天气API。
  • 然后将其行动写成一个JSON字典,name键是工具名称,arguments是参数(例如“Stanford”)。

相比之下,代码智能体会将其行动写成如下代码片段:

weather_api(“Stanford”)

工具会被写成像是在调用一个Python函数。

在这个简单例子中,区别似乎不大。但现在你将看到它能带来多大的不同。

如果任务更复杂,比如从一系列国家中确定购买智能手机成本最低的国家,并且你需要为每个国家按顺序应用多个工具来获取最终价格。在代码中,这很简单:你只需编写一个Python代码片段,循环遍历所有国家,并为每个国家执行一系列链接在一起的操作,最后在同一个Python代码片段中返回最终答案。

相比之下,JSON或文本智能体将需要连续执行许多步骤(例如12步)才能达到相同的结果。但这是相同的结果吗?每一个新步骤都意味着更多的延迟、更高的成本和更多的出错机会。

为何选择代码?

将行动写成JSON或文本已成为事实上的标准,可能是因为这是实现智能体行为的最初尝试,毕竟写出JSON、解析它并执行字典中找到的工具非常简单。

但我们相信,现在需要用代码来执行智能体行动,不仅是因为我们刚刚说明的原因(在代码中链接或并行化操作更容易),还因为许多其他原因。例如,在代码中,你可以:

  • 为变量赋值以便后续重用。
  • 操作非文本元素。
  • 通过定义函数来构建自己的工具。

简而言之,代码是一种更强大的方式来描述计算机执行的操作,因为它就是为此而生的。如果JSON是更好的方式,你每天都会用JSON编码。但显然,没有人这样做。

上一张幻灯片的例子取自一篇优秀的论文,你应该阅读它。这篇论文还比较了代码行动和JSON行动的成功率以及所需的大语言模型调用次数,结果表明代码行动不仅更成功,而且更精简。这也是我们在smolagents中比较代码和JSON智能体时的经验。

实战案例:冰淇淋卡车采购

在接下来的课程中,我们将使用一个冰淇淋卡车的例子。假设你决定追求真正的热情,开始经营冰淇淋卡车生意。恭喜!这是一个很好的起点。你已经买了卡车和所有必需的设备,并估计每天能卖出30升冰淇淋。

现在,你每天早晨都需要获取生冰淇淋原料。你想比较不同批发供应商的每日送货选项。这就是我需要帮助你的地方。我将向你展示如何构建一个能够计算和比较所有选项总价格的智能体。

环境设置与数据导入

首先,我将设置环境,然后导入必要的数据。以下是不同的供应商。让我们计算哪个供应商实际上最便宜。我已经为你做好了计算作为参考。从这些计算来看,你能找到的最便宜的供应商是“Brainfreeze Brothers”。

构建代码智能体

现在,让我向你展示这些智能体。我首先定义它可以使用的工具。我使用smolagents中的@tool装饰器,它可以将任何配备了适当类型提示和文档字符串的函数转换为智能体可以使用的工具。要在一个函数上使用这个装饰器,你需要确保类型提示设置正确,并且函数文档字符串包含每个输入参数的描述。

每个新工具现在都拥有所有必需的属性,如名称和描述。这些将被智能体用来正确使用工具。

接着,我们初始化将用作智能体引擎的模型。这里,我使用通过Hugging Face Hub由Together AI提供的Qwen模型。我必须声明,我是Qwen模型的忠实粉丝,我认为它们在这方面做得非常出色。为了让这个模型工作,我们需要使用从Hub账户设置页面创建的、启用了推理提供商访问权限的令牌登录。

初始化智能体

现在让我们设置我们的智能体。CodeAgent是smolagents中主要的智能体类。它是一个多功能的智能体,在其代码中生成并执行Python代码片段。它也可以调用你提供给它的工具,在这里,它会像调用常规Python函数一样调用它们。

初始化你的智能体需要两个参数:modeltools。这里我还给了它额外的授权导入,让它能高效地运行计算和Pandas DataFrame。

单次工具调用示例

让我展示一下在代码中,一次简单的工具调用是什么样子。我给智能体一个只需要一次调用的简单任务。

你可以看到,原始模型输出包含一个代码片段,然后被我们的智能体提取并运行。在这个片段中,工具calculate_transport_costs就像调用一个标准的Python函数一样被调用。在打印第一步的输出进行检查后,智能体可以在第二步中直接返回答案。

执行核心任务

现在,我将给智能体它真正的任务:为你比较供应商成本。注意,给智能体详细的指令很重要,就像你对队友所做的那样。在这里,我给了它所有必要的信息,以及关于包含运输成本和可能关税的额外细节。

看起来代码智能体成功地解决了手头的任务,给出了正确的结果:Brainfreeze Brothers是最便宜的供应商,价格正确。

智能体如何工作?

智能体是如何做到这一点的?它只需要两步。

  1. 在第一步中,它生成了自己的Python函数来计算价格。这非常有趣,意味着这个函数将来可以随时被再次调用。基本上,智能体为自己创建了一个新工具,这是节省未来工作的好方法。然后它为自己显示结果以便检查。
  2. 在第二步中,检查结果后,它直接返回了它们。

代码智能体 vs. 传统工具调用智能体

这是一个代码智能体,但它与传统的工具调用格式相比如何?让我先展示它们的不同之处。

以下是一个代码智能体如何编写其输出来回答一个关于如何计算运输成本的简单问题。如你所见,是和上面相同类型的Python代码片段。

相反,一个传统的工具调用智能体会将其行动写成JSON块。思考过程可以完全相同,但行动的表述方式不同。在这个单次工具调用的例子中,没有哪种表述方式比另一种更自然。

但对于更复杂的任务,它会如何工作呢?smolagents也在名为ToolCallingAgent的类中实现了传统的工具调用。所以我现在将向你展示如何创建这样一个智能体。我给它和上面相同的模型以及相同的工具集。

现在,让我们让这个新智能体运行与上面完全相同的任务。

如你所见,这个智能体链接了许多单独的工具调用,因为它不能像我们的代码智能体那样使用for循环或使用不同变量来链接顺序操作。代码智能体用两步解决了任务,而这里,智能体运行了更多步骤,从而累积了令牌数、延迟和成本。每一个新步骤也是增加出错风险的额外机会。

智能体只能将其答案作为Markdown文本返回,因为它没有像我们的代码智能体那样返回DataFrame的能力。最后,由于每次计算都需要在文本中重新输入所有变量,而不是在代码中自然地处理它们,大语言模型必须正确记住它们并准确计算。结果,看起来大语言模型犯了一个错误,因为Brainfreeze Brothers的最终价格与我们上面建立的基准不符。

请注意,结果可能因人而异。例如,你可能有一个工具调用智能体第一次尝试就完美完成了任务。但我们经常看到这种失败模式发生。无论如何,运行时间要长得多,因为智能体总是必须进行这些多次单独的工具调用。

总结

在本节课中,我们一起学习了代码智能体的核心优势。我们通过一个冰淇淋卡车采购的案例,实战演示了如何使用smolagents框架构建CodeAgent。我们看到,与传统的ToolCallingAgent相比,CodeAgent能够通过编写和运行Python代码,用更少的步骤、更低的延迟和错误率完成复杂任务(如循环计算和数据处理)。代码提供了更强大、更自然的行动描述方式。

但你可能想知道这个代码智能体如何以安全的方式运行大语言模型生成的代码。这将是下一节课的内容。

004:安全代码执行 🔒

在本节课中,我们将探讨运行由大语言模型生成的代码时可能面临的安全风险,并学习如何使用smolagents框架内置的安全机制以及远程沙箱来保护你的系统。

概述

代码智能体执行LLM生成的Python代码会带来任意代码执行的风险,从而可能导致恶意攻击。这种风险源于多种途径,例如LLM的失误、供应链攻击或提示注入。恶意代码可能损害文件系统、窃取数据、滥用资源或安装后门。因此,确保代码执行环境的安全至关重要。本节将介绍smolagents提供的多层安全防护措施。

代码执行的风险来源

上一节我们介绍了代码智能体的基本概念,本节中我们来看看其潜在的安全风险。恶意代码可能通过以下几种方式在你的系统上执行:

  • LLM失误:大语言模型仍可能犯错,在尝试帮助你的过程中无意生成有害代码。虽然风险较低,但在大量运行中仍可能观察到此类尝试。
  • 供应链攻击:如果你运行一个恶意的LLM模型,它生成的代码会主动试图损害你的系统。在使用安全推理的知名模型时,此风险极低,但仍有可能发生。
  • 提示注入:一个浏览网页的智能体可能访问恶意网站,该网站包含有害指令,从而将攻击注入到智能体的记忆中。

一旦恶意代码得以执行,无论是意外还是故意,它都可能造成多种危害。以下是其主要攻击目标:

  • 损害你的文件系统。
  • 窃取数据。
  • 滥用资源,包括本地资源或API服务。
  • 危害你的网络。
  • 安装恶意软件或后门,用于后续攻击。

鉴于以上风险,我们必须尽可能确保代码执行环境的安全。

smolagents的内置安全层

现在,我们将了解如何利用smolagents提供的多种保护层来安全运行代码智能体。让我们从自定义的Python解释器开始,这是第一层安全防护。

在smolagents中,代码执行并非由标准的Python解释器完成。我们从头构建了一个更安全的本地Python执行器。具体来说,这个解释器通过加载代码的抽象语法树(AST)并按操作执行,同时确保始终遵循特定规则。

以下是其内置的安全规则:

  • 任何未定义的命令将被忽略。
  • 导入操作受到限制。
  • 无限循环被阻止。

让我们在实践中看看这些规则如何生效。首先,我们设置执行器,并创建一个包装器来优雅地只显示最终错误,而非整个堆栈跟踪。

以下是Python解释器中内置的安全防护措施:

1. 处理未定义命令
在Jupyter环境中,某些命令可以运行。然而,在这个自定义解释器中,由于我们是从头重写的,任何未实现的行为都会失败。你会看到系统抛出一个错误。

2. 限制导入操作
任何不在白名单内的导入都必须被明确授权才能执行。例如,尝试导入os模块并使用os.system来运行任意命令将会失败,因为默认情况下该导入不被允许。除非被显式添加到授权列表,否则导入操作是被禁止的。此外,即使某些看似无害的包(如random)可能提供访问危险包的途径,匹配一系列危险模式的包也不会被导入。例如,尝试从random模块访问os命令同样会引发错误。

3. 防止无限循环和资源膨胀
我们设置了基本操作处理总数的上限,以防止无限循环和资源滥用。当你运行一个无限循环时,命令开始执行,但一段时间后会因超出循环迭代次数的硬限制而抛出错误。

由于这些安全措施,该解释器相对更安全。在实际使用中,它已在多种用例中应用,且未观察到对环境造成损害。

然而,这个解决方案并非万无一失,因为没有任何本地沙箱是绝对安全的。可以想象,LLM仍可能找到执行恶意行为的方法来损害你的环境。例如,如果你允许导入像Pillow这样用于处理图像的无害包,LLM可能会生成数千张图像来塞满你的硬盘。代码逻辑可能是先导入被授权的Pillow包,然后设置一个不会触发迭代计数器的循环,每次循环都在你的系统中保存一张图像。

使用远程沙箱增强安全性

刚才的演示表明,即使有内置防护,自定义Python解释器也并非100%安全。实际上,任何在本地系统上运行的Python沙箱都仍存在风险。那么,如何进一步提高安全性呢?

保护LLM生成代码执行的最佳方式是使用安全的沙箱环境,更好的是使用不在你本地环境中的远程沙箱。你可以通过两种方式实现:

第一种方式是保留大部分代码在本地,仅在智能体生成代码片段后,将它们发送到远程沙箱执行。这种方式相当安全,我们将在notebook中演示。然而,如果你想运行多智能体系统,第一种方案会有限制。因为你的代码并未完全移植到沙箱中,远程代码执行器将无法调用管理型智能体,除非它拥有运行该智能体所需的所有代码和调用其底层LLM的API密钥。

第二种方式是将所有内容(代码、API密钥、工具)都导出到沙箱中。这将解锁多智能体系统,但迫使你导出可能敏感的API密钥以调用模型。

smolagents允许你使用本地Docker容器或E2B沙箱。在notebook中,我将展示如何实现第一种方案,即使用E2B。

实践:使用E2B沙箱运行代码智能体

现在,让我们使用E2B沙箱来运行一个代码智能体。我们首先传入E2B的API密钥。

然后,我们定义我们的智能体。这里我们将定义一个自定义的“访问网页”工具。我们没有使用smolagents提供的默认工具,目的是展示你可以轻松定义自定义工具并将其发送到E2B沙箱。你只需要定义工具,然后将其传递给智能体,并设置executor_type=E2B以及包含你E2B API密钥的executor_kwargs

运行时,智能体会自动在沙箱中初始化,并且工具已传输到服务器。这可能需要一些时间,因为沙箱需要启动。你可以看到所有必要的导入和安装都在服务器上执行。然后我们会收到一条消息,表明我们的智能体已准备就绪。

接着我们运行它。我们给智能体一个请求,该请求将利用我们刚刚定义的“访问网页”工具。经过一些确保工具正常工作的安装后,我们的智能体正常运行,但代码是在沙箱内部执行的。这展示了Hugging Face的GitHub页面,并显示了顶部的代码仓库。我们的智能体正确地返回了其中一个顶级仓库,即transformers

当然,你可以使用E2B构建更复杂的智能体。但请记住,正如我们在幻灯片中看到的,这是一种无法构建多智能体系统的解决方案。不过,单智能体系统通常足够强大,可以运行你所需的所有工作负载。如果你想切换到多智能体系统,可以将整个系统设置在沙箱上,但这需要一些自定义设置。

总结

本节课中,我们一起学习了代码智能体执行环境的安全风险与防护措施。我们首先分析了恶意代码执行的三种主要途径:LLM失误、供应链攻击和提示注入,及其可能造成的危害。接着,我们深入探讨了smolagents框架内置的安全层,包括其自定义Python解释器如何通过忽略未定义命令、限制导入和防止无限循环来提供基础保护。最后,我们认识到本地沙箱的局限性,并学习了如何使用E2B远程沙箱来显著提升安全性,包括其配置方法和适用场景。现在,你拥有了一个更安全的环境来运行你的智能体。在下一课中,我将向你展示如何在生产环境中监控你的智能体。

005:监控与评估你的智能体 🧠

在本节课中,我们将学习如何构建一个强大的智能体来处理客户请求流,并重点掌握如何记录和监控智能体的运行过程,以便评估其表现。

概述

上一节我们成功设置了冰淇淋车。随着业务传播,你开始接到越来越多的电话,包括希望跳过排队取冰淇淋的预订单,以及更复杂的请求,例如“我想开一家冰淇淋车,该怎么做?”。本节中,我们将构建一个智能体来分流处理这些请求,并学习如何记录智能体的运行过程以进行监控。

设置项目与追踪

首先,我们需要为项目命名。由于这是关于处理客户请求的,我们将其命名为 customer_success

接下来设置追踪功能。请注意,我们在此处使用了项目名称。在这个特定案例中,我们使用了一个自定义端点来重定向到正确的URL。如果你在本地运行,代码会更简单。

# 设置追踪的示例代码
project_name = "customer_success"
# ... 设置追踪的代码 ...

现在,检测功能已准备就绪。这意味着每当运行与smolagents相关的代码时,其记录都会被保存在追踪界面中。

设置智能体并查看追踪

现在,让我们设置smolagents。首先使用API密钥登录Hugging Face Hub。

然后,我们可以尝试显示一个非常简单的追踪记录,例如仅记录一个模型回答。

# 示例:记录一个简单的模型回答
from smolagents import record_model_call
answer = record_model_call(model, prompt)

运行后,我们得到了答案。接下来,我将展示如何查看这个追踪记录。

这是追踪界面的链接。点击后,你可以看到界面。在这里,你可以通过项目名称 customer_success 找到你的新项目。点击它,然后你就能看到显示的模型调用记录。它包含了延迟、令牌数量、输入和输出消息。

这个界面能高效地展示模型运行,但它也能展示智能体的运行。现在我将展示如何做到这一点。

让我们切换回笔记本。现在,我们将基于上述模型定义一个完整的智能体。我们赋予它相同的模型和一个空的工具列表。

# 定义一个简单的智能体
agent = Agent(model=model, tools=[])

让我们问它一个数学问题。

实际上,智能体一次性解决了这个问题。让我们看看它在界面中是什么样子。

我们回到追踪界面。从这里,我们可以回溯查看。

智能体运行记录显示在这里。

如你所见,智能体仅用一步就快速完成了任务。但有趣的部分在于,你有了一个层次化的结构:最顶层是智能体运行,在步骤内部,首先有一个模型调用(类似于我之前展示的),然后是一个工具调用。当你有多个步骤时,它们会在步骤层级上链接在一起。如果你有多个智能体,树状结构会扩展以显示所有不同的智能体运行。

为生产系统设置客户支持智能体

现在你已经学会了如何追踪智能体运行,我将展示如何为你的完整客户支持智能体设置生产系统。

你需要定义几个工具来帮助客户下单或获取价格信息。

以下是定义的工具示例:

# 定义工具示例
tools = [
    place_order_tool,
    get_prices_tool,
    # ... 其他工具
]

现在,你可以使用上述工具来设置最终的智能体,并用一个简单的订单进行测试运行。

# 设置并测试智能体
final_agent = Agent(model=model, tools=tools)
response = final_agent.run("我想预订一个巧克力冰淇淋。")

如你所见,智能体正确地使用了工具来下单。

使用数据集测试与评估

现在智能体已准备就绪,请求将源源不断地流入。我创建了一个包含虚假客户请求的小型数据集来测试智能体。

每个请求都是一个元组,左边是请求内容,右边是期望的工具调用(有时为None)。

现在,我们可以运行每个请求,智能体处理的所有过程都将被记录在我们上面定义的Phoenix平台中。

一旦所有请求处理完毕,你可以从Phoenix获取所有追踪记录,作为一个包含不同“跨度”(spans)的数据框。

让我们看看它的样子。如你所见,所有独立的跨度都被追踪了:最顶层是智能体运行,中间层是记录为链的不同步骤,更细粒度上,我们还记录了工具和LLM调用。

这个数据框会很大,尤其是当你有很多请求时。因此,我们需要进行一些处理,从中提取我们想要的信息。

这里,我们想检查的是每个请求之后是否跟随了适当的工具调用。例如,我们希望请求“你是如何开始冰淇淋生意的”后面没有工具调用。

让我们处理跨度数据框,为每个请求提取智能体调用的相应工具。

# 处理数据框以提取工具调用信息
# ... 数据处理代码 ...

这将使我们能够得到一个最终的结果数据框,并判断工具调用是否正确执行。

如你所见,有时工具调用正确,有时则不然。例如,问题“你是如何开始冰淇淋生意的”后面跟随了工具调用get_prices,这对于该请求是不合适的。

当然,对于你的生产系统,你还需要检查其他元素。例如,问题“卢浮宫现在的天气怎么样?”是我们无法用给定工具正确回答的。因此,这里没有调用任何工具,根据我们非常基本的评分标准(我们是否调用了正确的工具),这是正确的。

但如果你更仔细地检查答案,你会发现智能体在运行之前定义了一个模拟的天气API调用。这意味着给客户的回答是“幻觉”出来的:客户被告知天气晴朗,22摄氏度,而实际上智能体对此一无所知,因为它没有可用的信息。

这种行为是你希望通过更细粒度的评估来监控的,例如使用LLM作为评判员,根据请求和期望答案来评估智能体追踪记录。

当然,你自己的实现可能会根据你想要达到的结果而有所不同,但现在你已经掌握了构建它所需的所有工具。

总结

在本节课中,我们一起学习了:

  1. 如何为你的smolagents对象设置追踪功能。
  2. 如何追踪一次智能体运行。
  3. 如何最终获取追踪记录并对其评估,以检查你的智能体是否正常运行。

在下一课中,我将展示如何设置一个多智能体系统,以处理极其复杂的任务。

006:构建深度研究智能体 🧠

在本节课中,我们将学习如何构建一个深度研究智能体。这个智能体需要完成一个复杂的任务:找出世界上参观人数最多的前10个博物馆,并获取它们所在地在七月的平均气温,最终生成一份交互式报告。我们将从创建一个简单的智能体开始,逐步引入规划、多智能体协作和质量检查等高级概念,以构建一个更强大、更可靠的系统。

概述

上一节我们介绍了智能体的基本工作原理。本节中,我们将面对一个更复杂的现实任务。我们将构建一个能够进行深度网络研究、整合信息并生成可视化报告的智能体。这个过程将涉及创建专用工具、设置多智能体团队以及实施结果验证。

创建基础工具

首先,我们需要为智能体配备执行任务所需的工具。主要是搜索工具和网页访问工具。

以下是使用 smolagents 库创建这两种工具的示例代码。我们使用了两种不同的工具构造方式:函数装饰器和类定义。

from smolagents import tool
import duckduckgo_search

# 使用装饰器创建搜索工具
@tool
def search_web(query: str) -> str:
    """使用DuckDuckGo搜索网络并返回摘要。"""
    results = duckduckgo_search.ddg(query, max_results=5)
    return "\n".join([f"{r['title']}: {r['body']}" for r in results])

# 使用类定义创建网页访问工具
from smolagents import Tool

class VisitWebPage(Tool):
    name = "visit_webpage"
    description = "访问一个特定的URL并返回其文本内容。"
    inputs = {"url": {"type": "string", "description": "要访问的网页URL。"}}
    output_type = "string"

    def __call__(self, url: str):
        import requests
        from bs4 import BeautifulSoup
        response = requests.get(url)
        soup = BeautifulSoup(response.content, 'html.parser')
        return soup.get_text()

创建工具后,我们可以进行简单测试,例如搜索“冰淇淋的融化温度”,以确保工具工作正常。

设置基础智能体

有了工具,接下来我们设置一个基础的单智能体。首先需要指定使用的模型,例如 OpenAI 的 GPT-4。

from smolagents import CodeAgent
import os

os.environ['OPENAI_API_KEY'] = 'your-api-key-here'
model = "gpt-4"

# 创建基础智能体
simple_agent = CodeAgent(
    tools=[search_web, VisitWebPage()],
    model=model
)

然后,我们可以向这个智能体提出我们的核心请求:

“请给我一份2023年世界前10大博物馆的列表,包含它们的参观人数和七月的大致日平均气温。”

运行智能体后,我们可能会观察到一些典型问题。例如,智能体可能在执行操作时产生错误,或者返回的结果不完整(如只找到4个博物馆而非10个),数据也可能不精确(如气温被报告为整数)。这表明我们需要为智能体搭建更多“脚手架”来提升其表现。

构建多智能体团队

为了改进结果,我们将采用两个关键策略:设置规划间隔和使用多智能体结构。

  • 规划间隔:让智能体定期规划后续步骤,而不是盲目执行。
  • 多智能体结构:为不同的子任务分配专门的智能体。这有两个主要好处:
    1. 可以专门化每个智能体(通过工具或模型选择),使其在其核心任务上表现更好。
    2. 分离记忆可以减少每一步的输入令牌数量,从而降低延迟和成本。

对于我们的任务,我们将创建一个团队,包含一个专门负责网络搜索的智能体,并由一个经理智能体进行管理。

以下是创建专用网络搜索智能体的代码:

web_search_agent = CodeAgent(
    name="WebResearcher",
    description="一个专门负责从互联网搜索和提取信息的智能体。",
    tools=[search_web, VisitWebPage()],
    model=model
)

接下来,创建经理智能体。它需要更强的推理能力,因此我们为其配备规划能力和额外的绘图库导入权限,以便生成最终的可视化报告。

manager_agent = CodeAgent(
    name="Manager",
    description="管理研究任务并整合报告,能调用WebResearcher。",
    tools=[],  # 经理自身不直接使用搜索工具
    model=model,
    planning_interval=5,  # 每5步进行一次规划
    additional_imports=["pandas", "plotly.express", "geopy"]  # 授予绘图权限
)
# 注意:需要配置经理智能体能够调用 web_search_agent,这通常通过特定的多智能体协调类实现。

实施质量检查

为了确保最终结果的质量,我们引入一个验证步骤。使用一个多模态模型(例如,能分析图像的模型)来检查生成的报告地图是否满足了用户任务的所有要求。

def quality_check(final_map_image_path, original_query):
    """
    使用多模态模型检查生成的地图是否回答了原始问题。
    如果检查失败,则抛出异常,让智能体继续改进。
    """
    # 此处为伪代码,表示调用多模态模型API的过程
    # evaluation = multimodal_model.ask(f"Does this map show {original_query}?")
    if evaluation == "FAIL":
        raise Exception("质量检查未通过。报告需要包含前10个博物馆及其气温信息。")
    else:
        return "PASS"

运行与结果分析

当一切设置就绪,我们向经理智能体发出任务指令。运行过程会呈现清晰的步骤:

  1. 规划阶段:经理智能体首先制定计划,将大任务分解为小任务(如:1. 查找博物馆列表;2. 查找气温;3. 查找坐标;4. 生成地图)。
  2. 执行与协作:经理智能体将“查找博物馆列表”子任务委托给 WebResearcherWebResearcher 执行详细的网络搜索,并返回一份清晰的报告。这个过程可能很冗长,但正是专门化智能体的价值所在——它处理了所有网络细节,防止经理智能体的上下文被无关信息填满。
  3. 迭代收集:经理智能体收到博物馆列表后,继续委托 WebResearcher 查找这些地点的气温和地理坐标。
  4. 整合与可视化:经理智能体收集所有数据后,使用 plotly 库生成一个交互式地图,将博物馆、参观人数和气温信息标注在地理位置上。
  5. 质量验证:生成的地图被送入质量检查流程。多模态模型确认其符合要求后,最终报告才被返回给用户。

最终,我们获得了一份包含所需所有信息的交互式报告。通过访问智能体的内部状态,我们还可以提取并展示生成的地图。

# 访问并显示最终生成的地图
final_map = manager_agent.latest_state.get('final_plot')
display(final_map)

现在,你就可以根据这份报告,在世界顶级博物馆旁规划你的冰淇淋车生意了!

总结

本节课中我们一起学习了如何构建一个深度研究智能体。我们从创建一个基础的单智能体开始,发现了其在复杂任务中的局限性。为了克服这些限制,我们引入了规划间隔多智能体团队协作的结构,让专门的智能体处理专门的任务,并由一个经理智能体进行协调。最后,我们还加入了多模态质量检查步骤来确保输出结果的可靠性。通过这一完整的流程,我们构建了一个能够理解复杂指令、执行深度研究、整合多源信息并生成高质量可视化报告的强大智能体系统。

007:总结 🎉

在本节课中,我们将一起回顾整个课程的核心内容,总结使用Hugging Face smolagents库构建强大代码智能体的关键知识与技能。


恭喜你完成本课程。在本课程中,你学习了如何使用Hugging Face的smolagents库构建强大的代码智能体。

具体而言,你现在掌握了以下核心技能:

  • 安全运行LLM生成的代码:你学会了如何在一个受控、隔离的环境中执行由大型语言模型生成的代码,从而避免潜在的安全风险。
  • 监控与评估智能体:你了解了如何跟踪智能体的执行过程、分析其性能,并使用合适的指标对其进行评估。
  • 构建强大的多智能体系统:你探索了如何将多个智能体组合起来,让它们协同工作以解决更复杂的任务。

smolagents是一个开源库。欢迎你加入我们,共同让它变得更好。

你可以在GitHub上找到我们。😊


总结

本节课中,我们一起回顾了使用Hugging Face smolagents构建代码智能体的核心要点。我们总结了安全执行代码、监控评估智能体以及构建多智能体系统这三个关键模块。smolagents作为一个开源项目,期待你的参与和贡献。

posted @ 2026-03-26 08:12  绝不原创的飞龙  阅读(2)  评论(0)    收藏  举报