Agent 课程文档
构建使用代码的 Agent
并获得增强的文档体验
开始使用
构建使用代码的 Agent
代码 Agent 是 smolagents
中的默认 Agent 类型。它们生成 Python 工具调用来执行操作,从而实现高效、富有表现力且准确的动作表示。
它们简化的方法减少了所需操作的数量,简化了复杂的操作,并实现了现有代码函数的重用。smolagents
提供了一个轻量级框架,用于构建代码 Agent,大约用 1,000 行代码实现。
图表来自论文 可执行代码动作引发更好的 LLM Agent
为什么选择代码 Agent?
在多步骤 Agent 过程中,LLM 编写并执行操作,通常涉及外部工具调用。传统方法使用 JSON 格式将工具名称和参数指定为字符串,系统必须解析这些字符串以确定要执行哪个工具。
然而,研究表明,工具调用 LLM 使用代码直接操作时效果更佳。这是 smolagents
的核心原则,如上方图表所示,该图表来自 可执行代码动作引发更好的 LLM Agent。
用代码而不是 JSON 编写动作具有以下几个关键优势:
- 可组合性:轻松组合和重用动作
- 对象管理:直接处理图像等复杂结构
- 通用性:表达任何计算上可能的任务
- 对于 LLM 来说很自然:高质量代码已存在于 LLM 训练数据中
代码 Agent 如何工作?
上面的图表说明了 CodeAgent.run()
如何运行,它遵循我们在单元 1 中提到的 ReAct 框架。smolagents
中 Agent 的主要抽象是 MultiStepAgent
,它是核心构建块。CodeAgent
是一种特殊的 MultiStepAgent
,我们将在下面的示例中看到。
CodeAgent
通过一系列步骤循环执行动作,现有变量和知识被整合到 Agent 的上下文中,并保存在执行日志中
系统提示存储在
SystemPromptStep
中,用户查询记录在TaskStep
中。然后,执行以下 while 循环
2.1 方法
agent.write_memory_to_messages()
将 Agent 的日志写入 LLM 可读的 聊天消息列表。2.2 这些消息被发送到
Model
,后者生成一个补全。2.3 解析补全以提取动作,在我们的例子中,由于我们正在使用
CodeAgent
,因此应为代码片段。2.4 执行动作。
2.5 结果记录到
ActionStep
的内存中。
在每个步骤结束时,如果 Agent 包含任何函数调用(在 agent.step_callback
中),则会执行它们。
让我们看一些例子
阿尔弗雷德计划在韦恩家族的豪宅举办派对,需要您的帮助以确保一切顺利进行。为了帮助他,我们将应用我们所学的关于多步骤 CodeAgent
如何运作的知识。

如果您尚未安装 smolagents
,可以通过运行以下命令进行安装
pip install smolagents -U
让我们也登录 Hugging Face Hub 以访问 Serverless Inference API。
from huggingface_hub import login
login()
使用 smolagents 为派对选择播放列表
音乐是成功派对的重要组成部分!阿尔弗雷德需要一些帮助来选择播放列表。幸运的是,smolagents
为我们提供了解决方案!我们可以构建一个能够使用 DuckDuckGo 搜索网络的 Agent。为了让 Agent 访问此工具,我们在创建 Agent 时将其包含在工具列表中。

对于模型,我们将依赖 HfApiModel
,它提供对 Hugging Face 的 Serverless Inference API 的访问。默认模型是 "Qwen/Qwen2.5-Coder-32B-Instruct"
,它性能良好且可用于快速推理,但您可以从 Hub 中选择任何兼容的模型。
运行 Agent 非常简单
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel())
agent.run("Search for the best music recommendations for a party at the Wayne's mansion.")
当您运行此示例时,输出将显示正在执行的工作流程步骤的跟踪。它还将打印相应的 Python 代码以及消息
─ Executing parsed code: ────────────────────────────────────────────────────────────────────────────────────────
results = web_search(query="best music for a Batman party")
print(results)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
经过几个步骤后,您将看到生成的播放列表,阿尔弗雷德可以将其用于派对!🎵
使用自定义工具准备菜单

