isage-middleware 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.

Potentially problematic release.


This version of isage-middleware might be problematic. Click here for more details.

Files changed (191) hide show
  1. isage_middleware-0.1.0.dist-info/METADATA +424 -0
  2. isage_middleware-0.1.0.dist-info/RECORD +191 -0
  3. isage_middleware-0.1.0.dist-info/WHEEL +5 -0
  4. isage_middleware-0.1.0.dist-info/top_level.txt +1 -0
  5. sage/__init__.py +2 -0
  6. sage/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  7. sage/__pycache__/__init__.cpython-311.pyc +0 -0
  8. sage/middleware/__init__.py +83 -0
  9. sage/middleware/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  10. sage/middleware/__pycache__/__init__.cpython-311.pyc +0 -0
  11. sage/middleware/api/__init__.py +22 -0
  12. sage/middleware/api/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  13. sage/middleware/api/__pycache__/__init__.cpython-311.pyc +0 -0
  14. sage/middleware/api/__pycache__/graph_api.cpython-311.opt-2.pyc +0 -0
  15. sage/middleware/api/__pycache__/graph_api.cpython-311.pyc +0 -0
  16. sage/middleware/api/__pycache__/kv_api.cpython-311.opt-2.pyc +0 -0
  17. sage/middleware/api/__pycache__/kv_api.cpython-311.pyc +0 -0
  18. sage/middleware/api/__pycache__/memory_api.cpython-311.opt-2.pyc +0 -0
  19. sage/middleware/api/__pycache__/memory_api.cpython-311.pyc +0 -0
  20. sage/middleware/api/__pycache__/vdb_api.cpython-311.opt-2.pyc +0 -0
  21. sage/middleware/api/__pycache__/vdb_api.cpython-311.pyc +0 -0
  22. sage/middleware/api/graph_api.py +74 -0
  23. sage/middleware/api/kv_api.py +45 -0
  24. sage/middleware/api/memory_api.py +64 -0
  25. sage/middleware/api/vdb_api.py +60 -0
  26. sage/middleware/enterprise/__init__.py +75 -0
  27. sage/middleware/enterprise/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  28. sage/middleware/enterprise/__pycache__/__init__.cpython-311.pyc +0 -0
  29. sage/middleware/enterprise/sage_db/__init__.py +132 -0
  30. sage/middleware/enterprise/sage_db/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  31. sage/middleware/enterprise/sage_db/__pycache__/__init__.cpython-311.pyc +0 -0
  32. sage/middleware/enterprise/sage_db/__pycache__/sage_db.cpython-311.opt-2.pyc +0 -0
  33. sage/middleware/enterprise/sage_db/__pycache__/sage_db.cpython-311.pyc +0 -0
  34. sage/middleware/enterprise/sage_db/python/__init__.py +7 -0
  35. sage/middleware/enterprise/sage_db/python/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  36. sage/middleware/enterprise/sage_db/python/__pycache__/__init__.cpython-311.pyc +0 -0
  37. sage/middleware/enterprise/sage_db/python/__pycache__/sage_db.cpython-311.opt-2.pyc +0 -0
  38. sage/middleware/enterprise/sage_db/python/__pycache__/sage_db.cpython-311.pyc +0 -0
  39. sage/middleware/enterprise/sage_db/python/sage_db.py +44 -0
  40. sage/middleware/enterprise/sage_db/sage_db.py +395 -0
  41. sage/middleware/enterprise/sage_db/tests/__pycache__/test_python.cpython-311.opt-2.pyc +0 -0
  42. sage/middleware/enterprise/sage_db/tests/__pycache__/test_python.cpython-311.pyc +0 -0
  43. sage/middleware/enterprise/sage_db/tests/test_python.py +144 -0
  44. sage/middleware/examples/__pycache__/api_usage_tutorial.cpython-311.opt-2.pyc +0 -0
  45. sage/middleware/examples/__pycache__/api_usage_tutorial.cpython-311.pyc +0 -0
  46. sage/middleware/examples/__pycache__/dag_microservices_demo.cpython-311.opt-2.pyc +0 -0
  47. sage/middleware/examples/__pycache__/dag_microservices_demo.cpython-311.pyc +0 -0
  48. sage/middleware/examples/__pycache__/microservices_demo.cpython-311.opt-2.pyc +0 -0
  49. sage/middleware/examples/__pycache__/microservices_demo.cpython-311.pyc +0 -0
  50. sage/middleware/examples/__pycache__/microservices_integration_demo.cpython-311.opt-2.pyc +0 -0
  51. sage/middleware/examples/__pycache__/microservices_integration_demo.cpython-311.pyc +0 -0
  52. sage/middleware/examples/__pycache__/microservices_registration_demo.cpython-311.opt-2.pyc +0 -0
  53. sage/middleware/examples/__pycache__/microservices_registration_demo.cpython-311.pyc +0 -0
  54. sage/middleware/examples/api_usage_tutorial.py +339 -0
  55. sage/middleware/examples/dag_microservices_demo.py +220 -0
  56. sage/middleware/examples/microservices_demo.py +0 -0
  57. sage/middleware/examples/microservices_integration_demo.py +373 -0
  58. sage/middleware/examples/microservices_registration_demo.py +144 -0
  59. sage/middleware/py.typed +2 -0
  60. sage/middleware/services/graph/__init__.py +8 -0
  61. sage/middleware/services/graph/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  62. sage/middleware/services/graph/__pycache__/__init__.cpython-311.pyc +0 -0
  63. sage/middleware/services/graph/__pycache__/graph_index.cpython-311.opt-2.pyc +0 -0
  64. sage/middleware/services/graph/__pycache__/graph_index.cpython-311.pyc +0 -0
  65. sage/middleware/services/graph/__pycache__/graph_service.cpython-311.opt-2.pyc +0 -0
  66. sage/middleware/services/graph/__pycache__/graph_service.cpython-311.pyc +0 -0
  67. sage/middleware/services/graph/examples/__pycache__/graph_demo.cpython-311.opt-2.pyc +0 -0
  68. sage/middleware/services/graph/examples/__pycache__/graph_demo.cpython-311.pyc +0 -0
  69. sage/middleware/services/graph/examples/graph_demo.py +177 -0
  70. sage/middleware/services/graph/graph_index.py +194 -0
  71. sage/middleware/services/graph/graph_service.py +541 -0
  72. sage/middleware/services/graph/search_engine/__init__.py +0 -0
  73. sage/middleware/services/graph/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  74. sage/middleware/services/graph/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
  75. sage/middleware/services/graph/search_engine/__pycache__/base_graph_index.cpython-311.opt-2.pyc +0 -0
  76. sage/middleware/services/graph/search_engine/__pycache__/base_graph_index.cpython-311.pyc +0 -0
  77. sage/middleware/services/graph/search_engine/base_graph_index.py +0 -0
  78. sage/middleware/services/kv/__init__.py +8 -0
  79. sage/middleware/services/kv/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  80. sage/middleware/services/kv/__pycache__/__init__.cpython-311.pyc +0 -0
  81. sage/middleware/services/kv/__pycache__/kv_service.cpython-311.opt-2.pyc +0 -0
  82. sage/middleware/services/kv/__pycache__/kv_service.cpython-311.pyc +0 -0
  83. sage/middleware/services/kv/examples/__pycache__/kv_demo.cpython-311.opt-2.pyc +0 -0
  84. sage/middleware/services/kv/examples/__pycache__/kv_demo.cpython-311.pyc +0 -0
  85. sage/middleware/services/kv/examples/kv_demo.py +213 -0
  86. sage/middleware/services/kv/kv_service.py +306 -0
  87. sage/middleware/services/kv/search_engine/__init__.py +0 -0
  88. sage/middleware/services/kv/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  89. sage/middleware/services/kv/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
  90. sage/middleware/services/kv/search_engine/__pycache__/base_kv_index.cpython-311.opt-2.pyc +0 -0
  91. sage/middleware/services/kv/search_engine/__pycache__/base_kv_index.cpython-311.pyc +0 -0
  92. sage/middleware/services/kv/search_engine/__pycache__/bm25s_index.cpython-311.opt-2.pyc +0 -0
  93. sage/middleware/services/kv/search_engine/__pycache__/bm25s_index.cpython-311.pyc +0 -0
  94. sage/middleware/services/kv/search_engine/base_kv_index.py +75 -0
  95. sage/middleware/services/kv/search_engine/bm25s_index.py +238 -0
  96. sage/middleware/services/memory/__init__.py +12 -0
  97. sage/middleware/services/memory/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  98. sage/middleware/services/memory/__pycache__/__init__.cpython-311.pyc +0 -0
  99. sage/middleware/services/memory/__pycache__/memory_service.cpython-311.opt-2.pyc +0 -0
  100. sage/middleware/services/memory/__pycache__/memory_service.cpython-311.pyc +0 -0
  101. sage/middleware/services/memory/examples/__pycache__/dag_microservices_demo.cpython-311.opt-2.pyc +0 -0
  102. sage/middleware/services/memory/examples/__pycache__/dag_microservices_demo.cpython-311.pyc +0 -0
  103. sage/middleware/services/memory/examples/__pycache__/memory_demo.cpython-311.opt-2.pyc +0 -0
  104. sage/middleware/services/memory/examples/__pycache__/memory_demo.cpython-311.pyc +0 -0
  105. sage/middleware/services/memory/examples/dag_microservices_demo.py +220 -0
  106. sage/middleware/services/memory/examples/memory_demo.py +490 -0
  107. sage/middleware/services/memory/memory_collection/__pycache__/base_collection.cpython-311.opt-2.pyc +0 -0
  108. sage/middleware/services/memory/memory_collection/__pycache__/base_collection.cpython-311.pyc +0 -0
  109. sage/middleware/services/memory/memory_collection/__pycache__/graph_collection.cpython-311.opt-2.pyc +0 -0
  110. sage/middleware/services/memory/memory_collection/__pycache__/graph_collection.cpython-311.pyc +0 -0
  111. sage/middleware/services/memory/memory_collection/__pycache__/kv_collection.cpython-311.opt-2.pyc +0 -0
  112. sage/middleware/services/memory/memory_collection/__pycache__/kv_collection.cpython-311.pyc +0 -0
  113. sage/middleware/services/memory/memory_collection/__pycache__/vdb_collection.cpython-311.opt-2.pyc +0 -0
  114. sage/middleware/services/memory/memory_collection/__pycache__/vdb_collection.cpython-311.pyc +0 -0
  115. sage/middleware/services/memory/memory_collection/base_collection.py +0 -0
  116. sage/middleware/services/memory/memory_collection/graph_collection.py +0 -0
  117. sage/middleware/services/memory/memory_collection/kv_collection.py +0 -0
  118. sage/middleware/services/memory/memory_collection/vdb_collection.py +0 -0
  119. sage/middleware/services/memory/memory_service.py +474 -0
  120. sage/middleware/services/memory/utils/__init__.py +0 -0
  121. sage/middleware/services/memory/utils/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  122. sage/middleware/services/memory/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  123. sage/middleware/services/memory/utils/__pycache__/path_utils.cpython-311.opt-2.pyc +0 -0
  124. sage/middleware/services/memory/utils/__pycache__/path_utils.cpython-311.pyc +0 -0
  125. sage/middleware/services/memory/utils/path_utils.py +0 -0
  126. sage/middleware/services/vdb/__init__.py +8 -0
  127. sage/middleware/services/vdb/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  128. sage/middleware/services/vdb/__pycache__/__init__.cpython-311.pyc +0 -0
  129. sage/middleware/services/vdb/__pycache__/vdb_service.cpython-311.opt-2.pyc +0 -0
  130. sage/middleware/services/vdb/__pycache__/vdb_service.cpython-311.pyc +0 -0
  131. sage/middleware/services/vdb/examples/__pycache__/vdb_demo.cpython-311.opt-2.pyc +0 -0
  132. sage/middleware/services/vdb/examples/__pycache__/vdb_demo.cpython-311.pyc +0 -0
  133. sage/middleware/services/vdb/examples/vdb_demo.py +447 -0
  134. sage/middleware/services/vdb/search_engine/__init__.py +0 -0
  135. sage/middleware/services/vdb/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  136. sage/middleware/services/vdb/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
  137. sage/middleware/services/vdb/search_engine/__pycache__/base_vdb_index.cpython-311.opt-2.pyc +0 -0
  138. sage/middleware/services/vdb/search_engine/__pycache__/base_vdb_index.cpython-311.pyc +0 -0
  139. sage/middleware/services/vdb/search_engine/__pycache__/faiss_index.cpython-311.opt-2.pyc +0 -0
  140. sage/middleware/services/vdb/search_engine/__pycache__/faiss_index.cpython-311.pyc +0 -0
  141. sage/middleware/services/vdb/search_engine/base_vdb_index.py +58 -0
  142. sage/middleware/services/vdb/search_engine/faiss_index.py +461 -0
  143. sage/middleware/services/vdb/vdb_service.py +433 -0
  144. sage/middleware/utils/__init__.py +5 -0
  145. sage/middleware/utils/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  146. sage/middleware/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  147. sage/middleware/utils/embedding/__init__.py +35 -0
  148. sage/middleware/utils/embedding/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
  149. sage/middleware/utils/embedding/__pycache__/__init__.cpython-311.pyc +0 -0
  150. sage/middleware/utils/embedding/__pycache__/_cohere.cpython-311.opt-2.pyc +0 -0
  151. sage/middleware/utils/embedding/__pycache__/_cohere.cpython-311.pyc +0 -0
  152. sage/middleware/utils/embedding/__pycache__/bedrock.cpython-311.opt-2.pyc +0 -0
  153. sage/middleware/utils/embedding/__pycache__/bedrock.cpython-311.pyc +0 -0
  154. sage/middleware/utils/embedding/__pycache__/embedding_api.cpython-311.opt-2.pyc +0 -0
  155. sage/middleware/utils/embedding/__pycache__/embedding_api.cpython-311.pyc +0 -0
  156. sage/middleware/utils/embedding/__pycache__/embedding_model.cpython-311.opt-2.pyc +0 -0
  157. sage/middleware/utils/embedding/__pycache__/embedding_model.cpython-311.pyc +0 -0
  158. sage/middleware/utils/embedding/__pycache__/hf.cpython-311.opt-2.pyc +0 -0
  159. sage/middleware/utils/embedding/__pycache__/hf.cpython-311.pyc +0 -0
  160. sage/middleware/utils/embedding/__pycache__/instructor.cpython-311.opt-2.pyc +0 -0
  161. sage/middleware/utils/embedding/__pycache__/instructor.cpython-311.pyc +0 -0
  162. sage/middleware/utils/embedding/__pycache__/jina.cpython-311.opt-2.pyc +0 -0
  163. sage/middleware/utils/embedding/__pycache__/jina.cpython-311.pyc +0 -0
  164. sage/middleware/utils/embedding/__pycache__/lollms.cpython-311.opt-2.pyc +0 -0
  165. sage/middleware/utils/embedding/__pycache__/lollms.cpython-311.pyc +0 -0
  166. sage/middleware/utils/embedding/__pycache__/mockembedder.cpython-311.opt-2.pyc +0 -0
  167. sage/middleware/utils/embedding/__pycache__/mockembedder.cpython-311.pyc +0 -0
  168. sage/middleware/utils/embedding/__pycache__/nvidia_openai.cpython-311.opt-2.pyc +0 -0
  169. sage/middleware/utils/embedding/__pycache__/nvidia_openai.cpython-311.pyc +0 -0
  170. sage/middleware/utils/embedding/__pycache__/ollama.cpython-311.opt-2.pyc +0 -0
  171. sage/middleware/utils/embedding/__pycache__/ollama.cpython-311.pyc +0 -0
  172. sage/middleware/utils/embedding/__pycache__/openai.cpython-311.opt-2.pyc +0 -0
  173. sage/middleware/utils/embedding/__pycache__/openai.cpython-311.pyc +0 -0
  174. sage/middleware/utils/embedding/__pycache__/siliconcloud.cpython-311.opt-2.pyc +0 -0
  175. sage/middleware/utils/embedding/__pycache__/siliconcloud.cpython-311.pyc +0 -0
  176. sage/middleware/utils/embedding/__pycache__/zhipu.cpython-311.opt-2.pyc +0 -0
  177. sage/middleware/utils/embedding/__pycache__/zhipu.cpython-311.pyc +0 -0
  178. sage/middleware/utils/embedding/_cohere.py +68 -0
  179. sage/middleware/utils/embedding/bedrock.py +174 -0
  180. sage/middleware/utils/embedding/embedding_api.py +12 -0
  181. sage/middleware/utils/embedding/embedding_model.py +150 -0
  182. sage/middleware/utils/embedding/hf.py +90 -0
  183. sage/middleware/utils/embedding/instructor.py +10 -0
  184. sage/middleware/utils/embedding/jina.py +115 -0
  185. sage/middleware/utils/embedding/lollms.py +100 -0
  186. sage/middleware/utils/embedding/mockembedder.py +46 -0
  187. sage/middleware/utils/embedding/nvidia_openai.py +97 -0
  188. sage/middleware/utils/embedding/ollama.py +97 -0
  189. sage/middleware/utils/embedding/openai.py +112 -0
  190. sage/middleware/utils/embedding/siliconcloud.py +133 -0
  191. sage/middleware/utils/embedding/zhipu.py +85 -0
