Agent Executor¶
In [1]:
Copied!
var userHomeDir = System.getProperty("user.home");
var localRespoUrl = "file://" + userHomeDir + "/.m2/repository/";
var langchain4jVersion = "1.0.1";
var langchain4jbeta = "1.0.1-beta6";
var langgraph4jVersion = "1.6-SNAPSHOT";
var userHomeDir = System.getProperty("user.home");
var localRespoUrl = "file://" + userHomeDir + "/.m2/repository/";
var langchain4jVersion = "1.0.1";
var langchain4jbeta = "1.0.1-beta6";
var langgraph4jVersion = "1.6-SNAPSHOT";
Remove installed package from Jupiter cache
In [2]:
Copied!
%%bash
rm -rf \{userHomeDir}/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j
%%bash
rm -rf \{userHomeDir}/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j
add local maven repo and install dependencies
In [ ]:
Copied!
%dependency /add-repo local \{localRespoUrl} release|never snapshot|always
// %dependency /list-repos
%dependency /add org.slf4j:slf4j-jdk14:2.0.9
%dependency /add org.bsc.langgraph4j:langgraph4j-core:\{langgraph4jVersion}
%dependency /add org.bsc.langgraph4j:langgraph4j-langchain4j:\{langgraph4jVersion}
%dependency /add org.bsc.langgraph4j:langgraph4j-agent-executor:\{langgraph4jVersion}
%dependency /add dev.langchain4j:langchain4j:\{langchain4jVersion}
%dependency /add dev.langchain4j:langchain4j-open-ai:\{langchain4jVersion}
%dependency /resolve
%dependency /add-repo local \{localRespoUrl} release|never snapshot|always
// %dependency /list-repos
%dependency /add org.slf4j:slf4j-jdk14:2.0.9
%dependency /add org.bsc.langgraph4j:langgraph4j-core:\{langgraph4jVersion}
%dependency /add org.bsc.langgraph4j:langgraph4j-langchain4j:\{langgraph4jVersion}
%dependency /add org.bsc.langgraph4j:langgraph4j-agent-executor:\{langgraph4jVersion}
%dependency /add dev.langchain4j:langchain4j:\{langchain4jVersion}
%dependency /add dev.langchain4j:langchain4j-open-ai:\{langchain4jVersion}
%dependency /resolve
Initialize Logger
In [4]:
Copied!
try( var file = new java.io.FileInputStream("./logging.properties")) {
java.util.logging.LogManager.getLogManager().readConfiguration( file );
}
var log = org.slf4j.LoggerFactory.getLogger("AgentExecutor");
try( var file = new java.io.FileInputStream("./logging.properties")) {
java.util.logging.LogManager.getLogManager().readConfiguration( file );
}
var log = org.slf4j.LoggerFactory.getLogger("AgentExecutor");
Create Tools
In [5]:
Copied!
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.util.Optional;
import static java.lang.String.format;
public class TestTool {
private String lastResult;
Optional<String> lastResult() {
return Optional.ofNullable(lastResult);
}
@Tool("tool for test AI agent executor")
String execTest(@P("test message") String message) {
lastResult = format( "test tool executed: %s", message);
return lastResult;
}
}
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.util.Optional;
import static java.lang.String.format;
public class TestTool {
private String lastResult;
Optional lastResult() {
return Optional.ofNullable(lastResult);
}
@Tool("tool for test AI agent executor")
String execTest(@P("test message") String message) {
lastResult = format( "test tool executed: %s", message);
return lastResult;
}
}
In [8]:
Copied!
import static org.bsc.langgraph4j.StateGraph.END;
import static org.bsc.langgraph4j.StateGraph.START;
import org.bsc.langgraph4j.CompileConfig;
import org.bsc.langgraph4j.RunnableConfig;
import org.bsc.langgraph4j.checkpoint.BaseCheckpointSaver;
import org.bsc.langgraph4j.checkpoint.MemorySaver;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.serializer.StateSerializer;
import org.bsc.langgraph4j.agentexecutor.AgentExecutor;
import dev.langchain4j.model.openai.OpenAiChatModel;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
var chatModel = OpenAiChatModel.builder()
.apiKey( System.getenv("OPENAI_API_KEY") )
//.modelName( "gpt-3.5-turbo-0125" )
.modelName( "gpt-4o-mini" )
.logResponses(true)
.maxRetries(2)
.temperature(0.0)
.maxTokens(2000)
.build();
var stateGraph = AgentExecutor.builder()
.chatModel(chatModel)
.toolsFromObject( new TestTool() )
.build();
import static org.bsc.langgraph4j.StateGraph.END;
import static org.bsc.langgraph4j.StateGraph.START;
import org.bsc.langgraph4j.CompileConfig;
import org.bsc.langgraph4j.RunnableConfig;
import org.bsc.langgraph4j.checkpoint.BaseCheckpointSaver;
import org.bsc.langgraph4j.checkpoint.MemorySaver;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.serializer.StateSerializer;
import org.bsc.langgraph4j.agentexecutor.AgentExecutor;
import dev.langchain4j.model.openai.OpenAiChatModel;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
var chatModel = OpenAiChatModel.builder()
.apiKey( System.getenv("OPENAI_API_KEY") )
//.modelName( "gpt-3.5-turbo-0125" )
.modelName( "gpt-4o-mini" )
.logResponses(true)
.maxRetries(2)
.temperature(0.0)
.maxTokens(2000)
.build();
var stateGraph = AgentExecutor.builder()
.chatModel(chatModel)
.toolsFromObject( new TestTool() )
.build();
Test 1¶
Update State replacing the 'input'
In [9]:
Copied!
import dev.langchain4j.data.message.UserMessage;
var saver = new MemorySaver();
CompileConfig compileConfig = CompileConfig.builder()
.checkpointSaver( saver )
.build();
var graph = stateGraph.compile( compileConfig );
var config = RunnableConfig.builder()
.threadId("test1")
.build();
var iterator = graph.streamSnapshots( Map.of( "messages", UserMessage.from("perform test once")), config );
for( var step : iterator ) {
log.info( "STEP: {}", step );
}
import dev.langchain4j.data.message.UserMessage;
var saver = new MemorySaver();
CompileConfig compileConfig = CompileConfig.builder()
.checkpointSaver( saver )
.build();
var graph = stateGraph.compile( compileConfig );
var config = RunnableConfig.builder()
.threadId("test1")
.build();
var iterator = graph.streamSnapshots( Map.of( "messages", UserMessage.from("perform test once")), config );
for( var step : iterator ) {
log.info( "STEP: {}", step );
}
START callAgent STEP: StateSnapshot{node=__START__, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }]}, config=RunnableConfig{ threadId=test1, checkPointId=27429124-b74c-4eaa-b29e-cbf757f12839, nextNode=agent, streamMode=SNAPSHOTS }} executeTools execute: execTest STEP: StateSnapshot{node=agent, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }]}, config=RunnableConfig{ threadId=test1, checkPointId=3e2bf343-4a92-4e71-a215-b42dc807a217, nextNode=action, streamMode=SNAPSHOTS }} callAgent STEP: StateSnapshot{node=action, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_3kcsKL1AcgUTXPvr835vdKfv" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test1, checkPointId=b5918cd8-12eb-4b58-a3e3-a4565a70bc81, nextNode=agent, streamMode=SNAPSHOTS }} STEP: StateSnapshot{node=agent, state={agent_response=The test has been executed with the message: "perform test once". If you need anything else, feel free to ask!, messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_3kcsKL1AcgUTXPvr835vdKfv" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test1, checkPointId=3de4b09a-6801-43f0-9b4b-dd8a40fe63f9, nextNode=__END__, streamMode=SNAPSHOTS }} STEP: NodeOutput{node=__END__, state={agent_response=The test has been executed with the message: "perform test once". If you need anything else, feel free to ask!, messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_3kcsKL1AcgUTXPvr835vdKfv" toolName = "execTest" text = "test tool executed: perform test once" }]}}
In [10]:
Copied!
import org.bsc.langgraph4j.state.RemoveByHash;
var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );
for( var snapshot : history ) {
log.info( "{}", snapshot );
}
// var state2 = history.get(2);
// var updatedConfig = graph.updateState( state2.config(),
// Map.of( "messages", UserMessage.from("perform test twice")), null);
// var iterator = graph.streamSnapshots( null, updatedConfig );
// for( var step : iterator ) {
// log.info( "STEP:\n {}", step );
// }
import org.bsc.langgraph4j.state.RemoveByHash;
var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );
for( var snapshot : history ) {
log.info( "{}", snapshot );
}
// var state2 = history.get(2);
// var updatedConfig = graph.updateState( state2.config(),
// Map.of( "messages", UserMessage.from("perform test twice")), null);
// var iterator = graph.streamSnapshots( null, updatedConfig );
// for( var step : iterator ) {
// log.info( "STEP:\n {}", step );
// }
StateSnapshot{node=agent, state={agent_response=The test has been executed with the message: "perform test once". If you need anything else, feel free to ask!, messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_3kcsKL1AcgUTXPvr835vdKfv" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test1, checkPointId=3de4b09a-6801-43f0-9b4b-dd8a40fe63f9, nextNode=__END__, streamMode=VALUES }} StateSnapshot{node=action, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_3kcsKL1AcgUTXPvr835vdKfv" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test1, checkPointId=b5918cd8-12eb-4b58-a3e3-a4565a70bc81, nextNode=agent, streamMode=VALUES }} StateSnapshot{node=agent, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_3kcsKL1AcgUTXPvr835vdKfv", name = "execTest", arguments = "{"message":"perform test once"}" }] }]}, config=RunnableConfig{ threadId=test1, checkPointId=3e2bf343-4a92-4e71-a215-b42dc807a217, nextNode=action, streamMode=VALUES }} StateSnapshot{node=__START__, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }]}, config=RunnableConfig{ threadId=test1, checkPointId=27429124-b74c-4eaa-b29e-cbf757f12839, nextNode=agent, streamMode=VALUES }}
Test 2¶
Update State replacing the 'input' using a cloned state
In [11]:
Copied!
var config = RunnableConfig.builder()
.threadId("test2")
.build();
var iterator = graph.streamSnapshots( Map.of( "messages", UserMessage.from("perform test once") ), config );
for( var step : iterator ) {
log.info( "STEP: {}", step );
}
var config = RunnableConfig.builder()
.threadId("test2")
.build();
var iterator = graph.streamSnapshots( Map.of( "messages", UserMessage.from("perform test once") ), config );
for( var step : iterator ) {
log.info( "STEP: {}", step );
}
START callAgent STEP: StateSnapshot{node=__START__, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }]}, config=RunnableConfig{ threadId=test2, checkPointId=00a2b94c-0a05-495c-8621-3bf6e7a88b72, nextNode=agent, streamMode=SNAPSHOTS }} executeTools execute: execTest STEP: StateSnapshot{node=agent, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_gkU71yQ9RWWls6zVVksyrjGc", name = "execTest", arguments = "{"message":"perform test once"}" }] }]}, config=RunnableConfig{ threadId=test2, checkPointId=887b1fbd-2e30-4b64-9577-3a917533cf68, nextNode=action, streamMode=SNAPSHOTS }} callAgent STEP: StateSnapshot{node=action, state={messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_gkU71yQ9RWWls6zVVksyrjGc", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_gkU71yQ9RWWls6zVVksyrjGc" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test2, checkPointId=520634ab-1658-4b24-b67c-6bfaf758c119, nextNode=agent, streamMode=SNAPSHOTS }} STEP: StateSnapshot{node=agent, state={agent_response=The test has been executed with the message: "perform test once"., messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_gkU71yQ9RWWls6zVVksyrjGc", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_gkU71yQ9RWWls6zVVksyrjGc" toolName = "execTest" text = "test tool executed: perform test once" }]}, config=RunnableConfig{ threadId=test2, checkPointId=f3e0ffea-a7f2-461c-a9a7-3e08fa64ea1e, nextNode=__END__, streamMode=SNAPSHOTS }} STEP: NodeOutput{node=__END__, state={agent_response=The test has been executed with the message: "perform test once"., messages=[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_gkU71yQ9RWWls6zVVksyrjGc", name = "execTest", arguments = "{"message":"perform test once"}" }] }, ToolExecutionResultMessage { id = "call_gkU71yQ9RWWls6zVVksyrjGc" toolName = "execTest" text = "test tool executed: perform test once" }]}}
In [12]:
Copied!
var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );
var state2 = history.get(2);
var updatedState = new HashMap<String,Object>();
updatedState.putAll(state2.state().data());
updatedState.put( "messages", UserMessage.from("perform test twice") );
// var updatedConfig = graph.updateState( state2.config(), updatedState );
// log.info( "UPDATED CONFIG: {}", updatedConfig );
// var iterator = graph.streamSnapshots( null, updatedConfig );
// for( var step : iterator ) {
// log.info( "STEP:\n {}", step );
// }
var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );
var state2 = history.get(2);
var updatedState = new HashMap();
updatedState.putAll(state2.state().data());
updatedState.put( "messages", UserMessage.from("perform test twice") );
// var updatedConfig = graph.updateState( state2.config(), updatedState );
// log.info( "UPDATED CONFIG: {}", updatedConfig );
// var iterator = graph.streamSnapshots( null, updatedConfig );
// for( var step : iterator ) {
// log.info( "STEP:\n {}", step );
// }
Out[12]:
[UserMessage { name = null contents = [TextContent { text = "perform test once" }] }, AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_gkU71yQ9RWWls6zVVksyrjGc", name = "execTest", arguments = "{"message":"perform test once"}" }] }]