工具

Agent 使用工具(Tool)执行各种各样的行动。在 smolagents 中,工具被视为 LLM 可以在 Agent 系统内部调用的函数

为与工具进行交互,需要为 LLM 提供包含以下关键组件的接口描述

比如,当在韦恩庄园准备派对时,Alfred 需要借助各种工具收集信息 - 从搜索餐饮服务到寻找派对主题创意。下面是搜索工具接口示例:

通过使用这些工具,Alfred 可以做出明智的决定,并且收集规划完美派对所需的所有信息。

该动画演示 smolagents 如何管理工具调用。


1. 工具创建方法

smolagents 中,可以通过 2 种方式创建 Agent:

1.1. @tool 装饰器

@tool 装饰器是定义简单工具的推荐方式。在底层,smolagents 从 Python 中解析函数的基本信息。因此,如果清晰地命名函数,同时编写良好的文档字符串,那么 LLM 可以更容易地使用该工具。

使用如下方式,定义函数:

1.1.1. 生成获取评分最高的餐饮服务的工具

假设 Alfred 已经确定派对菜单,但现在他需要帮助为客人准备食物。为此,他想要雇用一个餐饮服务,并且需要找出评分最高的选项。Alfred 可以利用工具搜索他所在地区的最好的餐饮服务。

以下是 Alfred 使用 @tool 装饰器实现该功能的示例:

from smolagents import CodeAgent, HfApiModel, tool

# Let's pretend we have a function that fetches the highest-rated catering services.
@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


agent = CodeAgent(tools=[catering_service_tool], model=HfApiModel())

# Run the agent to find the best catering service
result = agent.run(
    "Can you give me the name of the highest-rated catering service in Gotham City?"
)

print(result)   # Output: Gotham Catering Co.

1.2. 使用 Python 类定义工具

该方式涉及创建 Tool 的子类。可以将复杂工具实现为类,而非函数。该类使用元数据包装函数,这些元数据有助于 LLM 理解如何高效地使用该工具。在该类中,定义:

1.2.1. 生成用于生成超级英雄主题派对创意的工具

Alfred 在庄园举办的派对是超级英雄主题活动,他需要一些创意使该派对变得真正特别。作为出色的主人,他想用独特的主题给客人带来惊喜。
为此,他可以使用根据给定类别生成超级英雄主题派对创意的 Agent。通过这种方式,Alfred 可以找到完美的派对主题,使客人感到惊艳。

from smolagents import Tool, CodeAgent, HfApiModel

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'.")

# Instantiate the tool
party_theme_tool = SuperheroPartyThemeTool()
agent = CodeAgent(tools=[party_theme_tool], model=HfApiModel())

# Run the agent to generate a party theme idea
result = agent.run(
    "What would be a good superhero party idea for a 'villain masquerade' theme?"
)

print(result)  # Output: "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains."

2. 默认工具箱

smolagents 附带一系列可以直接注入到 Agent 中的预构建工具。默认工具箱包括:

Alfred 可以使用各种工具,确保韦恩庄园的派对完美无瑕:


3. 从 MCP 服务导入工具集

smolagents 支持从 MCP 服务导入工具。

可以在 ToolCollection 对象中加载 MCP 服务端工具,如下所示:

import os
from smolagents import ToolCollection, CodeAgent
from mcp import StdioServerParameters
from smolagents import HfApiModel


model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")


server_parameters = StdioServerParameters(
    command="uvx",
    args=["--quiet", "pubmedmcp@0.1.3"],
    env={"UV_PYTHON": "3.12", **os.environ},
)

with ToolCollection.from_mcp(server_parameters, trust_remote_code=True) as tool_collection:
    agent = CodeAgent(tools=[*tool_collection.tools], model=model, add_base_tools=True)
    agent.run("Please find a remedy for hangover.")