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.
- isage_middleware-0.1.0.dist-info/METADATA +424 -0
- isage_middleware-0.1.0.dist-info/RECORD +191 -0
- isage_middleware-0.1.0.dist-info/WHEEL +5 -0
- isage_middleware-0.1.0.dist-info/top_level.txt +1 -0
- sage/__init__.py +2 -0
- sage/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/__init__.py +83 -0
- sage/middleware/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/api/__init__.py +22 -0
- sage/middleware/api/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/api/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/api/__pycache__/graph_api.cpython-311.opt-2.pyc +0 -0
- sage/middleware/api/__pycache__/graph_api.cpython-311.pyc +0 -0
- sage/middleware/api/__pycache__/kv_api.cpython-311.opt-2.pyc +0 -0
- sage/middleware/api/__pycache__/kv_api.cpython-311.pyc +0 -0
- sage/middleware/api/__pycache__/memory_api.cpython-311.opt-2.pyc +0 -0
- sage/middleware/api/__pycache__/memory_api.cpython-311.pyc +0 -0
- sage/middleware/api/__pycache__/vdb_api.cpython-311.opt-2.pyc +0 -0
- sage/middleware/api/__pycache__/vdb_api.cpython-311.pyc +0 -0
- sage/middleware/api/graph_api.py +74 -0
- sage/middleware/api/kv_api.py +45 -0
- sage/middleware/api/memory_api.py +64 -0
- sage/middleware/api/vdb_api.py +60 -0
- sage/middleware/enterprise/__init__.py +75 -0
- sage/middleware/enterprise/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/__init__.py +132 -0
- sage/middleware/enterprise/sage_db/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/sage_db/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/__pycache__/sage_db.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/sage_db/__pycache__/sage_db.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/python/__init__.py +7 -0
- sage/middleware/enterprise/sage_db/python/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/sage_db/python/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/python/__pycache__/sage_db.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/sage_db/python/__pycache__/sage_db.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/python/sage_db.py +44 -0
- sage/middleware/enterprise/sage_db/sage_db.py +395 -0
- sage/middleware/enterprise/sage_db/tests/__pycache__/test_python.cpython-311.opt-2.pyc +0 -0
- sage/middleware/enterprise/sage_db/tests/__pycache__/test_python.cpython-311.pyc +0 -0
- sage/middleware/enterprise/sage_db/tests/test_python.py +144 -0
- sage/middleware/examples/__pycache__/api_usage_tutorial.cpython-311.opt-2.pyc +0 -0
- sage/middleware/examples/__pycache__/api_usage_tutorial.cpython-311.pyc +0 -0
- sage/middleware/examples/__pycache__/dag_microservices_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/examples/__pycache__/dag_microservices_demo.cpython-311.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_demo.cpython-311.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_integration_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_integration_demo.cpython-311.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_registration_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/examples/__pycache__/microservices_registration_demo.cpython-311.pyc +0 -0
- sage/middleware/examples/api_usage_tutorial.py +339 -0
- sage/middleware/examples/dag_microservices_demo.py +220 -0
- sage/middleware/examples/microservices_demo.py +0 -0
- sage/middleware/examples/microservices_integration_demo.py +373 -0
- sage/middleware/examples/microservices_registration_demo.py +144 -0
- sage/middleware/py.typed +2 -0
- sage/middleware/services/graph/__init__.py +8 -0
- sage/middleware/services/graph/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/graph/__pycache__/graph_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/__pycache__/graph_index.cpython-311.pyc +0 -0
- sage/middleware/services/graph/__pycache__/graph_service.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/__pycache__/graph_service.cpython-311.pyc +0 -0
- sage/middleware/services/graph/examples/__pycache__/graph_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/examples/__pycache__/graph_demo.cpython-311.pyc +0 -0
- sage/middleware/services/graph/examples/graph_demo.py +177 -0
- sage/middleware/services/graph/graph_index.py +194 -0
- sage/middleware/services/graph/graph_service.py +541 -0
- sage/middleware/services/graph/search_engine/__init__.py +0 -0
- sage/middleware/services/graph/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/graph/search_engine/__pycache__/base_graph_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/graph/search_engine/__pycache__/base_graph_index.cpython-311.pyc +0 -0
- sage/middleware/services/graph/search_engine/base_graph_index.py +0 -0
- sage/middleware/services/kv/__init__.py +8 -0
- sage/middleware/services/kv/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/kv/__pycache__/kv_service.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/__pycache__/kv_service.cpython-311.pyc +0 -0
- sage/middleware/services/kv/examples/__pycache__/kv_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/examples/__pycache__/kv_demo.cpython-311.pyc +0 -0
- sage/middleware/services/kv/examples/kv_demo.py +213 -0
- sage/middleware/services/kv/kv_service.py +306 -0
- sage/middleware/services/kv/search_engine/__init__.py +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/base_kv_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/base_kv_index.cpython-311.pyc +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/bm25s_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/kv/search_engine/__pycache__/bm25s_index.cpython-311.pyc +0 -0
- sage/middleware/services/kv/search_engine/base_kv_index.py +75 -0
- sage/middleware/services/kv/search_engine/bm25s_index.py +238 -0
- sage/middleware/services/memory/__init__.py +12 -0
- sage/middleware/services/memory/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/memory/__pycache__/memory_service.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/__pycache__/memory_service.cpython-311.pyc +0 -0
- sage/middleware/services/memory/examples/__pycache__/dag_microservices_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/examples/__pycache__/dag_microservices_demo.cpython-311.pyc +0 -0
- sage/middleware/services/memory/examples/__pycache__/memory_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/examples/__pycache__/memory_demo.cpython-311.pyc +0 -0
- sage/middleware/services/memory/examples/dag_microservices_demo.py +220 -0
- sage/middleware/services/memory/examples/memory_demo.py +490 -0
- sage/middleware/services/memory/memory_collection/__pycache__/base_collection.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/base_collection.cpython-311.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/graph_collection.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/graph_collection.cpython-311.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/kv_collection.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/kv_collection.cpython-311.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/vdb_collection.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/memory_collection/__pycache__/vdb_collection.cpython-311.pyc +0 -0
- sage/middleware/services/memory/memory_collection/base_collection.py +0 -0
- sage/middleware/services/memory/memory_collection/graph_collection.py +0 -0
- sage/middleware/services/memory/memory_collection/kv_collection.py +0 -0
- sage/middleware/services/memory/memory_collection/vdb_collection.py +0 -0
- sage/middleware/services/memory/memory_service.py +474 -0
- sage/middleware/services/memory/utils/__init__.py +0 -0
- sage/middleware/services/memory/utils/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/utils/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/memory/utils/__pycache__/path_utils.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/memory/utils/__pycache__/path_utils.cpython-311.pyc +0 -0
- sage/middleware/services/memory/utils/path_utils.py +0 -0
- sage/middleware/services/vdb/__init__.py +8 -0
- sage/middleware/services/vdb/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/__pycache__/vdb_service.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/__pycache__/vdb_service.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/examples/__pycache__/vdb_demo.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/examples/__pycache__/vdb_demo.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/examples/vdb_demo.py +447 -0
- sage/middleware/services/vdb/search_engine/__init__.py +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/base_vdb_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/base_vdb_index.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/faiss_index.cpython-311.opt-2.pyc +0 -0
- sage/middleware/services/vdb/search_engine/__pycache__/faiss_index.cpython-311.pyc +0 -0
- sage/middleware/services/vdb/search_engine/base_vdb_index.py +58 -0
- sage/middleware/services/vdb/search_engine/faiss_index.py +461 -0
- sage/middleware/services/vdb/vdb_service.py +433 -0
- sage/middleware/utils/__init__.py +5 -0
- sage/middleware/utils/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__init__.py +35 -0
- sage/middleware/utils/embedding/__pycache__/__init__.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/__init__.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/_cohere.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/_cohere.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/bedrock.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/bedrock.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/embedding_api.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/embedding_api.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/embedding_model.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/embedding_model.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/hf.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/hf.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/instructor.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/instructor.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/jina.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/jina.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/lollms.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/lollms.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/mockembedder.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/mockembedder.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/nvidia_openai.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/nvidia_openai.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/ollama.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/ollama.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/openai.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/openai.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/siliconcloud.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/siliconcloud.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/zhipu.cpython-311.opt-2.pyc +0 -0
- sage/middleware/utils/embedding/__pycache__/zhipu.cpython-311.pyc +0 -0
- sage/middleware/utils/embedding/_cohere.py +68 -0
- sage/middleware/utils/embedding/bedrock.py +174 -0
- sage/middleware/utils/embedding/embedding_api.py +12 -0
- sage/middleware/utils/embedding/embedding_model.py +150 -0
- sage/middleware/utils/embedding/hf.py +90 -0
- sage/middleware/utils/embedding/instructor.py +10 -0
- sage/middleware/utils/embedding/jina.py +115 -0
- sage/middleware/utils/embedding/lollms.py +100 -0
- sage/middleware/utils/embedding/mockembedder.py +46 -0
- sage/middleware/utils/embedding/nvidia_openai.py +97 -0
- sage/middleware/utils/embedding/ollama.py +97 -0
- sage/middleware/utils/embedding/openai.py +112 -0
- sage/middleware/utils/embedding/siliconcloud.py +133 -0
- 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
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|