powermem 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.
Files changed (123) hide show
  1. powermem/__init__.py +103 -0
  2. powermem/agent/__init__.py +35 -0
  3. powermem/agent/abstract/__init__.py +22 -0
  4. powermem/agent/abstract/collaboration.py +259 -0
  5. powermem/agent/abstract/context.py +187 -0
  6. powermem/agent/abstract/manager.py +232 -0
  7. powermem/agent/abstract/permission.py +217 -0
  8. powermem/agent/abstract/privacy.py +267 -0
  9. powermem/agent/abstract/scope.py +199 -0
  10. powermem/agent/agent.py +791 -0
  11. powermem/agent/components/__init__.py +18 -0
  12. powermem/agent/components/collaboration_coordinator.py +645 -0
  13. powermem/agent/components/permission_controller.py +586 -0
  14. powermem/agent/components/privacy_protector.py +767 -0
  15. powermem/agent/components/scope_controller.py +685 -0
  16. powermem/agent/factories/__init__.py +16 -0
  17. powermem/agent/factories/agent_factory.py +266 -0
  18. powermem/agent/factories/config_factory.py +308 -0
  19. powermem/agent/factories/memory_factory.py +229 -0
  20. powermem/agent/implementations/__init__.py +16 -0
  21. powermem/agent/implementations/hybrid.py +728 -0
  22. powermem/agent/implementations/multi_agent.py +1040 -0
  23. powermem/agent/implementations/multi_user.py +1020 -0
  24. powermem/agent/types.py +53 -0
  25. powermem/agent/wrappers/__init__.py +14 -0
  26. powermem/agent/wrappers/agent_memory_wrapper.py +427 -0
  27. powermem/agent/wrappers/compatibility_wrapper.py +520 -0
  28. powermem/config_loader.py +318 -0
  29. powermem/configs.py +249 -0
  30. powermem/core/__init__.py +19 -0
  31. powermem/core/async_memory.py +1493 -0
  32. powermem/core/audit.py +258 -0
  33. powermem/core/base.py +165 -0
  34. powermem/core/memory.py +1567 -0
  35. powermem/core/setup.py +162 -0
  36. powermem/core/telemetry.py +215 -0
  37. powermem/integrations/__init__.py +17 -0
  38. powermem/integrations/embeddings/__init__.py +13 -0
  39. powermem/integrations/embeddings/aws_bedrock.py +100 -0
  40. powermem/integrations/embeddings/azure_openai.py +55 -0
  41. powermem/integrations/embeddings/base.py +31 -0
  42. powermem/integrations/embeddings/config/base.py +132 -0
  43. powermem/integrations/embeddings/configs.py +31 -0
  44. powermem/integrations/embeddings/factory.py +48 -0
  45. powermem/integrations/embeddings/gemini.py +39 -0
  46. powermem/integrations/embeddings/huggingface.py +41 -0
  47. powermem/integrations/embeddings/langchain.py +35 -0
  48. powermem/integrations/embeddings/lmstudio.py +29 -0
  49. powermem/integrations/embeddings/mock.py +11 -0
  50. powermem/integrations/embeddings/ollama.py +53 -0
  51. powermem/integrations/embeddings/openai.py +49 -0
  52. powermem/integrations/embeddings/qwen.py +102 -0
  53. powermem/integrations/embeddings/together.py +31 -0
  54. powermem/integrations/embeddings/vertexai.py +54 -0
  55. powermem/integrations/llm/__init__.py +18 -0
  56. powermem/integrations/llm/anthropic.py +87 -0
  57. powermem/integrations/llm/base.py +132 -0
  58. powermem/integrations/llm/config/anthropic.py +56 -0
  59. powermem/integrations/llm/config/azure.py +56 -0
  60. powermem/integrations/llm/config/base.py +62 -0
  61. powermem/integrations/llm/config/deepseek.py +56 -0
  62. powermem/integrations/llm/config/ollama.py +56 -0
  63. powermem/integrations/llm/config/openai.py +79 -0
  64. powermem/integrations/llm/config/qwen.py +68 -0
  65. powermem/integrations/llm/config/qwen_asr.py +46 -0
  66. powermem/integrations/llm/config/vllm.py +56 -0
  67. powermem/integrations/llm/configs.py +26 -0
  68. powermem/integrations/llm/deepseek.py +106 -0
  69. powermem/integrations/llm/factory.py +118 -0
  70. powermem/integrations/llm/gemini.py +201 -0
  71. powermem/integrations/llm/langchain.py +65 -0
  72. powermem/integrations/llm/ollama.py +106 -0
  73. powermem/integrations/llm/openai.py +166 -0
  74. powermem/integrations/llm/openai_structured.py +80 -0
  75. powermem/integrations/llm/qwen.py +207 -0
  76. powermem/integrations/llm/qwen_asr.py +171 -0
  77. powermem/integrations/llm/vllm.py +106 -0
  78. powermem/integrations/rerank/__init__.py +20 -0
  79. powermem/integrations/rerank/base.py +43 -0
  80. powermem/integrations/rerank/config/__init__.py +7 -0
  81. powermem/integrations/rerank/config/base.py +27 -0
  82. powermem/integrations/rerank/configs.py +23 -0
  83. powermem/integrations/rerank/factory.py +68 -0
  84. powermem/integrations/rerank/qwen.py +159 -0
  85. powermem/intelligence/__init__.py +17 -0
  86. powermem/intelligence/ebbinghaus_algorithm.py +354 -0
  87. powermem/intelligence/importance_evaluator.py +361 -0
  88. powermem/intelligence/intelligent_memory_manager.py +284 -0
  89. powermem/intelligence/manager.py +148 -0
  90. powermem/intelligence/plugin.py +229 -0
  91. powermem/prompts/__init__.py +29 -0
  92. powermem/prompts/graph/graph_prompts.py +217 -0
  93. powermem/prompts/graph/graph_tools_prompts.py +469 -0
  94. powermem/prompts/importance_evaluation.py +246 -0
  95. powermem/prompts/intelligent_memory_prompts.py +163 -0
  96. powermem/prompts/templates.py +193 -0
  97. powermem/storage/__init__.py +14 -0
  98. powermem/storage/adapter.py +896 -0
  99. powermem/storage/base.py +109 -0
  100. powermem/storage/config/base.py +13 -0
  101. powermem/storage/config/oceanbase.py +58 -0
  102. powermem/storage/config/pgvector.py +52 -0
  103. powermem/storage/config/sqlite.py +27 -0
  104. powermem/storage/configs.py +159 -0
  105. powermem/storage/factory.py +59 -0
  106. powermem/storage/migration_manager.py +438 -0
  107. powermem/storage/oceanbase/__init__.py +8 -0
  108. powermem/storage/oceanbase/constants.py +162 -0
  109. powermem/storage/oceanbase/oceanbase.py +1384 -0
  110. powermem/storage/oceanbase/oceanbase_graph.py +1441 -0
  111. powermem/storage/pgvector/__init__.py +7 -0
  112. powermem/storage/pgvector/pgvector.py +420 -0
  113. powermem/storage/sqlite/__init__.py +0 -0
  114. powermem/storage/sqlite/sqlite.py +218 -0
  115. powermem/storage/sqlite/sqlite_vector_store.py +311 -0
  116. powermem/utils/__init__.py +35 -0
  117. powermem/utils/utils.py +605 -0
  118. powermem/version.py +23 -0
  119. powermem-0.1.0.dist-info/METADATA +187 -0
  120. powermem-0.1.0.dist-info/RECORD +123 -0
  121. powermem-0.1.0.dist-info/WHEEL +5 -0
  122. powermem-0.1.0.dist-info/licenses/LICENSE +206 -0
  123. powermem-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,438 @@
