开启左侧

LangGraph4j 入门

[复制链接]
创想小编 发表于 9 小时前 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
作者:智汇风渔AI小白
LangGraph4j 是一个 Java实现的开源 AI 工作流框架,它受到了 Python 版本 LangGraph的启发,能够与 LangChain4j 和 Spring AI无缝集成,而且这个框架还是开源的。
核心特性

1、StateGraph 工作流图

在LangGraph4j 中,StateGraph 是主要使用的核心类,用于定义应用程序的结构。
它将复杂的AI工作流抽象为一个有向图 的概念。每个 节点 代表一个具体的操作单元,比如调用 LLM 生成文本、搜索外部数据、处理用户输入等。节点之间通过 边 来连接,多个节点之间通过 状态 来共享数据,形成了一个完整的处理流程。
和传统的有向无环图不同,LangGraph4j 支持循环,比如一个智能体可能需要根据结果回到之前的步骤进行重试,或者需要在某个条件满足之前持续循环执行某个逻辑。
注意,使用图之前必须编译编译过程不仅会进行基础的结构检查,还会定义运行时参数,创建一个不可变的、可运行的图。
2、AgentState 状态

AgentState 是整个工作流的状态载体,它本质上是一个Map,在不同节点之间传递。每个节点都可以从这个状态中读取数据,并返回对状态的更新。
注意:实际应用中,如果不需要利用 LangChain4j 的持久化机制,就不建议大家用内置的 Schema 和 Reducer 来维护状态了。不如自己定义一个Context 上下文类来管理状态,想怎么操作状态就怎么操作,不用理解 LangGraph4j 自己的一套语法。
3、Nodes工作节点

节点是图的构建块,负责执行具体的操作。
工作流程:首先接收当前的AgentState 状态作为输入,然后执行某些计算(比如调用 LLM、执行工具、运行自定义业务逻辑),最后返回一个 Map<String,Object>,表示对状态的更新。这些更新会根据 Schema中定义的 Reducer应用到 AgentState 中。
节点可以是同步的,也可以是异步的,甚至可以多个节点同时执行。
LangGraph4j 还定义了两个特殊的节点:START 和 END。START 节点表示图的入口点,END节点表示执行路径的结束点。
  1. importstaticorg.bsc.langgraph4j.StateGraph.START;importstaticorg.bsc.langgraph4j.StateGraph.END;
  2. graph.addEdge(START,"nodeA");
  3. graph.addEdge("nodeA", END);
复制代码
4、Edges 边

边定义了节点之间的控制流,决定了工作流的执行路径。正如官方文档所说:“节点负责干活,边负责决定下一步”。
LangGraph4j 支持几种不同类型的边:
● 普通边:最简单的边类型,提供一个节点到另外一个节点的无条件转换。可以通过addEdge(sourceNodeName,destinationNodeName)来定义普通边。
● 条件边:下一个节点是根据当前AgentState动态确定的,更加灵活。当源节点完成后,会执行一个判断函数,这个函数接收当前状态并返回下一个要执行的节点名称。相当于实现了if else 分支逻辑。比如智能体决定使用工具,就跳转到“执行工具”节点,否则跳转到“回复用户”节点。
● 入口点:可以定义当用户输入到达首先调用哪个节点,同样支持条件入口点
5、Checkpoints 检查点

检查点允许你保存图在任何步骤的状态,也就是状态的持久化,有利于调试和恢复复杂的工作流。
检查点的核心作用主要体现在两个方面:
● 支持人类检查、中断喝批准工作步骤。在某些场景下,人类必须能够在任何时间点查看土地状态,并且图必须能够在人类对状态进行任何更新后恢复执行。这种“人在环路”的设计在许多实际应用中都是必须的。
● 允许通过线程隔离不同用户的交互,并且相同用户可以恢复之前的记忆。这对于构建多用户的AI 应用来说特别重要,每个用户都可以由自己的执行历史。根我们之前学习的 Chat Memory对话记忆类似,给工作流传入不同的 thread_id 配置即可:
  1. var config =RunnableConfig.builder().threadId("a").build();
  2. graph.invoke(inputs, config);LangGraph4j 默认提供了基于内存的检查点器:
  3. var saver =newMemorySaver();
