Strona główna / Artykuły / Wskazówki praktyczne: Tworzenie agenta wsparcia LEPA za pomocą LangGraph

Wskazówki praktyczne: Tworzenie agenta wsparcia LEPA za pomocą LangGraph

Krok po kroku instrukcja obsługi Notatek praktycznych: tworzenie agenta wsparcia LEPA za pomocą LangGraph – umowy, sprawdzania oraz miejsca na kod do wstawienia dla zespołów implementujących ten wzorzec.

2082 słów

Niech to służy jako wersja przeznaczona dla operatorów, zawierająca zasady przedstawione w „Tworzenie agenta wsparcia LEPA przy użyciu LangGraph”: wyraźne etapy, uporządkowane sekcje kodu oraz notatki dotyczące napraw, które przetrwają przeniesienie obowiązków. Etap Przeglądu działa najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis rozmowy, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Wolimy 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.

Czego oczekiwałeś od pierwszej grafiki

Aby skutecznie zarządzać tą fazą, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanej punktacji kontrolnej, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadkowe, częściowe ukończenie zadań. Konieczne jest ludzkie zatwierdzenie w przypadkach, gdy dochodzi do wydawania pieniędzy lub modyfikacji danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności procesu biznesowego.

User message
     ↓
Notice who is speaking (teacher / admin / unknown)
     ↓
Classify the topic (grades, login, …)
     ↓
Too vague? Ask a clarifying question
     ↓
Otherwise continue toward docs + an answer

Ustawienia projektu (celowo utrzymane w prostocie)

Aby konfiguracja projektu była celowo podzielona na etapy, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Konieczne jest ludzkie zatwierdzenie w przypadkach, gdy dochodzi do wydawania pieniędzy lub modyfikacji danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności biznesowej.

PRJ-02/
├── app/
│   ├── state.py      # SupportState
│   ├── graph.py      # StateGraph wiring
│   ├── agents/       # intake, knowledge, support
│   ├── nodes/        # classify, ask_clarification
│   └── tools/        # search_knowledge (next article)
├── knowledge/        # LEPA support Markdown
├── api/              # FastAPI (later article)
└── tests/

Stan: obiekt, który przemieszcza się po grafie

Dla stanu obiektu danego etapu należy zdefiniować dane wejściowe, osobę odpowiedzialną za ten 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. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Konieczne jest ludzkie zatwierdzenie dla operacji, które wiążą się z wydatkami lub zmianami w danych produkcyjnych. Połączenia skompilowane w czasie kompilacji nie równają się pełnej kompletności biznesowej. Dla stanu obiektu danego etapu należy zdefiniować dane wejściowe, osobę odpowiedzialną za ten 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. Należy preferować małe, testowalne jednostki nad rozbudowanymi skryptami. Gdy krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną strukturę procesów.

e.

messages                 # conversation turns (add_messages reducer)
user_role                # teacher / admin / unknown
issue_category           # grades, authentication, …
clarification_needed     # should we ask for more detail?
clarification_question   # what we ask
retrieved_documents      # doc snippets (later step)
final_answer             # what we return to the user
conversation_summary     # reserved for later — unused in v1
messages: Annotated[list, add_messages]
{"user_role": "teacher"}
{"issue_category": "grades", "clarification_needed": False}

Węzły: po jednym zadaniu na każdy

Pracując z węzłami, w których na każdym etapie jest po jednym zadaniu, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co się dzieje 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ć ciche, częściowe ukończenie zadań. Ustal punkty kontrolne po kosztownych krokach. Program powinien unikać ponownego pobierania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie wykonać późniejszy węzeł.

(state) → partial update

Odbiór danych

Gdy przechodzisz przez etap przyjmowania danych, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co się dzieje 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 proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Ustal punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.

Klasyfikacja

Gdy pracujesz nad etapem Classify, 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. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Ustaw punkty kontrolne po kosztownych krokach. Funkcja wznowienia nie powinna ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł. Gdy pracujesz nad etapem Classify, 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 nad rozbudowane skrypty. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną ścieżkę przetwarzania.

Zapytaj o wyjaśnienie

Faza wyjaśniania pytań działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię do analizy. 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 wprowadzanymi danymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj 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ł wpisał dane do którego pola, co powoduje przerwanie kontynuacji pracy po zakłóceniach.

Wiedza + wsparcie

Etap wsparcia merytorycznego funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu zmian, 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 przechodzi się 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 zakłóceniach.

Krawędzie: jak przebiega kontrola

Metoda zarządzania ruchem na etapach działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden przykład udanego działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres. 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 elementy ukrywają informację o tym, który węzeł zapisał dane w danym polu, co utrudnia kontynuację pracy po przerwach.

Zwykłe krawędzie

Faza Normal edges działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden przykład udanego działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno ścieżkę udanego działania, jak i ścieżkę przywracania do normalnego stanu. 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. Wkładki nawiasowe ukrywają informację o tym, który węzeł zapisał dane w danym polu, i powodują przerwanie kontynuacji po przerwach.

graph.add_edge(START, "intake")
graph.add_edge("intake", "classify")
graph.add_edge("knowledge", "support")
graph.add_edge("support", END)
When this node finishes, always go there next.

Krawędzie warunkowe

Faza warunkowych krawędzi działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przypadek 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. Wtórne struktury ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach.

