书籍名称:Agentic Design Patterns: A Hands-On Guide to Building Intelligent Systems
本书作者:Antonio Gulli
链接地址:https://docs.google.com/document/d/1RZ5-2fykDQKOBx01pwfKkDe0GCs5ydca7xW9Q4wqS_M
内容摘要:本文是对《智能体设计模式》第七章的翻译。此章节介绍了多智能体协作和通信的内容,以及如何进行相关设计。
翻译来源:煤矿工厂
概述
虽然单一代理架构对于明确定义的问题可能有效,但当面临复杂的、多领域任务时,其能力往往受到限制。多代理协作模式通过将系统构建为由不同专业代理组成的协作集合来解决这些限制。这种方法基于任务分解原则,即将高层目标分解为离散的子问题。然后,每个子问题都被分配给拥有最适合该任务的特定工具、数据访问或推理能力的代理。
例如,一个复杂的研究查询可能会被分解并分配给负责信息检索的研究代理、负责统计处理的数据分析代理以及负责生成最终报告的综合代理。这种系统的效率不仅在于分工,而且关键取决于代理间的通信机制。这需要一个标准化的通信协议和共享的本体,允许代理交换数据、委托子任务并协调其行动,以确保最终输出的一致性。
这种分布式架构提供了多项优势,包括增强的模块化、可扩展性和鲁棒性,因为单个代理的故障不一定会导致整个系统故障。协作可以产生协同效应,使多代理系统的集体性能超越集合中任何单个代理的潜在能力。
多智能体协作模式涉及设计多个独立或半独立智能体协同工作以实现共同目标的系统。每个智能体通常具有明确的角色、与整体目标一致的特定目标,并且可能访问不同的工具或知识库。这种模式的力量在于这些智能体之间的互动和协同作用。
协作可以采取各种形式:
- 顺序交接:一个智能体完成一项任务并将其输出传递给另一个智能体,以进行管道中的下一步(类似于规划模式,但明确涉及不同的智能体)。
- 并行处理:多个智能体同时处理问题的不同部分,然后将它们的结果组合起来。
- 辩论和共识:多智能体协作中,具有不同视角和信息来源的智能体参与讨论以评估选项,最终达成共识或更明智的决策。
- 分层结构:一个管理者智能体可能根据其工具访问或插件能力动态地将任务委派给工作者智能体,并综合它们的结果。每个智能体还可以处理相关的工具组,而不是由单个智能体处理所有工具。
- 专家团队:在不同领域具有专业知识的智能体(例如,研究员、作家、编辑)协作以产生复杂的输出。
- 评论员-审阅者:智能体创建初始输出,例如计划、草稿或答案。第二组智能体然后批判性地评估此输出是否符合政策、安全性、合规性、正确性、质量以及与组织目标的对齐。原始创建者或最终智能体根据此反馈修改输出。这种模式对于代码生成、研究写作、逻辑检查和确保道德对齐特别有效。这种方法的优点包括增强的健壮性、改进的质量以及减少幻觉或错误的可能性。
多智能体系统(参见图1)主要包括智能体角色和职责的划分、建立智能体之间交换信息的通信渠道,以及制定指导其协作努力的任务流或交互协议。

