Belajar AI #40: Memori Agent — Short-term, Long-term, dan Context Engineering

Di episode #26 kita sudah membahas bahwa AI Agent itu punya loop perceive-reason-act, dan di episode #27 kita lihat bagaimana model memanggil tools. Tapi ada satu masalah mendasar yang sering saya lupa (ironis, memang): model LLM itu stateless. Setiap kali sesi baru dimulai, semua konteks percakapan sebelumnya hilang kecuali kita kirim ulang. Hari ini saya catat bagaimana caranya membuat agent yang tidak “lupa” — mulai dari memori jangka pendek, memori jangka panjang, sampai disiplin yang sekarang disebut context engineering.

Kenapa LLM selalu lupa

Saya mulai dari analogi programmer: model LLM itu seperti fungsi murni. Input (prompt) masuk, output keluar, tidak ada variabel global yang tersimpan antar-panggilan. Tidak ada session, tidak ada database bawaan. Semua “ingatan” yang terlihat sebenarnya berasal dari satu hal: konteks percakapan yang kita kirim ulang di setiap request.

Masalahnya jelas. Pertama, context window terbatas — berapa pun panjangnya, percakapan panjang suatu hari akan melebihi batas. Kedua, mengirim seluruh riwayat di setiap request itu mahal: token yang dikirim = token yang dibayar, dan latensi ikut naik. Ketiga, kualitas model menurun kalau konten penting tenggelam di tengah lautan riwayat (disebut context rot — informasi relevan “tertimbun” noise percakapan).

Dua tingkat memori: short-term dan long-term

Solusinya meminjam ide dari sistem operasi yang sudah kita kenal. Memori jangka pendek (short-term memory) = isi context window: pesan percakapan, system prompt, ringkasan sesi berjalan. Memori jangka panjang (long-term memory) = penyimpanan eksternal (file, database, vector DB) yang bisa dicari agent lewat tools lalu dimasukkan kembali ke konteks hanya saat dibutuhkan.

Paper MemGPT (arXiv:2310.08560, 2023) memformulasikan ini sebagai virtual context management: meniru virtual memory di OS, di mana context window ibarat RAM (cepat tapi kecil) dan penyimpanan eksternal ibarat disk (besar tapi harus dipaging). Agent sendiri yang memutuskan data mana yang “di-swap in” ke konteks dan mana yang dievakuasi ke disk. Sistem yang lahir dari paper ini sekarang dikenal sebagai Letta.

Di dokumentasi Letta, hierarki memorinya jelas: memory block yang selalu ada di context (disarankan di bawah 50 ribu karakter per blok, maksimal sekitar 20 blok per agent) untuk fakta penting seperti nama user; file yang bisa dibuka/ditutup saat butuh (batas 5 MB per file) untuk dokumen sedang; dan archival memory (tak terbatas, diakses lewat tool insert/search) untuk ingatan yang jarang tapi sesekali perlu. Ini nyatanya: tidak semua ingatan diperlakukan sama.

Pola memori yang bisa langsung dipakai

  • Compaction / summarization. Saat riwayat mendekati batas, rangkum bagian awal jadi satu paragraf, lalu ganti riwayat aslinya. Ini yang dilakukan banyak coding agent ketika percakapan memanjang.
  • Retrieval-based memory. Simpan fakta/kejadian penting di vector DB, cari relevan per tugas. Di episode #33 kita sudah bahas embedding dan chunking — infrastrukturnya persis sama, yang berubah hanya isi yang disimpan: bukan dokumen perusahaan, melainkan ingatan agent.
  • File-based memory (notes). Cara paling sederhana: agent menulis catatan ke file markdown, lalu membacanya di awal sesi. Tidak butuh vector DB, mudah diaudit, dan manusia bisa mengoreksi langsung.
  • Structured state. Untuk data yang terstruktur (status order, hasil langkah sebelumnya), simpan sebagai JSON di database dan muat ulang tiap iterasi. Mirip state machine, bukan “ingatan” dalam arti bebas — tapi justru karena itu paling handal.

Bentuk paling minimal dari memori berbasis file kira-kira seperti ini:

import json, pathlib

MEMORY = pathlib.Path("agent_memory.json")

def load_memory():
    if MEMORY.exists():
        return json.loads(MEMORY.read_text())
    return {"preferences": {}, "history_summaries": []}

def remember(key, value):
    mem = load_memory()
    mem["preferences"][key] = value
    MEMORY.write_text(json.dumps(mem, indent=2))

Ini memang bukan hal yang canggih. Dan itu justru poinnya: sebagian besar kebutuhan memori agent di dunia nyata bisa dicukupi dengan file terstruktur plus retrieval sederhana, bukan framework berlapis.

Context engineering: memori hanyalah bagian terbesar

Belakangan istilah context engineering lebih sering muncul dibanding prompt engineering. Bedanya: prompt engineering fokus merangkai satu instruksi agar bagus; context engineering fokus merancang SELURUH isi context window tiap iterasi — apa yang masuk, apa yang dikeluarkan, kapan diambil dari mana. Anthropic menyebutnya sebagai disiplin merancang context window seperti merancang resource terbatas, dengan konsep seperti context rot dan needle stacking (terlalu banyak instruksi saling bertumpuk yang justru menurunkan kepatuhan model).

Ini berarti bagi saya: saat membangun agent, sebagian besar pekerjaan “membuatnya pintar” sebenarnya adalah pekerjaan manajemen data — memilih, meringkas, dan menyajikan konteks. Modelnya sudah kita dapat dari provider (episode #39 membahas pilihan model open source), tapi memori yang rapi adalah tanggung jawab kita sebagai developer.

Catatan praktis saya

Pertama, mulai dari yang paling murah: file + summarization dulu, vector DB hanya kalau volume ingatan memang besar. Kedua, selalu simpan memori yang bisa dibaca manusia (markdown/JSON, bukan vektor mentah) supaya mudah diperbaiki saat isinya salah — agent yang “mengingat” hal keliru bisa lebih berbahaya daripada agent yang lupa. Ketiga, ukur juga kualitas memorinya, bukan cuma fungsinya: apakah ingatan yang diambil benar-benar relevan dengan tugas saat ini? Ini menghubungkan kembali ke bahasan eval di episode #30 — agent dengan memori yang buruk akan gagal pada test case percakapan panjang, dan itu harus terdeteksi sebelum dipakai pengguna.

Sumber

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses