智慧體課程文件

多智慧體系統

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Ask a Question Open In Colab

多智慧體系統

多智慧體系統使 專門的智慧體能夠協作完成複雜任務,從而提高了模組性、可擴充套件性和魯棒性。它不是依賴單個智慧體,而是將任務分配給具有不同能力的多個智慧體。

smolagents 中,可以組合不同的智慧體來生成 Python 程式碼、呼叫外部工具、執行網頁搜尋等。透過協調這些智慧體,我們可以建立強大的工作流。

一個典型的設定可能包括

  • 一個用於任務委派的 管理者智慧體
  • 一個用於程式碼執行的 程式碼直譯器智慧體
  • 一個用於資訊檢索的 網頁搜尋智慧體

下圖展示了一個簡單的多智慧體架構,其中一個 管理者智慧體 協調一個 程式碼直譯器工具 和一個 網頁搜尋智慧體,而後者又利用像 DuckDuckGoSearchToolVisitWebpageTool 這樣的工具來收集相關資訊。

多智慧體系統的實際應用

一個多智慧體系統由多個專門的智慧體組成,它們在一個 協調器智慧體 的協調下協同工作。這種方法透過將任務分配給具有不同角色的智慧體,使得複雜的工作流成為可能。

例如,一個 多智慧體 RAG 系統 可以整合

  • 一個用於瀏覽網際網路的 網頁智慧體
  • 一個用於從知識庫中獲取資訊的 檢索器智慧體
  • 一個用於生成視覺內容的 影像生成智慧體

所有這些智慧體都在一個協調器的管理下執行,該協調器負責任務的委派和互動。

使用多智慧體層級結構解決複雜任務

你可以按照這個 notebook 中的程式碼進行操作,你可以在 Google Colab 中執行它。

招待會快要開始了!在你的幫助下,阿爾弗雷德現在幾乎完成了所有準備工作。

但現在出了個問題:蝙蝠車不見了。阿爾弗雷德需要儘快找到一輛替代品。

幸運的是,關於布魯斯·韋恩生平的傳記電影已經拍了幾部,所以也許阿爾弗雷德可以從某個電影片場弄到一輛留下的車,並將其重新改裝以達到現代標準,這當然會包括一個全自動駕駛選項。

但這輛車可能在世界各地的任何一個拍攝地點——這些地點可能有很多。

所以阿爾弗雷德需要你的幫助。你能構建一個能夠解決這個任務的智慧體嗎?

👉 找出世界上所有蝙蝠俠電影的拍攝地點,計算透過船隻運輸到那裡的時間,並在地圖上表示出來,用顏色區分船隻運輸時間。同時用相同的船隻運輸時間表示一些超級跑車工廠的位置。

讓我們開始構建吧!

這個例子需要一些額外的軟體包,所以我們先安裝它們。

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

我們首先建立一個工具來獲取貨機運輸時間。

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:
    """
    Calculate the travel time for a cargo plane between two points on Earth using great-circle distance.

    Args:
        origin_coords: Tuple of (latitude, longitude) for the starting point
        destination_coords: Tuple of (latitude, longitude) for the destination
        cruising_speed_kmh: Optional cruising speed in km/h (defaults to 750 km/h for typical cargo planes)

    Returns:
        float: The estimated travel time in hours

    Example:
        >>> # Chicago (41.8781° N, 87.6298° W) to Sydney (33.8688° S, 151.2093° E)
        >>> result = calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093))
    """

    def to_radians(degrees: float) -> float:
        return degrees * (math.pi / 180)

    # Extract coordinates
    lat1, lon1 = map(to_radians, origin_coords)
    lat2, lon2 = map(to_radians, destination_coords)

    # Earth's radius in kilometers
    EARTH_RADIUS_KM = 6371.0

    # Calculate great-circle distance using the haversine formula
    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = (
        math.sin(dlat / 2) ** 2
        + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
    )
    c = 2 * math.asin(math.sqrt(a))
    distance = EARTH_RADIUS_KM * c

    # 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)


print(calculate_cargo_travel_time((41.8781, -87.6298), (-33.8688, 151.2093)))

設定智慧體

對於模型提供商,我們使用 Together AI,它是 Hub 上新的推理提供商之一!

GoogleSearchTool 使用 Serper API 進行網頁搜尋,因此需要設定環境變數 SERPAPI_API_KEY 並傳遞 provider="serpapi",或者設定 SERPER_API_KEY 並傳遞 provider=serper