Crew AI 和 Google ADK 等框架旨在通过提供智能体、任务及其交互过程规范的结构来促进这种范式。这种方法对于需要各种专业知识、包含多个离散阶段或利用并发处理和跨智能体信息佐证优势的挑战特别有效。
应用示例
多智能体协作是一种强大的模式,适用于众多领域:
- 复杂研究与分析:一组智能体可以协作完成一个研究项目。一个智能体可能专注于搜索学术数据库,另一个负责总结研究成果,第三个负责识别趋势,第四个则将信息综合成报告。这与人类研究团队的运作方式类似。
- 软件开发:设想智能体协作开发软件。一个智能体可以是需求分析师,另一个是代码生成器,第三个是测试员,第四个是文档编写者。它们可以相互传递输出,以构建和验证组件。
- 创意内容生成:创建一个营销活动可能涉及市场研究智能体、文案撰写智能体、图形设计智能体(使用图像生成工具)和社交媒体调度智能体,它们共同协作。
- 金融分析:多智能体系统可以分析金融市场。智能体可能专注于获取股票数据、分析新闻情绪、进行技术分析,并生成投资建议。
- 户支持升级:一线支持智能体可以处理初步查询,在需要时将复杂问题升级给专业智能体(例如,技术专家或计费专员),展示了基于问题复杂度的顺序交接。
- 供应链优化:智能体可以代表供应链中的不同节点(供应商、制造商、分销商)并协作优化库存水平、物流和调度,以应对不断变化的需求或中断。
- 网络分析与修复:自主运营极大地受益于智能体架构,尤其是在故障定位方面。多个智能体可以协作分类和修复问题,并提出最佳行动方案。这些智能体还可以与传统的机器学习模型和工具集成,利用现有系统,同时提供生成式AI的优势。
划分专业化智能体并精心协调它们之间的相互关系,使开发人员能够构建系统,这些系统展现出增强的模块化、可扩展性,以及处理对于单一的集成智能体而言无法克服的复杂问题的能力。
交互和通信方式的探索
理解智能体之间复杂的交互和通信方式是设计有效多智能体系统的基础。如图2所示,存在一系列相互关系和通信模型,从最简单的单智能体场景到复杂的、定制设计的协作框架。每种模型都具有独特的优点和挑战,影响着多智能体系统的整体效率、鲁棒性和适应性。
理解智能体之间复杂的交互和通信方式是设计有效多智能体系统的基础。如图2所示,存在一系列相互关系和通信模型,从最简单的单智能体场景到复杂的、定制设计的协作框架。每种模型都具有独特的优点和挑战,影响着多智能体系统的整体效率、鲁棒性和适应性。
- 单智能体:在最基本的层面上,“单智能体”独立运行,不与其他实体直接交互或通信。虽然这种模型易于实现和管理,但其能力本质上受限于单个智能体的范围和资源。它适用于可分解为独立子问题(每个子问题均可由一个单一的、自给自足的智能体解决)的任务。
- 网络: “网络”模型代表了协作的重大一步,多个智能体以去中心化的方式直接相互交互。通信通常以点对点方式进行,允许信息、资源甚至任务的共享。这种模型增强了弹性,因为一个智能体的故障不一定会使整个系统瘫痪。然而,在大型、非结构化网络中管理通信开销并确保一致的决策可能具有挑战性。
- 监督者:在“监督者”模型中,一个专门的智能体,即“监督者”,监督和协调一组下属智能体的活动。监督者充当通信、任务分配和冲突解决的中心枢纽。这种分层结构提供了清晰的权限线,可以简化管理和控制。然而,它引入了单点故障(监督者),如果监督者被大量下属或复杂任务淹没,则可能成为瓶颈。
- 监督者作为工具:此模型是“监督者”概念的细微扩展,其中监督者的角色更多地是提供资源、指导或分析支持给其他智能体,而不是直接命令和控制。监督者可以提供工具、数据或计算服务,使其他智能体能够更有效地执行任务,而不必规定它们的每一个行动。这种方法旨在利用监督者的能力,而不施加严格的自上而下的控制。
- 分层: “分层”模型在监督者概念的基础上扩展,创建了一个多层组织结构。这涉及多个级别的监督者,高级监督者监督低级监督者,最终在最低层有一组操作智能体。这种结构非常适合可以分解为子问题(每个子问题由层次结构的特定层管理)的复杂问题。它提供了一种结构化的方法来管理可伸缩性和复杂性,允许在定义的边界内进行分布式决策。
- 自定义: “自定义”模型代表了多智能体系统设计的最终灵活性。它允许创建独特的相互关系和通信结构,精确地根据给定问题或应用程序的特定要求进行定制。这可以涉及结合前面提到的模型元素的混合方法,或从环境的独特约束和机会中产生的全新设计。自定义模型通常源于优化特定性能指标、处理高度动态环境或将领域特定知识整合到系统架构中的需求。设计和实施自定义模型通常需要深入理解多智能体系统原理,并仔细考虑通信协议、协调机制和涌现行为。

