第2章 Graph核心三要素深度解析

章节目标:深入理解 Spring AI Alibaba Graph 的三大核心组件——State、Nodes 和 Edges,掌握它们各自的作用、接口定义以及协作方式,为后续构建智能体工作流打下坚实基础。


2.1 Graph概述

2.1.1 什么是 Spring AI Alibaba Graph

Spring AI Alibaba Graph 是一个用于构建智能体(Agent)工作流的框架,它将智能体的执行流程抽象为图(Graph)结构。在这个图中:

  • 节点(Node)代表智能体执行的具体逻辑步骤,例如调用大模型、调用工具、数据处理等。
  • 边(Edge)代表节点之间的流转关系,决定了执行流程的分支和顺序。
  • 状态(State)是贯穿整个工作流的共享数据结构,记录着每个步骤的中间结果和上下文信息。

通过这种方式,开发者可以用图的方式来建模复杂的智能体行为,将一个大任务拆解为多个小步骤,并通过条件分支实现灵活的决策逻辑。

2.1.2 Graph 的核心设计理念

Spring AI Alibaba Graph 的设计遵循以下理念:

  1. 状态驱动(State-Driven):整个工作流的执行由 State 驱动。每个节点读取当前状态,执行计算后更新状态,状态的变更推动流程向前推进。
  2. 函数式编程(Functional Programming):节点和边都使用函数式接口定义,代码简洁、易于测试和复用。
  3. 可组合性(Composability):节点可以自由组合,边可以灵活定义流转规则,支持条件分支和循环。
  4. 异步执行(Async Execution):所有节点和边默认支持异步操作,适合高并发的智能体场景。

2.2 State详解

2.2.1 OverAllState 的作用

OverAllState 是 Spring AI Alibaba Graph 中用于表示应用程序当前状态的核心数据结构。它扮演着共享状态容器的角色:

  • 数据共享:所有节点都可以读取和修改 OverAllState 中的数据,实现节点间的信息传递。
  • 状态快照:在任何时刻,OverAllState 都代表着工作流的当前快照,包含了执行到当前步骤的所有中间结果。
  • 类型安全OverAllState 通过泛型机制支持自定义状态类型,确保类型安全。

2.2.2 OverAllState 的核心方法

OverAllState 提供了以下关键方法:

// 获取指定 key 的值
<T> T value(String key);

// 设置指定 key 的值
<T> void override(String key, T value);

// 向指定 key 追加值(如果 key 对应的值是列表)
<T> void append(String key, T value);

// 获取所有 key 的集合
Set<String> keySet();

// 获取状态的 Map 表示
Map<String, Object> data();

2.2.3 定义自定义 State

在实际开发中,通常需要定义自己的状态类型来承载业务数据。以下是一个自定义状态的示例:

import com.alibaba.cloud.ai.graph.state.OverAllState;

/**
 * 自定义状态类,用于承载智能体工作流中的业务数据
 */
public class MyAgentState extends OverAllState {

    // 定义状态中的 key 常量
    public static final String KEY_USER_INPUT = "userInput";
    public static final String KEY_LLM_RESPONSE = "llmResponse";
    public static final String KEY_TOOL_RESULTS = "toolResults";
    public static final String KEY_FINAL_ANSWER = "finalAnswer";

    public MyAgentState() {
        super();
    }

    public MyAgentState(Map<String, Object> initialData) {
        super(initialData);
    }

    // 便捷方法:获取用户输入
    public String getUserInput() {
        return value(KEY_USER_INPUT);
    }

    // 便捷方法:设置 LLM 响应
    public void setLlmResponse(String response) {
        override(KEY_LLM_RESPONSE, response);
    }

    // 便捷方法:添加工具调用结果
    public void addToolResult(Object result) {
        append(KEY_TOOL_RESULTS, result);
    }
}

2.2.4 State 的生命周期

