reme-ai 0.1.4__py3-none-any.whl → 0.1.5__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.
- reme_ai/__init__.py +1 -1
- reme_ai/app.py +1 -1
- reme_ai/config/default.yaml +40 -5
- reme_ai/react/simple_react_op.py +11 -8
- reme_ai/retrieve/personal/extract_time_op.py +2 -3
- reme_ai/retrieve/personal/fuse_rerank_op.py +1 -1
- reme_ai/retrieve/personal/print_memory_op.py +1 -1
- reme_ai/retrieve/personal/read_message_op.py +1 -1
- reme_ai/retrieve/personal/retrieve_memory_op.py +34 -4
- reme_ai/retrieve/personal/semantic_rank_op.py +4 -4
- reme_ai/retrieve/personal/set_query_op.py +1 -1
- reme_ai/retrieve/task/build_query_op.py +2 -2
- reme_ai/retrieve/task/merge_memory_op.py +1 -1
- reme_ai/retrieve/task/rerank_memory_op.py +4 -4
- reme_ai/retrieve/task/rewrite_memory_op.py +6 -6
- reme_ai/service/__init__.py +0 -0
- reme_ai/service/base_memory_service.py +112 -0
- reme_ai/service/personal_memory_service.py +128 -0
- reme_ai/service/task_memory_service.py +126 -0
- reme_ai/summary/personal/contra_repeat_op.py +2 -2
- reme_ai/summary/personal/get_observation_op.py +4 -4
- reme_ai/summary/personal/get_observation_with_time_op.py +4 -4
- reme_ai/summary/personal/get_reflection_subject_op.py +4 -4
- reme_ai/summary/personal/info_filter_op.py +4 -4
- reme_ai/summary/personal/load_today_memory_op.py +6 -7
- reme_ai/summary/personal/long_contra_repeat_op.py +4 -4
- reme_ai/summary/personal/update_insight_op.py +4 -4
- reme_ai/summary/task/comparative_extraction_op.py +9 -7
- reme_ai/summary/task/failure_extraction_op.py +7 -5
- reme_ai/summary/task/memory_deduplication_op.py +6 -6
- reme_ai/summary/task/memory_validation_op.py +8 -6
- reme_ai/summary/task/simple_comparative_summary_op.py +6 -4
- reme_ai/summary/task/simple_summary_op.py +6 -4
- reme_ai/summary/task/success_extraction_op.py +7 -5
- reme_ai/summary/task/trajectory_preprocess_op.py +1 -1
- reme_ai/summary/task/trajectory_segmentation_op.py +6 -4
- reme_ai/vector_store/delete_memory_op.py +1 -1
- reme_ai/vector_store/recall_vector_store_op.py +3 -3
- reme_ai/vector_store/update_memory_freq_op.py +1 -1
- reme_ai/vector_store/update_memory_utility_op.py +1 -1
- reme_ai/vector_store/update_vector_store_op.py +3 -3
- reme_ai/vector_store/vector_store_action_op.py +21 -18
- {reme_ai-0.1.4.dist-info → reme_ai-0.1.5.dist-info}/METADATA +8 -6
- reme_ai-0.1.5.dist-info/RECORD +87 -0
- reme_ai-0.1.4.dist-info/RECORD +0 -83
- {reme_ai-0.1.4.dist-info → reme_ai-0.1.5.dist-info}/WHEEL +0 -0
- {reme_ai-0.1.4.dist-info → reme_ai-0.1.5.dist-info}/entry_points.txt +0 -0
- {reme_ai-0.1.4.dist-info → reme_ai-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {reme_ai-0.1.4.dist-info → reme_ai-0.1.5.dist-info}/top_level.txt +0 -0
reme_ai/__init__.py
CHANGED
reme_ai/app.py
CHANGED
reme_ai/config/default.yaml
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# default config.yaml
|
2
1
|
backend: http
|
3
2
|
language: ""
|
4
3
|
thread_pool_max_workers: 32
|
@@ -18,6 +17,9 @@ http:
|
|
18
17
|
flow:
|
19
18
|
retrieve_task_memory:
|
20
19
|
flow_content: build_query_op >> recall_vector_store_op >> rerank_memory_op >> rewrite_memory_op
|
20
|
+
stream: false
|
21
|
+
use_async: true
|
22
|
+
service_type: http+mcp
|
21
23
|
description: "Retrieves the most relevant top-k memory experiences from historical data based on the current query to enhance task-solving capabilities"
|
22
24
|
input_schema:
|
23
25
|
query:
|
@@ -27,6 +29,9 @@ flow:
|
|
27
29
|
|
28
30
|
summary_task_memory:
|
29
31
|
flow_content: trajectory_preprocess_op >> (success_extraction_op|failure_extraction_op|comparative_extraction_op) >> memory_validation_op >> update_vector_store_op
|
32
|
+
stream: false
|
33
|
+
use_async: true
|
34
|
+
service_type: http+mcp
|
30
35
|
description: "Summarizes conversation trajectories or messages into structured memory representations for long-term storage"
|
31
36
|
input_schema:
|
32
37
|
trajectories:
|
@@ -36,6 +41,9 @@ flow:
|
|
36
41
|
|
37
42
|
retrieve_personal_memory:
|
38
43
|
flow_content: set_query_op >> (extract_time_op | (retrieve_memory_op >> semantic_rank_op)) >> fuse_rerank_op
|
44
|
+
stream: false
|
45
|
+
use_async: true
|
46
|
+
service_type: http+mcp
|
39
47
|
description: "Retrieves the most relevant personal memories from historical data based on the query to enhance response quality"
|
40
48
|
input_schema:
|
41
49
|
query:
|
@@ -45,6 +53,9 @@ flow:
|
|
45
53
|
|
46
54
|
summary_personal_memory:
|
47
55
|
flow_content: info_filter_op >> (get_observation_op | get_observation_with_time_op | load_today_memory_op) >> contra_repeat_op >> update_vector_store_op
|
56
|
+
stream: false
|
57
|
+
use_async: true
|
58
|
+
service_type: http+mcp
|
48
59
|
description: "Consolidates user observations and memories by filtering information and removing redundancies for efficient storage"
|
49
60
|
input_schema:
|
50
61
|
trajectories:
|
@@ -54,6 +65,9 @@ flow:
|
|
54
65
|
|
55
66
|
retrieve_task_memory_simple:
|
56
67
|
flow_content: build_query_op >> recall_vector_store_op >> merge_memory_op
|
68
|
+
stream: false
|
69
|
+
use_async: true
|
70
|
+
service_type: http+mcp
|
57
71
|
description: "Retrieves the most relevant top-k memory experiences from historical data based on the current query with simplified processing"
|
58
72
|
input_schema:
|
59
73
|
query:
|
@@ -63,6 +77,9 @@ flow:
|
|
63
77
|
|
64
78
|
summary_task_memory_simple:
|
65
79
|
flow_content: simple_summary_op >> update_vector_store_op
|
80
|
+
stream: false
|
81
|
+
use_async: true
|
82
|
+
service_type: http+mcp
|
66
83
|
description: "Summarizes conversation trajectories or messages into memories using a simplified approach"
|
67
84
|
input_schema:
|
68
85
|
trajectories:
|
@@ -72,16 +89,22 @@ flow:
|
|
72
89
|
|
73
90
|
vector_store:
|
74
91
|
flow_content: vector_store_action_op
|
92
|
+
stream: false
|
93
|
+
use_async: true
|
94
|
+
service_type: http+mcp
|
75
95
|
description: "Directly operates on the vector store with various management actions"
|
76
96
|
input_schema:
|
77
97
|
action:
|
78
98
|
type: "str"
|
79
99
|
description: "vector store operations"
|
80
100
|
required: true
|
81
|
-
enum: [ copy, delete, delete_ids, dump, load ]
|
101
|
+
enum: [ copy, delete, delete_ids, dump, load, list]
|
82
102
|
|
83
103
|
record_task_memory:
|
84
104
|
flow_content: update_memory_freq_op >> update_memory_utility_op >> update_vector_store_op
|
105
|
+
stream: false
|
106
|
+
use_async: true
|
107
|
+
service_type: http+mcp
|
85
108
|
description: "Update the freq & utility attributes of retrieved task memories"
|
86
109
|
input_schema:
|
87
110
|
workspace_id:
|
@@ -99,6 +122,9 @@ flow:
|
|
99
122
|
|
100
123
|
delete_task_memory:
|
101
124
|
flow_content: delete_memory_op >> update_vector_store_op
|
125
|
+
stream: false
|
126
|
+
use_async: true
|
127
|
+
service_type: http+mcp
|
102
128
|
description: "Delete task memories when utility/freq < utility_threshold and freq >= freq_threshold"
|
103
129
|
input_schema:
|
104
130
|
workspace_id:
|
@@ -116,6 +142,9 @@ flow:
|
|
116
142
|
|
117
143
|
react:
|
118
144
|
flow_content: simple_react_op
|
145
|
+
stream: false
|
146
|
+
use_async: true
|
147
|
+
service_type: http+mcp
|
119
148
|
description: "React to the current task with an agent"
|
120
149
|
input_schema:
|
121
150
|
query:
|
@@ -142,11 +171,18 @@ op:
|
|
142
171
|
llm:
|
143
172
|
default:
|
144
173
|
backend: openai_compatible
|
145
|
-
# model_name: qwen3-30b-a3b-thinking-2507
|
146
174
|
model_name: qwen3-30b-a3b-instruct-2507
|
147
175
|
params:
|
148
176
|
temperature: 0.6
|
149
177
|
|
178
|
+
qwen3_30b_instruct:
|
179
|
+
backend: openai_compatible
|
180
|
+
model_name: qwen3-30b-a3b-instruct-2507
|
181
|
+
|
182
|
+
qwen3_30b_thinking:
|
183
|
+
backend: openai_compatible
|
184
|
+
model_name: qwen3-30b-a3b-thinking-2507
|
185
|
+
|
150
186
|
embedding_model:
|
151
187
|
default:
|
152
188
|
backend: openai_compatible
|
@@ -156,8 +192,7 @@ embedding_model:
|
|
156
192
|
|
157
193
|
vector_store:
|
158
194
|
default:
|
159
|
-
backend:
|
195
|
+
backend: memory
|
160
196
|
embedding_model: default
|
161
197
|
# params:
|
162
198
|
# hosts: "http://localhost:9200"
|
163
|
-
# hosts: "http://11.160.132.46:8200"
|
reme_ai/react/simple_react_op.py
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
1
3
|
from flowllm import C
|
2
4
|
from flowllm.context.flow_context import FlowContext
|
3
|
-
from flowllm.op.
|
5
|
+
from flowllm.op.llm.react_llm_op import ReactLLMOp
|
4
6
|
|
5
7
|
|
6
8
|
@C.register_op()
|
7
|
-
class SimpleReactOp(
|
9
|
+
class SimpleReactOp(ReactLLMOp):
|
8
10
|
...
|
9
11
|
|
10
12
|
|
11
|
-
|
13
|
+
async def main():
|
12
14
|
from reme_ai.config.config_parser import ConfigParser
|
13
15
|
|
14
|
-
C.
|
16
|
+
C.set_service_config(parser=ConfigParser, config_name="config=default").init_by_service_config()
|
15
17
|
context = FlowContext(query="茅台和五粮现在股价多少?")
|
16
18
|
|
17
19
|
op = SimpleReactOp()
|
18
|
-
op(context=context)
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
await op.async_call(context=context)
|
21
|
+
print(context.response.answer)
|
22
|
+
|
23
|
+
if __name__ == "__main__":
|
24
|
+
asyncio.run(main())
|
@@ -23,10 +23,9 @@ class ExtractTimeOp(BaseLLMOp):
|
|
23
23
|
"""
|
24
24
|
|
25
25
|
def get_language_value(self, value_dict: dict):
|
26
|
-
|
27
26
|
return value_dict.get(self.language, value_dict.get("en"))
|
28
27
|
|
29
|
-
def
|
28
|
+
async def async_execute(self):
|
30
29
|
"""
|
31
30
|
Executes the primary logic of identifying and extracting time data from an LLM's response.
|
32
31
|
|
@@ -59,7 +58,7 @@ class ExtractTimeOp(BaseLLMOp):
|
|
59
58
|
logger.info(f"Extracting time from query: {query[:100]}...")
|
60
59
|
|
61
60
|
# Invoke the LLM to generate a response
|
62
|
-
response = self.llm.
|
61
|
+
response = await self.llm.achat([Message(role=Role.USER, content=full_prompt)])
|
63
62
|
|
64
63
|
# Handle empty or unsuccessful responses
|
65
64
|
if not response or not response.content:
|
@@ -45,7 +45,7 @@ class FuseRerankOp(BaseLLMOp):
|
|
45
45
|
memory.metadata["match_msg_flag"] = str(int(match_msg_flag))
|
46
46
|
return match_event_flag, match_msg_flag
|
47
47
|
|
48
|
-
def
|
48
|
+
async def async_execute(self):
|
49
49
|
"""
|
50
50
|
Executes the reranking process on memories considering their scores, types, and temporal relevance.
|
51
51
|
|
@@ -1,13 +1,43 @@
|
|
1
|
-
from
|
1
|
+
from typing import List
|
2
2
|
|
3
|
-
from
|
3
|
+
from flowllm import C, BaseLLMOp
|
4
|
+
from flowllm.schema.vector_node import VectorNode
|
5
|
+
from loguru import logger
|
6
|
+
|
7
|
+
from reme_ai.schema.memory import BaseMemory, vector_node_to_memory
|
4
8
|
|
5
9
|
|
6
10
|
@C.register_op()
|
7
|
-
class RetrieveMemoryOp(
|
11
|
+
class RetrieveMemoryOp(BaseLLMOp):
|
8
12
|
"""
|
9
13
|
Retrieves memories based on specified criteria such as status, type, and timestamp.
|
10
14
|
Processes these memories concurrently, sorts them by similarity, and logs the activity,
|
11
15
|
facilitating efficient memory retrieval operations within a given scope.
|
12
16
|
"""
|
13
|
-
|
17
|
+
|
18
|
+
async def async_execute(self):
|
19
|
+
recall_key: str = self.op_params.get("recall_key", "query")
|
20
|
+
top_k: int = self.context.get("top_k", 3)
|
21
|
+
|
22
|
+
query: str = self.context[recall_key]
|
23
|
+
assert query, "query should be not empty!"
|
24
|
+
|
25
|
+
workspace_id: str = self.context.workspace_id
|
26
|
+
nodes: List[VectorNode] = await self.vector_store.async_search(query=query,
|
27
|
+
workspace_id=workspace_id,
|
28
|
+
top_k=top_k)
|
29
|
+
memory_list: List[BaseMemory] = []
|
30
|
+
memory_content_list: List[str] = []
|
31
|
+
for node in nodes:
|
32
|
+
memory: BaseMemory = vector_node_to_memory(node)
|
33
|
+
if memory.content not in memory_content_list:
|
34
|
+
memory_list.append(memory)
|
35
|
+
memory_content_list.append(memory.content)
|
36
|
+
logger.info(f"retrieve memory.size={len(memory_list)}")
|
37
|
+
|
38
|
+
threshold_score: float | None = self.op_params.get("threshold_score", None)
|
39
|
+
if threshold_score is not None:
|
40
|
+
memory_list = [mem for mem in memory_list if mem.score >= threshold_score or mem.score is None]
|
41
|
+
logger.info(f"after filter by threshold_score size={len(memory_list)}")
|
42
|
+
|
43
|
+
self.context.response.metadata["memory_list"] = memory_list
|
@@ -19,7 +19,7 @@ class SemanticRankOp(BaseLLMOp):
|
|
19
19
|
"""
|
20
20
|
file_path: str = __file__
|
21
21
|
|
22
|
-
def
|
22
|
+
async def async_execute(self):
|
23
23
|
"""
|
24
24
|
Executes the primary workflow of the SemanticRankOp which includes:
|
25
25
|
- Retrieves query and memory list from context.
|
@@ -56,7 +56,7 @@ class SemanticRankOp(BaseLLMOp):
|
|
56
56
|
logger.info(f"After deduplication: {len(memory_list)} memories")
|
57
57
|
|
58
58
|
# Perform semantic ranking using LLM
|
59
|
-
ranked_memories = self._semantic_rank_memories(query, memory_list)
|
59
|
+
ranked_memories = await self._semantic_rank_memories(query, memory_list)
|
60
60
|
if ranked_memories:
|
61
61
|
memory_list = ranked_memories
|
62
62
|
|
@@ -71,7 +71,7 @@ class SemanticRankOp(BaseLLMOp):
|
|
71
71
|
# Save ranked memories back to context
|
72
72
|
self.context.response.metadata["memory_list"] = memory_list
|
73
73
|
|
74
|
-
def _semantic_rank_memories(self, query: str, memories: List[BaseMemory]) -> List[BaseMemory]:
|
74
|
+
async def _semantic_rank_memories(self, query: str, memories: List[BaseMemory]) -> List[BaseMemory]:
|
75
75
|
"""
|
76
76
|
Use LLM to semantically rank memories based on relevance to the query
|
77
77
|
"""
|
@@ -93,7 +93,7 @@ Memories:
|
|
93
93
|
Please respond in JSON format:
|
94
94
|
{{"rankings": [{{"index": 0, "score": 0.8}}, {{"index": 1, "score": 0.6}}, ...]}}"""
|
95
95
|
|
96
|
-
response = self.llm.
|
96
|
+
response = await self.llm.achat([Message(role=Role.USER, content=prompt)])
|
97
97
|
|
98
98
|
if not response or not response.content:
|
99
99
|
logger.warning("LLM ranking failed, using original order")
|
@@ -14,7 +14,7 @@ class SetQueryOp(BaseOp):
|
|
14
14
|
into the context, utilizing either provided parameters or details from the context.
|
15
15
|
"""
|
16
16
|
|
17
|
-
def
|
17
|
+
async def async_execute(self):
|
18
18
|
"""
|
19
19
|
Executes the operation's primary function, which involves determining the query and its
|
20
20
|
timestamp, then storing these values within the context.
|
@@ -9,7 +9,7 @@ from reme_ai.schema import Message, Role
|
|
9
9
|
class BuildQueryOp(BaseLLMOp):
|
10
10
|
file_path: str = __file__
|
11
11
|
|
12
|
-
def
|
12
|
+
async def async_execute(self):
|
13
13
|
if "query" in self.context:
|
14
14
|
query = self.context.query
|
15
15
|
|
@@ -17,7 +17,7 @@ class BuildQueryOp(BaseLLMOp):
|
|
17
17
|
if self.op_params.get("enable_llm_build", True):
|
18
18
|
execution_process = merge_messages_content(self.context.messages)
|
19
19
|
prompt = self.prompt_format(prompt_name="query_build", execution_process=execution_process)
|
20
|
-
message = self.llm.
|
20
|
+
message = await self.llm.achat(messages=[Message(role=Role.USER, content=prompt)])
|
21
21
|
query = message.content
|
22
22
|
|
23
23
|
else:
|
@@ -17,7 +17,7 @@ class RerankMemoryOp(BaseLLMOp):
|
|
17
17
|
"""
|
18
18
|
file_path: str = __file__
|
19
19
|
|
20
|
-
def
|
20
|
+
async def async_execute(self):
|
21
21
|
"""Execute rerank operation"""
|
22
22
|
memory_list: List[BaseMemory] = self.context.response.metadata["memory_list"]
|
23
23
|
retrieval_query: str = self.context.query
|
@@ -36,7 +36,7 @@ class RerankMemoryOp(BaseLLMOp):
|
|
36
36
|
|
37
37
|
# Step 1: LLM reranking (optional)
|
38
38
|
if enable_llm_rerank:
|
39
|
-
memory_list = self._llm_rerank(retrieval_query, memory_list)
|
39
|
+
memory_list = await self._llm_rerank(retrieval_query, memory_list)
|
40
40
|
logger.info(f"After LLM reranking: {len(memory_list)} memories")
|
41
41
|
|
42
42
|
# Step 2: Score-based filtering (optional)
|
@@ -51,7 +51,7 @@ class RerankMemoryOp(BaseLLMOp):
|
|
51
51
|
# Store results in context
|
52
52
|
self.context.response.metadata["memory_list"] = reranked_memories
|
53
53
|
|
54
|
-
def _llm_rerank(self, query: str, candidates: List[BaseMemory]) -> List[BaseMemory]:
|
54
|
+
async def _llm_rerank(self, query: str, candidates: List[BaseMemory]) -> List[BaseMemory]:
|
55
55
|
"""LLM-based reranking of candidate experiences"""
|
56
56
|
if not candidates:
|
57
57
|
return candidates
|
@@ -65,7 +65,7 @@ class RerankMemoryOp(BaseLLMOp):
|
|
65
65
|
candidates=candidates_text,
|
66
66
|
num_candidates=len(candidates))
|
67
67
|
|
68
|
-
response = self.llm.
|
68
|
+
response = await self.llm.achat([Message(role=Role.USER, content=prompt)])
|
69
69
|
|
70
70
|
# Parse reranking results
|
71
71
|
reranked_indices = self._parse_rerank_response(response.content)
|
@@ -17,7 +17,7 @@ class RewriteMemoryOp(BaseLLMOp):
|
|
17
17
|
"""
|
18
18
|
file_path: str = __file__
|
19
19
|
|
20
|
-
def
|
20
|
+
async def async_execute(self):
|
21
21
|
"""Execute rewrite operation"""
|
22
22
|
memory_list: List[BaseMemory] = self.context.response.metadata["memory_list"]
|
23
23
|
query: str = self.context.query
|
@@ -32,13 +32,13 @@ class RewriteMemoryOp(BaseLLMOp):
|
|
32
32
|
logger.info(f"Generating context from {len(memory_list)} memories")
|
33
33
|
|
34
34
|
# Generate initial context message
|
35
|
-
rewritten_memory = self._generate_context_message(query, messages, memory_list)
|
35
|
+
rewritten_memory = await self._generate_context_message(query, messages, memory_list)
|
36
36
|
|
37
37
|
# Store results in context
|
38
38
|
self.context.response.answer = rewritten_memory
|
39
39
|
self.context.response.metadata["memory_list"] = [memory.model_dump() for memory in memory_list]
|
40
40
|
|
41
|
-
def _generate_context_message(self, query: str, messages: List[Message], memories: List[BaseMemory]) -> str:
|
41
|
+
async def _generate_context_message(self, query: str, messages: List[Message], memories: List[BaseMemory]) -> str:
|
42
42
|
"""Generate context message from retrieved memories"""
|
43
43
|
if not memories:
|
44
44
|
return ""
|
@@ -49,7 +49,7 @@ class RewriteMemoryOp(BaseLLMOp):
|
|
49
49
|
formatted_memories = self._format_memories_for_context(memories)
|
50
50
|
|
51
51
|
if self.op_params.get("enable_llm_rewrite", True):
|
52
|
-
context_content = self._rewrite_context(query, formatted_memories, messages)
|
52
|
+
context_content = await self._rewrite_context(query, formatted_memories, messages)
|
53
53
|
else:
|
54
54
|
context_content = formatted_memories
|
55
55
|
|
@@ -59,7 +59,7 @@ class RewriteMemoryOp(BaseLLMOp):
|
|
59
59
|
logger.error(f"Error generating context message: {e}")
|
60
60
|
return self._format_memories_for_context(memories)
|
61
61
|
|
62
|
-
def _rewrite_context(self, query: str, context_content: str, messages: List[Message]) -> str:
|
62
|
+
async def _rewrite_context(self, query: str, context_content: str, messages: List[Message]) -> str:
|
63
63
|
"""LLM-based context rewriting to make experiences more relevant and actionable"""
|
64
64
|
if not context_content:
|
65
65
|
return context_content
|
@@ -74,7 +74,7 @@ class RewriteMemoryOp(BaseLLMOp):
|
|
74
74
|
current_context=current_context,
|
75
75
|
original_context=context_content)
|
76
76
|
|
77
|
-
response = self.llm.
|
77
|
+
response = await self.llm.achat([Message(role=Role.USER, content=prompt)])
|
78
78
|
|
79
79
|
# Extract rewritten context
|
80
80
|
rewritten_context = self._parse_json_response(response.content, "rewritten_context")
|
File without changes
|
@@ -0,0 +1,112 @@
|
|
1
|
+
from abc import abstractmethod, ABC
|
2
|
+
from typing import Optional, Dict, Any
|
3
|
+
|
4
|
+
from pydantic import Field
|
5
|
+
|
6
|
+
|
7
|
+
class BaseMemoryService(ABC):
|
8
|
+
|
9
|
+
def __init__(self):
|
10
|
+
self.session_id_dict: dict = {}
|
11
|
+
|
12
|
+
def add_session_memory_id(self, session_id: str, memory_id):
|
13
|
+
if session_id not in self.session_id_dict:
|
14
|
+
self.session_id_dict[session_id] = []
|
15
|
+
|
16
|
+
self.session_id_dict[session_id].append(memory_id)
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
async def start(self) -> None:
|
20
|
+
"""Starts the service, initializing any necessary resources or
|
21
|
+
connections."""
|
22
|
+
|
23
|
+
@abstractmethod
|
24
|
+
async def stop(self) -> None:
|
25
|
+
"""Stops the service, releasing any acquired resources."""
|
26
|
+
|
27
|
+
@abstractmethod
|
28
|
+
async def health(self) -> bool:
|
29
|
+
"""
|
30
|
+
Checks the health of the service.
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
True if the service is healthy, False otherwise.
|
34
|
+
"""
|
35
|
+
|
36
|
+
async def __aenter__(self):
|
37
|
+
"""Async context manager entry."""
|
38
|
+
await self.start()
|
39
|
+
return self
|
40
|
+
|
41
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
42
|
+
"""Async context manager exit."""
|
43
|
+
await self.stop()
|
44
|
+
return False
|
45
|
+
|
46
|
+
@abstractmethod
|
47
|
+
async def add_memory(
|
48
|
+
self,
|
49
|
+
user_id: str,
|
50
|
+
messages: list,
|
51
|
+
session_id: Optional[str] = None,
|
52
|
+
) -> None:
|
53
|
+
"""
|
54
|
+
Adds messages to the memory service.
|
55
|
+
|
56
|
+
Args:
|
57
|
+
user_id: The user id.
|
58
|
+
messages: The messages to add.
|
59
|
+
session_id: The session id, which is optional.
|
60
|
+
"""
|
61
|
+
|
62
|
+
@abstractmethod
|
63
|
+
async def search_memory(
|
64
|
+
self,
|
65
|
+
user_id: str,
|
66
|
+
messages: list,
|
67
|
+
filters: Optional[Dict[str, Any]] = Field(
|
68
|
+
description="Associated filters for the messages, "
|
69
|
+
"such as top_k, score etc.",
|
70
|
+
default=None,
|
71
|
+
),
|
72
|
+
) -> list:
|
73
|
+
"""
|
74
|
+
Searches messages from the memory service.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
user_id: The user id.
|
78
|
+
messages: The user query or the query with history messages,
|
79
|
+
both in the format of list of messages. If messages is a list,
|
80
|
+
the search will be based on the content of the last message.
|
81
|
+
filters: The filters used to search memory
|
82
|
+
"""
|
83
|
+
|
84
|
+
@abstractmethod
|
85
|
+
async def list_memory(
|
86
|
+
self,
|
87
|
+
user_id: str,
|
88
|
+
filters: Optional[Dict[str, Any]] = Field(
|
89
|
+
description="Associated filters for the messages, "
|
90
|
+
"such as top_k, score etc.",
|
91
|
+
default=None,
|
92
|
+
),
|
93
|
+
) -> list:
|
94
|
+
"""
|
95
|
+
Lists the memory items for a given user with filters, such as
|
96
|
+
page_num, page_size, etc.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
user_id: The user id.
|
100
|
+
filters: The filters for the memory items.
|
101
|
+
"""
|
102
|
+
|
103
|
+
@abstractmethod
|
104
|
+
async def delete_memory(
|
105
|
+
self,
|
106
|
+
user_id: str,
|
107
|
+
session_id: Optional[str] = None,
|
108
|
+
) -> None:
|
109
|
+
"""
|
110
|
+
Deletes the memory items for a given user with certain session id,
|
111
|
+
or all the memory items for a given user.
|
112
|
+
"""
|