介绍 smolagents,一个构建智能体的简单库
今天我们发布了
smolagents
,这是一个非常简单的库,可为语言模型解锁智能体能力。以下是它的一些亮点:
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel())
agent.run("How many seconds would it take for a leopard at full speed to run through Pont des Arts?")

目录
🤔 什么是智能体?
任何高效使用 AI 的系统都需要为 LLM 提供对现实世界的某种访问权限:例如,调用搜索工具以获取外部信息,或对某些程序进行操作以解决任务的可能性。换句话说,LLM 应该拥有**代理能力**。智能体程序是 LLM 通往外部世界的门户。
AI 智能体是**LLM 输出控制工作流的程序**。
任何利用 LLM 的系统都会将 LLM 输出集成到代码中。LLM 输入对代码工作流的影响是 LLM 在系统中的代理能力水平。
请注意,根据此定义,“智能体”不是一个离散的 0 或 1 定义:相反,“代理能力”在一个连续的范围内演变,具体取决于您赋予 LLM 对工作流的权力大小。
下表说明了不同系统中代理能力的变化
代理能力等级 | 描述 | 名称 | 示例模式 |
---|---|---|---|
☆☆☆ | LLM 输出对程序流程无影响 | 简单处理器 | process_llm_output(llm_response) |
★☆☆ | LLM 输出决定基本控制流 | 路由器 | if llm_decision(): path_a() else: path_b() |
★★☆ | LLM 输出决定函数执行 | 工具调用 | run_function(llm_chosen_tool, llm_chosen_args) |
★★★ | LLM 输出控制迭代和程序继续 | 多步智能体 | while llm_should_continue(): execute_next_step() |
★★★ | 一个代理工作流可以启动另一个代理工作流 | 多智能体 | if llm_trigger(): execute_agent() |
多步智能体具有以下代码结构
memory = [user_defined_task]
while llm_should_continue(memory): # this loop is the multi-step part
action = llm_get_next_action(memory) # this is the tool-calling part
observations = execute_action(action)
memory += [action, observations]
因此,该系统在一个循环中运行,每一步执行一个新动作(该动作可能涉及调用一些预先确定的**工具**,这些工具只是函数),直到其观察结果表明已达到令人满意的状态以解决给定任务。以下是一个多步智能体如何解决一个简单数学问题的示例

✅ 何时使用智能体 / ⛔ 何时避免使用它们
当您需要 LLM 来确定应用程序的工作流时,智能体非常有用。但它们通常是杀鸡用牛刀。问题是:我是否真的需要工作流的灵活性才能有效地解决手头的任务?如果预定的工作流经常不足,则意味着您需要更大的灵活性。让我们举一个例子:假设您正在开发一个处理冲浪旅行网站客户请求的应用程序。
您可以提前知道请求将属于两个类别中的一个(基于用户选择),并且您为这两个类别中的每个类别都有预定义的工作流。
- 想了解旅行信息?⇒ 让他们使用搜索栏搜索您的知识库
- 想与销售人员交谈?⇒ 让他们填写联系表格。
如果这种确定性工作流适用于所有查询,那么请尽情编写所有代码!这将为您提供一个 100% 可靠的系统,没有任何由于让不可预测的 LLM 干预您的工作流而引入的错误风险。为了简单和健壮性,建议避免使用任何代理行为。
但是,如果工作流无法提前确定得那么好呢?
例如,用户想问:“我星期一可以来,但我忘了带护照,所以可能会延迟到星期三,星期二早上可以带我和我的东西去冲浪,并购买取消保险吗?”这个问题取决于许多因素,上面预先确定的任何标准可能都不足以满足此请求。
如果预定的工作流经常不足,则意味着您需要更大的灵活性。
这就是代理设置有帮助的地方。
在上面的例子中,您只需创建一个多步代理,它可以访问天气 API 以获取天气预报、Google Maps API 以计算旅行距离、员工可用性仪表板以及知识库上的 RAG 系统。
直到最近,计算机程序还局限于预设的工作流,试图通过堆积 if/else 开关来处理复杂性。它们专注于极其狭窄的任务,例如“计算这些数字的总和”或“找到此图中的最短路径”。但实际上,大多数现实生活中的任务,例如我们上面提到的旅行示例,都不适合预设的工作流。代理系统为程序打开了广阔的现实世界任务!
代码智能体
在多步智能体中,在每一步,LLM 都可以以调用外部工具的形式编写一个动作。一种常见的(Anthropic、OpenAI 和许多其他公司使用的)编写这些动作的格式通常是不同程度的“将动作编写为工具名称和要使用的参数的 JSON,然后您解析该 JSON 以了解要执行哪个工具以及使用哪个参数”。
多篇 研究 论文 表明,在代码中调用 LLM 工具效果更好。
其原因很简单,我们**专门设计了我们的代码语言,使其成为表达计算机执行操作的最佳方式**。如果 JSON 片段是更好的表达方式,那么 JSON 将是顶级的编程语言,而编程将是人间地狱。
下图摘自 可执行代码操作能激发更好的 LLM 智能体,说明了在代码中编写操作的一些优点