如果你沒有設定任何 Serp API 提供商,你可以使用 DuckDuckGoSearchTool,但請注意它有速率限制。

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

我們可以先建立一個簡單的智慧體作為基線,給我們一份簡單的報告。

task = """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), and return them to me as a pandas dataframe.
Also give me some supercar factories with the same cargo plane transfer time."""
agent = CodeAgent(
    model=model,
    tools=[GoogleSearchTool("serper"), VisitWebpageTool(), calculate_cargo_travel_time],
    additional_authorized_imports=["pandas"],
    max_steps=20,
)
result = agent.run(task)
result

在我們的例子中,它生成了這個輸出

|  | Location                                             | Travel Time to Gotham (hours) |
|--|------------------------------------------------------|------------------------------|
| 0  | Necropolis Cemetery, Glasgow, Scotland, UK         | 8.60                         |
| 1  | St. George's Hall, Liverpool, England, UK         | 8.81                         |
| 2  | Two Temple Place, London, England, UK             | 9.17                         |
| 3  | Wollaton Hall, Nottingham, England, UK           | 9.00                         |
| 4  | Knebworth House, Knebworth, Hertfordshire, UK    | 9.15                         |
| 5  | Acton Lane Power Station, Acton Lane, Acton, UK  | 9.16                         |
| 6  | Queensboro Bridge, New York City, USA            | 1.01                         |
| 7  | Wall Street, New York City, USA                  | 1.00                         |
| 8  | Mehrangarh Fort, Jodhpur, Rajasthan, India       | 18.34                        |
| 9  | Turda Gorge, Turda, Romania                      | 11.89                        |
| 10 | Chicago, USA                                     | 2.68                         |
| 11 | Hong Kong, China                                 | 19.99                        |
| 12 | Cardington Studios, Northamptonshire, UK        | 9.10                         |
| 13 | Warner Bros. Leavesden Studios, Hertfordshire, UK | 9.13                         |
| 14 | Westwood, Los Angeles, CA, USA                  | 6.79                         |
| 15 | Woking, UK (McLaren)                             | 9.13                         |

我們可以透過加入一些專門的規劃步驟和新增更多的提示來稍微改進這一點。

規劃步驟允許智慧體提前思考並計劃其下一步行動,這對於更復雜的任務非常有用。

agent.planning_interval = 4

detailed_report = agent.run(f"""
You're an expert analyst. You make comprehensive reports after visiting many websites.
Don't hesitate to search for many queries at once in a for loop.
For each data point that you find, visit the source url to confirm numbers.

{task}
""")

print(detailed_report)
detailed_report

在我們的例子中,它生成了這個輸出

|  | Location                                         | Travel Time (hours) |
|--|--------------------------------------------------|---------------------|
| 0  | Bridge of Sighs, Glasgow Necropolis, Glasgow, UK | 8.6                 |
| 1  | Wishart Street, Glasgow, Scotland, UK         | 8.6                 |

благодаря этим быстрым изменениям, мы получили гораздо более лаконичный отчет, просто предоставив нашему агенту подробную подсказку и дав ему возможности планирования!

模型的上下文視窗很快就會被填滿。因此,如果我們要求智慧體將詳細搜尋的結果與另一個搜尋結果相結合,它會變得更慢,並迅速增加 token 數量和成本

➡️ 我們需要改進我們系統的結構。

✌️ 將任務分配給兩個智慧體

多智慧體結構允許在不同子任務之間分離記憶,這有兩個巨大的好處

  • 每個智慧體更專注於其核心任務,因此效能更高
  • 分離記憶減少了每一步的輸入 token 數量,從而降低了延遲和成本。

讓我們建立一個團隊,其中包含一個專門的網頁搜尋智慧體,由另一個智慧體管理。

管理者智慧體應該具備繪圖能力來撰寫最終報告:因此,讓我們給它訪問額外的匯入庫,包括 `plotly`,以及用於空間繪圖的 `geopandas` + `shapely`。

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

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,
)

管理者智慧體需要進行一些繁重的腦力勞動。

所以我們給它更強大的模型 DeepSeek-R1,並加入一個 `planning_interval`。

