0Pricing
AI Engineering Academy · Lektion

Puffer- und Fensterspeicher

Sie implementieren ConversationBufferMemory und ConversationBufferWindowMemory, um die letzten N Gesprächsrunden im Kontext zu behalten, und messen, wie sich die Fenstergröße auf Kohärenz und Kosten auswirkt.

Puffer- und Fensterspeicher ist eine kostenlose AI Engineering Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Engineering Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Pufferspeicher: Alles behalten

Der Pufferspeicher ist die einfachste Strategie: Speichern Sie jede Nachricht aus jeder Runde in einer Liste und fügen Sie den vollständigen Verlauf in jeden API-Aufruf ein. Dadurch bleibt der Kontext vollständig erhalten – das Modell kann auf alles Gesagte zurückgreifen. Der Nachteil ist das lineare und unbegrenzte Wachstum des Kontexts. Für kurze Sitzungen, etwa das einmalige Erledigen einer Aufgabe, ist der Pufferspeicher vollkommen geeignet und am einfachsten zu implementieren.

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(
    return_messages=True,  # return Message objects, not a string
    memory_key='history'   # key to inject into prompt template
)

# Add messages manually
memory.chat_memory.add_user_message('What is a neural network?')
memory.chat_memory.add_ai_message('A neural network is a system of layers...')

# Load what will be injected
print(memory.load_memory_variables({}))

Pufferspeicher in eine Chain integrieren

Um den Pufferspeicher mit LCEL zu verwenden, binden Sie ihn über RunnableWithMessageHistory ein oder verwenden Sie für den veralteten Ansatz ConversationChain. Das Speicherobjekt enthält den Verlauf, und die Chain verwendet einen MessagesPlaceholder in der Prompt-Vorlage, um ihn einzufügen. Nach jeder Ausführung hängt der Speicher die neue Runde automatisch an.

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}

def get_history(session_id: str):
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]

chain = (
    ChatPromptTemplate.from_messages([
        ('system', 'You are helpful.'),
        MessagesPlaceholder('history'),
        ('human', '{input}')
    ])
    | ChatOpenAI(model='gpt-4o-mini')
    | StrOutputParser()
)

with_memory = RunnableWithMessageHistory(
    chain, get_history,
    input_messages_key='input',
    history_messages_key='history'
)

Das Problem eines unbegrenzten Puffers

Der Pufferspeicher funktioniert, bis das Gespräch zu lang wird und das Kontextfenster des Modells überschreitet. Mit dem 128K-Kontext von GPT-4o-mini kann ein typischer Chat 200–400 Runden dauern, bevor ein Überlauf auftritt. Praktischer gesehen senden Sie selbst bei 50 Runden pro Anfrage mehr als 50.000 Tokens – ein erheblicher Kostenfaktor. Sie benötigen eine Strategie, um die Größe des Verlaufs zu begrenzen.

import tiktoken

enc = tiktoken.encoding_for_model('gpt-4o-mini')

def count_history_tokens(messages: list) -> int:
    total = 0
    for msg in messages:
        total += len(enc.encode(msg.content))
        total += 4  # per-message overhead
    return total

# Check how big the history has grown
history = store.get('session-1')
if history:
    token_count = count_history_tokens(history.messages)
    print(f'History size: {len(history.messages)} messages, {token_count} tokens')

Fensterspeicher: Die letzten N Runden behalten

Der Fensterspeicher behält nur die letzten K Gesprächsrunden und verwirft ältere Nachrichten. Dadurch wird der Kontext unabhängig von der Gesprächsdauer auf K * avg_tokens_per_turn begrenzt. Der Nachteil ist, dass sehr früher Kontext verloren geht – das Modell kann Dinge vergessen, die der Benutzer viele Runden zuvor gesagt hat. Für die meisten allgemeinen Chatbots bietet ein Fenster von 5–10 Runden eine gute Kohärenz bei akzeptablen Kosten.

from langchain.memory import ConversationBufferWindowMemory

# Keep last 5 turns (10 messages: 5 user + 5 assistant)
memory = ConversationBufferWindowMemory(
    k=5,              # number of TURNS to keep (each turn = user + AI)
    return_messages=True,
    memory_key='history'
)

# After 10 turns, only turns 6-10 will be in context
# Turns 1-5 are silently dropped

Fensterspeicher mit InMemoryChatMessageHistory implementieren

LangChains InMemoryChatMessageHistory behält alle Nachrichten, Sie können den Verlauf jedoch vor dem Einfügen in den Prompt kürzen. Ein gängiges Muster besteht darin, den vollständigen Verlauf für Protokollierungszwecke zu speichern, dem LLM aber nur die letzten N Nachrichten zu übergeben. Verwenden Sie die Python-Slice-Notation für history.messages, um das aktuellste Fenster abzurufen.

