Zum Hauptinhalt springen

Konversationsgedächtnis

Definition

Konversationsgedächtnis bezeichnet die Menge an Techniken, die einem Chat-Agenten ermöglichen, Informationen aus früheren Gesprächsrunden zu behalten und zu nutzen. Im Gegensatz zur Retrieval-Augmented Generation, die externe Dokumente einbezieht, befasst sich das Konversationsgedächtnis ausschließlich damit, was bereits zwischen dem Benutzer und dem Agenten gesagt wurde. Dies richtig umzusetzen trennt einen frustrierenden Chatbot, der Sie bittet, sich zu wiederholen, von einem Agenten, der sich aufmerksam anfühlt.

Es gibt verschiedene Strategien zur Verwaltung des Gesprächsverlaufs, jede mit unterschiedlichen Abwägungen zwischen Kosten, Wiedergabetreue und Skalierbarkeit. Der einfachste Ansatz — jede Nachricht wörtlich beizubehalten — funktioniert bei kurzen Gesprächen gut, erschöpft aber schnell das Kontextfenster des Modells. Ausgefeiltere Muster verwenden Zusammenfassung oder semantische Indizierung, um den relevantesten Verlauf für den aktuellen Gesprächszug zu komprimieren oder selektiv abzurufen.

Die Wahl des richtigen Gedächtnismusters hängt stark von der erwarteten Gesprächslänge, der Bedeutung genauer Formulierungen gegenüber semantischer Bedeutung und den Kostenbeschränkungen der Bereitstellung ab. In der Praxis kombinieren produktive Chat-Agenten häufig zwei oder mehr Muster: einen kurzfristigen wörtlichen Puffer für unmittelbare Kohärenz und eine Zusammenfassungs- oder Vektorschicht für langfristiges Abrufen.

Funktionsweise

Puffergedächtnis

Puffergedächtnis ist das unkomplizierteste Muster: Der Agent führt eine geordnete Liste der letzten N Nachrichtenpaare und stellt sie jedem neuen Kontextfenster voran. Wenn der Puffer voll ist, wird das älteste Paar verworfen (FIFO). Dies garantiert, dass der Agent immer Zugang zu den jüngsten Austauschen hat, ohne Transformation oder verlustbehaftete Komprimierung. Puffergedächtnis ist ideal für kurze bis mittlere Gespräche und verursacht keine zusätzlichen LLM-Aufrufe. Der Hauptnachteil ist, dass älterer Kontext still verworfen wird, ohne eine Zusammenfassung.

Zusammenfassungsgedächtnis

Zusammenfassungsgedächtnis behebt das Vergessen-Problem, indem ein LLM periodisch eine laufende Zusammenfassung des bisherigen Gesprächs generiert. Wenn der Puffer zu groß wird, verdichtet der Agent ihn zu einer kompakten Erzählung — erfasst Schlüsselfakten, Entscheidungen und Stimmung — und verwirft dann die Rohnachrichten. Die Zusammenfassung belegt weit weniger Token als die ursprünglichen Gesprächszüge. Der Kompromiss ist ein sekundärer LLM-Aufruf für jeden Zusammenfassungsschritt, was Latenz und Kosten erhöht.

Vektorgedächtnis

Vektorgedächtnis bettet jeden Gesprächszug ein und speichert ihn in einer Vektordatenbank. Bei jedem neuen Gesprächszug werden die semantisch relevantesten vergangenen Austausche durch Ähnlichkeitssuche abgerufen und in das Kontextfenster eingefügt. Dieses Muster glänzt, wenn Gespräche sehr lang sind oder wenn die aktuelle Frage etwas betrifft, das viele Gesprächszüge zurückliegt. Vektorgedächtnis erfordert Einbettungsinfrastruktur und führt zu Abruflatenz.

Entitätsgedächtnis

Entitätsgedächtnis extrahiert benannte Entitäten — Personen, Orte, Produkte, Präferenzen — aus dem Gespräch und pflegt einen strukturierten Datensatz darüber, was der Agent über jede Entität weiß. Wenn eine Entität erneut erwähnt wird, wird ihr gespeichertes Profil in den Kontext eingefügt. Entitätsgedächtnis ist ideal für persönliche Assistenten, bei denen es wertvoller ist, sich zu erinnern, dass "Alice morgendliche Meetings bevorzugt" oder "der Projekttermin der 10. Juni ist".

Wann verwenden / Wann NICHT verwenden

Verwenden wennVermeiden wenn
Gespräche sich über mehr als ein paar Gesprächszüge erstreckenDie Aufgabe ein einzelner Gesprächszug ohne Verlaufsbedarf ist
Benutzer erwarten, dass der Agent sich an ihre früheren Aussagen erinnertGesprächsdaten aus Datenschutz- oder Compliance-Gründen nicht gespeichert werden können
Kontextfensterkosten erheblich sind und der Verlauf lang istDas Gespräch immer kurz genug ist, um vollständig ins Kontextfenster zu passen
Benutzer mehrere Entitäten oder Themen in der Sitzung besprechenZusammenfassungslatenz für den Anwendungsfall inakzeptabel ist
Sitzungsübergreifendes Abrufen erforderlich ist (Vektor-/Entitätsmuster)Die zusätzliche Infrastrukturkomplexität den Wiedergabetreue-Nutzen überwiegt

