Skip to content

Commit 21aab0e

Browse files
authored
Add files via upload
1 parent 1b7f8c1 commit 21aab0e

12 files changed

Lines changed: 2383 additions & 0 deletions

memoryos-chromadb/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .memoryos import Memoryos
2+
3+
__all__ = ['Memoryos']
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Complete Travel Planning Conversation Test Script
4+
Testing Memory System's Query Response Capability
5+
"""
6+
7+
import sys
8+
import os
9+
import json
10+
import time
11+
sys.path.append('.')
12+
13+
from memoryos import Memoryos
14+
15+
def main():
16+
print("=" * 60)
17+
print("🚀 MemoryOS Travel Planning Memory Test")
18+
print("=" * 60)
19+
20+
# Create Memoryos instance
21+
memoryos = Memoryos(
22+
user_id='travel_user_test',
23+
openai_api_key='',
24+
openai_base_url='',
25+
data_storage_path='./comprehensive_test_data',
26+
assistant_id='travel_assistant',
27+
embedding_model_name='BAAI/bge-m3',
28+
mid_term_capacity=1000,
29+
mid_term_heat_threshold=13.0,
30+
mid_term_similarity_threshold=0.7,
31+
short_term_capacity=2
32+
)
33+
34+
print("📝 Phase 1: Adding 30 rounds of travel planning conversations...")
35+
36+
# 30 rounds of rich travel planning conversations in English
37+
conversations = [
38+
# Basic information and travel preferences (1-10)
39+
("Hello, I want to plan a trip", "Hello! I'd be happy to help you plan your trip. Where would you like to travel?"),
40+
("My name is Emily, I'm 28 years old, and I'm a graphic designer", "Nice to meet you, Emily! As a graphic designer, you must have great aesthetic taste."),
41+
("I prefer artistic and cultural travel destinations", "Artistic places are very charming! Do you prefer historical culture or modern art?"),
42+
("I prefer historical culture, ancient architecture and museums", "Historical culture is very enriching! Have you considered European or Asian ancient cities?"),
43+
("I want to go to Japan, especially Kyoto and Nara", "Japan's ancient capitals are beautiful! Kyoto's temples and Nara's deer are very famous."),
44+
("I'm planning to go in October for about 7-10 days", "October is the best season to visit Japan! The autumn foliage season is beautiful."),
45+
("My budget is around 15,000-20,000 yuan", "That's a reasonable budget! We can arrange a very nice itinerary."),
46+
("I prefer niche places, don't want to go to overly commercialized spots", "I understand! You prefer experiencing local culture rather than tourist hotspots."),
47+
("Yes, I hope to deeply experience local life", "Deep travel is very meaningful! Would you like to try staying at a guesthouse or traditional inn?"),
48+
("I want to experience traditional Japanese ryokan", "Japanese ryokan are very special! Hot springs and kaiseki cuisine are worth experiencing."),
49+
50+
# Specific itinerary planning (11-20)
51+
("Can you recommend some niche temples in Kyoto?", "I recommend Sanzen-in, Jakko-in, and Tenryu-ji in Arashiyama."),
52+
("I'm very interested in traditional handicrafts", "Kyoto has many traditional crafts! Kiyomizu pottery and Nishijin weaving are very famous."),
53+
("Can you arrange some handicraft experience courses?", "Of course! Pottery, kimono making, and tea ceremony all have experience courses."),
54+
("I want to learn tea ceremony, do I need to make a reservation?", "Tea ceremony experiences need advance booking, let me check available times for you."),
55+
("Besides Kyoto, what do you recommend in Nara?", "Nara's Todai-ji Temple, Kasuga Taisha Shrine are worth seeing, plus Deer Park."),
56+
("I heard Nara has many alleys with great atmosphere", "Yes! Naramachi's old streets have great charm, with many traditional shops."),
57+
("How should I arrange transportation?", "I suggest buying a JR Kansai Area Pass, transportation between Kyoto and Nara is very convenient."),
58+
("I want to go to some restaurants recommended by locals", "I recommend some local shops not in tourist guides, very authentic!"),
59+
("Do you have vegetarian restaurant recommendations? I pay attention to healthy eating", "Kyoto has many shojin ryori restaurants, both healthy and cultural experience."),
60+
("I want to learn about local festival culture", "In October there's Jidai Matsuri, one of Kyoto's three major festivals, very worth seeing!"),
61+
62+
# In-depth needs and personal preferences (21-30)
63+
("I enjoy photography, what are some good photo spots?", "Bamboo Grove, Fushimi Inari's thousands of torii gates are perfect for photography!"),
64+
("I especially like photographing architecture and people", "You'll definitely love Kinkaku-ji's reflection and the geisha district streetscapes."),
65+
("I don't like crowded places", "I recommend some early morning time slots, fewer tourists and great lighting."),
66+
("I want to buy some traditional crafts as souvenirs", "Nishijin weaving items and Kiyomizu pottery tea sets have great collectible value."),
67+
("Are there any seasonal experience activities?", "In October you can participate in momiji-gari (autumn leaf viewing) and hot spring bathing while viewing maples."),
68+
("I want to try some local lifestyle experiences", "We can arrange early morning visits to fish markets to experience locals' rhythm."),
69+
("For accommodation, I hope to experience different types", "We can arrange 2 nights at traditional ryokan, others at boutique guesthouses."),
70+
("I'm also interested in Japanese flower arrangement", "Kyoto has many ikebana school experience classes, we can arrange one session."),
71+
("Do you have shopping suggestions?", "I recommend some long-established shops, good quality and historical significance."),
72+
("Overall, I hope this trip has rich cultural content", "Understood! I'll arrange a deep cultural experience journey for you.")
73+
]
74+
75+
# Add conversations
76+
for i, (user_input, agent_response) in enumerate(conversations, 1):
77+
print(f" [{i:2d}/{len(conversations)}] Adding conversation: {user_input[:40]}...")
78+
memoryos.add_memory(user_input, agent_response)
79+
80+
# Display status every 10 rounds
81+
if i % 10 == 0:
82+
sessions = memoryos.mid_term_memory.sessions
83+
if sessions:
84+
max_heat = max(session.get('H_segment', 0) for session in sessions.values())
85+
print(f" Current max heat: {max_heat:.2f}")
86+
87+
print(f"\n🔥 Phase 2: Force triggering mid-term analysis...")
88+
memoryos.force_mid_term_analysis()
89+
90+
print(f"\n⏳ Phase 3: Waiting for system synchronization...")
91+
time.sleep(2)
92+
93+
print(f"\n🧠 Phase 4: Testing Memory System Query Response...")
94+
95+
# Test queries based on previous conversations
96+
test_queries = [
97+
{
98+
"query": "What's my name and what's my profession?",
99+
"expected_keywords": ["Emily", "graphic designer", "designer"],
100+
"description": "Testing basic user information recall"
101+
},
102+
{
103+
"query": "Where do I want to travel and what are my preferences?",
104+
"expected_keywords": ["Japan", "Kyoto", "Nara", "historical", "culture"],
105+
"description": "Testing travel destination and preference recall"
106+
},
107+
{
108+
"query": "What are my hobbies and what kind of experiences am I interested in?",
109+
"expected_keywords": ["photography", "traditional", "cultural"],
110+
"description": "Testing hobby and interest recall"
111+
}
112+
]
113+
114+
print("\n" + "="*60)
115+
print("🔍 MEMORY SYSTEM QUERY TESTING")
116+
print("="*60)
117+
118+
total_score = 0
119+
max_score = len(test_queries)
120+
121+
for i, test_case in enumerate(test_queries, 1):
122+
print(f"\n📋 Test Query {i}: {test_case['description']}")
123+
print(f"Question: {test_case['query']}")
124+
print("-" * 50)
125+
126+
try:
127+
# Get response from memory system
128+
response = memoryos.get_response(test_case['query'])
129+
print(f"System Response: {response}")
130+
131+
# Check if expected keywords are in the response
132+
response_lower = response.lower()
133+
found_keywords = []
134+
missing_keywords = []
135+
136+
for keyword in test_case['expected_keywords']:
137+
if keyword.lower() in response_lower:
138+
found_keywords.append(keyword)
139+
else:
140+
missing_keywords.append(keyword)
141+
142+
# Calculate score for this query
143+
keyword_score = len(found_keywords) / len(test_case['expected_keywords'])
144+
145+
print(f"\n✅ Found keywords: {found_keywords}")
146+
if missing_keywords:
147+
print(f"❌ Missing keywords: {missing_keywords}")
148+
149+
print(f"🎯 Keyword match rate: {keyword_score:.1%}")
150+
151+
# Determine if this test passed (>50% keyword match)
152+
if keyword_score >= 0.5:
153+
print(f"✅ Test {i}: PASSED")
154+
total_score += 1
155+
else:
156+
print(f"❌ Test {i}: FAILED")
157+
158+
except Exception as e:
159+
print(f"❌ Error during query {i}: {e}")
160+
print(f"❌ Test {i}: FAILED")
161+
162+
# Final results
163+
print("\n" + "="*60)
164+
print("📊 FINAL TEST RESULTS")
165+
print("="*60)
166+
167+
success_rate = (total_score / max_score) * 100
168+
print(f"Passed Tests: {total_score}/{max_score}")
169+
print(f"Success Rate: {success_rate:.1f}%")
170+
print(f"Total Conversations Added: {len(conversations)}")
171+
print(f"Test Theme: Japan Travel Planning")
172+
print(f"User Profile: Emily, 28-year-old graphic designer, loves cultural travel and photography")
173+
174+
if success_rate >= 70:
175+
print("\n🎉 EXCELLENT! Memory system performed very well!")
176+
return True
177+
elif success_rate >= 50:
178+
print("\n👍 GOOD! Memory system performed adequately!")
179+
return True
180+
else:
181+
print("\n😞 NEEDS IMPROVEMENT! Memory system needs optimization!")
182+
return False
183+
184+
if __name__ == "__main__":
185+
success = main()
186+
if success:
187+
print("\n🎊 Congratulations! MemoryOS Travel Planning Memory Test Completed Successfully!")
188+
else:
189+
print("\n🔧 Memory system needs further optimization.")

memoryos-chromadb/long_term.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import json
2+
import numpy as np
3+
from typing import Optional, Dict, Any
4+
5+
try:
6+
from .utils import get_timestamp, get_embedding, normalize_vector, OpenAIClient, gpt_user_profile_analysis, gpt_knowledge_extraction
7+
from .storage_provider import ChromaStorageProvider
8+
except ImportError:
9+
from utils import get_timestamp, get_embedding, normalize_vector, OpenAIClient, gpt_user_profile_analysis, gpt_knowledge_extraction
10+
from storage_provider import ChromaStorageProvider
11+
12+
class LongTermMemory:
13+
def __init__(self,
14+
storage_provider: ChromaStorageProvider,
15+
llm_interface: OpenAIClient,
16+
knowledge_capacity=100,
17+
embedding_model_name: str = "all-MiniLM-L6-v2",
18+
embedding_model_kwargs: Optional[dict] = None):
19+
self.storage = storage_provider
20+
self.llm_interface = llm_interface
21+
self.knowledge_capacity = knowledge_capacity
22+
self.embedding_model_name = embedding_model_name
23+
self.embedding_model_kwargs = embedding_model_kwargs or {}
24+
25+
def update_user_profile(self, user_id: str, conversation_history: str) -> Optional[Dict[str, Any]]:
26+
"""
27+
Generates a new user profile based on conversation history and updates it in storage.
28+
"""
29+
existing_profile_str = json.dumps(self.get_user_profile(user_id) or {})
30+
31+
updated_profile = gpt_user_profile_analysis(
32+
conversation_str=conversation_history,
33+
client=self.llm_interface,
34+
existing_user_profile=existing_profile_str
35+
)
36+
37+
if updated_profile:
38+
self.storage.update_user_profile(user_id, updated_profile)
39+
print(f"LongTermMemory: Updated user profile for {user_id}.")
40+
return updated_profile
41+
return None
42+
43+
def get_user_profile(self, user_id: str) -> Optional[Dict[str, Any]]:
44+
return self.storage.get_user_profile(user_id)
45+
46+
def add_knowledge(self, knowledge_text: str, knowledge_type: str = "user"):
47+
"""
48+
Adds a knowledge entry (for user or assistant) to ChromaDB.
49+
knowledge_type can be 'user' or 'assistant'.
50+
"""
51+
print(f"DEBUG: add_knowledge received text: '{knowledge_text}'") # Debugging line
52+
if not knowledge_text or knowledge_text.strip().lower() in ["", "none", "- none", "- none."]:
53+
print(f"LongTermMemory: Empty {knowledge_type} knowledge received, not saving.")
54+
return
55+
56+
vec = get_embedding(
57+
knowledge_text,
58+
model_name=self.embedding_model_name,
59+
**self.embedding_model_kwargs
60+
)
61+
vec = normalize_vector(vec).tolist()
62+
63+
if knowledge_type == "user":
64+
self.storage.add_user_knowledge(knowledge_text, vec)
65+
else:
66+
self.storage.add_assistant_knowledge(knowledge_text, vec)
67+
68+
self.storage.enforce_knowledge_capacity(knowledge_type, self.knowledge_capacity)
69+
70+
def extract_knowledge_from_text(self, text: str) -> Optional[Dict[str, Any]]:
71+
"""
72+
Uses an LLM to extract structured knowledge from a block of text.
73+
"""
74+
if not text.strip():
75+
return None
76+
return gpt_knowledge_extraction(conversation_str=text, client=self.llm_interface)
77+
78+
def get_user_knowledge(self) -> list:
79+
return self.storage.get_all_user_knowledge()
80+
81+
def get_assistant_knowledge(self) -> list:
82+
return self.storage.get_all_assistant_knowledge()
83+
84+
def search_knowledge(self, query: str, knowledge_type: str = "user", top_k=5) -> list:
85+
query_vec = get_embedding(
86+
query,
87+
model_name=self.embedding_model_name,
88+
**self.embedding_model_kwargs
89+
)
90+
query_vec = normalize_vector(query_vec).tolist()
91+
92+
if knowledge_type == "user":
93+
results = self.storage.search_user_knowledge(query_vec, top_k=top_k)
94+
else:
95+
results = self.storage.search_assistant_knowledge(query_vec, top_k=top_k)
96+
97+
print(f"LongTermMemory: Searched {knowledge_type} knowledge for '{query[:30]}...'. Found {len(results)} matches.")
98+
return results

0 commit comments

Comments
 (0)