Ultimate AI Memory System with Vector + Graph + Temporal Decay
npm install remina-v2The best-in-class AI memory system with unified Vector + Graph storage, temporal decay, and intelligent memory consolidation.
- Hybrid Storage: Vector (Milvus) + Graph (FalkorDB) for both semantic and relational queries
- Temporal Decay: Memories fade over time, frequently accessed ones stay strong
- Memory Consolidation: LLM-based ADD/UPDATE/DELETE decisions prevent duplicates
- Two-Tier Caching: Redis L1 cache + PostgreSQL L2 storage
- Hybrid Search: RRF fusion of vector, fulltext, and graph results
- Intent Detection: Smart query routing based on query patterns
| Component | Technology | Purpose |
|-----------|------------|---------|
| L1 Cache | Redis | Hot memories, session context |
| L2 Storage | PostgreSQL | Source of truth, full records |
| Vector | Milvus | Semantic search, embeddings |
| Graph | FalkorDB | Entity-relationship traversal |
| LLM | OpenAI | Fact extraction, consolidation |
``bash`
cd remina-v2
docker-compose up -d
`bash`
npm install remina
`typescript
import { Memory } from 'remina';
const memory = new Memory({
postgres: { connectionString: 'postgresql://remina:remina@localhost:5432/remina' },
redis: { url: 'redis://localhost:6379' },
milvus: { address: 'localhost:19530' },
falkordb: { url: 'redis://localhost:6380' },
openaiApiKey: process.env.OPENAI_API_KEY!,
});
// Add memories from conversation
await memory.add([
{ role: 'user', content: 'My name is Bob. I run Merkle Palace hotel.' },
{ role: 'assistant', content: 'Nice to meet you Bob!' },
{ role: 'user', content: 'The hotel has three room types: Deluxe, Standard, and Heritage.' },
], 'user-123');
// Search - works for both semantic AND relational queries
const results = await memory.search('What room types does Merkle Palace have?', 'user-123');
console.log(results.memories);
// [{ content: 'Merkle Palace has three room types: Deluxe, Standard, and Heritage', ... }]
console.log(results.relations);
// [
// { source: 'Merkle Palace', relationship: 'HAS_ROOM_TYPE', target: 'Deluxe', fact: '...' },
// { source: 'Merkle Palace', relationship: 'HAS_ROOM_TYPE', target: 'Standard', fact: '...' },
// { source: 'Merkle Palace', relationship: 'HAS_ROOM_TYPE', target: 'Heritage', fact: '...' },
// ]
// Clean up
await memory.close();
`
`typescript
class Memory {
constructor(config: MemoryConfig)
// Core operations
add(messages: string | Message[], userId: string): Promise
search(query: string, userId: string, limit?: number): Promise
get(memoryId: string): Promise
getAll(userId: string, limit?: number): Promise
update(memoryId: string, content: string): Promise
delete(memoryId: string): Promise
deleteAll(userId: string): Promise
// Graph operations
getEntity(entityId: string): Promise
getEntities(userId: string, limit?: number): Promise
getRelationships(userId: string, limit?: number): Promise
traverse(entityId: string, hops?: number): Promise
// Lifecycle
close(): Promise
}
`
`typescript
interface MemoryConfig {
// Required connections
postgres: { connectionString: string }
redis: { url: string }
milvus: { address: string; token?: string }
falkordb: { url: string }
// LLM
openaiApiKey: string
openaiModel?: string // Default: 'gpt-4o-mini'
embeddingModel?: string // Default: 'text-embedding-3-small'
// Optional tuning
decay?: {
halfLifeDays?: number // Default: 30
frequencyBoost?: number // Default: 0.1
importanceWeight?: number // Default: 0.3
}
cache?: {
memoryTtlSeconds?: number // Default: 3600
searchTtlSeconds?: number // Default: 300
enabled?: boolean // Default: true
}
}
`
1. Extract Facts: LLM extracts memorable facts from conversation
2. Consolidate: Compare with existing memories, decide ADD/UPDATE/DELETE
3. Extract Graph: LLM extracts entities and relationships
4. Store: Save to Postgres (L2), Milvus (vector), FalkorDB (graph), Redis (L1)
1. Check Cache: Redis L1 for recent queries
2. Parallel Search: Milvus (vector) + Postgres (fulltext) + FalkorDB (graph)
3. Rank: RRF fusion + temporal decay scoring
4. Return: Combined memories + relations
Memories decay exponentially over time:
``
score = base_score × e^(-λt)
Where:
- λ = ln(2) / halfLifeDayst = days since last access`
-
Frequently accessed memories get a logarithmic boost.
Apache-2.0