Buffer- en windowgeheugen
U implementeert ConversationBufferMemory en ConversationBufferWindowMemory om de laatste N gespreksbeurten in de context te bewaren en meet hoe de venstergrootte samenhangt met coherentie en kosten.
Buffer- en windowgeheugen is een gratis AI Engineering Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject AI Engineering Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus AI Engineering Academy bevat in totaal 4 lessen.
Buffergeheugen: alles behouden
Buffergeheugen is de eenvoudigste strategie: sla elk bericht uit elke beurt op in een lijst en voeg de volledige geschiedenis toe aan elke API-aanroep. Zo blijft de context volledig behouden — het model kan verwijzen naar alles wat op enig moment is gezegd. Het nadeel is dat de context lineair groeit zonder bovengrens. Voor korte sessies, zoals het voltooien van één taak, is buffergeheugen zeer geschikt en het eenvoudigst te implementeren.
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({}))Buffergeheugen integreren met een keten
Als je buffergeheugen met LCEL wilt gebruiken, koppel je het via RunnableWithMessageHistory of gebruik je ConversationChain voor de verouderde aanpak. Het geheugenobject bevat de geschiedenis en de keten gebruikt een MessagesPlaceholder in de promptsjabloon om deze in te voegen. Na elke aanroep voegt het geheugen automatisch de nieuwe beurt toe.
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'
)Het probleem met een onbeperkte buffer
Buffergeheugen werkt totdat het gesprek te lang wordt en het contextvenster van het model overschrijdt. Met het contextvenster van 128K van GPT-4o-mini kan een typisch gesprek 200–400 beurten duren voordat het overloopt. Praktischer gezien verstuur je zelfs bij 50 beurten per aanvraag meer dan 50K tokens — een aanzienlijke kostenpost. Je hebt een strategie nodig om de grootte van de geschiedenis te 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')Venstergeheugen: de laatste N beurten behouden
Venstergeheugen behoudt alleen de laatste K gespreksbeurten en verwijdert oudere berichten. Hiermee begrens je de context op K * avg_tokens_per_turn, ongeacht hoe lang het gesprek duurt. De keerzijde is dat de vroegste context verloren gaat — het model kan dingen vergeten die de gebruiker veel beurten eerder heeft gezegd. Voor de meeste chatbots voor algemeen gebruik biedt een venster van 5–10 beurten een goede samenhang tegen aanvaardbare 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 droppedVenstergeheugen implementeren met InMemoryChatMessageHistory
De InMemoryChatMessageHistory van LangChain bewaart alle berichten, maar je kunt de geschiedenis inkorten voordat je deze in de prompt invoegt. Een veelgebruikt patroon is om de volledige geschiedenis te bewaren voor logregistratie, maar alleen de laatste N berichten aan de LLM door te geven. Gebruik de slice-notatie van Python op history.messages om het meest recente venster op te halen.
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
)Venster op basis van tokens versus beurten
Je kunt de venstergrootte opgeven in beurten (de laatste K-paren van gebruiker en AI) of in tokens (de laatste T tokens van de geschiedenis). Een venster op basis van tokens is betrouwbaarder, omdat de lengte van beurten varieert — een beurt met code is 10 keer langer dan een beurt met 'ja'. De trim_messages()-hulpmethode van LangChain ondersteunt beide strategieën en kan de systeemprompt behouden terwijl de geschiedenis wordt ingekort.
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')Samenhang meten tegenover venstergrootte
Om de juiste venstergrootte te kiezen, moet je meten hoe de samenhang van het gesprek afneemt naarmate het venster kleiner wordt. Voer een reeks testgesprekken uit waarin beurt N verwijst naar informatie uit beurt N-5, N-10 en N-20. Test of het model nog steeds correct kan antwoorden met vensters van 5, 10 en 20 beurten. Het antwoord geeft je de minimale venstergrootte voor jouw specifieke gebruikssituatie.
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 resultsSysteemprompt combineren met venstergeheugen
Wanneer je venstergeheugen gebruikt, moet je altijd de systeemprompt behouden — deze definieert de persona en regels van de AI. Zonder deze prompt kan het model zijn persona verliezen zodra het venster voorbij de eerste beurt schuift. Gebruik de optie include_system=True in inkortfuncties, of voeg het systeembericht altijd vóór de geschiedenis met venster toe in je promptsjabloon.
# 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 windowKeuzehulp: buffer- versus venstergeheugen
Gebruik buffergeheugen wanneer: gesprekken kort en begrensd zijn (een eenmalige taak, een formulierwizard), de volledige context cruciaal is (juridische analyse, codebeoordeling) en het tokenbudget geen probleem vormt. Gebruik venstergeheugen wanneer: gesprekken onbeperkt lang kunnen worden (klantenondersteuning, algemene assistenten), recente context belangrijker is dan verre context en je voorspelbare, begrensde tokenkosten nodig hebt.
# 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'Het venster opslaan in Redis
Sla voor productiegebruik de volledige gesprekgeschiedenis op in Redis (voor snel ophalen) en beperk deze tijdens het lezen tot de venstergrootte. Redis met een TTL zorgt ervoor dat oude sessies automatisch verlopen. Gebruik een geordende verzameling of een lijst met LRANGE om efficiënt alleen de laatste N berichten op te halen zonder de volledige geschiedenis te 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 historyDe gezondheid van geheugen in productie bewaken
Houd deze statistieken in productie bij om problemen met geheugen op te sporen: gemiddeld aantal geschiedenistokens per aanvraag om te detecteren dat sessies te groot worden, gebruik van het contextvenster (waarschuw bij > 80%), aantal sessies in de opslag om geheugenlekken in de sessieopslag te detecteren en cachetrefferpercentage voor sessies die opnieuw uit Redis worden geladen. Geef een waarschuwing wanneer het gemiddelde aantal geschiedenistokens een instelbare drempel overschrijdt.
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
passKorte controle
Test je begrip van buffer- en venstergeheugenstrategieën.
Samenvatting van de les
In deze les heb je geleerd dat buffergeheugen de volledige geschiedenis behoudt maar onbeperkt groeit, waardoor het alleen geschikt is voor korte, begrensde gesprekken, dat venstergeheugen alleen de laatste K beurten behoudt voor voorspelbare, begrensde kosten ten koste van verre context, en dat inkorten op basis van tokens met trim_messages() betrouwbaarder is dan vensters op basis van beurten, omdat de berichtlengte varieert. Hierna bekijken we samenvattingsgeheugen voor open, lange gesprekken.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Buffer- en windowgeheugen” gratis?
Ja — de volledige tekst van “Buffer- en windowgeheugen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus AI Engineering Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus AI Engineering Academy bevat in totaal 4 lessen.
Wat leer ik in “Buffer- en windowgeheugen”?
U implementeert ConversationBufferMemory en ConversationBufferWindowMemory om de laatste N gespreksbeurten in de context te bewaren en meet hoe de venstergrootte samenhangt met coherentie en kosten. Je oefent met AI Engineering Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met AI Engineering Academy te beginnen?
Ervaring vooraf is niet nodig. AI Engineering Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Buffer- en windowgeheugen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over AI Engineering Academy?
Ja. Elke les over AI Engineering Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Waarom stateless LLM's extern geheugen nodig hebben
- Buffer- en windowgeheugen
- Samenvattingsgeheugen en tokenbewuste afkapping
- Chatgeschiedenis bewaren in Redis en PostgreSQL