Buffer- og vindusminne
Implementer ConversationBufferMemory og ConversationBufferWindowMemory for å beholde de siste N turene i konteksten, og mål hvordan vindusstørrelsen påvirker sammenheng og kostnad.
Buffer- og vindusminne er en gratis leksjon i AI Engineering Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i AI Engineering Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.
Bufferminne: Behold alt
Bufferminne er den enkleste strategien: lagre hver melding fra hver runde i en liste og ta med hele historikken i hvert API-kall. Det bevarer full kontekst — modellen kan referere til alt som er sagt, uansett når det ble sagt. Ulempen er lineær kontekstvekst uten noen øvre grense. For korte økter, for eksempel gjennomføring av én enkelt oppgave, er bufferminne svært egnet og enklest å implementere.
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({}))Integrere bufferminne med en kjede
For å bruke bufferminne med LCEL kobler De det gjennom RunnableWithMessageHistory, eller bruker ConversationChain for den eldre tilnærmingen. Minneobjektet inneholder historikken, og kjeden bruker en MessagesPlaceholder i ledetekstmalen for å sette den inn. Etter hvert kall legger minnet automatisk den nye runden til.
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'
)Problemet med ubegrenset buffer
Bufferminne fungerer helt til samtalen blir for lang og overskrider modellens kontekstvindu. Med GPT-4o-minis kontekst på 128K kan en typisk chat vare i 200–400 runder før den flyter over. Mer praktisk sett sender De selv etter 50 runder over 50K token per forespørsel — en betydelig kostnad. De trenger en strategi for å begrense historikkstørrelsen.
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')Vindusminne: Behold de siste N rundene
Vindusminne beholder bare de siste K samtalerundene og forkaster eldre meldinger. Dette begrenser konteksten til K * avg_tokens_per_turn, uansett hvor lenge samtalen varer. Ulempen er at svært tidlig kontekst går tapt — modellen kan glemme ting brukeren sa mange runder tidligere. For de fleste chatboter til generell bruk gir et vindu på 5–10 runder god sammenheng til en akseptabel kostnad.
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 droppedImplementere vindusminne med InMemoryChatMessageHistory
LangChains InMemoryChatMessageHistory beholder alle meldinger, men De kan forkorte historikken før den settes inn i ledeteksten. Et vanlig mønster er å lagre hele historikken for logging, men bare sende de siste N meldingene til LLM-en. Bruk Pythons utsnittsnotasjon på history.messages for å hente det nyeste vinduet.
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
)Tokenbasert versus rundenivåbasert vindu
Vindusstørrelsen kan angis i runder (de siste K parene av bruker- og AI-meldinger) eller i token (de siste T tokenene i historikken). Tokenbaserte vinduer er mer pålitelige fordi lengden på rundene varierer — en runde med kode er ti ganger lengre enn en runde med «ja». LangChains verktøy trim_messages() støtter begge strategiene og kan bevare systemledeteksten mens historikken forkortes.
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')Måle sammenheng opp mot vindusstørrelse
For å velge riktig vindusstørrelse må De måle hvordan samtalens sammenheng svekkes når vinduet blir mindre. Kjør et sett med testsamtaler der runde N viser til informasjon fra runde N-5, N-10 og N-20. Test om modellen fortsatt kan svare riktig med vinduer på 5, 10 og 20 runder. Resultatet viser den minste vindusstørrelsen som trengs for Deres spesifikke bruksområde.
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 resultsKombinere systemledetekst med vindusminne
Når De bruker vindusminne, må De alltid bevare systemledeteksten — den definerer AI-personaen og reglene. Uten den kan modellen miste personaen når vinduet har beveget seg forbi den første runden. Bruk alternativet include_system=True i funksjoner for trimming, eller sett alltid systemmeldingen inn før den vindusbegrensede historikken i ledetekstmalen.
# 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 windowVeiledning for valg mellom buffer- og vindusminne
Bruk bufferminne når: samtalene er korte og avgrensede (en engangsoppgave eller en skjemaveiviser), full kontekst er avgjørende (juridisk analyse eller kodegjennomgang), og tokenbudsjettet ikke er en bekymring. Bruk vindusminne når: samtalene kan bli vilkårlig lange (kundestøtte eller generelle assistenter), nyere kontekst er viktigere enn fjern kontekst, og De trenger forutsigbare, begrensede tokenkostnader.
# 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'Lagre vinduet i Redis
For produksjonsbruk lagrer De hele samtalehistorikken i Redis (for rask uthenting) og begrenser den til vindusstørrelsen ved lesing. Redis med en TTL sørger for at gamle økter utløper automatisk. Bruk et sortert sett eller en liste med LRANGE for effektivt å hente bare de siste N meldingene uten å laste inn hele historikken.
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 historyOvervåke minnehelsen i produksjon
Følg med på disse måltallene i produksjon for å oppdage minnerelaterte problemer: gjennomsnittlig antall historikktoken per forespørsel for å oppdage økter som blir for store, utnyttelse av kontekstvinduet (varsle hvis > 80%), antall økter i lageret for å oppdage minnelekkasjer i øktlageret, og hurtigbufferens treffrate for økter som lastes inn på nytt fra Redis. Send et varsel når det gjennomsnittlige antallet historikktoken overskrider en konfigurerbar terskel.
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
passKort kontroll
Test forståelsen Deres av strategiene for buffer- og vindusminne.
Oppsummering av leksjonen
I denne leksjonen lærte De at bufferminne bevarer hele historikken, men vokser uten grense og derfor bare egner seg for korte, avgrensede samtaler, at vindusminne bare beholder de siste K rundene for forutsigbare, begrensede kostnader på bekostning av fjern kontekst, og at tokenbasert trimming med trim_messages() er mer pålitelig enn rundenivåbaserte vinduer fordi meldingslengden varierer. Neste gang utforsker vi sammendragsminne for åpne, lange samtaler.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Buffer- og vindusminne» gratis?
Ja – hele teksten i «Buffer- og vindusminne» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av AI Engineering Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Buffer- og vindusminne»?
Implementer ConversationBufferMemory og ConversationBufferWindowMemory for å beholde de siste N turene i konteksten, og mål hvordan vindusstørrelsen påvirker sammenheng og kostnad. Du øver på AI Engineering Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med AI Engineering Academy?
Ingen tidligere erfaring er nødvendig. AI Engineering Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Buffer- og vindusminne»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne AI Engineering Academy-leksjonen?
Ja. Alle AI Engineering Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Hvorfor tilstandsfrie LLM-er trenger eksternt minne
- Buffer- og vindusminne
- Sammendragsminne og tokenbevisst avkorting
- Lagre chathistorikk i Redis og PostgreSQL