现在我们已经选择了播放列表,我们需要为客人安排菜单。同样,阿尔弗雷德可以利用 smolagents
来做到这一点。在这里,我们使用 @tool
装饰器来定义一个充当工具的自定义函数。我们稍后将更详细地介绍工具创建,因此现在,我们可以简单地运行代码。
正如您在下面的示例中看到的,我们将使用 @tool
装饰器创建一个工具,并将其包含在 tools
列表中。
from smolagents import CodeAgent, tool, HfApiModel
# Tool to suggest a menu based on the occasion
@tool
def suggest_menu(occasion: str) -> str:
"""
Suggests a menu based on the occasion.
Args:
occasion (str): The type of occasion for the party. Allowed values are:
- "casual": Menu for casual party.
- "formal": Menu for formal party.
- "superhero": Menu for superhero party.
- "custom": Custom menu.
"""
if occasion == "casual":
return "Pizza, snacks, and drinks."
elif occasion == "formal":
return "3-course dinner with wine and dessert."
elif occasion == "superhero":
return "Buffet with high-energy and healthy food."
else:
return "Custom menu for the butler."
# Alfred, the butler, preparing the menu for the party
agent = CodeAgent(tools=[suggest_menu], model=HfApiModel())
# Preparing the menu for the party
agent.run("Prepare a formal menu for the party.")
Agent 将运行几个步骤,直到找到答案。在文档字符串中精确允许的值有助于引导 Agent 找到存在的 occasion
参数值并限制幻觉。
菜单准备好了!🥗
在 Agent 内部使用 Python 导入
我们已经准备好了播放列表和菜单,但我们需要检查另一个关键细节:准备时间!
阿尔弗雷德需要计算如果他现在开始准备,一切何时就绪,以防他们需要其他超级英雄的帮助。
smolagents
专注于编写和执行 Python 代码片段的 Agent,为安全提供沙盒执行环境。
代码执行具有严格的安全措施 - 默认情况下,预定义安全列表之外的导入被阻止。但是,您可以通过在 additional_authorized_imports
中将它们作为字符串传递来授权其他导入。有关安全代码执行的更多详细信息,请参阅官方指南。
在创建 Agent 时,我们将使用 additional_authorized_imports
以允许导入 datetime
模块。
from smolagents import CodeAgent, HfApiModel
import numpy as np
import time
import datetime
agent = CodeAgent(tools=[], model=HfApiModel(), additional_authorized_imports=['datetime'])
agent.run(
"""
Alfred needs to prepare for the party. Here are the tasks:
1. Prepare the drinks - 30 minutes
2. Decorate the mansion - 60 minutes
3. Set up the menu - 45 minutes
4. Prepare the music and playlist - 45 minutes
If we start right now, at what time will the party be ready?
"""
)
这些示例仅仅是您可以使用代码 Agent 完成的工作的开始,我们已经开始看到它们在准备派对方面的实用性。您可以在 smolagents 文档中了解更多关于如何构建代码 Agent 的信息。
总而言之,smolagents
专注于编写和执行 Python 代码片段的 Agent,为安全提供沙盒执行环境。它支持本地和基于 API 的语言模型,使其能够适应各种开发环境。
将我们的自定义派对筹备 Agent 分享到 Hub
与社区分享我们自己的阿尔弗雷德 Agent 岂不是很棒吗?通过这样做,任何人都可以轻松地从 Hub 下载并使用该 Agent,将哥谭的终极派对策划者带到他们的指尖!让我们实现它!🎉
smolagents
库通过允许您与社区分享完整的 Agent 并下载其他 Agent 以供立即使用,从而使这成为可能。它就像以下代码一样简单
# Change to your username and repo name
agent.push_to_hub('sergiopaniego/AlfredAgent')
要再次下载 Agent,请使用以下代码
# Change to your username and repo name
alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True)
alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme")
同样令人兴奋的是,共享的 Agent 可以直接作为 Hugging Face Spaces 使用,允许您与它们进行实时交互。您可以在此处探索其他 Agent。
例如,AlfredAgent 在此处可用。您可以直接在下方试用它
您可能想知道——阿尔弗雷德是如何使用 smolagents
构建这样一个 Agent 的?通过集成多个工具,他可以按如下方式生成 Agent。现在不用担心工具,因为我们将在本单元后面的专门章节中详细探讨。
from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, HfApiModel, Tool, tool, VisitWebpageTool
@tool
def suggest_menu(occasion: str) -> str:
"""
Suggests a menu based on the occasion.
Args:
occasion: The type of occasion for the party.
"""
if occasion == "casual":
return "Pizza, snacks, and drinks."
elif occasion == "formal":
return "3-course dinner with wine and dessert."
elif occasion == "superhero":
return "Buffet with high-energy and healthy food."
else:
return "Custom menu for the butler."
@tool
def catering_service_tool(query: str) -> str:
"""
This tool returns the highest-rated catering service in Gotham City.
Args:
query: A search term for finding catering services.
"""
# Example list of catering services and their ratings
services = {
"Gotham Catering Co.": 4.9,
"Wayne Manor Catering": 4.8,
"Gotham City Events": 4.7,
}
# Find the highest rated catering service (simulating search query filtering)
best_service = max(services, key=services.get)
return best_service
class SuperheroPartyThemeTool(Tool):
name = "superhero_party_theme_generator"
description = """
This tool suggests creative superhero-themed party ideas based on a category.
It returns a unique party theme idea."""
inputs = {
"category": {
"type": "string",
"description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').",
}
}
output_type = "string"
def forward(self, category: str):
themes = {
"classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.",
"villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.",
"futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets."
}
return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.")
# Alfred, the butler, preparing the menu for the party
agent = CodeAgent(
tools=[
DuckDuckGoSearchTool(),
VisitWebpageTool(),
suggest_menu,
catering_service_tool,
SuperheroPartyThemeTool()
],
model=HfApiModel(),
max_steps=10,
verbosity_level=2
)
agent.run("Give me the best playlist for a party at the Wayne's mansion. The party idea is a 'villain masquerade' theme")
正如您所见,我们创建了一个 CodeAgent
,其中包含多个工具,这些工具增强了 Agent 的功能,使其成为可以与社区分享的终极派对策划者!🎉
现在,轮到您了:构建您自己的 Agent,并使用我们刚刚学到的知识与社区分享!🕵️♂️💡
使用 OpenTelemetry 和 Langfuse 检查我们的派对筹备 Agent 📡
随着阿尔弗雷德微调派对筹备 Agent,他越来越厌倦调试它的运行。Agent 本质上是不可预测的,并且难以检查。但由于他的目标是构建终极派对筹备 Agent 并将其部署到生产环境中,因此他需要强大的可追溯性,以便将来进行监控和分析。
smolagents
再次出手相救!它采用了 OpenTelemetry 标准来检测 Agent 运行,从而实现无缝检查和日志记录。借助 Langfuse 和 SmolagentsInstrumentor
,阿尔弗雷德可以轻松跟踪和分析他的 Agent 行为。
设置非常简单!
首先,我们需要安装必要的依赖项
pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents
接下来,阿尔弗雷德已经在 Langfuse 上创建了一个帐户,并准备好了他的 API 密钥。如果您尚未这样做,可以在此处注册 Langfuse Cloud,或者探索替代方案。
获得 API 密钥后,需要按如下方式正确配置它们
import os
import base64
LANGFUSE_PUBLIC_KEY="pk-lf-..."
LANGFUSE_SECRET_KEY="sk-lf-..."
LANGFUSE_AUTH=base64.b64encode(f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()).decode()
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://cloud.langfuse.com/api/public/otel" # EU data region
# os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://us.cloud.langfuse.com/api/public/otel" # US data region
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}"
最后,阿尔弗雷德准备好初始化 SmolagentsInstrumentor
并开始跟踪他的 Agent 性能。
from opentelemetry.sdk.trace import TracerProvider
from openinference.instrumentation.smolagents import SmolagentsInstrumentor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
trace_provider = TracerProvider()
trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter()))
SmolagentsInstrumentor().instrument(tracer_provider=trace_provider)
阿尔弗雷德现在已连接 🔌!来自 smolagents
的运行正在 Langfuse 中记录,使他可以完全了解 Agent 的行为。通过这种设置,他已准备好重新访问之前的运行并进一步改进他的派对筹备 Agent。
from smolagents import CodeAgent, HfApiModel
agent = CodeAgent(tools=[], model=HfApiModel())
alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True)
alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme")
阿尔弗雷德现在可以在此处访问这些日志以查看和分析它们。
与此同时,建议的播放列表为派对准备工作营造了完美氛围。很酷,对吧?🎶
现在我们已经创建了我们的第一个代码 Agent,让我们学习如何创建工具调用 Agent,这是 smolagents
中提供的第二种 Agent 类型。
资源
- smolagents 博客 - smolagents 和代码交互简介
- smolagents:构建优秀的 Agent - 可靠 Agent 的最佳实践
- 构建有效的 Agent - Anthropic - Agent 设计原则
- 使用 OpenTelemetry 共享运行 - 有关如何设置 OpenTelemetry 以跟踪您的 Agent 的详细信息。