总之,为多智能体系统选择相互关系和通信模型是一个关键的设计决策。每种模型都提供独特的优点和缺点,最佳选择取决于任务的复杂性、智能体数量、所需的自主级别、对鲁棒性的需求以及可接受的通信开销等因素。多智能体系统未来的发展可能会继续探索和完善这些模型,并开发协作智能的新范式。
代码示例上手
Crew AI
这段 Python 代码使用 CrewAI 框架定义了一个由 AI 驱动的团队,用于生成一篇关于 AI 趋势的博客文章。它首先设置环境,从 .env 文件加载 API 密钥。应用程序的核心是定义两个代理:一个研究员负责查找和总结 AI 趋势,一个写作者负责根据研究结果创建博客文章。
相应地定义了两个任务:一个用于研究趋势,另一个用于撰写博客文章,其中撰写任务依赖于研究任务的输出。然后将这些代理和任务组装成一个团队,指定一个按顺序执行任务的流程。团队使用代理、任务和语言模型(特别是“gemini-2.0-flash”模型)进行初始化。主函数使用 kickoff() 方法执行此团队,协调代理之间的协作以产生所需的输出。最后,代码打印团队执行的最终结果,即生成的博客文章。
import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
from langchain_google_genai import ChatGoogleGenerativeAI
def setup_environment():
"""加载环境变量并检查所需的API密钥。"""
load_dotenv()
ifnot os.getenv("GOOGLE_API_KEY"):
raise ValueError("未找到 GOOGLE_API_KEY。请在您的 .env 文件中设置。")
def main():
"""
使用最新的 Gemini 模型初始化并运行用于内容创建的 AI 团队。
"""
setup_environment()
# 定义要使用的语言模型。
# 已更新为 Gemini 2.0 系列的模型,以获得更好的性能和功能。
# 对于前沿(预览版)功能,您可以使用 "gemini-2.5-flash"。
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
# 定义具有特定角色和目标的代理
researcher = Agent(
role='高级研究分析师',
goal='查找并总结人工智能的最新趋势。',
backstory="您是一位经验丰富的研究分析师,擅长识别关键趋势并综合信息。",
verbose=True,
allow_delegation=False,
)
writer = Agent(
role='技术内容撰稿人',
goal='根据研究结果撰写一篇清晰且引人入胜的博客文章。',
backstory="您是一位技术娴熟的撰稿人,可以将复杂的技术主题转化为易于理解的内容。",
verbose=True,
allow_delegation=False,
)
# 为代理定义任务
research_task = Task(
description="研究2024-2025年人工智能领域排名前3的新兴趋势。重点关注实际应用和潜在影响。",
expected_output="一份关于排名前3的AI趋势的详细总结,包括要点和来源。",
agent=researcher,
)
writing_task = Task(
description="根据研究结果撰写一篇500字的博客文章。文章应该引人入胜,并易于普通受众理解。",
expected_output="一篇关于最新AI趋势的完整500字博客文章。",
agent=writer,
context=[research_task],
)
# 创建团队
blog_creation_crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
llm=llm,
verbose=2# 设置详细程度以获取详细的团队执行日志
)
# 执行团队任务
print("## 正在运行使用 Gemini 2.0 Flash 的博客创建团队... ##")
try:
result = blog_creation_crew.kickoff()
print("\n------------------\n")
print("## 团队最终输出 ##")
print(result)
except Exception as e:
print(f"\n发生了一个意外错误: {e}")
if __name__ == "__main__":
main()
我们现在将深入探讨 Google ADK 框架中的更多示例,特别强调分层、并行和顺序协调范例,以及将代理实现为操作工具。
Google ADK
以下代码示例演示了如何在 Google ADK 中通过创建父子关系来建立分层代理结构。代码定义了两种类型的代理:LlmAgent 和从 BaseAgent 派生的自定义 TaskExecutor 代理。TaskExecutor 专为特定的非 LLM 任务而设计,在此示例中,它仅生成一个“任务成功完成”事件。一个名为 greeter 的 LlmAgent 使用指定的模型和指令初始化,充当友好的迎宾员。自定义 TaskExecutor 被实例化为 task_doer。一个名为 coordinator 的父 LlmAgent 也使用模型和指令创建。coordinator 的指令引导它将问候语委托给 greeter,并将任务执行委托给 task_doer。greeter 和 task_doer 作为子代理添加到 coordinator,建立父子关系。然后,代码断言此关系已正确设置。最后,它打印一条消息,指示代理层次结构已成功创建。
from google.adk.agents import LlmAgent, BaseAgent
from google.adk.agents.invocation_context import InvocationContext
from google.adk.events import Event
from typing import AsyncGenerator
# 通过继承 BaseAgent 正确实现自定义代理
class TaskExecutor(BaseAgent):
"""一个具有自定义、非 LLM 行为的专用代理。"""
name: str = "任务执行器"# 代理的名称
description: str = "执行一个预定义的任务。"# 代理的描述
asyncdef _run_async_impl(self, context: InvocationContext) -> AsyncGenerator[Event, None]:
"""任务的自定义实现逻辑。"""
# 这里将是您的自定义逻辑所在。
# 对于此示例,我们将只生成一个简单的事件。
yield Event(author=self.name, content="任务成功完成。")
# 定义具有正确初始化的单个代理
# LlmAgent 需要指定一个模型。
greeter = LlmAgent(
name="问候者", # 代理名称
model="gemini-2.0-flash-exp",
instruction="你是一个友好的问候者。"# 代理的指令
)
task_doer = TaskExecutor() # 实例化我们具体的自定义代理
# 创建一个父代理并分配其子代理
# 父代理的描述和指令应指导其委派逻辑。
coordinator = LlmAgent(
name="协调者", # 代理名称
model="gemini-2.0-flash-exp",
description="一个可以问候用户和执行任务的协调者。", # 代理的描述
instruction="当被要求问候时,委托给问候者。当被要求执行任务时,委托给任务执行器。", # 代理的指令
sub_agents=[
greeter,
task_doer
]
)
# ADK 框架自动建立父子关系。
# 如果在初始化后检查,这些断言将通过。
assert greeter.parent_agent == coordinator
assert task_doer.parent_agent == coordinator
print("代理层级结构创建成功。")
此代码摘录说明了在 Google ADK 框架内使用 LoopAgent 来建立迭代工作流。代码定义了两个代理:ConditionChecker 和 ProcessingStep。ConditionChecker 是一个自定义代理,用于检查会话状态中的“status”值。如果“status”为“completed”,ConditionChecker 会升级一个事件以停止循环。否则,它会生成一个事件以继续循环。ProcessingStep 是一个使用“gemini-2.0-flash-exp”模型的 LlmAgent。其指令是执行一个任务,如果它是最后一步,则将会话“status”设置为“completed”。创建了一个名为 StatusPoller 的 LoopAgent。StatusPoller 配置了 max_iterations=10。StatusPoller 包含 ProcessingStep 和 ConditionChecker 实例作为子代理。LoopAgent 将按顺序执行子代理,最多执行 10 次迭代,如果 ConditionChecker 发现状态为“completed”,则停止。
import asyncio
from typing import AsyncGenerator
from google.adk.agents import LoopAgent, LlmAgent, BaseAgent
from google.adk.events import Event, EventActions
from google.adk.agents.invocation_context import InvocationContext
# 最佳实践:将自定义代理定义为完整、自描述的类。
class ConditionChecker(BaseAgent):
"""一个自定义代理,用于检查会话状态中的 'completed' 状态。"""
name: str = "条件检查器"
description: str = "检查一个过程是否完成并发出信号停止循环。"
asyncdef _run_async_impl(
self, context: InvocationContext
) -> AsyncGenerator[Event, None]:
"""检查状态并生成一个事件以继续或停止循环。"""
status = context.session.state.get("status", "pending")
is_done = (status == "completed")
if is_done:
# 当条件满足时,升级以终止循环。
yield Event(author=self.name, actions=EventActions(escalate=True))
else:
# 生成一个简单的事件以继续循环。
yield Event(author=self.name, content="条件未满足,继续循环。")
# 修正:LlmAgent 必须有一个模型和清晰的指令。
process_step = LlmAgent(
name="处理步骤",
model="gemini-2.0-flash-exp",
instruction="你是一个较长过程中的一个步骤。执行你的任务。如果你是最后一步,通过将 'status' 设置为 'completed' 来更新会话状态。"
)
# LoopAgent 协调工作流程。
poller = LoopAgent(
name="状态轮询器",
max_iterations=10,
sub_agents=[
process_step,
ConditionChecker() # 实例化定义良好的自定义代理。
]
)
# 这个轮询器现在将重复执行 'process_step'
# 然后是 'ConditionChecker'
# 直到状态为 'completed' 或 10 次迭代已过。
此代码摘录阐明了 Google ADK 中的 SequentialAgent 模式,该模式旨在构建线性工作流。此代码使用 google.adk.agents 库定义了一个顺序代理管道。该管道由两个代理组成,step1 和 step2。step1 被命名为“Step1_Fetch”,其输出将存储在会话状态中的“data”键下。step2 被命名为“Step2_Process”,并被指示分析存储在 session.state["data"] 中的信息并提供摘要。名为“MyPipeline”的 SequentialAgent 协调这些子代理的执行。当管道以初始输入运行时,step1 将首先执行。step1 的响应将保存到会话状态中的“data”键下。随后,step2 将执行,利用 step1 根据其指令放入状态的信息。这种结构允许构建工作流,其中一个代理的输出成为下一个代理的输入。这是创建多步 AI 或数据处理管道的常见模式。
from google.adk.agents import SequentialAgent, Agent
# 该代理的输出将被保存到 session.state["data"]
step1 = Agent(name="步骤1_获取", output_key="data")
# 该代理将使用来自上一步的数据。
# 我们指示它如何查找和使用这些数据。
step2 = Agent(
name="步骤2_处理",
instruction="分析在 state['data'] 中找到的信息并提供一个摘要。"
)
pipeline = SequentialAgent(
name="我的流水线",
sub_agents=[step1, step2]
)
# 当流水线以初始输入运行时,步骤1将执行,
# 其响应将被存储在 session.state["data"] 中,然后
# 步骤2将执行,按照指示使用状态中的信息。
以下代码示例说明了 Google ADK 中的 ParallelAgent 模式,该模式有助于并发执行多个代理任务。data_gatherer 旨在并发运行两个子代理:weather_fetcher 和 news_fetcher。weather_fetcher 代理被指示获取给定位置的天气并将结果存储在 session.state[“weather_data”] 中。同样,news_fetcher 代理被指示检索给定主题的头条新闻并将其存储在 session.state[“news_data”] 中。每个子代理都配置为使用“gemini-2.0-flash-exp”模型。ParallelAgent 协调这些子代理的执行,允许它们并行工作。weather_fetcher 和 news_fetcher 的结果都将被收集并存储在会话状态中。最后,该示例展示了代理执行完成后如何从 final_state 访问收集到的天气和新闻数据。
from google.adk.agents import Agent, ParallelAgent
# 最好将获取逻辑定义为代理的工具
# 为了简化本例,我们将逻辑嵌入到代理的指令中。
# 在实际场景中,您将使用工具。
# 定义将并行运行的各个代理
weather_fetcher = Agent(
name="天气获取器",
model="gemini-2.0-flash-exp",
instruction="获取给定位置的天气并仅返回天气报告。",
output_key="weather_data"# 结果将存储在 session.state["weather_data"] 中
)
news_fetcher = Agent(
name="新闻获取器",
model="gemini-2.0-flash-exp",
instruction="获取给定主题的头条新闻并仅返回该新闻。",
output_key="news_data" # 结果将存储在 session.state["news_data"] 中
)
# 创建 ParallelAgent 来协调子代理
data_gatherer = ParallelAgent(
name="数据收集器",
sub_agents=[
weather_fetcher,
news_fetcher
]
)
下面这个代码片段示例说明了 Google ADK 中的“代理即工具”范式,它允许代理以类似于函数调用的方式利用另一个代理的功能。具体来说,代码使用 Google 的 LlmAgent 和 AgentTool 类定义了一个图像生成系统。它由两个代理组成:父 artist_agent 和子 image_generator_agent。generate_image 函数是一个简单的工具,用于模拟图像创建,返回模拟图像数据。image_generator_agent 负责根据它收到的文本提示使用此工具。artist_agent 的作用是首先发明一个创意图像提示。然后,它通过 AgentTool 包装器调用 image_generator_agent。AgentTool 充当桥梁,允许一个代理将另一个代理用作工具。当 artist_agent 调用 image_tool 时,AgentTool 使用 artist 发明的提示调用 image_generator_agent。然后,image_generator_agent 使用该提示调用 generate_image 函数。最后,生成的图像(或模拟数据)通过代理返回。这种架构展示了一个分层代理系统,其中一个更高级别的代理协调一个更低级别、更专业的代理来执行任务。
from google.adk.agents import LlmAgent
from google.adk.tools import agent_tool
from google.genai import types
# 1. 核心功能的简单函数工具。
# 这遵循了将行动与推理分离的最佳实践。
def generate_image(prompt: str) -> dict:
"""
根据文本提示生成图像。
参数:
prompt: 要生成的图像的详细描述。
返回:
一个包含状态和生成的图像字节的字典。
"""
print(f"工具: 正在为提示生成图像: '{prompt}'")
# 在实际实现中,这会调用图像生成API。
# 对于此示例,我们返回模拟图像数据。
mock_image_bytes = b"mock_image_data_for_a_cat_wearing_a_hat"# 模拟一只戴帽子的猫的图像数据
return {
"status": "success",
# 该工具返回原始字节,代理将处理 Part 的创建。
"image_bytes": mock_image_bytes,
"mime_type": "image/png"
}
# 2. 将 ImageGeneratorAgent 重构为 LlmAgent。
# 它现在正确使用了传递给它的输入。
image_generator_agent = LlmAgent(
name="图像生成",
model="gemini-2.0-flash",
description="根据详细的文本提示生成图像。",
instruction=(
"你是一个图像生成专家。你的任务是接收用户的请求 "
"并使用 `generate_image` 工具来创建图像。 "
"用户的整个请求应该作为工具的 'prompt' 参数。 "
"在工具返回图像字节后,你必须输出图像。"
),
tools=[generate_image]
)
# 3. 将修正后的代理封装在 AgentTool 中。
# 这里的描述是父代理所看到的。
image_tool = agent_tool.AgentTool(
agent=image_generator_agent,
description="使用此工具生成图像。输入应该是所需图像的描述性提示。"
)
# 4. 父代理保持不变。其逻辑是正确的。
artist_agent = LlmAgent(
name="艺术家",
model="gemini-2.0-flash",
instruction=(
"你是一位富有创造力的艺术家。首先,为图像构思一个富有创意且描述性的提示。 "
"然后,使用 `图像生成` 工具根据你的提示生成图像。"
),
tools=[image_tool]
)
本章摘要
内容:复杂问题常常超出单一、整体的基于LLM的智能体的能力。一个独立的智能体可能缺乏多样化的专业技能,或者无法访问解决多方面任务所有部分所需的特定工具。这种限制造成了瓶颈,降低了系统的整体有效性和可扩展性。因此,处理复杂的、多领域的目标变得低效,并可能导致不完整或次优的结果。
原因:多智能体协作模式通过创建由多个协作智能体组成的系统,提供了一种标准化解决方案。一个复杂问题被分解成更小、更易于管理的子问题。然后,每个子问题被分配给一个拥有解决该问题所需精确工具和能力的专业智能体。这些智能体通过定义的通信协议和交互模型(如顺序交接、并行工作流或分层委托)协同工作。这种智能体化的分布式方法产生了协同效应,使群体能够实现任何单一智能体都无法实现的结果。
经验法则:当任务对于单个智能体来说过于复杂,并且可以分解为需要专业技能或工具的独立子任务时,请使用此模式。它非常适合需要多样化专业知识、并行处理或多阶段结构化工作流的问题,例如复杂的研究和分析、软件开发或创意内容生成。

