Scenario 9: User Profile Management
This scenario demonstrates powermem's UserMemory feature - automatic user profile extraction, management, and integration with memory search.
Prerequisites
- Python 3.10+
- powermem installed (
pip install powermem) - LLM provider configured (for profile extraction)
- OceanBase configured as vector store (UserMemory requires OceanBase)
Important Note:
UserMemoryrequires OceanBase as the storage backend. If you attempt to useUserMemorywith a different storage provider, it will raise aValueError. Please configure OceanBase as your vector store provider.
Understanding User Profile Management
UserMemory extends Memory with user profile capabilities:
- Automatic profile extraction: Extracts user-related information from conversations (name, profession, interests, preferences, etc.)
- Continuous profile updates: Updates and refines the profile based on new conversations
- Profile storage: Stores profiles separately from memories for efficient retrieval
- Joint search: Optionally includes profile information when searching memories
Step 1: Initialize UserMemory
First, let's initialize UserMemory with proper configuration:
# user_profile_example.py
from powermem import UserMemory, auto_config
# Load configuration (auto-loads from .env or uses defaults)
config = auto_config()
# Create UserMemory instance
user_memory = UserMemory(config=config)
print("✓ UserMemory initialized successfully!")
Run this code:
python user_profile_example.py
Expected output:
✓ UserMemory initialized successfully!
Step 2: Add Conversation and Extract Profile
Add a conversation and automatically extract user profile information:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
# Add a conversation
conversation = [
{"role": "user", "content": "Hi, I'm Alice. I'm a 28-year-old software engineer from San Francisco. I work at a tech startup and love Python programming."},
{"role": "assistant", "content": "Nice to meet you, Alice! Python is a great language for software engineering."}
]
result = user_memory.add(
messages=conversation,
user_id="user_001",
agent_id="assistant_agent",
run_id="session_001"
)
print(f"✓ Conversation added successfully")
print(f" - Profile extracted: {result.get('profile_extracted', False)}")
if result.get('profile_content'):
print(f" - Profile content: {result['profile_content']}")
print(f" - Memory results count: {len(result.get('results', []))}")
Run this code:
python user_profile_example.py
Expected output:
✓ Conversation added successfully
- Profile extracted: True
- Profile content: Name: Alice. Age: 28. Location: San Francisco. Profession: Software engineer at a tech startup. Interests: Python programming.
- Memory results count: 1
Step 3: Update Profile with More Conversations
Add more conversations to update and refine the user profile:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
# First conversation
conversation1 = [
{"role": "user", "content": "Hi, I'm Alice. I'm a software engineer from San Francisco."},
{"role": "assistant", "content": "Nice to meet you, Alice!"}
]
result1 = user_memory.add(
messages=conversation1,
user_id="user_001",
agent_id="assistant_agent"
)
print("=== First conversation ===")
print(f"Profile extracted: {result1.get('profile_extracted', False)}")
if result1.get('profile_content'):
print(f"Profile: {result1['profile_content']}")
# Second conversation - adds more information
conversation2 = [
{"role": "user", "content": "I also enjoy reading science fiction novels and playing tennis on weekends."},
{"role": "assistant", "content": "That sounds like great hobbies!"}
]
result2 = user_memory.add(
messages=conversation2,
user_id="user_001",
agent_id="assistant_agent"
)
print("\n=== Second conversation ===")
print(f"Profile updated: {result2.get('profile_extracted', False)}")
if result2.get('profile_content'):
print(f"Updated profile: {result2['profile_content']}")
Run this code:
python user_profile_example.py
Expected output:
=== First conversation ===
Profile extracted: True
Profile: Name: Alice. Profession: Software engineer. Location: San Francisco.
=== Second conversation ===
Profile updated: True
Updated profile: Name: Alice. Profession: Software engineer. Location: San Francisco. Hobbies: Reading science fiction novels, playing tennis.
Step 4: Get User Profile
Retrieve the user profile directly:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
# Add some conversations first
conversation = [
{"role": "user", "content": "I'm Bob, a data scientist. I love machine learning and hiking."},
{"role": "assistant", "content": "Great to meet you, Bob!"}
]
user_memory.add(
messages=conversation,
user_id="user_002",
agent_id="assistant_agent"
)
# Get the user profile
profile = user_memory.profile(
user_id="user_002"
)
if profile:
print("✓ Profile retrieved successfully")
print(f" - Profile ID: {profile.get('id')}")
print(f" - User ID: {profile.get('user_id')}")
if profile.get('profile_content'):
print(f" - Profile content: {profile.get('profile_content', '')}")
if profile.get('topics'):
print(f" - Topics: {profile.get('topics')}")
print(f" - Created at: {profile.get('created_at')}")
print(f" - Updated at: {profile.get('updated_at')}")
else:
print("✗ No profile found")
Run this code:
python user_profile_example.py
Expected output:
✓ Profile retrieved successfully
- Profile ID: 1234567890123456789
- User ID: user_002
- Agent ID: assistant_agent
- Run ID:
- Profile content: Name: Bob. Profession: Data scientist. Interests: Machine learning, hiking.
- Created at: 2024-01-15T10:30:00
- Updated at: 2024-01-15T10:30:00
Step 5: Search Memories Without Profile
Search memories without including the profile:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
user_id = "user_003"
# Add some conversations
user_memory.add(
messages=[
{"role": "user", "content": "I'm Charlie, a product manager. I work on mobile apps."},
{"role": "assistant", "content": "Interesting!"}
],
user_id=user_id,
agent_id="assistant_agent"
)
user_memory.add(
messages=[
{"role": "user", "content": "I prefer agile development methodology."},
{"role": "assistant", "content": "That's a popular approach."}
],
user_id=user_id,
agent_id="assistant_agent"
)
# Search without profile
results = user_memory.search(
query="work and preferences",
user_id=user_id,
agent_id="assistant_agent",
limit=5,
add_profile=False # Don't include profile
)
print(f"✓ Search completed")
print(f" - Results count: {len(results.get('results', []))}")
print(f" - Profile included: {'profile_content' in results}")
for i, result in enumerate(results.get('results', []), 1):
print(f" {i}. {result.get('memory', '')} (score: {result.get('score', 0):.2f})")
Run this code:
python user_profile_example.py
Expected output:
✓ Search completed
- Results count: 2
- Profile included: False
1. Works on mobile apps as a product manager (score: 0.85)
2. Prefers agile development methodology (score: 0.78)
Optional: Query Rewrite with User Profile
UserMemory.search() can optionally rewrite the query using the user's profile to improve recall. This feature is optional and disabled by default. It only runs when query_rewrite.enabled=True and a user_id with profile_content is available. If the profile is missing, the query is too short, or the rewrite fails, it falls back to the original query.
Practical example (profile + ambiguous query):
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
user_id = "user_rewrite_demo"
# Build profile with relocation info
user_memory.add(
messages="Last month I moved from Chengdu to Hangzhou, and started a new job.",
user_id=user_id,
profile_type="content"
)
# Ambiguous query that relies on profile context
results = user_memory.search(
query="Recommend some delicious food near my place.",
user_id=user_id,
limit=5
)
Contrast: rewrite enabled vs disabled
import os
# Enable query rewrite via env
os.environ["QUERY_REWRITE_ENABLED"] = "true"
user_memory_rewrite = UserMemory(config=auto_config())
# Disable query rewrite via env
os.environ["QUERY_REWRITE_ENABLED"] = "false"
user_memory_no_rewrite = UserMemory(config=auto_config())
# Same query, same user profile
query = "Recommend some delicious food near my place."
result_with_rewrite = user_memory_rewrite.search(
query=query,
user_id=user_id,
limit=5
)
result_without_rewrite = user_memory_no_rewrite.search(
query=query,
user_id=user_id,
limit=5
)
Example config:
config = {
# ... other config
"query_rewrite": {
"enabled": True,
# "prompt": "Rewrite queries to be specific and grounded in the user profile."
}
}
Environment variables are also supported (see .env.example):
QUERY_REWRITE_ENABLED=false
# QUERY_REWRITE_PROMPT=
# QUERY_REWRITE_MODEL_OVERRIDE=
QUERY_REWRITE_PROMPTis optional custom instructions for rewrite.QUERY_REWRITE_MODEL_OVERRIDEis optional and must be another model from the same LLM provider family.
Step 6: Search Memories With Profile
Search memories and include the user profile in results:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
user_id = "user_004"
# Add conversations
user_memory.add(
messages=[
{"role": "user", "content": "I'm Diana, a UX designer. I love creating beautiful interfaces."},
{"role": "assistant", "content": "That's wonderful!"}
],
user_id=user_id,
agent_id="assistant_agent"
)
# Search with profile
results = user_memory.search(
query="user background and interests",
user_id=user_id,
agent_id="assistant_agent",
limit=5,
add_profile=True # Include profile
)
print(f"✓ Search with profile completed")
print(f" - Results count: {len(results.get('results', []))}")
print(f" - Profile included: {'profile_content' in results}")
if 'profile_content' in results:
print(f"\n User Profile:")
print(f" {results['profile_content']}")
print(f"\n Search Results:")
for i, result in enumerate(results.get('results', []), 1):
print(f" {i}. {result.get('memory', '')} (score: {result.get('score', 0):.2f})")
Run this code:
python user_profile_example.py
Expected output:
✓ Search with profile completed
- Results count: 1
- Profile included: True
User Profile:
Name: Diana. Profession: UX designer. Interests: Creating beautiful interfaces.
Search Results:
1. Works as a UX designer, loves creating beautiful interfaces (score: 0.92)
Step 7: Extract Profile in Native Language
You can specify a native language for profile extraction, ensuring the profile is written in the user's preferred language regardless of the conversation language:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
# Example 1: English conversation, Chinese profile
conversation_en = [
{"role": "user", "content": "I am a software engineer working in Beijing. I love drinking tea and reading books."},
{"role": "assistant", "content": "That sounds great!"}
]
result_zh = user_memory.add(
messages=conversation_en,
user_id="user_bilingual_001",
native_language="zh" # Extract profile in Chinese
)
print("✓ English conversation processed")
if result_zh.get('profile_content'):
print(f" - Profile (Chinese): {result_zh['profile_content']}")
# Example 2: Chinese conversation, English profile
conversation_zh = [
{"role": "user", "content": "I'm 25 years old, working at Microsoft in Seattle."},
{"role": "assistant", "content": "Nice to meet you"}
]
result_en = user_memory.add(
messages=conversation_zh,
user_id="user_bilingual_002",
native_language="en" # Extract profile in English
)
print("\n✓ Chinese conversation processed")
if result_en.get('profile_content'):
print(f" - Profile (English): {result_en['profile_content']}")
# Example 3: Structured topics with native language
result_topics = user_memory.add(
messages="I'm 25 years old, working at Microsoft in Seattle.",
user_id="user_bilingual_003",
profile_type="topics",
native_language="zh" # Topic values in Chinese, keys remain English
)
print("\n✓ Structured topics extracted")
if result_topics.get('topics'):
print(f" - Topics: {result_topics['topics']}")
Run this code:
python user_profile_example.py
Supported Language Codes:
| Code | Language | Code | Language |
|---|---|---|---|
| zh | Chinese | en | English |
| ja | Japanese | ko | Korean |
| fr | French | de | German |
| es | Spanish | it | Italian |
| pt | Portuguese | ru | Russian |
| ar | Arabic | hi | Hindi |
| th | Thai | vi | Vietnamese |
Step 8: Delete User Profile
Delete a user profile:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config, agent_id="assistant_agent")
user_id = "user_007"
# Add conversation and create profile
user_memory.add(
messages=[
{"role": "user", "content": "I'm Grace, a teacher."},
{"role": "assistant", "content": "Nice to meet you!"}
],
user_id=user_id
)
# Get profile to confirm it exists
profile = user_memory.profile(user_id=user_id)
if profile:
profile_id = profile.get('id')
print(f"✓ Profile exists with ID: {profile_id}")
# Delete the profile
deleted = user_memory.delete_profile(
user_id=user_id
)
if deleted:
print(f"✓ Profile deleted successfully")
else:
print(f"✗ Failed to delete profile")
# Verify deletion
profile_after = user_memory.profile(user_id=user_id)
if not profile_after:
print("✓ Profile confirmed deleted")
else:
print("✗ Profile still exists")
Run this code:
python user_profile_example.py
Expected output:
✓ Profile exists with ID: 1234567890123456789
✓ Profile deleted successfully
✓ Profile confirmed deleted
Complete Example
Here's a complete example combining all the features:
# complete_user_profile_example.py
from powermem import UserMemory, auto_config
def main():
# Load configuration
config = auto_config()
# Initialize UserMemory
user_memory = UserMemory(config=config, agent_id="demo_agent")
user_id = "demo_user"
print("=" * 60)
print("UserMemory Profile Management Example")
print("=" * 60)
# Step 1: Add initial conversation
print("\n1. Adding initial conversation...")
conversation1 = [
{"role": "user", "content": "Hi, I'm Alex, a 32-year-old data scientist from New York. I specialize in machine learning and love reading tech blogs."},
{"role": "assistant", "content": "Nice to meet you, Alex! That's fascinating."}
]
result1 = user_memory.add(
messages=conversation1,
user_id=user_id,
run_id="session_001"
)
print(f" ✓ Profile extracted: {result1.get('profile_extracted', False)}")
if result1.get('profile_content'):
print(f" Profile: {result1['profile_content']}")
# Step 2: Update profile with more information
print("\n2. Updating profile with more conversations...")
conversation2 = [
{"role": "user", "content": "I also enjoy hiking and photography on weekends."},
{"role": "assistant", "content": "Those are great hobbies!"}
]
result2 = user_memory.add(
messages=conversation2,
user_id=user_id,
run_id="session_002"
)
print(f" ✓ Profile updated: {result2.get('profile_extracted', False)}")
# Step 3: Get full profile
print("\n3. Retrieving full profile...")
profile = user_memory.profile(
user_id=user_id
)
if profile:
print(f" ✓ Profile ID: {profile.get('id')}")
print(f" Profile content: {profile.get('profile_content', '')}")
print(f" Last updated: {profile.get('updated_at')}")
# Step 4: Search with profile
print("\n4. Searching memories with profile...")
search_results = user_memory.search(
query="user interests and hobbies",
user_id=user_id,
limit=5,
add_profile=True
)
if 'profile_content' in search_results:
print(f" User Profile: {search_results['profile_content']}")
print(f"\n Found {len(search_results.get('results', []))} memories:")
for i, result in enumerate(search_results.get('results', []), 1):
print(f" {i}. {result.get('memory', '')} (score: {result.get('score', 0):.2f})")
# Step 5: Cleanup (optional)
print("\n5. Cleaning up...")
# Note: In production, you might want to keep the profiles
# deleted = user_memory.delete_profile(user_id=user_id)
# if deleted:
# print(" ✓ Profile deleted")
print("\n" + "=" * 60)
print("Example completed successfully!")
print("=" * 60)
if __name__ == "__main__":
main()
Run this code:
python complete_user_profile_example.py
Best Practices
-
Always provide
user_id: Theadd()method requiresuser_id; ensure each user has a unique identifier -
Use
agent_idto distinguish agents: In multi-agent scenarios, useagent_idto separate profiles and memories across agents -
Use
run_idappropriately: Userun_idto distinguish sessions or runs for more precise profile management -
Check profiles regularly: Use
profile()to periodically check and ensure profile information remains accurate -
Include profile when needed: When additional context is useful, set
add_profile=Trueto include the user profile in search results -
Handle empty profiles: If
profile()returns{}, no profile has been extracted yet; calladd()with conversation data first -
Profile updates: Profiles are automatically updated when you add new conversations with the same
user_id,agent_id, andrun_idcombination -
Message filtering: By default, only
userrole messages are used for profile extraction (assistant messages are excluded). You can customize this withinclude_rolesandexclude_rolesparameters -
Query rewrite (optional): Enable
query_rewrite.enabled=Trueto letsearch()rewrite queries using profile content; it falls back to the original query when unavailable
Step 8: Filter Messages by Roles
By default, UserMemory.add() only extracts profile information from user messages. You can customize which message roles are used for profile extraction:
# user_profile_example.py
from powermem import UserMemory, auto_config
config = auto_config()
user_memory = UserMemory(config=config)
# Conversation with multiple roles
conversation = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hi, I'm Frank, a doctor from Boston."},
{"role": "assistant", "content": "Nice to meet you, Frank!"},
{"role": "tool", "content": "Weather data: Boston, 72°F"}
]
# Default behavior: only include 'user' messages, exclude 'assistant' messages
result = user_memory.add(
messages=conversation,
user_id="user_008"
)
print("Default filtering (user only):")
print(f" Profile: {result.get('profile_content', 'N/A')}")
# Include all messages (disable filtering)
result = user_memory.add(
messages=conversation,
user_id="user_009",
include_roles=None, # or []
exclude_roles=None # or []
)
print("\nNo filtering (all roles):")
print(f" Profile: {result.get('profile_content', 'N/A')}")
# Custom filtering: include user and system, exclude tool
result = user_memory.add(
messages=conversation,
user_id="user_010",
include_roles=["user", "system"],
exclude_roles=["tool"]
)
print("\nCustom filtering (user + system, exclude tool):")
print(f" Profile: {result.get('profile_content', 'N/A')}")
Run this code:
python user_profile_example.py
Expected output:
Default filtering (user only):
Profile: Name: Frank. Profession: Doctor. Location: Boston.
No filtering (all roles):
Profile: Name: Frank. Profession: Doctor. Location: Boston.
Custom filtering (user + system, exclude tool):
Profile: Name: Frank. Profession: Doctor. Location: Boston.
Related Documents
- UserMemory Guide - Detailed guide on UserMemory features
- Getting Started - Learn the basics of PowerMem
- Multi-Agent Guide - Using multiple agents with Memory