惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
Last Week in AI
Last Week in AI
博客园_首页
I
InfoQ
T
Tailwind CSS Blog
爱范儿
爱范儿
雷峰网
雷峰网
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
B
Blog
WordPress大学
WordPress大学
A
About on SuperTechFans
V
Visual Studio Blog
有赞技术团队
有赞技术团队
P
Proofpoint News Feed

博客园 - 菩提树下的杨过

langchain4j 学习系列(10)-Skill使用示例 利用SWIG实现JAVA调用C/C++代码 LangGraph4j 学习系列(9)-人机协同(human_in_the_loop) LangGraph4j 学习系列(8)-checkpoint检查点 LangGraph4j 学习系列(7)-流式响应 LangGraph4j 学习系列(6)-并行工作流 LangGraph4j 学习系列(5)-Hook勾子 LangGraph4j 学习系列(4)-SCHEMA和Channel LangGraph4j 学习系列(2)-条件工作流 LangGraph4j 学习系列(1)-顺序工作流 Agent设计模式学习(基于langchain4j实现)(11) - PlanAndExecute Agent设计模式学习(基于langchain4j实现)(10) - ReACT Agent设计模式学习(基于langchain4j实现)(9) - 人机协同 Agent设计模式学习(基于langchain4j实现)(8) - 非AI智能体 Agent设计模式学习(基于langchain4j实现)(7) - 监督者模式 Agent设计模式学习(基于langchain4j实现)(6) - 组合复杂工作流 Agent设计模式学习(基于langchain4j实现)(5) - 条件工作流 Agent设计模式学习(基于langchain4j实现)(4) - 并行工作流 Agent设计模式学习(基于langchain4j实现)(3) - 循环工作流 Agent设计模式学习(基于langchain4j实现)(2) - 顺序工作流
LangGraph4j 学习系列(3)-循环工作流
菩提树下的杨过 · 2026-03-01 · via 博客园 - 菩提树下的杨过

上节继续,本节将演示条件工作流如何用langgraph4j实现。

image

注:循环工作流可以看成 条件工作流的一个变种。node1 -> node2 -> node1 这样就形成了1个死循环(loop),为了能跳出死循环,用条件边来判定跳出时机。

一、定义节点

public class Node1Action implements NodeAction<AgentState> {
    @Override
    public Map<String, Object> apply(AgentState state) throws Exception {
        System.out.println("current Node: node-1");
        return Map.of("myData", "node1-my-value",
                "node1Key", "node1-value");
    }
}
public class Node2Action implements NodeAction<AgentState> {
    @Override
    public Map<String, Object> apply(AgentState state) throws Exception {
        System.out.println("current Node: node-2");
        return Map.of("myData", "node2-my-value",
                "node2Key", "node2-value");
    }
}

二、完整示例

public class LoopGraphApplication {

    public static void main(String[] args) throws GraphStateException {
        StateGraph<AgentState> sequenceGraph = getLoopGraph();
        System.out.println(sequenceGraph.getGraph(GraphRepresentation.Type.MERMAID, "loop Graph", true).content());
        sequenceGraph.compile().invoke(Map.of("loopCount", 0L)).ifPresent(c -> {
            System.out.println(c.data());
        });
    }

    private static final int MAX_LOOP_ITERATIONS = 3;

    public static StateGraph<AgentState> getLoopGraph() throws GraphStateException {
        return new StateGraph<>(AgentState::new)
                .addNode("node-1", node_async(new Node1Action()))
                .addNode("node-2", node_async(new Node2Action()))
                .addEdge(GraphDefinition.START, "node-1")
                .addEdge("node-2", "node-1")
                //循环的跳出条件比较简单,3次后退出,这里就不单独定义EdgeAction类了,用lambda表达式
                .addConditionalEdges("node-1", state -> {
                    long count = getLoopCount(state);
                    System.out.println("loop Count: " + count);
                    if (count >= MAX_LOOP_ITERATIONS) {
                        return CompletableFuture.completedFuture("exit");
                    }
                    return CompletableFuture.completedFuture("continue");
                }, Map.of(
                        "exit", GraphDefinition.END,
                        "continue", "node-2"));
    }

    private static long getLoopCount(AgentState state) {
        Optional<Object> loopCount = state.value("loopCount");
        if (loopCount.isEmpty()) {
            return 0L;
        }
        Object v = loopCount.get();
        if (v instanceof Number n) {
            return n.longValue();
        }
        return Long.parseLong(v.toString());
    }


}

三、运行结果

current Node: node-1
loop Count: 0
current Node: node-2
current Node: node-1
loop Count: 1
current Node: node-2
current Node: node-1
loop Count: 2
current Node: node-2
current Node: node-1
loop Count: 3
{node1Key=node1-value, loopCount=3, node2Key=node2-value, myData=node1-my-value}