Hallo, Agent-in-Training! Emma hier, zurück von einer weiteren nächtlichen Erkundung der faszinierenden Welt der KI-Agenten. Du weißt schon, die Art von Nacht, in der du mit einer einfachen Frage beginnst und plötzlich ist es 3 Uhr morgens, und du hast ein halbgares Python-Skript und eine neue Obsession?
So sieht mein Leben in letzter Zeit aus, und das liegt alles an etwas, das auf den ersten Blick etwas trocken klingt: Gedächtnis in KI-Agenten.
Jetzt, bevor deine Augen glasig werden, lass mich dir sagen, warum das absolut entscheidend ist, besonders für uns Anfänger, die versuchen, etwas Nützliches zu bauen. Wir haben alle mit Chatbots gespielt, oder? Du fragst ihn etwas, er antwortet. Dann stellst du eine Folgefrage, und manchmal erinnert er sich an den vorherigen Kontext, und manchmal… ist es, als würdest du mit einem Goldfisch reden. Dieser „Erinnerungs“-Teil? Das ist Gedächtnis, und es ist der Unterschied zwischen einer frustrierenden Interaktion und einem Agenten, der wirklich intelligent und hilfreich wirkt.
Heute möchte ich darüber sprechen, wie wir als Anfänger Agenten bauen können, die tatsächlich Dinge erinnern, wobei wir uns auf einen super praktischen Ansatz konzentrieren: die Verwendung einer einfachen Textdatei für „kurzfristiges“ Gedächtnis und einen grundlegenden Vektorstore für „langfristiges“ Wissen. Es geht hier nicht darum, einen multimodalen, sich selbst verbessernden Super-Agenten zu bauen (noch nicht!), sondern darum, mit den Grundlagen zu experimentieren, die diese komplexen Systeme möglich machen. Denk daran, als würde man deinem Agenten beibringen, ein Tagebuch und eine Referenzbibliothek zu führen.
Warum Gedächtnis wichtig ist (über das „Nicht Vergessen“ hinaus)
Seien wir ehrlich. Ein KI-Agent, der nach jeder Interaktion alles vergisst, ist nicht wirklich ein Agent. Er ist eher wie ein sehr schneller Rechner. Aber wenn ein Agent sich an frühere Gespräche, Fakten, die er gelernt hat, oder Aktionen, die er durchgeführt hat, erinnern kann, verwandelt er sich plötzlich. Er kann:
- Kontext beibehalten: Das ist riesig für natürliche Gespräche. „Was ist mit dem?“ macht Sinn, wenn der Agent sich an „das“ erinnert.
- lernen und sich anpassen: Wenn ein Agent Vorlieben oder frühere Misserfolge erinnert, kann er sein Verhalten anpassen.
- mehrstufige Aufgaben durchführen: Denk daran, eine Reise zu buchen. Der Agent muss sich an dein Ziel, deine Daten und deine Vorlieben über mehrere Runden hinweg erinnern.
- Interaktionen personalisieren: Sich an den Namen eines Benutzers oder frühere Fragen zu erinnern, macht die Erfahrung viel reibungsloser.
Mein eigener „Aha!“-Moment damit kam, als ich versuchte, einen einfachen Agenten zu bauen, der mir bei der Planung meiner wöchentlichen Mahlzeiten hilft. Zunächst hatte ich ihn einfach Rezepte basierend auf den Zutaten vorschlagen lassen, die ich ihm gesagt hatte. Aber jedes Mal, wenn ich einen Vorschlag verfeinern oder eine diätetische Einschränkung erwähnen wollte, musste ich mich wiederholen. Das war frustrierend! Es war, als hätte ich ein Gespräch mit jemandem, der nach jedem Satz sofort Amnesie hatte. Da wurde mir klar: dieses Ding braucht ein Gehirn, auch wenn es nur ein kleines ist.
Kurzzeitgedächtnis: Der Scratchpad-Ansatz
Für uns Anfänger ist der einfachste Weg, einem Agenten „kurzfristiges“ Gedächtnis zu geben – das, welches den unmittelbaren Gesprächskontext erinnert – überraschend einfach: eine Textdatei. Oder, wenn du dich fancy fühlst, eine Liste im Speicher, die gelegentlich in eine Datei geschrieben wird. Das ist, als würde dein Agent ein laufendes Notizblatt des aktuellen Gesprächs führen.
Wie ich es mache: Eine einfache Protokolldatei
Mein Mahlzeitenplaner-Agent musste sich merken, worüber wir gerade gesprochen haben. Habe ich gerade nach Hähnchenrezepten gefragt? Habe ich gerade gesagt, dass ich keinen Brokkoli mag? Dafür habe ich ein sehr einfaches Protokollierungssystem implementiert. Jedes Benutzereingabe und jede Agentenausgabe wird an eine Textdatei angehängt. Wenn der Agent antworten muss, kann er die letzten paar Zeilen dieser Datei lesen, um den Kontext zu erhalten.
Hier ist ein super einfaches Python-Beispiel, wie du das möglicherweise verwalten könntest. Stell dir vor, die Hauptlogik deines Agenten ruft eine Funktion auf, um die Gesprächshistorie zu „speichern“ und „abzurufen“.
# conversation_manager.py
CONVERSATION_LOG_FILE = "agent_conversation_log.txt"
MAX_SHORT_TERM_MEMORY_LINES = 10 # Nur die letzten 10 Wendungen merken
def add_to_short_term_memory(speaker, message):
"""Fügt eine Nachricht zum Gesprächsprotokoll hinzu."""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(CONVERSATION_LOG_FILE, "a") as f:
f.write(f"[{timestamp}] {speaker}: {message}\n")
def get_short_term_memory():
"""Liest die letzten Zeilen des Gesprächsprotokolls."""
try:
with open(CONVERSATION_LOG_FILE, "r") as f:
lines = f.readlines()
# Gib nur die aktuellsten Zeilen zurück
return "".join(lines[-MAX_SHORT_TERM_MEMORY_LINES:])
except FileNotFoundError:
return ""
# Beispielverwendung innerhalb der Schleife deines Agenten:
# user_input = input("Du: ")
# add_to_short_term_memory("Benutzer", user_input)
# current_context = get_short_term_memory()
# agent_response = your_llm_call(prompt=f"{current_context}\nBenutzer: {user_input}\nAgent:")
# add_to_short_term_memory("Agent", agent_response)
# print(f"Agent: {agent_response}")
Dieser Ansatz ist extrem einfach, und das ist seine Schönheit für Anfänger. Du fütterst wortwörtlich die letzten paar Teile deines Gesprächs zurück an dein Sprachmodell (LLM) als Teil des Prompts. Es ist wie dein Freund zu erinnern, „Hey, erinnerst du dich, dass wir gestern über diesen Film gesprochen haben? Nun, ich habe ihn gesehen, und…“ Das LLM verwendet dann diesen Kontext, um eine relevantere Antwort zu generieren.
Emmas Tipp: Versuche nicht, die gesamte Gesprächshistorie an das LLM zurückzugeben, wenn sie zu lang wird! LLMs haben „Kontextfenster“, was die maximale Menge an Text ist, die sie auf einmal verarbeiten können. Für Anfänger ist es sinnvoll, sich auf die letzten 5-10 Wendungen zu beschränken, um die Dinge überschaubar und kosteneffektiv zu halten.
Langzeitgedächtnis: Die Grundlagen des Vektorstores
Okay, unser Agent kann sich an die letzten paar Dinge erinnern, die wir gesagt haben. Großartig! Aber was, wenn ich meinem Mahlzeitenplaner-Agenten letzte Woche gesagt habe, dass ich allergisch gegen Erdnüsse bin? Oder dass ich montags vegetarische Gerichte bevorzuge? Solche Informationen müssen über ein einzelnes Gespräch hinaus bestehen bleiben und zugänglich sein, wenn sie relevant sind, nicht nur wenn sie kürzlich erwähnt wurden. Hier kommt das „langfristige“ Gedächtnis ins Spiel, und für uns bedeutet das einen grundlegenden Vektorstore.
Was ist ein Vektorstore? (Vereinfacht für Anfänger)
Stell dir vor, du hast eine riesige Bibliothek mit Büchern. Wenn du Bücher über „Weltraumreisen“ finden willst, könntest du manuell jeden Buchtitel durchsehen, aber das würde ewig dauern. Stattdessen würdest du wahrscheinlich zum Bereich Science-Fiction gehen und dann nach Schlüsselwörtern suchen. Ein Vektorstore ist wie ein super mächtiger, blitzschneller Bibliothekar für Informationen, die in Zahlen umgewandelt wurden.
Hier ist die vereinfachte Idee:
- Embeddings: Du nimmst einen Text (z. B. „Ich bin allergisch gegen Erdnüsse“) und wandelst ihn in eine Liste von Zahlen um. Diese Liste von Zahlen wird als „Embedding“ bezeichnet. Entscheidend ist, dass Texte mit ähnlicher Bedeutung Embeddings haben, die in diesem Zahlenraum „nahe“ beieinander liegen.
- Speicherung: Du speicherst diese Embeddings (und den Originaltext) in einer speziellen Datenbank, die ein Vektorstore genannt wird.
- Abruf: Wenn dein Agent eine neue Anfrage erhält (z. B. „Schlage ein Abendessen Rezept vor“), erstellst du ein Embedding für diese Anfrage. Dann bittest du den Vektorstore, die gespeicherten Embeddings zu finden, die „am nächsten“ (am ähnlichsten) zu deinem Anfrage-Embedding sind. Diese nächsten Embeddings zeigen auf die ursprünglichen Textstücke, die am relevantesten für deine Anfrage sind.
Wenn dein Agent also nach einem „Abendessen Rezept“ fragt und einen Eintrag im langfristigen Gedächtnis über „Erdnussallergie“ hat, könnte das Embedding für „Abendessen Rezept“ „nah genug“ an „Erdnussallergie“ liegen, um dieses wichtige Stück Information abzurufen, selbst wenn „Erdnussallergie“ im aktuellen Gespräch nicht ausdrücklich erwähnt wurde.
Mein erstes Vektorstore-Experiment: Benutzerpräferenzen
Für meinen Mahlzeitenplaner wollte ich, dass er diätetische Einschränkungen und bevorzugte Küchen speichert. Also wollte ich, dass die Tatsache, dass ich „kein rotes Fleisch esse“, gespeichert und abgerufen wird, wann immer er ein Rezept vorschlägt. So habe ich eine grundlegende Version mit einer Bibliothek wie `FAISS` (Facebook AI Similarity Search) oder `ChromaDB` (die oft einfacher für die lokale Entwicklung ist) eingerichtet, kombiniert mit `sentence-transformers` für Embeddings.
Lass uns `ChromaDB` für dieses Beispiel verwenden, da es recht anfängerfreundlich ist, lokal zu starten. Du würdest es normalerweise mit `pip install chromadb sentence-transformers` installieren.
# long_term_memory.py
from sentence_transformers import SentenceTransformer
import chromadb
# Initialisiere das Einbettungsmodell
# Dieses Modell wandelt Text in numerische Vektoren um
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
# Initialisiere ChromaDB-Client und Sammlung
# Dies erstellt eine Datenbank auf deinem lokalen Computer
client = chromadb.PersistentClient(path="./chroma_db")
try:
long_term_collection = client.get_or_create_collection(name="agent_long_term_memory",
metadata={"hnsw:space": "cosine"})
except Exception as e:
print(f"Fehler beim Erstellen/Abfragen der Sammlung: {e}")
# Behandle potenzielle Fehler, z. B. wenn die DB beschädigt oder gesperrt ist
# Für einen Anfänger könnte es am einfachsten sein, den DB-Pfad neu zu starten oder neu zu erstellen
def add_to_long_term_memory(fact_id, fact_text):
"""Fügt einer Tatsache das Langzeitgedächtnis hinzu."""
try:
embedding = embedding_model.encode(fact_text).tolist() # Wandle numpy-Array in Liste um
long_term_collection.add(
documents=[fact_text],
embeddings=[embedding],
ids=[fact_id]
)
print(f"'{fact_text}' wurde mit der ID: {fact_id} zum Langzeitgedächtnis hinzugefügt")
except Exception as e:
print(f"Fehler beim Hinzufügen zum Langzeitgedächtnis: {e}")
def retrieve_from_long_term_memory(query_text, n_results=3):
"""Ruft relevante Fakten aus dem Langzeitgedächtnis anhand einer Anfrage ab."""
try:
query_embedding = embedding_model.encode(query_text).tolist()
results = long_term_collection.query(
query_embeddings=[query_embedding],
n_results=n_results,
include=['documents', 'distances']
)
# Formatiere die Ergebnisse schön
retrieved_facts = []
if results and results['documents']:
for i, doc_list in enumerate(results['documents']):
for j, doc in enumerate(doc_list):
retrieved_facts.append({
"text": doc,
"distance": results['distances'][i][j]
})
return retrieved_facts
except Exception as e:
print(f"Fehler beim Abrufen aus dem Langzeitgedächtnis: {e}")
return []
# Beispielverwendung:
# add_to_long_term_memory("user_allergy_001", "Benutzer ist allergisch gegen Erdnüsse.")
# add_to_long_term_memory("user_pref_002", "Benutzer bevorzugt vegetarische Mahlzeiten an Montagen.")
# add_to_long_term_memory("user_diet_003", "Benutzer isst kein rotes Fleisch.")
# query = "Schlage ein gesundes Abendessenrezept für heute Abend vor."
# relevante_info = retrieve_from_long_term_memory(query, n_results=2)
# print(f"\nRelevante Langzeitinformationen für '{query}':")
# for item in relevante_info:
# print(f"- {item['text']} (Distanz: {item['distance']:.2f})")
# query_2 = "Was soll ich am Montag kochen?"
# relevante_info_2 = retrieve_from_long_term_memory(query_2, n_results=2)
# print(f"\nRelevante Langzeitinformationen für '{query_2}':")
# for item in relevante_info_2:
# print(f"- {item['text']} (Distanz: {item['distance']:.2f})")
Wenn der Agent eine neue Anfrage erhält (wie “Schlage ein Abendessenrezept vor”), fragt er zuerst sein Langzeitgedächtnis (die ChromaDB-Sammlung) mit dieser Anfrage ab. Er ruft die relevantesten Fakten ab (wie “Benutzer ist allergisch gegen Erdnüsse” oder “Benutzer bevorzugt vegetarische Mahlzeiten an Montagen”) und kombiniert diese Fakten dann mit der Kurzzeit-Konversationshistorie, bevor er alles an das LLM sendet. Auf diese Weise hat das LLM einen viel reichhaltigeren Kontext zur Verfügung.
Emmas Tipp: Die `ids` in der `add`-Funktion sind wichtig. Sie ermöglichen es dir, spezifische Fakten später zu aktualisieren oder zu löschen, falls nötig. Wenn sich zum Beispiel die Vorliebe eines Benutzers ändert, kannst du das alte Faktum mit einem neuen unter Verwendung derselben ID überschreiben.
Alles zusammenbringen: Eine einfache Agentenschleife
Wie entscheidet unser Agent also, wann er das Kurzzeit- und wann das Langzeitgedächtnis verwenden soll? Es ist normalerweise eine Kombination. Hier ist ein konzeptioneller Ablauf für einen einfachen Agenten:
- Benutzereingabe: Der Benutzer tippt eine Nachricht ein.
- Kurzzeitig speichern: Die Nachricht des Benutzers wird im Kurzzeit-Konversationsprotokoll hinzugefügt.
- Langzeit abrufen: Verwende die Nachricht des Benutzers (oder eine zusammenfassende Version des Gesprächs) als Anfrage für den Vektorstore. Rufe die Top N relevantesten Fakten ab.
- Prompt erstellen: Kombiniere die aktuelle Kurzzeit-Konversationshistorie UND die abgerufenen Langzeitfakten zu einem einzigen, umfassenden Prompt für das LLM.
- LLM generiert Antwort: Das LLM verarbeitet diesen angereicherten Prompt und generiert eine Antwort.
- Kurzzeitig speichern: Die Antwort des Agenten wird im Kurzzeit-Konversationsprotokoll hinzugefügt.
- (Optional) Langzeit aktualisieren: Wenn der Agent ein neues Stück Information generiert, das langfristig gespeichert werden soll (z. B. “Okay, ich habe notiert, dass du glutenfreie Optionen möchtest.”), kann es dem Vektorstore hinzugefügt werden.
- Antwort ausgeben: Der Agent präsentiert die Antwort dem Benutzer.
Dieser Zyklus ermöglicht es deinem Agenten, sich des unmittelbaren Hin und Her bewusst zu sein, während er gleichzeitig auf ein breiteres Wissen zurückgreifen kann, das er sich angeeignet hat.
Herausforderungen in der realen Welt und was ich gelernt habe
Natürlich ist nicht alles Sonnenschein und perfekt abgerufene Fakten. Hier sind einige Dinge, auf die ich gestoßen bin:
- Prompt Engineering ist entscheidend: Es reicht nicht aus, alle abgerufenen Fakten einfach in den LLM-Prompt zu kippen. Du musst dem LLM erklären, wie es diese Informationen nutzen soll. Etwas wie: “Hier sind einige relevante Kontexte zu den Vorlieben des Benutzers: [abgerufene Fakten]. Basierend darauf und unserer Gesprächshistorie: [Kurzzeitgedächtnis], bitte antworte auf die letzte Anfrage des Benutzers…”
- Umgang mit Begrenzungen des Kontextfensters: Wenn du zu viele Langzeitfakten abrufst UND eine lange Kurzzeitgeschichte hast, kannst du das Token-Limit des LLM überschreiten. Möglicherweise benötigst du das Kurzzeitgedächtnis oder musst selektiv sein, wie viele Langzeitfakten du einschließt.
- Wann Langzeitgedächtnis aktualisieren: Zu entscheiden, wann ein Stück Information aus dem Gespräch dauerhaft gespeichert werden sollte, ist eine Designentscheidung. Für meinen Essensplaner sind explizite Aussagen wie “Ich mag italienisches Essen” oder “Ich bin allergisch gegen Nüsse” klare Kandidaten. Subtilere Hinweise sind schwieriger und könnten einen weiteren LLM-Aufruf erfordern, um sie zu identifizieren.
- “Garbage In, Garbage Out”: Wenn deine Anfangs Fakten im Vektorstore schlecht formuliert oder widersprüchlich sind, leidet dein Abruf darunter. Klarheit ist wichtig.
Aber ehrlich gesagt war das größte Hindernis für mich, einfach anzufangen. Die Idee von “Vektorstores” klang einschüchternd. Aber sobald ich es in Einbettungen und einfache Ähnlichkeitssuche aufschlüsselte und anfängerfreundliche Bibliotheken verwendete, machte es Klick. Es ist wie das Lernen, Fahrrad zu fahren – zu Beginn wackelig, aber unglaublich befreiend, sobald man den Dreh raus hat.
Umsetzbare Erkenntnisse für deinen ersten speicherfähigen Agenten
Bist du bereit, deinem Agenten ein Gehirn zu geben, das tatsächlich erinnert?
- Starte einfach mit Kurzzeit: Implementiere eine einfache Textdatei oder eine In-Memory-Liste, um die letzten paar Gesprächswenden im Auge zu behalten. Dies ist das unmittelbare Notizbuch deines Agenten.
- Experimentiere mit einem lokalen Vektorstore für Langzeit: Installiere `chromadb` und `sentence-transformers`. Versuch, ein paar “Fakten” über dich selbst oder ein bestimmtes Thema hinzuzufügen, und frage sie dann ab. Gewöhne dich an, wie der Abruf funktioniert.
- Kombiniere sie in der Schleife deines Agenten: Strukturiere deinen Agenten so, dass er zuerst relevante Langzeitinformationen abruft, dann diese mit der aktuellen Kurzzeitkontext kombiniert und schließlich alles an dein gewähltes LLM sendet.
- Fokussiere auf klare Aufforderungen: Sage deinem LLM ausdrücklich, wie es die abgerufenen Informationen verwenden soll. Kippe nicht einfach Text hinein.
- Testen, testen, testen: Probiere Grenzfälle aus. Was passiert, wenn der Benutzer eine alte Tatsache widerspricht? Was, wenn er etwas völlig Unzutreffendes fragt? Beobachte, wie dein Gedächtnissystem damit umgeht.
Agents, die sich erinnern, zu entwickeln ist ein grundlegender Schritt hin zu wirklich nützlichen und intelligenten KI-Tools. Es hebt sie über einfache Frage-und-Antwort-Bots hinaus und verwandelt sie in Begleiter, die Kontext verstehen und Wissen anhäufen. Du schaffst das! Gib deinem Agenten ein Gedächtnis und lass mich wissen, welche brillanten Dinge er zu erinnern beginnt.
Viel Spaß beim Bauen,
Emma
🕒 Published: