第 15 章 · 第一个 AI 工作流:Hello Graph 从 START 跑到 END

版本:LangGraph4j 1.8.25 (Java 17+) 目标:用 BOM + langgraph4j-core,跑通一张只有一个节点的图:START → greet → END。 本章不接模型、不落盘。

上图就是本章要跑通的全部:输入里带 namegreet 节点写回 greetinglogs,到 END 后取出最终状态。


15.1 依赖

LangGraph4j 1.8.25
Java 17+(推荐 21)

版本只在 BOM 里写一次。业务依赖不要再手写 <version>,避免和 BOM 锁的版本不一致。

xml 复制代码
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.bsc.langgraph4j</groupId>
      <artifactId>langgraph4j-bom</artifactId>
      <version>1.8.25</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
​
<dependencies>
  <dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-core</artifactId>
  </dependency>
</dependencies>

Gradle:implementation(platform("org.bsc.langgraph4j:langgraph4j-bom:1.8.25")),再 implementation("org.bsc.langgraph4j:langgraph4j-core")

本章只引 langgraph4j-core


15.2 一张能跑的图

下面这段可以放进 main。读的时候对照上图:schema 声明键怎么合并,greet 只返回要改的键,边把 STARTEND 接上,compile 之后才能 invoke

java 复制代码
import static org.bsc.langgraph4j.StateGraph.END;
import static org.bsc.langgraph4j.StateGraph.START;
​
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
​
import org.bsc.langgraph4j.CompiledGraph;
import org.bsc.langgraph4j.StateGraph;
import org.bsc.langgraph4j.action.AsyncNodeAction;
import org.bsc.langgraph4j.action.NodeAction;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.state.Channel;
import org.bsc.langgraph4j.state.Channels;
​
public class HelloGraph {
​
    public static class HelloState extends AgentState {
        public HelloState(Map<String, Object> initData) {
            super(initData);
        }
​
        public Optional<String> greeting() {
            return value("greeting");
        }
    }
​
    public static void main(String[] args) throws Exception {
        Map<String, Channel<?>> schema = Map.of(
                "greeting", Channels.base(() -> ""),
                "logs", Channels.appenderWithDuplicate(ArrayList::new)
        );
​
        NodeAction<HelloState> greet = state -> {
            String name = state.<String>value("name").orElse("world");
            return Map.of(
                    "greeting", "Hello, " + name + "!",
                    "logs", List.of("greet-executed")
            );
        };
​
        CompiledGraph<HelloState> compiled = new StateGraph<>(schema, HelloState::new)
                .addNode("greet", AsyncNodeAction.node_async(greet))
                .addEdge(START, "greet")
                .addEdge("greet", END)
                .compile();
​
        compiled.invoke(Map.of("name", "LangGraph4j"))
                .ifPresent(s -> System.out.println(s.greeting().orElse("")));
        // → Hello, LangGraph4j!
    }
}

这段代码里有五点:

  1. 节点返回部分更新 ,只交出要改的键。这里是 greetinglogs

  2. 返回的 Map 由 Channel 合并进状态。节点里不要改 state.data() 里已有的集合。

  3. greetingChannels.base,后写覆盖前写。logsappenderWithDuplicate,每次追加,允许重复。

  4. name 只出现在 invoke 的输入里,不必写进 schema。没有 Channel 的键按覆盖合入。

  5. addNode 接收的是 AsyncNodeAction。同步逻辑先写成 NodeAction,再用 AsyncNodeAction.node_async 包一层。

无参 compile() 使用默认 CompileConfig。单次运行最多走 25 步(recursionLimit)。这张图只有一个节点,碰不到这个上限。


15.3 再看一遍执行

invoke 只给最终状态。要看经过了哪个节点,用 stream

java 复制代码
compiled.stream(Map.of("name", "stream-user"))
        .forEachAsync(out -> System.out.println(out.node() + " → " + out.state().data()))
        .join();

导出图结构(核对边是否接上):

java 复制代码
import org.bsc.langgraph4j.GraphRepresentation;
​
System.out.println(compiled.getGraph(
        GraphRepresentation.Type.MERMAID, "Hello Graph").content());

15.4 构造方法,以及跑不起来时看什么

StateGraph 有四种构造。本章用第一种。

构造 何时用
(channels, AgentStateFactory) 有 schema,更新走 Channel
(channels, StateSerializer) 还要规定状态怎么序列化
(AgentStateFactory) 不声明 schema,Channel 表为空。没声明的键按覆盖写入
(StateSerializer) 同上,但序列化方式自己指定
现象 处理
图不从入口走 addEdge(START, "greet")
编译或运行报找不到出口 addEdge("greet", END)
依赖版本互相打架 只在 BOM 锁 1.8.25,业务依赖去掉手写版本
资料里的 MessageChannel 编译失败 1.8.25 已没有这个类;列表用 Channels.appenderappenderWithDuplicate

compile() 得到的 CompiledGraph 可以反复 invoke。改节点或改边之后,要重新 compile

相关推荐
搜狐技术产品小编20231 小时前
解锁Kotlin Serialization高阶玩法:详解4种自定义序列化器与动态上下文策略
java·人工智能
甲维斯1 小时前
Jev到底是个什么东西?举个形象的例子!
人工智能
jingli91 小时前
多平台多店铺客服怎么统一接待?千牛/拼多多/抖音/京东/闲鱼/微信/快手切窗口太累,一个后台集中接管的七步落地方案(2026 实操版)
人工智能·自动化·用户运营
workflower1 小时前
SSH(Struts+Spring+Hibernate)
人工智能·机器学习·机器人·云计算·无人机
武子康1 小时前
自己做一个 Mini Reviewer:让 AI 审到本次准备提交的代码
人工智能·llm·agent
木子算法1 小时前
不是重心也不是中点:费马—韦伯点、它的最优性条件与迭代求解
人工智能·算法·目标跟踪
正经教主1 小时前
【FDE系列】阶段2:Day 43:Docker Compose — 多容器一键编排
人工智能·docker·fde
YOLO数据集集合1 小时前
天空红外小目标检测数据集 | 红外小目标 天空目标检测 无人机检测 鸟类识别 低空安防9099期
人工智能·目标检测·计算机视觉·目标跟踪·无人机·无人机视角·直升机检测
徐健峰1 小时前
Windows 安装 Codex CLI 教程:npm 安装、首次登录与常见报错排查【无图精华版】
人工智能·gpt