在整个 Graph 执行过程中,OverAllState 的生命周期如下:

  1. 初始化:Graph 启动时,OverAllState 被初始化为空状态或传入初始数据。
  2. 节点读取:每个节点执行时,从 OverAllState 中读取所需的数据。
  3. 节点更新:节点执行完成后,将计算结果写回到 OverAllState 中。
  4. 状态传递:更新后的 OverAllState 被传递给下一个节点或边。
  5. 最终状态:当 Graph 执行结束时,OverAllState 包含了整个工作流的完整执行结果。

重要提示OverAllState 是工作流的唯一状态来源,节点之间不直接传递数据,所有数据交换都通过 State 完成。这种设计保证了数据流的清晰和可追溯。


2.3 Nodes详解

2.3.1 AsyncNodeAction 接口

AsyncNodeAction 是定义节点的核心函数式接口,它的作用是编码智能体的逻辑

import com.alibaba.cloud.ai.graph.node.AsyncNodeAction;
import java.util.concurrent.CompletableFuture;

/**
 * 节点函数式接口:接收当前 State,执行计算,返回更新后的 State
 */
@FunctionalInterface
public interface AsyncNodeAction {

    /**
     * 执行节点逻辑
     *
     * @param state 当前工作流状态
     * @return CompletableFuture<OverAllState> 更新后的状态
     */
    CompletableFuture<OverAllState> execute(OverAllState state);
}

2.3.2 创建节点的基本方式

以下展示几种创建节点的典型方式:

方式一:使用 Lambda 表达式

import com.alibaba.cloud.ai.graph.state.OverAllState;

// 创建一个简单的节点:调用大模型生成回复
AsyncNodeAction llmNode = (state) -> {
    String userInput = state.value("userInput");

    // 调用大模型 API
    String response = chatModel.call(userInput);

    // 将结果更新到状态中
    state.override("llmResponse", response);

    return CompletableFuture.completedFuture(state);
};

方式二:使用方法引用

/**
 * 工具调用节点
 */
public class ToolNode {

    public CompletableFuture<OverAllState> execute(OverAllState state) {
        String query = state.value("query");

        // 执行工具调用
        ToolResult result = toolService.invoke(query);

        // 将工具结果追加到状态
        state.append("toolResults", result);

        return CompletableFuture.completedFuture(state);
    }
}

// 注册节点时使用方法引用
AsyncNodeAction toolNode = new ToolNode()::execute;

方式三:使用匿名内部类

AsyncNodeAction processNode = new AsyncNodeAction() {
    @Override
    public CompletableFuture<OverAllState> execute(OverAllState state) {
        // 数据处理逻辑
        String rawData = state.value("rawData");
        String processedData = processRawData(rawData);
        state.override("processedData", processedData);

        return CompletableFuture.completedFuture(state);
    }
};

2.3.3 AsyncNodeActionWithConfig 接口

当节点需要获取额外的上下文信息时(如超时配置、重试策略、自定义参数等),可以使用 AsyncNodeActionWithConfig 接口:

import com.alibaba.cloud.ai.graph.node.AsyncNodeActionWithConfig;
import com.alibaba.cloud.ai.graph.RunnableConfig;

/**
 * 带配置参数的节点函数式接口
 */
@FunctionalInterface
public interface AsyncNodeActionWithConfig {

    /**
     * 执行节点逻辑,可接收 RunnableConfig 上下文
     *
     * @param state  当前工作流状态
     * @param config 运行配置上下文
     * @return CompletableFuture<OverAllState> 更新后的状态
     */
    CompletableFuture<OverAllState> execute(OverAllState state, RunnableConfig config);
}

使用示例

// 创建一个需要读取配置的节点
AsyncNodeActionWithConfig configAwareNode = (state, config) -> {
    // 从配置中获取超时设置
    long timeout = config.timeout();

    // 从配置中获取自定义参数
    Map<String, Object> customParams = config.metadata();
    String modelName = (String) customParams.get("modelName");

    String userInput = state.value("userInput");

    // 使用配置参数调用大模型
    String response = chatModel.call(userInput, modelName, timeout);

    state.override("llmResponse", response);

    return CompletableFuture.completedFuture(state);
};

