Strona główna
» Domeny
»
Jak naprawić utratę pamięci agenta LangChain w długich rozmowach
Jak naprawić utratę pamięci agenta LangChain w długich rozmowach
Jeśli agent LangChain zapomina szczegółów podczas długiej rozmowy, napraw architekturę, zanim zwiększysz okno kontekstowe modelu. W obecnych agentach w stylu LangChain v1 ciągłość rozmowy opiera się na dwóch oddzielnych warstwach: checkpoint dla krótkoterminowego stanu w obrębie wątku oraz magazyn danych (store) dla długoterminowych informacji, które muszą przetrwać między wątkami. Długie rozmowy wymagają trzeciego elementu: zarządzania kontekstem, zwykle polegającego na przycinaniu lub streszczaniu starszych wiadomości, zanim przytłoczą model.
Ten przewodnik opiera się na oficjalnej dokumentacji LangChain sprawdzonej 11 września 2026 r. Obecna dokumentacja zaleca użycie langchain.agents.create_agent dla nowych agentów i opisuje trwałość LangGraph jako podstawowy system pamięci. Starsze przykłady oparte na ConversationChain, ConversationBufferMemory lub initialize_agent mogą nadal pojawiać się w materiałach archiwalnych, ale przewodnik migracji LangChain v1 przeniósł starsze łańcuchy i inne przestarzałe funkcje do pakietu langchain-classic. Zobacz oficjalny przewodnik migracji LangChain v1.
Ilustracja wygenerowana przez AI: Objaw jest prosty: fakt został podany wcześniej, ale późniejsza odpowiedź go nie uwzględnia. Ilustracja ma charakter koncepcyjny, nie jest zrzutem interfejsu LangChain.
Co naprawdę oznacza „utrata pamięci” w LangChain
Zanim zaczniesz zmieniać kod, oddziel trzy problemy, które z punktu widzenia użytkownika często wyglądają identycznie.
Objaw
Prawdopodobna przyczyna
Właściwa warstwa do naprawy
Agent zapomina po restarcie serwera
Stan był przechowywany tylko w pamięci procesu
Trwały checkpoint lub magazyn danych
Agent zapomina między dwoma żądaniami w tej samej rozmowie
Brak checkpointa lub użycie innego thread_id
Trwałość wątku
Agent pamięta wczesne tury w pamięci masowej, ale przestaje z nich korzystać w bardzo długich rozmowach
Kontekst modelu stał się zbyt duży lub zbyt zaszumiony
Streszczanie, przycinanie, wyszukiwanie
Agent pamięta preferencję w jednej rozmowie, ale nie w nowej
Fakt istnieje tylko w stanie wątku
Magazyn długoterminowy
Dokumentacja krótkoterminowej pamięci LangChain definiuje pamięć krótkoterminową jako stan w ramach jednego wątku. Jej dokumentacja długoterminowej pamięci definiuje pamięć długoterminową jako informacje, które przetrwają między różnymi rozmowami i sesjami.
Ilustracja wygenerowana przez AI: Pomyśl o pamięci krótkoterminowej jako o stanie jednego wątku rozmowy. Obecny LangChain realizuje tę ciągłość za pomocą checkpointa, a nie starszych klas pamięci często pokazywanych w starszych tutorialach.
Czego potrzebujesz przed rozpoczęciem
Potrzebujesz aktualnej aplikacji LangChain/LangGraph, integracji z modelem oraz miejsca do przechowywania stanu. Do lokalnych eksperymentów wystarczy InMemorySaver. W środowisku produkcyjnym użyj checkpointa opartego na bazie danych. Oficjalna dokumentacja LangChain pokazuje PostgreSQL za pośrednictwem osobnego pakietu langgraph-checkpoint-postgres.
Zachowaj jasność co do czterech identyfikatorów:
ID rozmowy lub czatu: identyfikator, który Twoja aplikacja udostępnia użytkownikom.
thread_id: klucz trwałości LangGraph używany do wznawiania stanu jednego wątku.
ID użytkownika: trwała tożsamość używana do nazewnictwa pamięci długoterminowych.
Klucz pamięci: klucz dla jednego trwałego elementu w przestrzeni nazw magazynu danych.
Nie powinny one automatycznie mieć tej samej wartości. Jeden użytkownik może mieć wiele wątków, a jeden wątek może zawierać wiele faktów.
Krok 1: Odtwórz błąd za pomocą testu dwóch żądań
Zacznij od jak najmniejszego testu. Poproś agenta o zapamiętanie unikalnego szczegółu, a następnie wywołaj go ponownie i zapytaj o ten szczegół. Nie testuj pamięci za pomocą pojedynczego wywołania invoke(), ponieważ model widzi wszystko w tym jednym żądaniu, nawet gdy trwałość jest uszkodzona.
config = {"configurable": {"thread_id": "debug-thread-001"}}
agent.invoke(
{"messages": [{"role": "user", "content": "Remember that my project codename is Juniper."}]},
config,
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is my project codename?"}]},
config,
)
Jeśli drugie żądanie zapomni „Juniper”, sprawdź konfigurację checkpointa i faktyczny thread_id, zanim zaczniesz zmieniać prompty.
Krok 2: Dodaj checkpoint dla pamięci w obrębie tego samego wątku
Checkpoint przechowuje migawki stanu grafu agenta. LangGraph używa go do pamięci krótkoterminowej, odzyskiwania po przerwaniu, przepływów z udziałem człowieka (human-in-the-loop) i tolerancji błędów. Obecny przewodnik po trwałości opisuje checkpointy jako ograniczone do wątku i stwierdza, że aplikacja uzyskuje dostęp do stanu, przekazując thread_id. Zobacz oficjalny przewodnik po trwałości LangGraph.
InMemorySaver jest doskonały do potwierdzenia, że połączenie wątku działa, ale przechowuje checkpointy w pamięci RAM. LangGraph wyraźnie ostrzega, że MemorySaver/InMemorySaver nie zachowują danych po restarcie procesu.
Krok 3: Utrzymuj ten sam thread_id dla tej samej rozmowy
Najczęstszym błędem na poziomie aplikacji jest tworzenie nowego thread_id przy każdym żądaniu HTTP. Baza danych może działać idealnie, podczas gdy każde żądanie rozpoczyna inny wątek LangGraph.
Na przykład, jeśli Twój frontend ma ID czatu chat_8bf4. Mapuj tę wartość deterministycznie na wątek LangGraph i używaj jej ponownie dla każdej tury w tej rozmowie. Nowa rozmowa powinna otrzymać nowy identyfikator wątku.
Ilustracja wygenerowana przez AI: Trwałość nie usuwa limitu okna kontekstowego modelu. Stabilny wątek może zawierać więcej historii, niż model powinien otrzymywać przy każdym wywołaniu.
Nie używaj jednego stałego thread_id dla wszystkich rozmów należących do tego samego użytkownika. To scalenie niepowiązanych rozmów w jeden strumień stanu. Jeśli używasz PostgreSQL, obecne wskazówki dotyczące rozwiązywania problemów w LangGraph mówią również, że thread_id powinien mieć mniej niż 255 znaków; UUID lub deterministyczny skrót (hash) jest bezpieczniejszy niż ogromny serializowany obiekt.
Krok 4: Zastąp pamięć w pamięci RAM przed wdrożeniem produkcyjnym
Gdy test dwóch żądań przejdzie pomyślnie, przetestuj restart procesu. Zapisz fakt, zatrzymaj aplikację, uruchom ją ponownie, a następnie zapytaj o fakt z tym samym identyfikatorem wątku. Jeśli nadal używasz InMemorySaver, zapomnienie jest zachowaniem oczekiwanym.
Oficjalna dokumentacja pamięci krótkoterminowej pokazuje konfigurację produkcyjną opartą na PostgreSQL z użyciem PostgresSaver:
from langchain.agents import create_agent
from langgraph.checkpoint.postgres import PostgresSaver
DB_URI = "postgresql://user:password@db-host/app"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup()
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
)
Aby skonfigurować pakiet zgodnie z obecną dokumentacją LangChain, zobacz Pamięć krótkoterminowa. Nie umieszczaj prawdziwych danych uwierzytelniających do bazy danych bezpośrednio w kodzie źródłowym; użyj zwykłego systemu zarządzania sekretami.
Ilustracja wygenerowana przez AI: Jednym szczególnie ważnym punktem jest pamięć lokalna dla procesu: checkpoint w pamięci RAM jest celowo tracony po restarcie, więc testy restartu należą do zestawu testów pamięci.
Krok 5: Zarządzaj długimi historiami zamiast wysyłać wszystko na zawsze
Okno kontekstowe to ilość kontekstu wejściowego i wyjściowego, którą model może obsłużyć w jednym wywołaniu modelu. Checkpointing może zachować bardzo długą rozmowę w pamięci masowej, ale nie oznacza to, że każda historyczna wiadomość powinna być wysyłana do modelu na zawsze.
Przewodnik po pamięci krótkoterminowej LangChain mówi, że długie historie mogą przekroczyć okno kontekstowe modelu i że nawet modele zdolne do przyjęcia pełnej historii mogą być rozpraszane przez nieaktualne lub nie na temat treści, co wiąże się z wyższym opóźnieniem i kosztem. Udokumentowane strategie to przycinanie, usuwanie, streszczanie lub stosowanie niestandardowej polityki.
Używaj streszczania, gdy stare szczegóły nadal mają znaczenie
SummarizationMiddleware to obecna wbudowana opcja zastępowania starszej historii zwięzłym podsumowaniem przy zachowaniu najnowszych wiadomości. Jego wyzwalacz może opierać się na liczbie tokenów, liczbie wiadomości lub ułamku kontekstu modelu.
Powyższe liczby są przykładem polityki, a nie uniwersalnymi ustawieniami. Wybierz progi po zmierzeniu własnych promptów, wyników narzędzi, limitów kontekstu modelu, opóźnień i jakości podsumowań. Zobacz dokumentację wbudowanego middleware LangChain, aby poznać obecnie obsługiwane opcje wyzwalacza i zachowania.
Ilustracja wygenerowana przez AI: Testuj przywoływanie po wystarczającej liczbie tur, aby aktywować politykę przycinania lub streszczania; krótka rozmowa może ukryć błędy związane z długim kontekstem.
Nie przycinaj wiadomości narzędziowych bezrefleksyjnie
Jeśli implementujesz niestandardowe usuwanie lub przycinanie, zachowaj poprawną sekwencję wiadomości. LangChain ostrzega, że wielu dostawców wymaga, aby wiadomość asystenta zawierająca wywołania narzędzi była następowana przez odpowiadające jej wiadomości z wynikami narzędzi. Usunięcie jednej połowy tej pary może spowodować błędy dostawcy lub dezorientujące zachowanie modelu.
Krok 6: Przenieś trwałe fakty do magazynu długoterminowego
Magazyn danych (store) to warstwa trwałości LangGraph dla danych zdefiniowanych przez aplikację poza stanem grafu jednego wątku. Obecna dokumentacja LangChain używa magazynów do informacji, które powinny być dostępne między rozmowami, takich jak preferencje użytkownika, fakty lub wspólna wiedza aplikacji.
Elementy magazynu długoterminowego to dokumenty JSON zorganizowane według przestrzeni nazw i klucza. Praktyczna przestrzeń nazw często zawiera identyfikator użytkownika lub organizacji:
Różni się to od zapisywania całej transkrypcji. Przechowuj informacje, które Twój produkt celowo traktuje jako trwałe. Jeśli fakt jest prywatny lub regulowany, zastosuj zwykłe polityki retencji, autoryzacji, szyfrowania i usuwania, zamiast zakładać, że „pamięć agenta” jest z nich wyłączona.
Ilustracja wygenerowana przez AI: Ta ilustracja używa szerokich etykiet koncepcyjnych, a nie dosłownych obecnych nazw API. Dla nowego kodu LangChain v1 użyj rozróżnienia checkpoint/magazyn opisanych w tekście i oficjalnej dokumentacji.
Używaj magazynu opartego na bazie danych w środowisku produkcyjnym
Oficjalny przewodnik po pamięci długoterminowej pokazuje zarówno InMemoryStore, jak i PostgresStore, i wyraźnie zauważa, że implementacja w pamięci RAM powinna zostać zastąpiona magazynem opartym na bazie danych w środowisku produkcyjnym. Wymienia również integracje magazynów poza PostgreSQL. Użyj backendu, który pasuje do wdrożenia i wymagań operacyjnych, zamiast wybierać bazę wektorową tylko dlatego, że w grę wchodzi słowo „pamięć”.
Dodaj wyszukiwanie semantyczne tylko wtedy, gdy potrzebujesz przywoływania nieprecyzyjnego
Magazyny LangGraph mogą być skonfigurowane z indeksem, aby store.search() mogło pobierać elementy według podobieństwa semantycznego. Jest to przydatne, gdy masz wiele pamięci i nie znasz dokładnego klucza. Dla małego zestawu ustrukturyzowanych preferencji bezpośrednie wyszukiwanie przestrzeni nazw/klucza jest często prostsze i bardziej deterministyczne.
Krok 7: Uczyń ścieżki odczytu i zapisu pamięci jawnymi
Zapisanie elementu długoterminowego nie gwarantuje, że agent go użyje. Aplikacja nadal potrzebuje ścieżki wyszukiwania. Obecne agenty LangChain pozwalają narzędziom uzyskiwać dostęp do dostarczonego magazynu przez ToolRuntime.
from dataclasses import dataclass
from langchain.tools import tool, ToolRuntime
@dataclass
class Context:
user_id: str
@tool
def get_response_style(runtime: ToolRuntime[Context]) -> str:
store = runtime.store
if store is None:
return "No memory store configured"
namespace = ("users", runtime.context.user_id, "preferences")
item = store.get(namespace, "response_style")
return item.value["value"] if item else "default"
Możesz również budować dynamiczne prompty lub middleware, które odczytują stan i trwałą pamięć przed wywołaniem modelu. Ważną zasadą projektową jest to, że ścieżka wyszukiwania powinna być obserwowalna i testowalna. „Informacja istnieje gdzieś w bazie danych” to za mało.
Ilustracja wygenerowana przez AI: Przydatny test regresji prosi o wcześniejszy fakt po wielu turach i weryfikuje, że odpowiedź pochodzi z zamierzonej warstwy pamięci, a nie z przypadkowo zduplikowanego tekstu promptu.
Krok 8: Testuj cztery granice pamięci osobno
Niezawodny zestaw testów pamięci powinien obejmować więcej niż „model zapamiętał moje imię raz”. Użyj co najmniej tych czterech przypadków:
Test
Oczekiwany wynik
Dwa wywołania, ten sam identyfikator wątku
Informacje w obrębie wątku są dostępne
Dwa wywołania, różne identyfikatory wątków
Krótkoterminowa historia wątku nie przecieka
Restart aplikacji, ten sam identyfikator wątku z trwałym checkpointem
Stan wątku może zostać wznowiony
Nowy wątek, ten sam użytkownik z magazynem długoterminowym
Tylko celowo zapisane trwałe fakty mogą zostać przywołane
Następnie dodaj test długiej rozmowy, który przekracza próg streszczania. Upewnij się, że ważne trwałe fakty przetrwają, ostatnie sekwencje wywołań narzędzi pozostaną ważne, a rozmiar promptu mieści się w docelowym budżecie.
Ilustracja wygenerowana przez AI: Traktuj to jako koncepcyjną listę kontrolną QA. Architektura LangChain v1 powinna być walidowana względem oficjalnych API checkpointa, magazynu i middleware, a nie przykładów starszych klas pamięci.
Minimalna architektura produkcyjna
Dla wielu aplikacji agentowych solidna konstrukcja wygląda następująco:
API otrzymuje user_id, conversation_id i nową wiadomość użytkownika.
Aplikacja mapuje conversation_id na stabilny thread_id LangGraph.
Trwały checkpoint przywraca stan wątku.
Magazyn długoterminowy pobiera tylko trwałe fakty użytkownika lub aplikacji potrzebne do żądania.
Streszczanie lub przycinanie utrzymuje historię widoczną dla modelu w zmierzonym budżecie kontekstu.
Agent uruchamia narzędzia i model.
Checkpoint zatwierdza zaktualizowany stan wątku.
Tylko zatwierdzone fakty są zapisywane w magazynie długoterminowym.
Jeśli wdrażasz przez LangGraph Agent Server, obecny przewodnik po trwałości mówi, że serwer automatycznie obsługuje infrastrukturę trwałości, więc nie duplikuj tej warstwy bez sprawdzenia modelu wdrożenia.
Częste błędy sprawiające, że pamięć wydaje się uszkodzona
Generowanie nowego thread_id dla każdego żądania
Tworzy to nowy stan rozmowy przy każdej turze. Loguj identyfikator wątku obok identyfikatora czatu aplikacji i weryfikuj ponowne użycie.
Używanie InMemorySaver w usłudze wieloprocesowej lub restartowalnej
Stan lokalny w RAM znika wraz z procesem i może nie być współdzielony między workerami. Użyj trwałego backendu dla ciągłości produkcyjnej.
Zakładanie, że checkpoint rozwiązuje problem okna kontekstowego
Checkpoint zachowuje stan; nie gwarantuje, że nieustannie rosnąca transkrypcja jest użyteczna dla modelu. Dodaj jawną politykę zarządzania kontekstem.
Wkładanie każdego historycznego faktu do promptu
Więcej kontekstu nie oznacza automatycznie lepszego kontekstu. Pobieraj informacje istotne dla bieżącej tury i osobno zachowaj ciągłość niedawnej rozmowy.
Traktowanie podsumowań jako idealnej bazy danych
Podsumowania to skompresowane reprezentacje generowane przez model. Jeśli fakt musi być dokładny – identyfikator konta, ograniczenie kontraktowe, preferencja zatwierdzona przez użytkownika lub stan przepływu pracy – przechowuj go jako dane ustrukturyzowane, zamiast liczyć na to, że przetrwa wielokrotne streszczanie.
Mieszanie zakresów krótkoterminowych i długoterminowych
Historia wątku nie powinna po cichu stawać się globalnym profilem użytkownika. Odwrotnie, preferencja użytkownika mająca towarzyszyć mu między rozmowami nie powinna żyć tylko w jednym wątku.
Kopiowanie tutoriali pamięci sprzed v1 bez sprawdzania importów
Jeśli przykład zaczyna się od starszych łańcuchów lub starych klas pamięci, porównaj go z obecną migracją v1 i dokumentacją pamięci przed użyciem w nowej aplikacji.
Lista kontrolna debugowania
Potwierdź, że agent został utworzony z checkpointem.
Loguj i porównuj thread_id między kolejnymi żądaniami.
Sprawdź przechowywany stan wątku, zanim obwinisz model.
Uruchom ponownie proces i powtórz ten sam test wątku.
Zastąp InMemorySaver trwałym checkpointem dla środowiska produkcyjnego.
Mierz wzrost liczby wiadomości/tokenów w długich rozmowach.
Włącz streszczanie lub przycinanie, zanim historia stanie się nadmierna.
Utrzymuj sekwencje wywołań/wyników narzędzi ważne podczas usuwania wiadomości.
Przenieś fakty między wątkami do nazwanego magazynu długoterminowego.
Przetestuj nowy wątek dla tego samego użytkownika, aby zweryfikować celowe przywoływanie długoterminowe.
Przetestuj innego użytkownika, aby zweryfikować izolację pamięci.
Śledź, które elementy pamięci zostały pobrane dla każdej odpowiedzi.
Podsumowanie
Utrata pamięci agenta LangChain rzadko jest rozwiązywana przez jedno większe okno kontekstowe. Najpierw uczyń stan wątku trwałym za pomocą checkpointa i stabilnego thread_id. Następnie kontroluj długie historie za pomocą przycinania lub SummarizationMiddleware. Na końcu umieść fakty, które muszą przetrwać między rozmowami, w nazwanym magazynie długoterminowym i celowo je pobieraj.
To rozdzielenie daje Ci coś znacznie bardziej użytecznego niż „pamięć”: system, który możesz restartować, skalować, testować, audytować i analizować, gdy użytkownik pyta: „Dlaczego agent zapomniał?”