reme-ai 0.1.3__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.
Files changed (57) hide show
  1. reme_ai/__init__.py +1 -1
  2. reme_ai/app.py +1 -1
  3. reme_ai/config/default.yaml +56 -5
  4. reme_ai/constants/common_constants.py +0 -2
  5. reme_ai/constants/language_constants.py +1 -1
  6. reme_ai/enumeration/language_enum.py +14 -0
  7. reme_ai/react/simple_react_op.py +11 -8
  8. reme_ai/retrieve/personal/extract_time_op.py +2 -3
  9. reme_ai/retrieve/personal/fuse_rerank_op.py +1 -1
  10. reme_ai/retrieve/personal/print_memory_op.py +1 -1
  11. reme_ai/retrieve/personal/read_message_op.py +1 -1
  12. reme_ai/retrieve/personal/retrieve_memory_op.py +34 -4
  13. reme_ai/retrieve/personal/semantic_rank_op.py +4 -4
  14. reme_ai/retrieve/personal/set_query_op.py +1 -1
  15. reme_ai/retrieve/task/build_query_op.py +2 -2
  16. reme_ai/retrieve/task/merge_memory_op.py +1 -1
  17. reme_ai/retrieve/task/rerank_memory_op.py +4 -4
  18. reme_ai/retrieve/task/rewrite_memory_op.py +6 -6
  19. reme_ai/service/__init__.py +0 -0
  20. reme_ai/service/base_memory_service.py +112 -0
  21. reme_ai/service/personal_memory_service.py +128 -0
  22. reme_ai/service/task_memory_service.py +126 -0
  23. reme_ai/summary/personal/contra_repeat_op.py +2 -2
  24. reme_ai/summary/personal/get_observation_op.py +4 -4
  25. reme_ai/summary/personal/get_observation_with_time_op.py +4 -4
  26. reme_ai/summary/personal/get_reflection_subject_op.py +4 -4
  27. reme_ai/summary/personal/info_filter_op.py +4 -4
  28. reme_ai/summary/personal/load_today_memory_op.py +6 -7
  29. reme_ai/summary/personal/long_contra_repeat_op.py +4 -4
  30. reme_ai/summary/personal/update_insight_op.py +4 -4
  31. reme_ai/summary/task/__init__.py +0 -1
  32. reme_ai/summary/task/comparative_extraction_op.py +9 -7
  33. reme_ai/summary/task/failure_extraction_op.py +7 -5
  34. reme_ai/summary/task/memory_deduplication_op.py +6 -6
  35. reme_ai/summary/task/memory_validation_op.py +8 -6
  36. reme_ai/summary/task/simple_comparative_summary_op.py +6 -4
  37. reme_ai/summary/task/simple_summary_op.py +6 -4
  38. reme_ai/summary/task/success_extraction_op.py +7 -5
  39. reme_ai/summary/task/trajectory_preprocess_op.py +3 -32
  40. reme_ai/summary/task/trajectory_segmentation_op.py +6 -4
  41. reme_ai/utils/datetime_handler.py +1 -1
  42. reme_ai/vector_store/delete_memory_op.py +1 -1
  43. reme_ai/vector_store/recall_vector_store_op.py +3 -3
  44. reme_ai/vector_store/update_memory_freq_op.py +1 -1
  45. reme_ai/vector_store/update_memory_utility_op.py +1 -1
  46. reme_ai/vector_store/update_vector_store_op.py +3 -3
  47. reme_ai/vector_store/vector_store_action_op.py +21 -18
  48. {reme_ai-0.1.3.dist-info → reme_ai-0.1.5.dist-info}/METADATA +298 -133
  49. reme_ai-0.1.5.dist-info/RECORD +87 -0
  50. reme_ai/enumeration/language_constants.py +0 -215
  51. reme_ai/summary/task/pdf_preprocess_op_wrapper.py +0 -50
  52. reme_ai/utils/miner_u_pdf_processor.py +0 -726
  53. reme_ai-0.1.3.dist-info/RECORD +0 -85
  54. {reme_ai-0.1.3.dist-info → reme_ai-0.1.5.dist-info}/WHEEL +0 -0
  55. {reme_ai-0.1.3.dist-info → reme_ai-0.1.5.dist-info}/entry_points.txt +0 -0
  56. {reme_ai-0.1.3.dist-info → reme_ai-0.1.5.dist-info}/licenses/LICENSE +0 -0
  57. {reme_ai-0.1.3.dist-info → reme_ai-0.1.5.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ from reme_ai.schema.memory import BaseMemory
10
10
  class MemoryDeduplicationOp(BaseOp):
11
11
  file_path: str = __file__
12
12
 
13
- def execute(self):
13
+ async def async_execute(self):
14
14
  """Remove duplicate task memories"""
15
15
  # Get task memories to deduplicate
16
16
  task_memories: List[BaseMemory] = self.context.memory_list
@@ -22,7 +22,7 @@ class MemoryDeduplicationOp(BaseOp):
22
22
  logger.info(f"Starting deduplication for {len(task_memories)} task memories")
23
23
 
24
24
  # Perform deduplication
25
- deduplicated_task_memories = self._deduplicate_task_memories(task_memories)
25
+ deduplicated_task_memories = await self._deduplicate_task_memories(task_memories)
26
26
 
27
27
  logger.info(
28
28
  f"Deduplication complete: {len(deduplicated_task_memories)} deduplicated task memories out of {len(task_memories)}")
@@ -30,7 +30,7 @@ class MemoryDeduplicationOp(BaseOp):
30
30
  # Update context
31
31
  self.context.memory_list = deduplicated_task_memories
32
32
 
33
- def _deduplicate_task_memories(self, task_memories: List[BaseMemory]) -> List[BaseMemory]:
33
+ async def _deduplicate_task_memories(self, task_memories: List[BaseMemory]) -> List[BaseMemory]:
34
34
  """Remove duplicate task memories"""
35
35
  if not task_memories:
36
36
  return task_memories
@@ -41,7 +41,7 @@ class MemoryDeduplicationOp(BaseOp):
41
41
  unique_task_memories = []
42
42
 
43
43
  # Get existing task memory embeddings
44
- existing_embeddings = self._get_existing_task_memory_embeddings(workspace_id)
44
+ existing_embeddings = await self._get_existing_task_memory_embeddings(workspace_id)
45
45
 
46
46
  for task_memory in task_memories:
47
47
  # Generate embedding for current task memory
@@ -67,14 +67,14 @@ class MemoryDeduplicationOp(BaseOp):
67
67
 
68
68
  return unique_task_memories
69
69
 
70
- def _get_existing_task_memory_embeddings(self, workspace_id: str) -> List[List[float]]:
70
+ async def _get_existing_task_memory_embeddings(self, workspace_id: str) -> List[List[float]]:
71
71
  """Get embeddings of existing task memories"""
72
72
  try:
73
73
  if not hasattr(self.context, 'vector_store') or not self.context.vector_store or not workspace_id:
74
74
  return []
75
75
 
76
76
  # Query existing task memory nodes
77
- existing_nodes = self.context.vector_store.search(
77
+ existing_nodes = await self.context.vector_store.async_search(
78
78
  query="...", # Empty query to get all
79
79
  workspace_id=workspace_id,
80
80
  top_k=self.op_params.get("max_existing_task_memories", 1000)
@@ -3,6 +3,8 @@ import re
3
3
  from typing import List, Dict, Any
4
4
 
5
5
  from flowllm import C, BaseLLMOp
6
+ from flowllm.enumeration.role import Role
7
+ from flowllm.schema.message import Message as FlowMessage
6
8
  from loguru import logger
7
9
 
8
10
  from reme_ai.schema import Message
@@ -13,7 +15,7 @@ from reme_ai.schema.memory import BaseMemory
13
15
  class MemoryValidationOp(BaseLLMOp):
14
16
  file_path: str = __file__
15
17
 
16
- def execute(self):
18
+ async def async_execute(self):
17
19
  """Validate quality of extracted task memories"""
18
20
 
19
21
  task_memories: List[BaseMemory] = []
@@ -31,7 +33,7 @@ class MemoryValidationOp(BaseLLMOp):
31
33
  validated_task_memories = []
32
34
 
33
35
  for task_memory in task_memories:
34
- validation_result = self._validate_single_task_memory(task_memory)
36
+ validation_result = await self._validate_single_task_memory(task_memory)
35
37
  if validation_result and validation_result.get("is_valid", False):
36
38
  task_memory.score = validation_result.get("score", 0.0)
37
39
  validated_task_memories.append(task_memory)
@@ -45,13 +47,13 @@ class MemoryValidationOp(BaseLLMOp):
45
47
  self.context.response.answer = json.dumps([x.model_dump() for x in validated_task_memories])
46
48
  self.context.response.metadata["memory_list"] = validated_task_memories
47
49
 
48
- def _validate_single_task_memory(self, task_memory: BaseMemory) -> Dict[str, Any]:
50
+ async def _validate_single_task_memory(self, task_memory: BaseMemory) -> Dict[str, Any]:
49
51
  """Validate single task memory"""
50
- validation_info = self._llm_validate_task_memory(task_memory)
52
+ validation_info = await self._llm_validate_task_memory(task_memory)
51
53
  logger.info(f"Validating: {validation_info}")
52
54
  return validation_info
53
55
 
54
- def _llm_validate_task_memory(self, task_memory: BaseMemory) -> Dict[str, Any]:
56
+ async def _llm_validate_task_memory(self, task_memory: BaseMemory) -> Dict[str, Any]:
55
57
  """Validate task memory using LLM"""
56
58
  try:
57
59
  prompt = self.prompt_format(
@@ -96,7 +98,7 @@ class MemoryValidationOp(BaseLLMOp):
96
98
  "reason": f"Parse error: {str(e_inner)}"
97
99
  }
98
100
 
99
- return self.llm.chat(messages=[Message(content=prompt)], callback_fn=parse_validation)
101
+ return await self.llm.achat(messages=[FlowMessage(role=Role.USER, content=prompt)], callback_fn=parse_validation)
100
102
 
101
103
  except Exception as e:
102
104
  logger.error(f"LLM validation failed: {e}")
@@ -2,6 +2,8 @@ import json
2
2
  from typing import List, Dict
3
3
 
4
4
  from flowllm import C, BaseLLMOp
5
+ from flowllm.enumeration.role import Role
6
+ from flowllm.schema.message import Message as FlowMessage
5
7
  from loguru import logger
6
8
 
7
9
  from reme_ai.schema import Message, Trajectory
@@ -13,7 +15,7 @@ from reme_ai.utils.op_utils import merge_messages_content
13
15
  class SimpleComparativeSummaryOp(BaseLLMOp):
14
16
  file_path: str = __file__
15
17
 
16
- def compare_summary_trajectory(self, trajectory_a: Trajectory, trajectory_b: Trajectory) -> List[BaseMemory]:
18
+ async def compare_summary_trajectory(self, trajectory_a: Trajectory, trajectory_b: Trajectory) -> List[BaseMemory]:
17
19
  summary_prompt = self.prompt_format(prompt_name="summary_prompt",
18
20
  execution_process_a=merge_messages_content(trajectory_a.messages),
19
21
  execution_process_b=merge_messages_content(trajectory_b.messages),
@@ -42,9 +44,9 @@ class SimpleComparativeSummaryOp(BaseLLMOp):
42
44
  logger.exception(f"parse content failed!\n{content}")
43
45
  raise e
44
46
 
45
- return self.llm.chat(messages=[Message(content=summary_prompt)], callback_fn=parse_content)
47
+ return await self.llm.achat(messages=[FlowMessage(role=Role.USER, content=summary_prompt)], callback_fn=parse_content)
46
48
 
47
- def execute(self):
49
+ async def async_execute(self):
48
50
  trajectories: list = self.context.get("trajectories", [])
49
51
  trajectories: List[Trajectory] = [Trajectory(**x) if isinstance(x, dict) else x for x in trajectories]
50
52
 
@@ -61,7 +63,7 @@ class SimpleComparativeSummaryOp(BaseLLMOp):
61
63
  continue
62
64
 
63
65
  if task_trajectories[0].score > task_trajectories[-1].score:
64
- task_memories = self.compare_summary_trajectory(trajectory_a=task_trajectories[0],
66
+ task_memories = await self.compare_summary_trajectory(trajectory_a=task_trajectories[0],
65
67
  trajectory_b=task_trajectories[-1])
66
68
  memory_list.extend(task_memories)
67
69
 
@@ -2,6 +2,8 @@ import json
2
2
  from typing import List
3
3
 
4
4
  from flowllm import C, BaseLLMOp
5
+ from flowllm.enumeration.role import Role
6
+ from flowllm.schema.message import Message as FlowMessage
5
7
  from loguru import logger
6
8
 
7
9
  from reme_ai.schema import Message, Trajectory
@@ -13,7 +15,7 @@ from reme_ai.utils.op_utils import merge_messages_content
13
15
  class SimpleSummaryOp(BaseLLMOp):
14
16
  file_path: str = __file__
15
17
 
16
- def summary_trajectory(self, trajectory: Trajectory) -> List[BaseMemory]:
18
+ async def summary_trajectory(self, trajectory: Trajectory) -> List[BaseMemory]:
17
19
  execution_process = merge_messages_content(trajectory.messages)
18
20
  success_score_threshold: float = self.op_params.get("success_score_threshold", 0.9)
19
21
  logger.info(f"success_score_threshold={success_score_threshold}")
@@ -49,15 +51,15 @@ class SimpleSummaryOp(BaseLLMOp):
49
51
  logger.exception(f"parse content failed!\n{content}")
50
52
  raise e
51
53
 
52
- return self.llm.chat(messages=[Message(content=summary_prompt)], callback_fn=parse_content)
54
+ return await self.llm.achat(messages=[FlowMessage(role=Role.USER, content=summary_prompt)], callback_fn=parse_content)
53
55
 
54
- def execute(self):
56
+ async def async_execute(self):
55
57
  trajectories: list = self.context.trajectories
56
58
  trajectories: List[Trajectory] = [Trajectory(**x) if isinstance(x, dict) else x for x in trajectories]
57
59
 
58
60
  memory_list: List[BaseMemory] = []
59
61
  for trajectory in trajectories:
60
- memories = self.summary_trajectory(trajectory)
62
+ memories = await self.summary_trajectory(trajectory)
61
63
  if memories:
62
64
  memory_list.extend(memories)
63
65
 
@@ -1,6 +1,8 @@
1
1
  from typing import List
2
2
 
3
3
  from flowllm import C, BaseLLMOp
4
+ from flowllm.enumeration.role import Role
5
+ from flowllm.schema.message import Message as FlowMessage
4
6
  from loguru import logger
5
7
 
6
8
  from reme_ai.schema import Message, Trajectory
@@ -12,7 +14,7 @@ from reme_ai.utils.op_utils import merge_messages_content, parse_json_experience
12
14
  class SuccessExtractionOp(BaseLLMOp):
13
15
  file_path: str = __file__
14
16
 
15
- def execute(self):
17
+ async def async_execute(self):
16
18
  """Extract task memories from successful trajectories"""
17
19
  success_trajectories: List[Trajectory] = self.context.success_trajectories
18
20
 
@@ -29,11 +31,11 @@ class SuccessExtractionOp(BaseLLMOp):
29
31
  if "segments" in trajectory.metadata:
30
32
  # Process segmented step sequences
31
33
  for segment in trajectory.metadata["segments"]:
32
- task_memories = self._extract_success_task_memory_from_steps(segment, trajectory)
34
+ task_memories = await self._extract_success_task_memory_from_steps(segment, trajectory)
33
35
  success_task_memories.extend(task_memories)
34
36
  else:
35
37
  # Process entire trajectory
36
- task_memories = self._extract_success_task_memory_from_steps(trajectory.messages, trajectory)
38
+ task_memories = await self._extract_success_task_memory_from_steps(trajectory.messages, trajectory)
37
39
  success_task_memories.extend(task_memories)
38
40
 
39
41
  logger.info(f"Extracted {len(success_task_memories)} success task memories")
@@ -41,7 +43,7 @@ class SuccessExtractionOp(BaseLLMOp):
41
43
  # Add task memories to context
42
44
  self.context.success_task_memories = success_task_memories
43
45
 
44
- def _extract_success_task_memory_from_steps(self, steps: List[Message], trajectory: Trajectory) -> List[BaseMemory]:
46
+ async def _extract_success_task_memory_from_steps(self, steps: List[Message], trajectory: Trajectory) -> List[BaseMemory]:
45
47
  """Extract task memory from successful step sequences"""
46
48
  step_content = merge_messages_content(steps)
47
49
  context = get_trajectory_context(trajectory, steps)
@@ -70,4 +72,4 @@ class SuccessExtractionOp(BaseLLMOp):
70
72
 
71
73
  return task_memories
72
74
 
73
- return self.llm.chat(messages=[Message(content=prompt)], callback_fn=parse_task_memories)
75
+ return await self.llm.achat(messages=[FlowMessage(role=Role.USER, content=prompt)], callback_fn=parse_task_memories)
@@ -1,4 +1,3 @@
1
- import json
2
1
  from typing import List, Dict
3
2
 
4
3
  from flowllm import C, BaseOp
@@ -11,18 +10,10 @@ from reme_ai.schema import Trajectory
11
10
  class TrajectoryPreprocessOp(BaseOp):
12
11
  file_path: str = __file__
13
12
 
14
- def execute(self):
13
+ async def async_execute(self):
15
14
  """Preprocess trajectories: validate and classify"""
16
15
  trajectories: list = self.context.get("trajectories", [])
17
- # trajectories: List[Trajectory] = [Trajectory(**x) if isinstance(x, dict) else x for x in trajectories]
18
- new_trajectories: List[Trajectory] = []
19
- for x in trajectories:
20
- if isinstance(x, dict):
21
- x["messages"] = self._modify_tool_calls(x["messages"])
22
- new_trajectories.append(Trajectory(**x))
23
- else:
24
- new_trajectories.append(x)
25
- trajectories = new_trajectories
16
+ trajectories: List[Trajectory] = [Trajectory(**x) if isinstance(x, dict) else x for x in trajectories]
26
17
 
27
18
  # Classify trajectories
28
19
  classified = self._classify_trajectories(trajectories)
@@ -53,24 +44,4 @@ class TrajectoryPreprocessOp(BaseOp):
53
44
  'success': success_trajectories,
54
45
  'failure': failure_trajectories,
55
46
  'all': trajectories
56
- }
57
-
58
- def _modify_tool_calls(self, messages: List[Dict]) -> List[Dict]:
59
- new_messages = []
60
-
61
- for msg in messages:
62
- if 'tool_calls' in msg:
63
- processed_tool_calls = []
64
- for tool_call in msg['tool_calls']:
65
- tool_type = tool_call.get("type", "function")
66
- nested_data = tool_call.get(tool_type, {})
67
- tool_call.update({
68
- "arguments": json.loads(nested_data.get("arguments", "")),
69
- "name": nested_data.get("name", "")
70
- })
71
- tool_call.pop(tool_type)
72
- processed_tool_calls.append(tool_call)
73
- msg['tool_calls'] = processed_tool_calls
74
- new_messages.append(msg)
75
-
76
- return new_messages
47
+ }
@@ -3,6 +3,8 @@ import re
3
3
  from typing import List
4
4
 
5
5
  from flowllm import C, BaseLLMOp
6
+ from flowllm.enumeration.role import Role
7
+ from flowllm.schema.message import Message as FlowMessage
6
8
  from loguru import logger
7
9
 
8
10
  from reme_ai.schema import Message, Trajectory
@@ -12,7 +14,7 @@ from reme_ai.schema import Message, Trajectory
12
14
  class TrajectorySegmentationOp(BaseLLMOp):
13
15
  file_path: str = __file__
14
16
 
15
- def execute(self):
17
+ async def async_execute(self):
16
18
  """Segment trajectories into meaningful steps"""
17
19
  # Get trajectories from context
18
20
  all_trajectories: List[Trajectory] = self.context.get("all_trajectories", [])
@@ -30,7 +32,7 @@ class TrajectorySegmentationOp(BaseLLMOp):
30
32
  # Add segmentation info to trajectories
31
33
  segmented_count = 0
32
34
  for trajectory in target_trajectories:
33
- segments = self._llm_segment_trajectory(trajectory)
35
+ segments = await self._llm_segment_trajectory(trajectory)
34
36
  trajectory.metadata["segments"] = segments
35
37
  segmented_count += 1
36
38
 
@@ -51,7 +53,7 @@ class TrajectorySegmentationOp(BaseLLMOp):
51
53
  else:
52
54
  return all_trajectories
53
55
 
54
- def _llm_segment_trajectory(self, trajectory: Trajectory) -> List[List[Message]]:
56
+ async def _llm_segment_trajectory(self, trajectory: Trajectory) -> List[List[Message]]:
55
57
  """Use LLM for trajectory segmentation"""
56
58
  trajectory_content = self._format_trajectory_content(trajectory)
57
59
 
@@ -80,7 +82,7 @@ class TrajectorySegmentationOp(BaseLLMOp):
80
82
 
81
83
  return segments if segments else [trajectory.messages]
82
84
 
83
- return self.llm.chat(messages=[Message(content=prompt)], callback_fn=parse_segmentation,
85
+ return await self.llm.achat(messages=[FlowMessage(role=Role.USER, content=prompt)], callback_fn=parse_segmentation,
84
86
  default_value=[trajectory.messages])
85
87
 
86
88
  @staticmethod
@@ -2,8 +2,8 @@ import datetime
2
2
  import re
3
3
  from typing import List
4
4
 
5
+ from reme_ai.constants.language_constants import LanguageEnum
5
6
  from reme_ai.constants.language_constants import WEEKDAYS, DATATIME_WORD_LIST, MONTH_DICT
6
- from reme_ai.enumeration.language_constants import LanguageEnum
7
7
 
8
8
 
9
9
  class DatetimeHandler(object):
@@ -8,7 +8,7 @@ from flowllm.schema.vector_node import VectorNode
8
8
  class DeleteMemoryOp(BaseLLMOp):
9
9
  file_path: str = __file__
10
10
 
11
- def execute(self):
11
+ async def async_execute(self):
12
12
  workspace_id: str = self.context.workspace_id
13
13
  freq_threshold: int = self.context.freq_threshold
14
14
  utility_threshold: float = self.context.utility_threshold
@@ -10,15 +10,15 @@ from reme_ai.schema.memory import BaseMemory, vector_node_to_memory
10
10
  @C.register_op()
11
11
  class RecallVectorStoreOp(BaseLLMOp):
12
12
 
13
- def execute(self):
13
+ async def async_execute(self):
14
14
  recall_key: str = self.op_params.get("recall_key", "query")
15
- top_k: int = self.op_params.get("top_k", 3)
15
+ top_k: int = self.context.get("top_k", 3)
16
16
 
17
17
  query: str = self.context[recall_key]
18
18
  assert query, "query should be not empty!"
19
19
 
20
20
  workspace_id: str = self.context.workspace_id
21
- nodes: List[VectorNode] = self.vector_store.search(query=query, workspace_id=workspace_id, top_k=top_k)
21
+ nodes: List[VectorNode] = await self.vector_store.async_search(query=query, workspace_id=workspace_id, top_k=top_k)
22
22
  memory_list: List[BaseMemory] = []
23
23
  memory_content_list: List[str] = []
24
24
  for node in nodes:
@@ -10,7 +10,7 @@ from reme_ai.schema.memory import BaseMemory, dict_to_memory
10
10
  class UpdateMemoryFreqOp(BaseOp):
11
11
  file_path: str = __file__
12
12
 
13
- def execute(self):
13
+ async def async_execute(self):
14
14
  memory_dicts: List[dict] = self.context.memory_dicts
15
15
 
16
16
  if not memory_dicts:
@@ -10,7 +10,7 @@ from reme_ai.schema.memory import BaseMemory
10
10
  class UpdateMemoryUtilityOp(BaseOp):
11
11
  file_path: str = __file__
12
12
 
13
- def execute(self):
13
+ async def async_execute(self):
14
14
  memory_dicts: List[dict] = self.context.memory_dicts
15
15
  update_utility = self.context.update_utility
16
16
 
@@ -11,18 +11,18 @@ from reme_ai.schema.memory import BaseMemory
11
11
  @C.register_op()
12
12
  class UpdateVectorStoreOp(BaseLLMOp):
13
13
 
14
- def execute(self):
14
+ async def async_execute(self):
15
15
  workspace_id: str = self.context.workspace_id
16
16
 
17
17
  deleted_memory_ids: List[str] = self.context.response.metadata.get("deleted_memory_ids", [])
18
18
  if deleted_memory_ids:
19
- self.vector_store.delete(node_ids=deleted_memory_ids, workspace_id=workspace_id)
19
+ await self.vector_store.async_delete(node_ids=deleted_memory_ids, workspace_id=workspace_id)
20
20
  logger.info(f"delete memory_ids={json.dumps(deleted_memory_ids, indent=2)}")
21
21
 
22
22
  insert_memory_list: List[BaseMemory] = self.context.response.metadata.get("memory_list", [])
23
23
  if insert_memory_list:
24
24
  insert_nodes: List[VectorNode] = [x.to_vector_node() for x in insert_memory_list]
25
- self.vector_store.insert(nodes=insert_nodes, workspace_id=workspace_id)
25
+ await self.vector_store.async_insert(nodes=insert_nodes, workspace_id=workspace_id)
26
26
  logger.info(f"insert insert_node.size={len(insert_nodes)}")
27
27
 
28
28
  # Store results in context
@@ -7,22 +7,22 @@ from reme_ai.schema.memory import vector_node_to_memory, dict_to_memory, BaseMem
7
7
  @C.register_op()
8
8
  class VectorStoreActionOp(BaseLLMOp):
9
9
 
10
- def execute(self):
10
+ async def async_execute(self):
11
11
  workspace_id: str = self.context.workspace_id
12
12
  action: str = self.context.action
13
-
13
+ result = ""
14
14
  if action == "copy":
15
15
  src_workspace_id: str = self.context.src_workspace_id
16
- result = self.vector_store.copy_workspace(src_workspace_id=src_workspace_id,
17
- dest_workspace_id=workspace_id)
16
+ result = await self.vector_store.async_copy_workspace(src_workspace_id=src_workspace_id,
17
+ dest_workspace_id=workspace_id)
18
18
 
19
19
  elif action == "delete":
20
- if self.vector_store.exist_workspace(workspace_id):
21
- result = self.vector_store.delete_workspace(workspace_id=workspace_id)
20
+ if await self.vector_store.async_exist_workspace(workspace_id):
21
+ result = await self.vector_store.async_delete_workspace(workspace_id=workspace_id)
22
22
 
23
23
  elif action == "delete_ids":
24
24
  memory_ids: list = self.context.memory_ids
25
- result = self.vector_store.delete(workspace_id=workspace_id, node_ids=memory_ids)
25
+ result = await self.vector_store.async_delete(workspace_id=workspace_id, node_ids=memory_ids)
26
26
 
27
27
  elif action == "dump":
28
28
  path: str = self.context.path
@@ -30,9 +30,16 @@ class VectorStoreActionOp(BaseLLMOp):
30
30
  def node_to_memory(node: VectorNode) -> dict:
31
31
  return vector_node_to_memory(node).model_dump()
32
32
 
33
- result = self.vector_store.dump_workspace(workspace_id=workspace_id,
34
- path=path,
35
- callback_fn=node_to_memory)
33
+ result = await self.vector_store.async_dump_workspace(workspace_id=workspace_id,
34
+ path=path,
35
+ callback_fn=node_to_memory)
36
+
37
+ elif action == "list":
38
+ def node_to_memory(node: VectorNode) -> dict:
39
+ return vector_node_to_memory(node).model_dump()
40
+
41
+ result = await self.vector_store.async_iter_workspace_nodes(workspace_id=workspace_id)
42
+ result = [node_to_memory(node) for node in result]
36
43
 
37
44
  elif action == "load":
38
45
  path: str = self.context.path
@@ -41,15 +48,11 @@ class VectorStoreActionOp(BaseLLMOp):
41
48
  memory: BaseMemory = dict_to_memory(memory_dict=memory_dict)
42
49
  return memory.to_vector_node()
43
50
 
44
- result = self.vector_store.load_workspace(workspace_id=workspace_id,
45
- path=path,
46
- callback_fn=memory_dict_to_node)
51
+ result = await self.vector_store.async_load_workspace(workspace_id=workspace_id,
52
+ path=path,
53
+ callback_fn=memory_dict_to_node)
47
54
 
48
55
  else:
49
56
  raise ValueError(f"invalid action={action}")
50
57
 
51
- # Store results in context
52
- if isinstance(result, dict):
53
- self.context.response.metadata["action_result"] = result
54
- else:
55
- self.context.response.metadata["action_result"] = {"result": str(result)}
58
+ self.context.response.metadata["action_result"] = result