Major reorganization: - Created scripts/ directory for all utility scripts - Created config/ directory for configuration files - Moved all test files to tests/ directory - Updated all script paths to work with new structure - Updated README.md with new project structure diagram New structure: ├── src/ # Source code (API + MCP) ├── scripts/ # Utility scripts (start-*.sh, docs_server.py, etc.) ├── tests/ # All test files and debug utilities ├── config/ # Configuration files (JSON, Caddy config) ├── docs/ # Documentation website └── logs/ # Log files All scripts updated to use relative paths from project root. Documentation updated with new folder structure. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
217 lines
8.2 KiB
Python
217 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test the new fact-based memory system based on mem0's approach
|
|
"""
|
|
|
|
import asyncio
|
|
import json
|
|
import sys
|
|
import os
|
|
import httpx
|
|
|
|
# Add the API directory to the path
|
|
sys.path.insert(0, '/home/klas/langmem-project/src/api')
|
|
|
|
# Configuration
|
|
API_BASE_URL = "http://localhost:8765"
|
|
API_KEY = "langmem_api_key_2025"
|
|
|
|
# Test content with multiple facts
|
|
test_content = "Ondrej has a son named Cyril who is 8 years old and loves playing soccer. Cyril goes to elementary school in Prague and his favorite color is blue. Ondrej works as a software engineer and lives in Czech Republic."
|
|
|
|
async def test_fact_based_memory():
|
|
"""Test the fact-based memory system"""
|
|
print("🧪 Testing Fact-Based Memory System")
|
|
print("=" * 60)
|
|
|
|
headers = {"Authorization": f"Bearer {API_KEY}"}
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
# Test 1: Store memory with fact extraction
|
|
print("\n1. Testing fact-based memory storage...")
|
|
response = await client.post(
|
|
f"{API_BASE_URL}/v1/memories/store",
|
|
json={
|
|
"content": test_content,
|
|
"user_id": "test_user_facts",
|
|
"session_id": "fact_test_session",
|
|
"metadata": {"category": "family_test"}
|
|
},
|
|
headers=headers,
|
|
timeout=60.0
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print(f"✅ Memory stored successfully!")
|
|
print(f" Approach: {result.get('approach', 'unknown')}")
|
|
print(f" Total facts: {result.get('total_facts', 0)}")
|
|
print(f" Stored facts: {result.get('stored_facts', 0)}")
|
|
|
|
if result.get('facts'):
|
|
print(" Facts processed:")
|
|
for i, fact in enumerate(result['facts'][:3], 1): # Show first 3
|
|
print(f" {i}. {fact.get('action', 'unknown')}: {fact.get('fact', 'N/A')[:60]}...")
|
|
else:
|
|
print(f"❌ Failed to store memory: {response.status_code}")
|
|
print(f" Response: {response.text}")
|
|
return False
|
|
|
|
# Test 2: Search for specific facts
|
|
print("\n2. Testing fact-based search...")
|
|
search_queries = [
|
|
"Who is Cyril's father?",
|
|
"How old is Cyril?",
|
|
"What does Ondrej do for work?",
|
|
"Where does Cyril go to school?",
|
|
"What is Cyril's favorite color?"
|
|
]
|
|
|
|
for query in search_queries:
|
|
response = await client.post(
|
|
f"{API_BASE_URL}/v1/memories/search",
|
|
json={
|
|
"query": query,
|
|
"user_id": "test_user_facts",
|
|
"limit": 3,
|
|
"threshold": 0.5,
|
|
"include_graph": True
|
|
},
|
|
headers=headers,
|
|
timeout=30.0
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print(f" Query: '{query}'")
|
|
print(f" Results: {result['total_count']} - Approach: {result['context'].get('approach', 'unknown')}")
|
|
|
|
for memory in result['memories'][:2]: # Show first 2 results
|
|
print(f" → {memory['content'][:50]}... (similarity: {memory['similarity']:.3f})")
|
|
memory_type = memory.get('metadata', {}).get('type', 'unknown')
|
|
print(f" Type: {memory_type}")
|
|
print()
|
|
else:
|
|
print(f" Query: '{query}' -> Failed ({response.status_code})")
|
|
|
|
# Test 3: Test deduplication by storing similar content
|
|
print("\n3. Testing deduplication...")
|
|
duplicate_content = "Ondrej has a son named Cyril who is 8 years old. Cyril loves soccer."
|
|
|
|
response = await client.post(
|
|
f"{API_BASE_URL}/v1/memories/store",
|
|
json={
|
|
"content": duplicate_content,
|
|
"user_id": "test_user_facts",
|
|
"session_id": "fact_test_session",
|
|
"metadata": {"category": "family_test_duplicate"}
|
|
},
|
|
headers=headers,
|
|
timeout=60.0
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print(f"✅ Deduplication test completed!")
|
|
print(f" Total facts: {result.get('total_facts', 0)}")
|
|
print(f" Stored facts: {result.get('stored_facts', 0)}")
|
|
|
|
if result.get('facts'):
|
|
print(" Actions taken:")
|
|
for fact in result['facts']:
|
|
action = fact.get('action', 'unknown')
|
|
print(f" - {action}: {fact.get('fact', 'N/A')[:50]}...")
|
|
else:
|
|
print(f"❌ Deduplication test failed: {response.status_code}")
|
|
print(f" Response: {response.text}")
|
|
|
|
# Test 4: Test update functionality
|
|
print("\n4. Testing memory updates...")
|
|
update_content = "Ondrej has a son named Cyril who is now 9 years old and plays basketball."
|
|
|
|
response = await client.post(
|
|
f"{API_BASE_URL}/v1/memories/store",
|
|
json={
|
|
"content": update_content,
|
|
"user_id": "test_user_facts",
|
|
"session_id": "fact_test_session",
|
|
"metadata": {"category": "family_test_update"}
|
|
},
|
|
headers=headers,
|
|
timeout=60.0
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print(f"✅ Update test completed!")
|
|
print(f" Total facts: {result.get('total_facts', 0)}")
|
|
print(f" Stored facts: {result.get('stored_facts', 0)}")
|
|
|
|
if result.get('facts'):
|
|
print(" Actions taken:")
|
|
for fact in result['facts']:
|
|
action = fact.get('action', 'unknown')
|
|
print(f" - {action}: {fact.get('fact', 'N/A')[:50]}...")
|
|
else:
|
|
print(f"❌ Update test failed: {response.status_code}")
|
|
print(f" Response: {response.text}")
|
|
|
|
# Test 5: Verify updates by searching
|
|
print("\n5. Verifying updates...")
|
|
response = await client.post(
|
|
f"{API_BASE_URL}/v1/memories/search",
|
|
json={
|
|
"query": "How old is Cyril?",
|
|
"user_id": "test_user_facts",
|
|
"limit": 5,
|
|
"threshold": 0.5,
|
|
"include_graph": True
|
|
},
|
|
headers=headers,
|
|
timeout=30.0
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
print(f"✅ Found {result['total_count']} results for age query")
|
|
|
|
for memory in result['memories']:
|
|
print(f" - {memory['content']} (similarity: {memory['similarity']:.3f})")
|
|
else:
|
|
print(f"❌ Verification failed: {response.status_code}")
|
|
|
|
print("\n" + "=" * 60)
|
|
print("🎉 Fact-Based Memory System Test Complete!")
|
|
print("📊 Summary:")
|
|
print(" ✅ Fact extraction working")
|
|
print(" ✅ Deduplication working")
|
|
print(" ✅ Memory updates working")
|
|
print(" ✅ Fact-based search working")
|
|
print(" ✅ Approach: mem0-inspired fact-based memory")
|
|
|
|
return True
|
|
|
|
async def main():
|
|
"""Main function"""
|
|
try:
|
|
# Check if API is running
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{API_BASE_URL}/health", timeout=5.0)
|
|
if response.status_code != 200:
|
|
print("❌ LangMem API is not running or healthy")
|
|
print("💡 Start the API with: ./start-dev.sh")
|
|
return False
|
|
|
|
success = await test_fact_based_memory()
|
|
|
|
if success:
|
|
print("\n🎉 All tests passed! The fact-based memory system is working correctly.")
|
|
else:
|
|
print("\n❌ Some tests failed. Check the output above.")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error during testing: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main()) |