@@ -0,0 +1,474 @@
1
+ """
2
+ Memory Service - 记忆编排微服务
3
+ 协调KV、VDB和Graph服务,提供统一的高级记忆管理接口
4
+ 不再包含底层存储实现,而是通过服务调用机制协调其他微服务
5
+ """
6
+ from typing import Dict, Any, List, Optional, TYPE_CHECKING
7
+ from dataclasses import dataclass
8
+ import logging
9
+ import time
10
+ import uuid
11
+
12
+ from sage.kernel.runtime.service.base_service import BaseService
13
+
14
+ if TYPE_CHECKING:
15
+ from sage.core.factory.service_factory import ServiceFactory
16
+ from sage.kernel import ServiceContext
17
+
18
+
19
+ @dataclass
20
+ class MemoryConfig:
21
+ """Memory服务配置"""
22
+ kv_service_name: str = "kv_service"
23
+ vdb_service_name: str = "vdb_service"
24
+ graph_service_name: str = "graph_service"
25
+ default_vector_dimension: int = 384
26
+ max_search_results: int = 50
27
+ enable_caching: bool = True
28
+ enable_knowledge_graph: bool = True
29
+
30
+
31
+ class MemoryService(BaseService):
32
+ """
33
+ 记忆编排服务任务
34
+
35
+ 提供高级的记忆管理功能,协调KV、VDB和Graph微服务
36
+ 在SAGE DAG中作为服务节点使用
37
+ """
38
+
39
+ def __init__(self, service_factory: 'ServiceFactory', ctx: 'ServiceContext' = None):
40
+ super().__init__(service_factory, ctx)
41
+
42
+ # 从service_factory获取配置
43
+ self.config: MemoryConfig = getattr(service_factory, 'config', MemoryConfig())
44
+
45
+ self.logger.info(f"Memory Service '{self.service_name}' initialized")
46
+ self.logger.info(f"KV Service: {self.config.kv_service_name}")
47
+ self.logger.info(f"VDB Service: {self.config.vdb_service_name}")
48
+ self.logger.info(f"Graph Service: {self.config.graph_service_name}")
49
+
50
+ def _start_service_instance(self):
51
+ """启动Memory服务实例"""
52
+ self.logger.info(f"Memory Service '{self.service_name}' started")
53
+
54
+ def _stop_service_instance(self):
55
+ """停止Memory服务实例"""
56
+ self.logger.info(f"Memory Service '{self.service_name}' stopped")
57
+
58
+ def _get_kv_service(self):
59
+ """获取KV服务的代理"""
60
+ if not hasattr(self, 'ctx') or self.ctx is None:
61
+ raise RuntimeError("Service context not available")
62
+ return self.ctx.service_manager.get_service_proxy(self.config.kv_service_name)
63
+
64
+ def _get_vdb_service(self):
65
+ """获取VDB服务的代理"""
66
+ if not hasattr(self, 'ctx') or self.ctx is None:
67
+ raise RuntimeError("Service context not available")
68
+ return self.ctx.service_manager.get_service_proxy(self.config.vdb_service_name)
69
+
70
+ def _get_graph_service(self):
71
+ """获取Graph服务的代理"""
72
+ if not hasattr(self, 'ctx') or self.ctx is None:
73
+ raise RuntimeError("Service context not available")
74
+ return self.ctx.service_manager.get_service_proxy(self.config.graph_service_name)
75
+
76
+ # 高级记忆操作方法
77
+
78
+ def store_memory(
79
+ self,
80
+ content: str,
81
+ vector: List[float],
82
+ session_id: Optional[str] = None,
83
+ memory_type: str = "conversation",
84
+ metadata: Optional[Dict[str, Any]] = None,
85
+ create_knowledge_graph: bool = False
86
+ ) -> str:
87
+ """
88
+ 存储记忆(高级API)
89
+
90
+ Args:
91
+ content: 记忆内容
92
+ vector: 向量表示
93
+ session_id: 会话ID
94
+ memory_type: 记忆类型
95
+ metadata: 额外元数据
96
+ create_knowledge_graph: 是否创建知识图谱关系
97
+
98
+ Returns:
99
+ str: 记忆ID
100
+ """
101
+ try:
102
+ memory_id = str(uuid.uuid4())
103
+ timestamp = time.time()
104
+
105
+ # 准备完整元数据
106
+ full_metadata = {
107
+ "session_id": session_id,
108
+ "memory_type": memory_type,
109
+ "timestamp": timestamp,
110
+ "content_preview": content[:100],
111
+ **(metadata or {})
112
+ }
113
+
114
+ # 存储到KV服务
115
+ kv_service = self._get_kv_service()
116
+ kv_data = {
117
+ "id": memory_id,
118
+ "content": content,
119
+ "session_id": session_id,
120
+ "memory_type": memory_type,
121
+ "timestamp": timestamp,
122
+ "metadata": full_metadata
123
+ }
124
+
125
+ kv_success = kv_service.put(f"memory:{memory_id}", kv_data)
126
+ if not kv_success:
127
+ raise RuntimeError("Failed to store memory in KV service")
128
+
129
+ # 存储到VDB服务
130
+ vdb_service = self._get_vdb_service()
131
+ vdb_data = [{
132
+ "id": memory_id,
133
+ "vector": vector,
134
+ "text": content,
135
+ "metadata": full_metadata
136
+ }]
137
+
138
+ vdb_ids = vdb_service.add_vectors(vdb_data)
139
+ if not vdb_ids:
140
+ # 回滚KV存储
141
+ kv_service.delete(f"memory:{memory_id}")
142
+ raise RuntimeError("Failed to store memory in VDB service")
143
+
144
+ # 如果启用知识图谱,创建节点和关系
145
+ if create_knowledge_graph and self.config.enable_knowledge_graph:
146
+ try:
147
+ graph_service = self._get_graph_service()
148
+
149
+ # 创建记忆节点
150
+ node_data = {
151
+ "id": memory_id,
152
+ "labels": ["Memory", memory_type.capitalize()],
153
+ "properties": {
154
+ "content": content,
155
+ "timestamp": timestamp,
156
+ "session_id": session_id
157
+ }
158
+ }
159
+ graph_service.add_node(node_data)
160
+
161
+ # 如果有会话ID,创建会话关系
162
+ if session_id:
163
+ # 确保会话节点存在
164
+ session_node = {
165
+ "id": f"session:{session_id}",
166
+ "labels": ["Session"],
167
+ "properties": {"session_id": session_id}
168
+ }
169
+ graph_service.add_node(session_node)
170
+
171
+ # 创建关系
172
+ relationship = {
173
+ "from_node": f"session:{session_id}",
174
+ "to_node": memory_id,
175
+ "rel_type": "CONTAINS",
176
+ "properties": {"created_at": timestamp}
177
+ }
178
+ graph_service.add_relationship(relationship)
179
+
180
+ except Exception as e:
181
+ self.logger.warning(f"Failed to create knowledge graph for memory {memory_id}: {e}")
182
+
183
+ self.logger.debug(f"STORE memory: {memory_id}")
184
+ return memory_id
185
+
186
+ except Exception as e:
187
+ self.logger.error(f"Error storing memory: {e}")
188
+ raise
189
+
190
+ def search_memories(
191
+ self,
192
+ query_vector: List[float],
193
+ session_id: Optional[str] = None,
194
+ memory_type: Optional[str] = None,
195
+ limit: int = 10,
196
+ similarity_threshold: Optional[float] = None,
197
+ include_graph_context: bool = False
198
+ ) -> List[Dict[str, Any]]:
199
+ """
200
+ 搜索相关记忆(高级API)
201
+
202
+ Args:
203
+ query_vector: 查询向量
204
+ session_id: 限制在特定会话
205
+ memory_type: 限制记忆类型
206
+ limit: 返回结果数量
207
+ similarity_threshold: 相似度阈值
208
+ include_graph_context: 是否包含图上下文信息
209
+
210
+ Returns:
211
+ List[Dict]: 增强的记忆列表
212
+ """
213
+ try:
214
+ # 构建VDB查询条件
215
+ metadata_filter = {}
216
+ if session_id:
217
+ metadata_filter["session_id"] = session_id
218
+ if memory_type:
219
+ metadata_filter["memory_type"] = memory_type
220
+
221
+ # 从VDB搜索相似向量
222
+ vdb_service = self._get_vdb_service()
223
+ search_results = vdb_service.search_vectors(
224
+ query_vector=query_vector,
225
+ top_k=min(limit, self.config.max_search_results),
226
+ metadata_filter=metadata_filter if metadata_filter else None
227
+ )
228
+
229
+ # 过滤相似度
230
+ if similarity_threshold is not None:
231
+ search_results = [r for r in search_results if r['distance'] <= similarity_threshold]
232
+
233
+ # 从KV服务获取完整记忆数据
234
+ kv_service = self._get_kv_service()
235
+ memories = []
236
+
237
+ for result in search_results:
238
+ memory_id = result['id']
239
+ memory_data = kv_service.get(f"memory:{memory_id}")
240
+
241
+ if memory_data:
242
+ enhanced_memory = {
243
+ **memory_data,
244
+ "similarity_score": result['distance'],
245
+ "vector_text": result.get('text', ''),
246
+ }
247
+
248
+ # 如果启用图上下文,获取相关的图信息
249
+ if include_graph_context and self.config.enable_knowledge_graph:
250
+ try:
251
+ graph_service = self._get_graph_service()
252
+ # 获取该记忆的图上下文(相邻节点和关系)
253
+ graph_context = graph_service.get_node_context(memory_id, depth=1)
254
+ enhanced_memory["graph_context"] = graph_context
255
+ except Exception as e:
256
+ self.logger.warning(f"Failed to get graph context for {memory_id}: {e}")
257
+ enhanced_memory["graph_context"] = {}
258
+
259
+ memories.append(enhanced_memory)
260
+ else:
261
+ self.logger.warning(f"Memory {memory_id} found in VDB but not in KV")
262
+
263
+ self.logger.debug(f"SEARCH memories: found {len(memories)} results")
264
+ return memories
265
+
266
+ except Exception as e:
267
+ self.logger.error(f"Error searching memories: {e}")
268
+ return []
269
+
270
+ def get_memory(self, memory_id: str, include_graph_context: bool = False) -> Optional[Dict[str, Any]]:
271
+ """获取指定记忆(高级API)"""
272
+ try:
273
+ kv_service = self._get_kv_service()
274
+ memory_data = kv_service.get(f"memory:{memory_id}")
275
+
276
+ if memory_data:
277
+ # 如果启用图上下文,获取相关信息
278
+ if include_graph_context and self.config.enable_knowledge_graph:
279
+ try:
280
+ graph_service = self._get_graph_service()
281
+ graph_context = graph_service.get_node_context(memory_id, depth=1)
282
+ memory_data["graph_context"] = graph_context
283
+ except Exception as e:
284
+ self.logger.warning(f"Failed to get graph context for {memory_id}: {e}")
285
+ memory_data["graph_context"] = {}
286
+
287
+ self.logger.debug(f"GET memory: {memory_id} found")
288
+ return memory_data
289
+ else:
290
+ self.logger.debug(f"GET memory: {memory_id} not found")
291
+ return None
292
+
293
+ except Exception as e:
294
+ self.logger.error(f"Error getting memory {memory_id}: {e}")
295
+ return None
296
+
297
+ def delete_memory(self, memory_id: str) -> bool:
298
+ """删除指定记忆(高级API)"""
299
+ try:
300
+ success = True
301
+
302
+ # 从KV服务删除
303
+ kv_service = self._get_kv_service()
304
+ kv_success = kv_service.delete(f"memory:{memory_id}")
305
+ if not kv_success:
306
+ success = False
307
+
308
+ # 从VDB服务删除
309
+ vdb_service = self._get_vdb_service()
310
+ vdb_success = vdb_service.delete_vectors([memory_id])
311
+ if vdb_success == 0:
312
+ success = False
313
+
314
+ # 从图服务删除(如果启用)
315
+ if self.config.enable_knowledge_graph:
316
+ try:
317
+ graph_service = self._get_graph_service()
318
+ graph_service.delete_node(memory_id)
319
+ except Exception as e:
320
+ self.logger.warning(f"Failed to delete graph node for {memory_id}: {e}")
321
+
322
+ self.logger.debug(f"DELETE memory: {memory_id}, success: {success}")
323
+ return success
324
+
325
+ except Exception as e:
326
+ self.logger.error(f"Error deleting memory {memory_id}: {e}")
327
+ return False
328
+
329
+ def get_session_memories(
330
+ self,
331
+ session_id: str,
332
+ memory_type: Optional[str] = None,
333
+ limit: Optional[int] = None,
334
+ include_graph_analysis: bool = False
335
+ ) -> Dict[str, Any]:
336
+ """获取会话记忆(高级API)"""
337
+ try:
338
+ # 构建查询条件
339
+ metadata_filter = {"session_id": session_id}
340
+ if memory_type:
341
+ metadata_filter["memory_type"] = memory_type
342
+
343
+ # 从VDB获取会话中的所有记忆
344
+ vdb_service = self._get_vdb_service()
345
+ session_vectors = vdb_service.list_vectors(metadata_filter=metadata_filter)
346
+
347
+ # 从KV获取完整数据
348
+ kv_service = self._get_kv_service()
349
+ memories = []
350
+
351
+ for vector_data in session_vectors:
352
+ memory_id = vector_data['id']
353
+ memory_data = kv_service.get(f"memory:{memory_id}")
354
+ if memory_data:
355
+ memories.append(memory_data)
356
+
357
+ # 按时间排序
358
+ memories.sort(key=lambda m: m.get('timestamp', 0))
359
+
360
+ # 应用限制
361
+ if limit:
362
+ memories = memories[-limit:]
363
+
364
+ result = {
365
+ "session_id": session_id,
366
+ "memory_count": len(memories),
367
+ "memories": memories
368
+ }
369
+
370
+ # 如果启用图分析,提供会话的图分析
371
+ if include_graph_analysis and self.config.enable_knowledge_graph:
372
+ try:
373
+ graph_service = self._get_graph_service()
374
+ session_graph = graph_service.get_session_graph(session_id)
375
+ result["graph_analysis"] = session_graph
376
+ except Exception as e:
377
+ self.logger.warning(f"Failed to get session graph analysis: {e}")
378
+ result["graph_analysis"] = {}
379
+
380
+ self.logger.debug(f"GET session memories: {session_id}, found {len(memories)} memories")
381
+ return result
382
+
383
+ except Exception as e:
384
+ self.logger.error(f"Error getting session memories {session_id}: {e}")
385
+ return {"session_id": session_id, "memory_count": 0, "memories": []}
386
+
387
+ def stats(self) -> Dict[str, Any]:
388
+ """获取综合服务统计信息"""
389
+ try:
390
+ base_stats = self.get_statistics()
391
+
392
+ # 获取各个服务的统计
393
+ service_stats = {}
394
+
395
+ try:
396
+ kv_service = self._get_kv_service()
397
+ service_stats["kv"] = kv_service.stats() if hasattr(kv_service, 'stats') else {}
398
+ except Exception as e:
399
+ service_stats["kv"] = {"error": str(e)}
400
+
401
+ try:
402
+ vdb_service = self._get_vdb_service()
403
+ service_stats["vdb"] = vdb_service.stats() if hasattr(vdb_service, 'stats') else {}
404
+ except Exception as e:
405
+ service_stats["vdb"] = {"error": str(e)}
406
+
407
+ if self.config.enable_knowledge_graph:
408
+ try:
409
+ graph_service = self._get_graph_service()
410
+ service_stats["graph"] = graph_service.stats() if hasattr(graph_service, 'stats') else {}
411
+ except Exception as e:
412
+ service_stats["graph"] = {"error": str(e)}
413
+
414
+ memory_stats = {
415
+ "config": {
416
+ "kv_service_name": self.config.kv_service_name,
417
+ "vdb_service_name": self.config.vdb_service_name,
418
+ "graph_service_name": self.config.graph_service_name,
419
+ "enable_knowledge_graph": self.config.enable_knowledge_graph,
420
+ "enable_caching": self.config.enable_caching
421
+ },
422
+ "services": service_stats
423
+ }
424
+
425
+ base_stats.update(memory_stats)
426
+ return base_stats
427
+
428
+ except Exception as e:
429
+ self.logger.error(f"Error getting stats: {e}")
430
+ return self.get_statistics()
431
+
432
+
433
+ # 工厂函数,用于在DAG中创建Memory服务
434
+ def create_memory_service_factory(
435
+ service_name: str = "memory_service",
436
+ kv_service_name: str = "kv_service",
437
+ vdb_service_name: str = "vdb_service",
438
+ graph_service_name: str = "graph_service",
439
+ default_vector_dimension: int = 384,
440
+ max_search_results: int = 50,
441
+ enable_caching: bool = True,
442
+ enable_knowledge_graph: bool = True
443
+ ):
444
+ """
445
+ 创建Memory服务工厂
446
+
447
+ Args:
448
+ service_name: 服务名称
449
+ kv_service_name: KV服务名称
450
+ vdb_service_name: VDB服务名称
451
+ graph_service_name: Graph服务名称
452
+ default_vector_dimension: 默认向量维度
453
+ max_search_results: 最大搜索结果数
454
+ enable_caching: 是否启用缓存
455
+ enable_knowledge_graph: 是否启用知识图谱
456
+
457
+ Returns:
458
+ ServiceFactory: 可以用于注册到环境的服务工厂
459
+ """
460
+ from sage.core.factory.service_factory import ServiceFactory
461
+
462
+ config = MemoryConfig(
463
+ kv_service_name=kv_service_name,
464
+ vdb_service_name=vdb_service_name,
465
+ graph_service_name=graph_service_name,
466
+ default_vector_dimension=default_vector_dimension,
467
+ max_search_results=max_search_results,
468
+ enable_caching=enable_caching,
469
+ enable_knowledge_graph=enable_knowledge_graph
470
+ )
471
+
472
+ factory = ServiceFactory(service_name, MemoryService)
473
+ factory.config = config
474
+ return factory
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ """
2
+ VDB Service Module
3
+ 向量数据库服务模块
4
+ """
5
+
6
+ from .vdb_service import VDBService, create_vdb_service_factory
7
+
8
+ __all__ = ["VDBService", "create_vdb_service_factory"]