Agenci ReAct w LangGraph: Krok po kroku – myślenie, działanie, obserwacja
Zaimplementuj pętlę ReAct jako wyraźne węzły grafu z typowanym stanem, wywołaniami narzędzi oraz warunkami zatrzymania, które można przetestować.
To przewodnik odbudowuje funkcjonalną ścieżkę dla: ReAct Agents Explained: Krok po kroku – implementacja przy użyciu LangGraph. Skupia się na kontraktach, sprawdzaniach oraz kodzie, który można umieścić w repozytorium bez konieczności domyślania się intencji. Aby uzyskać ogólny obraz, 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Lepiej używać małych, testowalnych jednostek niż rozbudowanych skryptów. Gdy dany krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.
Wprowadzenie
W części wprowadzającej 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje rozwiązania; wykonawca je wdraża; sprawdzający porównuje wyniki z założonym celem.
Czym jest agent ReAct?
W rozdziale „Co to jest agent ReAct?” 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 znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Należy oddzielić planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje rozwiązania; wykonawca je modyfikuje; weryfikator sprawdza wyniki pod kątem realizacji celu.
Dlaczego ReAct jest lepszy od czystej metody Chain-of-Thought
Aby wyjaśnić, dlaczego ReAct jest lepszy od czystego podejścia Chain-of-Thought, 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 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. Należy oddzielić planowanie od wykonywania zadań za pomocą narzędzi. Planer proponuje rozwiązania; wykonawca je wdraża; sprawdzacz porównuje wyniki z założonym celem. Aby wyjaśnić, dlaczego ReAct jest lepszy od czystego podejścia Chain-of-Thought, 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, łatwe do przetestowania jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, błąd powinien wskazywać na konkretną przyczynę.
zamiast skomplikowanego łańcucha przetwarzania.Thought: I don’t know the answer yet. I should search.
Action: Search("Paris weather this week")
Observation: It will rain on Thursday.
Thought: I should suggest indoor activities.
Final Answer: ...
ReAct Prompting
W przypadku ReAct Prompting należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną fazę oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić daną fazę na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Ściśle określ schematy narzędzi. Szerokie pola tekstowe sprzyjają infekcjom i sprawiają, że audyty są kosztowne.
Cel ReAct Prompting
Dla celów ReAct Prompting 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 i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Schematy narzędzi muszą być ściśle określone – szerokie pola tekstowe umożliwiają iniekcje i sprawiają, że audyty są kosztowne.
Kluczowe elementy ReAct Prompting
Dla kluczowych elementów techniki ReAct Prompting 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 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 przeglądania całej struktury. Schematy narzędzi należy ściśle określić. Szersze argumenty tekstowe sprzyjają iniekcjom i utrudniają audyt. Dla kluczowych elementów techniki ReAct Prompting 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną ścieżkę przetwarzania.
1. Rozumowanie typu Chain-of-Thought
W przypadku rozumowania typu Chain-of-Thought należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć przypadkowe, częściowe ukończenie zadań. Utwórz punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
2. Wyraźna przestrzeń działań
Dla 2. Przestrzeni działań – określ 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. Zapisuj czas trwania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Ustaw punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
3. Integracja obserwacji
Dla punktu 3. Integracja obserwacji 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 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. Ustawiaj punkty kontrolne po kosztownych wywołaniach modeli, aby ponowne próby nie powodowały ponownego obliczania tych samych zadań. Dla punktu 3. Integracja obserwacji 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną strukturę procesów.
4. Pętle iteracyjne
Dla 4. iteracyjnego pętlenia należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną etap oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić daną etap na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje; wykonawca wprowadza zmiany; weryfikator sprawdza wyniki pod kątem osiągnięcia celu.
5. Generowanie ostatecznej odpowiedzi
Dla etapu 5. Generowanie ostatecznej odpowiedzi 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. Należy rejestrować czasy wykonywania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Należy oddzielić planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje rozwiązania; wykonawca je wdraża; sprawdzający porównuje wyniki z założonym celem.
Kanoniczna struktura promptu ReAct
Dla kanonicznej struktury promptu ReAct 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 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. Należy oddzielić planowanie od wykonywania zadań za pomocą narzędzi. Planer proponuje rozwiązania; wykonawca je wdraża; sprawdzacz porównuje wyniki z celem. Dla kanonicznej struktury promptu ReAct 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, łatwe do przetestowania jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powinno to wskazywać na konkretną przyczynę, a nie na skomplikowaną strukturę procesów.
Question: <user question>Thought: <reason about what to do next>
Action: <selected tool>
Action Input: <tool input>
Observation: <tool output>
... (repeat as needed)
Thought: I now know the final answer
Final Answer: <answer to the user>
Zero-Shot ReAct Prompting
W przypadku Zero-Shot ReAct Prompting należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną etap oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić daną etap na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadań. Ściśle określ schematy narzędzi. Szerokie pola tekstowe umożliwiają wstrzykiwanie złośliwego kodu i sprawiają, że audyty stają się kosztowne.
ReAct Prompting vs ReAct Agents
Dla podejścia ReAct Prompting w porównaniu z ReAct Agents należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną etap oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić daną etap na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Schematy narzędzi muszą być ściśle określone – szerokie pola tekstowe umożliwiają iniekcje i sprawiają, że audyty są kosztowne.
Dlaczego LangGraph do ReAct Agents?
Aby zrozumieć, dlaczego wybrać LangGraph dla agentów ReAct, należy przed zmianą kodu zdefiniować 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. Konfigurację należy przechowywać 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 przeglądania całej struktury. Schematy narzędzi należy ściśle określić. Szersze argumenty tekstowe sprzyjają iniekcjom i utrudniają audyt. Aby zrozumieć, dlaczego wybrać LangGraph dla agentów ReAct, należy przed zmianą kodu zdefiniować 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. Należy preferować małe, łatwe do przetestowania jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną sekwencję operacji.
Główny problem: ReAct to maszyna stanowa, a nie prompt
W rozdziale „Główny problem: ReAct to maszyna stanowa, a nie prompt” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie wykonać dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Ustaw punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
Co się psuje bez LangGraph
Dla przypadków, które nie działają przy użyciu LangGraph, 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 i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Ustal punkt kontrolny po drogich wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
1. Ukryty przepływ sterowania
Dla 1. Ukrytego przepływu sterowania 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 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. Ustawiaj punkty kontrolne po kosztownych wywołaniach modeli, aby ponowne próby nie powodowały ponownego naliczania tych samych zadań. Dla 1. Ukrytego przepływu sterowania 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną strukturę przepływu.
while True:
llm_output = llm(prompt)
if "Action:" in llm_output:
tool_result = call_tool(...)
else:
break
2. Kruche zarządzanie stanem
Dla punktu 2. Zarządzanie kruchym stanem: zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, 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ć ciche, częściowe ukończenie zadania. Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje; wykonawca wprowadza zmiany; weryfikator sprawdza wyniki pod kątem osiągnięcia celu.
3. Brak semantyki pętli pierwszej klasy
Dla punktu 3: Brak semantyki pętli pierwszej klasy – należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną etap oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić daną etap na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Należy oddzielić planowanie od wykonywania przez narzędzia – planer proponuje, wykonawca wprowadza zmiany, a weryfikator sprawdza wyniki pod kątem celu.
4. Niska gotowość do produkcji
Dla punktu 4. Niska gotowość do produkcji: zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Utrzymuj 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. Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje rozwiązania; wykonawca je wdraża; sprawdzający porównuje wyniki z założonym celem. Dla punktu 4. Niska gotowość do produkcji: zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Woląć małe, testowalne jednostki nad rozbudowane skrypty. Gdy dany krok zawiedzie, powinno to wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną strukturę procesów.
Kluczowe koncepcje w LangGraph (podejście skupione na agencie)
W ramach kluczowych koncepcji w LangGraph (podejście skupione na agencie) 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 znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań. Ściśle określ schematy narzędzi. Zbyt szerokie pola tekstowe sprzyjają infekcjom i utrudniają audyty.
1. Stan: Pamięć agenta
Dla stanu 1: Pamięć agenta – zdefiniuj 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. Zapisuj czas trwania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Schematy narzędzi muszą być ściśle określone – szerokie pola tekstowe sprzyjają infekcjom i sprawiają, że audyty są kosztowne.
2. Węzły: Jednostki poznawcze i operacyjne
Dla węzłów 2: Jednostek poznawczych i operacyjnych, zdefiniuj wprowadzenia, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Utrzymuj 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. Ściśle określ schematy narzędzi. Szerokie pola tekstowe sprzyjają iniekcjom i utrudniają audyty. Dla węzłów 2: Jednostek poznawczych i operacyjnych, zdefiniuj wprowadzenia, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Wolimy małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną ścieżkę przetwarzania.
3. Krawędzie: Jasny przepływ sterowania
W przypadku 3. Krawędzie: Jasny przepływ sterowania należy zdefiniować dane wejściowe, 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 tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Ustal punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
4. Wykonywanie deterministyczne z elastycznością
Dla punktu 4. Deterministyczna eksploatacja z elastycznością: określ 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. Zapisuj czas trwania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Ustal punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie generowała dodatkowych opłat za tę samą pracę.
ReAct + LangGraph: doskonałe połączenie
Dla ReAct + LangGraph: doskonałe połączenie – zdefiniuj 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. 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. Ustaw punkt kontrolny po kosztownych wywołaniach modelu, aby ponowna próba nie powodowała ponownego obliczania tych samych zadań. Dla ReAct + LangGraph: doskonałe połączenie – zdefiniuj 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. Wolno preferować małe, łatwe do przetestowania jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną sekwencję operacji.
Zastosowanie: Asystent ds. anulowania rezerwacji w hotelu (polityka + obliczanie zwrotu)
Dla zastosowania: Asystent ds. anulowania rezerwacji w hotelu (polityka + obliczanie zwrotu), należy zdefiniować dane wejściowe, osobę odpowiedzialną za daną czynność oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić tę czynność od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planista proponuje rozwiązania; wykonawca je wdraża; sprawdzający porównuje wyniki z założonym celem.
Sformułowanie problemu
W celu sformułowania problemu 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 od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy oddzielić planowanie od wykonywania narzędzi. Planista proponuje; wykonawca wprowadza zmiany; weryfikator sprawdza wyniki pod kątem osiągnięcia celu.
Krok 1: Zainstaluj zależności
Należy oddzielić planowanie od wykonywania narzędzi. Planista proponuje; wykonawca wprowadza zmiany; weryfikator sprawdza wyniki pod kątem osiągnięcia celu.
pip install -U langgraph langchain langchain-openai
export OPENAI_API_KEY="..."
Krok 2: Zdefiniuj narzędzia (twoje „Działania”)
Schematy narzędzi muszą być ściśle określone. Szersze argumenty tekstowe sprzyjają infekcjom i sprawiają, że audyty są kosztowne.
from typing import TypedDict, Annotated
from datetime import datetime
import json
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langchain_core.messages import (
BaseMessage,
HumanMessage,
ToolMessage,
SystemMessage
)
from langchain_core.tools import tool
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import tools_condition
@tool
def get_cancellation_policy(rate_plan: str) -> str:
"""
Returns cancellation policy text for a given rate plan.
"""
policies = {
"flexible": "Free cancellation until 24 hours before check-in. After that, first night is charged.",
"semi-flex": "Free cancellation until 72 hours before check-in. After that, 50% of the stay is charged.",
"non-refundable": "No refund after booking. Full stay amount is charged on cancellation."
}
key = rate_plan.strip().lower()
return policies.get(key, "Policy not found. Supported: flexible, semi-flex, non-refundable.")
@tool
def calculate_refund(
rate_plan: str,
check_in: str,
cancel_date: str,
nightly_rate: float,
nights: int
) -> str:
"""
Calculates refund amount based on a simplified policy model.
Dates format: YYYY-MM-DD
"""
rp = rate_plan.strip().lower()
ci = datetime.strptime(check_in, "%Y-%m-%d").date()
cd = datetime.strptime(cancel_date, "%Y-%m-%d").date()
total = nightly_rate * nights
days_before = (ci - cd).days
if rp == "non-refundable":
refund = 0.0
charged = total
rule = "Non-refundable: no refund."
elif rp == "flexible":
if days_before >= 1:
refund = total
charged = 0.0
rule = "Flexible: cancelled >= 24h before check-in, full refund."
else:
charged = nightly_rate # 1 night penalty
refund = max(total - charged, 0.0)
rule = "Flexible: late cancel, 1 night charged."
elif rp == "semi-flex":
if days_before >= 3:
refund = total
charged = 0.0
rule = "Semi-flex: cancelled >= 72h before check-in, full refund."
else:
charged = 0.5 * total
refund = total - charged
rule = "Semi-flex: late cancel, 50% charged."
else:
return "Unsupported rate plan. Use: flexible, semi-flex, non-refundable."
return (
f"Rule: {rule}\n"
f"Days before check-in: {days_before}\n"
f"Total: ${total:.2f}\n"
f"Charged: ${charged:.2f}\n"
f"Refund: ${refund:.2f}"
)
Krok 3: Stwórz pętlę ReAct w LangGraph (Rozumowanie → Narzędzie → Rozumowanie)
Schematy narzędzi muszą być ściśle określone. Szersze argumenty tekstowe sprzyjają infekcjom i sprawiają, że audyty są kosztowne.
from typing import TypedDict, Annotated
from langchain_core.messages import BaseMessage, HumanMessage
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from langchain_core.tools import Tool
from langgraph.prebuilt import ToolNode, tools_condition
# 1) Define state
class AgentState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
booking_id: str
# 2) Define structured Output schema
class RefundDecision(BaseModel):
booking_id: str
rate_plan: str
total_amount: float
charged_amount: float
refund_amount: float
policy_summary: str
explanation: str
# 2) Choose model and System prompt
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
SYSTEM_PROMPT = SystemMessage(
content="""
You are a hotel cancellation assistant.
Rules:
- Use tools when needed.
- Never guess policy or refund.
- Final answer MUST be valid JSON with this schema:
{
"booking_id": "...",
"rate_plan": "...",
"total_amount": number,
"charged_amount": number,
"refund_amount": number,
"policy_summary": "...",
"explanation": "..."
}
"""
)
# 3) Register tools
tools = [get_cancellation_policy, calculate_refund]
def safe_tool_node(state):
last_msg = state["messages"][-1]
if not hasattr(last_msg, "tool_calls") or not last_msg.tool_calls:
return {}
tool_call = last_msg.tool_calls[0]
tool_name = tool_call["name"]
if tool_name not in ALLOWED_TOOLS:
return {
"messages": [
ToolMessage(
content=f"Tool '{tool_name}' is not allowed.",
tool_call_id=tool_call["id"]
)
]
}
for tool in tools:
if tool.name == tool_name:
result = tool.invoke(tool_call["args"])
return {
"messages": [
ToolMessage(
content=result,
tool_call_id=tool_call["id"]
)
]
}
# 4)Before reasoning, check if we already processed this booking.
REFUND_MEMORY = {}
def memory_lookup_node(state):
booking_id = state["booking_id"]
if booking_id in REFUND_MEMORY:
return {
"messages": [
HumanMessage(
content=f"Cached decision found:\n{REFUND_MEMORY[booking_id]}"
)
]
}
return {}
# 5) Reasoning node: LLM decides next action (tool call) or final answer
def agent_node(state: AgentState):
# Bind tools so the model can produce tool calls
llm_with_tools = llm.bind_tools(tools)
response = llm_with_tools.invoke(state["messages"])
return {"messages": [response]}
# 6) After final decision, store it.
def memory_write_node(state):
booking_id = state["booking_id"]
final_answer = state["messages"][-1].content
REFUND_MEMORY[booking_id] = final_answer
return {}
Budowanie i kompilacja grafu
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
# 7) Build the graph
builder = StateGraph(AgentState)
# Nodes
builder.add_node("memory_lookup", memory_lookup_node)
builder.add_node("agent", agent_node)
builder.add_node("tools", safe_tool_node)
builder.add_node("memory_write", memory_write_node)
# Flow
builder.add_edge(START, "memory_lookup")
builder.add_edge("memory_lookup", "agent")
builder.add_conditional_edges(
"agent",
tools_condition,
{
"tools": "tools", # model wants to act
END: "memory_write" # model finished reasoning
}
)
builder.add_edge("tools", "agent")
builder.add_edge("memory_write", END)
graph = builder.compile()
Krok 4: Uruchomienie agenta w konkretnym przypadku użycia
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
query = """
Booking details:
Rate plan: Non-Refundable
Check-in: 2026-01-20
Nights: 2
Nightly rate: 120
Cancelled on: 2026-01-18
"""
result = graph.invoke({
"booking_id": "BKG-12345",
"messages": [
SYSTEM_PROMPT,
HumanMessage(content=query)
]
})
final_output = result["messages"][-1].content
print(final_output)
Wynik
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
{
"booking_id": "BKG-12345",
"rate_plan": "Non-Refundable",
"total_amount": 240.0,
"charged_amount": 240.0,
"refund_amount": 0.0,
"policy_summary": "Non-refundable bookings do not allow refunds after confirmation.",
"explanation": "The booking was made under a non-refundable rate plan, which charges the full stay amount regardless of cancellation timing."
}
Co dzieje się wewnątrz (behawior ReAct)
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
1) Myśl (Uzasadnienie)
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
2) Działanie (wezwanie narzędzia)
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe zachęcają do iniekcji i sprawiają, że audyty są kosztowne.
3) Obserwacja (wyniki narzędzi)
Punkt kontrolny po drogich wywołaniach modelu, aby ponowna próba nie obciążała kosztami tej samej pracy.
4) Odpowiedź końcowa
Punkt kontrolny po drogich wywołaniach modelu, aby ponowna próba nie obciążała kosztami tej samej pracy.
Dlaczego to jest „ReAct” (a nie tylko narzędzia)
Punkt kontrolny po drogich wywołaniach modelu, aby ponowna próba nie obciążała kosztami tej samej pracy.
Wniosek
Rozdziel planowanie od wykonywania zadań za pomocą narzędzi. Planer proponuje; wykonawca wprowadza zmiany; weryfikator sprawdza wyniki pod kątem celu.
Lista kontrolna operacyjna
Schematy narzędzi muszą być ściśle określone. Szerokie argumenty tekstowe sprzyjają infekcjom i utrudniają audyty.
Krawędzie warunkowe powinny kodować zasady biznesowe jako nazwane funkcje, a nie jako ukryty tekst instrukcji.
Rodzaje danych powinny być umieszczane obok komponentów, a ich właściwości powinny być ograniczone. Zbyt liczne właściwości stanowią dług, którego TypeScript ma zapobiegać.
Napisz krótki przewodnik: jak rotować klucze, jak opróżnić kolejkę, jak cofnąć ostatnią zmianę.