Spring AI Alibaba 1.x 系列【31】集成 Studio 模块实现可视化 Agent 调试

文章目录

  • [1. 概述](#1. 概述)
  • [2. 入门案例](#2. 入门案例)
    • [2.1 引入依赖](#2.1 引入依赖)
    • [2.2 配置 API Key](#2.2 配置 API Key)
    • [2.3 工具定义](#2.3 工具定义)
    • [2.4 Agent 配置类](#2.4 Agent 配置类)
    • [2.5 启动测试](#2.5 启动测试)
  • [3. API 端点](#3. API 端点)
    • [3.1 Controller 类](#3.1 Controller 类)
    • [3.2 Agent API](#3.2 Agent API)
    • [3.3 Graph API](#3.3 Graph API)
    • [3.4 Thread API](#3.4 Thread API)
    • [3.5 UI 重定向](#3.5 UI 重定向)
  • [4. 高级用法](#4. 高级用法)
    • [4.1 Human-in-the-Loop 支持](#4.1 Human-in-the-Loop 支持)
    • [4.2 Graph 工作流支持](#4.2 Graph 工作流支持)
    • [4.3 独立运行模式](#4.3 独立运行模式)
    • [4.4 自定义 Agent/GraphLoader 加载器](#4.4 自定义 Agent/GraphLoader 加载器)
    • [4.5 生产环境自动关闭](#4.5 生产环境自动关闭)
      • [4.5.1 方案一:排除自动配置(推荐)](#4.5.1 方案一:排除自动配置(推荐))
      • [4.5.2 方案二:Maven 依赖控制](#4.5.2 方案二:Maven 依赖控制)

1. 概述

Spring AI Alibaba 提供了可视化 Agent 调试和交互 UI 模块,为开发者提供了与 AI Agent 进行可视化对话的前端界面。它支持嵌入式和独立部署两种模式,可以快速集成到任何 Spring Boot 应用中。

核心功能:

  • 可视化对话
  • 线程管理
  • 流式响应
  • 消息历史

特殊支持:

  • HITL 审批界面
  • 工具调用可视化
  • 自动/手动审批
  • 参数编辑

2. 入门案例

使用嵌入模式,将 Studio 作为依赖添加到 Spring Boot 项目中。

2.1 引入依赖

Maven 配置:

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-studio</artifactId>
    <version>1.1.2.2</version>
</dependency>

spring-ai-alibaba-studio 中包含了以下子依赖:

本项目完整依赖如下:

xml 复制代码
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-ai-alibaba.version>1.1.2.2</spring-ai-alibaba.version>
        <spring-ai-alibaba-ext.version>1.1.2.1</spring-ai-alibaba-ext.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--Spring AI BOM-->
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.1.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--Spring AI Alibaba BOM-->
            <dependency>
                <groupId>com.alibaba.cloud.ai</groupId>
                <artifactId>spring-ai-alibaba-bom</artifactId>
                <version>${spring-ai-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--Spring AI Alibaba Extensions BOM-->
            <dependency>
                <groupId>com.alibaba.cloud.ai</groupId>
                <artifactId>spring-ai-alibaba-extensions-bom</artifactId>
                <version>${spring-ai-alibaba-ext.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Spring AI Alibaba Studio - 可视化调试工具 -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-studio</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <!-- Spring AI Alibaba Agent Framework -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-agent-framework</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <!-- 阿里云百炼 DashScope Starter (通义千问) -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        </dependency>

        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.2 配置 API Key

yml 复制代码
spring:
  application:
    name: spring-ai-alibaba-studio-01
  ai:
    # 阿里云百炼配置 (DashScope)
    dashscope:
      api-key: sk-3d56ec506a894  # 从环境变量读取,或直接填写
      chat:
        options:
          model: qwen-plus  # 通义千问模型:qwen-turbo, qwen-plus, qwen-max
          temperature: 0.7
          max_tokens: 2000
server:
  port: 8080

2.3 工具定义

天气查询工具:

java 复制代码
/**
 * 天气查询工具
 * 模拟天气查询功能(演示用途)
 *
 * 实际项目中可以接入真实的天气 API
 */
@Component
public class WeatherTool {

    private static final Map<String, String[]> WEATHER_DATA = new HashMap<>();

    static {
        WEATHER_DATA.put("北京", new String[]{"晴", "多云", "阴", "小雨"});
        WEATHER_DATA.put("上海", new String[]{"多云", "阴", "小雨", "晴"});
        WEATHER_DATA.put("广州", new String[]{"晴", "多云", "大雨", "小雨"});
        WEATHER_DATA.put("深圳", new String[]{"多云", "晴", "小雨", "阴"});
        WEATHER_DATA.put("杭州", new String[]{"晴", "多云", "小雨", "阴"});
        WEATHER_DATA.put("成都", new String[]{"多云", "阴", "小雨", "晴"});
        WEATHER_DATA.put("武汉", new String[]{"晴", "多云", "小雨", "阴"});
        WEATHER_DATA.put("长沙", new String[]{"多云", "小雨", "晴", "阴"});
    }

    @Tool(description = "查询指定城市的天气情况")
    public String queryWeather(
            @ToolParam(description = "城市名称,如:北京、上海、广州") String city
    ) {
        String[] weathers = WEATHER_DATA.get(city);
        if (weathers == null) {
            return "未找到城市 " + city + " 的天气数据,支持的城市:北京、上海、广州、深圳、杭州、成都、武汉、长沙";
        }

        Random random = new Random();
        String weather = weathers[random.nextInt(weathers.length)];
        int temperature = 15 + random.nextInt(20);  // 15-35度
        int humidity = 40 + random.nextInt(40);      // 40-80%

        return String.format("%s天气:%s,温度:%d°C,湿度:%d%%", city, weather, temperature, humidity);
    }

    @Tool(description = "查询多个城市的天气对比")
    public String compareWeather(
            @ToolParam(description = "第一个城市名称") String city1,
            @ToolParam(description = "第二个城市名称") String city2
    ) {
        String weather1 = queryWeather(city1);
        String weather2 = queryWeather(city2);
        return weather1 + "\n" + weather2;
    }
}

时间查询工具:

java 复制代码
/**
 * 时间查询工具
 * 提供日期和时间查询功能
 */
@Component
public class DateTimeTool {

    @Tool(description = "获取当前的日期和时间")
    public String getCurrentDateTime() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        return "当前时间: " + now.format(formatter);
    }

    @Tool(description = "获取当前的日期")
    public String getCurrentDate() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        return "当前日期: " + now.format(formatter);
    }

    @Tool(description = "获取当前的时间")
    public String getCurrentTime() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        return "当前时间: " + now.format(formatter);
    }

    @Tool(description = "计算两个日期之间的天数差")
    public String daysBetween(
            @ToolParam(description = "开始日期,格式: yyyy-MM-dd") String startDate,
            @ToolParam(description = "结束日期,格式: yyyy-MM-dd") String endDate
    ) {
        try {
            LocalDateTime start = LocalDateTime.parse(startDate + "T00:00:00");
            LocalDateTime end = LocalDateTime.parse(endDate + "T00:00:00");
            long days = java.time.temporal.ChronoUnit.DAYS.between(start, end);
            return "从 " + startDate + " 到 " + endDate + " 共有 " + Math.abs(days) + " 天";
        } catch (Exception e) {
            return "日期格式错误,请使用 yyyy-MM-dd 格式";
        }
    }
}

2.4 Agent 配置类

定义 Agent BeanSpring AI Alibaba Studio 自动发现和管理,Studio 会自动扫描所有 ReactAgent Bean 并在界面中展示:

java 复制代码
@Configuration
public class AgentConfig {

    /**
     * 基础聊天 Agent
     * 最简单的 Agent 配置,用于基础对话测试
     */
    @Bean
    public ReactAgent chatAgent(ChatModel dashscopeChatModel) throws GraphRunnerException {
        return ReactAgent.builder()
                .name("chat-agent")
                .description("基础聊天助手,用于简单对话测试")
                .model(dashscopeChatModel)
                .systemPrompt("你是一个友好的 AI 助手,请用中文回答用户的问题。")
                .saver(new MemorySaver())  // 内存存储对话历史
                .enableLogging(true)
                .build();
    }

    /**
     * 工具调用 Agent
     * 配置了时间查询和天气查询工具的 Agent
     */
    @Bean
    public ReactAgent toolAgent(ChatModel dashscopeChatModel,
                                DateTimeTool dateTimeTool,
                                WeatherTool weatherTool) throws GraphRunnerException {
        return ReactAgent.builder()
                .name("tool-agent")
                .description("工具调用助手,支持时间查询和天气查询")
                .model(dashscopeChatModel)
                .methodTools(dateTimeTool, weatherTool)
                .systemPrompt("""
                    你是一个智能助手,可以使用以下工具帮助用户:
                    - 时间查询工具:获取当前日期和时间
                    - 天气查询工具:查询指定城市的天气情况

                    当用户询问时间或天气时,请调用相应的工具。
                    """)
                .saver(new MemorySaver())
                .enableLogging(true)
                .build();
    }

    /**
     * 编程助手 Agent
     * 专注于代码和编程问题的 Agent
     */
    @Bean
    public ReactAgent codingAgent(ChatModel dashscopeChatModel) throws GraphRunnerException {
        return ReactAgent.builder()
                .name("coding-agent")
                .description("编程助手,专注于代码开发和技术问题解答")
                .model(dashscopeChatModel)
                .systemPrompt("""
                    你是一个专业的编程助手,擅长:
                    - Java/Spring 开发
                    - Python 编程
                    - 代码调试和优化
                    - 技术问题解答

                    请提供清晰、专业的技术建议和代码示例。
                    """)
                .saver(new MemorySaver())
                .enableLogging(true)
                .build();
    }

    @Bean("skillAgent")
    public ReactAgent skillAgent(ChatModel dashscopeChatModel) throws GraphRunnerException {

        // 1. 创建 SkillRegistry
        SkillRegistry registry = FileSystemSkillRegistry.builder()
                .userSkillsDirectory(System.getProperty("user.home") + "/saa/skills")
                .projectSkillsDirectory("E:\\TD\\icloud\\study-spring-ai\\spring-ai-alibaba-studio-01\\src\\main\\resources\\skills")
                .autoLoad(true)
                .build();


        // 2. 创建 Hook
        SkillsAgentHook skillsHook = SkillsAgentHook.builder()
                .skillRegistry(registry)           // 必选:技能注册表
                .autoReload(true)                  // 可选:启用自动重载
                .build();

        // 3. 创建 ShellToolAgentHook (支持 shell 命令执行)
        ShellToolAgentHook shellHook = ShellToolAgentHook.builder()
                .build();

        // 4. 创建 agent,同时添加两个 Hook
        ReactAgent agent = ReactAgent.builder()
                .name("skill_agent")
                .model(dashscopeChatModel)
                .hooks(skillsHook, shellHook)  // 添加 Skills 和 Shell 两个 Hook
                .saver(new MemorySaver())
                .enableLogging(true)
                .build();

        return agent;
    }

}

2.5 启动测试

启动应用,访问 http://localhost:8080/chatui/index.html (前端使用相对路径,与后端同域名同端口):

打开一个对话框进行测试:

3. API 端点

3.1 Controller 类

Studio 模块定义了很多 Controller 类,提供 Agent 智能体、Graph 工作流、会话线程完整管理与执行能力。

注册条件:

Controller 注册条件
AgentController 始终注册
ExecutionController 始终注册
GraphController 始终注册(无 Graph 时返回空列表)
GraphExecutionController 仅当 GraphLoader Bean 存在时注册
GraphThreadController 仅当 GraphLoader Bean 存在时注册
ThreadController 始终注册
ChatUiRedirectController 始终注册

3.2 Agent API

Agent 管理:

端点 方法 描述 Controller
/list-apps GET 列出所有可用的 Agent 应用名称 AgentController

Agent 执行 :

端点 方法 描述 Controller
/run_sse POST 执行 Agent 并以 SSE 流式返回结果 ExecutionController
/resume_sse POST 恢复 Agent 执行(处理 Human-in-the-loop 反馈) ExecutionController

3.3 Graph API

Graph 管理:

端点 方法 描述 Controller
/list-graphs GET 列出所有可用的 Graph 名称 GraphController
/graphs/{graphName}/representation GET 获取指定 Graph 的 Mermaid 图表表示 GraphController

Graph 执行:

端点 方法 描述 Controller
/graph_run_sse POST 执行 Graph 并以 SSE 流式返回结果 GraphExecutionController

3.4 Thread API

Agent Thread 管理:

端点 方法 描述 Controller
/apps/{appName}/users/{userId}/threads GET 列出用户的所有线程 ThreadController
/apps/{appName}/users/{userId}/threads POST 创建新线程(自动生成 ID) ThreadController
/apps/{appName}/users/{userId}/threads/{threadId} GET 获取指定线程详情 ThreadController
/apps/{appName}/users/{userId}/threads/{threadId} POST 创建指定 ID 的线程 ThreadController
/apps/{appName}/users/{userId}/threads/{threadId} DELETE 删除指定线程 ThreadController

Graph Thread 管理:

端点 方法 描述 Controller
/graphs/{graphName}/users/{userId}/threads GET 列出用户在指定 Graph 的所有线程 GraphThreadController
/graphs/{graphName}/users/{userId}/threads POST 创建新线程(自动生成 ID) GraphThreadController
/graphs/{graphName}/users/{userId}/threads/{threadId} GET 获取指定线程详情 GraphThreadController
/graphs/{graphName}/users/{userId}/threads/{threadId} POST 创建指定 ID 的线程 GraphThreadController
/graphs/{graphName}/users/{userId}/threads/{threadId} DELETE 删除指定线程 GraphThreadController

3.5 UI 重定向

端点 方法 描述 Controller
/chatui GET 重定向到 /chatui/index.html ChatUiRedirectController
/chatui/ GET 重定向到 /chatui/index.html ChatUiRedirectController

4. 高级用法

4.1 Human-in-the-Loop 支持

定义一个删除文件的工具类:

java 复制代码
public class HitlFileTools {

    /**
     * 删除文件(需要用户确认)
     */
    @Tool(name = "delete_file", description = "根据 文件路径 删除指定文件")
    public String deleteFile(@ToolParam(description = "The absolute path of the file to delete") String filePath) {
        System.out.println("==========================================");
        System.out.println("🔒 HITL 删除文件工具被调用");
        System.out.println("文件路径:" + filePath);
        System.out.println("==========================================");

        // 执行删除
        try {
            System.out.println("✅ 文件删除成功:" + filePath);
            return "文件删除成功:" + filePath;
        } catch (Exception e) {
            System.err.println("❌ 删除文件失败:" + e.getMessage());
            return "删除文件失败:" + e.getMessage();
        }
    }

}

ReactAgent 配置 HumanInTheLoopHook

java 复制代码
    @Bean("chatAgent")
    public ReactAgent chatAgent(DashScopeChatModel dashScopeChatModel) throws GraphRunnerException {
        // 1. 创建 HITL Hook
        HumanInTheLoopHook humanInTheLoopHook = HumanInTheLoopHook.builder()
                .approvalOn(Map.of(
                        "delete_file", ToolConfig.builder()
                                .description("删除文件需要审批")
                                .build()
                ))
                .build();

        // 2. 创建 agent,添加 Hooks 和 HITL 工具
        ReactAgent agent = ReactAgent.builder()
                .name("skill_agent")
                .saver(new MemorySaver()) // 必须配置
                .model(dashScopeChatModel)
                .methodTools(new HitlFileTools())
                .hooks(skillsHook, humanInTheLoopHook)
                .enableLogging(true)
                .build();
        return agent;
    }

删除文件时,会弹出审批页面:

点击 Approve 并提交:

点击 Reject 并提交:

4.2 Graph 工作流支持

Graph 工作流配置:

java 复制代码
@Configuration
public class SimpleGraphConfig {

    /**
     * 创建一个包含 LLM 节点的智能对话工作流
     *
     * 工作流程:
     * START → collectInput(收集输入) → llmNode(大模型处理) → formatOutput(格式化输出) → END
     */
    @Bean
    public CompiledGraph llmWorkflowGraph(ChatModel dashscopeChatModel) throws GraphStateException {
        // 1. 定义键策略工厂
        KeyStrategyFactory keyFactory = () -> {
            Map<String, KeyStrategy> strategies = new HashMap<>();
            strategies.put("messages", new AppendStrategy());       // 消息追加(保留对话历史)
            strategies.put("input", new ReplaceStrategy());         // 输入替换
            strategies.put("llm_response", new ReplaceStrategy());  // LLM 响应替换
            strategies.put("result", new ReplaceStrategy());        // 最终结果替换
            return strategies;
        };

        // 2. 创建 ChatClient(用于 LLM 节点)
        ChatClient chatClient = ChatClient.builder(dashscopeChatModel).build();

        // 3. 创建状态图
        StateGraph graph = new StateGraph("llm_workflow", keyFactory)
                // 收集输入节点:将用户输入转换为消息格式
                .addNode("collectInput", node_async(state -> {
                    String userInput = state.value("input", "");
                    if (userInput.isEmpty()) {
                        userInput = "你好";
                    }
                    return Map.of(
                            "messages", "用户: " + userInput,
                            "input", userInput
                    );
                }))
                // LLM 节点:调用大模型生成响应
                .addNode("llmNode", node_async(state -> {
                    String userInput = state.value("input", "");

                    // 使用 ChatClient 调用大模型
                    String llmResponse = chatClient.prompt()
                            .user(userInput)
                            .system("你是一个友好的 AI 助手,请用中文简洁回答用户的问题。")
                            .call()
                            .content();

                    return Map.of(
                            "messages", "AI: " + llmResponse,
                            "llm_response", llmResponse
                    );
                }))
                // 格式化输出节点:生成最终结果
                .addNode("formatOutput", node_async(state -> {
                    String llmResponse = state.value("llm_response", "");
                    String userInput = state.value("input", "");

                    String formattedResult = String.format("""
                            === 对话结果 ===
                            用户输入: %s
                            AI 回复: %s
                            === 对话结束 ===
                            """, userInput, llmResponse);

                    return Map.of(
                            "messages", formattedResult,
                            "result", formattedResult
                    );
                }))
                // 添加边:定义节点间的流转关系
                .addEdge(START, "collectInput")
                .addEdge("collectInput", "llmNode")
                .addEdge("llmNode", "formatOutput")
                .addEdge("formatOutput", END);

        // 4. 编译并返回
        return graph.compile();
    }

    /**
     * 创建一个简单的 Echo 工作流(不含 LLM)
     * 用于测试和演示基础 Graph 结构
     */
    @Bean
    public CompiledGraph simpleWorkflowGraph() throws GraphStateException {
        // 1. 定义键策略工厂
        KeyStrategyFactory keyFactory = () -> {
            Map<String, KeyStrategy> strategies = new HashMap<>();
            strategies.put("messages", new AppendStrategy(false));  // 消息追加
            strategies.put("result", new ReplaceStrategy());        // 结果替换
            return strategies;
        };

        // 2. 创建状态图
        StateGraph graph = new StateGraph("simple_workflow", keyFactory)
                // 添加 Echo 节点
                .addNode("echo", node_async(state -> {
                    Object messages = state.value("messages").orElse(null);
                    return Map.of("result", "echo: " +
                            (messages != null ? messages.toString() : "empty"));
                }))
                // 添加边
                .addEdge(START, "echo")
                .addEdge("echo", END);

        // 3. 编译并返回
        return graph.compile();
    }
}

Studio 首页中会显示可用工作流:

可以在工作流对话窗口,查看图结构、进行对话,会显示整个工作流的执行过程:

4.3 独立运行模式

嵌入式模式UI 可作为嵌入式组件集成到你的任意 Spring Boot 应用中。前后端一体,静态资源打包在 JAR 中。
独立部署模式:前后端分离,独立部署。

独立运行前端开发服务器:

bash 复制代码
# 1. 克隆仓库

git clone https://github.com/alibaba/spring-ai-alibaba.git
cd spring-ai-alibaba/spring-ai-alibaba-studio/agent-chat-ui

# 2. 安装依赖
pnpm install
# 或
# npm install

# 3. 启动应用
pnpm dev
# 或
# npm run dev

应用启动后访问:http://localhost:3000

UI 默认连接后端 Agent 地址:http://localhost:8080,可在 .env.development 文件中修改配置:

bash 复制代码
# .env.development
# 后端 API 地址
NEXT_PUBLIC_API_URL=http://localhost:8080
# 后端应用中调用的 Agent 名称,后端需按需求注册对应 Agent,配置方式参考示例
NEXT_PUBLIC_APP_NAME=research_agent
# 用户 ID
NEXT_PUBLIC_USER_ID=user-001

4.4 自定义 Agent/GraphLoader 加载器

定义了 Agent GraphLoader 机制,自动注册:

  • 自动发现所有 Agent 类型:ReactAgentSequentialAgentParallelAgentLlmRoutingAgent
  • 自动发现所有 CompiledGraph 类型:与 AgentLoader 设计一致,但作用于 CompiledGraph


AgentLoaderGraphLoader 接口:

java 复制代码
public interface AgentLoader {

	@Nonnull
	List<String> listAgents();

	Agent loadAgent(String name);
}
public interface GraphLoader {

	@Nonnull
	List<String> listGraphs();

	CompiledGraph loadGraph(String name);
}

默认从 Spring 容器中进行查找:

java 复制代码
	protected static Map<String, Agent> discoverFromContext(ApplicationContext context) {
		Map<String, Agent> beans = context.getBeansOfType(Agent.class);
		Map<String, Agent> result = new LinkedHashMap<>();
		for (Agent agent : beans.values()) {
			String name = agent.name();
			if (result.putIfAbsent(name, agent) != null) {
				log.warn("Duplicate agent name '{}', keeping first. Consider using unique agent names for Studio.", name);
			}
		}
		return result;
	}

可以覆盖默认扫描行为,只暴露 chatcode 两个 Agent 示例:

java 复制代码
@Component
public class MyAgentLoader extends AbstractAgentLoader {
    private final Agent chatAgent;
    private final Agent codeAgent;

    public MyAgentLoader(@Qualifier("chatAgent") Agent chatAgent,
                         @Qualifier("codeAgent") Agent codeAgent) {
        this.chatAgent = chatAgent;
        this.codeAgent = codeAgent;
    }

    @Override
    protected Map<String, Agent> loadAgentMap() {
        return Map.of("chat", chatAgent, "code", codeAgent);
    }
}

4.5 生产环境自动关闭

4.5.1 方案一:排除自动配置(推荐)

Studio 模块中的自动配置类,会扫描 com.alibaba.cloud.ai.agent.studio 路径,并加载到 Spring 容器中:

java 复制代码
@Configuration
@ComponentScan(basePackages = "com.alibaba.cloud.ai.agent.studio")
public class SaaStudioWebModuleAutoConfiguration {
	public SaaStudioWebModuleAutoConfiguration() {
		System.out.println("✅ Spring AI Alibaba Studio module loaded!");
	}
}

可以在生成环境的 application.yml 中排除自动配置:

yml 复制代码
# application-prod.yml
spring:
  autoconfigure:
    exclude:
      - com.alibaba.cloud.ai.agent.studio.loader.StudioLoaderAutoConfiguration

或在启动类:

java 复制代码
@SpringBootApplication(exclude = {
    StudioLoaderAutoConfiguration.class
})

4.5.2 方案二:Maven 依赖控制

仅测试环境使用:

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-studio</artifactId>
    <scope>test</scope> 
</dependency>

或使用 profile 区分:

xml 复制代码
<dependencies>
    <!-- 生产环境不引入 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-studio</artifactId>
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
</dependencies>
相关推荐
Coffeeee17 小时前
帮你快速理解AI Agent之我想招个Android实习生
android·人工智能·agent
用户2986985301418 小时前
Java 实现 Word 文档文本与图片提取的方法
java·后端
新新技术迷18 小时前
AI聊天自动跟随滚动,附回到底部按钮
人工智能
先锋部队18 小时前
用Web Worker解析AI返回的大文本不卡UI
人工智能
把你拉进白名单18 小时前
8.OpenClaw源码解析——三层洋葱重试
人工智能·llm·agent
用户6324150317818 小时前
拖文档进AI对话框解析,前端要处理哪些脏活
人工智能
姗姗来迟了18 小时前
AI回答里的引用来源卡片,前端怎么做
人工智能
用户71062077334018 小时前
Codex-端口配置错误排查案例(stream disconnected before completion)
人工智能
SimonKing18 小时前
铁子,IntelliJ IDEA 2026.1.3来了,升不升?
java·后端·程序员