Context and Relationships
Context and relationships are fundamental to how Papr Memory organizes and retrieves information. This page explains how Papr Memory handles context and manages relationships between memories.
Understanding Context
Context in Papr Memory is primarily handled through metadata. The API supports various context elements that help organize and retrieve your memories effectively.
Key Metadata Fields
Papr Memory uses these key metadata fields to establish context, but you can also add your own custom metadata fields based on your specific needs:
Content Metadata
{ "topics": "product, planning, roadmap", "hierarchical_structures": "Business/Planning/Product" }
Source Metadata
{ "sourceUrl": "https://meeting-notes.example.com/123", "conversationId": "conv-123" }
Organization Metadata
{ "workspaceId": "ws_456", "userId": "user_789" }
Temporal Metadata
{ "createdAt": "2024-03-20T10:00:00Z" }
Custom Metadata
{ "priority": "high", "reviewStatus": "approved", "department": "engineering", "projectPhase": "planning" }
Metadata Considerations
- Custom Fields: You can define any custom metadata fields that make sense for your application
- Search Behavior: All metadata fields contribute to semantic search quality
- Filtering Limitations: Currently, you can only filter search results by
userId
- filtering by other metadata fields is not yet supported
Defining Relationships
Papr Memory automatically identifies relationships between memories. You can also define explicit relationships between memory items if you want to using the relationships_json
field. This is helpful if you want to connect specific memories to each other or for an AI agent to relate different chats to each other in a chat conversation for example:
# Add a memory with relationships to other memories
memory_response = client.memory.add(
content="Follow-up meeting notes",
type="text",
metadata={
"topics": "project, follow-up, action-items",
"conversationId": "conv-123"
},
relationships_json=[
{
"related_item_id": "mem_previous_meeting", # ID of related memory
"relation_type": "follows", # Type of relationship
"related_item_type": "TextMemoryItem", # Type of related memory
"metadata": {
"relevance": "high",
"notes": "Direct follow-up to previous discussion"
}
},
{
"related_item_id": "mem_project_plan",
"relation_type": "references",
"related_item_type": "TextMemoryItem",
"metadata": {
"relevance": "medium",
"notes": "References the main project plan"
}
}
]
)
Common Relationship Types
While you can define custom relationship types, here are some common patterns:
- follows: Memory item follows chronologically after another
- references: Memory item references or mentions another
- elaborates: Memory item provides more detail on another
- contradicts: Memory item provides contrary information to another
- summarizes: Memory item summarizes information from another
Conversation Context
The context
parameter allows you to provide conversation history or relevant context for a memory item:
# Add memory with conversation context
memory_response = client.memory.add(
content="Decision to increase API rate limits",
type="text",
metadata={
"topics": "api, infrastructure, decisions"
},
context=[
{"role": "user", "content": "Our customers are hitting API rate limits frequently"},
{"role": "assistant", "content": "What specific endpoints are causing issues?"},
{"role": "user", "content": "The /data and /analytics endpoints during peak hours"},
{"role": "assistant", "content": "Based on our usage patterns, we could safely increase limits"}
]
)
Hierarchical Structures
The hierarchical_structures
metadata field enables organizing memories in a tree-like structure. While not currently filterable, this field improves semantic search by adding important context:
# Add memory with hierarchical organization
memory_response = client.memory.add(
content="Team performance review Q1 2024",
type="text",
metadata={
"topics": "review, performance, metrics",
"hierarchical_structures": "Company/HR/Reviews/Q1_2024"
}
)
# Another memory in a different part of the hierarchy
memory_response = client.memory.add(
content="Product roadmap for mobile apps",
type="text",
metadata={
"topics": "roadmap, mobile, planning",
"hierarchical_structures": "Company/Product/Mobile/Roadmaps"
}
)
When searching, including hierarchical path information in your query can help find relevant memories, even though direct filtering by hierarchy is not yet supported:
# Query that includes hierarchical context
results = client.memory.search(
query="Find the latest mobile team performance metrics in the HR reviews from Q1 2024"
)
Context-Aware Search
When searching with Papr Memory, your detailed query provides context for finding the most relevant information:
# Search with a detailed, context-rich query
results = client.memory.search(
query="Find our product roadmap discussion from last month's planning meeting. I need to review the Q3 milestones and resource allocation we agreed on."
)
# Filter search by userId (currently the only metadata field that can be used as a filter)
results = client.memory.search(
query="Find the latest performance metrics for the mobile team",
metadata={
"userId": "user_123" # Only userId filtering is currently supported
}
)
Note: While you can include other metadata fields in the search request, currently only userId
is used for filtering. Other fields like hierarchical_structures
contribute to the semantic search but cannot yet be used as explicit filters.
User-Specific Context
You can manage user-specific memories by including user information in metadata. The userId
field is special because it's currently the only metadata field that can be explicitly filtered on:
# Add a memory with user context
memory_response = client.memory.add(
content="Personal notes from the design review",
type="text",
metadata={
"topics": "design, feedback, review",
"userId": "user_123",
"hierarchical_structures": "Projects/Website/Design"
}
)
# Search memories for a specific user (filtering by userId works)
results = client.memory.search(
query="Find my design review notes from last week",
metadata={
"userId": "user_123" # This will properly filter results to this user
}
)
This capability is particularly useful for applications serving multiple users, as it allows you to keep memories properly segregated by user while still benefiting from the shared semantic search infrastructure.
Best Practices
Metadata Consistency
- Use consistent metadata schemas across your application
- Establish conventions for topics, hierarchies, and relationship types
- Document your metadata schema for team reference
Custom Metadata Fields
- Define custom metadata fields that have meaning in your domain
- Use consistent naming conventions (camelCase or snake_case)
- Include metadata that will be useful for semantic search
- Remember that while all metadata improves search quality, only
userId
can currently be used for filtering
Hierarchical Structures
- Create clear hierarchies in
hierarchical_structures
- Use consistent path formats (e.g., "Projects/Marketing/Campaigns")
- Limit hierarchy depth to 3-5 levels for best performance
- Include hierarchical information in search queries since direct filtering isn't yet supported
- Create clear hierarchies in
Relationship Design
- Use specific relationship types that convey semantic meaning
- Add relevant metadata to relationships to enhance context
- Create bidirectional relationships when appropriate
- Avoid creating too many relationships per memory item
Conversation Context
- Include relevant parts of conversations for context
- Limit context to 5-10 turns for optimal performance
- Include both user and assistant messages for complete context
Search Queries
- Write detailed 2-3 sentence queries with specific details
- Include relevant time frames, people, or topics
- Mention metadata information in your natural language query
- Use
userId
filtering when you need to limit results to a specific user
Examples of Context-Rich Queries
"Find all discussions about the authentication service outage from last week's incident response meetings. I need to review the root cause analysis and the mitigation steps we implemented."
"Locate our customer feedback analysis from the Q1 review sessions. I'm specifically looking for insights about the mobile app user experience and any prioritized improvements we agreed on."
"Find documentation about our API rate limiting implementation from the technical design discussions. I need details about how we handle authentication failures and retry mechanisms."
Next Steps
- Explore the Memory Model
- Learn about ACL and Tenancy for user and access management