LangGraph4j 入门

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

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节点表示执行路径的结束点。

import static org.bsc.langgraph4j.StateGraph.START;
import static org.bsc.langgraph4j.StateGraph.END;

graph.addEdge(START, "nodeA");
graph.addEdge("nodeA", END);

4、Edges 边

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

5、Checkpoints 检查点

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

var config = RunnableConfig.builder()
                  .threadId("a")
                  .build();
graph.invoke(inputs, config);
LangGraph4j 默认提供了基于内存的检查点器:
var saver = new MemorySaver();

Demo

了解核心特性后,我们来运行一个demo:
1、引入pom

<!-- LangGraph4j -->
<dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-core</artifactId>
    <version>1.6.0-rc2</version>
</dependency>

2、引入代码

package com.yuliang.aicodemother.langgraph4j.demo;

import org.bsc.langgraph4j.action.NodeAction;
import java.util.Collections;
import java.util.List;
import java.util.Map;

// Node that adds a greeting
class GreeterNode implements NodeAction<SimpleState> {
    @Override
    public Map<String, Object> apply(SimpleState state) {
        System.out.println("GreeterNode executing. Current messages: " + state.messages());
        return Map.of(SimpleState.MESSAGES_KEY, "Hello from GreeterNode!");
    }
}

// Node that adds a response
class ResponderNode implements NodeAction<SimpleState> {
    @Override
    public Map<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!")) {
            return Map.of(SimpleState.MESSAGES_KEY, "Acknowledged greeting!");
        }
        return Map.of(SimpleState.MESSAGES_KEY, "No greeting found.");
    }
}


package com.yuliang.aicodemother.langgraph4j.demo;

import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.state.Channels;
import org.bsc.langgraph4j.state.Channel;

import java.util.*;

// Define the state for our graph
class SimpleState extends AgentState {
    public static final String MESSAGES_KEY = "messages";

    // Define the schema for the state.
    // MESSAGES_KEY will hold a list of strings, and new messages will be appended.
    public static final Map<String, Channel<?>> SCHEMA = Map.of(
            MESSAGES_KEY, Channels.appender(ArrayList::new)
    );

    public SimpleState(Map<String, Object> initData) {
        super(initData);
    }

    public List<String> messages() {
        return this.<List<String>>value("messages")
                .orElse( List.of() );
    }
}
package com.yuliang.aicodemother.langgraph4j.demo;

import org.bsc.langgraph4j.GraphRepresentation;
import org.bsc.langgraph4j.StateGraph;
import org.bsc.langgraph4j.GraphStateException;
import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async;
import static org.bsc.langgraph4j.StateGraph.START;
import static org.bsc.langgraph4j.StateGraph.END;

import java.util.List;
import java.util.Map;

public class SimpleGraphApp {

    public static void main(String[] args) throws GraphStateException {
        // Initialize nodes
        GreeterNode greeterNode = new GreeterNode();
        ResponderNode responderNode = new ResponderNode();

        // Define the graph structure
       var stateGraph = new StateGraph<>(SimpleState.SCHEMA, initData -> new SimpleState(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 graph
        var 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 );
        }
    }
}

运行结果,得到的图
在这里插入图片描述

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智汇风渔AI小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值