
构建你的第一个多智能体系统:初学者指南
图片来源:编辑 | Midjourney
人工智能的蓬勃发展,尤其是大型语言模型(LLMs)的兴起,得益于众多研究团队和公司的竞赛,他们竞相开发最先进的模型,并展示其在广泛领域的潜在用例。最近,这些发展往往聚焦于模型的一个方面:推理。给定模型的每个新迭代,通常都被宣传为具有更强的思考能力和更好的推理能力。
随着越来越强大的推理模型出现,人工智能代理(AI agents)的话题变得炙手可热。由于其能够采取行动以实现特定目标的能力,并且得到 LLM 强大的推理能力的支撑,代理及其讨论正 gaining momentum。
对于从业者来说,能够构建人工智能代理,尤其是多智能体系统,变得至关重要。我们该如何着手呢?让我们一起来探索。
多智能体系统
人工智能代理是能够观察环境、推理其目标并使用外部工具采取行动的自主系统。这意味着代理是一个能够推理和执行动作以实现其目标的系统。
总的来说,人工智能代理的核心依赖于认知架构,该架构由三个组件组成,包括:
- 作为核心决策引擎的语言模型
- 供代理与外部系统交互的工具
- 管理代理如何行动的编排(Orchestration)
单独来看,代理已经足够强大,可以执行基本任务。然而,单个代理可能不足以处理更复杂的任务。随着复杂性的增加,代理未能实现目标的可能性也更高。这就是多智能体系统出现的原因:允许多个代理协同工作以实现共享目标。多个专业的个体代理在一个协作环境中工作,以完成个体任务并实现共享的、总体的目标。
在结构上,多智能体系统可以以任何保持协作的方式构建。没有一种特定的架构对所有用例都是理想的。相反,我们选择最能适应当前问题的架构。
最常见的两种架构是网络(network)或监督者(supervisor)。

单智能体架构与多智能体网络和监督者架构的对比。
在网络架构中,代理在多智能体系统中运行,相互通信以决定下一个调用哪个代理。相比之下,监督者架构依赖于一个单一的监督者代理来决定下一个应采取行动的代理。除此之外,还有许多其他架构可供选择——您也可以设计一个适合您需求的架构,包括混合架构或临时架构。
例如,让我们构建一个多智能体系统来生成关于我们想要的一个特定主题的报告。我们将使用监督者网络架构,如下图所示。

