Spring Ai Alibaba-1.1.0.0-M5-SequentialAgent

Spring Ai Alibaba-1.1.0.0-M5-SequentialAgent

顺序执行模式中,多个Agent按预定义的顺序依次执行。每个Agent的输出成为下一个Agent的输入。

流程:

  1. Agent A处理初始输入
  2. Agent A 的输出传递给Agent B
  3. Agent B 处理并传递给Agent C
  4. 最后一个Agent返回最终结果

一、🏗️ 架构概览


二、✨ 项目概述

这是一个基于 Spring AI Alibaba 的多 Agent 协作系统示例项目。该项目演示了如何构建和运行多个 AI Agent 之间的协作流程,特别展示了顺序执行的 Agent 工作流。项目还包含了完善的监控和性能跟踪功能。


三、🛠️ 技术栈

  • Spring Boot 3.4.x
  • Spring AI Alibaba
  • Alibaba Cloud DashScope (通义千问 API)
  • micrometer 1.16.0
  • Java 17+

四、📁 项目结构

复制代码
SpringAiAlibabaMultiAgent/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/alibaba/springaialibabamultiagent/
│   │   │       ├── SpringAiAlibabaMultiAgentApplication.java  # 应用启动类
│   │   │       ├── config/                                    # 配置类目录
│   │   │       │   ├── AgentConfig.java                       # Agent 配置类
│   │   │       │   ├── MonitoringConfig.java                  # 监控配置类
│   │   │       │   └── StorageConfig.java                     # 存储配置类
│   │   │       ├── controller/                                # 控制器目录
│   │   │       │   └── SequentialAgentController.java         # 顺序 Agent 控制器
│   │   └── resources/
│   │       └── application.properties                         # 应用配置文件
├── pom.xml                                                    # Maven 配置文件
└── README.md                                                  # 项目说明文件

五、⚙️ 配置pom.xml

项目集成了 Micrometer 和 Prometheus 监控,可以通过以下端点访问监控信息:

  • http://localhost:8020/actuator/health: 健康检查

  • http://localhost:8020/actuator/metrics: 指标信息

  • http://localhost:8020/actuator/prometheus: Prometheus 格式的监控数据

    dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.4.12</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>3.4.12</version>
    </dependency>
    <dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <version>1.16.0</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-agent-framework</artifactId>
    <version>1.1.0.0-M5</version>
    </dependency>

    <dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> <version>1.1.0.0-M5</version> </dependency>

六、📝 配置application.properties

复制代码
server.port=8020
spring.application.name=SpringAiAlibabaMultiAgent
# ====SpringAIAlibaba Config=============
spring.ai.dashscope.api-key=${qwen-api}
spring.ai.dashscope.model=qwen-turbo
# 配置温度参数
spring.ai.dashscope.chat.options.temperature=0.5
# 配置最大token数
spring.ai.dashscope.chat.options.max-tokens=1048
# 启用字符编码过滤器
server.servlet.encoding.enabled=true
# 强制对所有请求和响应使用指定的字符编码
server.servlet.encoding.force=true
# 设置字符编码
server.servlet.encoding.charset=UTF-8
# Micrometer 监控配置
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.prometheus.metrics.export.enabled=true

七、🧰 配置类

🔗存储配置类

复制代码
@Configuration
public class StorageConfig {
    @Bean
    public MemoryStore memoryStore() {
        return new MemoryStore();
    }
    @Bean
    public MemorySaver memorySaver() {
        return new MemorySaver();
    }
}

🔗注册表配置类

复制代码
@Configuration
public class MonitoringConfig {
    /**
     * 创建ObservationRegistry Bean
     * 用于配置和初始化ObservationRegistry实例
     * @return ObservationRegistry实例
     */
    @Bean
    public ObservationRegistry observationRegistry() {
        return ObservationRegistry.create();
    }
}

🔗agent 配置类

复制代码
@Configuration
public class AgentConfig {

    /**
     * 创建写作Agent Bean
     * @param dashScopeChatModel DashScope聊天模型
     * @return ReactAgent实例
     */
    @Bean
    public ReactAgent writerAgent(DashScopeChatModel dashScopeChatModel, MemorySaver memorySaver) {
        return ReactAgent.builder()
                .name("writer_agent")
                .model(dashScopeChatModel)
                .description("专业写作Agent")
                .instruction("你是一个知名的作家,擅长写作和创作。请根据用户的提问进行回答。")
                .outputKey("article")
                .saver(memorySaver)
                .build();
    }

    /**
     * 创建评审Agent Bean
     * @param dashScopeChatModel DashScope聊天模型
     * @return ReactAgent实例
     */
    @Bean
    public ReactAgent reviewerAgent(DashScopeChatModel dashScopeChatModel, MemorySaver memorySaver) {
        return ReactAgent.builder()
                .name("reviewer_agent")
                .model(dashScopeChatModel)
                .description("专业评审Agent")
                .instruction("你是一个知名的评论家,擅长对文章进行评论和修改。" +
                        "对于散文类文章,请确保文章中必须包含对于西湖风景的描述。" +
                        "最终只返回修改后的文章,不要包含任何评论信息。")
                .outputKey("reviewed_article")
                .saver(memorySaver)
                .build();
    }
}