要点总结:
- 多智能体协作涉及多个智能体共同努力以实现一个共同目标。
- 这种模式利用专业角色、分布式任务和智能体间通信。
- 协作可以采取顺序交接、并行处理、辩论或分层结构等形式。
- 这种模式非常适合需要多样化专业知识或多个不同阶段的复杂问题。
结论
本章探讨了多智能体协作模式,展示了在系统中编排多个专业智能体的好处。我们研究了各种协作模型,强调了该模式在解决跨领域复杂多方面问题中的重要作用。理解智能体协作自然会引出对其与外部环境交互的探究。
参考文献
- Multi-Agent Collaboration Mechanisms: A Survey of LLMs, https://arxiv.org/abs/2501.06322
- Multi-Agent System — The Power of Collaboration, https://aravindakumar.medium.com/introducing-multi-agent-frameworks-the-power-of-collaboration-e9db31bba1b6
往期回顾
《Agentic Design Patterns:构建智能系统的实战指南》- 第六章 规划
《Agentic Design Patterns:构建智能系统的实战指南》- 第六章 规划
AIGC •来源:煤矿工厂• 2025年10月23日 上午10:39 •技术文章
书籍名称:Agentic Design Patterns: A Hands-On Guide to Building Intelligent Systems
本书作者:Antonio Gulli
链接地址:https://docs.google.com/document/d/18vvNESEwHnVUREzIipuaDNCnNAREGqEfy9MQYC9wb4o
内容摘要:本文是对《智能体设计模式》第六章的翻译。此章节介绍了规划(Planning)在智能体编程中的作用,以及如何结合规划功能进行设计。
翻译:煤矿工厂
概述
智能行为通常不仅仅是对即时输入做出反应。它需要远见,将复杂的任务分解成更小、更易于管理的步骤,并制定策略来实现期望的结果。这就是规划模式发挥作用的地方。规划的核心是代理或代理系统制定一系列行动以从初始状态迈向目标状态的能力。
在人工智能领域,将规划代理视为您委派复杂目标的专家会很有帮助。当您让它“组织一次团队外出活动”时,您定义的是“什么”(目标及其限制),而不是“如何”。代理的核心任务是自主地规划实现该目标的路径。它必须首先了解初始状态(例如,预算、参与者人数、期望日期)和目标状态(成功预订的外出活动),然后发现连接它们的最佳行动序列。计划不是预先知道的;它是根据请求创建的。
这个过程的一个标志是适应性。初始计划仅仅是一个起点,而不是一个僵化的脚本。代理真正的力量在于它能够整合新信息并引导项目避开障碍。例如,如果首选场地不可用或选定的餐饮供应商已满,一个有能力的代理不会简单地失败。它会适应:记录新的限制,重新评估其选项,并制定新的计划,也许通过建议替代场地或日期。
然而,认识到灵活性和可预测性之间的权衡至关重要。动态规划是一种特定的工具,而不是一个通用的解决方案。当一个问题的解决方案已经很好理解并且可重复时,将代理限制在预定的固定工作流程中会更有效。这种方法限制了代理的自主性,以减少不确定性和不可预测行为的风险,从而保证可靠和一致的结果。因此,决定使用规划代理还是简单的任务执行代理,取决于一个问题:需要“如何”被发现,还是它已经已知?
应用和示例
规划模式是自主系统中的核心计算过程,它使智能体能够合成一系列动作以实现特定目标,尤其是在动态或复杂的环境中。在规划模式下,智能体将高级目标转换为由离散、可执行步骤组成的结构化计划。
在程序任务自动化等领域,规划用于协调复杂的工作流程。例如,像新员工入职这样的业务流程可以分解为一系列有向的子任务,例如创建系统账户、分配培训模块以及与不同部门协调。智能体会生成一个计划,以逻辑顺序执行这些步骤,调用必要的工具或与各种系统交互以管理依赖关系。
在机器人技术和自主导航中,规划是状态空间遍历的基础。系统,无论是物理机器人还是虚拟实体,都必须生成路径或动作序列以从初始状态转换到目标状态。这涉及优化时间或能源消耗等指标,同时遵守环境限制,例如避开障碍物或遵守交通法规。
此模式对于结构化信息合成也至关重要。当任务是生成像研究报告这样复杂的输出时,智能体可以制定一个计划,其中包括信息收集、数据汇总、内容结构化和迭代完善等不同阶段。同样,在涉及多步骤问题解决的客户支持场景中,智能体可以创建并遵循一个系统的诊断、解决方案实施和升级计划。
本质上,规划模式允许智能体超越简单的、反应性的动作,转向目标导向的行为。它为解决需要连贯的相互依赖操作序列的问题提供了必要的逻辑框架。
代码示例上手 (Crew AI)
接下来的部分将演示如何使用 Crew AI 框架实现规划器(Planner)模式。这种模式涉及一个智能体,它首先制定一个多步骤计划来解决一个复杂的查询,然后按顺序执行该计划。
import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
from langchain_openai import ChatOpenAI
# 为安全起见,从 .env 文件加载环境变量
load_dotenv()
# 1. 为清晰起见,显式定义语言模型
llm = ChatOpenAI(model="gpt-4-turbo")
# 2. 定义一个清晰且专注的代理
planner_writer_agent = Agent(
role='文章规划师和撰写人',
goal='规划并撰写关于指定主题的简洁、引人入胜的摘要。',
backstory=(
'你是一位专业的科技作家和内容策略师。 '
'你的优势在于在撰写前制定清晰、可行的计划, '
'确保最终的摘要既信息丰富又易于理解。'
),
verbose=True,
allow_delegation=False,
llm=llm # 将特定的LLM分配给代理
)
# 3. 定义一个具有更结构化和具体预期输出的任务
topic = "强化学习在人工智能中的重要性"
high_level_task = Task(
description=(
f"1. 为主题“{topic}”的摘要创建一个要点计划。\n"
f"2. 根据你的计划撰写摘要,保持在200字左右。"
),
expected_output=(
"一份包含两个独立部分的最终报告:\n\n"
"### 计划\n"
"- 一个要点列表,概述摘要的主要内容。\n\n"
"### 摘要\n"
"- 对主题的简洁且结构良好的摘要。"
),
agent=planner_writer_agent,
)
# 创建一个具有明确流程的团队
crew = Crew(
agents=[planner_writer_agent],
tasks=[high_level_task],
process=Process.sequential,
)
# 执行任务
print("## 正在运行规划和撰写任务 ##")
result = crew.kickoff()
print("\n\n---\n## 任务结果 ##\n---")
print(result)
此代码使用 CrewAI 库创建一个人工智能智能体,该智能体负责规划并撰写给定主题的摘要。它首先导入必要的库,包括 CrewAI 和 langchain_openai,并从 .env 文件加载环境变量。一个 ChatOpenAI 语言模型被明确定义用于该智能体。创建了一个名为 planner_writer_agent 的智能体,其具体角色和目标是:先规划,后撰写一份简洁的摘要。该智能体的背景故事强调了其在规划和技术写作方面的专业知识。定义了一个任务,其明确描述是:首先创建一个计划,然后就“强化学习在人工智能中的重要性”这一主题撰写一份摘要,并指定了预期输出的格式。一个 Crew(团队)由该智能体和任务组成,并设置为按顺序处理它们。最后,调用 crew.kickoff() 方法来执行定义的任务并打印结果。
谷歌的 DeepResearch 功能
Google Gemini DeepResearch(见图1)是一个基于代理的系统,专为自主信息检索和合成而设计。它通过一个多步骤的代理管道运行,该管道动态且迭代地查询 Google 搜索,以系统地探索复杂主题。该系统旨在处理大量基于网络的来源,评估所收集数据的相关性和知识空白,并执行后续搜索以解决这些问题。最终输出将经过验证的信息整合为结构化的多页摘要,并引用原始来源。
进一步来说,该系统的操作并非单一的查询-响应事件,而是一个受管理的、长期运行的过程。它首先将用户的提示分解为多点研究计划(见图1),然后将其呈现给用户进行审查和修改。这允许在执行之前协作塑造研究轨迹。一旦计划获得批准,代理管道就会启动其迭代搜索和分析循环。这不仅仅是执行一系列预定义搜索;代理会根据其收集的信息动态地制定和完善其查询,主动识别知识空白、验证数据点并解决差异。

