कंप्यूटर एक्सेस सिस्टम

एजेंट मेमोरी सिस्टम: अपनी AI को स्थायी संदर्भ देना


हर AI एजेंट को मेमोरी की समस्या होती है। मॉडल का हर कॉल स्टेटलेस होता है। मॉडल को पिछला अनुरोध याद नहीं रहता। उसे यूज़र का नाम, प्राथमिकताएं या पहले के निर्णय याद नहीं रहते। बाहरी मेमोरी के बिना, आपका एजेंट हर बार शून्य से शुरू होता है।

यह गाइड चार मेमोरी स्ट्रेटेजी को कवर करती है — सबसे सरल से लेकर सबसे शक्तिशाली तक — और कब किसका उपयोग करना है। सभी उदाहरण TypeScript और Anthropic SDK का उपयोग करते हैं।

एजेंट्स को मेमोरी की ज़रूरत क्यों होती है

एक कोड रिव्यू एजेंट पर विचार करें। पहली बार चलाने पर, यूज़र अपनी टीम की परंपराओं की व्याख्या करता है: कोई any टाइप नहीं, हमेशा त्रुटियों को स्पष्ट रूप से संभालें, फंक्शनल स्टाइल पसंद करें। एजेंट एक अच्छा रिव्यू देता है।

दूसरी बार चलाने पर, यूज़र एक और फ़ाइल सबमिट करता है। एजेंट सब कुछ भूल चुका है। वह उन्हीं उल्लंघनों को याद नहीं करता जो उसने कल फ्लैग किए थे।

यही मूल समस्या है: एजेंट स्टेटलेस होते हैं, लेकिन उपयोगी एजेंट्स को निरंतरता की आवश्यकता होती है

मेमोरी एजेंट्स को तीन क्षमताएं देती है:

  • रिकॉल — किसी बातचीत में पहले से या पिछले सेशन से तथ्य पुनः प्राप्त करना
  • पर्सनलाइज़ेशन — समय के साथ यूज़र की प्राथमिकताओं के अनुकूल होना
  • समन्वय — मल्टी-एजेंट सिस्टम में, एजेंट्स के बीच स्टेट शेयर करना

चार मेमोरी प्रकार

कोड लिखने से पहले, स्ट्रेटेजी को स्पष्ट रूप से नाम देना उपयोगी है। एजेंट मेमोरी चार पैटर्न में आती है:

प्रकारकहाँ स्टोरदायरासबसे उपयुक्त
बफरसंदर्भ में (मेसेज अरे)वर्तमान सेशनछोटी बातचीत
सारांशसंदर्भ में (संपीड़ित)वर्तमान सेशनलंबी बातचीत
सिमेंटिकबाहरी (वेक्टर DB)क्रॉस-सेशनज्ञान रिकॉल
एपिसोडिकबाहरी (की-वैल्यू स्टोर)क्रॉस-सेशनयूज़र तथ्य, प्राथमिकताएं

प्रत्येक स्ट्रेटेजी में सरलता, लागत और क्षमता के बीच अलग-अलग ट्रेडऑफ होती है। वह न्यूनतम चुनें जो आपकी समस्या हल करे।

स्ट्रेटेजी 1: कन्वर्सेशन बफर

सबसे सरल स्ट्रेटेजी है हर मॉडल कॉल पर पूरा कन्वर्सेशन हिस्ट्री पास करना। मॉडल पिछले हर मेसेज को देखता है और पूरे संदर्भ के साथ जवाब देता है।

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface Message {
role: "user" | "assistant";
content: string;
}
// बफर में पूरा कन्वर्सेशन हिस्ट्री होता है
const buffer: Message[] = [];
async function chat(userMessage: string): Promise<string> {
// नया यूज़र मेसेज बफर में जोड़ें
buffer.push({ role: "user", content: userMessage });
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
// हर कॉल पर पूरा बफर पास करें
messages: buffer,
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
// असिस्टेंट का जवाब बफर में जोड़ें
buffer.push({ role: "assistant", content: assistantMessage });
return assistantMessage;
}
// उपयोग उदाहरण
await chat("मेरा नाम Alex है और मैं TypeScript से ज़्यादा Python पसंद करता हूँ।");
await chat("मुझे अपने अगले प्रोजेक्ट के लिए कौन सी भाषा इस्तेमाल करनी चाहिए?");
// मॉडल को पहले मेसेज में बताई गई प्राथमिकता याद है

कब इस्तेमाल करें: 20 से कम टर्न की बातचीत। सरल चैटबॉट। प्रोटोटाइप।

सीमा: कॉन्टेक्स्ट विंडो सीमित होती है। एक लंबा सेशन अंततः टोकन सीमा से अधिक हो जाता है, और सबसे पुराने मेसेज हटाने पड़ते हैं। मॉडल चुपचाप शुरुआती संदर्भ खो देता है, जिससे असंगत व्यवहार होता है।