八、🎯 控制器

复制代码
package com.alibaba.springaialibabamultiagent.controller;

import com.alibaba.cloud.ai.graph.CompileConfig;
import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.flow.agent.SequentialAgent;
import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import com.alibaba.cloud.ai.graph.store.stores.MemoryStore;
import com.alibaba.springaialibabamultiagent.listener.ComprehensiveGraphListener;
import io.micrometer.observation.ObservationRegistry;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;

@RestController
public class SequentialAgentController {

    @Resource
    private ReactAgent writerAgent;

    @Resource
    private ReactAgent reviewerAgent;

    @Resource
    private ObservationRegistry observationRegistry;

    @Resource
    private MemoryStore memoryStore;

    /**
     * 创建一个顺序执行的博客撰写和评审Agent
     *
     * @param topic 博客主题
     * @return 执行结果字符串
     */
    @GetMapping("/ai/blog")
    public String generateBlog(@RequestParam(name = "topic", defaultValue = "西湖风景") String topic,
                               @RequestParam(name = "user_id", defaultValue = "西湖风景") String user_id) {
        try {
            // 使用基于用户ID的稳定threadId,确保同一用户的对话可以保持记忆
            String threadId = "user_" + user_id;

            SequentialAgent blogAgent = SequentialAgent.builder()
                    .name("blog_agent")
                    .subAgents(List.of(writerAgent, reviewerAgent))
                    .description("一个顺序执行的博客撰写和评审Agent")
                    .compileConfig(CompileConfig.builder()
                            .recursionLimit(20) // 限制最多递归20次
                            //http://localhost:8020/actuator/prometheus
                            .observationRegistry(observationRegistry)
                            //.withLifecycleListener(new ComprehensiveGraphListener())
                            .store(memoryStore)
                            .build())
                    .build();

            RunnableConfig runnableConfig = RunnableConfig.builder()
                    .threadId(threadId)
                    .addMetadata("user_id", user_id)
                    .store(memoryStore)
                    .build();

            Optional<OverAllState> result = blogAgent.invoke("请写一篇关于'" + topic + "'的300字左右的散文",runnableConfig);

            StringBuilder response = new StringBuilder();
            if (result.isPresent()) {
                OverAllState state = result.get();

                // 获取第一个Agent(writer_agent)的输出
                Optional<Object> articleObj = state.value("article");
                if (articleObj.isPresent() && articleObj.get() instanceof AssistantMessage) {
                    AssistantMessage article = (AssistantMessage) articleObj.get();
                    response.append("===原始文章===: ").append(article.getText()).append("\n\n");
                }

                // 获取第二个Agent(reviewer_agent)的输出
                Optional<Object> reviewedArticleObj = state.value("reviewed_article");
                if (reviewedArticleObj.isPresent() && reviewedArticleObj.get() instanceof AssistantMessage) {
                    AssistantMessage reviewedArticle = (AssistantMessage) reviewedArticleObj.get();
                    response.append("===评审后文章===: ").append(reviewedArticle.getText());
                }
            }
            return response.toString();
        } catch (Exception e) {
            // 更好的错误处理,记录详细错误信息
            return "发生错误: " + e.getMessage() + "\n请稍后重试或检查网络连接";
        }
    }
}

九、🌐 测试场景

复制代码
http://localhost:8020/ai/blog?topic=天降祥瑞&user_id=1

十、🚀 扩展能力

  • 统一监控与治理:耗时统计、成功率分析等。

  • prometheus 实时监控

  • 引入redisStore实现存储

相关推荐
Leo July20 小时前
【Java】Spring Security 6.x 全解析:从基础认证到企业级权限架构
java·spring·架构
康康的AI博客20 小时前
腾讯王炸:CodeMoment - 全球首个产设研一体 AI IDE
ide·人工智能
中达瑞和-高光谱·多光谱20 小时前
中达瑞和LCTF:精准调控光谱,赋能显微成像新突破
人工智能
mahtengdbb120 小时前
【目标检测实战】基于YOLOv8-DynamicHGNetV2的猪面部检测系统搭建与优化
人工智能·yolo·目标检测
Pyeako20 小时前
深度学习--BP神经网络&梯度下降&损失函数
人工智能·python·深度学习·bp神经网络·损失函数·梯度下降·正则化惩罚
星火开发设计20 小时前
C++ 数组:一维数组的定义、遍历与常见操作
java·开发语言·数据结构·c++·学习·数组·知识
码道功成20 小时前
Pycham及IntelliJ Idea常用插件
java·ide·intellij-idea
清 澜21 小时前
大模型面试400问第一部分第一章
人工智能·大模型·大模型面试
消失的旧时光-194321 小时前
第四篇(实战): 订单表索引设计实战:从慢 SQL 到毫秒级
java·数据库·sql