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,223 @@
1
+ """
2
+ Query Profiler for Knowledge Graph
3
+
4
+ Provides detailed profiling and timing metrics for graph queries.
5
+ """
6
+
7
+ import time
8
+ import logging
9
+ from typing import Dict, Any, List, Optional
10
+ from dataclasses import dataclass, field
11
+ from contextlib import asynccontextmanager
12
+ from datetime import datetime
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ @dataclass
18
+ class QueryProfile:
19
+ """
20
+ Profile data for a single query execution
21
+
22
+ Attributes:
23
+ query_id: Unique identifier for the query
24
+ query_type: Type of query (search, traverse, etc.)
25
+ start_time: When the query started
26
+ end_time: When the query completed
27
+ duration_ms: Total duration in milliseconds
28
+ steps: List of execution steps with timing
29
+ metadata: Additional query metadata
30
+ """
31
+
32
+ query_id: str
33
+ query_type: str
34
+ start_time: datetime
35
+ end_time: Optional[datetime] = None
36
+ duration_ms: Optional[float] = None
37
+ steps: List[Dict[str, Any]] = field(default_factory=list)
38
+ metadata: Dict[str, Any] = field(default_factory=dict)
39
+
40
+ def complete(self) -> None:
41
+ """Mark query as complete and calculate duration"""
42
+ self.end_time = datetime.utcnow()
43
+ if self.start_time:
44
+ delta = self.end_time - self.start_time
45
+ self.duration_ms = delta.total_seconds() * 1000
46
+
47
+ def add_step(
48
+ self,
49
+ name: str,
50
+ duration_ms: float,
51
+ metadata: Optional[Dict[str, Any]] = None,
52
+ ) -> None:
53
+ """Add an execution step"""
54
+ self.steps.append(
55
+ {
56
+ "name": name,
57
+ "duration_ms": duration_ms,
58
+ "metadata": metadata or {},
59
+ }
60
+ )
61
+
62
+ def to_dict(self) -> Dict[str, Any]:
63
+ """Convert to dictionary"""
64
+ return {
65
+ "query_id": self.query_id,
66
+ "query_type": self.query_type,
67
+ "start_time": self.start_time.isoformat(),
68
+ "end_time": self.end_time.isoformat() if self.end_time else None,
69
+ "duration_ms": self.duration_ms,
70
+ "steps": self.steps,
71
+ "metadata": self.metadata,
72
+ }
73
+
74
+
75
+ class QueryProfiler:
76
+ """
77
+ Query profiler for detailed performance analysis
78
+
79
+ Tracks query execution with step-by-step timing and metadata.
80
+
81
+ Example:
82
+ ```python
83
+ profiler = QueryProfiler()
84
+
85
+ # Profile a query
86
+ async with profiler.profile("search_query", "vector_search") as profile:
87
+ # Step 1
88
+ async with profiler.step(profile, "embedding_lookup"):
89
+ embedding = await get_embedding(query)
90
+
91
+ # Step 2
92
+ async with profiler.step(profile, "vector_search"):
93
+ results = await search(embedding)
94
+
95
+ # Get profile
96
+ profile_data = profiler.get_profile("search_query")
97
+ print(f"Total: {profile_data.duration_ms}ms")
98
+ for step in profile_data.steps:
99
+ print(f" {step['name']}: {step['duration_ms']}ms")
100
+ ```
101
+ """
102
+
103
+ def __init__(self, max_profiles: int = 1000):
104
+ """
105
+ Initialize query profiler
106
+
107
+ Args:
108
+ max_profiles: Maximum number of profiles to keep in memory
109
+ """
110
+ self.max_profiles = max_profiles
111
+ self.profiles: Dict[str, QueryProfile] = {}
112
+ self._profile_order: List[str] = []
113
+
114
+ @asynccontextmanager
115
+ async def profile(
116
+ self,
117
+ query_id: str,
118
+ query_type: str,
119
+ metadata: Optional[Dict[str, Any]] = None,
120
+ ):
121
+ """
122
+ Context manager for profiling a query
123
+
124
+ Args:
125
+ query_id: Unique identifier for the query
126
+ query_type: Type of query
127
+ metadata: Additional metadata
128
+
129
+ Yields:
130
+ QueryProfile object
131
+ """
132
+ # Create profile
133
+ profile = QueryProfile(
134
+ query_id=query_id,
135
+ query_type=query_type,
136
+ start_time=datetime.utcnow(),
137
+ metadata=metadata or {},
138
+ )
139
+
140
+ try:
141
+ yield profile
142
+ finally:
143
+ # Complete profile
144
+ profile.complete()
145
+
146
+ # Store profile
147
+ self._store_profile(profile)
148
+
149
+ @asynccontextmanager
150
+ async def step(
151
+ self,
152
+ profile: QueryProfile,
153
+ step_name: str,
154
+ metadata: Optional[Dict[str, Any]] = None,
155
+ ):
156
+ """
157
+ Context manager for profiling a query step
158
+
159
+ Args:
160
+ profile: Parent query profile
161
+ step_name: Name of the step
162
+ metadata: Additional metadata
163
+ """
164
+ start_time = time.perf_counter()
165
+
166
+ try:
167
+ yield
168
+ finally:
169
+ end_time = time.perf_counter()
170
+ duration_ms = (end_time - start_time) * 1000
171
+ profile.add_step(step_name, duration_ms, metadata)
172
+
173
+ def _store_profile(self, profile: QueryProfile) -> None:
174
+ """Store profile with LRU eviction"""
175
+ # Add to storage
176
+ self.profiles[profile.query_id] = profile
177
+ self._profile_order.append(profile.query_id)
178
+
179
+ # Evict oldest if over limit
180
+ while len(self._profile_order) > self.max_profiles:
181
+ oldest_id = self._profile_order.pop(0)
182
+ if oldest_id in self.profiles:
183
+ del self.profiles[oldest_id]
184
+
185
+ def get_profile(self, query_id: str) -> Optional[QueryProfile]:
186
+ """Get profile by query ID"""
187
+ return self.profiles.get(query_id)
188
+
189
+ def get_all_profiles(self) -> List[QueryProfile]:
190
+ """Get all stored profiles"""
191
+ return list(self.profiles.values())
192
+
193
+ def get_stats(self) -> Dict[str, Any]:
194
+ """Get profiling statistics"""
195
+ if not self.profiles:
196
+ return {
197
+ "total_queries": 0,
198
+ "avg_duration_ms": 0,
199
+ "min_duration_ms": 0,
200
+ "max_duration_ms": 0,
201
+ }
202
+
203
+ durations = [p.duration_ms for p in self.profiles.values() if p.duration_ms]
204
+
205
+ return {
206
+ "total_queries": len(self.profiles),
207
+ "avg_duration_ms": (sum(durations) / len(durations) if durations else 0),
208
+ "min_duration_ms": min(durations) if durations else 0,
209
+ "max_duration_ms": max(durations) if durations else 0,
210
+ "query_types": self._get_query_type_stats(),
211
+ }
212
+
213
+ def _get_query_type_stats(self) -> Dict[str, int]:
214
+ """Get statistics by query type"""
215
+ stats: Dict[str, int] = {}
216
+ for profile in self.profiles.values():
217
+ stats[profile.query_type] = stats.get(profile.query_type, 0) + 1
218
+ return stats
219
+
220
+ def clear(self) -> None:
221
+ """Clear all profiles"""
222
+ self.profiles.clear()
223
+ self._profile_order.clear()
@@ -0,0 +1,27 @@
1
+ """
2
+ Knowledge Graph Reasoning Module
3
+
4
+ Provides query planning, multi-hop reasoning, and inference capabilities.
5
+ """
6
+
7
+ from aiecs.application.knowledge_graph.reasoning.query_planner import (
8
+ QueryPlanner,
9
+ )
10
+ from aiecs.application.knowledge_graph.reasoning.reasoning_engine import (
11
+ ReasoningEngine,
12
+ )
13
+ from aiecs.application.knowledge_graph.reasoning.inference_engine import (
14
+ InferenceEngine,
15
+ InferenceCache,
16
+ )
17
+ from aiecs.application.knowledge_graph.reasoning.evidence_synthesis import (
18
+ EvidenceSynthesizer,
19
+ )
20
+
21
+ __all__ = [
22
+ "QueryPlanner",
23
+ "ReasoningEngine",
24
+ "InferenceEngine",
25
+ "InferenceCache",
26
+ "EvidenceSynthesizer",
27
+ ]
@@ -0,0 +1,347 @@
1
+ """
2
+ Evidence Synthesis
3
+
4
+ Combine and synthesize evidence from multiple sources for robust reasoning.
5
+ """
6
+
7
+ import uuid
8
+ from typing import List, Optional, Dict, Any
9
+ from collections import defaultdict
10
+ from aiecs.domain.knowledge_graph.models.evidence import Evidence
11
+
12
+
13
+ class EvidenceSynthesizer:
14
+ """
15
+ Evidence Synthesizer
16
+
17
+ Combines evidence from multiple sources to create more robust conclusions.
18
+
19
+ Features:
20
+ - Merge overlapping evidence
21
+ - Calculate combined confidence
22
+ - Detect contradictions
23
+ - Synthesize explanations
24
+
25
+ Example:
26
+ ```python
27
+ synthesizer = EvidenceSynthesizer()
28
+
29
+ # Combine evidence from different sources
30
+ combined = synthesizer.synthesize_evidence([ev1, ev2, ev3])
31
+
32
+ # Get most reliable evidence
33
+ reliable = synthesizer.filter_by_confidence(combined, threshold=0.7)
34
+ ```
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ confidence_threshold: float = 0.5,
40
+ contradiction_threshold: float = 0.3,
41
+ ):
42
+ """
43
+ Initialize evidence synthesizer
44
+
45
+ Args:
46
+ confidence_threshold: Minimum confidence for evidence
47
+ contradiction_threshold: Threshold for detecting contradictions
48
+ """
49
+ self.confidence_threshold = confidence_threshold
50
+ self.contradiction_threshold = contradiction_threshold
51
+
52
+ def synthesize_evidence(
53
+ self, evidence_list: List[Evidence], method: str = "weighted_average"
54
+ ) -> List[Evidence]:
55
+ """
56
+ Synthesize evidence from multiple sources
57
+
58
+ Args:
59
+ evidence_list: List of evidence to synthesize
60
+ method: Synthesis method ("weighted_average", "max", "voting")
61
+
62
+ Returns:
63
+ Synthesized evidence list
64
+ """
65
+ if not evidence_list:
66
+ return []
67
+
68
+ # Group evidence by entity overlap
69
+ groups = self._group_overlapping_evidence(evidence_list)
70
+
71
+ # Synthesize each group
72
+ synthesized = []
73
+ for group in groups:
74
+ if len(group) == 1:
75
+ synthesized.append(group[0])
76
+ else:
77
+ combined = self._combine_evidence_group(group, method)
78
+ synthesized.append(combined)
79
+
80
+ return synthesized
81
+
82
+ def _group_overlapping_evidence(self, evidence_list: List[Evidence]) -> List[List[Evidence]]:
83
+ """
84
+ Group evidence that refers to overlapping entities
85
+
86
+ Args:
87
+ evidence_list: List of evidence to group
88
+
89
+ Returns:
90
+ List of evidence groups
91
+ """
92
+ groups = []
93
+ used = set()
94
+
95
+ for i, ev1 in enumerate(evidence_list):
96
+ if i in used:
97
+ continue
98
+
99
+ group = [ev1]
100
+ ev1_entities = set(ev1.get_entity_ids())
101
+ used.add(i)
102
+
103
+ # Find overlapping evidence
104
+ for j, ev2 in enumerate(evidence_list):
105
+ if j <= i or j in used:
106
+ continue
107
+
108
+ ev2_entities = set(ev2.get_entity_ids())
109
+ overlap = ev1_entities & ev2_entities
110
+
111
+ # If significant overlap, add to group
112
+ if len(overlap) > 0:
113
+ group.append(ev2)
114
+ used.add(j)
115
+
116
+ groups.append(group)
117
+
118
+ return groups
119
+
120
+ def _combine_evidence_group(self, group: List[Evidence], method: str) -> Evidence:
121
+ """
122
+ Combine a group of overlapping evidence
123
+
124
+ Args:
125
+ group: Group of evidence to combine
126
+ method: Combination method
127
+
128
+ Returns:
129
+ Combined evidence
130
+ """
131
+ if not group:
132
+ raise ValueError("Cannot combine empty evidence group")
133
+
134
+ if len(group) == 1:
135
+ return group[0]
136
+
137
+ # Collect all entities and relations
138
+ all_entities = []
139
+ all_relations = []
140
+ all_paths = []
141
+ seen_entity_ids = set()
142
+ seen_relation_ids = set()
143
+
144
+ for ev in group:
145
+ for entity in ev.entities:
146
+ if entity.id not in seen_entity_ids:
147
+ all_entities.append(entity)
148
+ seen_entity_ids.add(entity.id)
149
+
150
+ for relation in ev.relations:
151
+ if relation.id not in seen_relation_ids:
152
+ all_relations.append(relation)
153
+ seen_relation_ids.add(relation.id)
154
+
155
+ all_paths.extend(ev.paths)
156
+
157
+ # Calculate combined confidence and relevance
158
+ if method == "weighted_average":
159
+ # Weight by number of supporting evidence
160
+ total_confidence = sum(ev.confidence for ev in group)
161
+ total_relevance = sum(ev.relevance_score for ev in group)
162
+ confidence = total_confidence / len(group)
163
+ relevance = total_relevance / len(group)
164
+
165
+ elif method == "max":
166
+ # Take maximum
167
+ confidence = max(ev.confidence for ev in group)
168
+ relevance = max(ev.relevance_score for ev in group)
169
+
170
+ elif method == "voting":
171
+ # Majority voting with confidence weights
172
+ confidence = sum(ev.confidence for ev in group) / len(group)
173
+ relevance = sum(ev.relevance_score for ev in group) / len(group)
174
+
175
+ else:
176
+ # Default to weighted average
177
+ confidence = sum(ev.confidence for ev in group) / len(group)
178
+ relevance = sum(ev.relevance_score for ev in group) / len(group)
179
+
180
+ # Boost confidence if multiple sources agree
181
+ agreement_boost = min(0.1 * (len(group) - 1), 0.3)
182
+ confidence = min(1.0, confidence + agreement_boost)
183
+
184
+ # Create combined explanation
185
+ sources = list(set(ev.source for ev in group if ev.source))
186
+ explanation = f"Combined from {len(group)} sources: {', '.join(sources[:3])}"
187
+ if len(group) > 1:
188
+ explanation += (
189
+ f"\nAgreement across {len(group)} pieces of evidence increases confidence"
190
+ )
191
+
192
+ # Create synthesized evidence
193
+ combined = Evidence(
194
+ evidence_id=f"synth_{uuid.uuid4().hex[:8]}",
195
+ evidence_type=group[0].evidence_type,
196
+ entities=all_entities,
197
+ relations=all_relations,
198
+ paths=all_paths,
199
+ confidence=confidence,
200
+ relevance_score=relevance,
201
+ explanation=explanation,
202
+ source="synthesis",
203
+ metadata={
204
+ "source_count": len(group),
205
+ "source_evidence_ids": [ev.evidence_id for ev in group],
206
+ "synthesis_method": method,
207
+ },
208
+ )
209
+
210
+ return combined
211
+
212
+ def filter_by_confidence(
213
+ self, evidence_list: List[Evidence], threshold: Optional[float] = None
214
+ ) -> List[Evidence]:
215
+ """
216
+ Filter evidence by confidence threshold
217
+
218
+ Args:
219
+ evidence_list: List of evidence to filter
220
+ threshold: Confidence threshold (uses default if None)
221
+
222
+ Returns:
223
+ Filtered evidence list
224
+ """
225
+ threshold = threshold if threshold is not None else self.confidence_threshold
226
+ return [ev for ev in evidence_list if ev.confidence >= threshold]
227
+
228
+ def detect_contradictions(self, evidence_list: List[Evidence]) -> List[Dict[str, Any]]:
229
+ """
230
+ Detect contradictions in evidence
231
+
232
+ Args:
233
+ evidence_list: List of evidence to check
234
+
235
+ Returns:
236
+ List of detected contradictions
237
+ """
238
+ contradictions = []
239
+
240
+ # Group by entity
241
+ entity_evidence: Dict[str, List[Evidence]] = defaultdict(list)
242
+ for ev in evidence_list:
243
+ for entity in ev.entities:
244
+ entity_evidence[entity.id].append(ev)
245
+
246
+ # Check for contradictory claims
247
+ for entity_id, evidence_group in entity_evidence.items():
248
+ if len(evidence_group) < 2:
249
+ continue
250
+
251
+ # Look for low confidence with high relevance (potential
252
+ # contradiction)
253
+ confidences = [ev.confidence for ev in evidence_group]
254
+ if max(confidences) - min(confidences) > self.contradiction_threshold:
255
+ contradictions.append(
256
+ {
257
+ "entity_id": entity_id,
258
+ "evidence_ids": [ev.evidence_id for ev in evidence_group],
259
+ "confidence_range": (
260
+ min(confidences),
261
+ max(confidences),
262
+ ),
263
+ "description": f"Conflicting confidence scores for entity {entity_id}",
264
+ }
265
+ )
266
+
267
+ return contradictions
268
+
269
+ def estimate_overall_confidence(self, evidence_list: List[Evidence]) -> float:
270
+ """
271
+ Estimate overall confidence from evidence list
272
+
273
+ Considers:
274
+ - Individual confidence scores
275
+ - Agreement across evidence
276
+ - Source diversity
277
+
278
+ Args:
279
+ evidence_list: List of evidence
280
+
281
+ Returns:
282
+ Overall confidence score (0-1)
283
+ """
284
+ if not evidence_list:
285
+ return 0.0
286
+
287
+ # Base confidence (average)
288
+ base_confidence = sum(ev.confidence for ev in evidence_list) / len(evidence_list)
289
+
290
+ # Source diversity bonus
291
+ sources = set(ev.source for ev in evidence_list if ev.source)
292
+ diversity_bonus = min(0.1 * (len(sources) - 1), 0.2)
293
+
294
+ # Agreement bonus (entities appearing in multiple evidence)
295
+ entity_counts: Dict[str, int] = defaultdict(int)
296
+ for ev in evidence_list:
297
+ for entity_id in ev.get_entity_ids():
298
+ entity_counts[entity_id] += 1
299
+
300
+ # Average entity appearance count
301
+ if entity_counts:
302
+ avg_appearances = sum(entity_counts.values()) / len(entity_counts)
303
+ agreement_bonus = min(0.1 * (avg_appearances - 1), 0.15)
304
+ else:
305
+ agreement_bonus = 0.0
306
+
307
+ # Combined confidence
308
+ overall = base_confidence + diversity_bonus + agreement_bonus
309
+ return min(1.0, overall)
310
+
311
+ def rank_by_reliability(self, evidence_list: List[Evidence]) -> List[Evidence]:
312
+ """
313
+ Rank evidence by reliability
314
+
315
+ Considers:
316
+ - Confidence score
317
+ - Relevance score
318
+ - Source credibility
319
+
320
+ Args:
321
+ evidence_list: List of evidence to rank
322
+
323
+ Returns:
324
+ Ranked evidence list (most reliable first)
325
+ """
326
+ # Calculate reliability score for each evidence
327
+ scored = []
328
+ for ev in evidence_list:
329
+ # Base score from confidence and relevance
330
+ reliability = (ev.confidence * 0.6) + (ev.relevance_score * 0.4)
331
+
332
+ # Boost for synthesis (already vetted)
333
+ if ev.source == "synthesis":
334
+ reliability *= 1.1
335
+
336
+ # Boost for multiple supporting elements
337
+ element_count = len(ev.entities) + len(ev.relations) + len(ev.paths)
338
+ if element_count > 3:
339
+ reliability *= 1.05
340
+
341
+ reliability = min(1.0, reliability)
342
+ scored.append((ev, reliability))
343
+
344
+ # Sort by reliability (descending)
345
+ scored.sort(key=lambda x: x[1], reverse=True)
346
+
347
+ return [ev for ev, score in scored]