TellWorldAI 世界档案
问档案English

首页›实践›实践

实践

smolagents 多智能体系统

一个智能体要处理很多步时,速度会变慢,token 花费也会上升。本文用 smolagents 把任务拆给管理者智能体和网页搜索智能体,再给最终答案加一道检查。

这篇适合谁,读完能做到什么

如果你的 smolagents 智能体在步骤很多的任务上越来越慢、越来越贵,或者结果越来越不稳,可以试试把任务拆开。读完这篇,你应该能写出一个基线智能体,把网页调研拆成独立的托管智能体,让管理者智能体统一调度,并给最终答案加上检查。

为什么要用多个智能体

多智能体系统让各有专长的智能体共同完成复杂任务。和一个智能体包办所有事情相比,这种结构能提升模块化程度、可扩展性和稳健性[1]。任务会分配给能力不同的智能体,它们可以组合起来编写 Python 代码、调用外部工具、进行网页搜索等[1]。

一种典型的分工有三个角色:负责分派任务的管理者智能体,负责执行代码的代码解释器智能体,以及负责检索信息的网页搜索智能体[1]。多智能体 RAG 系统也是类似的思路,可以再加上浏览网页的 Web 智能体、从知识库检索的 Retriever 智能体,以及生成图像的图像生成智能体,全部由一个编排者统一管理[1]。

多智能体不等于越多越好。示例中只拆出了一个网页搜索智能体,由管理者统一调度[1]。

拆分的主要理由在于记忆。每个智能体各自保存记忆,能更专注于自己的核心任务。每一步输入的 token 变少,延迟和成本也随之降低[1]。

示例任务

示例要求找出全世界所有蝙蝠侠取景地,算出从哥谭用货机运过去要多久,并画一张按运输时间着色的地图。它还要求列出运输时间相同的一些超跑工厂[1]。这个任务需要网页搜索、读网页和地理计算,正好适合用来练习拆分工作。

准备

先安装示例用到的依赖。其中 litellm 这个 extra 提供模型连接,其余的包用于画图[1]:

pip install 'smolagents[litellm]' plotly geopandas shapely kaleido -q

示例使用 Together AI 作为模型提供方,它是 Hub 上可用的推理提供方之一[1]。

网页搜索使用 GoogleSearchTool,背后是 Serper API。设置环境变量 SERPAPI_API_KEY 并传入 provider="serpapi",或者设置 SERPER_API_KEY 并传入 provider=serper[1]。如果没有配置任何 Serp API 的密钥,可以改用 DuckDuckGoSearchTool,但它有速率限制[1]。

用下面的代码创建模型[1]:

import os
from PIL import Image
from smolagents import CodeAgent, GoogleSearchTool, InferenceClientModel, VisitWebpageTool

model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct", provider="together")

第一步:写一个运输时间工具

示例需要一个估算两点之间货机运输时间的工具。它用 @tool 声明,接收两个 (纬度, 经度) 元组,另外有一个默认为 750 km/h 的可选巡航速度参数[1]:

import math
from typing import Optional, Tuple

from smolagents import tool


@tool
def calculate_cargo_travel_time(
    origin_coords: Tuple[float, float],
    destination_coords: Tuple[float, float],
    cruising_speed_kmh: Optional[float] = 750.0,  # Average speed for cargo planes
) -> float:

函数先用 haversine 公式算出大圆距离,再为非直飞航线和空中交通管制多加 10%,并加上起飞和降落的一小时[1]。计算的最后部分如下[1]:

    # Add 10% to account for non-direct routes and air traffic controls
    actual_distance = distance * 1.1

    # Calculate flight time
    # Add 1 hour for takeoff and landing procedures
    flight_time = (actual_distance / cruising_speed_kmh) + 1.0

    # Format the results
    return round(flight_time, 2)

这里的 10% 和一小时是工具自己的估算参数,不是实测的飞行数据。结果只能当作粗略估计来用。

第二步:做一个单智能体基线

先用一个智能体,配上搜索、读网页和运输时间三个工具,得到一份基线报告。示例放行了 pandas 导入,并允许 20 步[1]:

agent = CodeAgent(
    model=model,
    tools=[GoogleSearchTool("serper"), VisitWebpageTool(), calculate_cargo_travel_time],
    additional_authorized_imports=["pandas"],
    max_steps=20,
)

如果想要更详细的报告,示例会打开规划功能。规划步骤让智能体提前想好下一步怎么走,用一个属性就能开启[1]:

agent.planning_interval = 4