from smolagents.utils import encode_image_base64, make_image_url
from smolagents import OpenAIServerModel


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!"
    image = Image.open(filepath)
    prompt = (
        f"Here is a user-given task and the agent steps: {agent_memory.get_succinct_steps()}. Now here is the plot that was made."
        "Please check that the reasoning process and plot are correct: do they correctly answer the given task?"
        "First list reasons why yes/no, then write your final decision: PASS in caps lock if it is satisfactory, FAIL if it is not."
        "Don't be harsh: if the plot mostly solves the task, it should pass."
        "To pass, a plot should be made using px.scatter_map and not any other method (scatter_map looks nicer)."
    )
    messages = [
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": prompt,
                },
                {
                    "type": "image_url",
                    "image_url": {"url": make_image_url(encode_image_base64(image))},
                },
            ],
        }
    ]
    output = multimodal_model(messages).content
    print("Feedback: ", output)
    if "FAIL" in output:
        raise Exception(output)
    return True


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()

這將生成類似這樣的東西,幫助我們理解智慧體和所用工具之間的結構和關係

CodeAgent | deepseek-ai/DeepSeek-R1
├── ✅ Authorized imports: ['geopandas', 'plotly', 'shapely', 'json', 'pandas', 'numpy']
├── 🛠️ Tools:
│   ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
│   ┃ Name                        ┃ Description                           ┃ Arguments                             ┃
│   ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│   │ calculate_cargo_travel_time │ Calculate the travel time for a cargo │ origin_coords (`array`): Tuple of     │
│   │                             │ plane between two points on Earth     │ (latitude, longitude) for the         │
│   │                             │ using great-circle distance.          │ starting point                        │
│   │                             │                                       │ destination_coords (`array`): Tuple   │
│   │                             │                                       │ of (latitude, longitude) for the      │
│   │                             │                                       │ destination                           │
│   │                             │                                       │ cruising_speed_kmh (`number`):        │
│   │                             │                                       │ Optional cruising speed in km/h       │
│   │                             │                                       │ (defaults to 750 km/h for typical     │
│   │                             │                                       │ cargo planes)                         │
│   │ final_answer                │ Provides a final answer to the given  │ answer (`any`): The final answer to   │
│   │                             │ problem.                              │ the problem                           │
│   └─────────────────────────────┴───────────────────────────────────────┴───────────────────────────────────────┘
└── 🤖 Managed agents:
    └── web_agent | CodeAgent | Qwen/Qwen2.5-Coder-32B-Instruct
        ├── ✅ Authorized imports: []
        ├── 📝 Description: Browses the web to find information
        └── 🛠️ Tools:
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
            ┃ Name                        ┃ Description                       ┃ Arguments                         ┃
            ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
            │ web_search                  │ Performs a google web search for  │ query (`string`): The search      │
            │                             │ your query then returns a string  │ query to perform.                 │
            │                             │ of the top search results.        │ filter_year (`integer`):          │
            │                             │                                   │ Optionally restrict results to a  │
            │                             │                                   │ certain year                      │
            │ visit_webpage               │ Visits a webpage at the given url │ url (`string`): The url of the    │
            │                             │ and reads its content as a        │ webpage to visit.                 │
            │                             │ markdown string. Use this to      │                                   │
            │                             │ browse webpages.                  │                                   │
            │ calculate_cargo_travel_time │ Calculate the travel time for a   │ origin_coords (`array`): Tuple of │
            │                             │ cargo plane between two points on │ (latitude, longitude) for the     │
            │                             │ Earth using great-circle          │ starting point                    │
            │                             │ distance.                         │ destination_coords (`array`):     │
            │                             │                                   │ Tuple of (latitude, longitude)    │
            │                             │                                   │ for the destination               │
            │                             │                                   │ cruising_speed_kmh (`number`):    │
            │                             │                                   │ Optional cruising speed in km/h   │
            │                             │                                   │ (defaults to 750 km/h for typical │
            │                             │                                   │ cargo planes)                     │
            │ final_answer                │ Provides a final answer to the    │ answer (`any`): The final answer  │
            │                             │ given problem.                    │ to the problem                    │
            └─────────────────────────────┴───────────────────────────────────┴───────────────────────────────────┘
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.
""")

我不知道你的執行結果如何,但在我的執行中,管理者智慧體熟練地將任務分配給網頁智慧體,首先是 `1. 搜尋蝙蝠俠拍攝地點`,然後是 `2. 尋找超級跑車工廠`,最後彙總列表並繪製地圖。

讓我們透過直接檢查智慧體狀態來看看地圖長什麼樣

manager_agent.python_executor.state["fig"]

這將輸出地圖

Multiagent system example output map

資源

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.