0Pricing
AI Engineering Academy · Pelajaran

Memori Penyangga dan Jendela

Terapkan ConversationBufferMemory dan ConversationBufferWindowMemory untuk mempertahankan N giliran terakhir dalam konteks, lalu ukur pengaruh ukuran jendela terhadap koherensi dan biaya.

Memori Penyangga dan Jendela adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Memori Penyangga: Simpan Semuanya

Memori penyangga adalah strategi paling sederhana: simpan setiap pesan dari setiap giliran dalam sebuah daftar dan sertakan seluruh riwayat dalam setiap panggilan API. Strategi ini mempertahankan konteks secara sempurna — model dapat merujuk pada apa pun yang pernah dikatakan. Kekurangannya adalah konteks bertambah secara linear tanpa batas. Untuk sesi singkat seperti menyelesaikan satu tugas, memori penyangga sangat sesuai dan paling mudah diterapkan.

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({}))

Mengintegrasikan Memori Penyangga dengan Rantai

Untuk menggunakan memori penyangga dengan LCEL, hubungkan memori tersebut melalui RunnableWithMessageHistory atau gunakan ConversationChain untuk pendekatan lama. Objek memori menyimpan riwayat, sedangkan rantai menggunakan MessagesPlaceholder dalam templat perintah untuk menyisipkannya. Setelah setiap pemanggilan, memori secara otomatis menambahkan giliran baru.

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'
)

Masalah pada Penyangga Tanpa Batas

Memori penyangga berfungsi sampai percakapan menjadi terlalu panjang dan melampaui jendela konteks model. Dengan konteks 128K milik GPT-4o-mini, percakapan biasa mungkin berlangsung selama 200–400 giliran sebelum meluap. Secara lebih praktis, bahkan pada 50 giliran, Anda mengirim lebih dari 50 ribu token per permintaan — biaya yang cukup besar. Anda memerlukan strategi untuk membatasi ukuran riwayat.

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')

Memori Jendela: Simpan N Giliran Terakhir

Memori jendela hanya menyimpan K giliran percakapan terakhir dan membuang pesan yang lebih lama. Strategi ini membatasi konteks pada K * avg_tokens_per_turn, terlepas dari lamanya percakapan. Imbalannya adalah konteks yang sangat awal akan hilang — model mungkin melupakan hal-hal yang dikatakan pengguna beberapa giliran sebelumnya. Untuk sebagian besar bot percakapan serbaguna, jendela berukuran 5–10 giliran memberikan koherensi yang baik dengan biaya yang wajar.

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

Menerapkan Memori Jendela dengan InMemoryChatMessageHistory

InMemoryChatMessageHistory milik LangChain menyimpan semua pesan, tetapi Anda dapat memangkas riwayat sebelum menyisipkannya ke dalam perintah. Pola yang umum adalah menyimpan seluruh riwayat untuk pencatatan, tetapi hanya meneruskan N pesan terakhir ke LLM. Gunakan notasi irisan Python pada history.messages untuk memperoleh jendela terbaru.

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
)

Jendela Berbasis Token vs Berbasis Giliran

Ukuran jendela dapat ditentukan dalam giliran (K pasangan manusia/AI terakhir) atau dalam token (T token terakhir dari riwayat). Pengaturan jendela berbasis token lebih andal karena panjang giliran bervariasi — giliran yang berisi kode bisa 10 kali lebih panjang daripada giliran yang berisi 'ya'. Utilitas trim_messages() milik LangChain mendukung kedua strategi dan dapat mempertahankan perintah sistem saat memangkas riwayat.

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')

Mengukur Koherensi dibandingkan Ukuran Jendela

Memilih ukuran jendela yang tepat memerlukan pengukuran tentang bagaimana koherensi percakapan menurun saat ukuran jendela diperkecil. Jalankan serangkaian percakapan uji ketika giliran N merujuk pada informasi dari giliran N-5, N-10, dan N-20. Uji apakah model masih dapat menjawab dengan benar menggunakan jendela 5, 10, dan 20 giliran. Hasilnya memberi tahu ukuran jendela minimum yang diperlukan untuk kasus penggunaan spesifik Anda.

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