一个关键的架构组件是系统异步管理此过程的能力。这种设计确保了可能涉及分析数百个来源的调查能够抵抗单点故障,并允许用户在完成后脱离并收到通知。该系统还可以整合用户提供的文档,将私人来源的信息与其基于网络的研究相结合。最终输出不仅仅是发现结果的串联列表,而是一个结构化的多页报告。在合成阶段,模型对收集到的信息进行批判性评估,识别主要主题并将内容组织成具有逻辑部分的连贯叙述。该报告旨在具有交互性,通常包括音频概述、图表和原始引用来源的链接等功能,允许用户进行验证和进一步探索。除了合成结果,模型还明确返回其搜索和查阅的完整来源列表(见图2)。这些以引用的形式呈现,提供完全透明度并直接访问主要信息。整个过程将一个简单的查询转化为一个全面的、合成的知识体系。

通过减少手动数据获取和合成所需的大量时间和资源投入,Gemini DeepResearch 提供了一种更结构化、更详尽的信息发现方法。该系统的价值在跨各种领域的复杂、多方面的研究任务中尤为明显。
例如,在竞争分析中,代理可以被指示系统地收集和整理市场趋势、竞争对手产品规格、来自不同在线来源的公众情绪以及营销策略的数据。这种自动化过程取代了手动跟踪多个竞争对手的繁重任务,使分析师能够专注于更高层次的战略解释,而不是数据收集(见图3)。

