aiecs 1.0.1__py3-none-any.whl → 1.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (340) hide show
  1. aiecs/__init__.py +13 -16
  2. aiecs/__main__.py +7 -7
  3. aiecs/aiecs_client.py +269 -75
  4. aiecs/application/executors/operation_executor.py +79 -54
  5. aiecs/application/knowledge_graph/__init__.py +7 -0
  6. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  7. aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
  8. aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
  11. aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
  12. aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
  13. aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
  14. aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
  15. aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
  16. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  17. aiecs/application/knowledge_graph/extractors/base.py +98 -0
  18. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
  19. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
  20. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
  21. aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
  22. aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
  23. aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
  24. aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
  25. aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
  26. aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
  27. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
  28. aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
  29. aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
  30. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
  31. aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
  32. aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
  33. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
  34. aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
  35. aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
  36. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  37. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
  38. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
  39. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  40. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
  41. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  42. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  43. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
  44. aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
  45. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
  46. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  47. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  48. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
  49. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
  50. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
  51. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
  52. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
  53. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
  54. aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
  55. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
  56. aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
  57. aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
  58. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
  59. aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
  60. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  61. aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
  62. aiecs/application/knowledge_graph/search/reranker.py +293 -0
  63. aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
  64. aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
  65. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  66. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
  67. aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
  68. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  69. aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
  70. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  71. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
  72. aiecs/common/__init__.py +9 -0
  73. aiecs/common/knowledge_graph/__init__.py +17 -0
  74. aiecs/common/knowledge_graph/runnable.py +471 -0
  75. aiecs/config/__init__.py +20 -5
  76. aiecs/config/config.py +762 -31
  77. aiecs/config/graph_config.py +131 -0
  78. aiecs/config/tool_config.py +399 -0
  79. aiecs/core/__init__.py +29 -13
  80. aiecs/core/interface/__init__.py +2 -2
  81. aiecs/core/interface/execution_interface.py +22 -22
  82. aiecs/core/interface/storage_interface.py +37 -88
  83. aiecs/core/registry/__init__.py +31 -0
  84. aiecs/core/registry/service_registry.py +92 -0
  85. aiecs/domain/__init__.py +270 -1
  86. aiecs/domain/agent/__init__.py +191 -0
  87. aiecs/domain/agent/base_agent.py +3870 -0
  88. aiecs/domain/agent/exceptions.py +99 -0
  89. aiecs/domain/agent/graph_aware_mixin.py +569 -0
  90. aiecs/domain/agent/hybrid_agent.py +1435 -0
  91. aiecs/domain/agent/integration/__init__.py +29 -0
  92. aiecs/domain/agent/integration/context_compressor.py +216 -0
  93. aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
  94. aiecs/domain/agent/integration/protocols.py +281 -0
  95. aiecs/domain/agent/integration/retry_policy.py +218 -0
  96. aiecs/domain/agent/integration/role_config.py +213 -0
  97. aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
  98. aiecs/domain/agent/lifecycle.py +291 -0
  99. aiecs/domain/agent/llm_agent.py +692 -0
  100. aiecs/domain/agent/memory/__init__.py +12 -0
  101. aiecs/domain/agent/memory/conversation.py +1124 -0
  102. aiecs/domain/agent/migration/__init__.py +14 -0
  103. aiecs/domain/agent/migration/conversion.py +163 -0
  104. aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
  105. aiecs/domain/agent/models.py +884 -0
  106. aiecs/domain/agent/observability.py +479 -0
  107. aiecs/domain/agent/persistence.py +449 -0
  108. aiecs/domain/agent/prompts/__init__.py +29 -0
  109. aiecs/domain/agent/prompts/builder.py +159 -0
  110. aiecs/domain/agent/prompts/formatters.py +187 -0
  111. aiecs/domain/agent/prompts/template.py +255 -0
  112. aiecs/domain/agent/registry.py +253 -0
  113. aiecs/domain/agent/tool_agent.py +444 -0
  114. aiecs/domain/agent/tools/__init__.py +15 -0
  115. aiecs/domain/agent/tools/schema_generator.py +364 -0
  116. aiecs/domain/community/__init__.py +155 -0
  117. aiecs/domain/community/agent_adapter.py +469 -0
  118. aiecs/domain/community/analytics.py +432 -0
  119. aiecs/domain/community/collaborative_workflow.py +648 -0
  120. aiecs/domain/community/communication_hub.py +634 -0
  121. aiecs/domain/community/community_builder.py +320 -0
  122. aiecs/domain/community/community_integration.py +796 -0
  123. aiecs/domain/community/community_manager.py +803 -0
  124. aiecs/domain/community/decision_engine.py +849 -0
  125. aiecs/domain/community/exceptions.py +231 -0
  126. aiecs/domain/community/models/__init__.py +33 -0
  127. aiecs/domain/community/models/community_models.py +234 -0
  128. aiecs/domain/community/resource_manager.py +461 -0
  129. aiecs/domain/community/shared_context_manager.py +589 -0
  130. aiecs/domain/context/__init__.py +40 -10
  131. aiecs/domain/context/context_engine.py +1910 -0
  132. aiecs/domain/context/conversation_models.py +87 -53
  133. aiecs/domain/context/graph_memory.py +582 -0
  134. aiecs/domain/execution/model.py +12 -4
  135. aiecs/domain/knowledge_graph/__init__.py +19 -0
  136. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  137. aiecs/domain/knowledge_graph/models/entity.py +148 -0
  138. aiecs/domain/knowledge_graph/models/evidence.py +178 -0
  139. aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
  140. aiecs/domain/knowledge_graph/models/path.py +171 -0
  141. aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
  142. aiecs/domain/knowledge_graph/models/query.py +261 -0
  143. aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
  144. aiecs/domain/knowledge_graph/models/relation.py +202 -0
  145. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  146. aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
  147. aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
  148. aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
  149. aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
  150. aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
  151. aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
  152. aiecs/domain/task/dsl_processor.py +172 -56
  153. aiecs/domain/task/model.py +20 -8
  154. aiecs/domain/task/task_context.py +27 -24
  155. aiecs/infrastructure/__init__.py +0 -2
  156. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  157. aiecs/infrastructure/graph_storage/base.py +837 -0
  158. aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
  159. aiecs/infrastructure/graph_storage/cache.py +424 -0
  160. aiecs/infrastructure/graph_storage/distributed.py +223 -0
  161. aiecs/infrastructure/graph_storage/error_handling.py +380 -0
  162. aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
  163. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  164. aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
  165. aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
  166. aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
  167. aiecs/infrastructure/graph_storage/metrics.py +344 -0
  168. aiecs/infrastructure/graph_storage/migration.py +400 -0
  169. aiecs/infrastructure/graph_storage/pagination.py +483 -0
  170. aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
  171. aiecs/infrastructure/graph_storage/postgres.py +1563 -0
  172. aiecs/infrastructure/graph_storage/property_storage.py +353 -0
  173. aiecs/infrastructure/graph_storage/protocols.py +76 -0
  174. aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
  175. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  176. aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
  177. aiecs/infrastructure/graph_storage/streaming.py +487 -0
  178. aiecs/infrastructure/graph_storage/tenant.py +412 -0
  179. aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
  180. aiecs/infrastructure/messaging/websocket_manager.py +51 -35
  181. aiecs/infrastructure/monitoring/__init__.py +22 -0
  182. aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
  183. aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
  184. aiecs/infrastructure/monitoring/structured_logger.py +3 -7
  185. aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
  186. aiecs/infrastructure/persistence/__init__.py +14 -1
  187. aiecs/infrastructure/persistence/context_engine_client.py +184 -0
  188. aiecs/infrastructure/persistence/database_manager.py +67 -43
  189. aiecs/infrastructure/persistence/file_storage.py +180 -103
  190. aiecs/infrastructure/persistence/redis_client.py +74 -21
  191. aiecs/llm/__init__.py +73 -25
  192. aiecs/llm/callbacks/__init__.py +11 -0
  193. aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
  194. aiecs/llm/client_factory.py +224 -36
  195. aiecs/llm/client_resolver.py +155 -0
  196. aiecs/llm/clients/__init__.py +38 -0
  197. aiecs/llm/clients/base_client.py +324 -0
  198. aiecs/llm/clients/google_function_calling_mixin.py +457 -0
  199. aiecs/llm/clients/googleai_client.py +241 -0
  200. aiecs/llm/clients/openai_client.py +158 -0
  201. aiecs/llm/clients/openai_compatible_mixin.py +367 -0
  202. aiecs/llm/clients/vertex_client.py +897 -0
  203. aiecs/llm/clients/xai_client.py +201 -0
  204. aiecs/llm/config/__init__.py +51 -0
  205. aiecs/llm/config/config_loader.py +272 -0
  206. aiecs/llm/config/config_validator.py +206 -0
  207. aiecs/llm/config/model_config.py +143 -0
  208. aiecs/llm/protocols.py +149 -0
  209. aiecs/llm/utils/__init__.py +10 -0
  210. aiecs/llm/utils/validate_config.py +89 -0
  211. aiecs/main.py +140 -121
  212. aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
  213. aiecs/scripts/aid/__init__.py +19 -0
  214. aiecs/scripts/aid/module_checker.py +499 -0
  215. aiecs/scripts/aid/version_manager.py +235 -0
  216. aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
  217. aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
  218. aiecs/scripts/dependance_check/__init__.py +15 -0
  219. aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
  220. aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
  221. aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
  222. aiecs/scripts/dependance_patch/__init__.py +7 -0
  223. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  224. aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
  225. aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
  226. aiecs/scripts/knowledge_graph/__init__.py +3 -0
  227. aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
  228. aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
  229. aiecs/scripts/tools_develop/README.md +671 -0
  230. aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
  231. aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
  232. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  233. aiecs/scripts/tools_develop/__init__.py +21 -0
  234. aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
  235. aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
  236. aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
  237. aiecs/scripts/tools_develop/schema_coverage.py +511 -0
  238. aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
  239. aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
  240. aiecs/scripts/tools_develop/verify_tools.py +352 -0
  241. aiecs/tasks/__init__.py +0 -1
  242. aiecs/tasks/worker.py +115 -47
  243. aiecs/tools/__init__.py +194 -72
  244. aiecs/tools/apisource/__init__.py +99 -0
  245. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  246. aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
  247. aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
  248. aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
  249. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  250. aiecs/tools/apisource/monitoring/metrics.py +330 -0
  251. aiecs/tools/apisource/providers/__init__.py +112 -0
  252. aiecs/tools/apisource/providers/base.py +671 -0
  253. aiecs/tools/apisource/providers/census.py +397 -0
  254. aiecs/tools/apisource/providers/fred.py +535 -0
  255. aiecs/tools/apisource/providers/newsapi.py +409 -0
  256. aiecs/tools/apisource/providers/worldbank.py +352 -0
  257. aiecs/tools/apisource/reliability/__init__.py +12 -0
  258. aiecs/tools/apisource/reliability/error_handler.py +363 -0
  259. aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
  260. aiecs/tools/apisource/tool.py +832 -0
  261. aiecs/tools/apisource/utils/__init__.py +9 -0
  262. aiecs/tools/apisource/utils/validators.py +334 -0
  263. aiecs/tools/base_tool.py +415 -21
  264. aiecs/tools/docs/__init__.py +121 -0
  265. aiecs/tools/docs/ai_document_orchestrator.py +607 -0
  266. aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
  267. aiecs/tools/docs/content_insertion_tool.py +1320 -0
  268. aiecs/tools/docs/document_creator_tool.py +1323 -0
  269. aiecs/tools/docs/document_layout_tool.py +1160 -0
  270. aiecs/tools/docs/document_parser_tool.py +1011 -0
  271. aiecs/tools/docs/document_writer_tool.py +1829 -0
  272. aiecs/tools/knowledge_graph/__init__.py +17 -0
  273. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
  274. aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
  275. aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
  276. aiecs/tools/langchain_adapter.py +300 -138
  277. aiecs/tools/schema_generator.py +455 -0
  278. aiecs/tools/search_tool/__init__.py +100 -0
  279. aiecs/tools/search_tool/analyzers.py +581 -0
  280. aiecs/tools/search_tool/cache.py +264 -0
  281. aiecs/tools/search_tool/constants.py +128 -0
  282. aiecs/tools/search_tool/context.py +224 -0
  283. aiecs/tools/search_tool/core.py +778 -0
  284. aiecs/tools/search_tool/deduplicator.py +119 -0
  285. aiecs/tools/search_tool/error_handler.py +242 -0
  286. aiecs/tools/search_tool/metrics.py +343 -0
  287. aiecs/tools/search_tool/rate_limiter.py +172 -0
  288. aiecs/tools/search_tool/schemas.py +275 -0
  289. aiecs/tools/statistics/__init__.py +80 -0
  290. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
  291. aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
  292. aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
  293. aiecs/tools/statistics/data_loader_tool.py +555 -0
  294. aiecs/tools/statistics/data_profiler_tool.py +638 -0
  295. aiecs/tools/statistics/data_transformer_tool.py +580 -0
  296. aiecs/tools/statistics/data_visualizer_tool.py +498 -0
  297. aiecs/tools/statistics/model_trainer_tool.py +507 -0
  298. aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
  299. aiecs/tools/task_tools/__init__.py +49 -36
  300. aiecs/tools/task_tools/chart_tool.py +200 -184
  301. aiecs/tools/task_tools/classfire_tool.py +268 -267
  302. aiecs/tools/task_tools/image_tool.py +175 -131
  303. aiecs/tools/task_tools/office_tool.py +226 -146
  304. aiecs/tools/task_tools/pandas_tool.py +477 -121
  305. aiecs/tools/task_tools/report_tool.py +390 -142
  306. aiecs/tools/task_tools/research_tool.py +149 -79
  307. aiecs/tools/task_tools/scraper_tool.py +339 -145
  308. aiecs/tools/task_tools/stats_tool.py +448 -209
  309. aiecs/tools/temp_file_manager.py +26 -24
  310. aiecs/tools/tool_executor/__init__.py +18 -16
  311. aiecs/tools/tool_executor/tool_executor.py +364 -52
  312. aiecs/utils/LLM_output_structor.py +74 -48
  313. aiecs/utils/__init__.py +14 -3
  314. aiecs/utils/base_callback.py +0 -3
  315. aiecs/utils/cache_provider.py +696 -0
  316. aiecs/utils/execution_utils.py +50 -31
  317. aiecs/utils/prompt_loader.py +1 -0
  318. aiecs/utils/token_usage_repository.py +37 -11
  319. aiecs/ws/socket_server.py +14 -4
  320. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
  321. aiecs-1.7.6.dist-info/RECORD +337 -0
  322. aiecs-1.7.6.dist-info/entry_points.txt +13 -0
  323. aiecs/config/registry.py +0 -19
  324. aiecs/domain/context/content_engine.py +0 -982
  325. aiecs/llm/base_client.py +0 -99
  326. aiecs/llm/openai_client.py +0 -125
  327. aiecs/llm/vertex_client.py +0 -186
  328. aiecs/llm/xai_client.py +0 -184
  329. aiecs/scripts/dependency_checker.py +0 -857
  330. aiecs/scripts/quick_dependency_check.py +0 -269
  331. aiecs/tools/task_tools/search_api.py +0 -7
  332. aiecs-1.0.1.dist-info/RECORD +0 -90
  333. aiecs-1.0.1.dist-info/entry_points.txt +0 -7
  334. /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
  335. /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
  336. /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
  337. /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
  338. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
  339. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
  340. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,148 @@
