Agent memory-এর ধরন ও VPS-এ খরচ
Semantic, episodic ও procedural agent memory-এর তুলনা এক সারণিতে। VPS-এ প্রতিটি ধরন সংরক্ষণ ও re-embed করতে কত খরচ হয়, বাস্তব হিসাবসহ জানুন।
এজেন্ট মেমরির তিনটি ধরন
এজেন্ট মেমরি তিন ভাগে বিভক্ত। প্রতিটি ধরনের মেমরি আপনার ব্যবহৃত হার্ডওয়্যারে আলাদা ধরনের খরচ তৈরি করে: semantic memory তথ্যমূলক তথ্য ধরে রাখে, episodic memory কী ঘটেছে তা ধরে রাখে, এবং procedural memory কোনো কাজ কীভাবে করতে হয় তা ধরে রাখে। নিচের সারণিতে server-এর একটি উদাহরণসহ প্রতিটি ধরন সংজ্ঞায়িত করা হয়েছে। এরপরের অংশে সাধারণত যে বিষয়টি বাদ পড়ে, তা ব্যাখ্যা করা হয়েছে: প্রতিটি ধরনের মেমরি সংরক্ষণ করতে কত খরচ হয় এবং পুনর্নির্মাণ করতে কত খরচ হয়।
The data behind this chart
[
{
"label": "Semantic",
"what_it_holds": "Facts the agent should treat as currently true",
"server_example": "The database listens on 10.8.0.4:5432 and the nightly dump runs at 03:15 UTC"
},
{
"label": "Episodic",
"what_it_holds": "A record of one past event or session",
"server_example": "On 2026-08-11 the deploy failed because the disk was full, and rotating logs fixed it"
},
{
"label": "Procedural",
"what_it_holds": "How to carry out a task, as steps the agent can run",
"server_example": "The restore runbook: stop the service, load the dump, run migrations, start the service"
}
]এই নামগুলো মানব মনোবিজ্ঞান থেকে নেওয়া, তবে ব্যবহারটি সরাসরি এক নয়। এই বিভাজনটি ব্যবহারিক কারণে গুরুত্বপূর্ণ: তিন ধরনের মেমরির আকার এবং পুনরুদ্ধারের পদ্ধতি আলাদা। তাই সবগুলোকে একই vector store-এ রাখলে প্রতিটি ধরনের কার্যকারিতা কমে যায়।
সেমান্টিক মেমরি ছোট, এবং আপনি এটি হাতে সম্পাদনা করতে চাইবেন
আপনার নিজের সার্ভার সম্পর্কে কয়েকশো তথ্যের আকার কয়েক দশ কিলোবাইটের বেশি নয়। এখানে storage সমস্যা নয়। সমস্যা হলো সংশোধন। সেমান্টিক মেমরিতে থাকা কোনো তথ্য ভুল হলে, এরপর agent-এর দেওয়া প্রতিটি উত্তরে সেটি ভুল থাকবে। তাই store-এ এমন ব্যবস্থা থাকতে হবে, যাতে নাম ধরে একটি তথ্য খুঁজে বের করা যায়, সেটি পরিবর্তন করা যায় এবং পুরোনো value আর নেই—এটি নিশ্চিত করা যায়।
এ কারণে keyed store ব্যবহার করা উপযুক্ত: primary key-সহ একটি Postgres table, অথবা git-এ থাকা ছোট ছোট markdown file-এর directory। উভয় ক্ষেত্রেই একটি query চালিয়ে value দেখা এবং সরাসরি সেটি সম্পাদনা করা যায়। Similarity search এ কাজের জন্য উপযুক্ত নয়, কারণ এটি key-এর বদলে সাদৃশ্য অনুযায়ী তথ্য খুঁজে আনে। "Change the database port" এর অর্থ তখন হয়ে যায় "find every chunk that mentions the database port", এবং সবগুলো পাওয়া গেছে কি না তা প্রমাণ করা যায় না। তথ্যগুলো keyed রাখুন। Loose recall-ও চাইলে সেগুলো embed করতে পারেন, তবে keyed copy-কেই সত্যের উৎস হিসেবে বিবেচনা করুন।
পুরোনো তথ্য নিজে থেকে শনাক্ত হয় না। Port পরিবর্তিত হলেও row একই থাকে, তাই agent জুন মাসে সঠিক থাকা একটি number দিয়েই উত্তর দিতে থাকে। agent memory-এর staleness এবং pruning policy এই পৃষ্ঠার অন্য অর্ধেক, এবং table ছোট থাকা অবস্থায় এটি নকশা করা অনেক কম ব্যয়বহুল।
সীমাহীনভাবে episodic memory বৃদ্ধি পাওয়ার কারণ
Episodic memory একটি log, আর log ক্রমেই বড় হয়। প্রতিটি session, প্রতিটি tool call এবং প্রতিটি ব্যর্থ command সম্ভাব্য episode। একটি agent যদি প্রতি turn-এ একটি করে row লেখে, তাহলে এক মাসে এমন অনেক বেশি row তৈরি হবে যা কখনো কেউ পড়বে না। খরচ শুধু disk-এর নয়: প্রতিটি embedded episode সেই index-এও যুক্ত হয়, যেটি search-কে পরীক্ষা করতে হয়।
Table তৈরি করার দিনই retention rule নির্ধারণ করুন, যখন deletion-এর খরচ এখনও নেই। দুটি প্রশ্নের উত্তর দিলেই বেশিরভাগ সিদ্ধান্ত নেওয়া যায়। প্রথমত, আদৌ কী লেখা মূল্যবান: একটি session-এর summary সাধারণত মূল্যবান, কিন্তু একটি ls -la-এর সম্পূর্ণ output সাধারণত নয়। দ্বিতীয়ত, প্রতিটি episode-এর শ্রেণি কতদিন থাকবে: যেমন raw episode 30 দিন এবং session summary এক বছর।
প্রতিটি episode row-এ একটি created_at timestamp এবং একটি source column রাখুন। created_at না থাকলে age অনুযায়ী deletion করা যায় না। source না থাকলে কোনো একটি ত্রুটিপূর্ণ origin থেকে আসা সবকিছু মুছে ফেলা যায় না। কোনো web page বা ticket memory-তে instruction লিখে দিচ্ছিল—এমন ঘটনা ধরা পড়ার দিন ঠিক এটিই প্রয়োজন হয়।
DELETE FROM episodes WHERE created_at < now() - interval '30 days';এটি একটি systemd timer থেকে চালান। এরপর row count এবং table size বাস্তবে কমছে বা বাড়ছে কি না পর্যবেক্ষণ করুন। কেউ প্রয়োগ না করলে retention policy কেবল একটি comment হয়ে থাকে।
psql -d agentmem -c "SELECT count(*) FROM episodes;"
psql -d agentmem -c "SELECT pg_size_pretty(pg_total_relation_size('episodes'));"Procedural memory repository-তে রাখা উচিত
Procedural memory হলো agent কীভাবে একটি কাজ করে: একটি shell script, একটি skill file, অথবা numbered step-সহ একটি runbook। এগুলো code, আর code code যেখানে থাকে সেখানেই থাকা উচিত—review, version এবং পড়া যায় এমন diff-সহ একটি git repository-তে।
একটি runbook embedded chunk হিসেবে সংরক্ষণ করলে পরে তার আনুমানিক একটি অনুলিপি পাওয়া যায়। Retrieval-এ সর্বোচ্চ score পাওয়া chunk-গুলো ফেরত আসে। ফলে agent step 2 এবং step 5 অনুযায়ী কাজ করতে পারে, কিন্তু step 3 কখনও সামনে নাও আসতে পারে। কোন version-এর procedure চালানো হয়েছে, তারও কোনো রেকর্ড থাকে না। git-এ git log উভয় প্রশ্নের উত্তর দেয়। Storage cost প্রায় শূন্য। এটিই vector-এর জন্য মূল্য দেওয়া এড়ানোর আরেকটি কারণ।
ডিস্কে একটি embedding-এর প্রকৃত খরচ
The data behind this chart
[
{
"label": "bge-small-en-v1.5 (384 dims)",
"bytes_per_vector": 1544,
"mib_per_100k_rows": 147.2
},
{
"label": "bge-base-en-v1.5 (768 dims)",
"bytes_per_vector": 3080,
"mib_per_100k_rows": 293.7
},
{
"label": "bge-large-en-v1.5 (1024 dims)",
"bytes_per_vector": 4104,
"mib_per_100k_rows": 391.4
},
{
"label": "text-embedding-3-small (1536 dims)",
"bytes_per_vector": 6152,
"mib_per_100k_rows": 586.7
},
{
"label": "text-embedding-3-large (3072 dims)",
"bytes_per_vector": 12296,
"mib_per_100k_rows": 1172.6
}
]pgvector একটি vector-কে প্রতি dimension-এ 4 bytes এবং একটি 8 byte header হিসেবে সংরক্ষণ করে। তাই এই হিসাব নির্দিষ্ট, এবং কিছু load করার আগেই এর জন্য পরিকল্পনা করা যায়। 384 dimension-এর একটি vector-এর আকার 1544 bytes। ফলে 100,000 chunk-এর vector-এর আকার হয় 147.2 MiB। একই corpus 3,072 dimension-এ embed করলে আকার হয় 1172.6 MiB, অর্থাৎ প্রতি row-তে 12296 bytes। Text একই, কিন্তু storage প্রায় আট গুণ।
এটি শুধু vector column-এর হিসাব। এর সঙ্গে chunk text, primary key, row overhead এবং index-এর আকার যোগ হয়। মানুষ সাধারণত index-এর বিষয়টি ভুলে যায়। HNSW (hierarchical navigable small world, pgvector যে graph index তৈরি করে) যেসব vector-এর মধ্যে link তৈরি করে, সেগুলোর নিজস্ব copy রাখে। তাই indexed store-এর প্রকৃত আকার উপরের হিসাবের দ্বিগুণের চেয়েও বেশি হয়। অনুমান না করে আপনার নিজের storage মাপুন।
SELECT pg_size_pretty(pg_total_relation_size('memories')) AS total,
pg_size_pretty(pg_relation_size('memories_embedding_idx')) AS idx;Search দ্রুত মনে হবে কি না, তা RAM নির্ধারণ করে। কারণ graph memory-তে থাকলেই সেটি দ্রুত traverse করা যায়। Postgres যে পরিমাণ index memory-তে রাখতে পারে, index তার চেয়ে বড় হলে search disk থেকে পড়া শুরু করে এবং latency বাড়ে। Build-এরও নিজস্ব limit আছে, maintenance_work_mem। Graph এই limit ছাড়িয়ে গেলে build তা জানায় এবং ধীর হয়ে যায়:
NOTICE: hnsw graph no longer fits into maintenance_work_mem after 61440 tuples
HINT: Increase maintenance_work_mem to speed up builds.একই corpus-এর আকার কমানোর দুটি উপায় আছে। ছোট model বেছে নিন। 384 dimension, 1,536 dimension-এর এক-চতুর্থাংশ storage নেয়। নিজের notes আবার খুঁজে পাওয়ার ক্ষেত্রে accuracy-এর পার্থক্য প্রায়ই গ্রহণযোগ্যভাবে ছোট থাকে। অথবা half precision ব্যবহার করুন। halfvec type প্রতি dimension-এ 2 bytes এবং একই 8 byte header নেয়। এতে column এবং তার index—দুটির সম্মিলিত আকার প্রায় অর্ধেক হয়ে যায়।
Model বেছে নেওয়ার আগে একটি limit জানা দরকার। August 2026 অনুযায়ী, একটি vector column-এ সর্বোচ্চ 2,000 dimension পর্যন্ত index তৈরি করা যায়। তাই 3,072 dimension-এর embedding column গ্রহণ করে, কিন্তু index গ্রহণ করে না:
ERROR: column cannot have more than 2000 dimensions for hnsw indexhalfvec সর্বোচ্চ 4,000 dimension পর্যন্ত index তৈরি করে। তাই সাধারণ সমাধান হলো cast করা মানের ওপর index তৈরি করা:
CREATE INDEX ON memories USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);pgvector কখন আলাদা memory service-এর চেয়ে ভালো
সার্ভারে যদি ইতিমধ্যে Postgres চলে, তাহলে vector সংরক্ষণে একটি package এবং একটি statement-ই যথেষ্ট।
psql -V
sudo apt install postgresql-16-pgvectorCREATE EXTENSION vector;package name-এর সংখ্যাটি আপনার Postgres major version। Ubuntu 24.04-এ এটি 16। তাই package ইনস্টল করার আগে psql -V পড়ুন।
একই database-এ memory রাখলে একই সময়ে memory এবং application data-এর জন্য একটি backup নেওয়া যায়, একটি connection pool ব্যবহার করা যায়, এবং transaction সুবিধা পাওয়া যায়: কোনো তথ্য এবং সেই তথ্যের বর্ণনাকারী row একসঙ্গে commit হবে, অথবা একসঙ্গে ব্যর্থ হবে। আলাদা service এই নিশ্চয়তা দিতে পারে না।
নিচের যেকোনো একটি শর্ত সত্য হলে dedicated memory service ব্যবহার করুন। Search load আপনার application-এর সঙ্গে resource নিয়ে প্রতিযোগিতা করছে এবং তার জন্য আলাদা machine প্রয়োজন। একাধিক host-এর একাধিক agent একই memory ব্যবহার করছে। অথবা আপনি এমন extraction এবং deduplication logic চান, যা একটি পূর্ণাঙ্গ product-এর সঙ্গে অন্তর্ভুক্ত থাকে। এই কারণেই self-hosted Mem0 memory server ব্যবহার করা যুক্তিযুক্ত। একটি agent এবং কয়েক million chunk-এর কম corpus-এর ক্ষেত্রে, আপনি ইতিমধ্যে যে সার্ভার চালাচ্ছেন তাতে pgvector ব্যবহার করা পরিচালনা করা সহজ এবং সমস্যার ঝুঁকিও কম। কোন engine বেছে নেবেন এবং প্রতিটি engine-এর কত RAM প্রয়োজন, তা VPS-এ vector database চালানো-এ ব্যাখ্যা করা হয়েছে।
মডেল পরিবর্তন করলে পুনরায় embedding করার খরচ
দুটি ভিন্ন মডেলের vector পরস্পরের সঙ্গে তুলনীয় নয়। তাই নতুন মডেল দিয়ে নতুন memory-এর embedding তৈরি করে পুরোনো row অপরিবর্তিত রাখা যায় না। মিশ্র table ভুল ফল দেয়, কারণ দুটি ভিন্ন coordinate system-এর মধ্যে গণনা করা distance-এর কোনো অর্থ নেই। মডেল পরিবর্তন করলে পুরো corpus-এর পুনরায় embedding করতে হয়।
এই খরচের 4টি অংশ রয়েছে: token-এর খরচ (API charge, অথবা নিজের server-এ CPU ও GPU time), প্রক্রিয়া চলাকালীন wall-clock time, backfill চলার সময় উভয় column একসঙ্গে রাখার জন্য disk space, এবং শেষে index rebuild। নিরাপদ ক্রম হলো: নতুন column যোগ করা, batch অনুযায়ী সেটিতে backfill করা, query নতুন column-এ পরিবর্তন করা, তারপর পুরোনো column ও তার index মুছে ফেলা।
প্রকাশিত কোনো figure-এর ওপর নির্ভর না করে নিজের hardware-এ rate পরিমাপ করুন। কারণ ছোট VPS-এ CPU-only embedding একই মডেল GPU-তে চালানোর তুলনায় অনেক ধীর হয়। একটি প্রতিনিধিত্বমূলক chunk-এর সময় মাপুন। তারপর corpus-এর আকার দিয়ে গুণ করুন।
ollama pull nomic-embed-text
time curl -s http://localhost:11434/api/embed \
-d '{"model": "nomic-embed-text", "input": "one representative chunk of your corpus"}' > /dev/nullএকটি local embedding model-এর weights memory store-এর একই disk-এও থাকে। Ollama কোন জায়গায় pulled model সংরক্ষণ করে-এ সেই space কোথায় ব্যবহৃত হয় তা ব্যাখ্যা করা হয়েছে।
সবকিছু সম্ভব করার জন্য একটি requirement রয়েছে: প্রতিটি vector-এর পাশে source text রাখুন। শুধু vector সংরক্ষণ করা store থেকে পুনরায় embedding করা যায় না, কারণ নতুন model-এ দেওয়ার মতো কোনো text অবশিষ্ট থাকে না। “এই row তৈরি করতে কোন text ব্যবহৃত হয়েছিল?”—এই প্রশ্নের উত্তর দিতে না পারলে migration path হলো text প্রথমবার যেখান থেকে এসেছিল, সেখান থেকে সম্পূর্ণ rebuild করা।
মেমরি চালু হলে যা পর্যবেক্ষণ করবেন
স্টোর পূর্ণ হওয়ার সঙ্গে সঙ্গে শুধু খরচই পরিবর্তিত হয় না। পুরোনো তথ্যের প্রাসঙ্গিকতা কমে যায় এবং পুরোনো ঘটনার রেকর্ড দরকারি ফলাফলকে আড়াল করে। এটিই আবার pruning-এর সমস্যা। মেমরি স্টোর agent-এর ভবিষ্যৎ আচরণের জন্য একটি writable input-ও। তাই এতে লেখার অনুমতি পাওয়া যেকোনো কিছু পরে agent-এর আচরণ প্রভাবিত করতে পারে। ওয়েব পেজ বা ticket-এর text যদি memory-তে পৌঁছায়, কীভাবে agent memory poisoning কাজ করে তা পড়ে নিন। এরপর কোন উৎস memory-তে লিখতে পারবে সেই পরিধি বাড়ান। প্রতিটি request-এ retrieval size token খরচও নির্ধারণ করে। এখান থেকেই agent-এর চলমান খরচ কীভাবে পূর্বানুমানযোগ্য রাখা যায় সেই বিষয়টি শুরু হয়।
FAQ
এজেন্টের memory-এর জন্য কি vector database দরকার?
তথ্যের জন্য নয়। Semantic memory ছোট এবং আপনাকে নাম ধরে তা সংশোধন করতে হয়। তাই keyed table বা git-এ থাকা markdown ফাইলের directory এ ক্ষেত্রে বেশি উপযোগী, কারণ আপনি একটি value দেখে সম্পাদনা করতে পারেন। যখন তালিকা করার পক্ষে corpus অতিরিক্ত বড় এবং অর্থের ভিত্তিতে তথ্য retrieve করতে হয়, তখন embeddings-এর খরচ সার্থক হয়। এটি সাধারণত episodic memory এবং document-এর ক্ষেত্রে প্রযোজ্য। আপনি যদি ইতিমধ্যে Postgres চালান, তাহলে আরেকটি service পরিচালনার প্রয়োজন ছাড়াই CREATE EXTENSION vector এই কাজটি করে।
এজেন্টের memory store কতটা disk ব্যবহার করবে?
pgvector-এ vector-এর আকার অনুমানযোগ্য: প্রতি dimension-এ 4 bytes, সঙ্গে 8 byte header। 768 dimension-এ প্রতি 100,000 row-তে 293.7 MiB এবং 384 dimension-এ 147.2 MiB লাগে। এর সঙ্গে chunk text, row overhead এবং HNSW index-এর storage যোগ করতে হবে। HNSW index vector-এর নিজস্ব copy রাখে। তাই vector-এর হিসাবের অন্তত দ্বিগুণ storage ধরে budget করুন এবং pg_total_relation_size দিয়ে প্রকৃত পরিমাণ মাপুন।
Procedural memory কোথায় রাখা উচিত?
git repository-তে, script বা skill file হিসেবে, যেগুলো এজেন্ট সরাসরি চালায়। একটি procedure-এর জন্য exact recall এবং version history দরকার। Similarity search কোনোটিই দেয় না। Chunk করা runbook থেকে সর্বোচ্চ score পাওয়া অংশগুলো ফিরে আসে। এতে step 2 এবং step 5 আসতে পারে, কিন্তু step 3 অনুপস্থিত থাকতে পারে। কোন version চালানো হয়েছে, তারও কোনো record থাকে না।
Embedding model পরিবর্তনের খরচ কী?
পুরো corpus আবার re-embed করতে হবে, কারণ ভিন্ন model-এর vector একে অপরের সঙ্গে তুলনা করা যায় না। Token charge বা GPU time, একই সময়ে পুরনো ও নতুন column রাখার জন্য disk এবং index rebuild-এর খরচ ধরুন। নতুন column যোগ করুন, batch অনুযায়ী backfill করুন, query-টি নতুন column-এ পরিবর্তন করুন, তারপর পুরনো column drop করুন। এই পুরো প্রক্রিয়ার জন্য প্রতিটি vector-এর পাশে source text সংরক্ষিত থাকতে হবে।