from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables import RunnableLambda

WINDOW_SIZE = 10  # last 10 messages (5 turns)

def get_windowed_history(session_id: str):
    full_history = store.get(session_id, InMemoryChatMessageHistory())
    store[session_id] = full_history
    return full_history

# In the chain, trim before injecting
def trim_history(messages):
    return messages[-WINDOW_SIZE:] if len(messages) > WINDOW_SIZE else messages

# Use in prompt with trimming
from langchain_core.messages import trim_messages
trimmer = trim_messages(
    max_tokens=2000,
    strategy='last',
    token_counter=ChatOpenAI(model='gpt-4o-mini'),
    include_system=True
)

Fenster nach Tokens oder nach Runden

Die Fenstergröße kann in Runden (den letzten K Paaren aus Benutzer- und KI-Nachricht) oder in Tokens (den letzten T Tokens des Verlaufs) angegeben werden. Ein tokenbasiertes Fenster ist zuverlässiger, weil die Länge von Runden variiert – eine Runde mit Code ist zehnmal länger als eine Runde mit „ja“. LangChains Hilfsfunktion trim_messages() unterstützt beide Strategien und kann die Systemaufforderung beim Kürzen des Verlaufs beibehalten.

from langchain_core.messages import trim_messages, SystemMessage, HumanMessage, AIMessage

# Token-based trimming — keep last 1000 tokens of conversation
trimmer = trim_messages(
    max_tokens=1000,
    strategy='last',       # keep most recent messages
    token_counter=len,     # approximate: count characters / 4
    include_system=True,   # always include the system prompt
    allow_partial=False,   # don't split a message in half
    start_on='human'       # start window on a human message
)

trimmed = trimmer.invoke(all_messages)
print(f'Trimmed to {len(trimmed)} messages')

Kohärenz und Fenstergröße messen

Um die richtige Fenstergröße zu wählen, müssen Sie messen, wie stark die Kohärenz eines Gesprächs abnimmt, wenn das Fenster kleiner wird. Führen Sie eine Reihe von Testgesprächen durch, in denen sich Runde N auf Informationen aus Runde N-5, N-10 und N-20 bezieht. Testen Sie, ob das Modell mit Fenstern von 5, 10 und 20 Runden weiterhin korrekt antworten kann. Daraus ergibt sich die Mindestfenstergröße, die für Ihren konkreten Anwendungsfall erforderlich ist.

def test_reference_at_distance(chain_with_memory, distances=[5, 10, 20]):
    results = {}
    for distance in distances:
        session_id = f'test-dist-{distance}'
        # Fill with filler turns
        for i in range(distance):
            chain_with_memory.invoke(
                {'input': f'Turn {i}: filler message'},
                config={'configurable': {'session_id': session_id}}
            )
        # Ask about something said at the start
        first_msg = 'Recall that the user said the magic word is AZURE.'
        response = chain_with_memory.invoke(
            {'input': 'What was the magic word?'},
            config={'configurable': {'session_id': session_id}}
        )
        results[distance] = 'AZURE' in response.upper()
    return results

System-Prompt und Fensterspeicher kombinieren

Wenn Sie den Fensterspeicher verwenden, müssen Sie stets den System-Prompt beibehalten – er definiert die Persona und die Regeln der KI. Ohne ihn kann das Modell seine Persona verlieren, sobald das Fenster über die erste Runde hinausgleitet. Verwenden Sie in Trim-Funktionen die Option include_system=True oder fügen Sie die Systemnachricht in Ihrer Prompt-Vorlage immer vor dem Verlauf im Fenster ein.

# Always put system prompt BEFORE the windowed history
prompt = ChatPromptTemplate.from_messages([
    ('system', 'You are a Python tutor. Always explain with code examples.'),
    MessagesPlaceholder('history'),  # windowed history injected here
    ('human', '{input}'),
])

# The system prompt is never trimmed — only the history window is managed
# This ensures the model's persona is always present regardless of window

Entscheidungshilfe: Puffer- oder Fensterspeicher

Verwenden Sie den Pufferspeicher, wenn Gespräche kurz und begrenzt sind (eine einmalige Aufgabe, ein Formularassistent), der vollständige Kontext entscheidend ist (rechtliche Analysen, Code-Reviews) und das Tokenbudget keine Rolle spielt. Verwenden Sie den Fensterspeicher, wenn Gespräche beliebig lang werden können (Kundensupport, allgemeine Assistenten), der aktuelle Kontext wichtiger ist als weit zurückliegender Kontext und Sie vorhersehbare, begrenzte Tokenkosten benötigen.

