Dokümanlar menüsü
Konuşma belleği (provenance'lı)
Semantik anımsama, yakın pencere, şemalı working memory ve tekrar oynatılabilir sıkıştırma — artı belleğin modelin önüne gerçekte ne koyduğunun ve neyi dışarıda bıraktığının journal kaydı.
Ne işe yarar#
Bir prompt bir döküm değil, bir bileşimdir. Bellek onu yakın pencereden, semantik anımsamadan, damıtılmış gözlemlerden ve working memory'den kurar — ve model cevabı verdiğinde bunlardan hangisinin cevabı taşıdığını kimse göremez. Çoğu bellek uygulaması tam burada durur.
Belleği journal'ın üstüne koymanın iki sonucu var. Birincisi, bileşim donar: loadContext girdi kalıcılaştırılmadan önce koşar, yani tam prompt tekrar oynatılabilir. İkincisi, belleğin kendi yaptığı LLM çağrıları — geçmişi gözlemlere özetlemek, gözlemleri yoğunlaştırmak — durableProcessorStep üzerinden journal'lanır; aynı sırayla tekrar çağrıldığında model koşmaz ve özet birebir aynı çıkar. Sıkıştırma sadece tekrarlanabilir değil, tekrar oynatılabilirdir.
Depolama bilinçli olarak iki porta ayrılmıştır. MemoryStore (storage.memory) thread'leri, mesajları, working memory'yi ve gözlemleri tutar — türetilmiş, sorgulanabilir taraf. RunJournal (storage.runs) ise memoize edilmiş LLM çağrılarını ve dayanıklı ilerlemeyi tutar.
Kurulum / import#
import { AgentMemory } from '@gnldev/memory';
import { SqliteStorage } from '@gnldev/durable/sqlite';AgentMemory, runDurable'ın beklediği Memory arayüzünü uygular ve üstüne daha zengin bir loadContext kancası ekler. memory yeteneği sunan bir storage ister — bellek-içi, SQLite ve Postgres adaptörlerinin hepsi sunar.
Anımsama ve yakın pencere#
recentN her zaman dahil edilen kuyruktur. recall ise sorgu güdümlü yarıdır ve seçenekleri uçtan uca store'a iner: topK, threshold, scope, messageRange (her isabeti seq'e göre komşularıyla genişletir, tekilleştirerek) ve alışıldık operatörlerle filter — $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin.
const storage = new SqliteStorage('app.db');
const memory = new AgentMemory({
storage,
embed, // a real embedding model for real recall
recentN: 10, // the tail that is always included
recall: { topK: 5, threshold: 0.7, messageRange: 1 },
});
const gnl = createGnl({ storage, agents, memory }); // top level, not per agent
await gnl.run('support', {
runId: 'ticket-9',
threadId: 'user-42', // the conversation
resourceId: 'user-42', // recall may reach across this user's threads
prompt: 'What did we decide about the refund?',
});Her konuşma için bir threadId, anımsamanın bir kullanıcının thread'leri arasına uzanmasını istediğinizde de bir resourceId verin.
Working memory#
Working memory, ajanın konuşma hakkında tuttuğu yapılandırılmış durumdur — bir zod şeması ya da serbest biçimli bir şablon. Açıkken updateWorkingMemory bir tool olarak kaydedilir ve güncel durum system mesajına işlenir. Tool, runDurable içinde durableTool ile sarılır; yani birleştirme journal'lanır ve bir resume aynı yamayı iki kez uygulamaz.
readOnly durumu enjekte eder ama güncelleme tool'unu kaydetmez; scope ise durumun thread'e mi yoksa kaynağa mı ait olduğunu seçer.
new AgentMemory({
storage,
workingMemory: {
schema: z.object({ plan: z.string(), openQuestions: z.array(z.string()) }),
scope: 'thread', // or 'resource'
// readOnly: true // inject the state, do not register the update tool
},
});Gözlemsel bellek — tekrar oynatılabilir sıkıştırma#
Bir thread pencereyi aştığında gözlemci önceki geçmişi gözlemlere damıtır, yansıtıcı da bu gözlemleri daha da yoğunlaştırır. İkisi de model çağrısıdır ve ikisi de sıraya göre journal'lanır: aynı seq ile tekrar çağrıldığında model koşmaz, özet bayt bayt aynıdır.
Her gözlem hangi mesaj aralığından damıtıldığını kaydeder (fromSeq/toSeq/threadId), böylece yoğunlaştırılmış bir hatıra hâlâ kaynağına kadar izlenebilir. Gözlemler üzerinde arama (recallObservations, createOmRecallTool) opt-in'dir — hiçbir preset o tool'u sizin için kaydetmez, yani gözlemsel belleği açmak modele sessizce yeni bir tool vermez.
new AgentMemory({
storage,
observationalMemory: { model, tokenThreshold: 4000 },
});
// the same seq -> the model is NOT called again and the summary is identical
// each observation keeps { threadId, fromSeq, toSeq } — traceable to its sourceProvenance — modele gerçekte ne gitti#
Belleği kullanan her çalıştırma bir :memctx kaydı yazar. Sayıların tek başına cevaplayamadığı soruyu cevaplar: yalnız kaç mesaj enjekte edildiğini değil, hangilerinin edildiğini — her biri thread, seq, rol, kısa bir önizleme ve anımsama isabetlerinde skor taşıyan bir ref olarak.
// journal key: <runId>:memctx
{
recalled: [
{ threadId: 'user-42', seq: 18, role: 'user', preview: 'the refund was approved…', score: 0.83 },
{ threadId: 'user-42', seq: 19, role: 'assistant', preview: '→ refund({"id":"r-7"})', reason: 'repair' },
],
recentCount: 10,
recent: [ /* capped at PROVENANCE_RECENT_CAP = 24 */ ],
droppedCount: 1,
dropped: [ { threadId: 'user-42', seq: 11, role: 'assistant', preview: '→ charge({…})' } ],
observationCount: 3,
workingMemoryChars: 412,
}İki kez okunmayı hak eden alan dropped. Anımsama bazen enjekte edilemeyecek bir mesaj seçer — tool-result'ı yeniden üretilemeyen bir tool-call taşıyan anımsanmış mesaj, sağlayıcının bütün prompt'u reddetmesine yol açardı. Onu dışarıda bırakmak doğrudur; sessizce bırakmak ise anımsamanın hiçbir şey bulamamasından ayırt edilemez, ve bu fark modelin neden unuttuğunu soran kişi için önemlidir.
Bu alan bilinçli olarak recalled'ın dışında tutulur. O liste "kanıtlanabilir biçimde enjekte edilen" olarak tüketilir — replay-regression'daki karşı-olgusal replay onu prompt'tan çıkarır; modele hiç ulaşmamış bir mesajı orada listelemek, hiç eklenmemiş bir şeyi çıkarmasına yol açardı.
API#
AgentMemoryMemory arayüzünü ve bir loadContext kancasını uygular. Config: storage, embed?, recentN?, recall?, workingMemory?, observationalMemory?, generateTitle?.
LoadedContext{ messages, system?, tools?, provenance? } — belleğin bu tur için kurduğu şey.
MemoryContextProvenance{ recalled[], recentCount, recent?[], droppedCount?, dropped?[], observationCount?, workingMemoryChars? } — ':memctx' okuma modeli. @gnldev/memory'den değil, @gnldev/durable'dan export edilir.
RecalledMessageRef{ threadId, seq, role, preview, score?, reason? } — reason: 'repair', benzerlikle seçilmek yerine anımsanmış bir tool-call'ı tamamlamak için çekilen satırı işaretler. @gnldev/memory'den değil, @gnldev/durable'dan export edilir.
createWorkingMemoryToolupdateWorkingMemory AI SDK tool'u; apply birleştirmeyi yapar ve yeni durumu döner.
observeGeçmişi gözlemlere damıtır; model çağrısı sıraya göre journal'lanır.
reflectGözlemleri daha da yoğunlaştırır; aynı biçimde journal'lanır.
createOmRecallToolÇağıranın verdiği recall closure'ını tool olarak sarar — opt-in, asla otomatik kaydedilmez.
memoryPresetHazır bir AgentMemory yapılandırması; defaultEmbed otomatik bağlanmaz, böylece anımsamayı sessizce değiştiremez.
createGnl({ storage, agents, memory })'dir. AgentConfig'de memory alanı yoktur; yani bir agent'ın içinde model ve tools'un yanına konan bellek nesnesi hiçbir şey yapmaz — ve belirti bir hata değil, sıfır mesaj içeren bir thread olur.createDefaultEmbed, bağımlılıksız ve deterministik bir token-hash gömmesidir — L2-normalize edilir, yani kosinüs benzerliğiyle çalışır ve testlerde/örneklerde işe yarar. Semantik bir model değildir. Gerçek anımsama gerçek bir gömme modeli ister; preset'lerin onu sizin için bağlamamasının sebebi de budur.