स्ट्रेटेजी 2: रोलिंग सारांश

जब बातचीत लंबी हो जाए, पुराने टर्न को हटाने की बजाय सारांशित करें। हाल के मेसेजेस की एक स्लाइडिंग विंडो से पहले क्या हुआ, उसका एक संपीड़ित सारांश बनाए रखें।

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface ConversationState {
summary: string; // पुराने टर्न का संपीड़ित हिस्ट्री
recentMessages: Array<{ role: "user" | "assistant"; content: string }>;
maxRecentTurns: number; // अंतिम N टर्न शब्दशः रखें
}
const state: ConversationState = {
summary: "",
recentMessages: [],
maxRecentTurns: 6, // 3 यूज़र + 3 असिस्टेंट टर्न
};
// पुराने टर्न को रोलिंग सारांश में संपीड़ित करें
async function compressSummary(
currentSummary: string,
messagesToCompress: Array<{ role: string; content: string }>
): Promise<string> {
const formatted = messagesToCompress
.map((m) => `${m.role.toUpperCase()}: ${m.content}`)
.join("\n");
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 512,
messages: [
{
role: "user",
content: `नीचे दिए गए नए एक्सचेंज जोड़कर कन्वर्सेशन सारांश अपडेट करें।
केवल अपडेट किया गया सारांश वापस करें। इसे 200 शब्दों से कम रखें।
वर्तमान सारांश:
${currentSummary || "(कोई नहीं)"}
नए एक्सचेंज:
${formatted}`,
},
],
});
return response.content[0].type === "text" ? response.content[0].text : currentSummary;
}
async function chat(userMessage: string): Promise<string> {
// जब बफर सीमा से अधिक हो, सबसे पुराने आधे को संपीड़ित करें
if (state.recentMessages.length >= state.maxRecentTurns * 2) {
const toCompress = state.recentMessages.splice(0, state.maxRecentTurns);
state.summary = await compressSummary(state.summary, toCompress);
}
state.recentMessages.push({ role: "user", content: userMessage });
// मेसेज अरे बनाएं: सिस्टम सारांश + हाल के शब्दशः टर्न
const messages = [
...(state.summary
? [
{
role: "user" as const,
content: `इस बातचीत में पहले का संदर्भ:\n${state.summary}`,
},
{
role: "assistant" as const,
content: "समझ गया। मैं उस संदर्भ का उपयोग करूँगा।",
},
]
: []),
...state.recentMessages,
];
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages,
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
state.recentMessages.push({ role: "assistant", content: assistantMessage });
return assistantMessage;
}

सारांश कॉल एक तेज़, सस्ते मॉडल (Haiku) का उपयोग करता है। मुख्य बातचीत सक्षम मॉडल (Sonnet) का उपयोग करती है। यह विभाजन गुणवत्ता बनाए रखते हुए लागत कम रखता है।

कब इस्तेमाल करें: 20 से अधिक टर्न के सेशन। सपोर्ट एजेंट। लंबे समय तक चलने वाले टास्क एजेंट।

सीमा: सारांश विवरण खो देते हैं। बातचीत की शुरुआत में बताए गए विशिष्ट तथ्य अस्पष्ट कथनों में संपीड़ित हो सकते हैं। विशिष्ट तथ्यों की सटीक रिकॉल के लिए, एपिसोडिक मेमोरी का उपयोग करें।

स्ट्रेटेजी 3: एपिसोडिक मेमोरी

एपिसोडिक मेमोरी किसी यूज़र या सेशन के बारे में विशिष्ट तथ्यों को की-वैल्यू स्टोर में संग्रहीत करती है। एजेंट बातचीत के दौरान तथ्य निकालता है और भविष्य के सेशन में उन्हें पुनः प्राप्त करता है।