def route_after_classify(state: SupportState) -> Literal["clarify", "continue"]:
    if state.get("clarification_needed"):
        return "clarify"
    return "continue"
graph.add_conditional_edges(
    "classify",
    route_after_classify,
    {
        "clarify": "ask_clarification",
        "continue": "knowledge",
    },
)
"help"  → clarify → ask_clarification → END
"How do I enter grades?" → continue → knowledge → support → END

START i END

Fazy START i END działają najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny przekaz, jeden przypadek awarii oraz notatkę o cofnięciu działań, zanim rozszerzysz zakres. Traktuj tę fazę 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 typowości. Wkładki nawiasowe ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji po przerwach.

START = where the runtime begins
END   = where this run stops
START → intake → classify → …
…
ask_clarification → END
support → END

Pełna topologia (taka, jaka została zbudowana)

Pełna topologia jako etap funkcjonuje najlepiej, gdy traktowana jest jako powierzchnia mierzalna. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia 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 wersji demonstracyjnej do środowisk współdzielonych. Utrzymuj stan grafu w formie prostych, spójnych struktur. Wkładki nawarstwione utrudniają określenie, który węzeł zapisał dane do którego pola, i powodują przerwę w kontynuacji pracy po zakłóceniach.

START
  → intake
  → classify
  → conditional
        ├─ clarify  → ask_clarification → END
        └─ continue → knowledge → support → END

Jak żądanie przemieszcza się po grafie

Sposób funkcjonowania etapów przetwarzania żądania działa najlepiej, gdy traktuje się je jako mierzalną strukturę. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny poufnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Utrzymuj stan struktury w prostym formacie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane w danym polu, co powoduje przerwanie kontynuacji przetwarzania po zakłóceniach.

Jasne pytanie

Faza jasnego sformułowania pytania 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 badania. Zdokumentuj zarówno prawidłowy przebieg operacji, jak i ścieżkę przywracania do normalnego stanu. 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 elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji po przerwach.

User: "Why aren't grades showing?"
        ↓
intake        → user_role = unknown (unless they said teacher/admin)
        ↓
classify      → issue_category = grades, clarification_needed = False
        ↓
route         → "continue"
        ↓
knowledge     → search docs (next article)
        ↓
support       → final_answer
        ↓
END

Niejasne pytanie

User: "help"
        ↓
intake
        ↓
classify      → unknown + clarification_needed = True
        ↓
route         → "clarify"
        ↓
ask_clarification → asks which LEPA area
        ↓
END

compile() i invoke(): moment wykonywania

return graph.compile(checkpointer=checkpointer)
from langchain_core.messages import HumanMessage
from app.graph import app_graph
result = app_graph.invoke(
    {"messages": [HumanMessage(content="How do I enter grades?")]}
)
print(result["final_answer"])

To, co celowo odłożyłeś

Wniosek

Linki

Listwa kontrolna operacyjna

Pozycje pokrewne

  • Notatki praktyczne: Workflows kontra agenci – kto powinien wybrać następny krok? — Szczegółowy przewodnik po Notatkach praktycznych: Workflows kontra agenci – kto powinien wybrać następny krok?: umowy, sprawdzenia oraz miejsca na kod do wstawić dla zespołów wdrażających ten wzorzec.
  • Notatki praktyczne: Szkolenie i adaptacja dla agentów AI korporacyjnych — Szczegółowy przewodnik po Notatkach praktycznych: Szkolenie i adaptacja dla agentów AI korporacyjnych: umowy, sprawdzenia oraz miejsca na kod do wstawić dla zespołów wdrażających ten wzorzec.
  • Notatki praktyczne: Inżynieria pętli – tworzenie samodoskonalących się agentów AI za pomocą czterech elementów — Szczegółowy przewodnik po Notatkach praktycznych: Inżynieria pętli – tworzenie samodoskonalących się agentów AI za pomocą czterech elementów: kontrakty, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.
  • Notatki praktyczne: Budowa bezpiecznego, neutralnego wobec agentów przeglądarki chmurowej — Szczegółowy przewodnik po Notatkach praktycznych: Budowa bezpiecznego, neutralnego wobec agentów przeglądarki chmurowej: kontrakty, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.
  • Notatki praktyczne: 6. Budowanie agenta czatowego z użyciem AWS Bedrock i Terraform — Krok po kroku instrukcja do Notatek praktycznych: 6. Budowanie agenta czatowego z użyciem AWS Bedrock i Terraform: kontrakty, sprawdzenia oraz gotowe fragmenty kodu dla zespołów wdrażających ten wzorzec.
  • Jak „granie w siatkówkę” z agentami AI pomogło mi przewidzieć rotację klientów w restauracji — Krok po kroku instrukcja dotycząca tematu „Jak ‘granie w siatkówkę’ z agentami AI pomogło mi przewidzieć rotację klientów w restauracji”: kontrakty, sprawdzenia oraz gotowe fragmenty kodu dla zespołów wdrażających ten wzorzec.
  • Praktyczne wskazówki: Aktualizuj swój Deep Agent za pomocą lokalnej przestrzeni sandbox o otwartym kodzie — Szczegółowy przewodnik po Praktycznych wskazówkach: Aktualizuj swój Deep Agent za pomocą lokalnej przestrzeni sandbox o otwartym kodzie: umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.