aiecs 1.5.1__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 (302) hide show
  1. aiecs/__init__.py +72 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +469 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +363 -0
  7. aiecs/application/knowledge_graph/__init__.py +7 -0
  8. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
  11. aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
  12. aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
  13. aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
  14. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  15. aiecs/application/knowledge_graph/extractors/base.py +100 -0
  16. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
  17. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
  18. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
  19. aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
  20. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
  21. aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
  22. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
  23. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
  24. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  25. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
  26. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
  27. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  28. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
  29. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  30. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  31. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
  32. aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
  33. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
  34. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  35. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  36. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
  37. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
  38. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
  39. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
  40. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
  41. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
  42. aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
  43. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
  44. aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
  45. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
  46. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  47. aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
  48. aiecs/application/knowledge_graph/search/reranker.py +295 -0
  49. aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
  50. aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
  51. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  52. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
  53. aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
  54. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  55. aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
  56. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  57. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
  58. aiecs/common/__init__.py +9 -0
  59. aiecs/common/knowledge_graph/__init__.py +17 -0
  60. aiecs/common/knowledge_graph/runnable.py +484 -0
  61. aiecs/config/__init__.py +16 -0
  62. aiecs/config/config.py +498 -0
  63. aiecs/config/graph_config.py +137 -0
  64. aiecs/config/registry.py +23 -0
  65. aiecs/core/__init__.py +46 -0
  66. aiecs/core/interface/__init__.py +34 -0
  67. aiecs/core/interface/execution_interface.py +152 -0
  68. aiecs/core/interface/storage_interface.py +171 -0
  69. aiecs/domain/__init__.py +289 -0
  70. aiecs/domain/agent/__init__.py +189 -0
  71. aiecs/domain/agent/base_agent.py +697 -0
  72. aiecs/domain/agent/exceptions.py +103 -0
  73. aiecs/domain/agent/graph_aware_mixin.py +559 -0
  74. aiecs/domain/agent/hybrid_agent.py +490 -0
  75. aiecs/domain/agent/integration/__init__.py +26 -0
  76. aiecs/domain/agent/integration/context_compressor.py +222 -0
  77. aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
  78. aiecs/domain/agent/integration/retry_policy.py +219 -0
  79. aiecs/domain/agent/integration/role_config.py +213 -0
  80. aiecs/domain/agent/knowledge_aware_agent.py +646 -0
  81. aiecs/domain/agent/lifecycle.py +296 -0
  82. aiecs/domain/agent/llm_agent.py +300 -0
  83. aiecs/domain/agent/memory/__init__.py +12 -0
  84. aiecs/domain/agent/memory/conversation.py +197 -0
  85. aiecs/domain/agent/migration/__init__.py +14 -0
  86. aiecs/domain/agent/migration/conversion.py +160 -0
  87. aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
  88. aiecs/domain/agent/models.py +317 -0
  89. aiecs/domain/agent/observability.py +407 -0
  90. aiecs/domain/agent/persistence.py +289 -0
  91. aiecs/domain/agent/prompts/__init__.py +29 -0
  92. aiecs/domain/agent/prompts/builder.py +161 -0
  93. aiecs/domain/agent/prompts/formatters.py +189 -0
  94. aiecs/domain/agent/prompts/template.py +255 -0
  95. aiecs/domain/agent/registry.py +260 -0
  96. aiecs/domain/agent/tool_agent.py +257 -0
  97. aiecs/domain/agent/tools/__init__.py +12 -0
  98. aiecs/domain/agent/tools/schema_generator.py +221 -0
  99. aiecs/domain/community/__init__.py +155 -0
  100. aiecs/domain/community/agent_adapter.py +477 -0
  101. aiecs/domain/community/analytics.py +481 -0
  102. aiecs/domain/community/collaborative_workflow.py +642 -0
  103. aiecs/domain/community/communication_hub.py +645 -0
  104. aiecs/domain/community/community_builder.py +320 -0
  105. aiecs/domain/community/community_integration.py +800 -0
  106. aiecs/domain/community/community_manager.py +813 -0
  107. aiecs/domain/community/decision_engine.py +879 -0
  108. aiecs/domain/community/exceptions.py +225 -0
  109. aiecs/domain/community/models/__init__.py +33 -0
  110. aiecs/domain/community/models/community_models.py +268 -0
  111. aiecs/domain/community/resource_manager.py +457 -0
  112. aiecs/domain/community/shared_context_manager.py +603 -0
  113. aiecs/domain/context/__init__.py +58 -0
  114. aiecs/domain/context/context_engine.py +989 -0
  115. aiecs/domain/context/conversation_models.py +354 -0
  116. aiecs/domain/context/graph_memory.py +467 -0
  117. aiecs/domain/execution/__init__.py +12 -0
  118. aiecs/domain/execution/model.py +57 -0
  119. aiecs/domain/knowledge_graph/__init__.py +19 -0
  120. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  121. aiecs/domain/knowledge_graph/models/entity.py +130 -0
  122. aiecs/domain/knowledge_graph/models/evidence.py +194 -0
  123. aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
  124. aiecs/domain/knowledge_graph/models/path.py +179 -0
  125. aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
  126. aiecs/domain/knowledge_graph/models/query.py +272 -0
  127. aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
  128. aiecs/domain/knowledge_graph/models/relation.py +136 -0
  129. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  130. aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
  131. aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
  132. aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
  133. aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
  134. aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
  135. aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
  136. aiecs/domain/task/__init__.py +13 -0
  137. aiecs/domain/task/dsl_processor.py +613 -0
  138. aiecs/domain/task/model.py +62 -0
  139. aiecs/domain/task/task_context.py +268 -0
  140. aiecs/infrastructure/__init__.py +24 -0
  141. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  142. aiecs/infrastructure/graph_storage/base.py +601 -0
  143. aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
  144. aiecs/infrastructure/graph_storage/cache.py +429 -0
  145. aiecs/infrastructure/graph_storage/distributed.py +226 -0
  146. aiecs/infrastructure/graph_storage/error_handling.py +390 -0
  147. aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
  148. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  149. aiecs/infrastructure/graph_storage/in_memory.py +514 -0
  150. aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
  151. aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
  152. aiecs/infrastructure/graph_storage/metrics.py +357 -0
  153. aiecs/infrastructure/graph_storage/migration.py +413 -0
  154. aiecs/infrastructure/graph_storage/pagination.py +471 -0
  155. aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
  156. aiecs/infrastructure/graph_storage/postgres.py +871 -0
  157. aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
  158. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  159. aiecs/infrastructure/graph_storage/sqlite.py +623 -0
  160. aiecs/infrastructure/graph_storage/streaming.py +495 -0
  161. aiecs/infrastructure/messaging/__init__.py +13 -0
  162. aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
  163. aiecs/infrastructure/messaging/websocket_manager.py +298 -0
  164. aiecs/infrastructure/monitoring/__init__.py +34 -0
  165. aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
  166. aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
  167. aiecs/infrastructure/monitoring/structured_logger.py +48 -0
  168. aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
  169. aiecs/infrastructure/persistence/__init__.py +24 -0
  170. aiecs/infrastructure/persistence/context_engine_client.py +187 -0
  171. aiecs/infrastructure/persistence/database_manager.py +333 -0
  172. aiecs/infrastructure/persistence/file_storage.py +754 -0
  173. aiecs/infrastructure/persistence/redis_client.py +220 -0
  174. aiecs/llm/__init__.py +86 -0
  175. aiecs/llm/callbacks/__init__.py +11 -0
  176. aiecs/llm/callbacks/custom_callbacks.py +264 -0
  177. aiecs/llm/client_factory.py +420 -0
  178. aiecs/llm/clients/__init__.py +33 -0
  179. aiecs/llm/clients/base_client.py +193 -0
  180. aiecs/llm/clients/googleai_client.py +181 -0
  181. aiecs/llm/clients/openai_client.py +131 -0
  182. aiecs/llm/clients/vertex_client.py +437 -0
  183. aiecs/llm/clients/xai_client.py +184 -0
  184. aiecs/llm/config/__init__.py +51 -0
  185. aiecs/llm/config/config_loader.py +275 -0
  186. aiecs/llm/config/config_validator.py +236 -0
  187. aiecs/llm/config/model_config.py +151 -0
  188. aiecs/llm/utils/__init__.py +10 -0
  189. aiecs/llm/utils/validate_config.py +91 -0
  190. aiecs/main.py +363 -0
  191. aiecs/scripts/__init__.py +3 -0
  192. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  193. aiecs/scripts/aid/__init__.py +19 -0
  194. aiecs/scripts/aid/version_manager.py +215 -0
  195. aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
  196. aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
  197. aiecs/scripts/dependance_check/__init__.py +17 -0
  198. aiecs/scripts/dependance_check/dependency_checker.py +938 -0
  199. aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
  200. aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
  201. aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
  202. aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
  203. aiecs/scripts/dependance_patch/__init__.py +7 -0
  204. aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
  205. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  206. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
  207. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
  208. aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
  209. aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
  210. aiecs/scripts/tools_develop/README.md +449 -0
  211. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  212. aiecs/scripts/tools_develop/__init__.py +21 -0
  213. aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
  214. aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
  215. aiecs/scripts/tools_develop/verify_tools.py +356 -0
  216. aiecs/tasks/__init__.py +1 -0
  217. aiecs/tasks/worker.py +172 -0
  218. aiecs/tools/__init__.py +299 -0
  219. aiecs/tools/apisource/__init__.py +99 -0
  220. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  221. aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
  222. aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
  223. aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
  224. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  225. aiecs/tools/apisource/monitoring/metrics.py +303 -0
  226. aiecs/tools/apisource/providers/__init__.py +115 -0
  227. aiecs/tools/apisource/providers/base.py +664 -0
  228. aiecs/tools/apisource/providers/census.py +401 -0
  229. aiecs/tools/apisource/providers/fred.py +564 -0
  230. aiecs/tools/apisource/providers/newsapi.py +412 -0
  231. aiecs/tools/apisource/providers/worldbank.py +357 -0
  232. aiecs/tools/apisource/reliability/__init__.py +12 -0
  233. aiecs/tools/apisource/reliability/error_handler.py +375 -0
  234. aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
  235. aiecs/tools/apisource/tool.py +850 -0
  236. aiecs/tools/apisource/utils/__init__.py +9 -0
  237. aiecs/tools/apisource/utils/validators.py +338 -0
  238. aiecs/tools/base_tool.py +201 -0
  239. aiecs/tools/docs/__init__.py +121 -0
  240. aiecs/tools/docs/ai_document_orchestrator.py +599 -0
  241. aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
  242. aiecs/tools/docs/content_insertion_tool.py +1333 -0
  243. aiecs/tools/docs/document_creator_tool.py +1317 -0
  244. aiecs/tools/docs/document_layout_tool.py +1166 -0
  245. aiecs/tools/docs/document_parser_tool.py +994 -0
  246. aiecs/tools/docs/document_writer_tool.py +1818 -0
  247. aiecs/tools/knowledge_graph/__init__.py +17 -0
  248. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
  249. aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
  250. aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
  251. aiecs/tools/langchain_adapter.py +542 -0
  252. aiecs/tools/schema_generator.py +275 -0
  253. aiecs/tools/search_tool/__init__.py +100 -0
  254. aiecs/tools/search_tool/analyzers.py +589 -0
  255. aiecs/tools/search_tool/cache.py +260 -0
  256. aiecs/tools/search_tool/constants.py +128 -0
  257. aiecs/tools/search_tool/context.py +216 -0
  258. aiecs/tools/search_tool/core.py +749 -0
  259. aiecs/tools/search_tool/deduplicator.py +123 -0
  260. aiecs/tools/search_tool/error_handler.py +271 -0
  261. aiecs/tools/search_tool/metrics.py +371 -0
  262. aiecs/tools/search_tool/rate_limiter.py +178 -0
  263. aiecs/tools/search_tool/schemas.py +277 -0
  264. aiecs/tools/statistics/__init__.py +80 -0
  265. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
  266. aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
  267. aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
  268. aiecs/tools/statistics/data_loader_tool.py +564 -0
  269. aiecs/tools/statistics/data_profiler_tool.py +658 -0
  270. aiecs/tools/statistics/data_transformer_tool.py +573 -0
  271. aiecs/tools/statistics/data_visualizer_tool.py +495 -0
  272. aiecs/tools/statistics/model_trainer_tool.py +487 -0
  273. aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
  274. aiecs/tools/task_tools/__init__.py +86 -0
  275. aiecs/tools/task_tools/chart_tool.py +732 -0
  276. aiecs/tools/task_tools/classfire_tool.py +922 -0
  277. aiecs/tools/task_tools/image_tool.py +447 -0
  278. aiecs/tools/task_tools/office_tool.py +684 -0
  279. aiecs/tools/task_tools/pandas_tool.py +635 -0
  280. aiecs/tools/task_tools/report_tool.py +635 -0
  281. aiecs/tools/task_tools/research_tool.py +392 -0
  282. aiecs/tools/task_tools/scraper_tool.py +715 -0
  283. aiecs/tools/task_tools/stats_tool.py +688 -0
  284. aiecs/tools/temp_file_manager.py +130 -0
  285. aiecs/tools/tool_executor/__init__.py +37 -0
  286. aiecs/tools/tool_executor/tool_executor.py +881 -0
  287. aiecs/utils/LLM_output_structor.py +445 -0
  288. aiecs/utils/__init__.py +34 -0
  289. aiecs/utils/base_callback.py +47 -0
  290. aiecs/utils/cache_provider.py +695 -0
  291. aiecs/utils/execution_utils.py +184 -0
  292. aiecs/utils/logging.py +1 -0
  293. aiecs/utils/prompt_loader.py +14 -0
  294. aiecs/utils/token_usage_repository.py +323 -0
  295. aiecs/ws/__init__.py +0 -0
  296. aiecs/ws/socket_server.py +52 -0
  297. aiecs-1.5.1.dist-info/METADATA +608 -0
  298. aiecs-1.5.1.dist-info/RECORD +302 -0
  299. aiecs-1.5.1.dist-info/WHEEL +5 -0
  300. aiecs-1.5.1.dist-info/entry_points.txt +10 -0
  301. aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
  302. aiecs-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,413 @@