1
+ """
2
+ Entity Domain Model
3
+
4
+ Represents a node/entity in the knowledge graph with properties and embeddings.
5
+ """
6
+
7
+ from typing import Any, Optional
8
+ from datetime import datetime
9
+ from pydantic import BaseModel, Field, field_validator, model_validator
10
+ import numpy as np
11
+
12
+ from aiecs.infrastructure.graph_storage.tenant import validate_tenant_id, InvalidTenantIdError
13
+
14
+
15
+ class Entity(BaseModel):
16
+ """
17
+ Knowledge Graph Entity
18
+
19
+ Represents a node in the knowledge graph with:
20
+ - Unique identifier
21
+ - Entity type (e.g., "Person", "Company", "Product")
22
+ - Properties (arbitrary key-value data)
23
+ - Optional vector embedding for semantic search
24
+ - Metadata (timestamps, source info)
25
+
26
+ Example:
27
+ ```python
28
+ entity = Entity(
29
+ id="person_001",
30
+ entity_type="Person",
31
+ properties={
32
+ "name": "John Doe",
33
+ "age": 30,
34
+ "occupation": "Software Engineer"
35
+ }
36
+ )
37
+ ```
38
+ """
39
+
40
+ id: str = Field(..., description="Unique identifier for the entity")
41
+
42
+ entity_type: str = Field(..., description="Type of the entity (e.g., 'Person', 'Company')")
43
+
44
+ properties: dict[str, Any] = Field(
45
+ default_factory=dict,
46
+ description="Arbitrary properties associated with the entity",
47
+ )
48
+
49
+ embedding: Optional[list[float]] = Field(default=None, description="Vector embedding for semantic search")
50
+
51
+ created_at: datetime = Field(
52
+ default_factory=datetime.utcnow,
53
+ description="Timestamp when entity was created",
54
+ )
55
+
56
+ updated_at: datetime = Field(
57
+ default_factory=datetime.utcnow,
58
+ description="Timestamp when entity was last updated",
59
+ )
60
+
61
+ source: Optional[str] = Field(
62
+ default=None,
63
+ description="Source of the entity data (e.g., document ID)",
64
+ )
65
+
66
+ tenant_id: Optional[str] = Field(
67
+ default=None,
68
+ description="Tenant identifier for multi-tenant isolation (alphanumeric, hyphens, underscores only)",
69
+ )
70
+
71
+ class Config:
72
+ json_encoders = {datetime: lambda v: v.isoformat()}
73
+ # Allow arbitrary types for numpy arrays if needed
74
+ arbitrary_types_allowed = True
75
+
76
+ @field_validator("embedding")
77
+ @classmethod
78
+ def validate_embedding(cls, v: Optional[list[float]]) -> Optional[list[float]]:
79
+ """Validate embedding is a list of floats"""
80
+ if v is not None:
81
+ if not isinstance(v, list):
82
+ raise ValueError("Embedding must be a list of floats")
83
+ if not all(isinstance(x, (int, float)) for x in v):
84
+ raise ValueError("All embedding values must be numeric")
85
+ return v
86
+
87
+ @model_validator(mode="before")
88
+ @classmethod
89
+ def validate_tenant_id_before(cls, data: Any) -> Any:
90
+ """Validate tenant_id format before model creation"""
91
+ # Pydantic converts keyword arguments to dict before calling model_validator
92
+ if isinstance(data, dict):
93
+ tenant_id = data.get("tenant_id")
94
+ if tenant_id is not None:
95
+ # Validate and raise InvalidTenantIdError directly
96
+ # Note: Pydantic will wrap this in ValidationError, but the error info is preserved
97
+ validate_tenant_id(tenant_id)
98
+ return data
99
+
100
+ def get_embedding_vector(self) -> Optional[np.ndarray]:
101
+ """
102
+ Get embedding as numpy array
103
+
104
+ Returns:
105
+ numpy array of embedding or None if no embedding
106
+ """
107
+ if self.embedding is None:
108
+ return None
109
+ return np.array(self.embedding, dtype=np.float32)
110
+
111
+ def set_embedding_vector(self, vector: np.ndarray) -> None:
112
+ """
113
+ Set embedding from numpy array
114
+
115
+ Args:
116
+ vector: Numpy array of embedding values
117
+ """
118
+ self.embedding = vector.tolist()
119
+
120
+ def get_property(self, key: str, default: Any = None) -> Any:
121
+ """
122
+ Get a specific property value
123
+
124
+ Args:
125
+ key: Property key
126
+ default: Default value if key not found
127
+
128
+ Returns:
129
+ Property value or default
130
+ """
131
+ return self.properties.get(key, default)
132
+
133
+ def set_property(self, key: str, value: Any) -> None:
134
+ """
135
+ Set a property value
136
+
137
+ Args:
138
+ key: Property key
139
+ value: Property value
140
+ """
141
+ self.properties[key] = value
142
+ self.updated_at = datetime.utcnow()
143
+
144
+ def __str__(self) -> str:
145
+ return f"Entity(id={self.id}, type={self.entity_type})"
146
+
147
+ def __repr__(self) -> str:
148
+ return f"Entity(id='{self.id}', entity_type='{self.entity_type}', properties={len(self.properties)} keys)"
@@ -0,0 +1,178 @@
1
+ """
2
+ Evidence Domain Models
3
+
4
+ Models for representing evidence from reasoning processes.
5
+ """
6
+
7
+ from typing import List, Optional, Dict, Any
8
+ from enum import Enum
9
+ from pydantic import BaseModel, Field
10
+ from aiecs.domain.knowledge_graph.models.entity import Entity
11
+ from aiecs.domain.knowledge_graph.models.relation import Relation
12
+ from aiecs.domain.knowledge_graph.models.path import Path
13
+
14
+
15
+ class EvidenceType(str, Enum):
16
+ """Types of evidence"""
17
+
18
+ ENTITY = "entity" # Single entity
19
+ RELATION = "relation" # Single relation
20
+ PATH = "path" # Complete path
21
+ SUBGRAPH = "subgraph" # Subgraph fragment
22
+
23
+
24
+ class Evidence(BaseModel):
25
+ """
26
+ Evidence from Reasoning
27
+
28
+ Represents a piece of evidence collected during reasoning,
29
+ with confidence scoring and provenance tracking.
30
+
31
+ Attributes:
32
+ evidence_id: Unique identifier for this evidence
33
+ evidence_type: Type of evidence (entity, relation, path, etc.)
34
+ entities: Entities involved in this evidence
35
+ relations: Relations involved in this evidence
36
+ paths: Paths involved in this evidence (for path-based evidence)
37
+ confidence: Confidence score (0-1, higher = more confident)
38
+ relevance_score: Relevance to the query (0-1)
39
+ explanation: Human-readable explanation of this evidence
40
+ source: Source of this evidence (e.g., "traversal", "vector_search")
41
+ metadata: Additional metadata
42
+
43
+ Example:
44
+ ```python
45
+ evidence = Evidence(
46
+ evidence_id="ev_001",
47
+ evidence_type=EvidenceType.PATH,
48
+ entities=[alice, bob, company],
49
+ relations=[knows_rel, works_at_rel],
50
+ paths=[path],
51
+ confidence=0.9,
52
+ relevance_score=0.85,
53
+ explanation="Alice knows Bob who works at Company X",
54
+ source="multi_hop_traversal"
55
+ )
56
+ ```
57
+ """
58
+
59
+ evidence_id: str = Field(..., description="Unique identifier for this evidence")
60
+
61
+ evidence_type: EvidenceType = Field(..., description="Type of evidence")
62
+
63
+ entities: List[Entity] = Field(default_factory=list, description="Entities involved in this evidence")
64
+
65
+ relations: List[Relation] = Field(default_factory=list, description="Relations involved in this evidence")
66
+
67
+ paths: List[Path] = Field(default_factory=list, description="Paths involved in this evidence")
68
+
69
+ confidence: float = Field(
70
+ default=1.0,
71
+ ge=0.0,
72
+ le=1.0,
73
+ description="Confidence score (0-1, higher = more confident)",
74
+ )
75
+
76
+ relevance_score: float = Field(default=0.5, ge=0.0, le=1.0, description="Relevance to the query (0-1)")
77
+
78
+ explanation: str = Field(default="", description="Human-readable explanation of this evidence")
79
+
80
+ source: str = Field(default="", description="Source of this evidence (e.g., query step ID)")
81
+
82
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
83
+
84
+ @property
85
+ def combined_score(self) -> float:
86
+ """Get combined score (confidence * relevance)"""
87
+ return self.confidence * self.relevance_score
88
+
89
+ def get_entity_ids(self) -> List[str]:
90
+ """Get list of all entity IDs in evidence"""
91
+ return [entity.id for entity in self.entities]
92
+
93
+ def __str__(self) -> str:
94
+ return f"Evidence(type={self.evidence_type}, " f"score={self.combined_score:.2f}, " f"entities={len(self.entities)})"
95
+
96
+
97
+ class ReasoningResult(BaseModel):
98
+ """
99
+ Result of Reasoning Process
100
+
101
+ Contains evidence collected, answer generated, and reasoning trace.
102
+
103
+ Attributes:
104
+ query: Original query that was answered
105
+ evidence: List of evidence pieces collected
106
+ answer: Generated answer (if applicable)
107
+ confidence: Overall confidence in the answer (0-1)
108
+ reasoning_trace: Human-readable trace of reasoning steps
109
+ execution_time_ms: Time taken to perform reasoning
110
+ metadata: Additional metadata
111
+
112
+ Example:
113
+ ```python
114
+ result = ReasoningResult(
115
+ query="What companies does Alice know people at?",
116
+ evidence=[ev1, ev2, ev3],
117
+ answer="Alice knows people at Company X and Company Y",
118
+ confidence=0.87,
119
+ reasoning_trace="Step 1: Find Alice\nStep 2: Find people Alice knows\n...",
120
+ execution_time_ms=125.5
121
+ )
122
+ ```
123
+ """
124
+
125
+ query: str = Field(..., description="Original query that was answered")
126
+
127
+ evidence: List[Evidence] = Field(default_factory=list, description="List of evidence pieces collected")
128
+
129
+ answer: Optional[str] = Field(default=None, description="Generated answer (if applicable)")
130
+
131
+ confidence: float = Field(
132
+ default=0.0,
133
+ ge=0.0,
134
+ le=1.0,
135
+ description="Overall confidence in the answer (0-1)",
136
+ )
137
+
138
+ reasoning_trace: List[str] = Field(default_factory=list, description="List of reasoning steps taken")
139
+
140
+ execution_time_ms: Optional[float] = Field(default=None, ge=0.0, description="Time taken to perform reasoning")
141
+
142
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
143
+
144
+ @property
145
+ def evidence_count(self) -> int:
146
+ """Get number of evidence pieces"""
147
+ return len(self.evidence)
148
+
149
+ @property
150
+ def has_answer(self) -> bool:
151
+ """Check if result has an answer"""
152
+ return self.answer is not None and len(self.answer) > 0
153
+
154
+ def get_top_evidence(self, n: int = 5) -> List[Evidence]:
155
+ """
156
+ Get top N evidence pieces by combined score
157
+
158
+ Args:
159
+ n: Number of evidence pieces to return
160
+
161
+ Returns:
162
+ Top N evidence pieces
163
+ """
164
+ sorted_evidence = sorted(self.evidence, key=lambda e: e.combined_score, reverse=True)
165
+ return sorted_evidence[:n]
166
+
167
+ def get_trace_string(self) -> str:
168
+ """Get reasoning trace as a single string"""
169
+ return "\n".join(self.reasoning_trace)
170
+
171
+ def __str__(self) -> str:
172
+ parts = [
173
+ f"ReasoningResult(evidence={self.evidence_count}",
174
+ f"confidence={self.confidence:.2f})",
175
+ ]
176
+ if self.has_answer and self.answer:
177
+ parts.insert(1, f"answer={self.answer[:50]}...")
178
+ return " ".join(parts)
@@ -0,0 +1,184 @@
1
+ """
2
+ Inference Rule Domain Models
3
+
4
+ Models for representing logical inference rules.
5
+ """
6
+
7
+ from typing import List, Dict, Any
8
+ from enum import Enum
9
+ from pydantic import BaseModel, Field
10
+ from aiecs.domain.knowledge_graph.models.relation import Relation
11
+
12
+
13
+ class RuleType(str, Enum):
14
+ """Types of inference rules"""
15
+
16
+ TRANSITIVE = "transitive" # A->B, B->C => A->C
17
+ SYMMETRIC = "symmetric" # A->B => B->A
18
+ REFLEXIVE = "reflexive" # A => A->A
19
+ CUSTOM = "custom" # User-defined rule
20
+
21
+
22
+ class InferenceRule(BaseModel):
23
+ """
24
+ Inference Rule
25
+
26
+ Represents a logical rule for inferring new relations from existing ones.
27
+
28
+ Attributes:
29
+ rule_id: Unique identifier for this rule
30
+ rule_type: Type of rule (transitive, symmetric, etc.)
31
+ relation_type: Relation type this rule applies to
32
+ description: Human-readable description
33
+ enabled: Whether this rule is enabled
34
+ confidence_decay: How much confidence decreases with each inference step (0-1)
35
+ metadata: Additional metadata
36
+
37
+ Example:
38
+ ```python
39
+ rule = InferenceRule(
40
+ rule_id="rule_001",
41
+ rule_type=RuleType.TRANSITIVE,
42
+ relation_type="WORKS_FOR",
43
+ description="If A works for B and B works for C, then A works for C",
44
+ confidence_decay=0.1
45
+ )
46
+ ```
47
+ """
48
+
49
+ rule_id: str = Field(..., description="Unique identifier for this rule")
50
+
51
+ rule_type: RuleType = Field(..., description="Type of inference rule")
52
+
53
+ relation_type: str = Field(..., description="Relation type this rule applies to")
54
+
55
+ description: str = Field(default="", description="Human-readable description of the rule")
56
+
57
+ enabled: bool = Field(default=True, description="Whether this rule is enabled")
58
+
59
+ confidence_decay: float = Field(
60
+ default=0.1,
61
+ ge=0.0,
62
+ le=1.0,
63
+ description="Confidence decay per inference step (0-1)",
64
+ )
65
+
66
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
67
+
68
+ def can_apply(self, relation: Relation) -> bool:
69
+ """
70
+ Check if this rule can apply to a given relation
71
+
72
+ Args:
73
+ relation: Relation to check
74
+
75
+ Returns:
76
+ True if rule can apply
77
+ """
78
+ if not self.enabled:
79
+ return False
80
+ return relation.relation_type == self.relation_type
81
+
82
+
83
+ class InferenceStep(BaseModel):
84
+ """
85
+ Single Inference Step
86
+
87
+ Represents one step in an inference chain, tracking what was inferred
88
+ and how.
89
+
90
+ Attributes:
91
+ step_id: Unique identifier for this step
92
+ inferred_relation: The relation that was inferred
93
+ source_relations: Relations used to infer this one
94
+ rule: The rule that was applied
95
+ confidence: Confidence in this inference (0-1)
96
+ explanation: Human-readable explanation
97
+
98
+ Example:
99
+ ```python
100
+ step = InferenceStep(
101
+ step_id="step_001",
102
+ inferred_relation=inferred_rel,
103
+ source_relations=[rel1, rel2],
104
+ rule=rule,
105
+ confidence=0.9,
106
+ explanation="Inferred from transitive rule"
107
+ )
108
+ ```
109
+ """
110
+
111
+ step_id: str = Field(..., description="Unique identifier for this step")
112
+
113
+ inferred_relation: Relation = Field(..., description="The relation that was inferred")
114
+
115
+ source_relations: List[Relation] = Field(..., description="Relations used to infer this one")
116
+
117
+ rule: InferenceRule = Field(..., description="The rule that was applied")
118
+
119
+ confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence in this inference (0-1)")
120
+
121
+ explanation: str = Field(default="", description="Human-readable explanation of the inference")
122
+
123
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
124
+
125
+
126
+ class InferenceResult(BaseModel):
127
+ """
128
+ Inference Result
129
+
130
+ Contains the results of applying inference rules.
131
+
132
+ Attributes:
133
+ inferred_relations: List of relations that were inferred
134
+ inference_steps: List of inference steps taken
135
+ total_steps: Total number of inference steps
136
+ confidence: Overall confidence in the results
137
+ explanation: Human-readable explanation
138
+
139
+ Example:
140
+ ```python
141
+ result = InferenceResult(
142
+ inferred_relations=[rel1, rel2],
143
+ inference_steps=[step1, step2],
144
+ total_steps=2,
145
+ confidence=0.85,
146
+ explanation="Inferred 2 relations using transitive rule"
147
+ )
148
+ ```
149
+ """
150
+
151
+ inferred_relations: List[Relation] = Field(
152
+ default_factory=list,
153
+ description="List of relations that were inferred",
154
+ )
155
+
156
+ inference_steps: List[InferenceStep] = Field(default_factory=list, description="List of inference steps taken")
157
+
158
+ total_steps: int = Field(default=0, ge=0, description="Total number of inference steps")
159
+
160
+ confidence: float = Field(
161
+ default=1.0,
162
+ ge=0.0,
163
+ le=1.0,
164
+ description="Overall confidence in the results",
165
+ )
166
+
167
+ explanation: str = Field(default="", description="Human-readable explanation")
168
+
169
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
170
+
171
+ @property
172
+ def has_results(self) -> bool:
173
+ """Check if any relations were inferred"""
174
+ return len(self.inferred_relations) > 0
175
+
176
+ def get_explanation_string(self) -> str:
177
+ """Get explanation as a single string"""
178
+ if not self.explanation:
179
+ return f"Inferred {len(self.inferred_relations)} relations in {self.total_steps} steps"
180
+ return self.explanation
181
+
182
+ def get_step_explanations(self) -> List[str]:
183
+ """Get explanations for each step"""
184
+ return [step.explanation for step in self.inference_steps]
@@ -0,0 +1,171 @@
1
+ """
2
+ Path Domain Model
3
+
4
+ Represents a path through the knowledge graph (sequence of entities and relations).
5
+ """
6
+
7
+ from typing import List, Optional
8
+ from pydantic import BaseModel, Field, field_validator
9
+ from aiecs.domain.knowledge_graph.models.entity import Entity
10
+ from aiecs.domain.knowledge_graph.models.relation import Relation
11
+
12
+
13
+ class Path(BaseModel):
14
+ """
15
+ Knowledge Graph Path
16
+
17
+ Represents a path through the knowledge graph as a sequence of entities
18
+ connected by relations. Paths are results of graph traversal operations.
19
+
20
+ Attributes:
21
+ nodes: Sequence of entities in the path
22
+ edges: Sequence of relations connecting the entities
23
+ score: Optional relevance score for the path
24
+ length: Number of hops in the path
25
+
26
+ Example:
27
+ ```python
28
+ path = Path(
29
+ nodes=[entity1, entity2, entity3],
30
+ edges=[relation1_2, relation2_3],
31
+ score=0.85
32
+ )
33
+ ```
34
+
35
+ Invariants:
36
+ - len(edges) == len(nodes) - 1 (for a valid path)
37
+ - edges[i].source_id == nodes[i].id
38
+ - edges[i].target_id == nodes[i+1].id
39
+ """
40
+
41
+ nodes: List[Entity] = Field(..., min_length=1, description="Sequence of entities in the path")
42
+
43
+ edges: List[Relation] = Field(
44
+ default_factory=list,
45
+ description="Sequence of relations connecting entities",
46
+ )
47
+
48
+ score: Optional[float] = Field(
49
+ default=None,
50
+ ge=0.0,
51
+ le=1.0,
52
+ description="Relevance score for the path (0.0-1.0)",
53
+ )
54
+
55
+ class Config:
56
+ arbitrary_types_allowed = True
57
+
58
+ @field_validator("edges")
59
+ @classmethod
60
+ def validate_path_structure(cls, v: List[Relation], info) -> List[Relation]:
61
+ """Validate that edges match nodes structure"""
62
+ nodes = info.data.get("nodes", [])
63
+ if not nodes:
64
+ return v
65
+
66
+ # Check edge count
67
+ if len(v) != len(nodes) - 1:
68
+ if len(v) > 0: # Only raise error if edges are provided
69
+ raise ValueError(f"Number of edges ({len(v)}) must be len(nodes) - 1 ({len(nodes) - 1})")
70
+
71
+ # Validate edge connectivity (if we have edges)
72
+ for i, edge in enumerate(v):
73
+ if i < len(nodes) - 1:
74
+ expected_source = nodes[i].id
75
+ expected_target = nodes[i + 1].id
76
+
77
+ if edge.source_id != expected_source:
78
+ raise ValueError(f"Edge {i} source_id ({edge.source_id}) doesn't match " f"node {i} id ({expected_source})")
79
+
80
+ if edge.target_id != expected_target:
81
+ raise ValueError(f"Edge {i} target_id ({edge.target_id}) doesn't match " f"node {i+1} id ({expected_target})")
82
+
83
+ return v
84
+
85
+ @property
86
+ def length(self) -> int:
87
+ """
88
+ Get path length (number of hops)
89
+
90
+ Returns:
91
+ Number of edges in the path
92
+ """
93
+ return len(self.edges)
94
+
95
+ @property
96
+ def start_entity(self) -> Entity:
97
+ """
98
+ Get the starting entity of the path
99
+
100
+ Returns:
101
+ First entity in the path
102
+ """
103
+ return self.nodes[0]
104
+
105
+ @property
106
+ def end_entity(self) -> Entity:
107
+ """
108
+ Get the ending entity of the path
109
+
110
+ Returns:
111
+ Last entity in the path
112
+ """
113
+ return self.nodes[-1]
114
+
115
+ def get_entity_ids(self) -> List[str]:
116
+ """
117
+ Get list of entity IDs in the path
118
+
119
+ Returns:
120
+ List of entity IDs
121
+ """
122
+ return [node.id for node in self.nodes]
123
+
124
+ def get_relation_types(self) -> List[str]:
125
+ """
126
+ Get list of relation types in the path
127
+
128
+ Returns:
129
+ List of relation types
130
+ """
131
+ return [edge.relation_type for edge in self.edges]
132
+
133
+ def contains_entity(self, entity_id: str) -> bool:
134
+ """
135
+ Check if path contains a specific entity
136
+
137
+ Args:
138
+ entity_id: Entity ID to check
139
+
140
+ Returns:
141
+ True if entity is in the path
142
+ """
143
+ return entity_id in self.get_entity_ids()
144
+
145
+ def contains_relation_type(self, relation_type: str) -> bool:
146
+ """
147
+ Check if path contains a specific relation type
148
+
149
+ Args:
150
+ relation_type: Relation type to check
151
+
152
+ Returns:
153
+ True if relation type is in the path
154
+ """
155
+ return relation_type in self.get_relation_types()
156
+
157
+ def __str__(self) -> str:
158
+ if not self.edges:
159
+ return f"Path({self.nodes[0]})"
160
+
161
+ path_str = str(self.nodes[0].id)
162
+ for edge, node in zip(self.edges, self.nodes[1:]):
163
+ path_str += f" -[{edge.relation_type}]-> {node.id}"
164
+
165
+ if self.score is not None:
166
+ path_str += f" (score={self.score:.3f})"
167
+
168
+ return f"Path({path_str})"
169
+
170
+ def __repr__(self) -> str:
171
+ return f"Path(length={self.length}, nodes={len(self.nodes)}, score={self.score})"