22 KiB
22 KiB
第05章:多智能体系统
📌 本章目标
- 理解多智能体系统的设计理念
- 掌握 Agent 层级结构的构建方法
- 学习三种工作流 Agent:Sequential、Parallel、Loop
- 掌握常见多 Agent 协作模式
- 了解 Agent 间的通信机制
5.1 多智能体系统概述
5.1.1 为什么需要多智能体?
当应用变得复杂时,使用单个"巨型"Agent 会面临以下问题:
| 问题 | 说明 |
|---|---|
| 指令膨胀 | 系统指令过长,LLM 难以同时遵循所有规则 |
| 工具过多 | 工具列表过长,LLM 选择工具的准确率下降 |
| 难以维护 | 修改一个功能可能影响其他功能 |
| 难以调试 | 出错时难以定位问题来源 |
多智能体系统通过将复杂任务分解为多个专门的 Agent 来解决这些问题。
5.1.2 ADK 多智能体架构
root_agent(根智能体)
│
┌─────────────┼─────────────┐
│ │ │
LlmAgent SequentialAgent ParallelAgent
(协调器) (顺序流水线) (并行执行器)
│ │ │
┌────┼────┐ ┌────┼────┐ ┌───┴───┐
│ │ │ │ │ │ │ │
Agent Agent Agent Agent Agent Agent Agent
(子1) (子2) (子3) (步骤1)(步骤2)(任务A) (任务B)
5.2 Agent 层级结构
5.2.1 父子关系
"""
Agent 层级结构基础
通过 sub_agents 参数建立父子关系
"""
from google.adk.agents import LlmAgent # 导入 LlmAgent 类
# ========================================
# 第一步:定义叶子节点 Agent(最底层的 Agent)
# ========================================
# 定义一个专门处理问候的 Agent
greeter_agent = LlmAgent(
name="Greeter", # Agent 名称
model="gemini-2.0-flash", # 使用 Gemini 模型
description="负责向用户打招呼和寒暄。", # 描述:用于路由决策
instruction=( # 系统指令
"你是一个友好的问候助手。\n"
"热情地向用户打招呼,并询问有什么可以帮助的。"
),
)
# 定义一个专门处理任务执行的 Agent
task_agent = LlmAgent(
name="TaskExecutor", # Agent 名称
model="gemini-2.0-flash", # 使用 Gemini 模型
description="负责执行用户的具体任务。", # 描述:用于路由决策
instruction=( # 系统指令
"你是一个任务执行助手。\n"
"认真完成用户交给你的任务。"
),
)
# ========================================
# 第二步:定义父 Agent,通过 sub_agents 建立层级
# ========================================
coordinator = LlmAgent(
name="Coordinator", # 父 Agent 名称
model="gemini-2.0-flash", # 使用 Gemini 模型
description="主协调器,负责分配任务。", # 描述
instruction=( # 系统指令
"你是一个协调器。\n"
"根据用户的请求,将任务分配给合适的子 Agent。\n"
"问候和寒暄类请求交给 Greeter。\n"
"具体任务交给 TaskExecutor。\n"
"使用 transfer_to_agent 工具来委派任务。"
),
sub_agents=[ # 🔑 注册子 Agent 列表
greeter_agent, # 问候 Agent
task_agent, # 任务执行 Agent
],
)
# ========================================
# 层级关系说明
# ========================================
# coordinator(父)
# ├── greeter_agent(子)
# └── task_agent(子)
#
# ADK 会自动设置:
# greeter_agent.parent_agent == coordinator
# task_agent.parent_agent == coordinator
#
# 注意:一个 Agent 只能有一个父 Agent
# 尝试将同一个 Agent 添加到多个父 Agent 会抛出 ValueError
5.2.2 多层级嵌套
"""
多层级嵌套的 Agent 结构
构建更复杂的多 Agent 系统
"""
from google.adk.agents import LlmAgent, SequentialAgent # 导入 Agent 类型
# ========================================
# 第三层:具体执行 Agent
# ========================================
code_reviewer = LlmAgent(
name="CodeReviewer", # 代码审查 Agent
model="gemini-2.0-flash", # 模型
description="审查代码质量,提出改进建议。", # 描述
instruction="你是代码审查专家,审查代码并给出改进建议。", # 指令
)
test_writer = LlmAgent(
name="TestWriter", # 测试编写 Agent
model="gemini-2.0-flash", # 模型
description="为代码编写单元测试。", # 描述
instruction="你是测试工程师,为给定的代码编写单元测试。", # 指令
)
# ========================================
# 第二层:开发流水线(顺序执行)
# ========================================
dev_pipeline = SequentialAgent(
name="DevPipeline", # 流水线名称
sub_agents=[ # 按顺序执行子 Agent
code_reviewer, # 先审查代码
test_writer, # 再编写测试
],
)
# ========================================
# 第二层:其他专门 Agent
# ========================================
doc_writer = LlmAgent(
name="DocWriter", # 文档编写 Agent
model="gemini-2.0-flash", # 模型
description="编写技术文档。", # 描述
instruction="你是技术文档工程师,编写清晰的技术文档。", # 指令
)
# ========================================
# 第一层:根 Agent(协调器)
# ========================================
root_agent = LlmAgent(
name="RootCoordinator", # 根协调器
model="gemini-2.0-flash", # 模型
description="开发团队协调器。", # 描述
instruction=( # 指令
"你是一个开发团队协调器。\n"
"代码审查和测试任务交给 DevPipeline。\n"
"文档编写任务交给 DocWriter。"
),
sub_agents=[ # 子 Agent 列表
dev_pipeline, # 开发流水线
doc_writer, # 文档编写
],
)
# 完整层级结构:
# root_agent(根协调器)
# ├── dev_pipeline(开发流水线 - SequentialAgent)
# │ ├── code_reviewer(代码审查)
# │ └── test_writer(测试编写)
# └── doc_writer(文档编写)
5.3 工作流 Agent
5.3.1 SequentialAgent(顺序执行)
"""
SequentialAgent — 顺序执行工作流
子 Agent 按照列表顺序依次执行
适用于数据处理流水线等场景
"""
from google.adk.agents import LlmAgent, SequentialAgent # 导入 Agent 类型
# ========================================
# 定义流水线的各个步骤
# ========================================
# 步骤一:信息提取 Agent
extractor = LlmAgent(
name="Extractor", # 信息提取 Agent
model="gemini-2.0-flash", # 模型
instruction="从用户输入中提取关键信息。只输出提取的关键信息。", # 指令
output_key="extracted_info", # 🔑 将输出保存到 state['extracted_info']
)
# 步骤二:信息分析 Agent
analyzer = LlmAgent(
name="Analyzer", # 信息分析 Agent
model="gemini-2.0-flash", # 模型
instruction=( # 指令:引用上一步的输出
"分析以下提取的信息,给出深度分析报告。\n"
"提取的信息:{extracted_info}" # 通过 {key} 引用 state 中的值
),
output_key="analysis_result", # 将分析结果保存到 state
)
# 步骤三:报告生成 Agent
reporter = LlmAgent(
name="Reporter", # 报告生成 Agent
model="gemini-2.0-flash", # 模型
instruction=( # 指令:引用前两步的输出
"根据分析结果生成一份简洁的报告。\n"
"原始信息:{extracted_info}\n" # 引用提取的信息
"分析结果:{analysis_result}" # 引用分析结果
),
)
# ========================================
# 创建顺序流水线
# ========================================
pipeline = SequentialAgent(
name="InfoPipeline", # 流水线名称
sub_agents=[ # 🔑 按顺序执行
extractor, # 第一步:提取信息
analyzer, # 第二步:分析信息
reporter, # 第三步:生成报告
],
)
# 执行流程:
# 1. Extractor 运行 → 输出保存到 state['extracted_info']
# 2. Analyzer 运行 → 读取 state['extracted_info'] → 输出保存到 state['analysis_result']
# 3. Reporter 运行 → 读取两个 state 值 → 生成最终报告
5.3.2 ParallelAgent(并行执行)
"""
ParallelAgent — 并行执行工作流
子 Agent 同时执行,互不阻塞
适用于多任务同时处理的场景
"""
from google.adk.agents import LlmAgent, ParallelAgent # 导入 Agent 类型
# ========================================
# 定义并行执行的任务
# ========================================
# 任务一:天气查询 Agent
weather_agent = LlmAgent(
name="WeatherFetcher", # 天气查询 Agent
model="gemini-2.0-flash", # 模型
instruction="查询并返回用户指定城市的天气信息。只返回天气数据。", # 指令
output_key="weather_data", # 输出保存到 state['weather_data']
)
# 任务二:新闻查询 Agent
news_agent = LlmAgent(
name="NewsFetcher", # 新闻查询 Agent
model="gemini-2.0-flash", # 模型
instruction="查询并返回用户指定城市的最新新闻。只返回新闻摘要。", # 指令
output_key="news_data", # 输出保存到 state['news_data']
)
# 任务三:交通查询 Agent
traffic_agent = LlmAgent(
name="TrafficFetcher", # 交通查询 Agent
model="gemini-2.0-flash", # 模型
instruction="查询并返回用户指定城市的交通状况。只返回交通信息。", # 指令
output_key="traffic_data", # 输出保存到 state['traffic_data']
)
# ========================================
# 创建并行执行器
# ========================================
gatherer = ParallelAgent(
name="InfoGatherer", # 并行执行器名称
sub_agents=[ # 🔑 这些 Agent 将同时执行
weather_agent, # 天气查询(并行)
news_agent, # 新闻查询(并行)
traffic_agent, # 交通查询(并行)
],
)
# 执行流程:
# 1. WeatherFetcher、NewsFetcher、TrafficFetcher 同时开始执行
# 2. 各自独立运行,互不影响
# 3. 所有 Agent 完成后,后续 Agent 可以读取三个 state 值
#
# 注意事项:
# - 并行 Agent 共享同一个 session.state
# - 使用不同的 output_key 避免数据覆盖
# - 事件(Event)可能交错输出
5.3.3 LoopAgent(循环执行)
"""
LoopAgent — 循环执行工作流
子 Agent 按顺序循环执行,直到满足退出条件
适用于轮询、迭代优化等场景
"""
from google.adk.agents import ( # 导入所需类型
LlmAgent, # LLM 智能体
LoopAgent, # 循环工作流
BaseAgent, # 基础智能体(用于自定义)
)
from google.adk.events import Event, EventActions # 导入事件和事件动作
from google.adk.agents.invocation_context import InvocationContext # 导入调用上下文
from typing import AsyncGenerator # 导入异步生成器类型
# ========================================
# 自定义条件检查 Agent
# ========================================
class QualityChecker(BaseAgent):
"""
质量检查 Agent
检查内容质量是否达标,决定是否继续循环
"""
async def _run_async_impl(
self,
ctx: InvocationContext, # 调用上下文
) -> AsyncGenerator[Event, None]: # 返回异步事件生成器
"""异步执行方法"""
# 从会话状态中获取当前质量分数
quality_score = ctx.session.state.get( # 读取状态
"quality_score", # 状态键名
0, # 默认值
)
# 判断质量是否达标(分数 >= 80 则通过)
is_passed = quality_score >= 80 # 质量阈值
# 生成事件,设置 escalate 标志
# escalate=True 表示退出循环
# escalate=False 表示继续循环
yield Event(
author=self.name, # 事件作者
actions=EventActions(
escalate=is_passed, # 🔑 达标则退出循环
),
content=f"质量分数: {quality_score}, {'通过' if is_passed else '未通过'}",
)
# ========================================
# 内容优化 Agent
# ========================================
content_improver = LlmAgent(
name="ContentImprover", # 内容优化 Agent
model="gemini-2.0-flash", # 模型
instruction=( # 指令
"你是一个内容优化专家。\n"
"根据当前内容的质量分数进行优化。\n"
"优化后评估质量分数(0-100),并更新到 state['quality_score']。"
),
)
# ========================================
# 创建循环执行器
# ========================================
optimizer_loop = LoopAgent(
name="ContentOptimizer", # 循环执行器名称
max_iterations=5, # 🔑 最大循环次数(防止无限循环)
sub_agents=[ # 每次循环依次执行
content_improver, # 第一步:优化内容
QualityChecker(name="Checker"), # 第二步:检查质量
],
)
# 执行流程:
# 迭代1: ContentImprover → Checker(分数<80, 继续)
# 迭代2: ContentImprover → Checker(分数<80, 继续)
# 迭代3: ContentImprover → Checker(分数>=80, 退出)
#
# 退出条件(满足任一即退出):
# 1. QualityChecker 设置 escalate=True
# 2. 达到 max_iterations 上限
5.4 常见多 Agent 协作模式
5.4.1 协调器/调度器模式
"""
协调器/调度器模式(Coordinator/Dispatcher Pattern)
最常用的多 Agent 模式
父 Agent 根据用户请求动态分配任务给子 Agent
"""
from google.adk.agents import LlmAgent # 导入 LlmAgent
# 定义专门的子 Agent
math_agent = LlmAgent(
name="MathExpert", # 数学专家
model="gemini-2.0-flash", # 模型
description="擅长数学计算和统计分析。", # 描述
instruction="你是数学专家,解决数学问题。", # 指令
)
writing_agent = LlmAgent(
name="WritingExpert", # 写作专家
model="gemini-2.0-flash", # 模型
description="擅长文案撰写和内容创作。", # 描述
instruction="你是写作专家,帮助用户撰写内容。", # 指令
)
coding_agent = LlmAgent(
name="CodingExpert", # 编程专家
model="gemini-2.0-flash", # 模型
description="擅长编程和代码调试。", # 描述
instruction="你是编程专家,帮助用户解决编程问题。", # 指令
)
# 定义协调器
coordinator = LlmAgent(
name="Coordinator", # 协调器
model="gemini-2.0-flash", # 模型
description="根据问题类型分配给合适的专家。", # 描述
instruction=( # 指令
"你是一个任务协调器。\n"
"根据用户的问题类型,将任务分配给合适的专家:\n"
"- 数学相关 → MathExpert\n"
"- 写作相关 → WritingExpert\n"
"- 编程相关 → CodingExpert\n"
"使用 transfer_to_agent 工具进行任务分配。"
),
sub_agents=[ # 注册所有专家 Agent
math_agent, # 数学专家
writing_agent, # 写作专家
coding_agent, # 编程专家
],
)
5.4.2 评审/批评模式(Generator-Critic)
"""
评审/批评模式(Generator-Critic Pattern)
生成器创建内容,评审器评估并给出改进建议
通过 LoopAgent 实现迭代优化
"""
from google.adk.agents import LlmAgent, LoopAgent, BaseAgent # 导入类型
from google.adk.events import Event, EventActions # 导入事件类型
from google.adk.agents.invocation_context import InvocationContext # 导入上下文
from typing import AsyncGenerator # 导入异步生成器
# 生成器 Agent:创建初稿
generator = LlmAgent(
name="Generator", # 生成器
model="gemini-2.0-flash", # 模型
instruction=( # 指令
"你是一个创意写手。\n"
"根据用户需求创作内容。\n"
"将创作的内容保存到 state['draft']。"
),
output_key="draft", # 输出保存到 state['draft']
)
# 评审器 Agent:评估内容质量
critic = LlmAgent(
name="Critic", # 评审器
model="gemini-2.0-flash", # 模型
instruction=( # 指令
"你是一个严格的内容评审。\n"
"评审以下内容,给出评分(1-10)和改进建议。\n"
"当前草稿:{draft}\n"
"如果评分 >= 8,将 state['approved'] 设为 True。\n"
"否则,将改进建议保存到 state['feedback']。"
),
)
# 条件检查 Agent:决定是否继续循环
class ApprovalChecker(BaseAgent):
"""检查内容是否通过审批"""
async def _run_async_impl(
self,
ctx: InvocationContext, # 调用上下文
) -> AsyncGenerator[Event, None]: # 返回事件生成器
"""执行检查"""
approved = ctx.session.state.get("approved", False) # 获取审批状态
yield Event( # 生成事件
author=self.name, # 事件作者
actions=EventActions(
escalate=approved, # 通过则退出循环
),
)
# 创建迭代优化循环
review_loop = LoopAgent(
name="ReviewLoop", # 循环名称
max_iterations=3, # 最多迭代3次
sub_agents=[ # 循环体
critic, # 第一步:评审
ApprovalChecker(name="Checker"), # 第二步:检查是否通过
generator, # 第三步:如果未通过,重新生成
],
)
# 执行流程:
# 1. Generator 创建初稿 → state['draft']
# 2. Critic 评审 → 评分 < 8 → state['feedback']
# 3. Checker → approved=False → 继续循环
# 4. Generator 根据反馈修改 → state['draft']
# 5. Critic 再次评审 → 评分 >= 8 → state['approved']=True
# 6. Checker → approved=True → 退出循环
5.5 Agent 间通信机制
5.5.1 共享状态(Shared State)
"""
Agent 间通过共享状态通信
最基础、最常用的通信方式
"""
from google.adk.agents import LlmAgent, SequentialAgent # 导入类型
# Agent A:收集信息
collector = LlmAgent(
name="Collector", # 信息收集 Agent
model="gemini-2.0-flash", # 模型
instruction="收集用户需求信息。", # 指令
output_key="user_requirements", # 输出保存到 state
)
# Agent B:基于 Agent A 的输出进行设计
designer = LlmAgent(
name="Designer", # 设计 Agent
model="gemini-2.0-flash", # 模型
instruction=( # 指令:引用 Agent A 的输出
"根据用户需求进行系统设计。\n"
"用户需求:{user_requirements}" # 通过 {key} 引用
),
output_key="design_doc", # 输出保存到 state
)
# Agent C:基于 Agent B 的输出进行评审
reviewer = LlmAgent(
name="Reviewer", # 评审 Agent
model="gemini-2.0-flash", # 模型
instruction=( # 指令:引用 Agent A 和 B 的输出
"评审系统设计文档。\n"
"用户需求:{user_requirements}\n" # 引用需求
"设计文档:{design_doc}" # 引用设计
),
)
# 创建流水线
pipeline = SequentialAgent(
name="DesignPipeline", # 流水线名称
sub_agents=[collector, designer, reviewer], # 顺序执行
)
5.5.2 通信机制对比
| 机制 | 说明 | 适用场景 |
|---|---|---|
| 共享 State | 通过 session.state 读写数据 |
顺序流水线、数据传递 |
| output_key | 自动将输出保存到 State | 简单的数据传递 |
| LLM Transfer | LLM 动态决定委派给哪个 Agent | 灵活的任务路由 |
| AgentTool | 将 Agent 作为工具调用 | Agent 复用 |
| temp: State | 临时状态,当前调用有效 | 工具间数据传递 |
📌 本章小结
- 多智能体系统通过
sub_agents参数建立层级关系 - SequentialAgent:子 Agent 按顺序执行,适合流水线
- ParallelAgent:子 Agent 并行执行,适合多任务同时处理
- LoopAgent:子 Agent 循环执行,适合迭代优化
- Agent 间通信主要通过共享 State 和 LLM Transfer
output_key是最简单的数据传递方式
下一章:第06章 - 会话与状态管理 → 深入了解会话和状态管理机制。