Strona główna / Artykuły / Wskazówki praktyczne: Jak tworzyć lepsze agenty AI za pomocą LangGraph

Wskazówki praktyczne: Jak tworzyć lepsze agenty AI za pomocą LangGraph

Praktyczne wskazówki: Jak tworzyć lepsze agenty AI za pomocą LangGraph – umowy, sprawdzania oraz gotowe miejsca na kod dla zespołów wdrażających ten wzorzec.

1873 słów

Poniższe notatki przedstawiają praktyczny plan działania dotyczący tematu „Jak tworzyć lepsze agenty AI za pomocą LangGraph”. Nacisk kładziony jest na kontrakty, sprawdzania oraz miejsca na kod do wstawienia, a nie na motywacyjne aspekty. Podczas przechodzenia przez etap przeglądu najpierw zapisz kontrakt: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez człowieka oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dopiero późniejszej optymalizacji.

1. Zarys badań: opanowanie przepływów pracy agentowych

Faza opanowywania w ramach 1. Zarysu Badań działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wtórne struktury ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach.

2. Rozwiązanie: Samokorygujący się agent wyszukiwania

Faza 2 „Rozwiązanie A” funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć milczące, częściowe ukończenie zadań. Utrzymuj stan grafu w prostej formie i określonej typowości. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji pracy po zakłóceniach.

Importy

Etap Importów działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu zmian, zanim rozszerzysz zakres pracy. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach.

import operator
from typing import Annotated, TypedDict, Union
from langgraph.graph import StateGraph, START, END

Wspólny mózg

Faza „The Shared Brain” funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny poufnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, aby operatorzy mogli je sprawdzić bez konieczności przeglądania całej struktury. Utrzymuj stan grafu w prostym formacie i z określonym typem danych. Wplecione struktury ukrywają informację o tym, który węzeł zapisał dane w danym polu, co powoduje przerwę w kontynuacji pracy po wystąpieniu zakłóceń.

# 1. State: The agent's shared memory
class AgentState(TypedDict):
  # 'operator.add' lets us append messages instead of overwriting
    messages: Annotated[list[str], operator.add]
    attempts: int
    found_info: bool

Węzły robocze

Faza węzłów roboczych funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę przywracania do stanu poprzedniego. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione struktury ukrywają informację o tym, który węzeł zapisał dane w danym polu, i powodują przerwanie kontynuacji działania po przerwach.

# 2. Nodes: Individual 'steps' in the process
def search_node(state: AgentState):
    print(f\n"--- Attempt {state['attempts'] + 1}: Searching ---")
    # Simulating a logic check
    success = state['attempts'] >= 1
    msg = "Success: Found LangGraph info!" if success else "No results found."
    return {"messages": [msg], "attempts": state['attempts'] + 1, "found_info": success}

def refine_query_node(state: AgentState):
    print("\n--- Refining query for better results ---")
    return {"messages": ["System: Query refined."]}

Logika routingu

Faza Logiki Łączenia działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach.

def should_continue(state: AgentState):
    if state["found_info"] or state["attempts"] >= 3:
        return "end"
    return "refine"

Budowanie grafu

Etap budowania grafu działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przypadek, jeden przypadek awarii oraz notatkę o cofnięciu działań, zanim rozszerzysz zakres pracy. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadań. Utrzymuj stan grafu w prostej formie i określonej strukturze typów. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji pracy po zakłóceniach.

# 4. Build the Graph
workflow = StateGraph(AgentState)
workflow.add_node("search", search_node)
workflow.add_node("refine", refine_query_node)

workflow.add_edge(START, "search")
workflow.add_conditional_edges("search", should_continue, {"refine": "refine", "end": END})
workflow.add_edge("refine", "search")

Zapuść agenta

Etap „Run the Agent” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Zapisuj czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwę w kontynuacji działania po zakłóceniach.

# 5. Execute
app = workflow.compile()
for output in app.stream({"messages": [], "attempts": 0, "found_info": False}):
    print(output)
--- Attempt 1: Searching ---
{'search': {'messages': ['No results found.'], 'attempts': 1, 'found_info': False}}

--- Refining query for better results ---
{'refine': {'messages': ['System: Query refined.']}}

--- Attempt 2: Searching ---
{'search': {'messages': ['Success: Found LangGraph info!'], 'attempts': 2, 'found_info': True}}

Etap „Run the Agent” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Dokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownego wykonania, kontrola przez ludzi oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później.

3. Pięć wskazówek, jak poprawić swoją pracę z LangGraph

Aby zastosować 3 kluczowe wskazówki, należy przed modyfikacją kodu określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Lepiej używać małych, testowalnych jednostek niż rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces. Konieczne jest ludzkie zatwierdzenie w tych przypadkach, gdy dochodzi do wydawania pieniędzy lub zmiany danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się kompletności biznesowej.

Wskazówka 1: Ustal precyzyjny schemat stanu

Aby skutecznie przeprowadzić etap nr 1, zdefiniuj wprowadzane dane, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj ten etap jako umowę pomiędzy wprowadzanymi danymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań. Zapewnij ludzką aprobatę w przypadku operacji, które wiążą się z wydatkami lub zmianami w danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności biznesowej.

Wskazówka 2: Opanuj warunkowe ścieżki

W fazie Tip 2 Master Conditional należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Zapisuj czas trwania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Wprowadź ludzką aprobatę dla przypadków, w których wydawane są pieniądze lub zmieniane są dane produkcyjne. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności rozwiązania biznesowego. W fazie Tip 2 Master Conditional należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Dokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.

Wskazówka 3: Nie zapominaj o wytrwałości (tworzeniu punktów kontrolnych)

Gdy pracujesz nad Wskazówką 3 „Nie twórz etapów”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolij małe, testowalne jednostki od rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Twórz punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie pobierać opłaty za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.

Wskazówka 4: Przyjmij udział człowieka w procesie

Gdy pracujesz nad wskazówką nr 4 „Przyjmij etap”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania. Ustaw punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.

Wskazówka nr 5: Zachowuj małe węzły

Gdy realizujesz wskazówkę nr 5 „Utrzymaj swoją fazę”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisz czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych. Ustal punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł. Gdy realizujesz wskazówkę nr 5 „Utrzymaj swoją fazę”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych wywołań, mechanizmy ludzkiej kontroli oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.

Zastosowanie w praktyce

Etap zastosowania w rzeczywistym środowisku funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres. Wolij małe, testowalne jednostki nad rozbudowane skrypty. Gdy jakiś krok się nie powiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wtórne struktury ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach.

Odnośniki

Etap odnośników funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania.

List kontrolny operacyjny

Pozycje pokrewne

  • Notatki praktyczne: ToolCallingAgent vs. CodeAgent – który radzi sobie lepiej na — Szczegółowy przewodnik po Notatkach praktycznych: ToolCallingAgent vs. CodeAgent – który radzi sobie lepiej na: kontrakty, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów stosujących ten wzorzec.
  • Notatki praktyczne: LangChain vs LangGraph vs Deep Agents – który powinieneś wybrać — Szczegółowy przewodnik po Notatkach praktycznych: LangChain vs LangGraph vs Deep Agents – który powinieneś wybrać: kontrakty, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów stosujących ten wzorzec.
  • Notatki praktyczne: Zatem z jakim Agent SDK powinieneś tworzyć? — Szczegółowy przewodnik po Notatkach praktycznych: Zatem z jakim Agent SDK powinieneś tworzyć?, w tym informacje o kontraktach, sprawdzeniach oraz miejscach na kod do wstawienia dla zespołów implementujących ten wzorzec.