我们的多智能体系统监督者网络架构。
结构细节很简单;我们将有四个专业的代理:
- 网络研究员代理
- 趋势分析师代理
- 报告撰写代理
- 校对代理
经理代理监督所有这些代理,它们仅在接到指示时执行任务。此外,网络研究员代理可以访问网络搜索工具,通过互联网研究目标主题。
让我们开始构建多智能体系统。我们将使用 CrewAI Agent 来简化操作,它非常适合启动多智能体系统。
首先,我们将安装开发系统所需的所有库。
1 |
pip install crewai langchain-community pydantic |
然后,我们将导入此教程中使用的所有必需库。
1 2 3 4 |
from crewai import Crew, Task, Agent, Process, LLM from pydantic import BaseModel from crewai.tools.structured_tool import CrewStructuredTool from langchain_community.tools import BraveSearch |
代理系统依赖于 LLM 作为其核心决策制定。推理能力越强越好。在本教程中,我们将使用 GPT-4o 模型作为我们的 LLM,但如果您愿意,也可以将其切换为其他模型。CrewAI 使用 LiteLLM 来访问 LLM,因此 LiteLLM 可用的任何内容都可以在 CrewAI 框架内使用。
1 2 3 4 |
llm = LLM( model='openai/gpt-4o', api_key="YOUR-API-KEY" ) |
然后,我们将使用 LangChain 初始化搜索工具,并使用以下代码通过 CrewAI 工具框架将其包装起来。在此示例中,我们将使用 Brave 搜索引擎。它需要 API 密钥,所以请不要忘记获取一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# 定义 BraveSearch 输入模式 class BraveSearchInput(BaseModel): query: str def brave_search_wrapper(*args, **kwargs): if isinstance(kwargs, dict) and "query" in kwargs: query = kwargs["query"] elif len(args) > 0 and isinstance(args[0], BraveSearchInput): query = args[0].query else: raise ValueError("Invalid input provided to BraveSearchTool.") brave_search = BraveSearch.from_api_key( api_key="BRAVE-API-KEY", search_kwargs={"count": 3} ) result = brave_search.run(query) return result def create_brave_search_tool(): return CrewStructuredTool.from_function( name="brave_search_tool", description=( "使用 BraveSearch 搜索网络,并为给定查询返回相关信息。" "对于查找有关各种主题的最新准确信息非常有用。" ), args_schema=BraveSearchInput, # 使用 BraveSearch 输入模式 func=brave_search_wrapper ) # 创建 BraveSearch 工具 SearchTool = create_brave_search_tool() |
接下来,我们将定义代理。CrewAI 通过仅要求对其角色、目标和背景的描述,使开发代理变得更加容易。您的描述越具体,代理执行其操作的效果就越好。
例如,下面的代码展示了我们如何定义网络研究员代理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 定义代理 web_researcher_agent = Agent( role="网络研究专家", goal=( "查找关于 {topic} 的最新、最有影响力且最相关的信息。这包括识别 " "关键用例、挑战和统计数据,为更深入的分析奠定基础。" ), backstory=( "您曾是一名调查记者,以善于揭示技术突破和市场洞察而闻名。" "凭借多年的经验,您在识别可操作数据和趋势方面表现出色。" ), tools=[SearchTool], llm=llm, verbose=True ) |
网络研究员代理的独特之处在于它能够访问我们之前初始化的 SearchTool。
我在上面的网络研究员代理中提供了占位符 {topic}
。这是用户可以在不更改代码的情况下输入其输入并影响多智能体系统的位置。
让我们为我们的多智能体系统定义其他代理。您可以随时更改每个代理的角色、目标和背景,因为我只提供尽可能简单的定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
trend_analyst_agent = Agent( role="洞察综合师", goal=( "分析研究结果,提取重要趋势,并按行业影响力、增长潜力和独特性进行排名。" "为决策者提供可操作的见解。" ), backstory=( "您是一位经验丰富的战略顾问,已转向 {topic} 分析领域。" "您善于发现模式,擅长将原始数据转化为清晰、可操作的见解。" ), tools=[], llm=llm, verbose=True ) report_writer_agent = Agent( role="叙事架构师", goal=( "撰写一份详细、专业的报告,有效地传达研究结果和分析。" "注重清晰度、逻辑流程和参与度。" ), backstory=( "您曾是一家知名期刊的技术作家,现在致力于创作行业领先的报告。" "您将讲故事与数据相结合,以确保您的作品既有信息量又引人入胜。" ), tools=[], llm=llm, verbose=True ) proofreader_agent = Agent( role="卓越抛光师", goal=( "优化草稿的语法准确性、可读性和格式,确保最终文件符合专业出版标准。" "精益求精。" ), backstory=( "您是一位屡获殊荣的编辑转校对员,擅长完善书面内容。" "您敏锐的细节洞察力确保了每一份文档都完美无瑕。" ), tools=[], llm=llm, verbose=True ) manager_agent = Agent( role="工作流程大师", goal=( "协调代理,管理任务依赖关系,并确保所有输出都符合质量标准。" "您的重点是通过高效的任务管理交付一个连贯的最终产品。" ), backstory=( "您曾是一名项目经理,热衷于高效的团队合作,确保每个流程都顺利运行," "并监督任务和验证结果。" ), tools=[], llm=llm, verbose=True ) |
设置好代理后,我们将设置它们将执行的任务。如果代理是个人,CrewAI 中的任务就是该代理将要执行并尝试达成的动作。
CrewAI 任务代码结构示例显示在下面的代码中。
1 2 3 4 5 6 7 8 9 |
# 定义任务 web_research_task = Task( description=( "进行网络研究,以识别 5-7 个关于 {topic} 的内容。重点关注关键用例。" ), expected_output=( "一个结构化的列表,包含 5-7 个 {topic}。" ) ) |
通常可以传递两个参数,包括任务描述和预期输出。您还可以设置许多其他参数,但这些是基本参数。
让我们为我们拥有的所有代理设置其他任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
trend_analysis_task = Task( description=( "分析研究结果,对 {topic} 进行排名。" ), expected_output=( "一个按影响力排名的趋势表,并附有对每个趋势的简要描述。" ) ) report_writing_task = Task( description=( "起草一份报告,总结 {topic} 的研究结果和分析。" "包括引言、趋势概述、分析和建议等部分。" ), expected_output=( "一份结构良好、专业的草稿,具有清晰的信息流程。确保逻辑组织和一致的语气。" ) ) proofreading_task = Task( description=( "优化草稿的语法准确性、连贯性和格式。" "确保最终文件经过精心打磨,可供发布。" ), expected_output=( "一份专业的、精美的报告,没有语法错误和不一致之处。格式化文档以方便阅读。" "方便阅读。" ) ) |
您可以设置由哪个代理执行哪个任务,但经理代理会为您完成这项工作。
最后,我们将设置团队(crew)来编排多智能体系统。我们将经理代理传递给团队,并让监督者决定执行哪个任务来达到目标。
1 2 3 4 5 6 7 |
crew = Crew( agents=[web_researcher_agent, trend_analyst_agent, report_writer_agent, proofreader_agent], tasks=[web_research_task, trend_analysis_task, report_writing_task, proofreading_task], process=Process.hierarchical, manager_agent=manager_agent, verbose=True ) |
一切就绪后,让我们启动多智能体系统。使用以下代码,我们可以传入要搜索和撰写报告的主题。
1 |
crew_output = crew.kickoff(inputs={"topic": "AI 趋势"}) |
输出将是关于多个代理工作的最终报告。内容太长无法在此展示,但最终报告看起来会像下图一样。

示例多智能体报告系统最终报告输出。
恭喜!您已经构建了您的第一个多智能体系统。我建议您尝试其他代理组合、架构和工具,以更好地了解如何开发系统。
结论
人工智能代理是一个能够推理并执行动作以实现给定目标的系统。单独来看,代理已经足够强大,可以执行基本任务。但是,在协作环境中工作多个专业个体代理的多智能体系统可以更有效地实现目标。
本文演示了如何使用 CrewAI 开发一个多智能体系统来生成所需主题的报告。通过这个库,我们看到了如何设置代理和任务,并通过实现使用经理代理的监督者架构来构建系统和代理协调。
感谢您提供如此清晰的示例。我们正在从旧的 langchain 实现迁移,这是一篇非常及时且相关的文章。
感谢 Gerard 的反馈和支持!
很棒的例子。我认为重要的步骤是为该过程包含可观察性,因为经理代理协调着工作人员。
谢谢 Rich 的反馈!