Vergleiche

KriteriumPuffergedächtnisZusammenfassungsgedächtnisVektorgedächtnis
Kosten pro GesprächszugNiedrig (kein zusätzlicher LLM-Aufruf)Mittel (gelegentlicher Zusammenfassungsaufruf)Mittel (Einbettungsaufruf + DB-Abfrage)
Wiedergabetreue des AbrufensGenau aber auf die letzten N Gesprächszüge begrenztVerlustbehaftete Komprimierung älterer GesprächszügeHoch für semantisch relevante Inhalte
KontextlängenverarbeitungSchlecht — älteste Gesprächszüge werden still verworfenGut — Zusammenfassung komprimiert alte GesprächszügeAusgezeichnet — ruft nur relevante Teile ab
LatenzMinimalMäßig (Zusammenfassung fügt einen Schritt hinzu)Mäßig (Einbettung + Nächster-Nachbar-Suche)
Sitzungsübergreifendes AbrufenNein (In-Memory-Puffer)Möglich wenn Zusammenfassung persistiert wirdJa (Vektorspeicher ist persistent)
ImplementierungskomplexitätSehr niedrigNiedrig–mittelMittel–hoch

Code-Beispiele

"""
Conversational memory patterns using LangChain.

Demonstrates:
1. ConversationBufferMemory — keep verbatim last N messages
2. ConversationSummaryMemory — compress history into a running summary
3. ConversationBufferWindowMemory — sliding window variant
"""
# pip install langchain langchain-openai openai
from langchain.memory import (
ConversationBufferMemory,
ConversationSummaryMemory,
ConversationBufferWindowMemory,
)
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI


# ---------------------------------------------------------------------------
# 1. Buffer memory — keeps ALL messages (use for short conversations)
# ---------------------------------------------------------------------------
def demo_buffer_memory():
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
memory = ConversationBufferMemory(return_messages=True)
chain = ConversationChain(llm=llm, memory=memory, verbose=False)

reply1 = chain.predict(input="My name is Alice. I enjoy hiking.")
reply2 = chain.predict(input="What outdoor activities would you recommend for me?")

# The second call has access to the first turn verbatim
print("Buffer memory — reply 2:", reply2)
print("History length:", len(memory.chat_memory.messages), "messages\n")


# ---------------------------------------------------------------------------
# 2. Summary memory — LLM compresses history on each turn
# ---------------------------------------------------------------------------
def demo_summary_memory():
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# The same LLM is used to generate summaries; you can use a cheaper model here
memory = ConversationSummaryMemory(llm=llm, return_messages=True)
chain = ConversationChain(llm=llm, memory=memory, verbose=False)

chain.predict(input="I'm planning a trip to Japan next spring.")
chain.predict(input="I'm most interested in traditional temples and local food.")
reply3 = chain.predict(input="Can you suggest a one-week itinerary?")

print("Summary memory — reply 3:", reply3)
# The buffer contains only the latest summary, not all past raw messages
print("Summary:", memory.moving_summary_buffer[:200], "...\n")


# ---------------------------------------------------------------------------
# 3. Window memory — keeps only the last k turns (sliding window)
# ---------------------------------------------------------------------------
def demo_window_memory(k: int = 3):
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# k=3 means only the last 3 HumanMessage+AIMessage pairs are retained
memory = ConversationBufferWindowMemory(k=k, return_messages=True)
chain = ConversationChain(llm=llm, memory=memory, verbose=False)

for i in range(6):
reply = chain.predict(input=f"This is message number {i + 1}.")
print(f"Turn {i + 1}: {reply[:80]}")

print(
f"\nWindow memory keeps {len(memory.chat_memory.messages)} messages "
f"(max {k * 2} for k={k} turn pairs)\n"
)


# ---------------------------------------------------------------------------
# Manual entity-style memory (illustrative, no extra dependency)
# ---------------------------------------------------------------------------
def demo_entity_memory_manual():
"""
Minimal entity memory: parse key facts from each turn and inject them.
In production, use LangChain's ConversationEntityMemory or a dedicated NER model.
"""
entity_store: dict[str, str] = {}

def extract_entities_mock(text: str) -> dict[str, str]:
"""Mock extraction — real impl would call an LLM or NER model."""
entities = {}
if "my name is" in text.lower():
name = text.lower().split("my name is")[-1].strip().split()[0].rstrip(".,")
entities["user_name"] = name.capitalize()
if "deadline" in text.lower():
entities["deadline"] = "mentioned but not parsed in this mock"
return entities

turns = [
("user", "My name is Bob and my project deadline is end of July."),
("user", "Can you help me prioritize my tasks?"),
]
for role, msg in turns:
entity_store.update(extract_entities_mock(msg))
entity_context = "; ".join(f"{k}={v}" for k, v in entity_store.items())
print(f"[{role}] {msg}")
print(f" Entity context injected: {entity_context}\n")


if __name__ == "__main__":
import os

if os.getenv("OPENAI_API_KEY"):
demo_buffer_memory()
demo_summary_memory()
demo_window_memory()
else:
print("Set OPENAI_API_KEY to run LangChain demos.")
demo_entity_memory_manual()

Praktische Ressourcen

Siehe auch