【AI Agent 全栈开发】Agents

🚀 欢迎来到我的CSDN博客:Optimistic _ chen
✨ 一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!
🚀我的专栏推荐:
| 专栏 | 内容特色 | 适合人群 |
|---|---|---|
| 🔥C语言从入门到精通 | 系统讲解基础语法、指针、内存管理、项目实战 | 零基础新手、考研党、复习 |
| 🔥Java基础语法 | 系统解释了基础语法、类与对象、继承 | Java初学者 |
| 🔥Java核心技术 | 面向对象、集合框架、多线程、网络编程、新特性解析 | 有一定语法基础的开发者 |
| 🔥Java EE 进阶实战 | Servlet、JSP、SpringBoot、MyBatis、项目案例拆解 | 想快速入门Java Web开发的同学 |
| 🔥Java数据结构与算法 | 图解数据结构、LeetCode刷题解析、大厂面试算法题 | 面试备战、算法爱好者、计算机专业学生 |
| 🔥Redis系列 | 从数据类型到核心特性解析 | 项目必备 |
🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例
✅ 持续更新:专栏内容定期更新,紧跟技术趋势
✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)
🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨
📌 标签:#技术博客 #编程学习 #Java #C语言 #算法 #程序员
Agent 简述
Agent(智能体)是一个能够感知环境输入、自主决策、规划行动路径,并可调用工具或执行操作以达成目标的自主性软件实体,核心就是由⼤语⾔模型(LLM)动态控制流程⾛向
简单来说:LLM是大脑,Agent是执行大脑发出指令的“手脚”。
Agents:通常由多个Agent组成的协作系统共同处理复杂指令,实现各司其职、高效配合的目标,也被称为多智能体系统
Chain Workflow(链式工作流)
链式工作流模式是一种将复杂的任务分解为多个"有序,依赖性强"的子任务,每个步骤由一个独立处理单元完成,前一步的输出作为下一步的输入,最终形成一条"数据流动的链条"。
链式处理的主要目的是:当任务可解析为多个子步骤时,通过分布降低单次推理难度,提升准确率。
Spring AI 链式工作流
下面是一个基于 Spring AI 的链式工作流示例,实现"用户问题 → 意图识别 → 信息提取 → 答案生成"的三步链式处理:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.util.Map;
/**
* Spring AI 链式工作流示例
* 将复杂任务拆解为:意图识别 → 信息提取 → 答案生成 三个有序步骤
*/
@Service
public class ChainWorkflowService {
private final ChatClient chatClient;
public ChainWorkflowService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
/**
* 执行链式工作流
*
* @param userInput 用户原始输入
* @return 最终生成的答案
*/
public String executeChain(String userInput) {
// 步骤1:意图识别 —— 判断用户想做什么
String intent = identifyIntent(userInput);
System.out.println("【步骤1】意图识别结果: " + intent);
// 步骤2:信息提取 —— 从用户输入中提取关键参数
String extractedInfo = extractInformation(userInput, intent);
System.out.println("【步骤2】提取的关键信息: " + extractedInfo);
// 步骤3:答案生成 —— 基于意图和提取的信息生成最终回答
String finalAnswer = generateAnswer(intent, extractedInfo);
System.out.println("【步骤3】最终答案: " + finalAnswer);
return finalAnswer;
}
/**
* 步骤1:意图识别
*/
private String identifyIntent(String userInput) {
String prompt = """
请分析以下用户输入,判断其意图类别(仅返回一个词):
- QUERY:查询/询问信息
- CODE:需要编写代码
- EXPLAIN:需要解释概念
- OTHER:其他
用户输入:{input}
意图类别:
""";
return chatClient.prompt(new PromptTemplate(prompt, Map.of("input", userInput)))
.call()
.content();
}
/**
* 步骤2:信息提取
*/
private String extractInformation(String userInput, String intent) {
String prompt = """
用户输入:{input}
意图:{intent}
请根据上述意图,从用户输入中提取关键信息(实体、参数、约束条件等),
以简洁的要点形式返回。
""";
return chatClient.prompt(new PromptTemplate(prompt, Map.of(
"input", userInput,
"intent", intent
))).call().content();
}
/**
* 步骤3:答案生成
*/
private String generateAnswer(String intent, String extractedInfo) {
String prompt = """
你是一个智能助手。
意图:{intent}
关键信息:{info}
请基于以上信息,生成准确、详细的回答。
""";
return chatClient.prompt(new PromptTemplate(prompt, Map.of(
"intent", intent,
"info", extractedInfo
))).call().content();
Parallelization Workflow(并⾏化⼯作流)
并行化工作流模式是一种通过并发执行多个独立的LLM调用,并在完成后自动聚合结果的处理模式。
并行意味着多个LLM调用同时进行,而不是串行执行
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
* 并行化工作流实现类
* 用于并发执行多个LLM调用并聚合结果
*/
public class ParallelizationWorkflow {
// 聊天客户端,用于与LLM交互
private final ChatClient chatClient;
/**
* 构造函数
* @param chatClient 聊天客户端实例
*/
public ParallelizationWorkflow(ChatClient chatClient) {
this.chatClient = chatClient;
}
/**
* 并行处理多个输入
* @param prompt 提示词模板
* @param inputs 输入数据列表
* @param nWorkers 工作线程数
* @return 处理结果列表,顺序与输入列表一致
*/
public List<String> parallel(String prompt, List<String> inputs, int nWorkers) {
// 参数校验
Assert.notNull(prompt, "Prompt cannot be null");
Assert.notEmpty(inputs, "Inputs list cannot be empty");
Assert.isTrue(nWorkers > 0, "Number of workers must be greater than 0");
// 创建固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(nWorkers);
try {
// 为每个输入创建异步任务
List<CompletableFuture<String>> futures = inputs.stream()
.map(input -> CompletableFuture.supplyAsync(() -> {
try {
// 构建完整提示词并调用LLM
String fullPrompt = prompt + "\nInput:" + input;
return chatClient.prompt(fullPrompt).call().content();
} catch (Exception e) {
// 异常处理:包装并抛出运行时异常
throw new RuntimeException("Failed to process input: " + input, e);
}
}, executor)) // 指定线程池执行
.collect(Collectors.toList()); // 收集所有Future
// 等待所有任务完成
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
allFutures.join(); // 阻塞直到所有任务完成
// 提取所有任务的结果
return futures.stream()
.map(CompletableFuture::join) // 获取每个任务的结果
.collect(Collectors.toList()); // 收集为列表
} finally {
// 确保线程池被关闭
executor.shutdown();
}
}
}
- 对inputs列表中的每一个元素:使用
CompletableFuture.supplyAsync(...)在线程池中提交一个异步任务,每个任务都会:
- 组合完整提示:
prompt+"\nInput:"+input; - 调用chatClient发起请求到LLM
- 获取响应内容.content()
- 返回结果,若失败则包装为RuntimeException
- 等等所有任务完成
- 收集结果,并保持顺序,最终返回一个与原始输入顺序完全一致的结果列表
总结:并⾏化⼯作流就是把⼀个⼤任务拆成多个⼩任务,让多个LLM调⽤同时运⾏,最后由程序⾃动把结果合并起来,从⽽实现⾼效、智能、可扩展
Routing Workflow(路由工作流)
路由工作流模式实现了智能任务分发,能够根据不同类型的输入进行专业化处理。
核心:根据输入内容的类型或特征,自动将任务"路由"到最合适处理它的子系统或模块。
类似于医院的导医台,在挂号的时候,不同的病症知道该去适合治疗的科室。这个导医台就是程序中的LLM。
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* Spring AI 路由工作流示例
* 根据输入内容类型自动路由到不同的处理模块
*/
@Service
public class RoutingWorkflowService {
private final ChatClient chatClient;
public RoutingWorkflowService(ChatClient chatClient) {
this.chatClient = chatClient;
}
/**
* 执行路由工作流
*
* @param userInput 用户原始输入
* @return 路由到对应模块处理后的结果
*/
public String executeRouting(String input,Map<String,String> routes) {
Assert.notNull(input,"输入文本不能为空");
Assert.notEmpty(routers,"路由表映射不能为空");
// 步骤1:路由决策 —— 判断输入应该由哪个模块处理
String routeKey = determineRoute(input);
//获取对应的专业提示词
String selectedPrompt=routes.get(routKey);
if(selectedPrompt==null){
throw new IllegalArgumentException("选中的路由"+routeKey+"在路由表中未定义");
}
return chatClient.prompt(selectedPrompt+"\n输入内容:\n"+input).call().content();
}
/**
* 步骤1:路由决策 - 判断输入类型
*/
private String determineRoute(String userInput,Iterable<String> availableRoutes) {
String selectorPrompt = String.format("""
请分析以下用户输入,判断其最适合由哪个模块处理:%s:
说明你的判断理由,然后以如下JSON格式输出结果:
{
“reasoning”:"简要解释为何分配给该团队,考虑关键词、用户意图和紧急程度",
"selection":“所选团队的名称”
}
用户请求:%s
""",availableRoutes,userInput);
RoutingResponse response=chatClient.prompt(selectorPrompt)
.call()
.entity(RoutingResponse.class);
return response.selection();
测试
import java.util.List;
import java.util.Map;
@Configuration
public class RoutingWorkflowTest {
@Bean
public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
return args -> {
// 定义四个简单明了的处理路线(更短的提示词)
Map<String, String> simpleRoutes = Map.of(
"财务",
"你是财务助手,请回答账单、扣费、退款等问题。开头写【财务】。",
"技术",
"你是技术支持,请回答登录、功能使用、系统错误等问题。开头写【技术】。",
"账户",
"你是账户助手,请处理账号找回、密码重置、安全验证等问题。开头写【账户】。",
"产品",
"你是产品顾问,请回答功能咨询、如何使用、推荐操作等问题。开头写【产品】。"
);
// 模拟三个非常简短的用户提问(贴近日常对话)
List<String> simpleTickets = List.of(
"我忘记密码了,登不进去账号", // → 应路由到"账户"
"上个月怎么多扣了50块钱?", // → 应路由到"财务"
"导出数据的功能在哪?怎么用?" // → 应路由到"产品"
);
var routerWorkflow = new RoutingWorkflow(chatClientBuilder.build());
System.out.println("🚀 开始路由工作流测试");
System.out.println("=".repeat(50));
int i = 1;
for (String ticket : simpleTickets) {
System.out.println("\n💬 问题 " + i++);
System.out.println("-".repeat(30));
System.out.println("用户提问: " + ticket);
System.out.println("-".repeat(30));
String response = routerWorkflow.route(ticket, simpleRoutes);
System.out.println("AI回复: " + response);
// 验证路由结果
String expectedRoute = switch (ticket) {
case "我忘记密码了,登不进去账号" -> "账户";
case "上个月怎么多扣了50块钱?" -> "财务";
case "导出数据的功能在哪?怎么用?" -> "产品";
default -> "未知";
};
if (response.contains("【" + expectedRoute + "】")) {
System.out.println("✅ 路由正确: " + expectedRoute);
} else {
System.out.println("❌ 路由可能错误,预期: " + expectedRoute);
}
}
};
}
}
适合输入任务具有明显不同的类别,不同类别的任务需要不同的处理逻辑,这些任务差异很大,如果让同一个LLM去处理,很容易出错;但是通过路由模式,可以让每个任务由最擅长的Agent
Orchestrator-Workers(编排器工作者模式)
Orchestrator-Workers 模式是一种用于处理复杂、动态任务的 AI 系统架构,其核心思想是:
- Orchestrator(编排器):负责分析任务,动态分解为多个子任务,并协调执行。
- Workers(工作者):并行处理各自的子任务,每个 Worker 专注于特定领域或视角。
- 结果聚合:将所有 Worker 的输出整合为最终响应。
该模式适用于无法预先确定子任务、需要多角度解决方案或自适应问题解决的场景。例如:学校举办一场活动,需要通知各学院、活动准备人员、工作人员、招聘志愿者和活动人员等,需要解决各种问题。
/**
* Orchestrator-Workers 模式实现
* 负责将复杂任务分解为多个子任务,并行处理并聚合结果
*/
public class OrchestratorWorkers {
private final ChatClient chatClient;
private final String orchestratorPrompt;
private final String workerPrompt;
private final ExecutorService executorService;
// 默认编排器提示词
public static final String DEFAULT_ORCHESTRATOR_PROMPT = """
请分析以下任务,并将其分解为2-3种不同的写作风格或视角:
任务:{task}
要求:
1. 解释你对该任务的理解
2. 不同写法应服务于不同受众或使用场景
3. 每个子任务需明确类型与具体描述
以如下 JSON 格式返回结果:
{
"analysis": "简要说明你的理解,以及为何这些角度有价值",
"tasks": [
{
"type": "专业",
"description": "用正式、技术性强的语言突出产品参数和认证标准"
},
{
"type": "通俗易懂",
"description": "用生活化语言讲故事,强调使用体验和情感共鸣"
}
]
}
""";
// 默认工作者提示词
public static final String DEFAULT_WORKER_PROMPT = """
请根据以下要求撰写内容:
原始任务:{original_task}
写作风格:{task_type}
具体要求:{task_description}
输出要求:语言流畅自然,适合发布。
""";
/**
* 表示由编排器生成的一个子任务
* @param type 风格类型,如"专业"、"亲民"
* @param description 子任务的具体说明
*/
public static record Task(String type, String description) {
}
/**
* 编排器的响应:包含对任务的理解和子任务列表
* @param analysis 任务分析说明
* @param tasks 拆分出的多个子任务
*/
public static record OrchestratorResponse(String analysis, List<Task> tasks) {
}
/**
* 最终输出结果
* @param analysis 编排器的任务理解
* @param workerResponses 各工作者的输出结果
*/
public static record FinalResponse(String analysis, List<String> workerResponses) {
}
/**
* 使用默认提示词创建实例
* @param chatClient ChatClient 实例
*/
public OrchestratorWorkers(ChatClient chatClient) {
this(chatClient, DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT);
}
/**
* 使用自定义提示词创建实例
* @param chatClient ChatClient 实例
* @param orchestratorPrompt 编排器提示词
* @param workerPrompt 工作者提示词
*/
public OrchestratorWorkers(ChatClient chatClient, String orchestratorPrompt, String workerPrompt) {
Assert.notNull(chatClient, "ChatClient 不能为空");
Assert.hasText(orchestratorPrompt, "编排器提示词不能为空");
Assert.hasText(workerPrompt, "工作者提示词不能为空");
this.chatClient = chatClient;
this.orchestratorPrompt = orchestratorPrompt;
this.workerPrompt = workerPrompt;
this.executorService = Executors.newFixedThreadPool(3); // 创建线程池用于并行处理
}
/**
* 执行"编排-协作"工作流:
* 1. 编排器分析任务 → 拆分为多视角子任务
* 2. 多个工作者并行处理各自风格的内容
* 3. 聚合所有结果
*
* @param taskDescription 主任务描述
* @return 包含分析过程和最终输出的结果
*/
@SuppressWarnings("null")
public FinalResponse process(String taskDescription) {
Assert.hasText(taskDescription, "任务描述不能为空");
try {
// Step 1: 编排器分析任务结构
OrchestratorResponse orchestratorResponse = analyzeTask(taskDescription);
// Step 2: 并行执行每个子任务
List<String> workerResponses = executeTasksInParallel(taskDescription, orchestratorResponse.tasks());
// Step 3: 返回最终结果
return new FinalResponse(orchestratorResponse.analysis(), workerResponses);
} catch (Exception e) {
System.err.println("处理任务时发生错误: " + e.getMessage());
e.printStackTrace();
throw new RuntimeException("任务处理失败: " + e.getMessage(), e);
}
}
/**
* 分析任务并拆分子任务
* @param taskDescription 任务描述
* @return 编排器响应
*/
private OrchestratorResponse analyzeTask(String taskDescription) {
OrchestratorResponse response = this.chatClient.prompt()
.user(u -> u.text(this.orchestratorPrompt)
.param("task", taskDescription))
.call()
.entity(OrchestratorResponse.class);
System.out.println(String.format("\n=== 编排器决策 ===\n分析: %s\n\n拆分任务: %s\n",
response.analysis(), response.tasks()));
return response;
}
/**
* 并行执行所有子任务
* @param originalTask 原始任务
* @param tasks 子任务列表
* @return 工作者响应列表
*/
private List<String> executeTasksInParallel(String originalTask, List<Task> tasks) {
List<CompletableFuture<String>> futures = tasks.stream()
.map(task -> CompletableFuture.supplyAsync(() ->
executeSingleTask(originalTask, task), executorService))
.collect(Collectors.toList());
// 等待所有任务完成
return futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
/**
* 执行单个子任务
* @param originalTask 原始任务
* @param task 子任务
* @return 工作者响应
*/
private String executeSingleTask(String originalTask, Task task) {
String response = this.chatClient.prompt()
.user(u -> u.text(this.workerPrompt)
.param("original_task", originalTask)
.param("task_type", task.type())
.param("task_description", task.description()))
.call()
.content();
System.out.println(String.format("工作者[%s] 处理完成,输出长度: %d",
task.type(), response.length()));
return response;
}
/**
* 关闭线程池资源
*/
public void shutdown() {
if (executorService != null && !executorService.isShutdown()) {
executorService.shutdown();
System.out.println("OrchestratorWorkers 线程池已关闭");
}
}
/**
* 使用 try-with-resources 风格的关闭方法
*/
public void close() {
shutdown();
}
}
Orchestrator-Workers 模式本质上就是⼀个最简单的Multi-Agent架构
评估-优化循环模式
Evaluator-Optimizer 模式(简称EO模式)是一种在大模型系统中实现迭代质量提升的闭环架构设计模式。
该模式通过两个主要组件:
- 评估器(Evaluator):对当前输出进行多维度的质量评估,比如是否完整、准确
- 优化器(Optimizer):根据评估结果提出改进建议,并重新生成更好的内容
有点像我们人类写作文时的样子,先写初稿,再检查,然后修改、斟酌,最后完成,比直接一次性写完质量更高。
import java.util.ArrayList;
import java.util.List;
/**
* Evaluator-Optimizer 模式实现类
* 通过评估-优化循环迭代提升生成内容质量
*
* 核心思想:通过生成-评估-优化的循环迭代,逐步改进输出质量
* 适用于需要高质量文本生成的场景,如沟通文案、报告撰写等
*/
public class EvaluatorOptimizer {
// 生成器提示语:用于撰写沟通文案
// 定义了生成器AI的任务、要求和输出格式
public static final String DEFAULT_GENERATOR_PROMPT = """
你的任务是帮助用户撰写一段合适的沟通文字,
用于与老师或辅导员交流某个学习相关请求。
如果有之前的尝试和反馈,请认真反思并进行改进。
要求:
- 使用礼貌、尊重、诚恳的语气
- 理由充分,体现责任感和规划能力
- 避免借口式表达,突出主动性和成长意愿
输出必须为单行 JSON 格式,严格遵循如下模板:
{"thoughts":"简要说明你的写作思路","response":"具体的沟通内容文本"}
规则:
1. 所有换行用 \\n 表示
2. 所有双引号写成 \\\"
3. 整个响应在一行内完成,无真实回车
示例:
{"thoughts":"强调实习对职业发展的价值","response":"老师您好,\\n我想和你沟通一下...\\n感谢您的理解和支持!"}
请只返回这个 JSON 结构。
""";
// 评估器提示语:评估沟通文案质量
// 定义了评估器AI的评估维度和标准
public static final String DEFAULT_EVALUATOR_PROMPT = """
请评估以下沟通文案是否适合用于与高校教师或辅导员对话。
从以下几个维度打分:
- 礼貌性:是否使用敬语,态度是否谦逊
- 逻辑性:理由是否充分、真实可信
- 清晰度:目标是否明确,结构是否清晰
- 合规性:是否符合学校规定,不鼓励逃课
- 改进建议:指出具体可优化之处
回复必须是单行 JSON,格式如下:
{"evaluation":"PASS, NEEDS_IMPROVEMENT, 或 FAIL", "feedback":"具体评价和建议"}
evaluation 字段只能取值:"PASS"(完全合格)、"NEEDS_IMPROVEMENT"(基本可行但需调整)、"FAIL"(不得体或违规)
只有当文案非常得体且无需修改时才可标记为 PASS。
""";
/**
* 生成结果记录类
* @param thoughts 生成时的思考过程,说明写作思路
* @param response 生成的沟通文案内容
*/
public static record Generation(String thoughts, String response) {
}
/**
* 评估结果记录类
* @param evaluation 评估结果枚举:PASS/NEEDS_IMPROVEMENT/FAIL
* @param feedback 具体的评估反馈和改进建议
*/
public static record EvaluationResponse(Evaluation evaluation, String feedback) {
/**
* 评估结果枚举
* PASS: 完全合格,无需修改
* NEEDS_IMPROVEMENT: 基本可行但需要调整
* FAIL: 不得体或违规,需要重写
*/
public enum Evaluation {
PASS, NEEDS_IMPROVEMENT, FAIL
}
}
/**
* 最终优化后的响应
* @param solution 最终被接受的解决方案(沟通文案)
* @param chainOfThought 整个思考链,记录每次迭代的生成结果
*/
public static record RefinedResponse(String solution, List<Generation> chainOfThought) {
}
// 依赖的AI聊天客户端,用于调用大模型
private final ChatClient chatClient;
// 生成器使用的提示语
private final String generatorPrompt;
// 评估器使用的提示语
private final String evaluatorPrompt;
/**
* 构造函数:使用默认提示语
* @param chatClient AI聊天客户端,不能为空
*/
public EvaluatorOptimizer(ChatClient chatClient) {
this(chatClient, DEFAULT_GENERATOR_PROMPT, DEFAULT_EVALUATOR_PROMPT);
}
/**
* 构造函数:自定义提示语
* @param chatClient AI聊天客户端,不能为空
* @param generatorPrompt 生成器提示语,不能为空
* @param evaluatorPrompt 评估器提示语,不能为空
*/
public EvaluatorOptimizer(ChatClient chatClient, String generatorPrompt, String evaluatorPrompt) {
// 参数校验
Assert.notNull(chatClient, "ChatClient 不能为空");
Assert.hasText(generatorPrompt, "生成器提示不能为空");
Assert.hasText(evaluatorPrompt, "评估器提示不能为空");
this.chatClient = chatClient;
this.generatorPrompt = generatorPrompt;
this.evaluatorPrompt = evaluatorPrompt;
}
/**
* 启动优化循环的公共入口方法
* @param task 用户的具体请求任务描述
* @return 优化后的最终响应,包含解决方案和思考链
*/
public RefinedResponse loop(String task) {
// 初始化记忆列表,存储所有尝试过的文案
List<String> memory = new ArrayList<>();
// 初始化思考链,记录每次生成的结果
List<Generation> chainOfThought = new ArrayList<>();
// 调用私有递归方法开始循环
return loop(task, "", memory, chainOfThought);
}
/**
* 私有递归方法:实现评估-优化的核心循环逻辑
* @param task 用户请求任务
* @param context 当前上下文,包含之前的尝试和反馈
* @param memory 记忆列表,存储所有历史尝试
* @param chainOfThought 思考链,记录每次生成
* @return 优化后的最终响应
*/
private RefinedResponse loop(String task, String context, List<String> memory,
List<Generation> chainOfThought) {
// 1. 生成阶段:根据任务和上下文生成文案
Generation generation = generate(task, context);
// 将生成的文案加入记忆
memory.add(generation.response());
// 将生成结果加入思考链
chainOfThought.add(generation);
// 2. 评估阶段:评估生成的文案质量
EvaluationResponse evaluationResponse = evaluate(generation.response(), task);
// 3. 判断是否通过评估
if (evaluationResponse.evaluation().equals(EvaluationResponse.Evaluation.PASS)) {
// 解决方案被接受!返回最终结果
return new RefinedResponse(generation.response(), chainOfThought);
}
// 4. 未通过评估,构建新的上下文进行下一轮迭代
// 新的上下文包含:所有历史尝试 + 最新反馈
StringBuilder newContext = new StringBuilder();
newContext.append("之前的尝试:");
for (String m : memory) {
newContext.append("\n- ").append(m);
}
newContext.append("\n最新反馈: ").append(evaluationResponse.feedback());
// 5. 递归调用,开始下一轮生成-评估循环
return loop(task, newContext.toString(), memory, chainOfThought);
}
/**
* 生成方法:调用AI生成沟通文案
* @param task 用户请求任务
* @param context 上下文信息(历史尝试和反馈)
* @return 生成结果,包含思考过程和文案内容
*/
private Generation generate(String task, String context) {
// 调用AI聊天客户端,传入生成器提示语、上下文和任务
Generation generationResponse = chatClient.prompt()
.user(u -> u.text("{prompt}\\n{context}\\n当前请求: {task}")
.param("prompt", this.generatorPrompt)
.param("context", context)
.param("task", task))
.call()
.entity(Generation.class);
// 打印生成结果,便于调试和观察
System.out.println(String.format("\\n=== 生成器输出 ===\\n思考: %s\\n文案: %s\\n",
generationResponse.thoughts(), generationResponse.response()));
return generationResponse;
}
/**
* 评估方法:调用AI评估文案质量
* @param content 待评估的文案内容
* @param task 原始请求任务
* @return 评估结果,包含评估等级和反馈建议
*/
private EvaluationResponse evaluate(String content, String task) {
// 调用AI聊天客户端,传入评估器提示语、任务和待评估文案
EvaluationResponse evaluationResponse = chatClient.prompt()
.user(u -> u.text("{prompt}\\n原始请求: {task}\\n待评估文案: {content}")
.param("prompt", this.evaluatorPrompt)
.param("task", task)
.param("content", content))
.call()
.entity(EvaluationResponse.class);
// 打印评估结果,便于调试和观察
System.out.println(String.format("\\n=== 评估器输出 ===\\n结果: %s\\n反馈: %s\\n",
evaluationResponse.evaluation(), evaluationResponse.feedback()));
return evaluationRe;
总结
本文详细介绍了 Spring AI 中五种核心的 Agent 工作流模式,每种模式都有其独特的适用场景和优势。下面总结这五种工作流模式的使用场景。
1. Chain Workflow(链式工作流)
使用场景:
- 顺序处理任务:当任务需要按照固定顺序执行,且前一步的输出是后一步的输入时
- 简单业务流程:如数据清洗、文档处理、审批流程等线性流程
- 教学演示:适合初学者理解 Agent 的基本工作原理
- 小型项目:需求明确、流程简单的应用场景
特点: 结构简单、易于理解和实现,但缺乏灵活性。
2. Parallelization Workflow(并行化工作流)
使用场景:
- 性能敏感应用:需要同时处理多个独立任务以提高效率
- 数据聚合:从多个数据源并行获取信息后汇总
- 竞品分析:同时分析多个竞争对手或产品
- 实时监控:并行监控多个系统指标或日志
- 批量处理:同时处理大量相似但独立的任务
特点: 显著提升处理速度,适合 I/O 密集型或网络请求密集的场景。
3. Routing Workflow(路由工作流)
使用场景:
- 智能客服:根据用户问题类型路由到不同的专业客服 Agent
- 内容分类:自动识别内容类型并分发给相应的处理模块
- 多领域专家系统:根据问题领域选择最合适的专家 Agent
- 工作流分支:根据条件判断选择不同的处理路径
- 优先级调度:根据任务紧急程度或重要性分配资源
特点: 灵活智能,能够根据输入动态选择处理路径。
4. Orchestrator-Workers(编排器工作者模式)
使用场景:
- 复杂业务流程:需要协调多个子任务完成复杂目标
- 项目管理:分解大任务为小任务并分配给不同团队/Agent
- 系统集成:协调多个子系统或微服务完成端到端流程
- 科研计算:将大型计算任务分解为多个子任务并行计算
- 供应链管理:协调采购、生产、物流等多个环节
特点: 层次化架构,适合复杂、多步骤的业务流程。
5. 评估-优化循环模式
使用场景:
- 内容生成优化:如文章、代码、设计方案的迭代改进
- A/B 测试:生成多个版本并选择最优结果
- 质量控制:对输出结果进行质量评估和自动修正
- 学习系统:通过反馈循环不断优化模型或策略
- 创意工作:如广告文案、产品设计的多次迭代优化
特点: 自我改进机制,适合质量要求高、需要持续优化的场景。
总结建议
- 从简单开始:对于新项目,建议从 Chain Workflow 开始,逐步引入更复杂的模式
- 模式组合使用:实际项目中经常需要组合多种模式,如并行处理后再路由
- 性能监控:复杂工作流需要完善的监控和日志,便于问题排查
- 测试策略:为每种工作流设计专门的测试用例,特别是并发和路由逻辑
- 文档化:清晰记录工作流设计决策和架构图,便于团队理解和维护
掌握这五种工作流模式,能够帮助你在实际项目中设计出更加高效、灵活和可靠的 AI Agent 系统。根据具体业务需求选择合适的工作流模式,是构建成功 A
Spring AI 与 LangGraph 工作流模式对比
为了更好地理解 Spring AI 中的工作流模式,下面将其与 LangGraph 框架中的对应模式进行对比分析:
| 工作流模式 | Spring AI 实现方式 | LangGraph 实现方式 | 主要区别 |
|---|---|---|---|
| Chain Workflow | 通过 Chain 接口和 SimpleChain 实现,支持顺序执行 |
使用 StateGraph 和线性边连接节点 |
Spring AI 更轻量,LangGraph 提供更丰富的状态管理和条件分支 |
| Parallelization Workflow | 使用 ParallelAgentExecutor 并行执行多个 Agent |
通过 ConditionalEdges 和并行分支实现 |
Spring AI 并行化更直接,LangGraph 的并行控制更精细 |
| Routing Workflow | 基于 Router 接口和条件判断实现路由逻辑 |
使用 Router 节点和条件边动态选择路径 |
两者概念相似,但 LangGraph 的路由机制更可视化、可调试 |
| Orchestrator-Workers | 通过主 Agent 协调多个子 Agent 完成任务 | 使用层次化图结构,父图调用子图 | Spring AI 更侧重 Agent 间协调,LangGraph 提供完整的图嵌套机制 |
| 评估-优化循环模式 | 通过评估器反馈循环迭代优化结果 | 使用循环边和状态持久化实现迭代优化 | Spring AI 循环逻辑更显式,LangGraph 的循环机制更内置于图结构 |
核心差异总结
-
抽象层次不同
- Spring AI:更贴近业务层,以 Agent 为中心的工作流设计
- LangGraph:更底层的图计算框架,提供通用的状态机和工作流引擎
-
状态管理方式
- Spring AI:状态通常通过消息传递或上下文对象管理
- LangGraph:内置
State对象,支持复杂的状态持久化和传递
-
可视化与调试
- Spring AI:依赖日志和监控工具进行调试
- LangGraph:原生支持图可视化,便于理解和调试复杂工作流
-
学习曲线
- Spring AI:对 Spring 开发者更友好,集成 Spring 生态更紧密
- LangGraph:需要理解图计算概念,但功能更强大灵活
-
适用场景
- Spring AI:适合 Spring 生态内的 AI 应用,快速构建业务工作流
- LangGraph:适合需要复杂状态管理、循环和条件分支的通用工作流
选择建议
- 选择 Spring AI:如果你的项目基于 Spring 生态,需要快速集成 AI 能力,且工作流相对简单直接
- 选择 LangGraph:如果你需要构建复杂、多分支、有状态的工作流,或者需要高度可视化和可调试的工作流引擎
- 混合使用:在实际项目中,也可以考虑使用 Spring AI 处理业务逻辑,而将复杂的工作流编排交给 LangGraph
两种框架各有优势,选择哪种取决于具体的项目需求、团队技术栈和工作流复杂度。
更多推荐
所有评论(0)