Skip to content

Commit 4ab316c

Browse files
authored
feat: update demo and add user manager (#31)
* feat: add product API and related functionality (cleaned sensitive data) * feat: add singleton for memos and llm * fix:fix persistent_user_manager * feat:update prompt and rm readme * fix:ci code
1 parent 3ef8e7f commit 4ab316c

File tree

16 files changed

+3582
-52
lines changed

16 files changed

+3582
-52
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""
2+
Example demonstrating how to use MOSProduct for multi-user scenarios.
3+
"""
4+
5+
from memos.configs.mem_cube import GeneralMemCubeConfig
6+
from memos.configs.mem_os import MOSConfig
7+
from memos.mem_cube.general import GeneralMemCube
8+
from memos.mem_os.product import MOSProduct
9+
10+
11+
def get_config(user_name):
12+
openapi_config = {
13+
"model_name_or_path": "gpt-4o-mini",
14+
"temperature": 0.8,
15+
"max_tokens": 1024,
16+
"top_p": 0.9,
17+
"top_k": 50,
18+
"remove_think_prefix": True,
19+
"api_key": "your-api-key-here",
20+
"api_base": "https://api.openai.com/v1",
21+
}
22+
# Create a default configuration
23+
default_config = MOSConfig(
24+
user_id="root",
25+
chat_model={"backend": "openai", "config": openapi_config},
26+
mem_reader={
27+
"backend": "naive",
28+
"config": {
29+
"llm": {
30+
"backend": "openai",
31+
"config": openapi_config,
32+
},
33+
"embedder": {
34+
"backend": "ollama",
35+
"config": {
36+
"model_name_or_path": "nomic-embed-text:latest",
37+
},
38+
},
39+
},
40+
},
41+
enable_textual_memory=True,
42+
enable_activation_memory=False,
43+
top_k=5,
44+
max_turns_window=20,
45+
)
46+
default_cube_config = GeneralMemCubeConfig.model_validate(
47+
{
48+
"user_id": user_name,
49+
"cube_id": f"{user_name}_default_cube",
50+
"text_mem": {
51+
"backend": "tree_text",
52+
"config": {
53+
"extractor_llm": {"backend": "openai", "config": openapi_config},
54+
"dispatcher_llm": {"backend": "openai", "config": openapi_config},
55+
"graph_db": {
56+
"backend": "neo4j",
57+
"config": {
58+
"uri": "bolt://localhost:7687",
59+
"user": "neo4j",
60+
"password": "12345678",
61+
"db_name": user_name,
62+
"auto_create": True,
63+
},
64+
},
65+
"embedder": {
66+
"backend": "ollama",
67+
"config": {
68+
"model_name_or_path": "nomic-embed-text:latest",
69+
},
70+
},
71+
},
72+
},
73+
"act_mem": {},
74+
"para_mem": {},
75+
}
76+
)
77+
default_mem_cube = GeneralMemCube(default_cube_config)
78+
return default_config, default_mem_cube
79+
80+
81+
def main():
82+
default_config, default_mem_cube = get_config(user_name="alice")
83+
# Initialize MOSProduct with default config
84+
mos_product = MOSProduct(default_config=default_config)
85+
86+
# Register first user with default config
87+
result1 = mos_product.user_register(
88+
user_id="alice",
89+
user_name="alice",
90+
interests="I'm interested in machine learning and AI research.",
91+
default_mem_cube=default_mem_cube,
92+
)
93+
print(f"User registration result: {result1}")
94+
95+
# Chat with Alice
96+
print("\n=== Chatting with Alice ===")
97+
for response_chunk in mos_product.chat(query="What are my interests?", user_id="alice"):
98+
print(response_chunk, end="")
99+
100+
# Add memory for Alice
101+
mos_product.add(
102+
user_id="alice",
103+
memory_content="I attended a machine learning conference last week.",
104+
mem_cube_id=result1["default_cube_id"],
105+
)
106+
107+
# Search memories for Alice
108+
search_result = mos_product.search(query="conference", user_id="alice")
109+
print(f"\nSearch result for Alice: {search_result}")
110+
111+
# Search memories for Alice
112+
search_result = mos_product.get_all(query="conference", user_id="alice", memory_type="text_mem")
113+
print(f"\nSearch result for Alice: {search_result}")
114+
115+
# List all users
116+
users = mos_product.list_users()
117+
print(f"\nAll registered users: {users}")
118+
119+
# Get user info
120+
alice_info = mos_product.get_user_info("alice")
121+
print(f"\nAlice's info: {alice_info}")
122+
123+
124+
if __name__ == "__main__":
125+
main()
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
"""
2+
Example demonstrating persistent user management in MemOS.
3+
4+
This example shows how to use the PersistentUserManager to maintain
5+
user configurations across service restarts.
6+
"""
7+
8+
import os
9+
import tempfile
10+
11+
from memos.configs.mem_os import MOSConfig
12+
from memos.mem_os.product import MOSProduct
13+
from memos.mem_user.persistent_user_manager import PersistentUserManager, UserRole
14+
15+
16+
def create_sample_config(user_id: str) -> MOSConfig:
17+
"""Create a sample configuration for a user."""
18+
return MOSConfig(
19+
user_id=user_id,
20+
chat_model={
21+
"backend": "openai",
22+
"config": {
23+
"model_name_or_path": "gpt-3.5-turbo",
24+
"api_key": "your-api-key-here",
25+
"temperature": 0.7,
26+
},
27+
},
28+
mem_reader={
29+
"backend": "naive",
30+
"config": {
31+
"llm": {
32+
"backend": "openai",
33+
"config": {
34+
"model_name_or_path": "gpt-3.5-turbo",
35+
"api_key": "your-api-key-here",
36+
},
37+
},
38+
"embedder": {
39+
"backend": "ollama",
40+
"config": {
41+
"model_name_or_path": "nomic-embed-text:latest",
42+
},
43+
},
44+
},
45+
},
46+
enable_textual_memory=True,
47+
enable_activation_memory=False,
48+
top_k=5,
49+
max_turns_window=20,
50+
)
51+
52+
53+
def demonstrate_persistence():
54+
"""Demonstrate the persistence functionality."""
55+
print("=== MemOS Persistent User Management Demo ===\n")
56+
57+
# Create a temporary database for this demo
58+
temp_dir = tempfile.mkdtemp()
59+
db_path = os.path.join(temp_dir, "demo_memos.db")
60+
61+
try:
62+
# Step 1: Create a persistent user manager
63+
print("1. Creating PersistentUserManager...")
64+
user_manager = PersistentUserManager(db_path=db_path)
65+
print(f" Database created at: {db_path}")
66+
67+
# Step 2: Create some sample configurations
68+
print("\n2. Creating sample user configurations...")
69+
user_configs = {}
70+
for i in range(3):
71+
user_id = f"user_{i + 1}"
72+
user_name = f"User {i + 1}"
73+
config = create_sample_config(user_id)
74+
user_configs[user_id] = config
75+
76+
# Create user with configuration
77+
created_id = user_manager.create_user_with_config(
78+
user_name, config, UserRole.USER, user_id
79+
)
80+
print(f" Created user: {user_name} (ID: {created_id})")
81+
82+
# Step 3: Verify configurations are saved
83+
print("\n3. Verifying configurations are saved...")
84+
for user_id in user_configs:
85+
config = user_manager.get_user_config(user_id)
86+
if config:
87+
print(f" ✓ Configuration found for {user_id}")
88+
print(f" - Textual memory enabled: {config.enable_textual_memory}")
89+
print(f" - Top-k: {config.top_k}")
90+
else:
91+
print(f" ✗ Configuration not found for {user_id}")
92+
93+
# Step 4: Simulate service restart by creating a new manager instance
94+
print("\n4. Simulating service restart...")
95+
print(" Creating new PersistentUserManager instance...")
96+
new_user_manager = PersistentUserManager(db_path=db_path)
97+
98+
# Step 5: Verify configurations are restored
99+
print("\n5. Verifying configurations are restored after restart...")
100+
for user_id in user_configs:
101+
config = new_user_manager.get_user_config(user_id)
102+
if config:
103+
print(f" ✓ Configuration restored for {user_id}")
104+
else:
105+
print(f" ✗ Configuration not restored for {user_id}")
106+
107+
# Step 6: Create MOSProduct and demonstrate restoration
108+
print("\n6. Creating MOSProduct with persistent user manager...")
109+
default_config = create_sample_config("default_user")
110+
mos_product = MOSProduct(default_config=default_config)
111+
112+
# The MOSProduct should automatically restore user instances
113+
print(f" Active user instances: {len(mos_product.user_instances)}")
114+
for user_id in mos_product.user_instances:
115+
print(f" - {user_id}")
116+
117+
# Step 7: Demonstrate configuration update
118+
print("\n7. Demonstrating configuration update...")
119+
user_id = "user_1"
120+
original_config = user_manager.get_user_config(user_id)
121+
if original_config:
122+
# Update configuration
123+
updated_config = original_config.model_copy(deep=True)
124+
updated_config.top_k = 10
125+
updated_config.enable_activation_memory = True
126+
127+
success = user_manager.save_user_config(user_id, updated_config)
128+
if success:
129+
print(f" ✓ Updated configuration for {user_id}")
130+
print(f" - New top-k: {updated_config.top_k}")
131+
print(f" - Activation memory: {updated_config.enable_activation_memory}")
132+
else:
133+
print(f" ✗ Failed to update configuration for {user_id}")
134+
135+
# Step 8: List all configurations
136+
print("\n8. Listing all user configurations...")
137+
all_configs = user_manager.list_user_configs()
138+
print(f" Total configurations: {len(all_configs)}")
139+
for user_id, config in all_configs.items():
140+
print(
141+
f" - {user_id}: top_k={config.top_k}, textual_memory={config.enable_textual_memory}"
142+
)
143+
144+
print("\n=== Demo completed successfully! ===")
145+
print(f"Database file: {db_path}")
146+
print("You can inspect this file to see the persistent data.")
147+
148+
except Exception as e:
149+
print(f"Error during demo: {e}")
150+
raise
151+
finally:
152+
# Cleanup
153+
if os.path.exists(db_path):
154+
os.remove(db_path)
155+
if os.path.exists(temp_dir):
156+
os.rmdir(temp_dir)
157+
158+
159+
def demonstrate_api_usage():
160+
"""Demonstrate how the API would work with persistence."""
161+
print("\n=== API Usage Example ===")
162+
print("""
163+
With the new persistent system, your API calls would work like this:
164+
165+
1. Register a user (configuration is automatically saved):
166+
POST /product/users/register
167+
{
168+
"user_id": "john_doe",
169+
"user_name": "John Doe",
170+
"interests": "AI, machine learning, programming"
171+
}
172+
173+
2. Get user configuration:
174+
GET /product/users/john_doe/config
175+
176+
3. Update user configuration:
177+
PUT /product/users/john_doe/config
178+
{
179+
"user_id": "john_doe",
180+
"enable_activation_memory": true,
181+
"top_k": 10,
182+
...
183+
}
184+
185+
4. After service restart, all user instances are automatically restored
186+
and the user can immediately use the system without re-registration.
187+
""")
188+
189+
190+
if __name__ == "__main__":
191+
demonstrate_persistence()
192+
demonstrate_api_usage()

0 commit comments

Comments
 (0)