AsyncNodeAction vs AsyncNodeActionWithConfig 对比

特性 AsyncNodeAction AsyncNodeActionWithConfig
参数 仅接收 State 接收 State + RunnableConfig
适用场景 简单逻辑,无需外部配置 需要动态配置、上下文传递
灵活性 基础 更高

2.4 Edges详解

2.4.1 AsyncEdgeAction 接口

AsyncEdgeAction 是定义边的核心函数式接口,它的作用是根据当前 State 决定下一步执行哪个节点

import com.alibaba.cloud.ai.graph.edge.AsyncEdgeAction;

/**
 * 边函数式接口:根据当前 State 确定下一个节点
 */
@FunctionalInterface
public interface AsyncEdgeAction {

    /**
     * 决定下一步执行的节点
     *
     * @param state 当前工作流状态
     * @return CompletableFuture<String> 下一个节点的名称
     */
    CompletableFuture<String> route(OverAllState state);
}

2.4.2 固定转换(Fixed Transition)

固定转换是最简单的边,它总是指向同一个目标节点,不涉及条件判断:

import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.StateGraph;

// 创建图并添加固定转换
StateGraph graph = new StateGraph(MyAgentState::new)
    // 添加节点
    .addNode("nodeA", nodeAAction)
    .addNode("nodeB", nodeBAction)
    // 添加固定转换:从 nodeA 固定跳转到 nodeB
    .addEdge("nodeA", "nodeB");

固定转换适用于顺序执行的场景,即前一个节点执行完后,无条件地进入下一个节点。

2.4.3 条件分支(Conditional Branching)

条件分支是边的重要特性,它允许根据当前状态的值动态决定下一步:

// 创建一个条件分支边
AsyncEdgeAction conditionalEdge = (state) -> {
    String llmResponse = state.value("llmResponse");

    // 根据 LLM 的响应内容决定下一步
    if (llmResponse.contains("需要调用工具")) {
        // 路由到工具调用节点
        return CompletableFuture.completedFuture("toolNode");
    } else if (llmResponse.contains("需要更多信息")) {
        // 路由到信息收集节点
        return CompletableFuture.completedFuture("infoCollectionNode");
    } else {
        // 直接返回答案
        return CompletableFuture.completedFuture("outputNode");
    }
};

// 在图中使用条件分支
StateGraph graph = new StateGraph(MyAgentState::new)
    .addNode("llmNode", llmNodeAction)
    .addNode("toolNode", toolNodeAction)
    .addNode("infoCollectionNode", infoCollectionAction)
    .addNode("outputNode", outputNodeAction)
    // 条件分支边:从 llmNode 出发,根据条件路由到不同节点
    .addConditionalEdge("llmNode", conditionalEdge);

2.4.4 AsyncEdgeActionWithConfig 接口

与节点类似,边也可以使用带配置的版本:

import com.alibaba.cloud.ai.graph.edge.AsyncEdgeActionWithConfig;

/**
 * 带配置参数的边函数式接口
 */
@FunctionalInterface
public interface AsyncEdgeActionWithConfig {

    /**
     * 决定下一步执行的节点,可接收 RunnableConfig 上下文
     *
     * @param state  当前工作流状态
     * @param config 运行配置上下文
     * @return CompletableFuture<String> 下一个节点的名称
     */
    CompletableFuture<String> route(OverAllState state, RunnableConfig config);
}

使用示例

// 基于配置的条件分支边
AsyncEdgeActionWithConfig configAwareEdge = (state, config) -> {
    Map<String, Object> metadata = config.metadata();
    boolean enableToolCall = (Boolean) metadata.getOrDefault("enableToolCall", true);

    String llmResponse = state.value("llmResponse");

    if (enableToolCall && llmResponse.contains("工具调用")) {
        return CompletableFuture.completedFuture("toolNode");
    }

    return CompletableFuture.completedFuture("outputNode");
};