# Decision matrix in code
def choose_memory_strategy(
    expected_turns: int,
    max_context_tokens: int = 128000,
    avg_tokens_per_turn: int = 200
) -> str:
    buffer_tokens = expected_turns * avg_tokens_per_turn
    if buffer_tokens < max_context_tokens * 0.5:
        return 'buffer'  # Safe to keep everything
    elif expected_turns <= 20:
        return 'window_10'  # Keep last 10 turns
    else:
        return 'summary'  # Need summarization for long convos

print(choose_memory_strategy(5))    # 'buffer'
print(choose_memory_strategy(50))   # 'window_10'
print(choose_memory_strategy(200))  # 'summary'

Das Fenster in Redis persistent speichern

Speichern Sie in einer produktiven Umgebung den vollständigen Gesprächsverlauf in Redis (für schnellen Abruf) und kürzen Sie ihn beim Lesen auf die Fenstergröße. Redis mit einer TTL sorgt dafür, dass alte Sitzungen automatisch ablaufen. Verwenden Sie ein Sorted Set oder eine Liste mit LRANGE, um effizient nur die letzten N Nachrichten abzurufen, ohne den gesamten Verlauf zu laden.

from langchain_community.chat_message_histories import RedisChatMessageHistory

def get_windowed_redis_history(session_id: str, window: int = 10):
    # RedisChatMessageHistory stores all messages
    history = RedisChatMessageHistory(
        session_id=session_id,
        url='redis://localhost:6379',
        ttl=3600  # 1 hour TTL
    )
    # Trim to window size in-memory before use
    all_msgs = history.messages
    if len(all_msgs) > window * 2:  # window turns = window*2 messages
        history.messages = all_msgs[-(window * 2):]
    return history

Die Gesundheit des Speichers in der Produktion überwachen

Überwachen Sie in der Produktion diese Kennzahlen, um speicherbezogene Probleme frühzeitig zu erkennen: durchschnittliche Verlaufstokens pro Anfrage, um zu erkennen, dass Sitzungen zu groß werden; Auslastung des Kontextfensters (Warnung bei > 80 %); Anzahl der Sitzungen im Speicher, um Speicherlecks im Sitzungsspeicher zu erkennen; sowie die Cache-Trefferquote für Sitzungen, die aus Redis erneut geladen werden. Lösen Sie einen Alarm aus, wenn die durchschnittliche Anzahl der Verlaufstokens einen konfigurierbaren Schwellenwert überschreitet.

import time
from langchain_core.callbacks import BaseCallbackHandler

class MemoryMonitorCallback(BaseCallbackHandler):
    def on_chain_start(self, serialized, inputs, **kwargs):
        history = inputs.get('history', [])
        token_estimate = sum(len(m.content.split()) * 1.3 for m in history)
        if token_estimate > 50000:
            print(f'WARNING: Large history {token_estimate:.0f} estimated tokens')

    def on_chain_end(self, outputs, **kwargs):
        # Log usage for dashboards
        pass

Kurzer Test

Testen Sie Ihr Verständnis der Strategien für Puffer- und Fensterspeicher.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Der Pufferspeicher bewahrt den vollständigen Verlauf, wächst jedoch unbegrenzt und eignet sich daher nur für kurze, begrenzte Gespräche; der Fensterspeicher behält nur die letzten K Runden und sorgt so auf Kosten weit zurückliegenden Kontexts für vorhersehbare, begrenzte Kosten; und tokenbasiertes Kürzen mit trim_messages() ist zuverlässiger als fensterbasierte Begrenzungen nach Runden, weil die Nachrichtenlänge variiert. Als Nächstes sehen wir uns den Zusammenfassungsspeicher für offene, lange Gespräche an.

Häufig gestellte Fragen

Ist die Lektion „Puffer- und Fensterspeicher“ kostenlos?

Ja — der vollständige Text von „Puffer- und Fensterspeicher“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Engineering Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Puffer- und Fensterspeicher“?

Sie implementieren ConversationBufferMemory und ConversationBufferWindowMemory, um die letzten N Gesprächsrunden im Kontext zu behalten, und messen, wie sich die Fenstergröße auf Kohärenz und Kosten… Du übst AI Engineering Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Engineering Academy zu starten?

Keine Vorkenntnisse erforderlich. AI Engineering Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Puffer- und Fensterspeicher“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Engineering Academy-Lektion Code schreiben und ausführen?

Ja. Jede AI Engineering Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum zustandslose LLMs externen Speicher benötigen
  2. Puffer- und Fensterspeicher
  3. Zusammenfassungsspeicher und tokenbewusstes Kürzen
  4. Chatverläufe in Redis und PostgreSQL speichern
← Zurück zu AI Engineering Academy