1
+ """
2
+ Sub-store migration status management module.
3
+
4
+ This module provides a database-backed migration status manager for sub-stores.
5
+ """
6
+
7
+ import logging
8
+ import uuid
9
+ import json
10
+ from datetime import datetime
11
+ from typing import Dict, List, Optional, Any
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class MigrationStatus:
17
+ """Migration status enum"""
18
+ PENDING = "pending" # Registered, not started
19
+ MIGRATING = "migrating" # Migration in progress
20
+ COMPLETED = "completed" # Completed, ready for routing
21
+ FAILED = "failed" # Migration failed
22
+
23
+
24
+ class SubStoreMigrationManager:
25
+ """
26
+ Sub-store migration status manager (database-backed).
27
+
28
+ This class manages migration status for sub-stores using a database table.
29
+ All status information is persisted in the database, supporting multi-process
30
+ sharing and application restarts.
31
+ """
32
+
33
+ def __init__(self, vector_store, main_collection_name: str):
34
+ """
35
+ Initialize migration manager.
36
+
37
+ Args:
38
+ vector_store: Vector store instance (must support SQL operations)
39
+ main_collection_name: Main collection name
40
+ """
41
+ self.vector_store = vector_store
42
+ self.main_collection_name = main_collection_name
43
+
44
+ # Table name for migration status
45
+ self.status_table = "sub_store_migration_status"
46
+
47
+ # Ensure table exists
48
+ self._init_status_table()
49
+
50
+ def _init_status_table(self):
51
+ """Initialize migration status table"""
52
+ try:
53
+ # Check if vector store supports SQL operations
54
+ if not hasattr(self.vector_store, 'execute_sql'):
55
+ logger.warning("Vector store does not support SQL operations, migration status will not be persisted")
56
+ return
57
+
58
+ # Create table if not exists
59
+ create_table_sql = f"""
60
+ CREATE TABLE IF NOT EXISTS {self.status_table} (
61
+ id VARCHAR(64) PRIMARY KEY,
62
+ main_collection_name VARCHAR(128) NOT NULL,
63
+ sub_store_name VARCHAR(128) NOT NULL,
64
+ routing_filter TEXT,
65
+ status VARCHAR(32) DEFAULT 'pending',
66
+ migrated_count INT DEFAULT 0,
67
+ total_count INT DEFAULT 0,
68
+ error_message TEXT,
69
+ created_at VARCHAR(128),
70
+ updated_at VARCHAR(128),
71
+ started_at VARCHAR(128),
72
+ completed_at VARCHAR(128),
73
+ UNIQUE KEY unique_sub_store (main_collection_name, sub_store_name),
74
+ KEY idx_main_collection (main_collection_name),
75
+ KEY idx_status (status)
76
+ )
77
+ """
78
+
79
+ self.vector_store.execute_sql(create_table_sql)
80
+ logger.info(f"Migration status table '{self.status_table}' initialized")
81
+
82
+ except Exception as e:
83
+ logger.warning(f"Failed to initialize migration status table: {e}")
84
+ logger.warning("Migration status will not be persisted")
85
+
86
+ def register_sub_store(
87
+ self,
88
+ sub_store_name: str,
89
+ routing_filter: Dict
90
+ ):
91
+ """
92
+ Register a sub store with pending status.
93
+
94
+ Args:
95
+ sub_store_name: Sub store name
96
+ routing_filter: Routing filter dict
97
+ """
98
+ try:
99
+ if not hasattr(self.vector_store, 'execute_sql'):
100
+ logger.debug("Skipping registration: vector store does not support SQL")
101
+ return
102
+
103
+ status_id = str(uuid.uuid4())
104
+ now = datetime.utcnow().isoformat()
105
+
106
+ # Convert routing filter to JSON string
107
+ routing_filter_json = json.dumps(routing_filter)
108
+
109
+ # Insert with ON DUPLICATE KEY UPDATE (for MySQL/OceanBase)
110
+ insert_sql = f"""
111
+ INSERT INTO {self.status_table}
112
+ (id, main_collection_name, sub_store_name, routing_filter, status, created_at, updated_at)
113
+ VALUES
114
+ ('{status_id}', '{self.main_collection_name}', '{sub_store_name}',
115
+ '{routing_filter_json}', '{MigrationStatus.PENDING}', '{now}', '{now}')
116
+ ON DUPLICATE KEY UPDATE
117
+ routing_filter = '{routing_filter_json}',
118
+ updated_at = '{now}'
119
+ """
120
+
121
+ self.vector_store.execute_sql(insert_sql)
122
+ logger.info(f"Registered sub store '{sub_store_name}' with status: pending")
123
+
124
+ except Exception as e:
125
+ logger.error(f"Failed to register sub store: {e}")
126
+
127
+ def is_ready(self, sub_store_name: str) -> bool:
128
+ """
129
+ Check if sub store is ready (migration completed).
130
+
131
+ Args:
132
+ sub_store_name: Sub store name
133
+
134
+ Returns:
135
+ True if migration completed, False otherwise
136
+ """
137
+ try:
138
+ status = self.get_status(sub_store_name)
139
+ if status:
140
+ return status.get("status") == MigrationStatus.COMPLETED
141
+ return False
142
+
143
+ except Exception as e:
144
+ logger.error(f"Failed to check sub store readiness: {e}")
145
+ return False
146
+
147
+ def mark_migrating(self, sub_store_name: str, total_count: int):
148
+ """
149
+ Mark sub store as migrating.
150
+
151
+ Args:
152
+ sub_store_name: Sub store name
153
+ total_count: Total number of records to migrate
154
+ """
155
+ try:
156
+ if not hasattr(self.vector_store, 'execute_sql'):
157
+ return
158
+
159
+ now = datetime.utcnow().isoformat()
160
+
161
+ update_sql = f"""
162
+ UPDATE {self.status_table}
163
+ SET status = '{MigrationStatus.MIGRATING}',
164
+ total_count = {total_count},
165
+ started_at = '{now}',
166
+ updated_at = '{now}'
167
+ WHERE main_collection_name = '{self.main_collection_name}'
168
+ AND sub_store_name = '{sub_store_name}'
169
+ """
170
+
171
+ self.vector_store.execute_sql(update_sql)
172
+ logger.info(f"Marked sub store '{sub_store_name}' as migrating (total: {total_count})")
173
+
174
+ except Exception as e:
175
+ logger.error(f"Failed to mark sub store as migrating: {e}")
176
+
177
+ def update_progress(self, sub_store_name: str, migrated_count: int):
178
+ """
179
+ Update migration progress.
180
+
181
+ Args:
182
+ sub_store_name: Sub store name
183
+ migrated_count: Number of migrated records
184
+ """
185
+ try:
186
+ if not hasattr(self.vector_store, 'execute_sql'):
187
+ return
188
+
189
+ now = datetime.utcnow().isoformat()
190
+
191
+ update_sql = f"""
192
+ UPDATE {self.status_table}
193
+ SET migrated_count = {migrated_count},
194
+ updated_at = '{now}'
195
+ WHERE main_collection_name = '{self.main_collection_name}'
196
+ AND sub_store_name = '{sub_store_name}'
197
+ """
198
+
199
+ self.vector_store.execute_sql(update_sql)
200
+ logger.debug(f"Updated progress for '{sub_store_name}': {migrated_count}")
201
+
202
+ except Exception as e:
203
+ logger.error(f"Failed to update progress: {e}")
204
+
205
+ def mark_completed(self, sub_store_name: str, migrated_count: int):
206
+ """
207
+ Mark sub store migration as completed.
208
+
209
+ Args:
210
+ sub_store_name: Sub store name
211
+ migrated_count: Final migrated count
212
+ """
213
+ try:
214
+ if not hasattr(self.vector_store, 'execute_sql'):
215
+ return
216
+
217
+ now = datetime.utcnow().isoformat()
218
+
219
+ update_sql = f"""
220
+ UPDATE {self.status_table}
221
+ SET status = '{MigrationStatus.COMPLETED}',
222
+ migrated_count = {migrated_count},
223
+ completed_at = '{now}',
224
+ updated_at = '{now}',
225
+ error_message = NULL
226
+ WHERE main_collection_name = '{self.main_collection_name}'
227
+ AND sub_store_name = '{sub_store_name}'
228
+ """
229
+
230
+ self.vector_store.execute_sql(update_sql)
231
+ logger.info(f"Marked sub store '{sub_store_name}' as completed ({migrated_count} records)")
232
+
233
+ except Exception as e:
234
+ logger.error(f"Failed to mark sub store as completed: {e}")
235
+
236
+ def mark_failed(self, sub_store_name: str, error_message: str):
237
+ """
238
+ Mark sub store migration as failed.
239
+
240
+ Args:
241
+ sub_store_name: Sub store name
242
+ error_message: Error message
243
+ """
244
+ try:
245
+ if not hasattr(self.vector_store, 'execute_sql'):
246
+ return
247
+
248
+ now = datetime.utcnow().isoformat()
249
+
250
+ # Escape single quotes in error message
251
+ error_message_escaped = error_message.replace("'", "''")
252
+
253
+ update_sql = f"""
254
+ UPDATE {self.status_table}
255
+ SET status = '{MigrationStatus.FAILED}',
256
+ error_message = '{error_message_escaped}',
257
+ updated_at = '{now}'
258
+ WHERE main_collection_name = '{self.main_collection_name}'
259
+ AND sub_store_name = '{sub_store_name}'
260
+ """
261
+
262
+ self.vector_store.execute_sql(update_sql)
263
+ logger.error(f"Marked sub store '{sub_store_name}' as failed: {error_message}")
264
+
265
+ except Exception as e:
266
+ logger.error(f"Failed to mark sub store as failed: {e}")
267
+
268
+ def get_status(self, sub_store_name: str) -> Optional[Dict[str, Any]]:
269
+ """
270
+ Get detailed status for a sub store.
271
+
272
+ Args:
273
+ sub_store_name: Sub store name
274
+
275
+ Returns:
276
+ Status dict or None if not found
277
+ """
278
+ try:
279
+ if not hasattr(self.vector_store, 'execute_sql'):
280
+ return None
281
+
282
+ query_sql = f"""
283
+ SELECT * FROM {self.status_table}
284
+ WHERE main_collection_name = '{self.main_collection_name}'
285
+ AND sub_store_name = '{sub_store_name}'
286
+ LIMIT 1
287
+ """
288
+
289
+ result = self.vector_store.execute_sql(query_sql)
290
+
291
+ if result and len(result) > 0:
292
+ row = result[0]
293
+ return {
294
+ "id": row.get("id"),
295
+ "main_collection_name": row.get("main_collection_name"),
296
+ "sub_store_name": row.get("sub_store_name"),
297
+ "routing_filter": json.loads(row.get("routing_filter", "{}")),
298
+ "status": row.get("status"),
299
+ "migrated_count": row.get("migrated_count", 0),
300
+ "total_count": row.get("total_count", 0),
301
+ "error_message": row.get("error_message"),
302
+ "created_at": row.get("created_at"),
303
+ "updated_at": row.get("updated_at"),
304
+ "started_at": row.get("started_at"),
305
+ "completed_at": row.get("completed_at"),
306
+ }
307
+
308
+ return None
309
+
310
+ except Exception as e:
311
+ logger.error(f"Failed to get status: {e}")
312
+ return None
313
+
314
+ def get_migration_progress(self, sub_store_name: str) -> Optional[Dict[str, Any]]:
315
+ """
316
+ Get migration progress including percentage.
317
+
318
+ Args:
319
+ sub_store_name: Sub store name
320
+
321
+ Returns:
322
+ Progress dict or None if not found
323
+ """
324
+ try:
325
+ status = self.get_status(sub_store_name)
326
+ if not status:
327
+ return None
328
+
329
+ total_count = status.get("total_count", 0)
330
+ migrated_count = status.get("migrated_count", 0)
331
+
332
+ # Calculate percentage
333
+ if total_count > 0:
334
+ progress_percentage = (migrated_count / total_count) * 100
335
+ else:
336
+ progress_percentage = 0.0
337
+
338
+ # Calculate elapsed time
339
+ started_at = status.get("started_at")
340
+ updated_at = status.get("updated_at")
341
+ elapsed_seconds = None
342
+
343
+ if started_at and updated_at:
344
+ try:
345
+ start_time = datetime.fromisoformat(started_at)
346
+ current_time = datetime.fromisoformat(updated_at)
347
+ elapsed_seconds = (current_time - start_time).total_seconds()
348
+ except Exception:
349
+ pass
350
+
351
+ return {
352
+ "sub_store_name": sub_store_name,
353
+ "status": status.get("status"),
354
+ "progress_percentage": progress_percentage,
355
+ "migrated_count": migrated_count,
356
+ "total_count": total_count,
357
+ "elapsed_seconds": elapsed_seconds,
358
+ "error_message": status.get("error_message"),
359
+ "is_ready": status.get("status") == MigrationStatus.COMPLETED
360
+ }
361
+
362
+ except Exception as e:
363
+ logger.error(f"Failed to get migration progress: {e}")
364
+ return None
365
+
366
+ def list_all_status(self) -> List[Dict[str, Any]]:
367
+ """
368
+ List status for all sub stores under this main collection.
369
+
370
+ Returns:
371
+ List of status dicts
372
+ """
373
+ try:
374
+ if not hasattr(self.vector_store, 'execute_sql'):
375
+ return []
376
+
377
+ query_sql = f"""
378
+ SELECT * FROM {self.status_table}
379
+ WHERE main_collection_name = '{self.main_collection_name}'
380
+ ORDER BY created_at
381
+ """
382
+
383
+ results = self.vector_store.execute_sql(query_sql)
384
+
385
+ status_list = []
386
+ for row in results:
387
+ status_list.append({
388
+ "id": row.get("id"),
389
+ "sub_store_name": row.get("sub_store_name"),
390
+ "routing_filter": json.loads(row.get("routing_filter", "{}")),
391
+ "status": row.get("status"),
392
+ "migrated_count": row.get("migrated_count", 0),
393
+ "total_count": row.get("total_count", 0),
394
+ "error_message": row.get("error_message"),
395
+ "created_at": row.get("created_at"),
396
+ "updated_at": row.get("updated_at"),
397
+ "started_at": row.get("started_at"),
398
+ "completed_at": row.get("completed_at"),
399
+ })
400
+
401
+ return status_list
402
+
403
+ except Exception as e:
404
+ logger.error(f"Failed to list all status: {e}")
405
+ return []
406
+
407
+ def reset_status(self, sub_store_name: str):
408
+ """
409
+ Reset sub store migration status to pending (for retry).
410
+
411
+ Args:
412
+ sub_store_name: Sub store name
413
+ """
414
+ try:
415
+ if not hasattr(self.vector_store, 'execute_sql'):
416
+ return
417
+
418
+ now = datetime.utcnow().isoformat()
419
+
420
+ update_sql = f"""
421
+ UPDATE {self.status_table}
422
+ SET status = '{MigrationStatus.PENDING}',
423
+ migrated_count = 0,
424
+ total_count = 0,
425
+ error_message = NULL,
426
+ started_at = NULL,
427
+ completed_at = NULL,
428
+ updated_at = '{now}'
429
+ WHERE main_collection_name = '{self.main_collection_name}'
430
+ AND sub_store_name = '{sub_store_name}'
431
+ """
432
+
433
+ self.vector_store.execute_sql(update_sql)
434
+ logger.info(f"Reset migration status for sub store '{sub_store_name}'")
435
+
436
+ except Exception as e:
437
+ logger.error(f"Failed to reset status: {e}")
438
+
@@ -0,0 +1,8 @@
1
+ """
2
+ OceanBase storage module initialization
3
+ """
4
+
5
+ from .oceanbase import OceanBaseVectorStore
6
+ from .oceanbase_graph import MemoryGraph
7
+
8
+ __all__ = ["OceanBaseVectorStore", "MemoryGraph"]
@@ -0,0 +1,162 @@
1
+ """
2
+ OceanBase storage constants
3
+
4
+ This module contains all constants used across OceanBase storage implementations.
5
+ """
6
+
7
+ try:
8
+ from pyobvector import VecIndexType
9
+ except ImportError:
10
+ # Fallback for when pyobvector is not available
11
+ class VecIndexType:
12
+ HNSW = "HNSW"
13
+ HNSW_SQ = "HNSW_SQ"
14
+ IVFFLAT = "IVFFLAT"
15
+ IVFSQ = "IVFSQ"
16
+ IVFPQ = "IVFPQ"
17
+
18
+
19
+ # =============================================================================
20
+ # Connection Defaults
21
+ # =============================================================================
22
+
23
+ DEFAULT_OCEANBASE_CONNECTION = {
24
+ "host": "localhost",
25
+ "port": "2881",
26
+ "user": "root@test",
27
+ "password": "",
28
+ "db_name": "test",
29
+ }
30
+
31
+
32
+ # =============================================================================
33
+ # Vector Index Configuration
34
+ # =============================================================================
35
+
36
+ # Index type groupings for easier management
37
+ INDEX_TYPE_HNSW = ("HNSW", "HNSW_SQ")
38
+ INDEX_TYPE_IVF = ("IVF", "IVF_FLAT", "IVF_SQ")
39
+ INDEX_TYPE_IVF_PQ = "IVF_PQ"
40
+
41
+ # Default vector metric type
42
+ DEFAULT_OCEANBASE_VECTOR_METRIC_TYPE = "l2"
43
+ DEFAULT_VIDX_NAME = "vidx"
44
+ DEFAULT_INDEX_TYPE = "HNSW"
45
+
46
+ # Default parameters for different index types
47
+ DEFAULT_OCEANBASE_HNSW_BUILD_PARAM = {"M": 16, "efConstruction": 200}
48
+ DEFAULT_OCEANBASE_HNSW_SEARCH_PARAM = {"efSearch": 64}
49
+ DEFAULT_OCEANBASE_IVF_BUILD_PARAM = {"nlist": 128}
50
+ DEFAULT_OCEANBASE_IVF_SEARCH_PARAM = {}
51
+ DEFAULT_OCEANBASE_IVF_PQ_BUILD_PARAM = {"nlist": 128, "m": 3}
52
+ DEFAULT_OCEANBASE_FLAT_BUILD_PARAM = {}
53
+ DEFAULT_OCEANBASE_FLAT_SEARCH_PARAM = {}
54
+
55
+ # Supported vector index types mapping
56
+ OCEANBASE_SUPPORTED_VECTOR_INDEX_TYPES = {
57
+ "HNSW": VecIndexType.HNSW,
58
+ "HNSW_SQ": VecIndexType.HNSW_SQ,
59
+ "IVF": VecIndexType.IVFFLAT,
60
+ "IVF_FLAT": VecIndexType.IVFFLAT,
61
+ "IVF_SQ": VecIndexType.IVFSQ,
62
+ "IVF_PQ": VecIndexType.IVFPQ,
63
+ "FLAT": VecIndexType.IVFFLAT,
64
+ }
65
+
66
+ # Index type to build parameters mapping
67
+ OCEANBASE_BUILD_PARAMS_MAPPING = {
68
+ "HNSW": DEFAULT_OCEANBASE_HNSW_BUILD_PARAM,
69
+ "HNSW_SQ": DEFAULT_OCEANBASE_HNSW_BUILD_PARAM,
70
+ "IVF": DEFAULT_OCEANBASE_IVF_BUILD_PARAM,
71
+ "IVF_FLAT": DEFAULT_OCEANBASE_IVF_BUILD_PARAM,
72
+ "IVF_SQ": DEFAULT_OCEANBASE_IVF_BUILD_PARAM,
73
+ "IVF_PQ": DEFAULT_OCEANBASE_IVF_PQ_BUILD_PARAM,
74
+ "FLAT": DEFAULT_OCEANBASE_FLAT_BUILD_PARAM,
75
+ }
76
+
77
+ # Index type to search parameters mapping
78
+ OCEANBASE_SEARCH_PARAMS_MAPPING = {
79
+ "HNSW": DEFAULT_OCEANBASE_HNSW_SEARCH_PARAM,
80
+ "HNSW_SQ": DEFAULT_OCEANBASE_HNSW_SEARCH_PARAM,
81
+ "IVF": DEFAULT_OCEANBASE_IVF_SEARCH_PARAM,
82
+ "IVF_FLAT": DEFAULT_OCEANBASE_IVF_SEARCH_PARAM,
83
+ "IVF_SQ": DEFAULT_OCEANBASE_IVF_SEARCH_PARAM,
84
+ "IVF_PQ": DEFAULT_OCEANBASE_IVF_SEARCH_PARAM,
85
+ "FLAT": DEFAULT_OCEANBASE_FLAT_SEARCH_PARAM,
86
+ }
87
+
88
+
89
+ # =============================================================================
90
+ # Field Names
91
+ # =============================================================================
92
+
93
+ DEFAULT_METADATA_FIELD = "metadata"
94
+ DEFAULT_PRIMARY_FIELD = "id"
95
+ DEFAULT_VECTOR_FIELD = "embedding"
96
+ DEFAULT_TEXT_FIELD = "document"
97
+
98
+
99
+ # =============================================================================
100
+ # Fulltext Search
101
+ # =============================================================================
102
+
103
+ # Supported fulltext parsers
104
+ OCEANBASE_SUPPORTED_FULLTEXT_PARSERS = ["ik", "ngram", "ngram2", "beng", "space"]
105
+ DEFAULT_FULLTEXT_PARSER = "ik"
106
+
107
+
108
+ # =============================================================================
109
+ # Graph Storage Configuration
110
+ # =============================================================================
111
+
112
+ # Table names for graph storage
113
+ TABLE_ENTITIES = "graph_entities"
114
+ TABLE_RELATIONSHIPS = "graph_relationships"
115
+
116
+ # Graph search parameters
117
+ DEFAULT_SIMILARITY_THRESHOLD = 0.7
118
+ DEFAULT_PATH_STRING_LENGTH = 500
119
+ DEFAULT_SEARCH_LIMIT = 100
120
+ DEFAULT_BM25_TOP_N = 15
121
+
122
+
123
+ # =============================================================================
124
+ # LLM Configuration
125
+ # =============================================================================
126
+
127
+ # Default LLM provider
128
+ DEFAULT_LLM_PROVIDER = "openai"
129
+
130
+ # Structured LLM providers
131
+ STRUCTURED_LLM_PROVIDERS = ["openai_structured"]
132
+
133
+
134
+ # =============================================================================
135
+ # Helper Functions
136
+ # =============================================================================
137
+
138
+ def get_default_build_params(index_type: str) -> dict:
139
+ """Get default build parameters for the given index type."""
140
+ if index_type in INDEX_TYPE_HNSW:
141
+ return DEFAULT_OCEANBASE_HNSW_BUILD_PARAM.copy()
142
+ elif index_type in INDEX_TYPE_IVF:
143
+ return DEFAULT_OCEANBASE_IVF_BUILD_PARAM.copy()
144
+ elif index_type == INDEX_TYPE_IVF_PQ:
145
+ return DEFAULT_OCEANBASE_IVF_PQ_BUILD_PARAM.copy()
146
+ else:
147
+ return DEFAULT_OCEANBASE_FLAT_BUILD_PARAM.copy()
148
+
149
+
150
+ def get_default_search_params(index_type: str) -> dict:
151
+ """Get default search parameters for the given index type."""
152
+ if index_type in INDEX_TYPE_HNSW:
153
+ return DEFAULT_OCEANBASE_HNSW_SEARCH_PARAM.copy()
154
+ elif index_type in INDEX_TYPE_IVF:
155
+ return DEFAULT_OCEANBASE_IVF_SEARCH_PARAM.copy()
156
+ else:
157
+ return DEFAULT_OCEANBASE_FLAT_SEARCH_PARAM.copy()
158
+
159
+
160
+ def is_structured_llm_provider(provider: str) -> bool:
161
+ """Check if the given provider is a structured LLM provider."""
162
+ return provider in STRUCTURED_LLM_PROVIDERS