2.4.5 边的类型总结

边的类型 说明 使用场景
固定转换(Fixed Edge) 无条件地从一个节点跳转到另一个节点 顺序执行流程
条件分支(Conditional Edge) 根据 State 的值动态决定下一个节点 需要决策的智能体流程
入口边(Entry Point) 指定 Graph 的起始节点 定义工作流的入口
结束边(End Edge) 标记 Graph 的终止节点 定义工作流的出口

2.5 KeyStrategy 策略

2.5.1 什么是 KeyStrategy

KeyStrategy 是 Spring AI Alibaba Graph 中用于控制状态更新方式的核心机制。它决定了当节点更新 State 中的某个键时,新的值如何与已有的值进行合并。

核心概念State 中的每个键(Key)都有自己独立的 Strategy 策略。不同键可以使用不同的更新策略,从而实现灵活的状态管理。

2.5.2 默认策略:AppendStrategy

如果没有为某个键显式指定 KeyStrategy,则默认使用 AppendStrategy。这意味着:

  • 该键的所有更新都会直接覆盖其原有值
  • 后一次写入会替换前一次的值。
// 默认行为:直接覆盖
state.override("key1", "value1");  // key1 = "value1"
state.override("key1", "value2");  // key1 = "value2"(覆盖了 value1)

2.5.3 常见的 KeyStrategy 类型

策略名称 行为描述 适用场景
AppendStrategy(默认) 新值直接覆盖旧值 单值状态,如字符串、数字
ListAppendStrategy 将新值追加到列表中 需要累积多个结果的场景
ReduceStrategy 使用自定义的 reduce 函数合并新旧值 需要对值进行聚合计算

2.5.4 显式配置 KeyStrategy

在定义 State 时,可以为不同的键指定不同的策略:

import com.alibaba.cloud.ai.graph.state.strategy.ListAppendStrategy;
import com.alibaba.cloud.ai.graph.state.strategy.ReduceStrategy;

// 创建图时配置 KeyStrategy
StateGraph graph = new StateGraph(
    // 定义状态工厂
    () -> new MyAgentState(),
    // 配置各键的更新策略
    Map.of(
        // "messages" 键使用列表追加策略
        "messages", new ListAppendStrategy<>(),
        // "tokenCount" 键使用累加策略
        "tokenCount", new ReduceStrategy<>((oldVal, newVal) ->
            (Integer) oldVal + (Integer) newVal)
    )
);

ListAppendStrategy 示例

// 使用 ListAppendStrategy 的消息列表
// 每次追加新消息时,消息会被添加到列表末尾,而不是覆盖

// 第一次更新
state.append("messages", new Message("user", "你好"));
// messages = [Message("user", "你好")]

// 第二次更新
state.append("messages", new Message("assistant", "你好!有什么可以帮助你的?"));
// messages = [
//   Message("user", "你好"),
//   Message("assistant", "你好!有什么可以帮助你的?")
// ]

// 第三次更新
state.append("messages", new Message("user", "我想了解 Graph"));
// messages = [
//   Message("user", "你好"),
//   Message("assistant", "你好!有什么可以帮助你的?"),
//   Message("user", "我想了解 Graph")
// ]

2.5.5 KeyStrategy 的工作流程

节点A执行完成
    |
    v
节点A返回更新 Map(包含 key -> newValue)
    |
    v
Graph 根据 key 查找对应的 KeyStrategy
    |
    v
KeyStrategy 将 newValue 合并到 State 中
    |
    v
合并后的 State 传递给下一个节点

设计要点KeyStrategy 的分离设计使得状态更新的行为可以独立配置,不同业务场景可以灵活选择最适合的合并策略,而不需要在节点逻辑中手动处理状态合并。


