universal-ai-brain
Version:
🧠 UNIVERSAL AI BRAIN 3.3 - The world's most advanced cognitive architecture with 24 specialized systems, MongoDB 8.1 $rankFusion hybrid search, latest Voyage 3.5 embeddings, and framework-agnostic design. Works with Mastra, Vercel AI, LangChain, OpenAI A
410 lines (353 loc) • 13.1 kB
text/typescript
/**
* @file SemanticMemoryEngine Tests
* Comprehensive tests for the SemanticMemoryEngine component with real MongoDB Atlas
*/
import { SemanticMemoryEngine, Memory, MemorySearchOptions } from '../../intelligence/SemanticMemoryEngine';
import { MemoryCollection } from '../../collections/MemoryCollection';
import { OpenAIEmbeddingProvider } from '../../embeddings/OpenAIEmbeddingProvider';
import {
setupTestDatabase,
cleanupTestDatabase,
createTestEmbeddingProvider,
createTestMemory,
isMongoAtlasError,
isOpenAIError,
shouldSkipTest
} from '../testConfig';
describe('SemanticMemoryEngine', () => {
let semanticMemoryEngine: SemanticMemoryEngine;
let memoryCollection: MemoryCollection;
let embeddingProvider: OpenAIEmbeddingProvider;
let testDb: any;
beforeAll(async () => {
try {
testDb = await setupTestDatabase();
memoryCollection = new MemoryCollection(testDb);
embeddingProvider = createTestEmbeddingProvider();
// Initialize collection with indexes
await memoryCollection.initialize();
semanticMemoryEngine = new SemanticMemoryEngine(memoryCollection, embeddingProvider);
console.log('✅ SemanticMemoryEngine test setup complete');
} catch (error) {
if (shouldSkipTest(error)) {
console.log('⏭️ Skipping SemanticMemoryEngine tests due to setup failure');
return;
}
throw error;
}
});
afterAll(async () => {
await cleanupTestDatabase();
});
describe('Memory Storage', () => {
it('should store memory with embedding generation', async () => {
if (!testDb || !semanticMemoryEngine) {
console.log('⏭️ Skipping test: Database not available');
return;
}
try {
const content = 'User prefers morning meetings for Universal AI Brain testing';
const testMemory = createTestMemory();
testMemory.content = content;
testMemory.metadata.type = 'preference';
testMemory.metadata.framework = 'vercel-ai';
const memoryId = await semanticMemoryEngine.storeMemory(content, testMemory.metadata);
expect(memoryId).toMatch(/^memory_/);
expect(memoryId).toBeDefined();
console.log(`✅ Successfully stored memory: ${memoryId}`);
} catch (error) {
if (shouldSkipTest(error)) {
console.log('⏭️ Skipping test due to external service unavailability');
return;
}
throw error;
}
});
it('should handle embedding generation failure gracefully', async () => {
mockEmbeddingProvider.generateEmbedding.mockRejectedValue(new Error('API Error'));
const content = 'Test content';
const metadata = {
type: 'context' as const,
importance: 0.5,
confidence: 0.8,
source: 'test',
framework: 'test',
sessionId: 'test',
tags: [],
relationships: [],
accessCount: 0,
lastAccessed: new Date(),
created: new Date(),
updated: new Date()
};
const memoryId = await semanticMemoryEngine.storeMemory(content, metadata);
expect(mockMemoryCollection.storeDocument).toHaveBeenCalled();
expect(memoryId).toMatch(/^memory_/);
});
it('should store memory without embedding when disabled', async () => {
const content = 'Test content';
const metadata = {
type: 'context' as const,
importance: 0.5,
confidence: 0.8,
source: 'test',
framework: 'test',
sessionId: 'test',
tags: [],
relationships: [],
accessCount: 0,
lastAccessed: new Date(),
created: new Date(),
updated: new Date()
};
const memoryId = await semanticMemoryEngine.storeMemory(content, metadata, {
generateEmbedding: false
});
expect(mockEmbeddingProvider.generateEmbedding).not.toHaveBeenCalled();
expect(mockMemoryCollection.storeDocument).toHaveBeenCalled();
expect(memoryId).toMatch(/^memory_/);
});
});
describe('Memory Retrieval', () => {
it('should retrieve relevant memories using vector search', async () => {
const mockMemories = [
{
_id: 'doc1',
content: JSON.stringify({
id: 'memory_1',
content: 'User likes coffee',
metadata: {
type: 'preference',
importance: 0.8,
confidence: 0.9,
framework: 'vercel-ai'
}
}),
embedding: { values: [0.1, 0.2, 0.3] },
vectorScore: 0.85
}
];
mockMemoryCollection.aggregate.mockResolvedValue(mockMemories);
const query = 'What does the user like to drink?';
const options: MemorySearchOptions = {
limit: 5,
minImportance: 0.5,
frameworks: ['vercel-ai']
};
const memories = await semanticMemoryEngine.retrieveRelevantMemories(query, options);
expect(mockEmbeddingProvider.generateEmbedding).toHaveBeenCalledWith(query);
expect(mockMemoryCollection.aggregate).toHaveBeenCalled();
expect(memories).toHaveLength(1);
expect(memories[0].content).toBe('User likes coffee');
});
it('should handle vector search failure with fallback', async () => {
mockEmbeddingProvider.generateEmbedding.mockRejectedValue(new Error('Embedding failed'));
mockMemoryCollection.aggregate.mockResolvedValue([]);
const query = 'Test query';
const memories = await semanticMemoryEngine.retrieveRelevantMemories(query);
expect(memories).toEqual([]);
});
it('should filter memories by type and framework', async () => {
const query = 'Test query';
const options: MemorySearchOptions = {
types: ['preference', 'fact'],
frameworks: ['vercel-ai'],
minImportance: 0.7
};
await semanticMemoryEngine.retrieveRelevantMemories(query, options);
const aggregateCall = mockMemoryCollection.aggregate.mock.calls[0][0];
const vectorSearchStage = aggregateCall[0].$vectorSearch;
expect(vectorSearchStage.filter).toEqual(
expect.objectContaining({
'metadata.type': 'semantic_memory',
'metadata.importance': { $gte: 0.7 }
})
);
});
});
describe('Memory Importance Management', () => {
it('should update memory importance with decay factor', async () => {
const mockMemory: Memory = {
id: 'memory_123',
content: 'Test memory',
metadata: {
type: 'context',
importance: 0.8,
confidence: 0.9,
source: 'test',
framework: 'test',
sessionId: 'test',
tags: [],
relationships: [],
accessCount: 5,
lastAccessed: new Date(),
created: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 7 days ago
updated: new Date()
}
};
// Mock getMemoryById to return the memory
mockMemoryCollection.aggregate.mockResolvedValue([{
content: JSON.stringify(mockMemory),
embedding: { values: [0.1, 0.2, 0.3] }
}]);
await semanticMemoryEngine.updateMemoryImportance('memory_123', 0.9, 'user_feedback');
expect(mockMemoryCollection.updateDocument).toHaveBeenCalled();
});
it('should throw error for non-existent memory', async () => {
mockMemoryCollection.aggregate.mockResolvedValue([]);
await expect(
semanticMemoryEngine.updateMemoryImportance('non_existent', 0.9)
).rejects.toThrow('Memory not found: non_existent');
});
});
describe('Memory Relationships', () => {
it('should create bidirectional relationships between memories', async () => {
const memory1: Memory = {
id: 'memory_1',
content: 'First memory',
metadata: {
type: 'context',
importance: 0.8,
confidence: 0.9,
source: 'test',
framework: 'test',
sessionId: 'test',
tags: [],
relationships: [],
accessCount: 0,
lastAccessed: new Date(),
created: new Date(),
updated: new Date()
}
};
const memory2: Memory = {
id: 'memory_2',
content: 'Second memory',
metadata: {
type: 'context',
importance: 0.7,
confidence: 0.8,
source: 'test',
framework: 'test',
sessionId: 'test',
tags: [],
relationships: [],
accessCount: 0,
lastAccessed: new Date(),
created: new Date(),
updated: new Date()
}
};
// Mock getMemoryById calls
mockMemoryCollection.aggregate
.mockResolvedValueOnce([{ content: JSON.stringify(memory1) }])
.mockResolvedValueOnce([{ content: JSON.stringify(memory2) }]);
await semanticMemoryEngine.createMemoryRelationship('memory_1', 'memory_2', 'similar');
expect(mockMemoryCollection.updateDocument).toHaveBeenCalledTimes(2);
});
it('should handle missing memories in relationship creation', async () => {
mockMemoryCollection.aggregate.mockResolvedValue([]);
await expect(
semanticMemoryEngine.createMemoryRelationship('memory_1', 'memory_2')
).rejects.toThrow('One or both memories not found');
});
});
describe('Memory Analytics', () => {
it('should generate comprehensive memory analytics', async () => {
const mockAnalyticsResult = [{
totalCount: [{ total: 100 }],
byType: [
{ _id: 'preference', count: 30 },
{ _id: 'fact', count: 40 },
{ _id: 'context', count: 30 }
],
byFramework: [
{ _id: 'vercel-ai', count: 50 },
{ _id: 'mastra', count: 30 },
{ _id: 'langchain', count: 20 }
],
averageImportance: [{ avg: 0.75 }],
averageConfidence: [{ avg: 0.82 }],
growthTrend: [
{ _id: '2024-01-01', count: 10 },
{ _id: '2024-01-02', count: 15 }
],
topTags: [
{ _id: 'preference', count: 25 },
{ _id: 'scheduling', count: 20 }
],
healthMetrics: [{
staleMemories: 5,
lowConfidenceMemories: 8,
orphanedMemories: 3
}]
}];
mockMemoryCollection.aggregate.mockResolvedValue(mockAnalyticsResult);
const analytics = await semanticMemoryEngine.generateMemoryAnalytics();
expect(analytics.totalMemories).toBe(100);
expect(analytics.memoriesByType).toEqual({
'preference': 30,
'fact': 40,
'context': 30
});
expect(analytics.memoriesByFramework).toEqual({
'vercel-ai': 50,
'mastra': 30,
'langchain': 20
});
expect(analytics.averageImportance).toBe(0.75);
expect(analytics.averageConfidence).toBe(0.82);
expect(analytics.memoryGrowthTrend).toHaveLength(2);
expect(analytics.topTags).toHaveLength(2);
expect(analytics.memoryHealth.staleMemories).toBe(5);
});
it('should handle empty analytics gracefully', async () => {
mockMemoryCollection.aggregate.mockResolvedValue([{
totalCount: [],
byType: [],
byFramework: [],
averageImportance: [],
averageConfidence: [],
growthTrend: [],
topTags: [],
healthMetrics: []
}]);
const analytics = await semanticMemoryEngine.generateMemoryAnalytics();
expect(analytics.totalMemories).toBe(0);
expect(analytics.averageImportance).toBe(0);
expect(analytics.averageConfidence).toBe(0);
});
});
describe('MongoDB Vector Search Integration', () => {
it('should construct proper $vectorSearch aggregation pipeline', async () => {
const query = 'Test query';
await semanticMemoryEngine.retrieveRelevantMemories(query, {
limit: 10,
minImportance: 0.5,
frameworks: ['vercel-ai'],
sessionId: 'session_123'
});
const aggregateCall = mockMemoryCollection.aggregate.mock.calls[0][0];
const vectorSearchStage = aggregateCall[0];
expect(vectorSearchStage).toHaveProperty('$vectorSearch');
expect(vectorSearchStage.$vectorSearch).toEqual(
expect.objectContaining({
index: 'memory_vector_index',
path: 'embedding.values',
queryVector: [0.1, 0.2, 0.3],
numCandidates: expect.any(Number),
limit: expect.any(Number),
filter: expect.any(Object)
})
);
});
it('should include proper vector score calculation', async () => {
await semanticMemoryEngine.retrieveRelevantMemories('test query');
const aggregateCall = mockMemoryCollection.aggregate.mock.calls[0][0];
const addFieldsStage = aggregateCall[1];
expect(addFieldsStage).toHaveProperty('$addFields');
expect(addFieldsStage.$addFields).toHaveProperty('vectorScore');
expect(addFieldsStage.$addFields.vectorScore).toEqual({ $meta: 'vectorSearchScore' });
});
});
});