大数跨境
0
0

燃爆啦!Spring AI 五大智能体开发模式震撼登场

燃爆啦!Spring AI 五大智能体开发模式震撼登场 Spring全家桶实战案例
2025-06-20
0
导读:燃爆啦!Spring AI 五大智能体开发模式震撼登场
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新135个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

智能体系统的基础构建模块是一个经过增强的 LLM,这种增强体现在它集成了检索工具记忆等功能。我们当前的模型能够主动利用这些能力——生成自己的搜索查询、选择合适的工具,并决定保留哪些信息。

Anthropic公司将不同 "智能体" 定义(有些人认为智能体是能够长期独立运行、使用各种工具完成复杂任务的全自主系统;而另一些人则将其视为遵循预定义工作流的实现方案)都归类为智能体系统,但在架构上对工作流和智能体进行了区分:

  • 工作流:它是一个系统,通过预定义的代码路径来协调大型语言模型(LLM)和工具,即按照既定的流程和规则来执行任务。

  • 智能体:它强调大型语言模型能够动态指导自身处理流程和工具使用,具有自主性,能够根据实际情况自主控制如何完成任务。

接下来,将介绍在生产环境中观察到的智能体系统的常见模式。我们将从基础构建模块——增强型大型语言模型(augmented LLM)开始,然后逐步增加复杂性,从简单的组合式工作流到自主智能体。

1.1 链式工作流(Chain Workflow)

链式工作流模式体现了将复杂任务分解为更简单、更易管理的步骤的原则。如下图所示:

使用场景:

  • 任务具有清晰的顺序步骤时

  • 当您愿意以增加延迟为代价换取更高准确性时

  • 当每个步骤都基于前一步骤的输出时

1.2 并行化工作流(Parallelization Workflow)

大型语言模型(LLMs)可以同时处理任务,并通过编程方式聚合它们的输出。如下图所示:

使用场景:

  • 处理大量相似但相互独立的事项时

  • 需要多个独立视角来完成的任务时

  • 当处理时间至关重要且任务可并行化时

1.3 路由工作流(Routing Workflow)

路由模式实现了智能的任务分配,能够对不同类型的输入进行专门处理。如下图所示:

使用场景:

  • 处理具有不同输入类别的复杂任务时

  • 当不同输入需要专门的处理方式时

  • 当能够准确进行分类处理时

1.4 协调器-工作者工作流(Orchestrator-workers)

在协调器-工作者工作流中,一个中央的大型语言模型(LLM)会动态地分解任务,将其分配给工作者LLM,并综合它们的处理结果。如下图所示:

使用场景:

  • 在那些子任务无法提前预测的复杂任务中

  • 在需要采用不同方法或视角来完成的任务中

  • 在需要自适应解决问题的情境中

1.5 评估器-优化器工作流(Evaluator-optimizer)

在评估器-优化器工作流中,一个大型语言模型(LLM)调用生成响应,而另一个模型则在循环中提供评估和反馈。如下图所示:

使用场景:

  • 当存在明确的评估标准时

  • 当迭代优化能带来可衡量的价值时

  • 当任务能从多轮评审中受益时

1.6 智能体(Agents)

智能体随LLMs成熟在生产中兴起,能处理复杂任务。它们从人类用户获取指令后独立规划操作,执行时从环境获取反馈以评估进展,可暂停等待人类反馈。任务完成后终止,常设停止条件。如下图所示:

使用场景:

智能体适用于解决开放式问题,即那些难以或无法预测所需步骤数量,且无法预先设定固定路径的问题。大型语言模型(LLM)可能会进行多轮操作,因此你必须对其决策能力有一定程度的信任。智能体的自主性使其非常适合在受信任的环境中扩展任务规模。

注意:智能体的自主性也意味着更高的成本以及错误累积的潜在风险。我们建议在沙盒环境中进行广泛的测试,并设置适当的防护措施。

