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,213 @@
1
+ """
2
+ KV Service API 使用示例
3
+ 展示如何正确使用KV微服务的API接口
4
+ """
5
+ import time
6
+ from sage.core.api.local_environment import LocalEnvironment
7
+ from sage.middleware.services.kv.kv_service import create_kv_service_factory
8
+ from sage.middleware.api.kv_api import KVServiceAPI
9
+
10
+
11
+ def test_kv_service_api():
12
+ """测试KV服务API的正确使用方式"""
13
+ print("🚀 KV Service API Demo")
14
+ print("=" * 50)
15
+
16
+ # 创建环境
17
+ env = LocalEnvironment("kv_service_demo")
18
+
19
+ # 注册KV服务 - 内存后端
20
+ kv_factory = create_kv_service_factory(
21
+ service_name="demo_kv_service",
22
+ backend_type="memory",
23
+ max_size=1000,
24
+ ttl_seconds=300 # 5分钟过期
25
+ )
26
+ env.register_service_factory("demo_kv_service", kv_factory)
27
+
28
+ print("✅ KV Service registered with memory backend")
29
+
30
+ # 在实际应用中,你需要启动环境并获取服务代理
31
+ # env.submit() # 启动环境
32
+ # kv_service = env.get_service_proxy("demo_kv_service")
33
+
34
+ # 这里我们演示API接口的预期使用方式
35
+ demonstrate_kv_api_usage()
36
+
37
+
38
+ def demonstrate_kv_api_usage():
39
+ """演示KV服务API的标准使用模式"""
40
+ print("\n📝 KV Service API Usage Patterns:")
41
+ print("-" * 40)
42
+
43
+ # 展示API接口
44
+ print("💡 KV Service API Interface:")
45
+ print(" class KVServiceAPI:")
46
+ print(" - put(key: str, value: Any) -> bool")
47
+ print(" - get(key: str) -> Optional[Any]")
48
+ print(" - delete(key: str) -> bool")
49
+ print(" - exists(key: str) -> bool")
50
+ print(" - list_keys(prefix: Optional[str] = None) -> List[str]")
51
+ print(" - size() -> int")
52
+ print(" - clear() -> bool")
53
+
54
+ print("\n📋 Standard Usage Example:")
55
+ usage_code = '''
56
+ # 1. 获取服务代理
57
+ kv_service = env.get_service_proxy("demo_kv_service")
58
+
59
+ # 2. 基本CRUD操作
60
+ # 存储数据
61
+ success = kv_service.put("user:123", {
62
+ "name": "Alice",
63
+ "age": 30,
64
+ "email": "alice@example.com"
65
+ })
66
+
67
+ # 读取数据
68
+ user_data = kv_service.get("user:123")
69
+ exists = kv_service.exists("user:123")
70
+
71
+ # 3. 批量操作
72
+ # 存储会话数据
73
+ session_data = {
74
+ "user_id": "123",
75
+ "timestamp": time.time(),
76
+ "activity": "browsing_products"
77
+ }
78
+ kv_service.put("session:abc", session_data)
79
+
80
+ # 列出所有用户相关的键
81
+ user_keys = kv_service.list_keys("user:")
82
+ session_keys = kv_service.list_keys("session:")
83
+
84
+ # 4. 管理操作
85
+ total_items = kv_service.size()
86
+ cleanup_success = kv_service.delete("session:abc")
87
+
88
+ # 5. 错误处理
89
+ try:
90
+ result = kv_service.get("non_existent_key")
91
+ if result is None:
92
+ print("Key not found")
93
+ except Exception as e:
94
+ print(f"Error accessing KV service: {e}")
95
+ '''
96
+ print(usage_code)
97
+
98
+ # 模拟执行结果
99
+ print("🎯 Expected Results:")
100
+ operations = [
101
+ ("put('user:123', user_data)", "True"),
102
+ ("get('user:123')", "{'name': 'Alice', 'age': 30, 'email': '...'}"),
103
+ ("exists('user:123')", "True"),
104
+ ("list_keys('user:')", "['user:123']"),
105
+ ("size()", "2"),
106
+ ("delete('session:abc')", "True"),
107
+ ("get('non_existent_key')", "None"),
108
+ ]
109
+
110
+ for operation, result in operations:
111
+ print(f" {operation:<30} -> {result}")
112
+
113
+
114
+ def test_kv_advanced_patterns():
115
+ """演示KV服务的高级使用模式"""
116
+ print("\n🔧 Advanced KV Usage Patterns:")
117
+ print("-" * 40)
118
+
119
+ advanced_patterns = '''
120
+ # 1. 缓存模式
121
+ class UserCache:
122
+ def __init__(self, kv_service: KVServiceAPI):
123
+ self.kv = kv_service
124
+ self.cache_ttl = 300 # 5分钟
125
+
126
+ def get_user(self, user_id: str):
127
+ cache_key = f"user_cache:{user_id}"
128
+ cached_user = self.kv.get(cache_key)
129
+
130
+ if cached_user is None:
131
+ # 从数据库加载
132
+ user = load_user_from_db(user_id)
133
+ # 存入缓存
134
+ self.kv.put(cache_key, user)
135
+ return user
136
+ return cached_user
137
+
138
+ # 2. 分布式锁模式
139
+ class DistributedLock:
140
+ def __init__(self, kv_service: KVServiceAPI):
141
+ self.kv = kv_service
142
+
143
+ def acquire_lock(self, resource_id: str, timeout: int = 30):
144
+ lock_key = f"lock:{resource_id}"
145
+ lock_value = {"acquired_at": time.time(), "timeout": timeout}
146
+
147
+ if not self.kv.exists(lock_key):
148
+ return self.kv.put(lock_key, lock_value)
149
+ return False
150
+
151
+ def release_lock(self, resource_id: str):
152
+ lock_key = f"lock:{resource_id}"
153
+ return self.kv.delete(lock_key)
154
+
155
+ # 3. 配置管理模式
156
+ class ConfigManager:
157
+ def __init__(self, kv_service: KVServiceAPI):
158
+ self.kv = kv_service
159
+ self.config_prefix = "config:"
160
+
161
+ def get_config(self, key: str, default=None):
162
+ config_key = f"{self.config_prefix}{key}"
163
+ value = self.kv.get(config_key)
164
+ return value if value is not None else default
165
+
166
+ def set_config(self, key: str, value):
167
+ config_key = f"{self.config_prefix}{key}"
168
+ return self.kv.put(config_key, value)
169
+
170
+ def list_all_configs(self):
171
+ return self.kv.list_keys(self.config_prefix)
172
+ '''
173
+ print(advanced_patterns)
174
+
175
+
176
+ def test_kv_with_redis():
177
+ """演示KV服务的Redis后端配置"""
178
+ print("\n🔧 Redis Backend Configuration:")
179
+
180
+ redis_config_example = '''
181
+ # Redis后端配置示例
182
+ redis_kv_factory = create_kv_service_factory(
183
+ service_name="redis_kv_service",
184
+ backend_type="redis",
185
+ redis_url="redis://localhost:6379",
186
+ redis_db=0,
187
+ connection_pool_size=10,
188
+ ttl_seconds=3600, # 1小时默认TTL
189
+ max_size=1000000 # 最大键数量
190
+ )
191
+
192
+ # 使用方式完全相同
193
+ env.register_service_factory("redis_kv", redis_kv_factory)
194
+
195
+ # API调用方式不变
196
+ redis_kv = env.get_service_proxy("redis_kv")
197
+ redis_kv.put("persistent_key", {"data": "stored_in_redis"})
198
+ '''
199
+
200
+ print(redis_config_example)
201
+ print("✅ Redis KV factory configuration shown")
202
+ print(" - 连接: redis://localhost:6379")
203
+ print(" - TTL: 1小时")
204
+ print(" - 持久化存储")
205
+ print(" - 相同的API接口")
206
+
207
+
208
+ if __name__ == "__main__":
209
+ test_kv_service_api()
210
+ test_kv_advanced_patterns()
211
+ test_kv_with_redis()
212
+ print("\n🎯 KV Service API demo completed!")
213
+ print("\n📚 Next: Check VDB and Memory service API examples")
@@ -0,0 +1,306 @@
1
+ """
2
+ KV Service - 键值存储微服务
3
+ 提供键值存储功能的服务任务,集成到SAGE DAG中
4
+ """
5
+ from typing import Dict, Any, Optional, List, TYPE_CHECKING
6
+ from dataclasses import dataclass
7
+ import json
8
+ import time
9
+ import logging
10
+
11
+ from sage.core.api.service.base_service import BaseService
12
+
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 KVConfig:
21
+ """KV服务配置"""
22
+ backend_type: str = "memory" # "memory" 或 "redis"
23
+ redis_url: Optional[str] = None
24
+ max_size: int = 10000
25
+ ttl_seconds: Optional[int] = None
26
+
27
+
28
+ class MemoryKVBackend:
29
+ """内存KV后端"""
30
+
31
+ def __init__(self, max_size: int = 10000, ttl_seconds: Optional[int] = None):
32
+ self.store: Dict[str, Any] = {}
33
+ self.timestamps: Dict[str, float] = {}
34
+ self.max_size = max_size
35
+ self.ttl_seconds = ttl_seconds
36
+ self.logger = logging.getLogger(__name__)
37
+
38
+ def get(self, key: str) -> Optional[Any]:
39
+ """获取值"""
40
+ if self._is_expired(key):
41
+ self.delete(key)
42
+ return None
43
+ return self.store.get(key)
44
+
45
+ def put(self, key: str, value: Any) -> bool:
46
+ """存储值"""
47
+ try:
48
+ if len(self.store) >= self.max_size and key not in self.store:
49
+ # 清理过期项或最老的项
50
+ self._evict_if_needed()
51
+
52
+ self.store[key] = value
53
+ self.timestamps[key] = time.time()
54
+ return True
55
+ except Exception as e:
56
+ self.logger.error(f"Error storing key {key}: {e}")
57
+ return False
58
+
59
+ def delete(self, key: str) -> bool:
60
+ """删除值"""
61
+ removed = key in self.store
62
+ self.store.pop(key, None)
63
+ self.timestamps.pop(key, None)
64
+ return removed
65
+
66
+ def list_keys(self, prefix: str = "") -> List[str]:
67
+ """列出所有键"""
68
+ # 先清理过期键
69
+ expired_keys = [k for k in self.store.keys() if self._is_expired(k)]
70
+ for k in expired_keys:
71
+ self.delete(k)
72
+
73
+ if prefix:
74
+ return [k for k in self.store.keys() if k.startswith(prefix)]
75
+ return list(self.store.keys())
76
+
77
+ def size(self) -> int:
78
+ """获取存储大小"""
79
+ return len(self.store)
80
+
81
+ def clear(self) -> None:
82
+ """清空存储"""
83
+ self.store.clear()
84
+ self.timestamps.clear()
85
+
86
+ def _is_expired(self, key: str) -> bool:
87
+ """检查键是否过期"""
88
+ if self.ttl_seconds is None:
89
+ return False
90
+
91
+ timestamp = self.timestamps.get(key)
92
+ if timestamp is None:
93
+ return True
94
+
95
+ return time.time() - timestamp > self.ttl_seconds
96
+
97
+ def _evict_if_needed(self):
98
+ """在需要时清理存储"""
99
+ # 先尝试清理过期项
100
+ expired_keys = [k for k in self.store.keys() if self._is_expired(k)]
101
+ for k in expired_keys:
102
+ self.delete(k)
103
+
104
+ # 如果还是太满,删除最老的项
105
+ if len(self.store) >= self.max_size:
106
+ # 按时间排序,删除最老的
107
+ sorted_keys = sorted(self.timestamps.items(), key=lambda x: x[1])
108
+ keys_to_remove = len(sorted_keys) - self.max_size + 1
109
+ for key, _ in sorted_keys[:keys_to_remove]:
110
+ self.delete(key)
111
+
112
+
113
+ class RedisKVBackend:
114
+ """Redis KV后端"""
115
+
116
+ def __init__(self, redis_url: str, ttl_seconds: Optional[int] = None):
117
+ try:
118
+ import redis
119
+ self.redis_client = redis.from_url(redis_url)
120
+ self.ttl_seconds = ttl_seconds
121
+ self.logger = logging.getLogger(__name__)
122
+
123
+ # 测试连接
124
+ self.redis_client.ping()
125
+ self.logger.info(f"Connected to Redis: {redis_url}")
126
+ except ImportError:
127
+ raise ImportError("Redis package not installed. Run: pip install redis")
128
+ except Exception as e:
129
+ raise ConnectionError(f"Failed to connect to Redis: {e}")
130
+
131
+ def get(self, key: str) -> Optional[Any]:
132
+ """获取值"""
133
+ try:
134
+ value = self.redis_client.get(key)
135
+ if value is None:
136
+ return None
137
+ return json.loads(value.decode('utf-8'))
138
+ except Exception as e:
139
+ self.logger.error(f"Error getting key {key}: {e}")
140
+ return None
141
+
142
+ def put(self, key: str, value: Any) -> bool:
143
+ """存储值"""
144
+ try:
145
+ serialized = json.dumps(value, ensure_ascii=False)
146
+ if self.ttl_seconds:
147
+ return self.redis_client.setex(key, self.ttl_seconds, serialized)
148
+ else:
149
+ return self.redis_client.set(key, serialized)
150
+ except Exception as e:
151
+ self.logger.error(f"Error storing key {key}: {e}")
152
+ return False
153
+
154
+ def delete(self, key: str) -> bool:
155
+ """删除值"""
156
+ try:
157
+ return bool(self.redis_client.delete(key))
158
+ except Exception as e:
159
+ self.logger.error(f"Error deleting key {key}: {e}")
160
+ return False
161
+
162
+ def list_keys(self, prefix: str = "") -> List[str]:
163
+ """列出所有键"""
164
+ try:
165
+ pattern = f"{prefix}*" if prefix else "*"
166
+ keys = self.redis_client.keys(pattern)
167
+ return [key.decode('utf-8') for key in keys]
168
+ except Exception as e:
169
+ self.logger.error(f"Error listing keys: {e}")
170
+ return []
171
+
172
+ def size(self) -> int:
173
+ """获取数据库大小"""
174
+ try:
175
+ return self.redis_client.dbsize()
176
+ except Exception as e:
177
+ self.logger.error(f"Error getting size: {e}")
178
+ return 0
179
+
180
+ def clear(self) -> None:
181
+ """清空数据库"""
182
+ try:
183
+ self.redis_client.flushdb()
184
+ except Exception as e:
185
+ self.logger.error(f"Error clearing database: {e}")
186
+
187
+
188
+ class KVService(BaseService):
189
+ """
190
+ KV服务任务
191
+
192
+ 提供键值存储功能,可以在SAGE DAG中作为服务节点使用
193
+ 支持内存和Redis后端
194
+ """
195
+
196
+ def __init__(self, service_factory: 'ServiceFactory', ctx: 'ServiceContext' = None):
197
+ super().__init__(service_factory, ctx)
198
+
199
+ # 从service_factory获取配置
200
+ self.config: KVConfig = getattr(service_factory, 'config', KVConfig())
201
+
202
+ # 初始化后端
203
+ if self.config.backend_type == "redis":
204
+ if not self.config.redis_url:
205
+ raise ValueError("Redis URL required for Redis backend")
206
+ self.backend = RedisKVBackend(self.config.redis_url, self.config.ttl_seconds)
207
+ self.logger.info(f"KV Service '{self.service_name}' initialized with Redis backend")
208
+ else:
209
+ self.backend = MemoryKVBackend(self.config.max_size, self.config.ttl_seconds)
210
+ self.logger.info(f"KV Service '{self.service_name}' initialized with memory backend")
211
+
212
+ def _start_service_instance(self):
213
+ """启动KV服务实例"""
214
+ self.logger.info(f"KV Service '{self.service_name}' started")
215
+
216
+ def _stop_service_instance(self):
217
+ """停止KV服务实例"""
218
+ self.logger.info(f"KV Service '{self.service_name}' stopped")
219
+
220
+ # KV操作方法 - 这些方法可以通过服务调用机制被调用
221
+
222
+ def get(self, key: str) -> Optional[Any]:
223
+ """获取键值"""
224
+ self.logger.debug(f"GET key: {key}")
225
+ result = self.backend.get(key)
226
+ self.logger.debug(f"GET result: {result is not None}")
227
+ return result
228
+
229
+ def put(self, key: str, value: Any) -> bool:
230
+ """存储键值"""
231
+ self.logger.debug(f"PUT key: {key}")
232
+ result = self.backend.put(key, value)
233
+ self.logger.debug(f"PUT result: {result}")
234
+ return result
235
+
236
+ def delete(self, key: str) -> bool:
237
+ """删除键值"""
238
+ self.logger.debug(f"DELETE key: {key}")
239
+ result = self.backend.delete(key)
240
+ self.logger.debug(f"DELETE result: {result}")
241
+ return result
242
+
243
+ def list_keys(self, prefix: str = "") -> List[str]:
244
+ """列出键"""
245
+ self.logger.debug(f"LIST keys with prefix: {prefix}")
246
+ result = self.backend.list_keys(prefix)
247
+ self.logger.debug(f"LIST result: {len(result)} keys")
248
+ return result
249
+
250
+ def size(self) -> int:
251
+ """获取存储大小"""
252
+ result = self.backend.size()
253
+ self.logger.debug(f"SIZE result: {result}")
254
+ return result
255
+
256
+ def clear(self) -> None:
257
+ """清空存储"""
258
+ self.logger.debug("CLEAR storage")
259
+ self.backend.clear()
260
+
261
+ def stats(self) -> Dict[str, Any]:
262
+ """获取服务统计信息"""
263
+ base_stats = self.get_statistics()
264
+ kv_stats = {
265
+ "backend_type": self.config.backend_type,
266
+ "storage_size": self.backend.size(),
267
+ "max_size": getattr(self.backend, 'max_size', None),
268
+ "ttl_seconds": self.config.ttl_seconds
269
+ }
270
+ base_stats.update(kv_stats)
271
+ return base_stats
272
+
273
+
274
+ # 工厂函数,用于在DAG中创建KV服务
275
+ def create_kv_service_factory(
276
+ service_name: str = "kv_service",
277
+ backend_type: str = "memory",
278
+ redis_url: Optional[str] = None,
279
+ max_size: int = 10000,
280
+ ttl_seconds: Optional[int] = None
281
+ ):
282
+ """
283
+ 创建KV服务工厂
284
+
285
+ Args:
286
+ service_name: 服务名称
287
+ backend_type: 后端类型 ("memory" 或 "redis")
288
+ redis_url: Redis连接URL (当backend_type="redis"时需要)
289
+ max_size: 最大存储条目数 (仅内存后端)
290
+ ttl_seconds: 数据过期时间(秒)
291
+
292
+ Returns:
293
+ ServiceFactory: 可以用于注册到环境的服务工厂
294
+ """
295
+ from sage.core.factory.service_factory import ServiceFactory
296
+
297
+ config = KVConfig(
298
+ backend_type=backend_type,
299
+ redis_url=redis_url,
300
+ max_size=max_size,
301
+ ttl_seconds=ttl_seconds
302
+ )
303
+
304
+ factory = ServiceFactory(service_name, KVService)
305
+ factory.config = config
306
+ return factory
File without changes
@@ -0,0 +1,75 @@
1
+ # file sage/core/sage.service.memory./search_engine/kv_index/base_kv_index.py
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import List, Any, Dict
5
+
6
+ class BaseKVIndex(ABC):
7
+ def __init__(
8
+ self,
9
+ name: str,
10
+ texts: List[str],
11
+ ids: List[str]
12
+ ):
13
+ """
14
+ 初始化索引基类。
15
+ Initialize the base class for KV Index.
16
+ """
17
+ self.name = name
18
+
19
+ @abstractmethod
20
+ def insert(self, text: str, id: str) -> None:
21
+ """
22
+ 插入一条新数据。
23
+ Insert a new entry.
24
+ """
25
+ pass
26
+
27
+ @abstractmethod
28
+ def delete(self, id: str) -> None:
29
+ """
30
+ 删除指定id的数据。
31
+ Delete an entry by id.
32
+ """
33
+ pass
34
+
35
+ @abstractmethod
36
+ def search(self, query: str, topk: int = 10) -> List[str]:
37
+ """
38
+ 检索相关数据,返回最相关的id列表。
39
+ Search for relevant entries and return the most relevant ids.
40
+ """
41
+ pass
42
+
43
+ @abstractmethod
44
+ def update(self, id: str, new_text: str) -> None:
45
+ """
46
+ 更新指定id的数据内容。
47
+ Update the entry corresponding to the given id.
48
+ """
49
+ pass
50
+
51
+ @classmethod
52
+ @abstractmethod
53
+ def load(cls, name: str, root_path: str) -> "BaseKVIndex":
54
+ """
55
+ 加载索引实例。
56
+ Load the index instance.
57
+ """
58
+ pass
59
+
60
+ @abstractmethod
61
+ def store(self, root_path: str) -> Dict[str, Any]:
62
+ """
63
+ 存储索引数据到指定目录。
64
+ Store the index data to the specified directory.
65
+ """
66
+ pass
67
+
68
+ @staticmethod
69
+ @abstractmethod
70
+ def clear(root_path: str, name: str) -> None:
71
+ """
72
+ 删除指定名称下的所有索引数据。
73
+ Remove all index data under the specified name.
74
+ """
75
+ pass