2.6 各组件之间的关系与协作流程

2.6.1 三要素协作模型

Spring AI Alibaba Graph 的三大核心组件通过以下方式协作:

+------------------+     +------------------+     +------------------+
|      State       |<----|      Nodes       |     |      Edges       |
|  (OverAllState)  |     | (AsyncNodeAction)|     | (AsyncEdgeAction)|
|                  |     |                  |     |                  |
| - 数据共享       |     | - 执行逻辑       |     | - 路由决策       |
| - 状态快照       |     | - 读取 State     |     | - 条件分支       |
| - 中间结果       |     | - 更新 State     |     | - 确定下一节点   |
+------------------+     +------------------+     +------------------+
         ^                        |                        |
         |                        v                        v
         |               +------------------+     +------------------+
         |               |  节点执行逻辑    |     |  判断下一节点    |
         |               |  state -> newState|    |  -> "nodeName"   |
         |               +------------------+     +------------------+
         |                        |
         +------------------------+
              State 更新后回传

2.6.2 完整的执行流程

以下是一个完整的 Graph 执行流程示例:

1. 初始化
   - 创建空的 OverAllState
   - 注入初始数据(用户输入等)

2. 入口节点(Entry Point)
   |
   v
3. 执行 Node A(如:LLM调用)
   - 读取 State 中的 userInput
   - 调用大模型 API
   - 将 llmResponse 写入 State
   |
   v
4. 执行 Edge A(条件分支)
   - 读取 State 中的 llmResponse
   - 判断是否需要工具调用
   - 返回下一个节点名称:"toolNode" 或 "outputNode"
   |
   v
5. 根据 Edge 的决策,执行 Node B 或 Node C
   |
   v
6. 重复步骤 3-5,直到到达 END 节点
   |
   v
7. 返回最终的 State 作为执行结果

2.6.3 数据流示意图

// 数据流代码示意
public void executeFlow() {
    // Step 1: 初始化 State
    OverAllState state = new OverAllState();
    state.override("userInput", "查询今天的天气");

    // Step 2: 第一个节点读取 State 并更新
    // Node: LLM 理解意图
    String userInput = state.value("userInput");  // 读取: "查询今天的天气"
    String intent = llmService.understand(userInput);
    state.override("intent", intent);              // 写入: intent = "weather_query"

    // Step 3: 边根据 State 做路由决策
    // Edge: 判断意图类型
    String nextNode = intent.equals("weather_query") ? "weatherTool" : "generalLLM";

    // Step 4: 第二个节点继续读取和更新
    // Node: 调用天气工具
    String city = state.value("userInput");  // 可读取之前的状态
    WeatherResult result = weatherService.query(city);
    state.override("weatherResult", result);  // 写入工具结果

    // Step 5: 最终结果
    // Node: 生成回复
    WeatherResult weather = state.value("weatherResult");
    String answer = llmService.generateAnswer(weather);
    state.override("finalAnswer", answer);

    // 最终 State 包含了所有中间结果
    String finalAnswer = state.value("finalAnswer");
}

2.7 完整代码示例

2.7.1 构建一个简单的智能体 Graph

以下是一个完整的智能体工作流示例,包含了状态定义、节点创建、边配置以及图的编译和执行:

package com.example.agent;

import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.StateGraph;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import com.alibaba.cloud.ai.graph.state.OverAllState;
import com.alibaba.cloud.ai.graph.state.strategy.ListAppendStrategy;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 简单的问答智能体 Graph 示例
 */
public class QaAgentGraph {

    // ==================== 1. 定义状态键常量 ====================
    public static final String KEY_INPUT = "input";
    public static final String KEY_MESSAGES = "messages";
    public static final String KEY_REQUIRES_TOOL = "requiresTool";
    public static final String KEY_TOOL_RESULT = "toolResult";
    public static final String KEY_OUTPUT = "output";

