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,378 @@
1
+ """
2
+ Custom Query Executor
3
+
4
+ Executes custom queries with pattern matching, projection, and aggregation.
5
+
6
+ Phase: 3.3 - Full Custom Query Execution
7
+ Version: 1.0
8
+ """
9
+
10
+ from typing import List, Dict, Any, Optional
11
+ from aiecs.domain.knowledge_graph.models.query import GraphQuery
12
+ from aiecs.infrastructure.graph_storage.base import GraphStore
13
+ from aiecs.application.knowledge_graph.pattern_matching.pattern_matcher import (
14
+ PatternMatcher,
15
+ PatternMatch,
16
+ )
17
+
18
+
19
+ class CustomQueryExecutor:
20
+ """
21
+ Custom Query Executor
22
+
23
+ Executes custom queries with:
24
+ - Pattern matching
25
+ - Result projection
26
+ - Aggregation
27
+ - Grouping
28
+ """
29
+
30
+ def __init__(self, graph_store: GraphStore):
31
+ """
32
+ Initialize custom query executor
33
+
34
+ Args:
35
+ graph_store: Graph storage backend
36
+ """
37
+ self.graph_store = graph_store
38
+ self.pattern_matcher = PatternMatcher(graph_store)
39
+
40
+ async def execute(
41
+ self, query: GraphQuery, start_entity_id: Optional[str] = None
42
+ ) -> Dict[str, Any]:
43
+ """
44
+ Execute a custom query
45
+
46
+ Args:
47
+ query: Graph query with custom patterns
48
+ start_entity_id: Optional starting entity ID
49
+
50
+ Returns:
51
+ Query results with matches, projections, and aggregations
52
+ """
53
+ # Execute pattern matching
54
+ matches = await self._execute_pattern_matching(query, start_entity_id)
55
+
56
+ # Apply projection if specified
57
+ if query.projection:
58
+ projected_results = self._apply_projection(matches, query.projection)
59
+ else:
60
+ projected_results = [self._match_to_dict(match) for match in matches]
61
+
62
+ # Apply aggregation if specified
63
+ if query.aggregations:
64
+ aggregated_results = self._apply_aggregation(
65
+ projected_results, query.aggregations, query.group_by
66
+ )
67
+ return {
68
+ "matches": len(matches),
69
+ "results": aggregated_results,
70
+ "aggregated": True,
71
+ }
72
+
73
+ return {
74
+ "matches": len(matches),
75
+ "results": projected_results,
76
+ "aggregated": False,
77
+ }
78
+
79
+ async def _execute_pattern_matching(
80
+ self, query: GraphQuery, start_entity_id: Optional[str]
81
+ ) -> List[PatternMatch]:
82
+ """
83
+ Execute pattern matching based on query
84
+
85
+ Args:
86
+ query: Graph query
87
+ start_entity_id: Optional starting entity ID
88
+
89
+ Returns:
90
+ List of pattern matches
91
+ """
92
+ max_matches = query.max_results or 100
93
+
94
+ # Single pattern
95
+ if query.pattern:
96
+ return await self.pattern_matcher.match_pattern(
97
+ query.pattern, start_entity_id, max_matches
98
+ )
99
+
100
+ # Multiple patterns (required)
101
+ if query.patterns:
102
+ if query.optional_patterns:
103
+ # Required + optional patterns
104
+ return await self.pattern_matcher.match_optional_patterns(
105
+ query.patterns,
106
+ query.optional_patterns,
107
+ start_entity_id,
108
+ max_matches,
109
+ )
110
+ else:
111
+ # Only required patterns
112
+ return await self.pattern_matcher.match_multiple_patterns(
113
+ query.patterns, start_entity_id, max_matches
114
+ )
115
+
116
+ # No patterns specified
117
+ return []
118
+
119
+ def _match_to_dict(self, match: PatternMatch) -> Dict[str, Any]:
120
+ """
121
+ Convert pattern match to dictionary
122
+
123
+ Args:
124
+ match: Pattern match
125
+
126
+ Returns:
127
+ Dictionary representation
128
+ """
129
+ return {
130
+ "entities": [
131
+ {
132
+ "id": entity.id,
133
+ "type": entity.entity_type,
134
+ "properties": entity.properties,
135
+ }
136
+ for entity in match.entities
137
+ ],
138
+ "relations": [
139
+ {
140
+ "id": relation.id,
141
+ "type": relation.relation_type,
142
+ "source": relation.source_id,
143
+ "target": relation.target_id,
144
+ "properties": relation.properties,
145
+ }
146
+ for relation in match.relations
147
+ ],
148
+ "score": match.score,
149
+ "bindings": match.bindings,
150
+ }
151
+
152
+ def _apply_projection(
153
+ self, matches: List[PatternMatch], projection: List[str]
154
+ ) -> List[Dict[str, Any]]:
155
+ """
156
+ Apply projection to matches
157
+
158
+ Args:
159
+ matches: Pattern matches
160
+ projection: Fields to project
161
+
162
+ Returns:
163
+ Projected results
164
+ """
165
+ projected = []
166
+
167
+ for match in matches:
168
+ result = {}
169
+
170
+ for field in projection:
171
+ value = self._extract_field(match, field)
172
+ result[field] = value
173
+
174
+ projected.append(result)
175
+
176
+ return projected
177
+
178
+ def _extract_field(self, match: PatternMatch, field: str) -> Any:
179
+ """
180
+ Extract a field value from a match
181
+
182
+ Supports dot notation for nested fields:
183
+ - "id" -> first entity's ID
184
+ - "entities[0].name" -> first entity's name
185
+ - "entities[0].properties.age" -> first entity's age property
186
+
187
+ Args:
188
+ match: Pattern match
189
+ field: Field path to extract
190
+
191
+ Returns:
192
+ Field value
193
+ """
194
+ # Handle simple fields
195
+ if field == "score":
196
+ return match.score
197
+
198
+ if field == "entity_count":
199
+ return len(match.entities)
200
+
201
+ if field == "relation_count":
202
+ return len(match.relations)
203
+
204
+ # Handle entity fields
205
+ if field.startswith("entities"):
206
+ # Parse entities[0].name or entities[0].properties.age
207
+ parts = field.split(".")
208
+
209
+ # Extract index
210
+ if "[" in parts[0]:
211
+ index_str = parts[0].split("[")[1].split("]")[0]
212
+ index = int(index_str)
213
+
214
+ if index >= len(match.entities):
215
+ return None
216
+
217
+ entity = match.entities[index]
218
+
219
+ # Extract nested field
220
+ if len(parts) == 1:
221
+ return {
222
+ "id": entity.id,
223
+ "type": entity.entity_type,
224
+ "properties": entity.properties,
225
+ }
226
+
227
+ if parts[1] == "id":
228
+ return entity.id
229
+ elif parts[1] == "type":
230
+ return entity.entity_type
231
+ elif parts[1] == "properties" and len(parts) > 2:
232
+ return entity.properties.get(parts[2])
233
+ elif parts[1] == "properties":
234
+ return entity.properties
235
+
236
+ # Handle relation fields
237
+ if field.startswith("relations"):
238
+ parts = field.split(".")
239
+
240
+ if "[" in parts[0]:
241
+ index_str = parts[0].split("[")[1].split("]")[0]
242
+ index = int(index_str)
243
+
244
+ if index >= len(match.relations):
245
+ return None
246
+
247
+ relation = match.relations[index]
248
+
249
+ if len(parts) == 1:
250
+ return {
251
+ "id": relation.id,
252
+ "type": relation.relation_type,
253
+ "source": relation.source_id,
254
+ "target": relation.target_id,
255
+ }
256
+
257
+ if parts[1] == "id":
258
+ return relation.id
259
+ elif parts[1] == "type":
260
+ return relation.relation_type
261
+ elif parts[1] == "source":
262
+ return relation.source_id
263
+ elif parts[1] == "target":
264
+ return relation.target_id
265
+ elif parts[1] == "properties" and len(parts) > 2:
266
+ return relation.properties.get(parts[2])
267
+
268
+ # Handle bindings
269
+ if field.startswith("bindings."):
270
+ binding_name = field.split(".")[1]
271
+ return match.bindings.get(binding_name)
272
+
273
+ return None
274
+
275
+ def _apply_aggregation(
276
+ self,
277
+ results: List[Dict[str, Any]],
278
+ aggregations: Dict[str, str],
279
+ group_by: Optional[List[str]] = None,
280
+ ) -> List[Dict[str, Any]]:
281
+ """
282
+ Apply aggregations to results
283
+
284
+ Args:
285
+ results: Projected results
286
+ aggregations: Aggregation functions (e.g., {"count": "COUNT", "avg_age": "AVG(age)"})
287
+ group_by: Optional fields to group by
288
+
289
+ Returns:
290
+ Aggregated results
291
+ """
292
+ if group_by:
293
+ # Group results
294
+ groups = {}
295
+
296
+ for result in results:
297
+ # Create group key
298
+ key_parts = []
299
+ for field in group_by:
300
+ key_parts.append(str(result.get(field, "")))
301
+ key = tuple(key_parts)
302
+
303
+ if key not in groups:
304
+ groups[key] = []
305
+ groups[key].append(result)
306
+
307
+ # Aggregate each group
308
+ aggregated = []
309
+
310
+ for key, group_results in groups.items():
311
+ agg_result = {}
312
+
313
+ # Add group by fields
314
+ for i, field in enumerate(group_by):
315
+ agg_result[field] = key[i]
316
+
317
+ # Apply aggregations
318
+ for agg_name, agg_func in aggregations.items():
319
+ agg_result[agg_name] = self._compute_aggregation(group_results, agg_func)
320
+
321
+ aggregated.append(agg_result)
322
+
323
+ return aggregated
324
+ else:
325
+ # Aggregate all results
326
+ agg_result = {}
327
+
328
+ for agg_name, agg_func in aggregations.items():
329
+ agg_result[agg_name] = self._compute_aggregation(results, agg_func)
330
+
331
+ return [agg_result]
332
+
333
+ def _compute_aggregation(self, results: List[Dict[str, Any]], agg_func: str) -> Any:
334
+ """
335
+ Compute an aggregation function
336
+
337
+ Supports:
338
+ - COUNT: Count of results
339
+ - SUM(field): Sum of field values
340
+ - AVG(field): Average of field values
341
+ - MIN(field): Minimum field value
342
+ - MAX(field): Maximum field value
343
+
344
+ Args:
345
+ results: Results to aggregate
346
+ agg_func: Aggregation function string
347
+
348
+ Returns:
349
+ Aggregated value
350
+ """
351
+ if agg_func == "COUNT":
352
+ return len(results)
353
+
354
+ # Parse function and field
355
+ if "(" in agg_func:
356
+ func_name = agg_func.split("(")[0]
357
+ field = agg_func.split("(")[1].split(")")[0]
358
+
359
+ # Extract field values
360
+ values = []
361
+ for result in results:
362
+ value = result.get(field)
363
+ if value is not None and isinstance(value, (int, float)):
364
+ values.append(value)
365
+
366
+ if not values:
367
+ return None
368
+
369
+ if func_name == "SUM":
370
+ return sum(values)
371
+ elif func_name == "AVG":
372
+ return sum(values) / len(values)
373
+ elif func_name == "MIN":
374
+ return min(values)
375
+ elif func_name == "MAX":
376
+ return max(values)
377
+
378
+ return None
@@ -0,0 +1,12 @@
1
+ """
2
+ Knowledge Graph Profiling
3
+
4
+ Performance profiling and analysis tools for knowledge graph operations.
5
+ """
6
+
7
+ from aiecs.application.knowledge_graph.profiling.query_profiler import (
8
+ QueryProfiler,
9
+ QueryProfile,
10
+ )
11
+
12
+ __all__ = ["QueryProfiler", "QueryProfile"]
@@ -0,0 +1,199 @@
1
+ """
2
+ Query Plan Visualizer
3
+
4
+ Visualize query execution plans and performance profiles.
5
+ """
6
+
7
+ from typing import Dict, Any, List
8
+ from aiecs.application.knowledge_graph.profiling.query_profiler import (
9
+ QueryProfile,
10
+ )
11
+ from aiecs.domain.knowledge_graph.models.query_plan import QueryPlan
12
+
13
+
14
+ class QueryPlanVisualizer:
15
+ """
16
+ Visualize query plans and execution profiles
17
+
18
+ Generates text-based visualizations of query plans and performance data.
19
+
20
+ Example:
21
+ ```python
22
+ visualizer = QueryPlanVisualizer()
23
+
24
+ # Visualize query plan
25
+ plan_viz = visualizer.visualize_plan(query_plan)
26
+ print(plan_viz)
27
+
28
+ # Visualize execution profile
29
+ profile_viz = visualizer.visualize_profile(query_profile)
30
+ print(profile_viz)
31
+ ```
32
+ """
33
+
34
+ def visualize_plan(self, plan: QueryPlan, show_costs: bool = True) -> str:
35
+ """
36
+ Visualize a query plan
37
+
38
+ Args:
39
+ plan: Query plan to visualize
40
+ show_costs: Whether to show cost estimates
41
+
42
+ Returns:
43
+ Text visualization of the plan
44
+ """
45
+ lines = []
46
+ lines.append("=" * 60)
47
+ lines.append("QUERY PLAN")
48
+ lines.append("=" * 60)
49
+
50
+ if show_costs:
51
+ total_cost = plan.calculate_total_cost()
52
+ lines.append(f"Total Estimated Cost: {total_cost:.2f}")
53
+ lines.append("")
54
+
55
+ for i, step in enumerate(plan.steps, 1):
56
+ lines.append(f"Step {i}: {step.operation.value}")
57
+ lines.append(f" Description: {step.description}")
58
+
59
+ if show_costs:
60
+ lines.append(f" Estimated Cost: {step.estimated_cost:.2f}")
61
+
62
+ if step.depends_on:
63
+ lines.append(f" Depends On: {', '.join(step.depends_on)}")
64
+
65
+ if step.metadata:
66
+ lines.append(f" Metadata: {step.metadata}")
67
+
68
+ lines.append("")
69
+
70
+ lines.append("=" * 60)
71
+ return "\n".join(lines)
72
+
73
+ def visualize_profile(self, profile: QueryProfile, show_steps: bool = True) -> str:
74
+ """
75
+ Visualize a query execution profile
76
+
77
+ Args:
78
+ profile: Query profile to visualize
79
+ show_steps: Whether to show individual steps
80
+
81
+ Returns:
82
+ Text visualization of the profile
83
+ """
84
+ lines = []
85
+ lines.append("=" * 60)
86
+ lines.append("QUERY EXECUTION PROFILE")
87
+ lines.append("=" * 60)
88
+ lines.append(f"Query ID: {profile.query_id}")
89
+ lines.append(f"Query Type: {profile.query_type}")
90
+ lines.append(f"Total Duration: {profile.duration_ms:.2f}ms")
91
+ lines.append("")
92
+
93
+ if show_steps and profile.steps:
94
+ lines.append("Execution Steps:")
95
+ lines.append("-" * 60)
96
+
97
+ for i, step in enumerate(profile.steps, 1):
98
+ duration = step["duration_ms"]
99
+ percentage = (duration / profile.duration_ms * 100) if profile.duration_ms else 0
100
+
101
+ lines.append(f"{i}. {step['name']}")
102
+ lines.append(f" Duration: {duration:.2f}ms ({percentage:.1f}%)")
103
+
104
+ # Show bar chart
105
+ bar_length = int(percentage / 2) # Scale to 50 chars max
106
+ bar = "█" * bar_length
107
+ lines.append(f" [{bar:<50}]")
108
+
109
+ if step.get("metadata"):
110
+ lines.append(f" Metadata: {step['metadata']}")
111
+
112
+ lines.append("")
113
+
114
+ if profile.metadata:
115
+ lines.append("Query Metadata:")
116
+ for key, value in profile.metadata.items():
117
+ lines.append(f" {key}: {value}")
118
+ lines.append("")
119
+
120
+ lines.append("=" * 60)
121
+ return "\n".join(lines)
122
+
123
+ def visualize_comparison(self, profiles: List[QueryProfile]) -> str:
124
+ """
125
+ Visualize comparison of multiple query profiles
126
+
127
+ Args:
128
+ profiles: List of profiles to compare
129
+
130
+ Returns:
131
+ Text visualization comparing profiles
132
+ """
133
+ if not profiles:
134
+ return "No profiles to compare"
135
+
136
+ lines = []
137
+ lines.append("=" * 60)
138
+ lines.append("QUERY PROFILE COMPARISON")
139
+ lines.append("=" * 60)
140
+
141
+ # Summary table
142
+ lines.append(f"{'Query ID':<20} {'Type':<15} {'Duration (ms)':<15}")
143
+ lines.append("-" * 60)
144
+
145
+ for profile in profiles:
146
+ duration = f"{profile.duration_ms:.2f}" if profile.duration_ms else "N/A"
147
+ lines.append(f"{profile.query_id:<20} {profile.query_type:<15} {duration:<15}")
148
+
149
+ lines.append("")
150
+
151
+ # Statistics
152
+ durations = [p.duration_ms for p in profiles if p.duration_ms]
153
+ if durations:
154
+ lines.append("Statistics:")
155
+ lines.append(f" Average: {sum(durations) / len(durations):.2f}ms")
156
+ lines.append(f" Min: {min(durations):.2f}ms")
157
+ lines.append(f" Max: {max(durations):.2f}ms")
158
+
159
+ lines.append("=" * 60)
160
+ return "\n".join(lines)
161
+
162
+ def export_to_json(self, profile: QueryProfile) -> Dict[str, Any]:
163
+ """
164
+ Export profile to JSON format
165
+
166
+ Args:
167
+ profile: Query profile to export
168
+
169
+ Returns:
170
+ Dictionary representation suitable for JSON export
171
+ """
172
+ return profile.to_dict()
173
+
174
+ def generate_flamegraph_data(self, profile: QueryProfile) -> List[Dict[str, Any]]:
175
+ """
176
+ Generate data for flamegraph visualization
177
+
178
+ Args:
179
+ profile: Query profile
180
+
181
+ Returns:
182
+ List of flamegraph data points
183
+ """
184
+ data = []
185
+
186
+ for step in profile.steps:
187
+ data.append(
188
+ {
189
+ "name": step["name"],
190
+ "value": step["duration_ms"],
191
+ "percentage": (
192
+ (step["duration_ms"] / profile.duration_ms * 100)
193
+ if profile.duration_ms
194
+ else 0
195
+ ),
196
+ }
197
+ )
198
+
199
+ return data