复制代码
Demo

了解核心特性后,我们来运行一个demo:
1、引入pom
  1. <!-- LangGraph4j -->
  2. <dependency>
  3.     <groupId>org.bsc.langgraph4j</groupId>
  4.     <artifactId>langgraph4j-core</artifactId>
  5.     <version>1.6.0-rc2</version>
  6. </dependency>
复制代码
2、引入代码
  1. packagecom.yuliang.aicodemother.langgraph4j.demo;importorg.bsc.langgraph4j.action.NodeAction;importjava.util.Collections;importjava.util.List;importjava.util.Map;// Node that adds a greetingclassGreeterNodeimplementsNodeAction<SimpleState>{@OverridepublicMap<String,Object>apply(SimpleState state){System.out.println("GreeterNode executing. Current messages: "+ state.messages());returnMap.of(SimpleState.MESSAGES_KEY,"Hello from GreeterNode!");}}// Node that adds a responseclassResponderNodeimplementsNodeAction<SimpleState>{@OverridepublicMap<String,Object>apply(SimpleState state){System.out.println("ResponderNode executing. Current messages: "+ state.messages());List<String> currentMessages = state.messages();if(currentMessages.contains("Hello from GreeterNode!")){returnMap.of(SimpleState.MESSAGES_KEY,"Acknowledged greeting!");}returnMap.of(SimpleState.MESSAGES_KEY,"No greeting found.");}}packagecom.yuliang.aicodemother.langgraph4j.demo;importorg.bsc.langgraph4j.state.AgentState;importorg.bsc.langgraph4j.state.Channels;importorg.bsc.langgraph4j.state.Channel;importjava.util.*;// Define the state for our graphclassSimpleStateextendsAgentState{publicstaticfinalString MESSAGES_KEY ="messages";// Define the schema for the state.// MESSAGES_KEY will hold a list of strings, and new messages will be appended.publicstaticfinalMap<String,Channel<?>> SCHEMA =Map.of(
  2.             MESSAGES_KEY,Channels.appender(ArrayList::new));publicSimpleState(Map<String,Object> initData){super(initData);}publicList<String>messages(){returnthis.<List<String>>value("messages").orElse(List.of());}}packagecom.yuliang.aicodemother.langgraph4j.demo;importorg.bsc.langgraph4j.GraphRepresentation;importorg.bsc.langgraph4j.StateGraph;importorg.bsc.langgraph4j.GraphStateException;importstaticorg.bsc.langgraph4j.action.AsyncNodeAction.node_async;importstaticorg.bsc.langgraph4j.StateGraph.START;importstaticorg.bsc.langgraph4j.StateGraph.END;importjava.util.List;importjava.util.Map;publicclassSimpleGraphApp{publicstaticvoidmain(String[] args)throwsGraphStateException{// Initialize nodesGreeterNode greeterNode =newGreeterNode();ResponderNode responderNode =newResponderNode();// Define the graph structurevar stateGraph =newStateGraph<>(SimpleState.SCHEMA, initData ->newSimpleState(initData)).addNode("greeter",node_async(greeterNode)).addNode("responder",node_async(responderNode))// Define edges.addEdge(START,"greeter")// Start with the greeter node.addEdge("greeter","responder").addEdge("responder", END)// End after the responder node;// Compile the graphvar compiledGraph = stateGraph.compile();GraphRepresentation demo = stateGraph.getGraph(GraphRepresentation.Type.MERMAID,"demo");System.out.println(demo.toString());// Run the graph// The `stream` method returns an AsyncGenerator.// For simplicity, we'll collect results. In a real app, you might process them as they arrive.// Here, the final state after execution is the item of interest.for(var item : compiledGraph.stream(Map.of(SimpleState.MESSAGES_KEY,"Let's, begin!"))){System.out.println( item );}}}
复制代码
运行结果,得到的图

LangGraph4j 入门-1.png






原文地址:https://blog.csdn.net/javaScript1997/article/details/155986376
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题
阅读排行更多+

Powered by Discuz! X3.4© 2001-2013 Discuz Team.( 京ICP备17022993号-3 )