同样,在学术探索中,该系统是进行广泛文献综述的强大工具。它可以识别和总结基础论文,追踪概念在众多出版物中的发展,并绘制出特定领域内新兴的研究前沿,从而加速学术探究的初始和最耗时的阶段。
这种方法的效率源于迭代搜索和过滤周期的自动化,这是手动研究中的核心瓶颈。通过系统处理比人类研究人员在可比时间内通常可行的更大数量和种类的信息来源的能力,实现了全面性。这种更广泛的分析范围有助于减少选择偏差的可能性,并增加发现不那么明显但可能关键的信息的可能性,从而对主题有更健壮和有充分依据的理解。
OpenAI Deep Research API
OpenAI 深度研究 API 是一种专门工具,旨在自动化复杂的研究任务。它利用先进的代理模型,能够独立推理、规划和综合来自真实世界的信息。与简单的问答模型不同,它接受高级查询,并自主将其分解为子问题,使用其内置工具执行网络搜索,并提供结构化、富含引用的最终报告。该 API 提供对整个过程的直接程序化访问。在撰写本文时,它使用 o3-deep-research-2025-06-26 等模型进行高质量综合,并使用更快的 o4-mini-deep-research-2025-06-26 模型用于对延迟敏感的应用程序。
深度研究 API 非常有用,因为它将原本需要数小时手动研究的工作自动化,提供专业级、数据驱动的报告,适用于为商业策略、投资决策或政策建议提供信息。其主要优势包括:
- 结构化、引用的输出:生成组织良好的报告,其中包含链接到来源元数据的内联引用,确保声明可验证且有数据支持。
- 透明度:与 ChatGPT 中抽象的过程不同,API 公开所有中间步骤,包括代理的推理、其执行的具体网络搜索查询以及它运行的任何代码。这允许进行详细调试与分析,并深入理解最终答案的构建过程。
- 可扩展性:支持模型上下文协议(MCP),使开发人员能够将代理连接到私人知识库和内部数据源,将公共网络研究与专有信息相结合。
要使用 API,您需要向 client.responses.create 端点发送请求,指定模型、输入提示以及代理可以使用的工具。输入通常包括定义代理角色和所需输出格式的 system_message,以及 user_query。您必须包含web_search_preview 工具,并可选择添加其他工具,如 code_interpreter 或自定义 MCP 工具(参见第 10 章)以获取内部数据。
from openai import OpenAI
# 使用您的API密钥初始化客户端
client = OpenAI(api_key="YOUR_OPENAI_API_KEY")
# 定义代理的角色和用户的研究问题
system_message = """您是一位专业的、准备结构化、数据驱动报告的研究员。
专注于数据丰富的见解,使用可靠来源,并包含内联引用。"""
user_query = "研究司美格鲁肽对全球医疗保健系统的经济影响。"
# 创建深度研究API调用
response = client.responses.create(
model="o3-deep-research-2025-06-26",
input=[
{
"role": "developer",
"content": [{"type": "input_text", "text": system_message}]
},
{
"role": "user",
"content": [{"type": "input_text", "text": user_query}]
}
],
reasoning={"summary": "auto"},
tools=[{"type": "web_search_preview"}]
)
# 访问并打印响应中的最终报告
final_report = response.output[-1].content[0].text
print(final_report)
# --- 访问内联引用和元数据 ---
print("--- 引用 ---")
annotations = response.output[-1].content[0].annotations
ifnot annotations:
print("报告中未找到引用。")
else:
for i, citation in enumerate(annotations):
# 引用指向的文本范围
cited_text = final_report[citation.start_index:citation.end_index]
print(f"引用 {i+1}:")
print(f" 被引用文本: {cited_text}")
print(f" 标题: {citation.title}")
print(f" URL: {citation.url}")
print(f" 位置: 字符 {citation.start_index}–{citation.end_index}")
print("\n" + "="*50 + "\n")
# --- 检查中间步骤 ---
print("--- 中间步骤 ---")
# 1. 推理步骤:模型生成的内部计划和摘要。
try:
reasoning_step = next(item for item in response.output if item.type == "reasoning")
print("\n[找到推理步骤]")
for summary_part in reasoning_step.summary:
print(f" - {summary_part.text}")
except StopIteration:
print("\n未找到推理步骤。")
# 2. 网页搜索调用:代理执行的确切搜索查询。
try:
search_step = next(item for item in response.output if item.type == "web_search_call")
print("\n[找到网页搜索调用]")
print(f" 执行的查询: '{search_step.action['query']}'")
print(f" 状态: {search_step.status}")
except StopIteration:
print("\n未找到网页搜索步骤。")
# 3. 代码执行:代理使用代码解释器运行的任何代码。
try:
code_step = next(item for item in response.output if item.type == "code_interpreter_call")
print("\n[找到代码执行步骤]")
print(" 代码输入:")
print(f" ```python\n{code_step.input}\n ```")
print(" 代码输出:")
print(f" {code_step.output}")
except StopIteration:
print("\n未找到代码执行步骤。")
此代码片段利用 OpenAI API 执行“深度研究”任务。它首先使用您的 API 密钥初始化 OpenAI 客户端(这对身份验证至关重要)。然后,将 AI 代理的角色定义为专业研究员,并设置用户关于“司美格鲁肽对全球医疗保健系统的经济影响”的研究问题。该代码构建了对 o3-deep-research-2025-06-26 模型的 API 调用,提供定义的 system_message 和 user_query 作为输入,并请求自动总结推理、启用网页搜索功能。
进行 API 调用后,它提取并打印最终生成的报告。随后,尝试访问并显示报告注释中的内联引用和元数据,包括引用的文本、标题、URL 以及在报告中的位置。最后,它检查并打印模型采取的中间步骤详情,例如推理步骤、网络搜索调用(含执行的查询),以及若使用了代码解释器,则还包括代码执行步骤。
摘要
内容:复杂问题通常无法通过单一行动解决,需要远见才能达到预期结果。如果没有结构化方法,代理系统难以处理涉及多个步骤和依赖项的多方面请求。这使得将高级目标分解为一系列可管理的小型可执行任务变得困难。因此,系统在面对复杂目标时无法有效制定策略,导致结果不完整或不正确。
原因:规划模式通过让代理系统首先创建连贯的计划来解决目标,从而提供标准化解决方案。它涉及将高级目标分解为一系列更小、可操作的步骤或子目标。这使得系统能够管理复杂的工作流程、协调各种工具并按逻辑顺序处理依赖项。大型语言模型(LLM)特别适合此任务,因为它们可以根据其庞大的训练数据生成合理有效的计划。这种结构化方法将简单的反应式代理转变为战略执行者,可以主动实现复杂目标,甚至在必要时调整计划。
经验法则:当用户的请求过于复杂,无法通过单一行动或工具处理时,请使用此模式。它非常适合自动化多步骤流程,例如生成详细研究报告、新员工入职或执行竞争分析。只要任务需要一系列相互依赖的操作才能达到最终的综合结果,就应用规划模式。
总结图示