import Anthropic from "@anthropic-ai/sdk";
import fs from "fs/promises";
const client = new Anthropic();
// प्रोडक्शन में, इस फाइल स्टोर को Redis या डेटाबेस से बदलें
const MEMORY_PATH = "./memory.json";
interface EpisodicStore {
[userId: string]: Record<string, string>;
}
async function loadMemory(): Promise<EpisodicStore> {
try {
const data = await fs.readFile(MEMORY_PATH, "utf-8");
return JSON.parse(data);
} catch {
return {};
}
}
async function saveMemory(store: EpisodicStore): Promise<void> {
await fs.writeFile(MEMORY_PATH, JSON.stringify(store, null, 2));
}
// नवीनतम एक्सचेंज से संरचित तथ्य निकालें
async function extractFacts(
userMessage: string,
assistantReply: string
): Promise<Record<string, string>> {
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 256,
messages: [
{
role: "user",
content: `इस एक्सचेंज से कोई भी व्यक्तिगत तथ्य, प्राथमिकताएं या महत्वपूर्ण निर्णय निकालें।
की-वैल्यू पेयर का JSON ऑब्जेक्ट वापस करें। यदि याद रखने योग्य कुछ नहीं है तो {} वापस करें।
यूज़र: ${userMessage}
असिस्टेंट: ${assistantReply}`,
},
],
});
try {
const text = response.content[0].type === "text" ? response.content[0].text : "{}";
const match = text.match(/\{[\s\S]*\}/);
return match ? JSON.parse(match[0]) : {};
} catch {
return {};
}
}
// संग्रहीत तथ्यों को सिस्टम प्रॉम्प्ट इंजेक्शन के रूप में फॉर्मेट करें
function formatMemory(facts: Record<string, string>): string {
const entries = Object.entries(facts);
if (entries.length === 0) return "";
return (
"इस यूज़र के बारे में आप क्या जानते हैं:\n" +
entries.map(([k, v]) => `- ${k}: ${v}`).join("\n")
);
}
async function chat(userId: string, userMessage: string): Promise<string> {
const store = await loadMemory();
const userFacts = store[userId] ?? {};
const systemPrompt = formatMemory(userFacts);
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: systemPrompt || undefined,
messages: [{ role: "user", content: userMessage }],
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
// तथ्य निकालें और भविष्य के सेशन के लिए उन्हें persist करें
const newFacts = await extractFacts(userMessage, assistantMessage);
if (Object.keys(newFacts).length > 0) {
store[userId] = { ...userFacts, ...newFacts };
await saveMemory(store);
}
return assistantMessage;
}
// सेशन 1
await chat("user-123", "मैं संक्षिप्त उत्तर पसंद करता हूँ। जब तक ज़रूरी न हो बुलेट पॉइंट नहीं।");
// सेशन 2 (कुछ दिन बाद एक अलग प्रोसेस)
await chat("user-123", "TCP हैंडशेक कैसे काम करता है, समझाएं।");
// एजेंट को सेशन 1 की फॉर्मेटिंग प्राथमिकता याद है

कब इस्तेमाल करें: यूज़र-फेसिंग एजेंट जो कई सेशन में चलते हैं। पर्सनलाइज़ेशन। प्राथमिकता ट्रैकिंग।

सीमा: तथ्य समय के साथ जमा होते हैं। पुराने तथ्य गलत व्यवहार पैदा कर सकते हैं (यूज़र ने अपनी पसंदीदा भाषा बदल ली; पुरानी प्राथमिकता अभी भी स्टोर में है)। तथ्यों को अपडेट या expire करने का तंत्र जोड़ें।

स्ट्रेटेजी 4: सिमेंटिक मेमोरी (वेक्टर सर्च)

एपिसोडिक मेमोरी अलग-अलग तथ्य संग्रहीत करती है। सिमेंटिक मेमोरी अर्थ के अनुसार इंडेक्स किए गए दस्तावेज़, कोड या बातचीत के अंश संग्रहीत करती है। जब एजेंट को जानकारी चाहिए, वह एक क्वेरी का उपयोग करके इंडेक्स खोजता है।

यही रिट्रीवल-ऑगमेंटेड जनरेशन (RAG) का आधार है।

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface Document {
id: string;
content: string;
embedding?: number[];
}
// दो वेक्टर के बीच कोसाइन समानता की गणना करें
function cosineSimilarity(a: number[], b: number[]): number {
const dot = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dot / (magA * magB);
}
class SemanticMemory {
private documents: Document[] = [];
// बाद में रिट्रीवल के लिए दस्तावेज़ इंडेक्स करें
async add(id: string, content: string): Promise<void> {
const embedding = await embed(content); // एक डेडिकेटेड एम्बेडिंग मॉडल इस्तेमाल करें
this.documents.push({ id, content, embedding });
}
// किसी क्वेरी के लिए सबसे प्रासंगिक k दस्तावेज़ रिट्रीव करें
async search(query: string, topK = 3): Promise<Document[]> {
const queryEmbedding = await embed(query);
return this.documents
.filter((doc) => doc.embedding)
.map((doc) => ({
doc,
score: cosineSimilarity(queryEmbedding, doc.embedding!),
}))
.sort((a, b) => b.score - a.score)
.slice(0, topK)
.map(({ doc }) => doc);
}
}
const memory = new SemanticMemory();
async function answerWithContext(question: string): Promise<string> {
// प्रासंगिक दस्तावेज़ रिट्रीव करें
const relevant = await memory.search(question);
const context = relevant.map((d) => d.content).join("\n\n---\n\n");
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: context
? `निम्नलिखित संदर्भ का उपयोग करके प्रश्न का उत्तर दें:\n\n${context}`
: undefined,
messages: [{ role: "user", content: question }],
});
return response.content[0].type === "text" ? response.content[0].text : "";
}
// उदाहरण: नॉलेज बेस इंडेक्स करें और क्वेरी करें
await memory.add("doc-1", "टीम React 18 और app router पैटर्न का उपयोग करती है।");
await memory.add("doc-2", "सभी API रूट को Zod स्कीमा के साथ इनपुट वैलिडेट करना होगा।");
await memory.add("doc-3", "डेटाबेस क्वेरी Drizzle ORM इस्तेमाल करती हैं। Raw SQL से बचें।");
const answer = await answerWithContext("मुझे नया API एंडपॉइंट कैसे लिखना चाहिए?");
// एजेंट doc-2 और doc-3 रिट्रीव करता है और एक आधारित उत्तर देता है

