# 让多个智能体在多智能体层级中协作 🤖🤝🤖  
_作者：[Aymeric Roucher](https://huggingface.co/m-ric)_

> 本教程属于进阶内容，建议先了解[另一本指南](agents)中的概念！

在本笔记本中，我们将构建一个**多智能体网页浏览器：一个多个智能体协作，通过互联网解决问题的智能体系统！**

它将是一个简单的层级结构，使用 `ManagedAgent` 对象来封装受管理的网页搜索智能体：

```
              +----------------+
              | 管理员智能体    |
              +----------------+
                       |
        _______________|______________
       |                              |
  代码解释器       +--------------------------------+
       工具         |         受管理的智能体        |
                     |      +------------------+      |
                     |      | 网页搜索智能体   |      |
                     |      +------------------+      |
                     |         |            |         |
                     |  网页搜索工具       |         |
                     |             访问网页工具   |
                     +--------------------------------+
```

让我们开始搭建这个系统。

⚡️ 我们的智能体将由 [meta-llama/Meta-Llama-3.1-70B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3.1-70B-Instruct) 提供支持，使用 `HfApiEngine` 类，它利用了 HF 的推理 API：推理 API 可以快速、轻松地运行任何操作系统模型。

运行以下命令来安装所需的依赖项：

```python
!pip install markdownify duckduckgo-search "transformers[agents]" --upgrade -q
```

我们将选择使用由 [Qwen/Qwen2.5-72B-Instruct](https://huggingface.co/Qwen/Qwen2.5-72B-Instruct) 提供支持的模型，因为它非常强大，并且在 HF API 中可以免费使用。

```python
model = "Qwen/Qwen2.5-72B-Instruct"
```

### 🔍 创建一个网页搜索工具

对于网页浏览，我们可以直接使用我们现有的 [`DuckDuckGoSearchTool`](https://github.com/huggingface/transformers/blob/main/src/transformers/agents/search.py) 工具来提供一个类似于 Google 搜索的功能。

但是，我们还需要能够查看 `DuckDuckGoSearchTool` 找到的网页内容。  
为此，我们可以导入库中内建的 `VisitWebpageTool`，但我们将重新构建这个工具，以便了解它是如何实现的。

因此，让我们从零开始，使用 `markdownify` 创建我们的 `VisitWebpageTool` 工具。

```python
import re
import requests
from markdownify import markdownify as md
from requests.exceptions import RequestException
from transformers.agents import tool


@tool
def visit_webpage(url: str) -> str:
    """Visits a webpage at the given URL and returns its content as a markdown string.

    Args:
        url: The URL of the webpage to visit.

    Returns:
        The content of the webpage converted to Markdown, or an error message if the request fails.
    """
    try:
        # Send a GET request to the URL
        response = requests.get(url)
        response.raise_for_status()  # Raise an exception for bad status codes

        # Convert the HTML content to Markdown
        markdown_content = md(response.text).strip()

        # Remove multiple line breaks
        markdown_content = re.sub(r"\n{3,}", "\n\n", markdown_content)

        return markdown_content

    except RequestException as e:
        return f"Error fetching the webpage: {str(e)}"
    except Exception as e:
        return f"An unexpected error occurred: {str(e)}"
```

好了，现在让我们初始化并测试我们的工具！

```python
>>> print(visit_webpage("https://en.wikipedia.org/wiki/Hugging_Face")[:500])
```

<pre>
Hugging Face \- Wikipedia

[Jump to content](#bodyContent)

Main menu

Main menu
move to sidebar
hide

 Navigation
 

* [Main page](/wiki/Main_Page "Visit the main page [z]")
* [Contents](/wiki/Wikipedia:Contents "Guides to browsing Wikipedia")
* [Current events](/wiki/Portal:Current_events "Articles related to current events")
* [Random article](/wiki/Special:Random "Visit a randomly selected article [x]")
* [About Wikipedia](/wiki/Wikipedia:About "Learn about Wikipedia and how it works")
* [Co
</pre>

## 构建我们的多智能体系统 🤖🤝🤖

现在我们已经拥有了所有的工具 `search` 和 `visit_webpage`，可以使用它们来创建网页智能体。

该选择什么配置呢？  
- 网页浏览是一个单线程任务，不需要并行调用工具，因此使用 JSON 调用工具非常合适。因此，我们选择 `ReactJsonAgent`。  
- 此外，由于有时网页搜索需要浏览多个页面才能找到正确答案，我们更倾向于将 `max_iterations` 增加到 10。

```python
from transformers.agents import (
    ReactCodeAgent,
    ReactJsonAgent,
    HfApiEngine,
    ManagedAgent,
)
from transformers.agents.search import DuckDuckGoSearchTool

llm_engine = HfApiEngine(model)

web_agent = ReactJsonAgent(
    tools=[DuckDuckGoSearchTool(), visit_webpage],
    llm_engine=llm_engine,
    max_iterations=10,
)
```

然后，我们将这个智能体封装到一个 `ManagedAgent` 中，这样它就可以通过管理员智能体进行调用了。


```python
managed_web_agent = ManagedAgent(
    agent=web_agent,
    name="search",
    description="Runs web searches for you. Give it your query as an argument.",
)
```


最后，我们创建一个管理员智能体，并在初始化时将我们的受管理智能体通过 `managed_agents` 参数传递给它。

由于这个智能体负责规划和思考，因此高级推理将非常有帮助，所以选择 `ReactCodeAgent` 是最合适的。

另外，我们想提一个涉及当前年份的问题：因此，我们需要添加 `additional_authorized_imports=["time", "datetime"]`。

```python
manager_agent = ReactCodeAgent(
    tools=[],
    llm_engine=llm_engine,
    managed_agents=[managed_web_agent],
    additional_authorized_imports=["time", "datetime"],
)
```

就这样！现在让我们运行我们的系统！我们选择一个需要进行一些计算的问题

```python
manager_agent.run("How many years ago was Stripe founded?")
```

我们的智能体成功地高效协作，解决了任务！ ✅

💡 你可以轻松地扩展到更多智能体：一个负责代码执行，一个负责网页搜索，一个负责文件加载……

🤔💭 甚至可以考虑构建更复杂的树状层级结构，一个 CEO 智能体负责管理多个中层经理，每个经理下有多个报告。

我们甚至可以添加更多的中间管理层，每层都有多个日常会议，进行大量敏捷工作和 Scrum 主管，每个新增的组件都会增加足够的摩擦力，确保任务永远无法完成……嗯，等等，不，我们还是坚持我们的简单结构吧。


<EditOnGithub source="https://github.com/huggingface/cookbook/blob/main/notebooks/zh-CN/multiagent_web_assistant.md" />