powermem 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- powermem/__init__.py +103 -0
- powermem/agent/__init__.py +35 -0
- powermem/agent/abstract/__init__.py +22 -0
- powermem/agent/abstract/collaboration.py +259 -0
- powermem/agent/abstract/context.py +187 -0
- powermem/agent/abstract/manager.py +232 -0
- powermem/agent/abstract/permission.py +217 -0
- powermem/agent/abstract/privacy.py +267 -0
- powermem/agent/abstract/scope.py +199 -0
- powermem/agent/agent.py +791 -0
- powermem/agent/components/__init__.py +18 -0
- powermem/agent/components/collaboration_coordinator.py +645 -0
- powermem/agent/components/permission_controller.py +586 -0
- powermem/agent/components/privacy_protector.py +767 -0
- powermem/agent/components/scope_controller.py +685 -0
- powermem/agent/factories/__init__.py +16 -0
- powermem/agent/factories/agent_factory.py +266 -0
- powermem/agent/factories/config_factory.py +308 -0
- powermem/agent/factories/memory_factory.py +229 -0
- powermem/agent/implementations/__init__.py +16 -0
- powermem/agent/implementations/hybrid.py +728 -0
- powermem/agent/implementations/multi_agent.py +1040 -0
- powermem/agent/implementations/multi_user.py +1020 -0
- powermem/agent/types.py +53 -0
- powermem/agent/wrappers/__init__.py +14 -0
- powermem/agent/wrappers/agent_memory_wrapper.py +427 -0
- powermem/agent/wrappers/compatibility_wrapper.py +520 -0
- powermem/config_loader.py +318 -0
- powermem/configs.py +249 -0
- powermem/core/__init__.py +19 -0
- powermem/core/async_memory.py +1493 -0
- powermem/core/audit.py +258 -0
- powermem/core/base.py +165 -0
- powermem/core/memory.py +1567 -0
- powermem/core/setup.py +162 -0
- powermem/core/telemetry.py +215 -0
- powermem/integrations/__init__.py +17 -0
- powermem/integrations/embeddings/__init__.py +13 -0
- powermem/integrations/embeddings/aws_bedrock.py +100 -0
- powermem/integrations/embeddings/azure_openai.py +55 -0
- powermem/integrations/embeddings/base.py +31 -0
- powermem/integrations/embeddings/config/base.py +132 -0
- powermem/integrations/embeddings/configs.py +31 -0
- powermem/integrations/embeddings/factory.py +48 -0
- powermem/integrations/embeddings/gemini.py +39 -0
- powermem/integrations/embeddings/huggingface.py +41 -0
- powermem/integrations/embeddings/langchain.py +35 -0
- powermem/integrations/embeddings/lmstudio.py +29 -0
- powermem/integrations/embeddings/mock.py +11 -0
- powermem/integrations/embeddings/ollama.py +53 -0
- powermem/integrations/embeddings/openai.py +49 -0
- powermem/integrations/embeddings/qwen.py +102 -0
- powermem/integrations/embeddings/together.py +31 -0
- powermem/integrations/embeddings/vertexai.py +54 -0
- powermem/integrations/llm/__init__.py +18 -0
- powermem/integrations/llm/anthropic.py +87 -0
- powermem/integrations/llm/base.py +132 -0
- powermem/integrations/llm/config/anthropic.py +56 -0
- powermem/integrations/llm/config/azure.py +56 -0
- powermem/integrations/llm/config/base.py +62 -0
- powermem/integrations/llm/config/deepseek.py +56 -0
- powermem/integrations/llm/config/ollama.py +56 -0
- powermem/integrations/llm/config/openai.py +79 -0
- powermem/integrations/llm/config/qwen.py +68 -0
- powermem/integrations/llm/config/qwen_asr.py +46 -0
- powermem/integrations/llm/config/vllm.py +56 -0
- powermem/integrations/llm/configs.py +26 -0
- powermem/integrations/llm/deepseek.py +106 -0
- powermem/integrations/llm/factory.py +118 -0
- powermem/integrations/llm/gemini.py +201 -0
- powermem/integrations/llm/langchain.py +65 -0
- powermem/integrations/llm/ollama.py +106 -0
- powermem/integrations/llm/openai.py +166 -0
- powermem/integrations/llm/openai_structured.py +80 -0
- powermem/integrations/llm/qwen.py +207 -0
- powermem/integrations/llm/qwen_asr.py +171 -0
- powermem/integrations/llm/vllm.py +106 -0
- powermem/integrations/rerank/__init__.py +20 -0
- powermem/integrations/rerank/base.py +43 -0
- powermem/integrations/rerank/config/__init__.py +7 -0
- powermem/integrations/rerank/config/base.py +27 -0
- powermem/integrations/rerank/configs.py +23 -0
- powermem/integrations/rerank/factory.py +68 -0
- powermem/integrations/rerank/qwen.py +159 -0
- powermem/intelligence/__init__.py +17 -0
- powermem/intelligence/ebbinghaus_algorithm.py +354 -0
- powermem/intelligence/importance_evaluator.py +361 -0
- powermem/intelligence/intelligent_memory_manager.py +284 -0
- powermem/intelligence/manager.py +148 -0
- powermem/intelligence/plugin.py +229 -0
- powermem/prompts/__init__.py +29 -0
- powermem/prompts/graph/graph_prompts.py +217 -0
- powermem/prompts/graph/graph_tools_prompts.py +469 -0
- powermem/prompts/importance_evaluation.py +246 -0
- powermem/prompts/intelligent_memory_prompts.py +163 -0
- powermem/prompts/templates.py +193 -0
- powermem/storage/__init__.py +14 -0
- powermem/storage/adapter.py +896 -0
- powermem/storage/base.py +109 -0
- powermem/storage/config/base.py +13 -0
- powermem/storage/config/oceanbase.py +58 -0
- powermem/storage/config/pgvector.py +52 -0
- powermem/storage/config/sqlite.py +27 -0
- powermem/storage/configs.py +159 -0
- powermem/storage/factory.py +59 -0
- powermem/storage/migration_manager.py +438 -0
- powermem/storage/oceanbase/__init__.py +8 -0
- powermem/storage/oceanbase/constants.py +162 -0
- powermem/storage/oceanbase/oceanbase.py +1384 -0
- powermem/storage/oceanbase/oceanbase_graph.py +1441 -0
- powermem/storage/pgvector/__init__.py +7 -0
- powermem/storage/pgvector/pgvector.py +420 -0
- powermem/storage/sqlite/__init__.py +0 -0
- powermem/storage/sqlite/sqlite.py +218 -0
- powermem/storage/sqlite/sqlite_vector_store.py +311 -0
- powermem/utils/__init__.py +35 -0
- powermem/utils/utils.py +605 -0
- powermem/version.py +23 -0
- powermem-0.1.0.dist-info/METADATA +187 -0
- powermem-0.1.0.dist-info/RECORD +123 -0
- powermem-0.1.0.dist-info/WHEEL +5 -0
- powermem-0.1.0.dist-info/licenses/LICENSE +206 -0
- powermem-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Importance evaluation prompts
|
|
3
|
+
|
|
4
|
+
This module provides prompts for importance evaluation operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
from .templates import PromptTemplates
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ImportanceEvaluationPrompts(PromptTemplates):
|
|
15
|
+
"""
|
|
16
|
+
Prompts for importance evaluation operations.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
|
20
|
+
"""
|
|
21
|
+
Initialize importance evaluation prompts.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
config: Configuration dictionary
|
|
25
|
+
"""
|
|
26
|
+
super().__init__(config)
|
|
27
|
+
self._load_importance_evaluation_templates()
|
|
28
|
+
|
|
29
|
+
def _load_importance_evaluation_templates(self) -> None:
|
|
30
|
+
"""Load importance evaluation specific templates."""
|
|
31
|
+
# Check for custom prompt in config
|
|
32
|
+
custom_prompt = self.config.get("custom_importance_evaluation_prompt")
|
|
33
|
+
|
|
34
|
+
# Use custom prompt if provided, otherwise use default
|
|
35
|
+
if custom_prompt:
|
|
36
|
+
default_system_prompt = custom_prompt
|
|
37
|
+
logger.info("Using custom importance evaluation prompt from config")
|
|
38
|
+
else:
|
|
39
|
+
default_system_prompt = """You are an AI assistant that evaluates the importance of memory content on a scale from 0.0 to 1.0.
|
|
40
|
+
|
|
41
|
+
Your task is to analyze memory content and assess its importance based on multiple criteria:
|
|
42
|
+
- Relevance: How relevant is this information to the user's needs and interests?
|
|
43
|
+
- Novelty: How new or unique is this information?
|
|
44
|
+
- Emotional Impact: How emotionally significant is this content?
|
|
45
|
+
- Actionability: How actionable or useful is this information?
|
|
46
|
+
- Factual Value: How factual and reliable is this information?
|
|
47
|
+
- Personal Significance: How personally important is this to the user?
|
|
48
|
+
|
|
49
|
+
Always provide detailed reasoning for your evaluation and return results in structured JSON format."""
|
|
50
|
+
|
|
51
|
+
importance_templates = {
|
|
52
|
+
"system": {
|
|
53
|
+
"importance_evaluator": default_system_prompt
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
"user": {
|
|
57
|
+
"evaluate_importance": """You are an AI assistant that evaluates the importance of memory content on a scale from 0.0 to 1.0.
|
|
58
|
+
|
|
59
|
+
Content to evaluate: "{content}"
|
|
60
|
+
|
|
61
|
+
{metadata_section}
|
|
62
|
+
{context_section}
|
|
63
|
+
Please evaluate the importance of this content based on the following criteria:
|
|
64
|
+
- Relevance: How relevant is this information to the user's needs and interests?
|
|
65
|
+
- Novelty: How new or unique is this information?
|
|
66
|
+
- Emotional Impact: How emotionally significant is this content?
|
|
67
|
+
- Actionability: How actionable or useful is this information?
|
|
68
|
+
- Factual Value: How factual and reliable is this information?
|
|
69
|
+
- Personal Significance: How personally important is this to the user?
|
|
70
|
+
|
|
71
|
+
Respond with a JSON object containing:
|
|
72
|
+
{{
|
|
73
|
+
"importance_score": <float between 0.0 and 1.0>,
|
|
74
|
+
"reasoning": "<brief explanation of the score>",
|
|
75
|
+
"criteria_scores": {{
|
|
76
|
+
"relevance": <float>,
|
|
77
|
+
"novelty": <float>,
|
|
78
|
+
"emotional_impact": <float>,
|
|
79
|
+
"actionable": <float>,
|
|
80
|
+
"factual": <float>,
|
|
81
|
+
"personal": <float>
|
|
82
|
+
}}
|
|
83
|
+
}}""",
|
|
84
|
+
|
|
85
|
+
"evaluate_importance_with_metadata": """Metadata: {metadata}
|
|
86
|
+
|
|
87
|
+
""",
|
|
88
|
+
|
|
89
|
+
"evaluate_importance_with_context": """Context: {context}
|
|
90
|
+
|
|
91
|
+
""",
|
|
92
|
+
|
|
93
|
+
"detailed_importance_breakdown": """Provide a detailed breakdown of importance evaluation for the following content:
|
|
94
|
+
|
|
95
|
+
Content: "{content}"
|
|
96
|
+
|
|
97
|
+
{metadata_section}
|
|
98
|
+
{context_section}
|
|
99
|
+
|
|
100
|
+
For each criterion, provide:
|
|
101
|
+
1. A score from 0.0 to 1.0
|
|
102
|
+
2. Brief reasoning for the score
|
|
103
|
+
3. Key factors that influenced the evaluation
|
|
104
|
+
|
|
105
|
+
Criteria to evaluate:
|
|
106
|
+
- Relevance: How relevant is this information to the user's needs and interests?
|
|
107
|
+
- Novelty: How new or unique is this information?
|
|
108
|
+
- Emotional Impact: How emotionally significant is this content?
|
|
109
|
+
- Actionability: How actionable or useful is this information?
|
|
110
|
+
- Factual Value: How factual and reliable is this information?
|
|
111
|
+
- Personal Significance: How personally important is this to the user?
|
|
112
|
+
|
|
113
|
+
Respond with a JSON object containing:
|
|
114
|
+
{{
|
|
115
|
+
"overall_score": <float between 0.0 and 1.0>,
|
|
116
|
+
"reasoning": "<overall explanation>",
|
|
117
|
+
"criteria_scores": {{
|
|
118
|
+
"relevance": {{
|
|
119
|
+
"score": <float>,
|
|
120
|
+
"reasoning": "<explanation>"
|
|
121
|
+
}},
|
|
122
|
+
"novelty": {{
|
|
123
|
+
"score": <float>,
|
|
124
|
+
"reasoning": "<explanation>"
|
|
125
|
+
}},
|
|
126
|
+
"emotional_impact": {{
|
|
127
|
+
"score": <float>,
|
|
128
|
+
"reasoning": "<explanation>"
|
|
129
|
+
}},
|
|
130
|
+
"actionable": {{
|
|
131
|
+
"score": <float>,
|
|
132
|
+
"reasoning": "<explanation>"
|
|
133
|
+
}},
|
|
134
|
+
"factual": {{
|
|
135
|
+
"score": <float>,
|
|
136
|
+
"reasoning": "<explanation>"
|
|
137
|
+
}},
|
|
138
|
+
"personal": {{
|
|
139
|
+
"score": <float>,
|
|
140
|
+
"reasoning": "<explanation>"
|
|
141
|
+
}}
|
|
142
|
+
}}
|
|
143
|
+
}}"""
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Add importance evaluation templates to existing templates
|
|
148
|
+
for category, templates in importance_templates.items():
|
|
149
|
+
if category not in self.templates:
|
|
150
|
+
self.templates[category] = {}
|
|
151
|
+
self.templates[category].update(templates)
|
|
152
|
+
|
|
153
|
+
def get_importance_evaluation_prompt(
|
|
154
|
+
self,
|
|
155
|
+
content: str,
|
|
156
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
157
|
+
context: Optional[Dict[str, Any]] = None
|
|
158
|
+
) -> str:
|
|
159
|
+
"""
|
|
160
|
+
Get importance evaluation prompt.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
content: Content to evaluate
|
|
164
|
+
metadata: Additional metadata
|
|
165
|
+
context: Additional context
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Formatted prompt
|
|
169
|
+
"""
|
|
170
|
+
# Build metadata section if provided
|
|
171
|
+
metadata_section = ""
|
|
172
|
+
if metadata:
|
|
173
|
+
metadata_section = self.format_template(
|
|
174
|
+
"user",
|
|
175
|
+
"evaluate_importance_with_metadata",
|
|
176
|
+
metadata=metadata
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Build context section if provided
|
|
180
|
+
context_section = ""
|
|
181
|
+
if context:
|
|
182
|
+
context_section = self.format_template(
|
|
183
|
+
"user",
|
|
184
|
+
"evaluate_importance_with_context",
|
|
185
|
+
context=context
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return self.format_template(
|
|
189
|
+
"user",
|
|
190
|
+
"evaluate_importance",
|
|
191
|
+
content=content,
|
|
192
|
+
metadata_section=metadata_section,
|
|
193
|
+
context_section=context_section
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
def get_detailed_importance_breakdown_prompt(
|
|
197
|
+
self,
|
|
198
|
+
content: str,
|
|
199
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
200
|
+
context: Optional[Dict[str, Any]] = None
|
|
201
|
+
) -> str:
|
|
202
|
+
"""
|
|
203
|
+
Get detailed importance breakdown prompt.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
content: Content to evaluate
|
|
207
|
+
metadata: Additional metadata
|
|
208
|
+
context: Additional context
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Formatted prompt
|
|
212
|
+
"""
|
|
213
|
+
# Build metadata section if provided
|
|
214
|
+
metadata_section = ""
|
|
215
|
+
if metadata:
|
|
216
|
+
metadata_section = self.format_template(
|
|
217
|
+
"user",
|
|
218
|
+
"evaluate_importance_with_metadata",
|
|
219
|
+
metadata=metadata
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Build context section if provided
|
|
223
|
+
context_section = ""
|
|
224
|
+
if context:
|
|
225
|
+
context_section = self.format_template(
|
|
226
|
+
"user",
|
|
227
|
+
"evaluate_importance_with_context",
|
|
228
|
+
context=context
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
return self.format_template(
|
|
232
|
+
"user",
|
|
233
|
+
"detailed_importance_breakdown",
|
|
234
|
+
content=content,
|
|
235
|
+
metadata_section=metadata_section,
|
|
236
|
+
context_section=context_section
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
def get_system_prompt(self) -> str:
|
|
240
|
+
"""
|
|
241
|
+
Get system prompt for importance evaluation.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
System prompt
|
|
245
|
+
"""
|
|
246
|
+
return self.get_template("system", "importance_evaluator")
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Intelligent memory prompts for fact extraction and memory consolidation
|
|
3
|
+
|
|
4
|
+
This module provides prompts for intelligent memory operations including:
|
|
5
|
+
1. Fact extraction from conversations
|
|
6
|
+
2. Memory consolidation and deduplication
|
|
7
|
+
3. Memory update operations (ADD/UPDATE/DELETE)
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import Dict, Any, Optional, List
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Use FACT_RETRIEVAL_PROMPT for compatibility
|
|
19
|
+
FACT_RETRIEVAL_PROMPT = f"""You are a Personal Information Organizer. Extract relevant facts, memories, and preferences from conversations into distinct, manageable facts.
|
|
20
|
+
|
|
21
|
+
Information Types: Personal preferences, details (names, relationships, dates), plans, activities, health/wellness, professional, miscellaneous.
|
|
22
|
+
|
|
23
|
+
CRITICAL Rules:
|
|
24
|
+
1. TEMPORAL: ALWAYS extract time info (dates, relative refs like "yesterday", "last week"). Include in facts (e.g., "Went to Hawaii in May 2023" or "Went to Hawaii last year", not just "Went to Hawaii"). Preserve relative time refs for later calculation.
|
|
25
|
+
2. COMPLETE: Extract self-contained facts with who/what/when/where when available.
|
|
26
|
+
3. SEPARATE: Extract distinct facts separately, especially when they have different time periods.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
Input: Hi.
|
|
30
|
+
Output: {{"facts" : []}}
|
|
31
|
+
|
|
32
|
+
Input: Yesterday, I met John at 3pm. We discussed the project.
|
|
33
|
+
Output: {{"facts" : ["Met John at 3pm yesterday", "Discussed project with John yesterday"]}}
|
|
34
|
+
|
|
35
|
+
Input: Last May, I went to India. Visited Mumbai and Goa.
|
|
36
|
+
Output: {{"facts" : ["Went to India in May", "Visited Mumbai in May", "Visited Goa in May"]}}
|
|
37
|
+
|
|
38
|
+
Input: I met Sarah last year and became friends. We went to movies last month.
|
|
39
|
+
Output: {{"facts" : ["Met Sarah last year and became friends", "Went to movies with Sarah last month"]}}
|
|
40
|
+
|
|
41
|
+
Input: I'm John, a software engineer.
|
|
42
|
+
Output: {{"facts" : ["Name is John", "Is a software engineer"]}}
|
|
43
|
+
|
|
44
|
+
Rules:
|
|
45
|
+
- Today: {datetime.now().strftime("%Y-%m-%d")}
|
|
46
|
+
- Return JSON: {{"facts": ["fact1", "fact2"]}}
|
|
47
|
+
- Extract from user/assistant messages only
|
|
48
|
+
- If no relevant facts, return empty list
|
|
49
|
+
- Preserve input language
|
|
50
|
+
|
|
51
|
+
Extract facts from the conversation below:"""
|
|
52
|
+
|
|
53
|
+
# Alias for compatibility
|
|
54
|
+
FACT_EXTRACTION_PROMPT = FACT_RETRIEVAL_PROMPT
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
DEFAULT_UPDATE_MEMORY_PROMPT = """You are a memory manager. Compare new facts with existing memory. Decide: ADD, UPDATE, DELETE, or NONE.
|
|
58
|
+
|
|
59
|
+
Operations:
|
|
60
|
+
1. **ADD**: New info not in memory -> add with new ID
|
|
61
|
+
2. **UPDATE**: Info exists but different/enhanced -> update (keep same ID). Prefer fact with most information.
|
|
62
|
+
3. **DELETE**: Contradictory info -> delete (use sparingly)
|
|
63
|
+
4. **NONE**: Already present or irrelevant -> no change
|
|
64
|
+
|
|
65
|
+
Temporal Rules (CRITICAL):
|
|
66
|
+
- New fact has time info, memory doesn't -> UPDATE memory to include time
|
|
67
|
+
- Both have time, new is more specific/recent -> UPDATE to new time
|
|
68
|
+
- Time conflicts (e.g., "2022" vs "2023") -> UPDATE to more recent
|
|
69
|
+
- Preserve relative time refs (e.g., "last year", "two months ago")
|
|
70
|
+
- When merging, combine temporal info: "Met Sarah" + "Met Sarah last year" -> UPDATE to "Met Sarah last year"
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
Add: Memory: [{{"id":"0","text":"User is engineer"}}], Facts: ["Name is John"]
|
|
74
|
+
-> [{{"id":"0","text":"User is engineer","event":"NONE"}}, {{"id":"1","text":"Name is John","event":"ADD"}}]
|
|
75
|
+
|
|
76
|
+
Update (time): Memory: [{{"id":"0","text":"Went to Hawaii"}}], Facts: ["Went to Hawaii in May 2023"]
|
|
77
|
+
-> [{{"id":"0","text":"Went to Hawaii in May 2023","event":"UPDATE","old_memory":"Went to Hawaii"}}]
|
|
78
|
+
|
|
79
|
+
Update (enhance): Memory: [{{"id":"0","text":"Likes cricket"}}], Facts: ["Loves cricket with friends"]
|
|
80
|
+
-> [{{"id":"0","text":"Loves cricket with friends","event":"UPDATE","old_memory":"Likes cricket"}}]
|
|
81
|
+
|
|
82
|
+
Delete: Only clear contradictions (e.g., "Loves pizza" vs "Dislikes pizza"). Prefer UPDATE for time conflicts.
|
|
83
|
+
|
|
84
|
+
Important: Use existing IDs only. Keep same ID when updating. Always preserve temporal information.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
# Alias for compatibility
|
|
88
|
+
MEMORY_UPDATE_PROMPT = DEFAULT_UPDATE_MEMORY_PROMPT
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_memory_update_prompt(
|
|
92
|
+
retrieved_old_memory: list,
|
|
93
|
+
new_facts: list,
|
|
94
|
+
custom_prompt: Optional[str] = None
|
|
95
|
+
) -> str:
|
|
96
|
+
"""
|
|
97
|
+
Generate the prompt for memory update operations.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
retrieved_old_memory: List of existing memories with id and text
|
|
101
|
+
new_facts: List of newly extracted facts
|
|
102
|
+
custom_prompt: Optional custom prompt template
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Complete prompt string for LLM
|
|
106
|
+
"""
|
|
107
|
+
if custom_prompt is None:
|
|
108
|
+
custom_prompt = DEFAULT_UPDATE_MEMORY_PROMPT
|
|
109
|
+
|
|
110
|
+
if retrieved_old_memory:
|
|
111
|
+
current_memory_part = f"Current memory:\n```\n{retrieved_old_memory}\n```\n"
|
|
112
|
+
else:
|
|
113
|
+
current_memory_part = "Current memory is empty.\n"
|
|
114
|
+
|
|
115
|
+
# Format new facts
|
|
116
|
+
new_facts_str = "\n".join([f"- {fact}" for fact in new_facts])
|
|
117
|
+
|
|
118
|
+
return f"""{custom_prompt}
|
|
119
|
+
|
|
120
|
+
{current_memory_part}New facts:
|
|
121
|
+
```
|
|
122
|
+
{new_facts_str}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Return JSON only:
|
|
126
|
+
{{
|
|
127
|
+
"memory": [
|
|
128
|
+
{{
|
|
129
|
+
"id": "<existing ID for update/delete, new ID for add>",
|
|
130
|
+
"text": "<memory content>",
|
|
131
|
+
"event": "ADD|UPDATE|DELETE|NONE",
|
|
132
|
+
"old_memory": "<old content, required for UPDATE>"
|
|
133
|
+
}}
|
|
134
|
+
]
|
|
135
|
+
}}
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def parse_messages_for_facts(messages: list) -> str:
|
|
140
|
+
"""
|
|
141
|
+
Parse messages into a format suitable for fact extraction.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
messages: List of message dictionaries with 'role' and 'content'
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Formatted string representation of the conversation
|
|
148
|
+
"""
|
|
149
|
+
if isinstance(messages, str):
|
|
150
|
+
return messages
|
|
151
|
+
|
|
152
|
+
if not isinstance(messages, list):
|
|
153
|
+
return str(messages)
|
|
154
|
+
|
|
155
|
+
conversation = ""
|
|
156
|
+
for msg in messages:
|
|
157
|
+
if isinstance(msg, dict) and 'role' in msg and 'content' in msg:
|
|
158
|
+
role = msg['role']
|
|
159
|
+
content = msg['content']
|
|
160
|
+
if role != "system": # Skip system messages
|
|
161
|
+
conversation += f"{role}: {content}\n"
|
|
162
|
+
|
|
163
|
+
return conversation
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Prompt templates for memory operations
|
|
3
|
+
|
|
4
|
+
This module provides prompt templates for different memory operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PromptTemplates:
|
|
15
|
+
"""
|
|
16
|
+
Base class for prompt templates.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
|
20
|
+
"""
|
|
21
|
+
Initialize prompt templates.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
config: Configuration dictionary
|
|
25
|
+
"""
|
|
26
|
+
self.config = config or {}
|
|
27
|
+
self.templates = {}
|
|
28
|
+
self._load_templates()
|
|
29
|
+
|
|
30
|
+
def _load_templates(self) -> None:
|
|
31
|
+
"""Load prompt templates."""
|
|
32
|
+
# Base templates
|
|
33
|
+
self.templates = {
|
|
34
|
+
"system": {
|
|
35
|
+
"memory_assistant": """You are a memory assistant that helps users manage and retrieve information.
|
|
36
|
+
Your role is to:
|
|
37
|
+
1. Extract important facts from user input
|
|
38
|
+
2. Store memories in an organized way
|
|
39
|
+
3. Retrieve relevant memories when needed
|
|
40
|
+
4. Provide context-aware responses
|
|
41
|
+
|
|
42
|
+
Always be helpful, accurate, and respectful of user privacy.""",
|
|
43
|
+
|
|
44
|
+
"fact_extractor": """You are a fact extraction specialist. Your task is to identify and extract
|
|
45
|
+
important facts, preferences, and information from user input. Focus on:
|
|
46
|
+
- Personal preferences and opinions
|
|
47
|
+
- Important facts and data
|
|
48
|
+
- Relationships and connections
|
|
49
|
+
- Goals and intentions
|
|
50
|
+
- Contextual information
|
|
51
|
+
|
|
52
|
+
Extract only factual, verifiable information.""",
|
|
53
|
+
|
|
54
|
+
"memory_processor": """You are a memory processing specialist. Your task is to:
|
|
55
|
+
1. Analyze and categorize memories
|
|
56
|
+
2. Determine importance and relevance
|
|
57
|
+
3. Suggest memory organization strategies
|
|
58
|
+
4. Identify patterns and connections
|
|
59
|
+
|
|
60
|
+
Always prioritize user privacy and data security."""
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
"user": {
|
|
64
|
+
"extract_facts": """Extract important facts and information from the following text:
|
|
65
|
+
|
|
66
|
+
Text: {text}
|
|
67
|
+
|
|
68
|
+
Please identify:
|
|
69
|
+
1. Key facts and information
|
|
70
|
+
2. Personal preferences or opinions
|
|
71
|
+
3. Important relationships or connections
|
|
72
|
+
4. Goals or intentions
|
|
73
|
+
5. Contextual information
|
|
74
|
+
|
|
75
|
+
Return the extracted information in a structured format.""",
|
|
76
|
+
|
|
77
|
+
"process_memory": """Process the following memory for storage:
|
|
78
|
+
|
|
79
|
+
Memory: {memory}
|
|
80
|
+
Context: {context}
|
|
81
|
+
|
|
82
|
+
Please:
|
|
83
|
+
1. Determine the importance level (low, medium, high)
|
|
84
|
+
2. Suggest appropriate categorization
|
|
85
|
+
3. Identify key topics or themes
|
|
86
|
+
4. Recommend storage duration
|
|
87
|
+
|
|
88
|
+
Return your analysis in a structured format.""",
|
|
89
|
+
|
|
90
|
+
"search_memories": """Search for memories related to the following query:
|
|
91
|
+
|
|
92
|
+
Query: {query}
|
|
93
|
+
Context: {context}
|
|
94
|
+
|
|
95
|
+
Please:
|
|
96
|
+
1. Identify relevant memory categories
|
|
97
|
+
2. Suggest search strategies
|
|
98
|
+
3. Recommend filtering criteria
|
|
99
|
+
4. Provide search optimization tips
|
|
100
|
+
|
|
101
|
+
Return your recommendations in a structured format."""
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
def get_template(self, category: str, template_name: str) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Get a specific template.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
category: Template category (system, user, etc.)
|
|
111
|
+
template_name: Name of the template
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Template string
|
|
115
|
+
"""
|
|
116
|
+
return self.templates.get(category, {}).get(template_name, "")
|
|
117
|
+
|
|
118
|
+
def format_template(self, category: str, template_name: str, **kwargs) -> str:
|
|
119
|
+
"""
|
|
120
|
+
Format a template with provided variables.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
category: Template category
|
|
124
|
+
template_name: Name of the template
|
|
125
|
+
**kwargs: Variables to format the template
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Formatted template string
|
|
129
|
+
"""
|
|
130
|
+
template = self.get_template(category, template_name)
|
|
131
|
+
try:
|
|
132
|
+
return template.format(**kwargs)
|
|
133
|
+
except KeyError as e:
|
|
134
|
+
logger.error(f"Missing template variable: {e}")
|
|
135
|
+
return template
|
|
136
|
+
|
|
137
|
+
def add_template(self, category: str, template_name: str, template: str) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Add a new template.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
category: Template category
|
|
143
|
+
template_name: Name of the template
|
|
144
|
+
template: Template string
|
|
145
|
+
"""
|
|
146
|
+
if category not in self.templates:
|
|
147
|
+
self.templates[category] = {}
|
|
148
|
+
|
|
149
|
+
self.templates[category][template_name] = template
|
|
150
|
+
|
|
151
|
+
def get_all_templates(self) -> Dict[str, Dict[str, str]]:
|
|
152
|
+
"""
|
|
153
|
+
Get all templates.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Dictionary of all templates
|
|
157
|
+
"""
|
|
158
|
+
return self.templates
|
|
159
|
+
|
|
160
|
+
def export_templates(self, file_path: str) -> None:
|
|
161
|
+
"""
|
|
162
|
+
Export templates to a file.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
file_path: Path to export file
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
169
|
+
json.dump(self.templates, f, indent=2, ensure_ascii=False)
|
|
170
|
+
logger.info(f"Templates exported to {file_path}")
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.error(f"Failed to export templates: {e}")
|
|
173
|
+
|
|
174
|
+
def import_templates(self, file_path: str) -> None:
|
|
175
|
+
"""
|
|
176
|
+
Import templates from a file.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
file_path: Path to import file
|
|
180
|
+
"""
|
|
181
|
+
try:
|
|
182
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
183
|
+
imported_templates = json.load(f)
|
|
184
|
+
|
|
185
|
+
# Merge with existing templates
|
|
186
|
+
for category, templates in imported_templates.items():
|
|
187
|
+
if category not in self.templates:
|
|
188
|
+
self.templates[category] = {}
|
|
189
|
+
self.templates[category].update(templates)
|
|
190
|
+
|
|
191
|
+
logger.info(f"Templates imported from {file_path}")
|
|
192
|
+
except Exception as e:
|
|
193
|
+
logger.error(f"Failed to import templates: {e}")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Storage layer for memory management
|
|
3
|
+
|
|
4
|
+
This module provides the storage abstraction and implementations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .base import VectorStoreBase
|
|
8
|
+
from .factory import VectorStoreFactory, GraphStoreFactory
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"VectorStoreBase",
|
|
12
|
+
"VectorStoreFactory",
|
|
13
|
+
"GraphStoreFactory",
|
|
14
|
+
]
|