任务小的时候这样做没问题,但上下文窗口很快就会被填满。如果让一个智能体既消化详细的搜索结果,又完成其他工作,运行会变慢,token 用量和成本也会迅速上升[1]。示例正是在这个节点开始拆分任务。

第三步:把网页调研交给托管智能体

网页搜索智能体有自己的名字、一句简短的描述和自己的工具[1]:

web_agent = CodeAgent(
    model=model,
    tools=[
        GoogleSearchTool(provider="serper"),
        VisitWebpageTool(),
        calculate_cargo_travel_time,
    ],
    name="web_agent",
    description="Browses the web to find information",
    verbosity_level=0,
    max_steps=10,
)

在这个方案中,管理者要用更强的模型。示例通过 Together AI 调用 DeepSeek-R1。它把网页智能体放进 managed_agents,放行了几个画图和数据处理的包,并把规划间隔设为 5[1]:

manager_agent = CodeAgent(
    model=InferenceClientModel("deepseek-ai/DeepSeek-R1", provider="together", max_tokens=8096),
    tools=[calculate_cargo_travel_time],
    managed_agents=[web_agent],
    additional_authorized_imports=[
        "geopandas",
        "plotly",
        "shapely",
        "json",
        "pandas",
        "numpy",
    ],
    planning_interval=5,
    verbosity_level=2,
    final_answer_checks=[check_reasoning_and_plot],
    max_steps=15,
)

运行之前,manager_agent.visualize() 会打印团队结构,包括授权的导入、工具和托管的智能体[1]。管理者的规划间隔设为 5,基线用的是 4,这些数值都是示例的设置,并不是通用的推荐[1]。

第四步:检查最终答案

final_answer_checks 接收的函数会在最终答案出来后运行。示例的检查函数会确认保存下来的地图文件存在,然后让一个多模态模型审阅它。函数开头是这一部分[1]:

def check_reasoning_and_plot(final_answer, agent_memory):
    multimodal_model = OpenAIServerModel("gpt-4o", max_tokens=8096)
    filepath = "saved_map.png"
    assert os.path.exists(filepath), "Make sure to save the plot under saved_map.png!"

检查函数的作用是在答案交回之前再核对一遍。如果审阅结果中包含 FAIL,检查就会抛出异常,答案不会被接受[1]:

    if "FAIL" in output:
        raise Exception(output)
    return True

示例的运行提示要求至少给出六个地点、把地图保存为 saved_map.png,并规定字符串应当直接打印,不要用代码去处理[1]:

manager_agent.run("""
Find all Batman filming locations in the world, calculate the time to transfer via cargo plane to here (we're in Gotham, 40.7128° N, 74.0060° W).
Also give me some supercar factories with the same cargo plane transfer time. You need at least 6 points in total.
Represent this as spatial map of the world, with the locations represented as scatter points with a color that depends on the travel time, and save it to saved_map.png!

Here's an example of how to plot and return a map:
import plotly.express as px
df = px.data.carshare()
fig = px.scatter_map(df, lat="centroid_lat", lon="centroid_lon", text="name", color="peak_hour", size=100,
     color_continuous_scale=px.colors.sequential.Magma, size_max=15, zoom=1)
fig.show()
fig.write_image("saved_image.png")
final_answer(fig)

Never try to process strings using code: when you have a string to read, just print it and you'll see it.
""")

运行结束后,可以用 manager_agent.python_executor.state["fig"] 从管理者的 Python 状态中取回生成的图[1]。

限制和常见问题

  • 规划和检查会增加模型调用次数,也就增加成本。任务确实需要时再开。
  • 搜索配额要留意。DuckDuckGo 的速率限制可能让长时间的运行中断,Serper 则需要自己的密钥[1]。
  • 估算结果只是估算。运输时间公式使用固定的余量,依赖结果之前要和可靠数据核对。
  • 如果只是想要一份报告,单个智能体加上规划可能已经够用。拆分的理由是任务大到单个智能体的上下文窗口吃紧,而不是为了形式上的分工[1]。

下一步

smolagents 文档里有专门的多智能体页面[2]。想看多智能体 RAG 系统的完整搭建过程,可以读那份分步指南[1]。

本文改编自 Hugging Face 开源智能体课程第二单元 smolagents 部分中的多智能体一节[1],原文以 Apache-2.0 许可证发布。

来源

  1. 1
    Multi-Agent SystemsHugging Face agents-course (Apache-2.0)
  2. 2

引用本页: smolagents 多智能体系统. TellWorld, https://www.tellworld.net/zh/practice/practice-smolagents-multi-agent. 更新于 2026-11-14

相关动态