📖目录
- 前言
- 1. 什么是 Agent?为什么需要它?
- 2. Agent 核心能力全景图
- 3. 核心功能详解(结合 AgentsExample.java)
-
- 3.1 基础配置:模型与 Prompt
- 3.2 工具集成:让 Agent “动手”
- 3.3 动态 Prompt:上下文感知
- 3.4 对话记忆:支持多轮上下文
- 3.5 流式响应:实时输出
- 3.6 结构化输出:强制 JSON/POJO
- 4. 高级扩展:Hook 与 Interceptor
-
- 4.1 Agent 生命周期钩子(Hook)
- 4.2 模型调用拦截器(Interceptor)
- 5. 完整源码及执行结果
-
- 5.1 完整源码
- 5.2 执行结果
- 5. 执行上下文分析
- 6. 生产建议
- 7. 结语
- 8. 福利资源
- 写在文末:关于技术写作的一点初衷
前言
📌 本文基于 Spring AI Alibaba 最新版本(2025 年 11 月,兼容 Spring Boot 3.5.7 / Spring Cloud Alibaba 2023.0.x) ✅ 适合中高级 Java 开发者、AI 应用架构师阅读 🔗 官方文档:https://sca.aliyun.com/en/docs/ai/overview/ 💡 参考代码说明:本文所有示例均直接源自官网提供的 AgentsExample.java 文件(位于 spring-ai-alibaba/examples/documentation/framework/tutorials/ 路径下),该文件是 Spring AI Alibaba 官方团队发布的 Agent 教程核心示例。文中关键代码片段已做精简,完整逻辑请以该文件为准。
在上一篇《【Spring AI Alibaba】① 技术内核全解析》中,我们系统剖析了框架的整体架构、核心组件(ChatClient、VectorStore、Function Calling)以及“模型无关”的扩展哲学——回答了 “Spring AI Alibaba 是什么、为何这样设计” 的问题。
而本文将聚焦一个更贴近业务落地的主题:如何用它构建真正能“思考+行动”的智能体(Agent)?
如果说第一篇讲的是“骨架”,那么本篇就是“肌肉与神经”——我们将深入 ReactAgent 的完整能力体系,涵盖:
- 工具调用与错误兜底
- 对话记忆(Memory)
- 动态 Prompt 注入
- 流式响应(Streaming)
- 结构化输出(Structured Output)
- 全链路拦截与生命周期钩子(Interceptor & Hook)
所有内容均基于官方 AgentsExample.java 示例,带你从理论走向可运行、可调试、可扩展的生产级实践。
1. 什么是 Agent?为什么需要它?
Agent = LLM + 工具 + 记忆 + 规划能力。其核心价值在于:
让大模型不仅能“说”,还能“做”。
典型场景:
- 自动化客服(查订单、退换货)
- 运维助手(查日志、重启服务)
- 数据分析师(查数据库、生成图表)
Spring AI Alibaba 的 ReactAgent 基于 ReAct(Reasoning + Acting) 范式,让模型在“思考”与“行动”间循环,直至达成目标。
2. Agent 核心能力全景图
根据 AgentsExample.java,Spring AI Alibaba Agent 支持以下能力模块(文本流程图):
┌───────────────────────┐
│ User Input │
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Dynamic System │◄─── ModelInterceptor (动态Prompt)
│ Prompt / Instruction│
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Tool Selection & │◄─── ToolCallback (工具定义)
│ Execution │◄─── ToolInterceptor (错误监控)
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Memory Management │◄─── MemorySaver (对话记忆)
│ (Thread Context) │
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Structured Output │◄─── outputType / outputSchema
│ (JSON / POJO) │
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Response Streaming │◄─── Flux<NodeOutput>
│ or Blocking Call │
└──────────┬────────────┘
▼
┌───────────────────────┐
│ Agent Hooks │◄─── BEFORE_AGENT / AFTER_AGENT
│ (Logging, Metrics) │
└───────────────────────┘
💡 关键设计:所有环节均可通过 Interceptor 或 Hook 插入自定义逻辑,实现非侵入式增强。
3. 核心功能详解(结合 AgentsExample.java)
3.1 基础配置:模型与 Prompt
// 示例1:基础模型配置
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.build();
支持高级参数(温度、Token 限制等):
// 示例2:高级模型配置
.defaultOptions(DashScopeChatOptions.builder()
.withTemperature(0.7)
.withMaxToken(2000)
.build())
3.2 工具集成:让 Agent “动手”
定义工具(实现 BiFunction):
// 示例3:工具定义
public static class SearchTool implements BiFunction<String, ToolContext, String> {
@Override
public String apply(@ToolParam(description = "搜索关键词") String query, ToolContext ctx) {
return "搜索结果:" + query;
}
}
注册工具并启用错误拦截:
// 示例4:工具错误处理(需自定义 ToolErrorInterceptor)
ReactAgent agent = ReactAgent.builder()
.tools(FunctionToolCallback.builder("search", new SearchTool()).build())
.interceptors(new ToolErrorInterceptor()) // 拦截工具异常
.build();
3.3 动态 Prompt:上下文感知
通过 ModelInterceptor 动态注入 Prompt:
// 示例7:动态 System Prompt
public static class DynamicPromptInterceptor extends ModelInterceptor {
@Override
public ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {
String userRole = (String) request.getContext().getOrDefault("user_role", "default");
String dynamicPrompt = switch (userRole) {
case "expert" -> "你正在与技术专家对话…";
case "beginner" -> "你正在与初学者对话…";
default -> "你是一个专业的助手…";
};
// 增强 SystemMessage
SystemMessage enhanced = new SystemMessage(request.getSystemMessage().getText() + "\\n\\n" + dynamicPrompt);
return handler.call(ModelRequest.builder(request).systemMessage(enhanced).build());
}
}
3.4 对话记忆:支持多轮上下文
使用 MemorySaver 维护会话状态:
// 示例13:配置记忆
ReactAgent agent = ReactAgent.builder()
.saver(new MemorySaver()) // 内存存储(生产环境建议用 Redis)
.build();
RunnableConfig config = RunnableConfig.builder().threadId("user_123").build();
agent.call("我叫张三", config);
AssistantMessage resp = agent.call("我叫什么名字?", config); // 输出: "你叫张三"
3.5 流式响应:实时输出
支持 Reactive 流式处理:
// 示例10.1:基础流式调用
Flux<NodeOutput> stream = agent.stream("帮我写一首关于春天的诗");
stream.subscribe(output -> {
if (!output.isSTART() && !output.isEND()) {
System.out.println("Token: " + output.tokenUsage());
}
});
3.6 结构化输出:强制 JSON/POJO
两种方式:
- 类型安全:outputType(PoemOutput.class)
- Schema 约束:outputSchema("{summary:…, keywords:…}")
// 示例11:outputType
ReactAgent agent = ReactAgent.builder()
.outputType(PoemOutput.class) // 自动校验并反序列化
.build();
4. 高级扩展:Hook 与 Interceptor
4.1 Agent 生命周期钩子(Hook)
// 示例14:日志 Hook
public static class LoggingHook extends AgentHook {
@Override
public HookPosition[] getHookPositions() {
return new HookPosition[]{HookPosition.BEFORE_AGENT, HookPosition.AFTER_AGENT};
}
@Override
public CompletableFuture<Map<String, Object>> beforeAgent(...) {
System.out.println("Agent 开始执行");
return CompletableFuture.completedFuture(Map.of());
}
}
4.2 模型调用拦截器(Interceptor)
用于内容安全、消息裁剪等:
// 示例15:消息裁剪 Hook(防 Token 超限)
public static class MessageTrimmingHook extends ModelHook {
private static final int MAX_MESSAGES = 10;
@Override
public CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, ...) {
List<Message> messages = (List<Message>) state.value("messages").orElse(List.of());
if (messages.size() > MAX_MESSAGES) {
return CompletableFuture.completedFuture(
Map.of("messages", messages.subList(messages.size() – MAX_MESSAGES, messages.size()))
);
}
return CompletableFuture.completedFuture(Map.of());
}
}
5. 完整源码及执行结果
5.1 完整源码
- 选择你的 LLM 提供商并获取 API-KEY(如阿里云百炼的 DashScope),格式为:sk-xxx
- 需要设置系统全局变量:AI_DASHSCOPE_API_KEY = sk-xxxx
- 将语句【System.getenv(“AI_DASHSCOPE_API_KEY”) 】替换成具体的api-key
/*
* Copyright 2024-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.cloud.ai.examples.documentation.framework.tutorials;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.alibaba.cloud.ai.graph.NodeOutput;
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.hook.AgentHook;
import com.alibaba.cloud.ai.graph.agent.hook.HookPosition;
import com.alibaba.cloud.ai.graph.agent.hook.ModelHook;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelCallHandler;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelInterceptor;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelRequest;
import com.alibaba.cloud.ai.graph.agent.interceptor.ModelResponse;
import com.alibaba.cloud.ai.graph.agent.interceptor.ToolCallHandler;
import com.alibaba.cloud.ai.graph.agent.interceptor.ToolCallRequest;
import com.alibaba.cloud.ai.graph.agent.interceptor.ToolCallResponse;
import com.alibaba.cloud.ai.graph.agent.interceptor.ToolInterceptor;
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.ai.tool.function.FunctionToolCallback;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import reactor.core.publisher.Flux;
/**
* Agents Tutorial – agents.md
*/
public class AgentsExample {
// ==================== 基础模型配置 ====================
/**
* 示例1:基础模型配置
*/
public static void basicModelConfiguration() {
// 创建 DashScope API 实例
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
// 创建 ChatModel
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
// 创建 Agent
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.build();
}
/**
* 示例2:高级模型配置
*/
public static void advancedModelConfiguration() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
.withTemperature(0.7) // 控制随机性
.withMaxToken(2000) // 最大输出长度
.withTopP(0.9) // 核采样参数
.build())
.build();
}
// ==================== 工具定义 ====================
public static void toolUsage() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
// 创建工具回调
ToolCallback searchTool = FunctionToolCallback
.builder("search", new SearchTool())
.description("搜索信息的工具")
.inputType(String.class)
.build();
// 使用多个工具
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.tools(searchTool)
.build();
}
/**
* 示例5:基础 System Prompt
*/
public static void basicSystemPrompt() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.systemPrompt("你是一个专业的技术助手。请准确、简洁地回答问题。")
.build();
}
/**
* 示例6:使用 instruction
*/
public static void instructionUsage() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
String instruction = """
你是一个经验丰富的软件架构师。
在回答问题时,请:
1. 首先理解用户的核心需求
2. 分析可能的技术方案
3. 提供清晰的建议和理由
4. 如果需要更多信息,主动询问
保持专业、友好的语气。
""";
ReactAgent agent = ReactAgent.builder()
.name("architect_agent")
.model(chatModel)
.instruction(instruction)
.build();
}
// ==================== System Prompt ====================
public static void dynamicSystemPrompt() {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("adaptive_agent")
.model(chatModel)
.interceptors(new DynamicPromptInterceptor())
.build();
}
/**
* 示例8:基础调用
*/
public static void basicInvocation() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.build();
// 字符串输入
AssistantMessage response = agent.call("杭州的天气怎么样?");
System.out.println(response.getText());
// UserMessage 输入
UserMessage userMessage = new UserMessage("帮我分析这个问题");
AssistantMessage response2 = agent.call(userMessage);
// 多个消息
List<Message> messages = List.of(
new UserMessage("我想了解 Java 多线程"),
new UserMessage("特别是线程池的使用")
);
AssistantMessage response3 = agent.call(messages);
}
/**
* 示例9:获取完整状态
*/
public static void getFullState() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.build();
Optional<OverAllState> result = agent.invoke("帮我写一首诗");
if (result.isPresent()) {
OverAllState state = result.get();
// 访问消息历史
Optional<Object> messages = state.value("messages");
List<Message> messageList = (List<Message>) messages.get();
// 访问自定义状态
Optional<Object> customData = state.value("custom_key");
System.out.println("完整状态:" + state);
}
}
/**
* 示例10:使用配置
*/
public static void useConfiguration() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("my_agent")
.model(chatModel)
.build();
String threadId = "thread_123";
RunnableConfig runnableConfig = RunnableConfig.builder()
.threadId(threadId)
.addMetadata("key", "value")
.build();
AssistantMessage response = agent.call("你的问题", runnableConfig);
}
// ==================== 调用 Agent ====================
/**
* 示例10.1:流式调用 – 基础用法
*/
public static void basicStreamInvocation() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("streaming_agent")
.model(chatModel)
.build();
// 流式输出
Flux<NodeOutput> stream = agent.stream("帮我写一首关于春天的诗");
stream.subscribe(
output -> {
// 处理每个节点输出
System.out.println("节点: " + output.node());
System.out.println("Agent: " + output.agent());
if (output.tokenUsage() != null) {
System.out.println("Token使用: " + output.tokenUsage());
}
},
error -> System.err.println("错误: " + error.getMessage()),
() -> System.out.println("流式输出完成")
);
}
/**
* 示例10.2:流式调用 – 高级用法
*/
public static void advancedStreamInvocation() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("streaming_agent")
.model(chatModel)
.saver(new MemorySaver())
.build();
RunnableConfig config = RunnableConfig.builder()
.threadId("stream_thread_1")
.build();
// 使用配置的流式调用
Flux<NodeOutput> stream = agent.stream(new UserMessage("解释一下量子计算"), config);
// 使用 doOnNext 处理中间输出
stream.doOnNext(output -> {
if (!output.isSTART() && !output.isEND()) {
System.out.println("处理中…");
System.out.println("当前节点: " + output.node());
}
})
.doOnComplete(() -> System.out.println("所有节点处理完成"))
.doOnError(e -> System.err.println("流处理错误: " + e.getMessage()))
.blockLast(); // 阻塞等待完成
}
/**
* 示例10.3:流式调用 – 收集所有输出
*/
public static void collectStreamOutputs() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("streaming_agent")
.model(chatModel)
.build();
Flux<NodeOutput> stream = agent.stream("分析机器学习的应用场景");
// 收集所有输出
List<NodeOutput> outputs = stream.collectList().block();
if (outputs != null) {
System.out.println("总共收到 " + outputs.size() + " 个节点输出");
// 获取最终输出
NodeOutput lastOutput = outputs.get(outputs.size() – 1);
System.out.println("最终状态: " + lastOutput.state());
// 获取消息
Optional<Object> messages = lastOutput.state().value("messages");
if (messages.isPresent()) {
List<Message> messageList = (List<Message>) messages.get();
Message lastMessage = messageList.get(messageList.size() – 1);
if (lastMessage instanceof AssistantMessage assistantMsg) {
System.out.println("最终回复: " + assistantMsg.getText());
}
}
}
}
public static void structuredOutputWithType() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
ReactAgent agent = ReactAgent.builder()
.name("poem_agent")
.model(chatModel)
.outputType(PoemOutput.class)
.saver(new MemorySaver())
.build();
AssistantMessage response = agent.call("写一首关于春天的诗");
// 输出会遵循 PoemOutput 的结构
System.out.println(response.getText());
}
/**
* 示例12:使用 outputSchema
*/
public static void structuredOutputWithSchema() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
String customSchema = """
请严格按照以下JSON格式返回结果:
{
"summary": "内容摘要",
"keywords": ["关键词1", "关键词2", "关键词3"],
"sentiment": "情感倾向(正面/负面/中性)",
"confidence": 0.95
}
""";
ReactAgent agent = ReactAgent.builder()
.name("analysis_agent")
.model(chatModel)
.outputSchema(customSchema)
.saver(new MemorySaver())
.build();
AssistantMessage response = agent.call("分析这段文本:春天来了,万物复苏。");
}
/**
* 示例13:配置记忆
*/
public static void configureMemory() throws GraphRunnerException {
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY"))
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
// 配置内存存储
ReactAgent agent = ReactAgent.builder()
.name("chat_agent")
.model(chatModel)
.saver(new MemorySaver())
.build();
// 使用 thread_id 维护对话上下文
RunnableConfig config = RunnableConfig.builder()
.threadId("user_123")
.build();
agent.call("我叫张三", config);
agent.call("我叫什么名字?", config); // 输出: "你叫张三"
}
// ==================== 结构化输出 ====================
public static void main(String[] args) {
System.out.println("=== Agents Tutorial Examples ===");
System.out.println("注意:需要设置 AI_DASHSCOPE_API_KEY 环境变量\\n");
try {
System.out.println("\\n— 示例1:基础模型配置 —");
basicModelConfiguration();
System.out.println("\\n— 示例2:高级模型配置 —");
advancedModelConfiguration();
System.out.println("\\n— 示例3:工具使用 —");
toolUsage();
System.out.println("\\n— 示例5:基础 System Prompt —");
basicSystemPrompt();
System.out.println("\\n— 示例6:使用 instruction —");
instructionUsage();
System.out.println("\\n— 示例7:动态 System Prompt —");
dynamicSystemPrompt();
System.out.println("\\n— 示例8:基础调用 —");
basicInvocation();
System.out.println("\\n— 示例9:获取完整状态 —");
getFullState();
System.out.println("\\n— 示例10:使用配置 —");
useConfiguration();
System.out.println("\\n— 示例10.1:流式调用 – 基础用法 —");
basicStreamInvocation();
System.out.println("\\n— 示例10.2:流式调用 – 高级用法 —");
advancedStreamInvocation();
System.out.println("\\n— 示例10.3:流式调用 – 收集所有输出 —");
collectStreamOutputs();
System.out.println("\\n— 示例11:使用 outputType —");
structuredOutputWithType();
System.out.println("\\n— 示例12:使用 outputSchema —");
structuredOutputWithSchema();
System.out.println("\\n— 示例13:配置记忆 —");
configureMemory();
System.out.println("\\n=== 所有示例执行完成 ===");
}
catch (GraphRunnerException e) {
System.err.println("执行示例时发生错误: " + e.getMessage());
e.printStackTrace();
}
catch (Exception e) {
System.err.println("发生未预期的错误: " + e.getMessage());
e.printStackTrace();
}
}
/**
* 示例3:定义和使用工具
*/
public static class SearchTool implements BiFunction<String, ToolContext, String> {
@Override
public String apply(
@ToolParam(description = "搜索关键词") String query,
ToolContext toolContext) {
return "搜索结果:" + query;
}
}
/**
* 示例4:工具错误处理
*/
public static class ToolErrorInterceptor extends ToolInterceptor {
@Override
public ToolCallResponse interceptToolCall(ToolCallRequest request, ToolCallHandler handler) {
try {
return handler.call(request);
}
catch (Exception e) {
return ToolCallResponse.of(request.getToolCallId(), request.getToolName(),
"Tool failed: " + e.getMessage());
}
}
@Override
public String getName() {
return "ToolErrorInterceptor";
}
}
// ==================== Memory ====================
/**
* 示例7:动态 System Prompt
*/
public static class DynamicPromptInterceptor extends ModelInterceptor {
@Override
public ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {
// 基于上下文动态调整 system prompt
Map<String, Object> context = request.getContext();
// 根据上下文构建动态提示词
String dynamicPrompt = buildDynamicPrompt(context);
// 增强 system message
SystemMessage enhancedSystemMessage;
if (request.getSystemMessage() == null) {
enhancedSystemMessage = new SystemMessage(dynamicPrompt);
}
else {
enhancedSystemMessage = new SystemMessage(
request.getSystemMessage().getText() + "\\n\\n" + dynamicPrompt
);
}
// 创建增强的请求
ModelRequest modifiedRequest = ModelRequest.builder(request)
.systemMessage(enhancedSystemMessage)
.build();
return handler.call(modifiedRequest);
}
private String buildDynamicPrompt(Map<String, Object> context) {
// 示例:根据用户角色动态生成提示词
String userRole = (String) context.getOrDefault("user_role", "default");
return switch (userRole) {
case "expert" -> """
你正在与技术专家对话。
– 使用专业术语
– 深入技术细节
– 提供高级建议
""";
case "beginner" -> """
你正在与初学者对话。
– 使用简单易懂的语言
– 详细解释概念
– 提供入门级建议
""";
default -> """
你是一个专业的助手。
– 根据问题复杂度调整回答
– 保持友好和专业
""";
};
}
@Override
public String getName() {
return "DynamicPromptInterceptor";
}
}
// ==================== Hooks ====================
/**
* 示例11:使用 outputType
*/
public static class PoemOutput {
private String title;
private String content;
private String style;
// Getters and Setters
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
}
/**
* 示例14:AgentHook – 在 Agent 开始/结束时执行
*/
public static class LoggingHook extends AgentHook {
@Override
public String getName() {
return "logging";
}
@Override
public HookPosition[] getHookPositions() {
return new HookPosition[] {
HookPosition.BEFORE_AGENT,
HookPosition.AFTER_AGENT
};
}
@Override
public CompletableFuture<Map<String, Object>> beforeAgent(OverAllState state, RunnableConfig config) {
System.out.println("Agent 开始执行");
return CompletableFuture.completedFuture(Map.of());
}
@Override
public CompletableFuture<Map<String, Object>> afterAgent(OverAllState state, RunnableConfig config) {
System.out.println("Agent 执行完成");
return CompletableFuture.completedFuture(Map.of());
}
}
// ==================== Interceptors ====================
/**
* 示例15:ModelHook – 在模型调用前后执行
*/
public static class MessageTrimmingHook extends ModelHook {
private static final int MAX_MESSAGES = 10;
@Override
public String getName() {
return "message_trimming";
}
@Override
public HookPosition[] getHookPositions() {
return new HookPosition[] {HookPosition.BEFORE_MODEL};
}
@Override
public CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {
Optional<Object> messagesOpt = state.value("messages");
if (messagesOpt.isPresent()) {
List<Message> messages = (List<Message>) messagesOpt.get();
if (messages.size() > MAX_MESSAGES) {
return CompletableFuture.completedFuture(Map.of("messages",
messages.subList(messages.size() – MAX_MESSAGES, messages.size())));
}
}
return CompletableFuture.completedFuture(Map.of());
}
@Override
public CompletableFuture<Map<String, Object>> afterModel(OverAllState state, RunnableConfig config) {
return CompletableFuture.completedFuture(Map.of());
}
}
/**
* 示例16:ModelInterceptor – 内容安全检查
*/
public static class GuardrailInterceptor extends ModelInterceptor {
@Override
public ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {
// 前置:检查输入
if (containsSensitiveContent(request.getMessages())) {
return ModelResponse.of(new AssistantMessage("检测到不适当的内容"));
}
// 执行调用
ModelResponse response = handler.call(request);
// 后置:检查输出
return sanitizeIfNeeded(response);
}
private boolean containsSensitiveContent(List<Message> messages) {
// 实现敏感内容检测逻辑
return false;
}
private ModelResponse sanitizeIfNeeded(ModelResponse response) {
// 实现响应清理逻辑
return response;
}
@Override
public String getName() {
return "GuardrailInterceptor";
}
}
// ==================== Main 方法 ====================
/**
* 示例17:ToolInterceptor – 监控和错误处理
*/
public static class ToolMonitoringInterceptor extends ToolInterceptor {
@Override
public ToolCallResponse interceptToolCall(ToolCallRequest request, ToolCallHandler handler) {
long startTime = System.currentTimeMillis();
try {
ToolCallResponse response = handler.call(request);
logSuccess(request, System.currentTimeMillis() – startTime);
return response;
}
catch (Exception e) {
logError(request, e, System.currentTimeMillis() – startTime);
return ToolCallResponse.of(request.getToolCallId(), request.getToolName(),
"工具执行遇到问题,请稍后重试");
}
}
private void logSuccess(ToolCallRequest request, long duration) {
System.out.println("Tool " + request.getToolName() + " succeeded in " + duration + "ms");
}
private void logError(ToolCallRequest request, Exception e, long duration) {
System.err.println("Tool " + request.getToolName() + " failed in " + duration + "ms: " + e.getMessage());
}
@Override
public String getName() {
return "ToolMonitoringInterceptor";
}
}
}
5.2 执行结果
=== Agents Tutorial Examples ===
注意:需要设置 AI_DASHSCOPE_API_KEY 环境变量
— 示例1:基础模型配置 —
— 示例2:高级模型配置 —
— 示例3:工具使用 —
— 示例5:基础 System Prompt —
— 示例6:使用 instruction —
— 示例7:动态 System Prompt —
— 示例8:基础调用 —
我目前无法获取实时天气信息。建议您通过可靠的天气预报网站或应用(如中国气象局、中央气象台、天气通、墨迹天气等)查询杭州当前的天气情况。通常这些平台会提供温度、湿度、风力、空气质量以及未来几天的天气趋势等详细信息。
如果您告诉我具体想了解的时间段(比如今天、明天或未来一周),我可以帮您分析一般情况下杭州那个时段的气候特点。
— 示例9:获取完整状态 —
完整状态:{"OverAllState":{"data":{"input":"帮我写一首诗","messages":[{"messageType":"USER","metadata":{"messageType":"USER"},"media":[],"text":"帮我写一首诗"},{"messageType":"ASSISTANT","metadata":{"search_info":"","role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","id":"4fac813d-4144-4811-a0ff-9c3fc98478d9","reasoningContent":""},"toolCalls":[],"media":[],"text":"春风拂柳绿成行, \\n细雨轻沾花自香。 \\n燕语呢喃穿旧巷, \\n蝶影翩跹过矮墙。 \\n\\n远山含黛云作裳, \\n流水潺潺入梦长。 \\n不问人间纷扰事, \\n一壶清酒醉斜阳。"}]}}}
— 示例10:使用配置 —
— 示例10.1:流式调用 – 基础用法 —
节点: __START__
Agent: streaming_agent
— 示例10.2:流式调用 – 高级用法 —
处理中…
当前节点: model
处理中…
当前节点: model
节点: model
Agent: streaming_agent
Token使用: DefaultUsage{promptTokens=15, completionTokens=1, totalTokens=16}
处理中…
当前节点: model
节点: model
Agent: streaming_agent
Token使用: DefaultUsage{promptTokens=15, completionTokens=3, totalTokens=18}
(中间省略…)
节点: model
Agent: streaming_agent
Token使用: DefaultUsage{promptTokens=15, completionTokens=103, totalTokens=118}
节点: __END__
Agent: streaming_agent
流式输出完成
处理中…
当前节点: model
处理中…
(中间省略…)
当前节点: model
所有节点处理完成
— 示例10.3:流式调用 – 收集所有输出 —
总共收到 246 个节点输出
最终状态: {"OverAllState":{"data":{"input":"分析机器学习的应用场景","messages":[{"messageType":"USER","metadata":{"messageType":"USER"},"media":[],"text":"分析机器学习的应用场景"},{"messageType":"ASSISTANT","metadata":{"search_info":"","role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","id":"54b1fea9-c981-4580-9bc2-5a9358d1f584","reasoningContent":""},"toolCalls":[],"media":[],"text":"机器学习(Machine Learning, ML)作为人工智能的核心技术之一,已在众多领域展现出强大的应用潜力。它通过从数据中自动学习模式和规律,实现预测、分类、聚类、推荐等功能。以下是机器学习的主要应用场景分析:\\n\\n—\\n\\n### 1. **互联网与电子商务**\\n- **个性化推荐系统** \\n 如电商网站(淘宝、京东)、视频平台(Netflix、YouTube)利用协同过滤、深度学习等算法为用户推荐商品或内容。\\n- **搜索引擎优化** \\n 通过自然语言处理(NLP)和排序学习(Learning to Rank)提升搜索结果的相关性。\\n- **广告投放与点击率预测** \\n 利用机器学习模型预测用户对广告的点击概率,实现精准营销。\\n\\n—\\n\\n### 2. **金融科技(FinTech)**\\n- **信用评分与风控** \\n 基于用户历史行为、交易记录等数据构建信用评估模型,判断贷款违约风险。\\n- **欺诈检测** \\n 使用异常检测算法识别信用卡盗刷、洗钱等异常交易行为。\\n- **股票市场预测与量化交易** \\n 利用时间序列分析、强化学习等方法辅助投资决策(需注意市场不确定性)。\\n\\n—\\n\\n### 3. **医疗健康**\\n- **疾病诊断与辅助决策** \\n 图像识别用于医学影像分析(如X光、CT、MRI),辅助医生诊断癌症、肺炎等疾病。\\n- **基因组学与药物研发** \\n 分析基因序列数据,发现致病基因;加速新药分子筛选过程。\\n- **健康监测与预测** \\n 可穿戴设备结合机器学习预测心律失常、糖尿病并发症等。\\n\\n—\\n\\n### 4. **智能制造与工业自动化**\\n- **预测性维护(Predictive Maintenance)** \\n 分析传感器数据预测设备故障,减少停机时间和维修成本。\\n- **质量控制** \\n 利用计算机视觉检测产品缺陷(如芯片、汽车零部件)。\\n- **生产流程优化** \\n 通过强化学习或回归模型优化参数配置,提高生产效率。\\n\\n—\\n\\n### 5. **交通运输与自动驾驶**\\n- **智能交通管理** \\n 预测交通流量、优化信号灯控制,缓解拥堵。\\n- **自动驾驶** \\n 感知(目标检测、语义分割)、决策(路径规划)、控制(动作执行)均依赖深度学习与强化学习。\\n- **路径规划与物流优化** \\n 快递配送路线优化、网约车调度等使用图神经网络或运筹学结合ML的方法。\\n\\n—\\n\\n### 6. **自然语言处理(NLP)**\\n- **语音识别与合成** \\n 如Siri、小爱同学等智能助手背后的语音转文字、文字转语音技术。\\n- **机器翻译** \\n Google Translate、DeepL 等基于Transformer架构实现高质量翻译。\\n- **情感分析与舆情监控** \\n 分析社交媒体评论、新闻文本中的情绪倾向,用于品牌管理或政策制定。\\n\\n—\\n\\n### 7. **教育科技(EdTech)**\\n- **个性化学习路径推荐** \\n 根据学生的学习行为和成绩推荐适合的学习资源。\\n- **智能阅卷与作业批改** \\n 自动批改选择题、填空题甚至作文(结合NLP)。\\n- **学习效果预测** \\n 预测学生是否可能挂科,提前干预。\\n\\n—\\n\\n### 8. **农业与环境科学**\\n- **精准农业** \\n 利用遥感图像和气象数据预测作物产量、病虫害风险。\\n- **气候建模与灾害预警** \\n 分析气候变化趋势,预测洪水、干旱等自然灾害。\\n- **土壤与水质分析** \\n 传感器数据结合模型评估土地适宜性或污染程度。\\n\\n—\\n\\n### 9. **安全与安防**\\n- **人脸识别与身份验证** \\n 广泛应用于门禁系统、支付验证、公共安全监控。\\n- **网络安全威胁检测** \\n 检测恶意软件、DDoS攻击、异常登录行为等。\\n- **视频监控智能分析** \\n 行为识别(如跌倒、打架)、人群密度监测等。\\n\\n—\\n\\n### 10. **娱乐与创意产业**\\n- **内容生成(AIGC)** \\n 文本生成(如ChatGPT)、图像生成(如Stable Diffusion)、音乐创作等。\\n- **游戏AI** \\n NPC智能行为设计、游戏平衡性调优、玩家行为预测。\\n- **影视特效与后期制作** \\n 深度伪造(Deepfake)、自动剪辑、画质增强等。\\n\\n—\\n\\n## 总结:机器学习应用的关键特点\\n\\n| 特点 | 说明 |\\n|——|——|\\n| **数据驱动** | 所有应用都依赖大量高质量数据 |\\n| **自动化决策** | 减少人工干预,提升效率 |\\n| **可扩展性强** | 模型一旦训练完成,可快速部署到多个场景 |\\n| **持续优化** | 支持在线学习,随时间不断改进性能 |\\n\\n—\\n\\n## 挑战与注意事项\\n- 数据隐私与伦理问题(如人脸识别滥用)\\n- 模型可解释性不足(“黑箱”问题)\\n- 过拟合与泛化能力差\\n- 对标注数据的依赖高\\n- 计算资源消耗大\\n\\n—\\n\\n随着算法进步(如大模型、自监督学习)、算力提升和数据积累,机器学习的应用场景将持续拓展,逐步渗透到社会生活的方方面面,推动智能化转型。未来,跨学科融合(如生物+AI、法律+AI)将成为新的增长点。"}]}}}
最终回复: 机器学习(Machine Learning, ML)作为人工智能的核心技术之一,已在众多领域展现出强大的应用潜力。它通过从数据中自动学习模式和规律,实现预测、分类、聚类、推荐等功能。以下是机器学习的主要应用场景分析:
—
### 1. **互联网与电子商务**
– **个性化推荐系统**
如电商网站(淘宝、京东)、视频平台(Netflix、YouTube)利用协同过滤、深度学习等算法为用户推荐商品或内容。
– **搜索引擎优化**
通过自然语言处理(NLP)和排序学习(Learning to Rank)提升搜索结果的相关性。
– **广告投放与点击率预测**
利用机器学习模型预测用户对广告的点击概率,实现精准营销。
—
### 2. **金融科技(FinTech)**
– **信用评分与风控**
基于用户历史行为、交易记录等数据构建信用评估模型,判断贷款违约风险。
– **欺诈检测**
使用异常检测算法识别信用卡盗刷、洗钱等异常交易行为。
– **股票市场预测与量化交易**
利用时间序列分析、强化学习等方法辅助投资决策(需注意市场不确定性)。
—
### 3. **医疗健康**
– **疾病诊断与辅助决策**
图像识别用于医学影像分析(如X光、CT、MRI),辅助医生诊断癌症、肺炎等疾病。
– **基因组学与药物研发**
分析基因序列数据,发现致病基因;加速新药分子筛选过程。
– **健康监测与预测**
可穿戴设备结合机器学习预测心律失常、糖尿病并发症等。
—
### 4. **智能制造与工业自动化**
– **预测性维护(Predictive Maintenance)**
分析传感器数据预测设备故障,减少停机时间和维修成本。
– **质量控制**
利用计算机视觉检测产品缺陷(如芯片、汽车零部件)。
– **生产流程优化**
通过强化学习或回归模型优化参数配置,提高生产效率。
—
### 5. **交通运输与自动驾驶**
– **智能交通管理**
预测交通流量、优化信号灯控制,缓解拥堵。
– **自动驾驶**
感知(目标检测、语义分割)、决策(路径规划)、控制(动作执行)均依赖深度学习与强化学习。
– **路径规划与物流优化**
快递配送路线优化、网约车调度等使用图神经网络或运筹学结合ML的方法。
—
### 6. **自然语言处理(NLP)**
– **语音识别与合成**
如Siri、小爱同学等智能助手背后的语音转文字、文字转语音技术。
– **机器翻译**
Google Translate、DeepL 等基于Transformer架构实现高质量翻译。
– **情感分析与舆情监控**
分析社交媒体评论、新闻文本中的情绪倾向,用于品牌管理或政策制定。
—
### 7. **教育科技(EdTech)**
– **个性化学习路径推荐**
根据学生的学习行为和成绩推荐适合的学习资源。
– **智能阅卷与作业批改**
自动批改选择题、填空题甚至作文(结合NLP)。
– **学习效果预测**
预测学生是否可能挂科,提前干预。
—
### 8. **农业与环境科学**
– **精准农业**
利用遥感图像和气象数据预测作物产量、病虫害风险。
– **气候建模与灾害预警**
分析气候变化趋势,预测洪水、干旱等自然灾害。
– **土壤与水质分析**
传感器数据结合模型评估土地适宜性或污染程度。
—
### 9. **安全与安防**
– **人脸识别与身份验证**
广泛应用于门禁系统、支付验证、公共安全监控。
– **网络安全威胁检测**
检测恶意软件、DDoS攻击、异常登录行为等。
– **视频监控智能分析**
行为识别(如跌倒、打架)、人群密度监测等。
—
### 10. **娱乐与创意产业**
– **内容生成(AIGC)**
文本生成(如ChatGPT)、图像生成(如Stable Diffusion)、音乐创作等。
– **游戏AI**
NPC智能行为设计、游戏平衡性调优、玩家行为预测。
– **影视特效与后期制作**
深度伪造(Deepfake)、自动剪辑、画质增强等。
—
## 总结:机器学习应用的关键特点
| 特点 | 说明 |
|——|——|
| **数据驱动** | 所有应用都依赖大量高质量数据 |
| **自动化决策** | 减少人工干预,提升效率 |
| **可扩展性强** | 模型一旦训练完成,可快速部署到多个场景 |
| **持续优化** | 支持在线学习,随时间不断改进性能 |
—
## 挑战与注意事项
– 数据隐私与伦理问题(如人脸识别滥用)
– 模型可解释性不足(“黑箱”问题)
– 过拟合与泛化能力差
– 对标注数据的依赖高
– 计算资源消耗大
—
随着算法进步(如大模型、自监督学习)、算力提升和数据积累,机器学习的应用场景将持续拓展,逐步渗透到社会生活的方方面面,推动智能化转型。未来,跨学科融合(如生物+AI、法律+AI)将成为新的增长点。
— 示例11:使用 outputType —
{
"content": "春风拂面柳轻摇,\\n细雨润花影自娇。\\n燕语呢喃穿翠幕,\\n桃红李白满山腰。\\n溪流欢唱冰初解,\\n草色遥看近却寥。\\n最是一年光好处,\\n踏青何必远寻桥。",
"style": "五言律诗",
"title": "春日即景"
}
— 示例12:使用 outputSchema —
— 示例13:配置记忆 —
=== 所有示例执行完成 ===
5. 执行上下文分析
从 classpath 可确认依赖版本:
- spring-ai-alibaba-graph-core-1.1.0.0-M5.jar
- spring-ai-alibaba-starter-a2a-nacos-1.1.0.0-M5.jar
- dashscope-api 相关组件
这表明示例运行在 Spring AI Alibaba 1.1.0.0-M5 版本,与 Spring Boot 3.5.7 兼容,符合当前最新预发布版特性。
6. 生产建议
7. 结语
Spring AI Alibaba 的 Agent 能力,将大模型从“聊天机器人”升级为“可编程智能体”。通过声明式 API 与丰富的扩展点,开发者可以快速构建复杂 AI 应用,而无需深陷 LLM 底层细节。
📝 动手建议:
8. 福利资源
- 📦 完整示例代码及执行结果已上传至附件
- 📚 Spring-AI-Alibaba官方文档:https://java2ai.com/docs/quick-start
- 🎁 免费额度:阿里云百炼平台提供 Qwen API 免费调用额度。可在注册/登录后,开通大模型服务获取
📝 版权声明:本文为原创,遵循 CC 4.0 BY-SA 协议。转载请附原文链接及本声明。 🔖 关键词:#SpringAI #AlibabaCloud #Agent #智能体 #ReAct #AI微服务 #JavaAI #Qwen
写在文末:关于技术写作的一点初衷
借此机会,想向各位读者稍作说明:撰写这类技术文章的初衷,是希望将一些复杂或分散的知识点进行梳理与提炼,让更多人有机会以更清晰的路径理解其背后的原理与设计思想。
诚然,官方文档是权威的信息来源,但“所有内容官网上都有”这样的说法,既忽略了信息获取的成本,也低估了知识整合的价值 – 毕竟,官网通常提供的是原始材料,而非直接可读的脉络;要从中提炼出系统性的认知,仍需大量阅读、调试甚至试错。
限于时间和精力,我无法在每篇文章中穷尽所有实践细节或覆盖全部边界场景,但这并不妨碍我们深入探讨机制与原理。事实上,会调用 API 的人未必理解其内部运作逻辑,而我的写作重心,始终放在“为什么”而非仅仅是“怎么做”。
若能因此激发更多人对底层原理的兴趣,或为同行节省些许摸索时间,便已深感欣慰。



