>_ DevTrendsfr

Langue

Accueil

Langages

Sections

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embarqué Sécurité
Java

Comment exécuter des agents IA cycliques en Java

La plupart des tutoriels sur les systèmes multi-agents avec les LLMs sont écrits en Python. Si vous développez un backend en Java et souhaitez construire quelque chose de plus complexe qu'une chaîne linéaire d'appels, vous deviez auparavant inventer vos propres machines à états finis ou bricoler des embranchements par-dessus LangChain4j.

Dans l'écosystème Python, LangGraph de l'équipe LangChain est devenu la référence pour ces tâches. Il résout un problème simple : les vrais agents conversationnels ne fonctionnent presque jamais en ligne droite (DAG). Un agent doit appeler un outil, examiner une erreur, demander une clarification à l'utilisateur ou redémarrer une sous-tâche. Ce sont des cycles.

Le projet LangGraph4j apporte ce concept au monde Java. La bibliothèque fonctionne bien avec Spring AI et LangChain4j, prend en charge la persistance d'état dans de vraies bases de données et offre la possibilité de construire des graphes d'exécution complexes.

Ce qu'il y a à l'intérieur et comment ça fonctionne

Au cœur de la bibliothèque se trouve la classe StateGraph. Vous décrivez un graphe comme un ensemble de nœuds, d'arêtes et d'état partagé qui circule entre les étapes.

Chaque nœud reçoit l'état actuel, exécute une logique (par exemple, appelle un LLM ou accède à une base de données) et renvoie un dictionnaire avec les mises à jour. Ces mises à jour sont fusionnées avec l'état partagé via des soi-disant réducteurs. Par exemple, les nouveaux messages peuvent être ajoutés à la fin d'une liste, tandis qu'un indicateur d'état peut simplement être écrasé.

Exemple de base

Vous avez besoin de Java 17 ou plus récent pour travailler avec ceci. Ajoutez la dépendance :

<dependency>
    <groupId>org.bsc.langgraph4j</groupId>
    <artifactId>langgraph4j-core</artifactId>
    <version>1.8.24</version>
</dependency>

Décrivons le graphe le plus simple avec deux nœuds et un état partagé pour les messages :

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);
        }
    }
}

Ici, le graphe renvoie un générateur asynchrone. Vous obtenez l'état du graphe après l'exécution de chaque nœud, ce qui est pratique pour transmettre les mises à jour de progression au client en temps réel.

Ce qui rend ce projet intéressant en pratique

1. Transitions conditionnelles et cycles

Les chaînes linéaires sont faciles à construire avec du code classique. La puissance des graphes se révèle quand vous ajoutez des arêtes conditionnelles. Vous attachez une fonction à une arête qui examine le résultat du travail du LLM et décide où aller ensuite : vers un nœud d'appel d'outil, vers une régénération ou vers la finalisation du dialogue.

2. Persistance d'état et retour dans le temps

Si un agent communique avec un utilisateur sur plusieurs itérations ou si un processus prend des heures, tout conserver en mémoire JVM n'est pas envisageable.

LangGraph4j inclut un module de point de contrôle. Des adaptateurs prêts à l'emploi sont disponibles pour PostgreSQL, Redis, MySQL, SQLite, OracleDB, Hazelcast et DynamoDB. Vous pouvez :

  • Sauvegarder l'état après chaque étape ;
  • Reprendre l'exécution à partir d'un point précis après un redémarrage du service ;
  • Implémenter le Human-in-the-loop, où le graphe attend la confirmation humaine d'une action puis continue ;
  • « Rembobiner » le graphe jusqu'à un instantané d'état précédent.

3. Intégration native avec Spring AI et LangChain4j

Vous n'aurez pas besoin de réécrire les appels de modèle pour une API séparée. Le dépôt inclut déjà des modules d'intégration.

Voici comment exécuter un agent ReAct avec LangGraph4j et 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);
}

Pour Spring AI, la syntaxe est pratiquement identique, en utilisant des annotations et des beans Spring.

4. LangGraph Studio et visualisation

Déboguer des graphes complexes sans visibilité est difficile. LangGraph4j peut générer des diagrammes de graphes aux formats PlantUML et Mermaid.

Les auteurs ont également créé une interface web appelée LangGraph4j Studio, que vous pouvez intégrer directement dans votre application Spring Boot, Quarkus ou Jetty pour exécuter visuellement et inspecter les nœuds du graphe dans le navigateur.

Points de vigilance

La bibliothèque est en développement actif (version 1.8.x au moment de cet article), donc certaines API rares peuvent changer entre les versions mineures.

Certains tutoriels dans le dossier d'exemples sont formatés comme des notebooks Jupyter pour Java. Pour exécuter ces exemples, les auteurs exigent Java 22, même si le cœur de la bibliothèque fonctionne parfaitement sur Java 17+ stable.

À qui cela s'adresse-t-il

Si vous construisez des services d'entreprise sur Spring Boot ou Quarkus et souhaitez implémenter des scénarios agentiques (support technique, automatisation CI/CD, traitement de documents multi-étapes), LangGraph4j élimine le besoin d'écrire votre propre planificateur de tâches pour les LLMs.

La bibliothèque fournit une foundation architecturale mature sans forcer l'équipe à passer à une stack Python juste pour l'orchestration d'agents. Vous pouvez commencer à expérimenter avec un modèle local via Ollama et un graphe simple de deux ou trois nœuds.

Projets similaires