高级特性:Plan 和 Sub-Agent 的妙用
学习如何使用 Plan 和 Sub-Agent 处理复杂任务,实现任务拆分和并行执行。
高级特性:Plan 和 Sub-Agent 的妙用
前言
在前面的文章中,我们学习了 Agent4J 的基础功能。现在让我们看看两个高级特性:Plan 和 Sub-Agent。
这两个特性让 Agent 能处理更复杂的任务:
- Plan:把复杂任务拆分成多个步骤,按顺序执行
- Sub-Agent:生成子 Agent,并行处理独立的子任务
就像一个项目经理,既能制定计划,又能分配任务给团队成员。
Plan:任务计划
什么是 Plan?
当任务比较复杂时,Agent 会自动创建一个执行计划。计划包含多个步骤,每个步骤都是一个独立的 LLM 调用。
agent.createSession()
.command("请帮我创建一个完整的电商系统,包括用户管理、商品管理、订单管理三个模块")
.then(new AgentResultHandler() {
public void onPlanCreated(Plan plan) {
System.out.println("创建了计划,共 " + plan.getSteps().size() + " 步");
}
public void onPlanStepStart(Plan plan, int current, int total, String step) {
System.out.println("开始执行第 " + current + " 步:" + step);
}
public void onPlanStepComplete(Plan plan, int current, int total, String step, String result) {
System.out.println("完成第 " + current + " 步");
}
})
.error(e -> e.printStackTrace());
Plan 的工作流程
- 分析任务:LLM 分析任务,决定是否需要创建计划
- 创建计划:如果需要,LLM 调用
create_plan工具 - 执行步骤:框架按顺序执行每个步骤
- 反馈结果:每个步骤的结果会反馈给 LLM
- 调整计划:LLM 可能会根据结果调整后续步骤
什么时候会创建 Plan?
LLM 会根据任务的复杂度自动决定是否创建 Plan:
- 简单任务:直接执行,不需要计划
- 复杂任务:创建计划,分步骤执行
- 非常复杂的任务:创建计划,每个步骤可能还会创建子计划
Plan 的回调
session.command(task).then(new AgentResultHandler() {
// 计划创建时
public void onPlanCreated(Plan plan) {
System.out.println("计划创建,步骤数:" + plan.getSteps().size());
}
// 计划开始执行时
public void onPlanExecuted(Plan plan) {
System.out.println("开始执行计划");
}
// 每个步骤开始时
public void onPlanStepStart(Plan plan, int current, int total, String step) {
System.out.println("步骤 " + current + "/" + total + ":" + step);
}
// 每个步骤完成时
public void onPlanStepComplete(Plan plan, int current, int total, String step, String result) {
System.out.println("步骤 " + current + " 完成,结果:" + result);
}
// 步骤中调用工具时
public void onPlanStepTool(Plan plan, ToolDescriptor tool, ToolStatus status) {
System.out.println("调用工具:" + tool.getName());
}
// 步骤执行失败时
public void onPlanStepError(Plan plan, int current, int total, String step, Exception error) {
System.out.println("步骤 " + current + " 失败:" + error.getMessage());
}
});
Plan 的实际例子
例子 1:创建项目结构
session.command("""
请创建一个 Spring Boot 项目,要求:
1. 创建 Maven 项目结构
2. 创建 pom.xml,包含必要的依赖
3. 创建主应用类
4. 创建配置文件
5. 创建示例 Controller
""");
Agent 可能会创建这样的计划:
- 创建目录结构
- 生成 pom.xml
- 创建 Application.java
- 创建 application.properties
- 创建 HelloController.java
例子 2:代码重构
session.command("""
请重构 UserService 类:
1. 提取公共方法到 BaseService
2. 使用策略模式重构状态处理
3. 添加单元测试
4. 更新文档
""");
例子 3:数据分析
session.command("""
请分析 sales.csv 文件:
1. 读取文件,了解数据结构
2. 清洗数据,处理缺失值
3. 统计每月销售额
4. 生成趋势图表
5. 输出分析报告
""");
Sub-Agent:子 Agent
什么是 Sub-Agent?
当任务中有多个独立的子任务时,Agent 可以生成子 Agent 来并行处理。
session.command("""
请同时分析这三个文件:
1. UserController.java
2. OrderController.java
3. ProductController.java
告诉我每个 Controller 的功能和潜在问题。
""");
Agent 可能会生成三个子 Agent,每个负责分析一个文件。
Sub-Agent 的工作流程
- 识别子任务:LLM 识别出可以并行处理的子任务
- 生成子 Agent:LLM 调用
create_sub_agent工具 - 分配任务:每个子 Agent 负责一个子任务
- 并行执行:子 Agent 独立执行任务
- 汇总结果:父 Agent 汇总所有子 Agent 的结果
Sub-Agent 的回调
session.command(task).then(new AgentResultHandler() {
// 子 Agent 创建时
public void onSubAgent(AgentClient agent, String message) {
System.out.println("生成子 Agent:" + agent.getName());
System.out.println("任务描述:" + message);
}
// 子 Agent 开始执行时
public void onSubAgentStart(AgentClient agent, String task) {
System.out.println("子 Agent 开始执行:" + task);
}
// 子 Agent 返回结果时
public void onSubAgentResult(AgentClient agent, String result) {
System.out.println("子 Agent 完成,结果:" + result);
}
});
Sub-Agent 的实际例子
例子 1:并行文件分析
session.command("""
请分析以下三个日志文件,找出错误信息:
1. /var/log/app1.log
2. /var/log/app2.log
3. /var/log/app3.log
""");
例子 2:并行数据处理
session.command("""
请处理以下三个 CSV 文件:
1. users.csv - 提取用户信息
2. orders.csv - 提取订单信息
3. products.csv - 提取商品信息
最后合并成一个完整的数据集。
""");
例子 3:并行代码生成
session.command("""
请同时生成以下三个模块的代码:
1. 用户管理模块(entity、dao、service、controller)
2. 订单管理模块(entity、dao、service、controller)
3. 商品管理模块(entity、dao、service、controller)
""");
Plan vs Sub-Agent
什么时候用 Plan,什么时候用 Sub-Agent?
用 Plan 的场景
- 任务有依赖关系:后续步骤依赖前面步骤的结果
- 需要严格控制顺序:比如先创建数据库,再创建表
- 需要人工干预:某些步骤需要人工确认
步骤 1 → 步骤 2 → 步骤 3 → 步骤 4
↓ ↓ ↓ ↓
结果 1 结果 2 结果 3 结果 4
用 Sub-Agent 的场景
- 子任务相互独立:不依赖其他子任务的结果
- 可以并行处理:同时执行可以提高效率
- 任务性质相似:都是同类型的任务
主任务
/ | \
/ | \
子任务1 子任务2 子任务3
↓ ↓ ↓
结果1 结果2 结果3
\ | /
\ | /
汇总结果
组合使用
在实际应用中,Plan 和 Sub-Agent 可以组合使用:
session.command("""
请帮我完成以下任务:
第一阶段:数据准备
1. 读取原始数据文件
2. 清洗数据
3. 生成三个子数据集
第二阶段:并行分析(使用 Sub-Agent)
4. 分析用户行为数据
5. 分析销售趋势数据
6. 分析库存变化数据
第三阶段:报告生成
7. 汇总分析结果
8. 生成可视化图表
9. 输出最终报告
""");
在这个例子中:
- 第一阶段和第三阶段用 Plan(有依赖关系)
- 第二阶段用 Sub-Agent(可以并行)
实际案例:自动化部署
让我们看一个更复杂的例子:自动化部署。
session.command("""
请帮我完成以下部署任务:
1. 检查代码是否有未提交的更改
2. 运行单元测试
3. 构建项目(mvn clean package)
4. 生成 Docker 镜像
5. 并行部署到三个环境:
- 开发环境(dev.example.com)
- 测试环境(test.example.com)
- 预发布环境(staging.example.com)
6. 验证部署是否成功
7. 发送部署通知邮件
""");
Agent 的执行计划:
Plan:
├── Step 1: 检查代码状态
├── Step 2: 运行测试
├── Step 3: 构建项目
├── Step 4: 生成 Docker 镜像
├── Step 5: 并行部署(Sub-Agent)
│ ├── Sub-Agent 1: 部署到 dev
│ ├── Sub-Agent 2: 部署到 test
│ └── Sub-Agent 3: 部署到 staging
├── Step 6: 验证部署
└── Step 7: 发送通知
性能考虑
Plan 的性能
Plan 的每个步骤都是一个独立的 LLM 调用,所以:
- 步骤越多,耗时越长
- 每个步骤都会消耗 Token
- 复杂的计划可能需要几分钟
Sub-Agent 的性能
Sub-Agent 可以并行执行,所以:
- 可以显著提高效率
- 但会增加并发请求
- 需要考虑 API 限流
最佳实践
- 合理拆分任务:不要拆得太细,也不要太粗
- 识别并行机会:能并行的就并行
- 避免不必要的步骤:每个步骤都要有价值
- 监控执行过程:通过回调了解进度
错误处理
Plan 的错误处理
如果某个步骤失败,Agent 会:
- 记录错误信息
- 尝试修复问题
- 如果无法修复,可能会跳过该步骤
- 继续执行后续步骤
session.command(task).then(new AgentResultHandler() {
public void onPlanStepError(Plan plan, int current, int total, String step, Exception error) {
System.out.println("步骤 " + current + " 失败:" + error.getMessage());
// Agent 会尝试自动修复
}
});
Sub-Agent 的错误处理
如果某个子 Agent 失败,父 Agent 会:
- 记录错误信息
- 继续等待其他子 Agent 完成
- 汇总成功的结果
- 报告失败的子任务
总结
Plan 和 Sub-Agent 是 Agent4J 的两个强大特性:
- Plan:把复杂任务拆分成步骤,按顺序执行
- Sub-Agent:并行处理独立的子任务,提高效率
合理使用这两个特性,可以让 Agent 处理更复杂的任务,提高执行效率。
在下一篇文章中,我们将学习会话管理与持久化。
项目地址:https://github.com/onlyGuo/agent4j
下一篇:会话管理与持久化:保存和恢复对话