Distributed Databases & AI Agent Engineering Practice
Building Persistent Memory for an AI Agent With seekdb: From "Full Context" to "Precise Recall"
Posted onInAI ApplicationsViews: Word count in article: 1.5kReading time ≈5 mins.
This article explains how to build a vectorized persistent memory system for a Node.js AI Agent based on the seekdb-js SDK and Qwen3 Max (via OpenRouter), achieving precise recall through three strategies — threshold, fixed-count, and hybrid — with measured Token savings of 85%–95%.
This article explains how to use the seekdb-js SDK + Qwen3 Max (via OpenRouter) to implement an efficient vector memory system for a Node.js AI Agent.
Background: Why Are Traditional Memory Approaches Inefficient?
When using LangGraph or a custom AI Agent, persistent memory is a core requirement. However, traditional memory approaches have an obvious efficiency problem: they always pass the entire message history as context to the LLM, even when those messages are completely irrelevant to the current question.
For example: when you simply greet the Agent with a “hello,” the system still stuffs the entire content of the past 50 conversation turns into the prompt. This redundant information not only wastes Tokens but can also interfere with the quality of the model’s answers.
Real-world consequences:
Token costs skyrocket (measured at 10–20× the actual demand)
Response latency increases
The model’s attention is diluted, lowering answer quality
seekdb’s solution: Store messages as embedding vectors, and use vector similarity search to recall only the historical messages most relevant to the current question.
Explaining the Core Concepts
1. What Are Embedding Vectors?
Computers can’t understand human language; they can only process numbers. Embedding vectors convert text into a list of numeric values that capture semantic information.
For example: “I like watching AI tutorials” → [0.12, -0.45, 0.88, ...]
Qwen3 Embedding 8B generates 4096-dimensional vectors (note: not 1024-dimensional)
Semantically similar sentences have vectors that are closer together in the multidimensional space
2. Vector Similarity Search
If you directly ask a computer whether “I like watching AI tutorials” and “I love watching YouTube AI videos” are similar, it can’t answer. But if you compare their embedding vectors, the computer can compute a definite similarity score.
seekdb’s advantages:
Based on OceanBase, it supports large-scale vector data
Native support for vector storage and similarity search
/** * Get the Embedding dimension (supports configuration via environment variable) */ exportfunctiongetEmbeddingDimension() { constDEFAULT_DIMENSION = 4096; const raw = process.env.EMBEDDING_DIMENSION;
if (!raw) returnDEFAULT_DIMENSION;
const dim = parseInt(raw, 10); if (!Number.isInteger(dim) || dim <= 0) { console.warn(`[config] Invalid EMBEDDING_DIMENSION="${raw}", using ${DEFAULT_DIMENSION}`); returnDEFAULT_DIMENSION; }
asyncchat(userMessage) { // Smart detection: is this a query about personal information? const isProfileQuery = /\b(I am|I'm|my name|my job|my profession|good at|what do I do|who am I)\b/i.test(userMessage);
// Dynamically choose a recall strategy based on query type const recallOptions = isProfileQuery ? { strategy: 'limit', limit: 3, role: 'user' } // Personal-info query: only what the user has said : { strategy: 'threshold', threshold: 0.65, limit: 5, role: 'user' };
// Recall relevant history const relevantHistory = awaitthis.memory.recall(userMessage, recallOptions);
const systemPrompt = relevantHistory.length > 0 ? `Here is the conversation history relevant to the current question:\n${context}` : 'You are a helpful AI assistant.';
// Store the conversation awaitthis.memory.store('user', userMessage); awaitthis.memory.store('assistant', response);
return response; } }
// Usage example const agent = newChatAgent(); await agent.init();
await agent.chat('Hi, I am a programmer and I love writing code'); await agent.chat('What am I good at?'); // Can recall "programmer" and "writing code" await agent.chat('How is the weather in Beijing?'); // Irrelevant history is filtered out
Key Feature: Role Filtering
In real-world applications, we usually care only about what the user themselves has said, not the Agent’s replies. The role parameter makes this possible:
1 2 3 4 5 6
// Recall only what the user themselves has said const memories = await memory.recall('What is my name?', { strategy: 'limit', limit: 3, role: 'user', // Key: only query messages with the user role });
This is especially useful when handling personal-information queries, as it avoids recalling irrelevant content such as the Agent’s polite replies.
Effectiveness Comparison
Approach
Messages Passed
Token Consumption
Latency
Full context
995 messages
Baseline 100%
Slow
seekdb + Limit
5 messages
~5% (95% saved)
Fast
seekdb + Threshold
18 messages (dynamic)
~15% (85% saved)
Fast
Summary
Core insights:
The key to memory isn’t “how much you store,” but “how accurately you recall”
Vector similarity search is the ultimate solution for semantic memory
Dynamically choosing a recall strategy based on query type works better