    // ==================== 2. 节点定义 ====================

    /**
     * 输入处理节点:解析用户输入并初始化消息列表
     */
    private CompletableFuture<OverAllState> inputNode(OverAllState state) {
        String input = state.value(KEY_INPUT);

        // 将用户输入添加到消息列表
        state.append(KEY_MESSAGES, new Message("user", input));

        return CompletableFuture.completedFuture(state);
    }

    /**
     * LLM 推理节点:调用大模型生成回复
     */
    private CompletableFuture<OverAllState> llmNode(OverAllState state) {
        // 从状态中获取消息历史
        List<Message> messages = state.value(KEY_MESSAGES);

        // 调用大模型(此处为示例,实际使用 ChatModel)
        String response = chatModel.call(messages);

        // 判断是否需要工具调用
        boolean requiresTool = response.contains("[TOOL_CALL]");
        state.override(KEY_REQUIRES_TOOL, requiresTool);
        state.override(KEY_LLM_RESPONSE, response);

        return CompletableFuture.completedFuture(state);
    }

    /**
     * 工具调用节点:执行外部工具
     */
    private CompletableFuture<OverAllState> toolNode(OverAllState state) {
        String response = state.value("llmResponse");

        // 解析工具调用参数(简化示例)
        String toolParams = extractToolParams(response);

        // 调用工具
        String toolResult = toolService.execute(toolParams);

        // 将工具结果写入状态
        state.override(KEY_TOOL_RESULT, toolResult);
        state.append(KEY_MESSAGES, new Message("tool", toolResult));

        return CompletableFuture.completedFuture(state);
    }

    /**
     * 输出节点:生成最终回复
     */
    private CompletableFuture<OverAllState> outputNode(OverAllState state) {
        String llmResponse = state.value("llmResponse");

        // 清理响应中的特殊标记,生成最终输出
        String output = cleanResponse(llmResponse);
        state.override(KEY_OUTPUT, output);

        return CompletableFuture.completedFuture(state);
    }

    // ==================== 3. 边定义 ====================

    /**
     * 条件分支边:判断是否需要工具调用
     */
    private CompletableFuture<String> routingEdge(OverAllState state) {
        Boolean requiresTool = state.value(KEY_REQUIRES_TOOL);

        if (Boolean.TRUE.equals(requiresTool)) {
            // 需要工具调用,路由到工具节点
            return CompletableFuture.completedFuture("toolNode");
        }
        // 不需要工具调用,直接输出
        return CompletableFuture.completedFuture("outputNode");
    }

    // ==================== 4. 构建和编译 Graph ====================

    public CompiledGraph buildGraph() {
        StateGraph graph = new StateGraph(
            // 状态工厂
            OverAllState::new,
            // KeyStrategy 配置
            Map.of(
                // messages 使用列表追加策略,保留完整的对话历史
                KEY_MESSAGES, new ListAppendStrategy<>()
            )
        );

        // 添加节点
        graph.addNode("inputNode", this::inputNode)
             .addNode("llmNode", this::llmNode)
             .addNode("toolNode", this::toolNode)
             .addNode("outputNode", this::outputNode);

        // 设置入口点
        graph.setEntryPoint("inputNode");

        // 添加固定转换边
        graph.addEdge("inputNode", "llmNode");

        // 添加条件分支边:从 llmNode 出发,根据条件路由
        graph.addConditionalEdge("llmNode", this::routingEdge);

        // 工具执行后,再次回到 LLM 节点进行推理
        graph.addEdge("toolNode", "llmNode");

        // 编译图
        return graph.compile();
    }

    // ==================== 5. 执行 Graph ====================

