Come Eseguire Agenti AI Ciclici in Java
La maggior parte dei tutorial sui sistemi multi-agente con LLM è scritta in Python. Se stai scrivendo un backend in Java e vuoi costruire qualcosa di più complesso di una catena lineare di chiamate, prima dovevi inventare i tuoi sistemi a stati finiti o improvvisare ramificazioni su LangChain4j.
Nell'ecosistema Python, LangGraph del team LangChain è diventato lo standard per questi compiti. Risolve un problema semplice: i veri agenti conversazionali quasi mai funzionano in linea retta (DAG). Un agente deve chiamare uno strumento, esaminare un errore, chiedere chiarimenti all'utente o riavviare un sottocompito. Questi sono cicli.
Il progetto LangGraph4j porta questo concetto nel mondo Java. La libreria funziona bene con Spring AI e LangChain4j, supporta la persistenza dello stato su database reali e fornisce la possibilità di costruire grafi di esecuzione complessi.
Cosa C'è all'Interno e Come Funziona
Al centro della libreria c'è la classe StateGraph. Descrivi un grafo come un insieme di nodi, archi e stato condiviso che viene passato tra i vari passaggi.
Ogni nodo riceve lo stato corrente, esegue una logica (ad esempio chiama un LLM o accede a un database) e restituisce un dizionario con gli aggiornamenti. Questi aggiornamenti vengono uniti allo stato condiviso attraverso i cosiddetti reducer. Ad esempio, i nuovi messaggi possono essere aggiunti alla fine di una lista, mentre un flag di stato può semplicemente essere sovrascritto.
Esempio Base
Per lavorare con questo servono Java 17 o versione successiva. Aggiungi la dipendenza:
<dependency>
<groupId>org.bsc.langgraph4j</groupId>
<artifactId>langgraph4j-core</artifactId>
<version>1.8.24</version>
</dependency>
Descriviamo il grafo più semplice con due nodi e uno stato condiviso per i messaggi:
import org.bsc.langgraph4j.StateGraph;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.state.Channels;
import org.bsc.langgraph4j.state.Channel;
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.ArrayList;
import java.util.List;
import java.util.Map;
// 1. Описываем структуру состояния
class SimpleState extends AgentState {
public static final String MESSAGES_KEY = "messages";
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());
}
}
public class SimpleApp {
public static void main(String[] args) throws Exception {
// 2. Собираем граф
var graph = new StateGraph<>(SimpleState.SCHEMA, SimpleState::new)
.addNode("greeter", node_async(state ->
Map.of(SimpleState.MESSAGES_KEY, "Привет от первого узла!")))
.addNode("responder", node_async(state ->
Map.of(SimpleState.MESSAGES_KEY, "Ответ получен.")))
.addEdge(START, "greeter")
.addEdge("greeter", "responder")
.addEdge("responder", END)
.compile();
// 3. Запускаем стриминг шагов
for (var step : graph.stream(Map.of(SimpleState.MESSAGES_KEY, "Старт"))) {
System.out.println("Шаг выполнен: " + step);
}
}
}
Qui, il grafo restituisce un generatore asincrono. Ottieni lo stato del grafo dopo l'esecuzione di ogni nodo, il che è comodo per trasmettere aggiornamenti in streaming al client in tempo reale.
Cosa Rende Questo Progetto Interessante in Pratica
1. Transizioni Condizionali e Cicli
Le catene lineari sono facili da costruire con il codice normale. La potenza dei grafi si manifesta quando aggiungi archi condizionali. Alleghi a un arco una funzione che esamina il risultato del lavoro del LLM e decide dove andare dopo: a un nodo di chiamata strumento, alla rigenerazione o al completamento del dialogo.
2. Persistenza dello Stato e Time Travel
Se un agente comunica con un utente attraverso più iterazioni o un processo richiede ore, mantenere tutto nella memoria JVM non è praticabile.
LangGraph4j include un modulo di checkpoint. Sono disponibili adattatori pronti all'uso per PostgreSQL, Redis, MySQL, SQLite, OracleDB, Hazelcast e DynamoDB. Puoi:
- Salvare lo stato dopo ogni passaggio;
- Riprendere l'esecuzione da un punto specifico dopo un riavvio del servizio;
- Implementare Human-in-the-loop, dove il grafo attende la conferma umana di un'azione e poi continua;
- "Riavvolgere" il grafo a uno snapshot di stato precedente.
3. Integrazione Nativa con Spring AI e LangChain4j
Non dovrai riscrivere le chiamate ai modelli per un'API separata. Il repository include già moduli di integrazione.
Ecco come eseguire un agente ReAct con LangGraph4j e LangChain4j:
var model = OllamaChatModel.builder()
.modelName("qwen2.5:7b")
.baseUrl("http://localhost:11434")
.build();
var agent = AgentExecutor.builder()
.chatModel(model)
.toolsFromObject(new TestTool())
.build()
.compile();
for (var item : agent.stream(Map.of("messages", "Проверь статус и верни число потоков"))) {
System.out.println(item);
}
Per Spring AI, la sintassi è praticamente identica, usando annotazioni e bean Spring.
4. LangGraph Studio e Visualizzazione
Il debug di grafi complessi senza visibilità è difficile. LangGraph4j può generare diagrammi del grafo in formati PlantUML e Mermaid.
Gli autori hanno anche costruito un'interfaccia web chiamata LangGraph4j Studio, che puoi incorporare direttamente nella tua applicazione Spring Boot, Quarkus o Jetty per eseguire visivamente e ispezionare i nodi del grafo nel browser.
Avvertimenti
La libreria è in fase di sviluppo attivo (versione 1.8.x al momento di questa revisione), quindi alcune API rare potrebbero cambiare tra le release minori.
Alcuni tutorial nella cartella degli esempi sono formattati come notebook Jupyter per Java. Per eseguire questi esempi, gli autori richiedono Java 22, anche se il nucleo della libreria funziona bene su Java 17+ stabile.
A Chi Serve
Se stai costruendo servizi enterprise su Spring Boot o Quarkus e vuoi implementare scenari agentici (supporto tecnico, automazione CI/CD, elaborazione di documenti multi-fase), LangGraph4j elimina la necessità di scrivere il tuo scheduler di compiti per i LLM.
La libreria fornisce una base architetturale matura senza costringere il team a passare a uno stack Python solo per l'orchestrazione degli agenti. Puoi iniziare a sperimentare con un modello locale tramite Ollama e un semplice grafo di due o tre nodi.
Progetti correlati