1
+ """
2
+ Graph Storage Migration Utilities
3
+
4
+ Provides tools to migrate graph data between different storage backends,
5
+ particularly from SQLite to PostgreSQL.
6
+ """
7
+
8
+ import logging
9
+ import asyncio
10
+ from typing import Optional, Dict, Any
11
+ from tqdm import tqdm
12
+
13
+ from aiecs.infrastructure.graph_storage.base import GraphStore
14
+ from aiecs.infrastructure.graph_storage.sqlite import SQLiteGraphStore
15
+ from aiecs.infrastructure.graph_storage.postgres import PostgresGraphStore
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class GraphStorageMigrator:
21
+ """
22
+ Migrates graph data from one storage backend to another
23
+
24
+ Example:
25
+ ```python
26
+ # Migrate from SQLite to PostgreSQL
27
+ source = SQLiteGraphStore("old_graph.db")
28
+ target = PostgresGraphStore(host="localhost", database="new_graph")
29
+
30
+ migrator = GraphStorageMigrator(source, target)
31
+ await migrator.migrate(batch_size=1000, show_progress=True)
32
+ ```
33
+ """
34
+
35
+ def __init__(self, source: GraphStore, target: GraphStore):
36
+ """
37
+ Initialize migrator
38
+
39
+ Args:
40
+ source: Source graph store to migrate from
41
+ target: Target graph store to migrate to
42
+ """
43
+ self.source = source
44
+ self.target = target
45
+
46
+ async def migrate(
47
+ self,
48
+ batch_size: int = 1000,
49
+ show_progress: bool = True,
50
+ verify: bool = True,
51
+ ) -> Dict[str, Any]:
52
+ """
53
+ Migrate all graph data from source to target
54
+
55
+ Args:
56
+ batch_size: Number of entities/relations to migrate per batch
57
+ show_progress: Show progress bar
58
+ verify: Verify migration integrity after completion
59
+
60
+ Returns:
61
+ Migration statistics dictionary
62
+ """
63
+ logger.info(
64
+ f"Starting migration from {type(self.source).__name__} to {type(self.target).__name__}"
65
+ )
66
+
67
+ stats = {
68
+ "entities_migrated": 0,
69
+ "relations_migrated": 0,
70
+ "errors": [],
71
+ "duration_seconds": 0,
72
+ }
73
+
74
+ import time
75
+
76
+ start_time = time.time()
77
+
78
+ try:
79
+ # Initialize both stores
80
+ if not getattr(self.source, "_is_initialized", False):
81
+ await self.source.initialize()
82
+ if not getattr(self.target, "_is_initialized", False):
83
+ await self.target.initialize()
84
+
85
+ # Migrate entities
86
+ logger.info("Migrating entities...")
87
+ stats["entities_migrated"] = await self._migrate_entities(batch_size, show_progress)
88
+
89
+ # Migrate relations
90
+ logger.info("Migrating relations...")
91
+ stats["relations_migrated"] = await self._migrate_relations(batch_size, show_progress)
92
+
93
+ # Verify if requested
94
+ if verify:
95
+ logger.info("Verifying migration...")
96
+ verification = await self._verify_migration()
97
+ stats["verification"] = verification
98
+
99
+ if not verification["success"]:
100
+ logger.warning(f"Migration verification found issues: {verification}")
101
+
102
+ stats["duration_seconds"] = time.time() - start_time
103
+ logger.info(f"Migration completed in {stats['duration_seconds']:.2f}s")
104
+ logger.info(
105
+ f"Migrated {stats['entities_migrated']} entities and {stats['relations_migrated']} relations"
106
+ )
107
+
108
+ except Exception as e:
109
+ logger.error(f"Migration failed: {e}")
110
+ stats["errors"].append(str(e))
111
+ raise
112
+
113
+ return stats
114
+
115
+ async def _migrate_entities(self, batch_size: int, show_progress: bool) -> int:
116
+ """Migrate all entities from source to target"""
117
+ # Get all entities from source
118
+ entities = await self.source.get_all_entities()
119
+ total = len(entities)
120
+
121
+ if total == 0:
122
+ logger.warning("No entities to migrate")
123
+ return 0
124
+
125
+ # Use tqdm for progress if requested
126
+ iterator = (
127
+ tqdm(entities, desc="Entities", disable=not show_progress)
128
+ if show_progress
129
+ else entities
130
+ )
131
+
132
+ migrated = 0
133
+ errors = []
134
+
135
+ # Migrate in batches using transactions
136
+ for i in range(0, total, batch_size):
137
+ batch = entities[i : i + batch_size]
138
+
139
+ try:
140
+ async with self.target.transaction():
141
+ for entity in batch:
142
+ try:
143
+ await self.target.add_entity(entity)
144
+ migrated += 1
145
+ if show_progress:
146
+ iterator.update(1)
147
+ except Exception as e:
148
+ error_msg = f"Failed to migrate entity {entity.id}: {e}"
149
+ logger.error(error_msg)
150
+ errors.append(error_msg)
151
+ except Exception as e:
152
+ logger.error(f"Batch transaction failed: {e}")
153
+ # Continue with next batch
154
+
155
+ if errors:
156
+ logger.warning(f"Entity migration completed with {len(errors)} errors")
157
+
158
+ return migrated
159
+
160
+ async def _migrate_relations(self, batch_size: int, show_progress: bool) -> int:
161
+ """Migrate all relations from source to target"""
162
+ # Get all relations by getting all entities and their neighbors
163
+ # This is a workaround since we don't have a direct get_all_relations
164
+ # method
165
+ all_entities = await self.source.get_all_entities()
166
+ relations = []
167
+
168
+ # Collect all unique relations
169
+ for entity in all_entities:
170
+ # This is an approximation - we'd need a better way to get all relations
171
+ # For now, we'll use a simpler approach
172
+ pass
173
+
174
+ # Alternative: If the store has a direct way to get relations, use it
175
+ # For SQLite and Postgres, we can query the relations table directly
176
+ if hasattr(self.source, "conn") or hasattr(self.source, "pool"):
177
+ relations = await self._get_all_relations_direct(self.source)
178
+ else:
179
+ logger.warning("Cannot directly access relations, migration may be incomplete")
180
+ return 0
181
+
182
+ total = len(relations)
183
+
184
+ if total == 0:
185
+ logger.warning("No relations to migrate")
186
+ return 0
187
+
188
+ iterator = (
189
+ tqdm(relations, desc="Relations", disable=not show_progress)
190
+ if show_progress
191
+ else relations
192
+ )
193
+
194
+ migrated = 0
195
+ errors = []
196
+
197
+ # Migrate in batches
198
+ for i in range(0, total, batch_size):
199
+ batch = relations[i : i + batch_size]
200
+
201
+ try:
202
+ async with self.target.transaction():
203
+ for relation in batch:
204
+ try:
205
+ await self.target.add_relation(relation)
206
+ migrated += 1
207
+ if show_progress:
208
+ iterator.update(1)
209
+ except Exception as e:
210
+ error_msg = f"Failed to migrate relation {relation.id}: {e}"
211
+ logger.error(error_msg)
212
+ errors.append(error_msg)
213
+ except Exception as e:
214
+ logger.error(f"Batch transaction failed: {e}")
215
+
216
+ if errors:
217
+ logger.warning(f"Relation migration completed with {len(errors)} errors")
218
+
219
+ return migrated
220
+
221
+ async def _get_all_relations_direct(self, store: GraphStore) -> list:
222
+ """Get all relations directly from database"""
223
+ from aiecs.domain.knowledge_graph.models.relation import Relation
224
+
225
+ relations = []
226
+
227
+ if isinstance(store, SQLiteGraphStore):
228
+ # SQLite direct query
229
+ cursor = await store.conn.execute(
230
+ "SELECT id, relation_type, source_id, target_id, properties, weight FROM relations"
231
+ )
232
+ rows = await cursor.fetchall()
233
+
234
+ for row in rows:
235
+ import json
236
+
237
+ relations.append(
238
+ Relation(
239
+ id=row[0],
240
+ relation_type=row[1],
241
+ source_id=row[2],
242
+ target_id=row[3],
243
+ properties=json.loads(row[4]) if row[4] else {},
244
+ weight=row[5] if row[5] else 1.0,
245
+ )
246
+ )
247
+
248
+ elif isinstance(store, PostgresGraphStore):
249
+ # PostgreSQL direct query
250
+ async with store.pool.acquire() as conn:
251
+ rows = await conn.fetch(
252
+ """
253
+ SELECT id, relation_type, source_id, target_id, properties, weight
254
+ FROM graph_relations
255
+ """
256
+ )
257
+
258
+ for row in rows:
259
+ relations.append(
260
+ Relation(
261
+ id=row["id"],
262
+ relation_type=row["relation_type"],
263
+ source_id=row["source_id"],
264
+ target_id=row["target_id"],
265
+ properties=(
266
+ row["properties"] if isinstance(row["properties"], dict) else {}
267
+ ),
268
+ weight=(float(row["weight"]) if row["weight"] else 1.0),
269
+ )
270
+ )
271
+
272
+ return relations
273
+
274
+ async def _verify_migration(self) -> Dict[str, Any]:
275
+ """Verify migration integrity"""
276
+ try:
277
+ # Get counts from both stores
278
+ source_stats = await self.source.get_stats()
279
+ target_stats = await self.target.get_stats()
280
+
281
+ entity_match = source_stats["entity_count"] == target_stats["entity_count"]
282
+ relation_match = source_stats["relation_count"] == target_stats["relation_count"]
283
+
284
+ return {
285
+ "success": entity_match and relation_match,
286
+ "source_entities": source_stats["entity_count"],
287
+ "target_entities": target_stats["entity_count"],
288
+ "source_relations": source_stats["relation_count"],
289
+ "target_relations": target_stats["relation_count"],
290
+ "entity_match": entity_match,
291
+ "relation_match": relation_match,
292
+ }
293
+ except Exception as e:
294
+ return {"success": False, "error": str(e)}
295
+
296
+
297
+ async def migrate_sqlite_to_postgres(
298
+ sqlite_path: str,
299
+ postgres_config: Optional[Dict[str, Any]] = None,
300
+ batch_size: int = 1000,
301
+ show_progress: bool = True,
302
+ ) -> Dict[str, Any]:
303
+ """
304
+ Convenience function to migrate from SQLite to PostgreSQL
305
+
306
+ Args:
307
+ sqlite_path: Path to SQLite database file
308
+ postgres_config: PostgreSQL connection config (or None to use defaults)
309
+ batch_size: Batch size for migration
310
+ show_progress: Show progress bars
311
+
312
+ Returns:
313
+ Migration statistics
314
+
315
+ Example:
316
+ ```python
317
+ stats = await migrate_sqlite_to_postgres(
318
+ "knowledge_graph.db",
319
+ postgres_config={
320
+ "host": "localhost",
321
+ "database": "production_kg"
322
+ }
323
+ )
324
+ print(f"Migrated {stats['entities_migrated']} entities")
325
+ ```
326
+ """
327
+ # Create stores
328
+ source = SQLiteGraphStore(sqlite_path)
329
+
330
+ if postgres_config:
331
+ target = PostgresGraphStore(**postgres_config)
332
+ else:
333
+ target = PostgresGraphStore() # Use defaults from config
334
+
335
+ # Migrate
336
+ migrator = GraphStorageMigrator(source, target)
337
+
338
+ try:
339
+ stats = await migrator.migrate(batch_size=batch_size, show_progress=show_progress)
340
+ return stats
341
+ finally:
342
+ await source.close()
343
+ await target.close()
344
+
345
+
346
+ # CLI support
347
+ if __name__ == "__main__":
348
+ import argparse
349
+ import sys
350
+
351
+ parser = argparse.ArgumentParser(description="Migrate graph storage between backends")
352
+ parser.add_argument("--source-sqlite", help="Source SQLite database path")
353
+ parser.add_argument("--target-pg-host", default="localhost", help="Target PostgreSQL host")
354
+ parser.add_argument(
355
+ "--target-pg-port",
356
+ type=int,
357
+ default=5432,
358
+ help="Target PostgreSQL port",
359
+ )
360
+ parser.add_argument(
361
+ "--target-pg-database",
362
+ required=True,
363
+ help="Target PostgreSQL database",
364
+ )
365
+ parser.add_argument("--target-pg-user", default="postgres", help="Target PostgreSQL user")
366
+ parser.add_argument("--target-pg-password", help="Target PostgreSQL password")
367
+ parser.add_argument("--batch-size", type=int, default=1000, help="Batch size")
368
+ parser.add_argument("--no-progress", action="store_true", help="Disable progress bars")
369
+
370
+ args = parser.parse_args()
371
+
372
+ if not args.source_sqlite:
373
+ print("Error: --source-sqlite is required")
374
+ sys.exit(1)
375
+
376
+ async def run():
377
+ stats = await migrate_sqlite_to_postgres(
378
+ sqlite_path=args.source_sqlite,
379
+ postgres_config={
380
+ "host": args.target_pg_host,
381
+ "port": args.target_pg_port,
382
+ "database": args.target_pg_database,
383
+ "user": args.target_pg_user,
384
+ "password": args.target_pg_password,
385
+ },
386
+ batch_size=args.batch_size,
387
+ show_progress=not args.no_progress,
388
+ )
389
+
390
+ print("\n" + "=" * 60)
391
+ print("Migration Summary")
392
+ print("=" * 60)
393
+ print(f"Entities migrated: {stats['entities_migrated']}")
394
+ print(f"Relations migrated: {stats['relations_migrated']}")
395
+ print(f"Duration: {stats['duration_seconds']:.2f}s")
396
+
397
+ if stats.get("verification"):
398
+ ver = stats["verification"]
399
+ if ver["success"]:
400
+ print("✅ Verification: PASSED")
401
+ else:
402
+ print("❌ Verification: FAILED")
403
+ print(
404
+ f" Source entities: {ver['source_entities']}, Target: {ver['target_entities']}"
405
+ )
406
+ print(
407
+ f" Source relations: {ver['source_relations']}, Target: {ver['target_relations']}"
408
+ )
409
+
410
+ if stats["errors"]:
411
+ print(f"\n⚠️ Errors encountered: {len(stats['errors'])}")
412
+
413
+ asyncio.run(run())