### Install and Run Example Application with Maven Source: https://java2ai.com/blog/spring-ai-alibaba-graph-preview This command sequence first installs the Spring AI Alibaba Graph source code locally and then runs the example application using Maven. This is necessary as the graph module is not yet officially released. ```bash mvn clean install cd spring-ai-alibaba-graph/spring-ai-alibaba-graph-example mvn spring-boot:run ``` -------------------------------- ### Clone and navigate to the example project Source: https://java2ai.com/blog/spring-ai-alibaba-mcp-filesystem Clone the Spring AI Alibaba examples repository and navigate to the filesystem MCP example directory. This sets up the project for running the demonstration. ```bash git clone https://github.com/springaialibaba/spring-ai-alibaba-examples.git cd spring-ai-alibaba-examples/spring-ai-alibaba-mcp-example/filesystem ``` -------------------------------- ### Build the example project Source: https://java2ai.com/blog/spring-ai-alibaba-mcp-filesystem Build the example project using Maven Wrapper. This compiles the code and prepares it for execution. ```bash ./mvnw clean install ``` -------------------------------- ### Start Frontend Development Server (npm) Source: https://java2ai.com/agents/dataagent/quick-start Start the frontend development server using npm to run the web application locally. ```bash # 使用 npm npm run dev ``` -------------------------------- ### Import START Node Source: https://java2ai.com/docs/frameworks/graph-core/core/core-library Import the START node staticly to reference it when defining graph entry points. ```java import static com.alibaba.cloud.ai.graph.StateGraph.START; ``` -------------------------------- ### Checkpoint Example with StateGraph Source: https://java2ai.com/docs/frameworks/graph-core/core/persistence This example demonstrates how to define state strategies, node actions, build a StateGraph, configure checkpoints, compile the graph, and invoke it with a RunnableConfig. It illustrates the creation of multiple checkpoints during graph execution. ```java import com.alibaba.cloud.ai.graph.CompileConfig; import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.KeyStrategy; import com.alibaba.cloud.ai.graph.KeyStrategyFactory; import com.alibaba.cloud.ai.graph.RunnableConfig; import com.alibaba.cloud.ai.graph.StateGraph; import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig; import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver; import com.alibaba.cloud.ai.graph.exception.GraphStateException; import com.alibaba.cloud.ai.graph.state.strategy.AppendStrategy; import com.alibaba.cloud.ai.graph.state.strategy.ReplaceStrategy; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.alibaba.cloud.ai.graph.StateGraph.END; import static com.alibaba.cloud.ai.graph.StateGraph.START; import static com.alibaba.cloud.ai.graph.action.AsyncNodeAction.node_async; // 定义状态策略 KeyStrategyFactory keyStrategyFactory = () -> { Map keyStrategyMap = new HashMap<>(); keyStrategyMap.put("foo", new ReplaceStrategy()); keyStrategyMap.put("bar", new AppendStrategy()); return keyStrategyMap; }; // 定义节点操作 var nodeA = node_async(state -> { return Map.of("foo", "a", "bar", List.of("a")); }); var nodeB = node_async(state -> { return Map.of("foo", "b", "bar", List.of("b")); }); // 创建图 StateGraph stateGraph = new StateGraph(keyStrategyFactory) .addNode("node_a", nodeA) .addNode("node_b", nodeB) .addEdge(START, "node_a") .addEdge("node_a", "node_b") .addEdge("node_b", END); // 配置检查点 SaverConfig saverConfig = SaverConfig.builder() .register(new MemorySaver()) .build(); // 编译图 CompiledGraph graph = stateGraph.compile( CompileConfig.builder() .saverConfig(saverConfig) .build() ); // 运行图 RunnableConfig config = RunnableConfig.builder() .threadId("1") .build(); Map input = new HashMap<>(); input.put("foo", ""); graph.invoke(input, config); ``` -------------------------------- ### MemoryStore Basic Usage Example Source: https://java2ai.com/docs/frameworks/agent-framework/advanced/memory Demonstrates how to use MemoryStore to save, retrieve, and search for memory items. This example uses an in-memory store, but production environments should use database-backed implementations. It shows organizing memory by namespace and key, and searching based on content. ```java import com.alibaba.cloud.ai.graph.store.stores.MemoryStore; import com.alibaba.cloud.ai.graph.store.StoreItem; import java.util.*; // MemoryStore 将数据保存到内存字典中。在生产环境中请使用基于数据库的存储实现 MemoryStore store = new MemoryStore(); String userId = "my-user"; String applicationContext = "chitchat"; List namespace = List.of(userId, applicationContext); // 保存记忆 Map memoryData = new HashMap<>(); memoryData.put("rules", List.of( "用户喜欢简短直接的语言", "用户只说中文和Java" )); memoryData.put("my-key", "my-value"); StoreItem item = StoreItem.of(namespace, "a-memory", memoryData); store.putItem(item); // 通过ID获取记忆 Optional retrievedItem = store.getItem(namespace, "a-memory"); // 在此命名空间内搜索记忆,通过内容等价性过滤,按向量相似度排序 List items = store.searchItems( namespace, Map.of("my-key", "my-value") ); ``` -------------------------------- ### Start Frontend Development Server (yarn) Source: https://java2ai.com/agents/dataagent/quick-start Start the frontend development server using yarn to run the web application locally. ```bash # 或使用 yarn yarn dev ``` -------------------------------- ### Install Frontend Dependencies (yarn) Source: https://java2ai.com/agents/dataagent/quick-start Install project dependencies using yarn for the frontend web application. ```bash # 或使用 yarn yarn install ``` -------------------------------- ### Install Frontend Dependencies (npm) Source: https://java2ai.com/agents/dataagent/quick-start Install project dependencies using npm for the frontend web application. ```bash # 使用 npm npm install ``` -------------------------------- ### Full Example: Streaming LLM Tokens with StateGraph Source: https://java2ai.com/docs/frameworks/graph-core/core/streaming This example demonstrates a complete implementation of streaming output using StateGraph. It includes defining state strategies, creating streaming and processing nodes, building and compiling the graph, and executing it in a streaming fashion. The output is processed chunk by chunk as it becomes available. ```java import com.alibaba.cloud.ai.graph.CompileConfig; import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.KeyStrategy; import com.alibaba.cloud.ai.graph.KeyStrategyFactory; import com.alibaba.cloud.ai.graph.RunnableConfig; import com.alibaba.cloud.ai.graph.StateGraph; import com.alibaba.cloud.ai.graph.action.AsyncNodeAction; import com.alibaba.cloud.ai.graph.exception.GraphStateException; import com.alibaba.cloud.ai.graph.state.strategy.AppendStrategy; import com.alibaba.cloud.ai.graph.streaming.StreamingOutput; import org.springframework.ai.chat.client.ChatClient; import java.util.HashMap; import java.util.Map; import static com.alibaba.cloud.ai.graph.StateGraph.END; import static com.alibaba.cloud.ai.graph.StateGraph.START; /** * 使用 StateGraph 实现流式输出的完整示例 */ public static void streamLLMTokens(ChatClient.Builder chatClientBuilder) throws GraphStateException { // 定义状态策略 KeyStrategyFactory keyStrategyFactory = () -> { Map keyStrategyMap = new HashMap<>(); keyStrategyMap.put("query", new AppendStrategy()); keyStrategyMap.put("messages", new AppendStrategy()); keyStrategyMap.put("result", new AppendStrategy()); return keyStrategyMap; }; // 创建流式节点 StreamingNode streamingNode = new StreamingNode(chatClientBuilder, "streaming_node"); // 创建处理节点 ProcessStreamingNode processNode = new ProcessStreamingNode(); // 构建图 StateGraph stateGraph = new StateGraph(keyStrategyFactory) .addNode("streaming_node", AsyncNodeAction.node_async(streamingNode)) .addNode("process_node", AsyncNodeAction.node_async(processNode)) .addEdge(START, "streaming_node") .addEdge("streaming_node", "process_node") .addEdge("process_node", END); // 编译图 CompiledGraph graph = stateGraph.compile( CompileConfig.builder() .build() ); // 创建配置 RunnableConfig config = RunnableConfig.builder() .threadId("streaming_thread") .build(); // 使用流式方式执行图 System.out.println("开始流式输出... "); graph.stream(Map.of("query", "请用一句话介绍 Spring AI"), config) .doOnNext(output -> { // 处理流式输出 if (output instanceof StreamingOutput streamingOutput) { // 流式输出块 String chunk = streamingOutput.chunk(); if (chunk != null && !chunk.isEmpty()) { System.out.print(chunk); // 实时打印流式内容 } } else { // 普通节点输出 String nodeId = output.node(); Map state = output.state().data(); System.out.println(" 节点 '" + nodeId + "' 执行完成"); if (state.containsKey("result")) { System.out.println("最终结果: " + state.get("result")); } } }) .doOnComplete(() -> { System.out.println(" 流式输出完成"); }) .doOnError(error -> { System.err.println("流式输出错误: " + error.getMessage()); }) .blockLast(); // 阻塞等待流完成 } ``` -------------------------------- ### Usage Examples for Token Limit Parameters Source: https://java2ai.com/integration/chatmodels/more/openai-sdk-chat Examples demonstrating how to use `maxTokens` and `maxCompletionTokens` with different model types. ```APIDOC ## Usage Examples for Token Limit Parameters ### Description Examples demonstrating how to use `maxTokens` and `maxCompletionTokens` with different model types. ### Example 1: Non-Reasoning Models (e.g., gpt-4o, gpt-3.5-turbo) ```java ChatResponse response = chatModel.call( new Prompt( "Explain quantum computing in simple terms.", OpenAiSdkChatOptions.builder() .model("gpt-4o") .maxTokens(150) // Use maxTokens for non-reasoning models .build() )); ``` ### Example 2: Reasoning Models (e.g., o1, o3 series) ```java ChatResponse response = chatModel.call( new Prompt( "Solve this complex math problem step by step: ...", OpenAiSdkChatOptions.builder() .model("o1-preview") .maxCompletionTokens(1000) // Use maxCompletionTokens for reasoning models .build() )); ``` ``` -------------------------------- ### Example Output Format Source: https://java2ai.com/blog/spring-ai-alibaba-module-rag Sample output structure for a web search query. ```markdown ### 必游景点 1. **西湖** - **核心特色**:杭州的标志性景点,包含“西湖十景”(如苏堤春晓、断桥残雪、三潭印月等),可泛舟湖上或沿湖骑行。 - **推荐活动**:夜游西湖灯光秀、漫步白堤/苏堤。 2. **灵隐寺与飞来峰** - **文化价值**:千年古刹灵隐寺被誉为“东南佛国”,飞来峰的摩崖石刻为宋代佛教艺术瑰宝。 --- ``` -------------------------------- ### Full Example: Persistent Dialogue with Tool Calls Source: https://java2ai.com/docs/frameworks/graph-core/examples/persistence Demonstrates a complete persistent dialogue flow using a state graph, tools, and a memory saver for persistence. This example shows how the system remembers context across multiple turns and utilizes tools. ```java import com.alibaba.cloud.ai.graph.*; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.model.function.FunctionCallbackWrapper; public class PersistenceExample { private static final Logger log = LoggerFactory.getLogger(PersistenceExample.class); public static void main(String[] args) { // 1. 配置状态策略 KeyStrategyFactory keyStrategyFactory = () -> { HashMap strategies = new HashMap<>(); strategies.put("messages", new AppendStrategy()); strategies.put("user_name", new ReplaceStrategy()); return strategies; }; // 2. 创建工具和节点 SearchTool searchTool = new SearchTool(); ChatClient.Builder builder = ChatClient.builder(chatModel); var agentNode = nodeasync(new AgentNode(builder, searchTool)); // 3. 构建 Graph StateGraph workflow = new StateGraph(keyStrategyFactory) .addNode("agent", agentNode) .addEdge(StateGraph.START, "agent") .addEdge("agent", StateGraph.END); // 4. 配置持久化 var checkpointer = new MemorySaver(); var compileConfig = CompileConfig.builder() .checkpointSaver(checkpointer) .build(); CompiledGraph graph = workflow.compile(compileConfig); // 5. 测试持久化对话 var config = RunnableConfig.builder() .threadId("demo-session") .build(); // 第一轮对话 graph.invoke(Map.of("messages", "Hi, I'm Charlie"), config); // 第二轮对话 - 能记住名字 var result = graph.invoke(Map.of("messages", "What's my name?"), config); log.info("Response: {}", result.data().get("messages")); // 第三轮对话 - 使用工具 result = graph.invoke(Map.of("messages", "What's the weather like?"), config); log.info("Response: {}", result.data().get("messages")); // 查看状态历史 List history = graph.getStateHistory(config); log.info("Total conversation steps: {}", history.size()); } } ``` -------------------------------- ### Human-in-the-Loop Workflow Example Source: https://java2ai.com/docs/frameworks/agent-framework/advanced/human-in-the-loop This example demonstrates setting up a ReactAgent with human-in-the-loop approval for tool usage within a StateGraph workflow. It includes custom nodes for preprocessing and validation, and defines conditional edges for workflow control. ```java import com.alibaba.cloud.ai.graph.CompileConfig; import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.KeyStrategy; import com.alibaba.cloud.ai.graph.KeyStrategyFactory; 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.StateGraph; import com.alibaba.cloud.ai.graph.action.InterruptionMetadata; import com.alibaba.cloud.ai.graph.action.NodeAction; import com.alibaba.cloud.ai.graph.agent.ReactAgent; import com.alibaba.cloud.ai.graph.agent.hook.hip.HumanInTheLoopHook; import com.alibaba.cloud.ai.graph.agent.hook.hip.ToolConfig; import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig; import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver; import com.alibaba.cloud.ai.graph.state.strategy.ReplaceStrategy; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import static com.alibaba.cloud.ai.graph.action.AsyncEdgeAction.edge_async; import static com.alibaba.cloud.ai.graph.action.AsyncNodeAction.node_async; // 1. 创建工具回调 ToolCallback searchTool = FunctionToolCallback .builder("search", (args) -> "搜索结果:AI Agent是能够感知环境、自主决策并采取行动的智能系统。") .description("搜索工具,用于查找相关信息") .inputType(String.class) .build(); // 2. 配置检查点保存器(工作流和Agent共享) MemorySaver saver = new MemorySaver(); // 3. 创建带有人工介入Hook的ReactAgent ReactAgent qaAgent = ReactAgent.builder() .name("qa_agent") .model(chatModel) .instruction("你是一个问答专家,负责回答用户的问题。如果需要搜索信息,请使用search工具。 用户问题:{cleaned_input}") .outputKey("qa_result") .saver(saver) .hooks(HumanInTheLoopHook.builder() .approvalOn("search", ToolConfig.builder() .description("搜索操作需要人工审批,请确认是否执行搜索") .build()) .build()) .tools(searchTool) .build(); // 4. 创建自定义Node(预处理) class PreprocessorNode implements NodeAction { @Override public Map apply(OverAllState state) throws Exception { String input = state.value("input", "").toString(); String cleaned = input.trim(); return Map.of("cleaned_input", cleaned); } } // 5. 创建自定义Node(验证) class ValidatorNode implements NodeAction { @Override public Map apply(OverAllState state) throws Exception { Optional qaResultOpt = state.value("qa_result"); if (qaResultOpt.isPresent() && qaResultOpt.get() instanceof Message message) { boolean isValid = message.getText().length() > 30; return Map.of("is_valid", isValid); } return Map.of("is_valid", false); } } // 6. 定义状态管理策略 KeyStrategyFactory keyStrategyFactory = () -> { HashMap strategies = new HashMap<>(); strategies.put("input", new ReplaceStrategy()); strategies.put("cleaned_input", new ReplaceStrategy()); strategies.put("qa_result", new ReplaceStrategy()); strategies.put("is_valid", new ReplaceStrategy()); return strategies; }; // 7. 构建工作流 StateGraph workflow = new StateGraph(keyStrategyFactory); // 添加普通Node workflow.addNode("preprocess", node_async(new PreprocessorNode())); workflow.addNode("validate", node_async(new ValidatorNode())); // 添加Agent Node(嵌套的ReactAgent) workflow.addNode(qaAgent.name(), qaAgent.asNode( true, // includeContents: 传递父图的消息历史 false // includeReasoning: 不返回推理过程 )); // 定义流程:预处理 -> Agent处理 -> 验证 workflow.addEdge(StateGraph.START, "preprocess"); workflow.addEdge("preprocess", qaAgent.name()); workflow.addEdge(qaAgent.name(), "validate"); // 条件边:验证通过则结束,否则重新处理 workflow.addConditionalEdges( "validate", edge_async(state -> { Boolean isValid = (Boolean) state.value("is_valid", false); return isValid ? "end" : qaAgent.name(); }), Map.of( "end", StateGraph.END, qaAgent.name(), qaAgent.name() ) ); // 8. 编译工作流(必须在CompileConfig中注册检查点保存器) CompiledGraph compiledGraph = workflow.compile( CompileConfig.builder() .saverConfig(SaverConfig.builder().register(saver).build()) .build() ); // 9. 执行工作流并处理中断 String threadId = "workflow-hilt-001"; Map input = Map.of("input", "请解释量子计算的基本原理"); // 第一次调用 - 可能触发中断 Optional nodeOutputOptional = compiledGraph.invokeAndGetOutput( input, RunnableConfig.builder().threadId(threadId).build() ); ``` -------------------------------- ### STDIO Transport Configuration Example Source: https://java2ai.com/integration/mcps/mcp-client-boot-starter-docs Configure STDIO transport connections, including command, arguments, and environment variables for the MCP server process. This example shows how to set up a connection named 'server1'. ```yaml spring: ai: mcp: client: stdio: root-change-notification: true connections: server1: command: /path/to/server args: - --port=8080 - --mode=production env: API_KEY: your-api-key DEBUG: "true" ``` -------------------------------- ### Use VectorStore in Application Source: https://java2ai.com/integration/rag/vectordbs/pgvector Example of autowiring the VectorStore, adding documents, and performing a similarity search. ```java @Autowired VectorStore vectorStore; // ... List documents = List.of( new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")), new Document("The World is Big and Salvation Lurks Around the Corner"), new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2"))); // 将文档添加到 PGVector vectorStore.add(documents); // 检索与查询相似的文档 List results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build()); ``` -------------------------------- ### SummaryMetadataEnricher Usage Example Source: https://java2ai.com/integration/rag/etl-pipeline Shows the manual initialization and application of the enricher, followed by inspecting the generated metadata. ```java ChatModel chatModel = // initialize your chat model SummaryMetadataEnricher enricher = new SummaryMetadataEnricher(chatModel, List.of(SummaryType.PREVIOUS, SummaryType.CURRENT, SummaryType.NEXT)); Document doc1 = new Document("Content of document 1"); Document doc2 = new Document("Content of document 2"); List enrichedDocs = enricher.apply(List.of(this.doc1, this.doc2)); // Check the metadata of the enriched documents for (Document doc : enrichedDocs) { System.out.println("Current summary: " + doc.getMetadata().get("section_summary")); System.out.println("Previous summary: " + doc.getMetadata().get("prev_section_summary")); System.out.println("Next summary: " + doc.getMetadata().get("next_section_summary")); } ``` -------------------------------- ### GET /ai/image Source: https://java2ai.com/integration/multimodals/image/openai-sdk-image An example endpoint demonstrating how to use the OpenAiSdkImageModel to generate images based on a prompt. ```APIDOC ## GET /ai/image ### Description Generates an image based on the provided prompt using the configured OpenAI image model. ### Method GET ### Endpoint /ai/image ### Parameters #### Query Parameters - **prompt** (string) - Optional - The text description for the image generation. Defaults to 'A light cream colored mini golden doodle'. ### Response #### Success Response (200) - **url** (string) - The URL of the generated image. #### Response Example { "url": "https://example.com/generated-image.png" } ``` -------------------------------- ### Spring Boot Application Starter Class Source: https://java2ai.com/blog/spring-ai-alibaba-observability-arms?spm=5176.29160081.0.0.2856aa5cenvkmu The main class to start the Spring Boot application for the function calling example. ```java @SpringBootApplication public class FunctionCallingExampleApplication { public static void main(String[] args) { SpringApplication.run(FunctionCallingExampleApplication.class, args); } } ``` -------------------------------- ### Cross-Session Memory Example Source: https://java2ai.com/docs/frameworks/agent-framework/advanced/memory This example demonstrates saving and retrieving information across different agent sessions using a shared memory store. It defines tools for saving and getting memory, then uses them in two distinct sessions for the same user to show memory persistence. ```java import com.alibaba.cloud.ai.graph.agent.ReactAgent; import com.alibaba.cloud.ai.graph.RunnableConfig; import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver; import com.alibaba.cloud.ai.graph.store.Store; import com.alibaba.cloud.ai.graph.store.stores.MemoryStore; import com.alibaba.cloud.ai.graph.store.StoreItem; import org.springframework.ai.chat.model.ToolContext; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; import java.util.*; import java.util.function.BiFunction; // 定义请求和响应记录 record SaveMemoryRequest(List namespace, String key, Map value) {} record GetMemoryRequest(List namespace, String key) {} record MemoryResponse(String message, Map value) {} // 创建记忆存储和工具 MemoryStore memoryStore = new MemoryStore(); ToolCallback saveMemoryTool = FunctionToolCallback.builder("saveMemory", (BiFunction) (request, context) -> { StoreItem item = StoreItem.of(request.namespace(), request.key(), request.value()); RunnableConfig runnableConfig = (RunnableConfig) context.getContext().get("config"); Store store = runnableConfig.store(); store.putItem(item); return new MemoryResponse("已保存", request.value()); }) .description("保存到长期记忆") .inputType(SaveMemoryRequest.class) .build(); ToolCallback getMemoryTool = FunctionToolCallback.builder("getMemory", (BiFunction) (request, context) -> { RunnableConfig runnableConfig = (RunnableConfig) context.getContext().get("config"); Store store = runnableConfig.store(); Optional itemOpt = store.getItem(request.namespace(), request.key()); return new MemoryResponse( itemOpt.isPresent() ? "找到" : "未找到", itemOpt.map(StoreItem::getValue).orElse(Map.of()) ); }) .description("从长期记忆获取") .inputType(GetMemoryRequest.class) .build(); ReactAgent agent = ReactAgent.builder() .name("session_agent") .model(chatModel) .tools(saveMemoryTool, getMemoryTool) .saver(new MemorySaver()) .build(); // 会话1:保存信息 RunnableConfig session1 = RunnableConfig.builder() .threadId("session_morning") .addMetadata("user_id", "user_003") .store(memoryStore) .build(); agent.invoke( "记住我的密码是 secret123。用 saveMemory 保存,namespace=['credentials'], key='user_003_password', value={'password': 'secret123'}.", session1 ); // 会话2:检索信息(不同的线程,同一用户) RunnableConfig session2 = RunnableConfig.builder() .threadId("session_afternoon") .addMetadata("user_id", "user_003") .store(memoryStore) .build(); agent.invoke( "我的密码是什么?用 getMemory 获取,namespace=['credentials'], key='user_003_password'.", session2 ); // 长期记忆在不同会话间持久化 ``` -------------------------------- ### Stream Workflow Execution Example Source: https://java2ai.com/docs/frameworks/agent-framework/advanced/workflow Compiles and executes a workflow using streaming to get real-time output from each node. Useful for interactive applications or when intermediate results are needed as they are generated. ```java import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.CompileConfig; import com.alibaba.cloud.ai.graph.NodeOutput; import com.alibaba.cloud.ai.graph.streaming.StreamingOutput; import java.util.Map; // 编译工作流 CompiledGraph compiledGraph = workflow.compile(CompileConfig.builder().build()); // 流式执行,实时获取每个节点的输出 NodeOutput lastOutput = compiledGraph.stream(Map.of("input", "请分析2024年AI行业发展趋势")) .doOnNext(output -> { if (output instanceof StreamingOutput streamingOutput) { if (streamingOutput.message() != null) { // streaming output from streaming llm node System.out.println("Streaming output from node " + streamingOutput.node() + ": " + streamingOutput.message().getText()); } else { // output from normal node, investigate the state to get the node data System.out.println("Output from node " + streamingOutput.node() + ": " + streamingOutput.state().data()); } } }) .blockLast(); // 获取最终状态 System.out.println("最终结果: " + lastOutput.state().data()); ``` -------------------------------- ### Complete Graph Execution and Replay Example Source: https://java2ai.com/docs/frameworks/graph-core/examples/time-travel Demonstrates building a state graph, configuring memory-based persistence, executing nodes, retrieving history, and replaying from a specific checkpoint. ```java import com.alibaba.cloud.ai.graph.CompileConfig; import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.KeyStrategy; import com.alibaba.cloud.ai.graph.KeyStrategyFactory; import com.alibaba.cloud.ai.graph.RunnableConfig; import com.alibaba.cloud.ai.graph.StateGraph; import com.alibaba.cloud.ai.graph.checkpoint.config.SaverConfig; import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver; import com.alibaba.cloud.ai.graph.exception.GraphStateException; import com.alibaba.cloud.ai.graph.state.StateSnapshot; import com.alibaba.cloud.ai.graph.state.strategy.AppendStrategy; import com.alibaba.cloud.ai.graph.state.strategy.ReplaceStrategy; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.alibaba.cloud.ai.graph.StateGraph.END; import static com.alibaba.cloud.ai.graph.StateGraph.START; import static com.alibaba.cloud.ai.graph.action.AsyncNodeAction.node_async; /** * 完整示例 */ public static void completeExample() throws GraphStateException { // 构建 Graph KeyStrategyFactory keyStrategyFactory = () -> { HashMap strategies = new HashMap<>(); strategies.put("messages", new AppendStrategy()); strategies.put("step", new ReplaceStrategy()); return strategies; }; StateGraph builder = new StateGraph(keyStrategyFactory) .addNode("step1", node_async(state -> Map.of("messages", "Step 1", "step", 1))) .addNode("step2", node_async(state -> Map.of("messages", "Step 2", "step", 2))) .addNode("step3", node_async(state -> Map.of("messages", "Step 3", "step", 3))) .addEdge(START, "step1") .addEdge("step1", "step2") .addEdge("step2", "step3") .addEdge("step3", END); // 配置持久化 var checkpointer = new MemorySaver(); var compileConfig = CompileConfig.builder() .saverConfig(SaverConfig.builder() .register(checkpointer) .build()) .build(); CompiledGraph graph = builder.compile(compileConfig); // 执行 var config = RunnableConfig.builder() .threadId("demo") .build(); graph.invoke(Map.of(), config); // 查看历史 List history = (List) graph.getStateHistory(config); history.forEach(snapshot -> { System.out.println("State: " + snapshot.state()); System.out.println("Node: " + snapshot.node()); System.out.println("---"); }); // 回溯到 step1 StateSnapshot step1Snapshot = history.stream() .filter(s -> "step1".equals(s.node())) .findFirst() .orElseThrow(); var replayConfig = RunnableConfig.builder() .threadId("demo") .checkPointId(step1Snapshot.config().checkPointId().orElse(null)) .build(); // 从 step1 重新执行 graph.invoke(Map.of(), replayConfig); } ``` -------------------------------- ### DeepSeek Reasoner Model Example in Java Source: https://java2ai.com/integration/chatmodels/deepseek-chat Demonstrates how to use the deepseek-reasoner model to get Chain of Thought (CoT) content before the final answer. Access CoT using getReasoningContent() and the final answer with getText(). ```java public void deepSeekReasonerExample() { DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder() .model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER.getValue()) .build(); Prompt prompt = new Prompt("9.11 and 9.8, which is greater?", promptOptions); ChatResponse response = chatModel.call(prompt); // Get the CoT content generated by deepseek-reasoner, only available when using deepseek-reasoner model DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput(); String reasoningContent = deepSeekAssistantMessage.getReasoningContent(); String text = deepSeekAssistantMessage.getText(); } ``` -------------------------------- ### FileDocumentWriter Execution Example Source: https://java2ai.com/integration/rag/etl-pipeline Example of writing documents to a file with appending enabled. ```java List documents = // initialize your documents FileDocumentWriter writer = new FileDocumentWriter("output.txt", true, MetadataMode.ALL, true); writer.accept(documents); ``` -------------------------------- ### Update State Example with Strategies Source: https://java2ai.com/docs/frameworks/graph-core/core/persistence Demonstrates updating state with defined strategies, where 'foo' is replaced and 'bar' has new elements appended. ```java import com.alibaba.cloud.ai.graph.CompiledGraph; import com.alibaba.cloud.ai.graph.KeyStrategy; import com.alibaba.cloud.ai.graph.KeyStrategyFactory; import com.alibaba.cloud.ai.graph.RunnableConfig; import com.alibaba.cloud.ai.graph.state.strategy.AppendStrategy; import com.alibaba.cloud.ai.graph.state.strategy.ReplaceStrategy; import java.util.HashMap; import java.util.List; import java.util.Map; KeyStrategyFactory keyStrategyFactory = () -> { Map keyStrategyMap = new HashMap<>(); keyStrategyMap.put("foo", new ReplaceStrategy()); // 替换策略 keyStrategyMap.put("bar", new AppendStrategy()); // 追加策略 return keyStrategyMap; }; RunnableConfig config = RunnableConfig.builder() .threadId("1") .build(); Map updates = new HashMap<>(); updates.put("foo", 2); updates.put("bar", List.of("b")); graph.updateState(config, updates, null); System.out.println("State updated successfully"); ``` -------------------------------- ### Few-Shot Example Configuration Source: https://java2ai.com/agents/assistantagent/features/evaluation/advanced Provide few-shot examples to an LLM evaluator to improve assessment accuracy. ```APIDOC ## Few-Shot Example Configuration ### Description Provide few-shot examples to an LLM evaluator to improve assessment accuracy. ### Method Java Code Example ### Endpoint N/A ### Parameters N/A ### Request Example ```java EvaluationCriterionBuilder.create("intent_type") .description("Determine user intent type") .resultType(ResultType.ENUM) .options("QUESTION", "TOOL_CALL", "CHITCHAT") .addFewShot( "今天天气怎么样?", // input "", // context (optional) "QUESTION" // expectedOutput ) .addFewShot( "帮我查一下订单状态", "", "TOOL_CALL" ) .addFewShot( "你好呀", "", "CHITCHAT" ) .build(); ``` ### Response N/A ``` -------------------------------- ### Qdrant Configuration Properties Source: https://java2ai.com/integration/rag/vectordbs/more/qdrant Example application.yml configuration for connecting to a Qdrant instance, including host, port, API key, and schema initialization. ```yaml spring: ai: vectorstore: qdrant: host: port: api-key: collection-name: use-tls: false initialize-schema: true ``` -------------------------------- ### Add DashScope Starter Dependency Source: https://java2ai.com/integration/multimodals/image/dashscope-image Include the necessary starter dependency in your build configuration to enable auto-configuration. ```xml com.alibaba.cloud.ai spring-ai-alibaba-starter-dashscope ``` ```groovy dependencies { implementation 'com.alibaba.cloud.ai:spring-ai-alibaba-starter-dashscope' } ``` -------------------------------- ### Qdrant VectorStore Usage Example Source: https://java2ai.com/integration/rag/vectordbs/more/qdrant Demonstrates adding documents to Qdrant and performing a similarity search using an auto-configured VectorStore bean. ```java @Autowired VectorStore vectorStore; // ... List documents = List.of( new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")), new Document("The World is Big and Salvation Lurks Around the Corner"), new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2")) ); // 将文档添加到 Qdrant vectorStore.add(documents); // 检索与查询相似的文档 List results = vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build()); ``` -------------------------------- ### Simple Calculator Server with MCP Annotations Source: https://java2ai.com/integration/mcps/annotations/mcp-annotations-examples A complete MCP server example that provides calculator tools. It includes methods for addition, subtraction, multiplication, division, and complex expression calculation, all annotated with @McpTool and @McpToolParam. ```java @SpringBootApplication public class CalculatorServerApplication { public static void main(String[] args) { SpringApplication.run(CalculatorServerApplication.class, args); } } @Component public class CalculatorTools { @McpTool(name = "add", description = "Add two numbers") public double add( @McpToolParam(description = "First number", required = true) double a, @McpToolParam(description = "Second number", required = true) double b) { return a + b; } @McpTool(name = "subtract", description = "Subtract two numbers") public double subtract( @McpToolParam(description = "First number", required = true) double a, @McpToolParam(description = "Second number", required = true) double b) { return a - b; } @McpTool(name = "multiply", description = "Multiply two numbers") public double multiply( @McpToolParam(description = "First number", required = true) double a, @McpToolParam(description = "Second number", required = true) double b) { return a * b; } @McpTool(name = "divide", description = "Divide two numbers") public double divide( @McpToolParam(description = "Dividend", required = true) double dividend, @McpToolParam(description = "Divisor", required = true) double divisor) { if (divisor == 0) { throw new IllegalArgumentException("Division by zero"); } return dividend / divisor; } @McpTool(name = "calculate-expression", description = "Calculate a complex mathematical expression") public CallToolResult calculateExpression( CallToolRequest request, McpSyncRequestContext context) { Map args = request.arguments(); String expression = (String) args.get("expression"); // Use convenient logging method context.info("Calculating: " + expression); try { double result = evaluateExpression(expression); return CallToolResult.builder() .addTextContent("Result: " + result) .build(); } catch (Exception e) { return CallToolResult.builder() .isError(true) .addTextContent("Error: " + e.getMessage()) .build(); } } } ``` -------------------------------- ### Configure STDIO Transport for MCP Client Source: https://java2ai.com/integration/mcps/examples/mcp-client Configure the STDIO transport for the MCP Client Starter using properties. This example shows how to set up a named connection with a command, arguments, and environment variables for the server process. ```yaml spring: ai: mcp: client: stdio: root-change-notification: true connections: server1: command: /path/to/server args: - --port=8080 - --mode=production env: API_KEY: your-api-key DEBUG: "true" ``` -------------------------------- ### RAG Integration Example Source: https://java2ai.com/integration/rag/document-readers Example of how to load documents into a vector store for RAG applications using the POI reader. ```APIDOC ## RAG Document Loading ### Description Demonstrates reading a document, splitting it into chunks, and storing it in a vector database. ### Implementation ```java public void loadDocumentToRAG(String filePath) { // 1. Read document PoiDocumentReader reader = new PoiDocumentReader(filePath); List documents = reader.get(); // 2. Split text List splitDocuments = textSplitter.transform(documents); // 3. Write to vector store vectorStore.write(splitDocuments); } ``` ``` -------------------------------- ### 引入 Spring AI Alibaba NL2SQL 依赖 Source: https://java2ai.com/blog/spring-ai-alibaba-nl2sql 在 Maven 项目中添加 starter 依赖以集成 NL2SQL 功能。 ```xml com.alibaba.cloud.ai spring-ai-alibaba-starter-nl2sql ${revision} ``` -------------------------------- ### Add Azure OpenAI Starter Dependency Source: https://java2ai.com/integration/chatmodels/more/azure-openai-chat Include the necessary starter dependency in your build file to enable auto-configuration. ```xml org.springframework.ai spring-ai-starter-model-azure-openai ``` ```groovy dependencies { implementation 'org.springframework.ai:spring-ai-starter-model-azure-openai' } ``` -------------------------------- ### Weather Service Response Example Source: https://java2ai.com/blog/spring-ai-alibaba-observability-arms This is an example of the response you can expect from the weather service API, providing forecast details. ```text 2024年8月12日,杭州的天气预报为晴转多云,气温32摄氏度。请做好防晒措施,并留意实际天气变化。 ``` -------------------------------- ### Runtime Chat Options Example Source: https://java2ai.com/integration/chatmodels/more/minimax-chat Demonstrates how to override default model and temperature settings for a specific prompt at runtime using MiniMaxChatOptions. ```java ChatResponse response = chatModel.call( new Prompt( "Generate the names of 5 famous pirates.", MiniMaxChatOptions.builder() .model(MiniMaxApi.ChatModel.ABAB_6_5_S_Chat.getValue()) .temperature(0.5) .build() )); ``` -------------------------------- ### Agent Code Example Calling MCP Tool Source: https://java2ai.com/agents/assistantagent/features/mcp/quickstart Example of how an Agent can call an MCP tool that has been automatically registered. ```java # Agent 生成的代码示例 result = mcp.tool_name(param1="value1", param2="value2") ``` -------------------------------- ### SequentialAgent Implementation Example Source: https://java2ai.com/docs/frameworks/agent-framework/advanced/multi-agent Demonstrates creating and using a SequentialAgent to chain multiple ReactAgents. The output of one agent is passed as input to the next, enabling complex workflows. Use this for tasks that require a step-by-step process. ```java import com.alibaba.cloud.ai.graph.agent.flow.agent.SequentialAgent; import com.alibaba.cloud.ai.graph.OverAllState; // 创建专业化的子Agent ReactAgent writerAgent = ReactAgent.builder() .name("writer_agent") .model(chatModel) .description("专业写作Agent") .instruction("你是一个知名的作家,擅长写作和创作。请根据用户的提问进行回答:{input}。") .outputKey("article") .build(); ReactAgent reviewerAgent = ReactAgent.builder() .name("reviewer_agent") .model(chatModel) .description("专业评审Agent") .instruction("你是一个知名的评论家,擅长对文章进行评论和修改。" + "对于散文类文章,请确保文章中必须包含对于西湖风景的描述。待评论文章: {article}" + "最终只返回修改后的文章,不要包含任何评论信息。") .outputKey("reviewed_article") .build(); // 创建顺序Agent SequentialAgent blogAgent = SequentialAgent.builder() .name("blog_agent") .description("根据用户给定的主题写一篇文章,然后将文章交给评论员进行评论") .subAgents(List.of(writerAgent, reviewerAgent)) .build(); // 使用 Optional result = blogAgent.invoke("帮我写一个100字左右的散文"); if (result.isPresent()) { OverAllState state = result.get(); // 访问第一个Agent的输出 state.value("article").ifPresent(article -> { if (article instanceof AssistantMessage) { System.out.println("原始文章: " + ((AssistantMessage) article).getText()); } }); // 访问第二个Agent的输出 state.value("reviewed_article").ifPresent(reviewedArticle -> { if (reviewedArticle instanceof AssistantMessage) { System.out.println("评审后文章: " + ((AssistantMessage) reviewedArticle).getText()); } }); } ``` -------------------------------- ### Install Agent Chat UI Dependencies Source: https://java2ai.com/docs/frameworks/studio/quick-start Install Node.js dependencies for the Agent Chat UI using pnpm or npm. ```bash pnpm install # or # npm install ``` -------------------------------- ### Initialize Cassandra Schema Source: https://java2ai.com/integration/rag/vectordbs/more/apache-cassandra Commands to download and apply the CQL schema for the Wikipedia dataset. ```bash wget https://s.apache.org/colbert-wikipedia-schema-cql -O colbert-wikipedia-schema.cql cqlsh -f colbert-wikipedia-schema.cql ``` -------------------------------- ### Typesense Filter Expression Example Source: https://java2ai.com/integration/rag/vectordbs/more/typesense This example shows a portable filter expression that will be automatically converted to Typesense's native filter format. ```plaintext country in ['UK', 'NL'] && year >= 2020 ```