要点
- 规划使代理能够将复杂目标分解为可操作的顺序步骤。
- 它对于处理多步骤任务、工作流自动化和驾驭复杂环境至关重要。
- LLM 可以根据任务描述生成分步方法来执行规划。
- 明确提示或设计需要规划步骤的任务会鼓励代理框架中的这种行为。
- Google Deep Research 是一个代理,它使用 Google Search 作为工具分析获取的来源,并进行反思、规划和执行。
结论
总之,规划模式是一个基础组件,它将代理系统从简单的反应式响应者提升为战略性、面向目标的执行者。现代大型语言模型(LLM)为此提供了核心能力,能够自主将高级目标分解为连贯、可操作的步骤。这种模式可以从直接的顺序任务执行(如 CrewAI 代理创建和遵循写作计划所展示的)扩展到更复杂和动态的系统。Google DeepResearch 代理就是这种高级应用的典范:它创建迭代研究计划,并根据持续的信息收集进行调整和演变。
最终,规划为复杂问题的人类意图与自动化执行提供了必要的桥梁。通过构建问题解决方法,这种模式使代理能够管理复杂的工作流程并提供全面、综合的结果。
参考文献
- Google DeepResearch (Gemini Feature): gemini.google.com
- OpenAI ,Introducing deep research https://openai.com/index/introducing-deep-research/
- Perplexity, Introducing Perplexity Deep Research, https://www.perplexity.ai/hub/blog/introducing-perplexity-deep-research
往期回顾
《Agentic Design Patterns:构建智能系统的实战指南》- 前言
《Agentic Design Patterns:构建智能系统的实战指南》- 第一章 提示链
《Agentic Design Patterns:构建智能系统的实战指南》- 第二章 路由
《Agentic Design Patterns:构建智能系统的实战指南》- 第三章 并行化
《Agentic Design Patterns:构建智能系统的实战指南》- 第四章 反思
《Agentic Design Patterns:构建智能系统的实战指南》- 第五章 工具使用
《Agentic Design Patterns:构建智能系统的实战指南》- 第六章 规划
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。