>_ DevTrendspl

Język

Strona główna

Języki

Sekcje

Frontend Backend Mobilne DevOps AI / ML GameDev Blockchain Systemy wbudowane Bezpieczeństwo
Java

Jak uruchamiać cykliczne agenty AI w Javie

Większość samouczków dotyczących systemów wieloagentowych z LLM-ami jest pisana w Pythonie. Jeśli tworzysz backend w Javie i chcesz zbudować coś bardziej złożonego niż liniowy łańcuch wywołań, wcześniej musiałeś wymyślać własne automaty skończone lub sklejać rozgałęzienia na szczycie LangChain4j.

W ekosystemie Pythona LangGraph od zespołu LangChain stał się standardem dla takich zadań. Rozwiązuje prosty problem: prawdziwe konwersacyjne agenty prawie nigdy nie działają w linii prostej (DAG). Agent musi wywołać narzędzie, sprawdzić błąd, poprosić użytkownika o wyjaśnienie lub ponownie uruchomić podzadanie. To są cykle.

Projekt LangGraph4j przenosi tę koncepcję do świata Javy. Biblioteka dobrze współpracuje ze Spring AI i LangChain4j, obsługuje persystencję stanu w rzeczywistych bazach danych i zapewnia możliwość budowania złożonych grafów wykonawczych.

Co jest w środku i jak to działa

W rdzeniu biblioteki znajduje się klasa StateGraph. Opisujesz graf jako zbiór węzłów, krawędzi i współdzielonego stanu, który jest przekazywany między krokami.

Każdy węzeł otrzymuje bieżący stan, wykonuje fragment logiki (na przykład wywołuje LLM lub komunikuje się z bazą danych) i zwraca słownik z aktualizacjami. Te aktualizacje są scalane ze współdzielonym stanem poprzez tak zwane reduktory. Na przykład nowe wiadomości mogą być dołączane na końcu listy, podczas gdy flaga statusu może być po prostu nadpisywana.

Podstawowy przykład

Potrzebujesz Javy 17 lub nowszej, aby pracować z tym. Dodaj zależność:

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

Opiszmy najprostszy graf z dwoma węzłami i współdzielonym stanem dla wiadomości:

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

Tutaj graf zwraca asynchroniczny generator. Otrzymujesz stan grafu po wykonaniu każdego węzła, co jest wygodne do strumieniowania postępów do klienta w czasie rzeczywistym.

Co czyni ten projekt interesującym w praktyce

1. Warunkowe przejścia i cykle

Liniowe łańcuchy łatwo budować zwykłym kodem. Siła grafów ujawnia się, gdy dodajesz warunkowe krawędzie. Do krawędzi dołączasz funkcję, która sprawdza wynik pracy LLM-a i decyduje, gdzie przejść dalej: do węzła wywołującego narzędzie, do regeneracji, czy do zakończenia dialogu.

2. Persystencja stanu i podróże w czasie

Jeśli agent komunikuje się z użytkownikiem przez wiele iteracji lub proces trwa godzinami, przechowywanie wszystkiego w pamięci JVM nie jest wykonalne.

LangGraph4j zawiera moduł checkpoint. Dostępne są gotowe adaptery dla PostgreSQL, Redis, MySQL, SQLite, OracleDB, Hazelcast i DynamoDB. Możesz:

  • Zapisywać stan po każdym kroku;
  • Wznawiać wykonanie z określonego punktu po restarcie usługi;
  • Zaimplementować Human-in-the-loop, gdzie graf czeka na potwierdzenie akcji przez człowieka, a następnie kontynuuje;
  • "Przewinąć" graf z powrotem do poprzedniej migawki stanu.

3. Natywna integracja ze Spring AI i LangChain4j

Nie będziesz musiał przepisywać wywołań modeli dla oddzielnego API. Repozytorium zawiera już moduły integracyjne.

Oto jak uruchomić agenta ReAct z LangGraph4j i 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);
}

Dla Spring AI składnia jest praktycznie identyczna, używając adnotacji i beanów Spring.

4. LangGraph Studio i wizualizacja

Debugowanie złożonych grafów bez widoczności jest trudne. LangGraph4j może generować diagramy grafów w formatach PlantUML i Mermaid.

Autorzy zbudowali również interfejs webowy o nazwie LangGraph4j Studio, który możesz osadzić bezpośrednio w aplikacji Spring Boot, Quarkus lub Jetty, aby wizualnie uruchamiać i inspekcjonować węzły grafu w przeglądarce.

Zastrzeżenia

Biblioteka jest aktywnie rozwijana (wersja 1.8.x w momencie tego przeglądu), więc niektóre rzadkie API mogą się zmieniać między wydaniami pomocniczymi.

Niektóre samouczki w folderze examples są sformatowane jako Jupyter notebooks dla Javy. Aby uruchomić te przykłady, autorzy wymagają Javy 22, mimo że rdzeń biblioteki działa bez problemu na stabilnej Javie 17+.

Dla kogo to jest

Jeśli budujesz usługi enterprise na Spring Boot lub Quarkus i chcesz implementować scenariusze agentowe (wsparcie techniczne, automatyzacja CI/CD, wielostopniowe przetwarzanie dokumentów), LangGraph4j eliminuje potrzebę pisania własnego schedulera zadań dla LLM-ów.

Biblioteka zapewnia dojrzałe fundamenty architektoniczne bez zmuszania zespołu do przejścia na stack Pythona wyłącznie dla orkiestracji agentów. Możesz zacząć eksperymentować z modelem lokalnym przez Ollama i prostym grafem z dwoma lub trzema węzłami.

Powiązane projekty