प्रोडक्शन उपयोग के लिए, इन-मेमोरी स्टोर को एक डेडिकेटेड वेक्टर डेटाबेस से बदलें। यदि आप पहले से PostgreSQL चलाते हैं तो Pgvector सबसे सरल विकल्प है। Chroma और Qdrant अच्छे स्टैंडअलोन विकल्प हैं।

कब इस्तेमाल करें: डॉक्यूमेंटेशन असिस्टेंट। कोड सर्च एजेंट। नॉलेज बेस प्रश्नोत्तर।

मेमोरी को MCP से जोड़ना

यदि आपने MCP सर्वर गाइड का पालन किया है, तो आप मेमोरी को MCP संसाधन के रूप में एक्सपोज़ कर सकते हैं। यह आपकी मेमोरी लेयर को किसी भी MCP-संगत क्लाइंट के लिए accessible बनाता है।

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{ name: "memory-server", version: "1.0.0" },
{ capabilities: { tools: {}, resources: {} } }
);
// उपकरण: एक तथ्य स्टोर करें
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name === "remember") {
const { key, value, userId } = request.params.arguments as {
key: string;
value: string;
userId: string;
};
await storeEpisodicFact(userId, key, value);
return { content: [{ type: "text", text: `स्टोर किया: ${key} = ${value}` }] };
}
if (request.params.name === "recall") {
const { userId } = request.params.arguments as { userId: string };
const facts = await loadEpisodicFacts(userId);
return {
content: [{ type: "text", text: JSON.stringify(facts, null, 2) }],
};
}
});
const transport = new StdioServerTransport();
await server.connect(transport);

MCP बोलने वाला कोई भी एजेंट अब remember और recall को स्टैंडर्ड टूल के रूप में कॉल कर सकता है। मेमोरी प्रति-एजेंट इम्प्लीमेंटेशन की बजाय एक शेयर्ड सर्विस बन जाती है।

सही स्ट्रेटेजी चुनना

इस निर्णय तालिका को शुरुआती बिंदु के रूप में उपयोग करें:

स्थितिस्ट्रेटेजी
एकल सेशन, 20 से कम टर्नबफर
एकल सेशन, लंबे समय तक चलने वालासारांश
मल्टी-सेशन, यूज़र प्राथमिकताएंएपिसोडिक
क्वेरी के लिए बड़ा नॉलेज बेससिमेंटिक
उपरोक्त सभीसंयोजन: सेशन के लिए सारांश + सेशन के पार एपिसोडिक/सिमेंटिक

बफर से शुरू करें। जब बातचीत लंबी हो जाए तो सारांश लेयर जोड़ें। जब यूज़र कई सेशन में वापस आते हैं तो एपिसोडिक मेमोरी जोड़ें। जब आपके पास रिट्रीव करने के लिए दस्तावेज़ों का एक corpus हो तो सिमेंटिक मेमोरी जोड़ें।

ज़रूरत से पहले जटिलता न जोड़ें। ज़्यादातर प्रोटोटाइप के लिए कन्वर्सेशन बफर सही उत्तर है।

निष्कर्ष

मेमोरी एक अकेली चीज़ नहीं है — यह रणनीतियों का एक समूह है जो अलग-अलग दायरे में अलग-अलग समस्याओं का समाधान करता है। बफर वर्तमान सेशन को संभालता है। सारांश उस सेशन को बढ़ाता है। एपिसोडिक मेमोरी सेशन को जोड़ती है। सिमेंटिक मेमोरी उत्तरों को नॉलेज बेस में आधारित करती है।

वह लेयर चुनें जो आपकी आज की समस्या हल करे। इसे एक साफ इंटरफेस के पीछे लपेटें ताकि बाद में इम्प्लीमेंटेशन बदल सकें। और यदि आपके एजेंट MCP के माध्यम से संवाद करते हैं, तो मेमोरी को एक शेयर्ड टूल के रूप में एक्सपोज़ करें — यह हर एजेंट को सरल रखता है जबकि पूरे सिस्टम को एक स्थायी दिमाग देता है।


संबंधित लेख