    public String run(String userInput) {
        // 编译图
        CompiledGraph compiledGraph = buildGraph();

        // 创建初始状态
        OverAllState initialState = new OverAllState();
        initialState.override(KEY_INPUT, userInput);

        // 运行图
        RunnableConfig config = RunnableConfig.builder()
            .timeout(30000)  // 30秒超时
            .build();

        OverAllState finalState = compiledGraph.invoke(initialState, config);

        // 获取最终结果
        return finalState.value(KEY_OUTPUT);
    }
}

2.7.2 使用 RunnableConfig 传递上下文

import com.alibaba.cloud.ai.graph.RunnableConfig;

/**
 * RunnableConfig 的使用示例
 */
public class ConfigExample {

    public void demonstrateConfig() {
        // 创建运行配置
        RunnableConfig config = RunnableConfig.builder()
            .timeout(60000)                    // 设置超时时间(毫秒)
            .metadata(Map.of(                  // 设置自定义元数据
                "modelName", "gpt-4",
                "temperature", 0.7,
                "maxTokens", 2000,
                "enableRetry", true
            ))
            .build();

        // 节点中使用配置
        AsyncNodeActionWithConfig configAwareNode = (state, runnableConfig) -> {
            // 读取超时配置
            long timeout = runnableConfig.timeout();

            // 读取自定义参数
            Map<String, Object> metadata = runnableConfig.metadata();
            String modelName = (String) metadata.get("modelName");
            Double temperature = (Double) metadata.get("temperature");

            // 根据配置执行逻辑
            String input = state.value("input");
            String result = chatModel.call(input, modelName, temperature, timeout);

            state.override("result", result);
            return CompletableFuture.completedFuture(state);
        };

        // 边中使用配置
        AsyncEdgeActionWithConfig configAwareEdge = (state, runnableConfig) -> {
            Map<String, Object> metadata = runnableConfig.metadata();
            boolean skipTool = (Boolean) metadata.getOrDefault("skipTool", false);

            if (skipTool) {
                return CompletableFuture.completedFuture("outputNode");
            }

            Boolean requiresTool = state.value("requiresTool");
            return CompletableFuture.completedFuture(
                Boolean.TRUE.equals(requiresTool) ? "toolNode" : "outputNode"
            );
        };
    }
}

2.7.3 运行结果示例

public class Main {
    public static void main(String[] args) {
        QaAgentGraph agent = new QaAgentGraph();

        // 场景1:直接问答
        String result1 = agent.run("什么是 Spring AI Alibaba Graph?");
        System.out.println(result1);
        // 输出:Spring AI Alibaba Graph 是一个用于构建智能体工作流的框架...

        // 场景2:需要工具调用
        String result2 = agent.run("今天北京的天气怎么样?");
        System.out.println(result2);
        // 执行流程:inputNode -> llmNode -> toolNode -> llmNode -> outputNode
        // 输出:今天北京的天气是晴天,气温 25°C...
    }
}

2.8 本章小结

本章深入解析了 Spring AI Alibaba Graph 的三大核心要素:

核心知识点回顾

组件 接口 职责
State OverAllState 共享数据结构,承载工作流的完整状态快照
Nodes AsyncNodeAction / AsyncNodeActionWithConfig 执行智能体的业务逻辑,读取和更新 State
Edges AsyncEdgeAction / AsyncEdgeActionWithConfig 决定流程的流转方向,支持条件分支和固定转换
KeyStrategy AppendStrategy / ListAppendStrategy / ReduceStrategy 控制 State 中各键的更新合并策略

关键设计原则

  1. State 是唯一的真相来源:所有节点间的数据交换都通过 State 完成。
  2. 函数式接口驱动:节点和边使用函数式接口定义,代码简洁且可测试。
  3. 策略分离:状态更新的策略与业务逻辑分离,通过 KeyStrategy 独立配置。
  4. 全链路异步:所有操作基于 CompletableFuture,支持高并发场景。

下一步学习

在下一章中,我们将学习如何使用 StateGraph构建和编译完整的 Graph 工作流,包括如何添加节点和边、设置入口点、以及图的编译和执行流程。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