在代码中而不是 JSON 类似片段中编写操作提供了更好的
- **可组合性:** 您可以将 JSON 操作相互嵌套,或者定义一组 JSON 操作供以后重用,就像您可以定义一个 Python 函数一样吗?
- **对象管理:** 如何在 JSON 中存储
generate_image
等操作的输出? - **通用性:** 代码旨在简单地表达计算机可以做的任何事情。
- **LLM 训练数据中的表示:** 大量高质量的代码操作已包含在 LLM 的训练数据中,这意味着它们已经为此进行了训练!
介绍 smolagents:让智能体变得简单 🥳
我们构建 smolagents
的目标是
✨ **简单性**:智能体的逻辑代码只有约数千行(请参阅 此文件)。我们将抽象层保持在原始代码之上的最小形态!
🧑💻 **一流的代码智能体支持**,即编写代码动作的智能体(而不是“用于编写代码的智能体”)。为了确保安全,我们通过 E2B 支持在沙盒环境中执行。
- 除了
CodeAgent
类之外,我们仍然支持将动作作为 JSON/文本 blob 编写的标准ToolCallingAgent
。
🤗 **Hub 集成**:您可以将工具分享到 Hub 并从 Hub 加载工具,未来还会更多!
🌐 **支持任何 LLM**:它支持在 Hub 上以 transformers
版本加载或通过我们的推理 API 托管的模型,但也通过我们的 LiteLLM 集成支持来自 OpenAI、Anthropic 和许多其他公司的模型。
smolagents
是 transformers.agents
的继任者,未来将取代它,因为 transformers.agents
将被弃用。
构建智能体
要构建智能体,您至少需要两个元素
tools
:智能体可以访问的工具列表model
:将作为智能体引擎的 LLM。
对于 model
,您可以使用任何 LLM,无论是使用我们利用 Hugging Face 免费推理 API 的 HfApiModel
类的开放模型(如上面的豹子示例所示),还是可以使用 LiteLLMModel
来利用 litellm 并从 100 多个不同的云 LLM 中进行选择。
对于工具,您只需创建一个带有输入和输出类型提示的函数,以及提供输入描述的文档字符串,然后使用 @tool
装饰器将其转换为工具。
以下是如何创建一个从 Google 地图获取旅行时间的自定义工具,以及如何将其用于旅行规划智能体
from typing import Optional
from smolagents import CodeAgent, HfApiModel, tool
@tool
def get_travel_duration(start_location: str, destination_location: str, transportation_mode: Optional[str] = None) -> str:
"""Gets the travel time between two places.
Args:
start_location: the place from which you start your ride
destination_location: the place of arrival
transportation_mode: The transportation mode, in 'driving', 'walking', 'bicycling', or 'transit'. Defaults to 'driving'.
"""
import os # All imports are placed within the function, to allow for sharing to Hub.
import googlemaps
from datetime import datetime
gmaps = googlemaps.Client(os.getenv("GMAPS_API_KEY"))
if transportation_mode is None:
transportation_mode = "driving"
try:
directions_result = gmaps.directions(
start_location,
destination_location,
mode=transportation_mode,
departure_time=datetime(2025, 6, 6, 11, 0), # At 11, date far in the future
)
if len(directions_result) == 0:
return "No way found between these places with the required transportation mode."
return directions_result[0]["legs"][0]["duration"]["text"]
except Exception as e:
print(e)
return e
agent = CodeAgent(tools=[get_travel_duration], model=HfApiModel(), additional_authorized_imports=["datetime"])
agent.run("Can you give me a nice one-day trip around Paris with a few locations and the times? Could be in the city or outside, but should fit in one day. I'm travelling only with a rented bicycle.")
在收集旅行时间和运行计算后,智能体返回最终方案
One-day Paris bike trip itinerary:
1. Start at Eiffel Tower at 9:00 AM.
2. Sightseeing at Eiffel Tower until 10:30 AM.
3. Travel to Notre-Dame Cathedral at 10:46 AM.
4. Sightseeing at Notre-Dame Cathedral until 12:16 PM.
5. Travel to Montmartre at 12:41 PM.
6. Sightseeing at Montmartre until 2:11 PM.
7. Travel to Jardin du Luxembourg at 2:33 PM.
8. Sightseeing at Jardin du Luxembourg until 4:03 PM.
9. Travel to Louvre Museum at 4:12 PM.
10. Sightseeing at Louvre Museum until 5:42 PM.
11. Lunch break until 6:12 PM.
12. Planned end time: 6:12 PM.
构建工具后,将其分享到 Hub 就像这样简单
get_travel_duration.push_to_hub("{your_username}/get-travel-duration-tool")
您可以在 这个空间 下看到结果。您可以在 空间中的 tool.py 文件 下查看工具的逻辑。如您所见,该工具实际上被导出为一个继承自 Tool
类的类,这是我们所有工具的底层结构。
开放模型在智能体工作流中的能力如何?
我们创建了 CodeAgent
实例,并使用一些领先的模型,在 此基准测试 上进行了比较,该基准测试从几个不同的基准测试中收集问题,以提供各种挑战的混合。
在此处查找基准测试 以获取有关所用代理设置的更多详细信息,并查看代码代理与工具调用代理的比较(剧透:代码效果更好)。
这项比较表明,开源模型现在可以与最好的闭源模型媲美!