接下来,我们将通过案例的方式演示上面的3种工作流模式。

2.实战案例

环境准备

<dependency>  <groupId>com.alibaba.cloud.ai</groupId>  <artifactId>spring-ai-alibaba-starter</artifactId>  <version>1.0.0-M6.1</version></dependency>

我们使用阿里的大模型。

配置文件

spring:  ai:    dashscope:      api-key: sk-xxxooo      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1      chat:        options:          stream: true          model: qwen-turbo

2.1 链式工作流

@Componentpublic class ChainWorkflow {  // 一系列系统提示(system prompts),这些提示定义了链式处理中的转换步骤。每个提示都充当一个关卡(gate),在进入下一步之前对输出进行验证和转换。  public static final String[] DEFAULT_SYSTEM_PROMPTS = {    // Step 1    """       从文本中仅提取数值及其对应的指标。       将每个数值和指标按照“数值: 指标”的格式逐行列出。       示例格式:       92: 客户满意度       45%: 收入增长率""",    // Step 2    """       将所有数值尽可能转换为百分比形式。       若数值并非百分比或点数形式,则将其转换为小数形式后再以百分比呈现(例如,92 点 → 92%)。       每行只保留一个数值。       示例格式:       92%:客户满意度       45%:收入增长率""",    // Step 3    """       将所有行按照数值大小进行降序排序。       每行保持“数值: 指标”的格式。       示例:       92%: 客户满意度       87%: 员工满意度""",    // Step 4    """       将排序后的数据格式化为以下带有“指标”和“数值”两列的 Markdown 表格:       | 指标 | 数值 |       |:--|--:|       | 客户满意度 | 92% | """  };  private final ChatClient chatClient;  public ChainWorkflow(ChatClient chatClient) {    this.chatClient = chatClient ;  }  public String chain(String userInput, String[] systemPrompts) {    int step = 0;    String response = userInput;    System.out.println(String.format("\nSTEP %s:\n %s", step++, response));    for (String prompt : systemPrompts) {      // 1. 使用上一步的响应来构建输入内容。      String input = String.format("{%s}\n {%s}", prompt, response);      // 2. 使用新的输入内容调用聊天客户端,并获取新的响应。      response = chatClient.prompt(input).call().content();      System.out.println(String.format("\nSTEP %s:\n %s", step++, response));    }    return response;  }}

测试接口

@GetMapping("")public ResponseEntity<String> chain() {  String[] prompts = ChainWorkflow.DEFAULT_SYSTEM_PROMPTS ;  String userInput = """    第三季度绩效总结:      本季度我们的客户满意度得分提升至92分。      与去年相比,收入增长了45%。      在我们的主要市场中,市场份额现已达到23%。      客户流失率从8%下降至5%。      新用户获取成本为每用户43美元。      产品采用率提升至78%。      员工满意度得分为87分。      营业利润率提高至34%。    """; ;  return ResponseEntity.ok(this.chainWorkflow.chain(userInput, prompts)) ;}

运行结果

控制台

接口输出

2.2 并行化工作流

@Componentpublic class ParalleWorkflow {  private final ChatClient chatClient;  public ParalleWorkflow(ChatClient chatClient) {    this.chatClient = chatClient;  }  /**   * 使用固定线程池和相同的提示模板并发处理多个输入。此方法会保持结果顺序与输入顺序一致。   *   * @param prompt   用于每个输入的提示模板。输入将被追加到此提示后。不能为null。示例:"Translate the following text to French:"   * @param inputs   待处理的输入字符串列表。每个输入将独立并行处理。不能为null或空。示例:["Hello", "World", "Good morning"](["你好", "世界", "早上好"]   * @param nWorkers 要使用的并发工作线程数。这控制着同时进行的最大LLM API调用次数。必须大于0。在设置此值时,请考虑API的速率限制。   * @return 与输入顺序相同的处理结果列表。每个结果包含LLM对相应输入的响应。   */  public List<Stringparallel(String prompt, List<String> inputs, int nWorkers) {    ExecutorService executor = Executors.newFixedThreadPool(nWorkers);    try {      List<CompletableFuture<String>> futures = inputs.stream()        .map(input -> CompletableFuture.supplyAsync(() -> {          try {            return chatClient.prompt(prompt + "\nInput: " + input).call().content();          } catch (Exception e) {            throw new RuntimeException("Failed to process input: " + input, e);          }       }, executor))       .collect(Collectors.toList());       // 等待所有任务完成       CompletableFuture<Void> allFutures = CompletableFuture.allOf(       futures.toArray(CompletableFuture[]::new));       allFutures.join();       return futures.stream()           .map(CompletableFuture::join)           .collect(Collectors.toList());    } finally {      executor.shutdown();    }  }}

测试接口

@GetMapping("")public ResponseEntity<?> index() {  List<String> response = this.paralleWorkflow.parallel("""    分析市场变化将如何影响该利益相关者群体。    提供具体影响及建议措施。    格式应清晰划分章节,并明确优先级。    """List.of("""        客户群体:        - 对价格敏感        - 追求更先进的技术        - 关注环境问题        """,        """            员工群体:            - 对工作保障的担忧            - 需要新技能            - 希望获得明确的方向指引            """,        """            投资者:            - 期望增长            - 希望控制成本            - 关注风险问题            """,        """            供应商:            - 产能限制            - 价格压力            - 技术转型            """), 4);  System.err.println(response) ;  return ResponseEntity.ok(response);}

2.3 路由工作流

public class RoutingWorkflow {  private final ChatClient chatClient;  public RoutingWorkflow(ChatClient chatClient) {    this.chatClient = chatClient;  }  public String route(String input, Map<String, String> routes) {    String routeKey = determineRoute(input, routes.keySet());    String selectedPrompt = routes.get(routeKey);    if (selectedPrompt == null) {      throw new IllegalArgumentException("Selected route '" + routeKey + "' not found in routes map");    }    return chatClient.prompt(selectedPrompt + "\nInput: " + input).call().content();  }  private String determineRoute(String input, Iterable<String> availableRoutes) {    System.out.println("\n有效路由: " + availableRoutes);    String selectorPrompt = String.format("""         分析输入内容,并从以下选项中选择最合适的支持团队: %s         先阐述你的推理过程,然后以以下JSON格式提供你的选择:         \\{             "reasoning": "对该工单应被路由到特定团队的简要解释。请考虑关键词、用户意图以及紧急程度。",             "selection": "所选团队的名称"         \\}         Input: %s""", availableRoutes, input);    RoutingResponse routingResponse = chatClient.prompt(selectorPrompt).call().entity(RoutingResponse.class);    System.out.println(String.format("路由分享:%s\n选择的路由: %s",      routingResponse.reasoning(), routingResponse.selection()));    return routingResponse.selection();  }}

测试代码

运行结果



以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

SpringBoot冷门但逆天的5个神级注解,老司机都在偷偷用!

炸裂!仅用一个类就能跑通Spring MVC程序

强大!Spring Boot 巧妙利用 SpEL 实现复杂的规则运算

太赞了!AOP弃用@Aspect,一个注解让你的代码灵活十倍!

技术专家!@Transactional 炸场升级:回滚+重试一体化

惊呆了!Spring Boot接口定义:8种逆天玩法

强大!JSON解析神器,再复杂也不怕了

Spring Boot中记录JDBC、JPA及MyBatis执行SQL及参数的正确姿势

Spring Boot中通过3种方式初始化数据,你们如何选择?

基于 Spring Boot 实现自定义二进制数据传输协议

生产环境Spring Boot切记要关闭这个开关

图片
图片
图片
图片
图片
图片
图片
图片
图片

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读7
粉丝0
内容832