Menggabungkan Perintah Sistem dengan Memori Jendela

Saat menggunakan memori jendela, selalu pertahankan perintah sistem — perintah ini menentukan persona dan aturan AI. Tanpanya, model mungkin kehilangan personanya setelah jendela bergeser melewati giliran pertama. Gunakan opsi include_system=True dalam fungsi pemangkasan, atau selalu sisipkan pesan sistem sebelum riwayat berjendela dalam templat perintah Anda.

# 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

Panduan Memilih Memori Penyangga atau Jendela

Gunakan memori penyangga ketika: percakapan singkat dan terbatas (tugas satu kali, panduan pengisian formulir), konteks lengkap sangat penting (analisis hukum, peninjauan kode), dan anggaran token bukan masalah. Gunakan memori jendela ketika: percakapan dapat berlangsung tanpa batas tertentu (dukungan pelanggan, asisten umum), konteks terbaru lebih penting daripada konteks yang jauh, dan Anda memerlukan biaya token yang dapat diprediksi serta terbatas.

# 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'

Menyimpan Jendela ke Redis

Untuk penggunaan produksi, simpan seluruh riwayat percakapan di Redis (untuk pengambilan cepat) dan pangkas riwayat tersebut ke ukuran jendela saat dibaca. Redis dengan TTL memastikan sesi lama kedaluwarsa secara otomatis. Gunakan set terurut atau daftar dengan LRANGE untuk mengambil hanya N pesan terakhir secara efisien tanpa memuat seluruh riwayat.

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

Memantau Kesehatan Memori dalam Produksi

Lacak metrik berikut dalam produksi untuk menemukan masalah terkait memori: rata-rata token riwayat per permintaan untuk mendeteksi sesi yang tumbuh terlalu besar, pemanfaatan jendela konteks (berikan peringatan jika > 80%), jumlah sesi di penyimpanan untuk mendeteksi kebocoran memori dalam penyimpanan sesi, dan rasio keberhasilan tembolok untuk sesi yang dimuat kembali dari Redis. Berikan peringatan ketika rata-rata token riwayat melewati ambang yang dapat dikonfigurasi.

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

Pemeriksaan Singkat

Uji pemahaman Anda tentang strategi memori penyangga dan jendela.

Ringkasan Pelajaran

Dalam pelajaran ini, Anda telah mempelajari bahwa: memori penyangga mempertahankan seluruh riwayat tetapi terus bertambah tanpa batas, sehingga hanya cocok untuk percakapan singkat yang terbatas, memori jendela hanya menyimpan K giliran terakhir untuk menghasilkan biaya yang dapat diprediksi dan terbatas dengan mengorbankan konteks yang jauh, serta pemangkasan berbasis token dengan trim_messages() lebih andal daripada jendela berbasis giliran karena panjang pesan bervariasi. Selanjutnya, kita akan membahas memori ringkasan untuk percakapan panjang yang terbuka.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Memori Penyangga dan Jendela” gratis?

Ya — teks lengkap “Memori Penyangga dan Jendela” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Memori Penyangga dan Jendela”?

Terapkan ConversationBufferMemory dan ConversationBufferWindowMemory untuk mempertahankan N giliran terakhir dalam konteks, lalu ukur pengaruh ukuran jendela terhadap koherensi dan biaya. Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?

Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Memori Penyangga dan Jendela” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mengapa LLM Tanpa Status Membutuhkan Memori Eksternal
  2. Memori Penyangga dan Jendela
  3. Memori Ringkasan dan Pemotongan yang Sadar Token
  4. Menyimpan Riwayat Obrolan di Redis dan PostgreSQL
← Kembali ke AI Engineering Academy