aiecs 1.0.1__py3-none-any.whl → 1.7.17__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.
- aiecs/__init__.py +13 -16
- aiecs/__main__.py +7 -7
- aiecs/aiecs_client.py +269 -75
- aiecs/application/executors/operation_executor.py +79 -54
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
- aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
- aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
- aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +98 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
- aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
- aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
- aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
- aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
- aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
- aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
- aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
- aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
- aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
- aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
- aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
- aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
- aiecs/application/knowledge_graph/search/reranker.py +293 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +471 -0
- aiecs/config/__init__.py +20 -5
- aiecs/config/config.py +762 -31
- aiecs/config/graph_config.py +131 -0
- aiecs/config/tool_config.py +435 -0
- aiecs/core/__init__.py +29 -13
- aiecs/core/interface/__init__.py +2 -2
- aiecs/core/interface/execution_interface.py +22 -22
- aiecs/core/interface/storage_interface.py +37 -88
- aiecs/core/registry/__init__.py +31 -0
- aiecs/core/registry/service_registry.py +92 -0
- aiecs/domain/__init__.py +270 -1
- aiecs/domain/agent/__init__.py +191 -0
- aiecs/domain/agent/base_agent.py +3949 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/graph_aware_mixin.py +569 -0
- aiecs/domain/agent/hybrid_agent.py +1731 -0
- aiecs/domain/agent/integration/__init__.py +29 -0
- aiecs/domain/agent/integration/context_compressor.py +216 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
- aiecs/domain/agent/integration/protocols.py +281 -0
- aiecs/domain/agent/integration/retry_policy.py +218 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
- aiecs/domain/agent/lifecycle.py +291 -0
- aiecs/domain/agent/llm_agent.py +692 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +1124 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +163 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
- aiecs/domain/agent/models.py +894 -0
- aiecs/domain/agent/observability.py +479 -0
- aiecs/domain/agent/persistence.py +449 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +159 -0
- aiecs/domain/agent/prompts/formatters.py +187 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +253 -0
- aiecs/domain/agent/tool_agent.py +444 -0
- aiecs/domain/agent/tools/__init__.py +15 -0
- aiecs/domain/agent/tools/schema_generator.py +377 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +469 -0
- aiecs/domain/community/analytics.py +432 -0
- aiecs/domain/community/collaborative_workflow.py +648 -0
- aiecs/domain/community/communication_hub.py +634 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +796 -0
- aiecs/domain/community/community_manager.py +803 -0
- aiecs/domain/community/decision_engine.py +849 -0
- aiecs/domain/community/exceptions.py +231 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +234 -0
- aiecs/domain/community/resource_manager.py +461 -0
- aiecs/domain/community/shared_context_manager.py +589 -0
- aiecs/domain/context/__init__.py +40 -10
- aiecs/domain/context/context_engine.py +1910 -0
- aiecs/domain/context/conversation_models.py +87 -53
- aiecs/domain/context/graph_memory.py +582 -0
- aiecs/domain/execution/model.py +12 -4
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +148 -0
- aiecs/domain/knowledge_graph/models/evidence.py +178 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
- aiecs/domain/knowledge_graph/models/path.py +171 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
- aiecs/domain/knowledge_graph/models/query.py +261 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
- aiecs/domain/knowledge_graph/models/relation.py +202 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
- aiecs/domain/task/dsl_processor.py +172 -56
- aiecs/domain/task/model.py +20 -8
- aiecs/domain/task/task_context.py +27 -24
- aiecs/infrastructure/__init__.py +0 -2
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +837 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
- aiecs/infrastructure/graph_storage/cache.py +424 -0
- aiecs/infrastructure/graph_storage/distributed.py +223 -0
- aiecs/infrastructure/graph_storage/error_handling.py +380 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
- aiecs/infrastructure/graph_storage/metrics.py +344 -0
- aiecs/infrastructure/graph_storage/migration.py +400 -0
- aiecs/infrastructure/graph_storage/pagination.py +483 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
- aiecs/infrastructure/graph_storage/postgres.py +1563 -0
- aiecs/infrastructure/graph_storage/property_storage.py +353 -0
- aiecs/infrastructure/graph_storage/protocols.py +76 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
- aiecs/infrastructure/graph_storage/streaming.py +487 -0
- aiecs/infrastructure/graph_storage/tenant.py +412 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
- aiecs/infrastructure/messaging/websocket_manager.py +51 -35
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
- aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
- aiecs/infrastructure/monitoring/structured_logger.py +3 -7
- aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
- aiecs/infrastructure/persistence/__init__.py +14 -1
- aiecs/infrastructure/persistence/context_engine_client.py +184 -0
- aiecs/infrastructure/persistence/database_manager.py +67 -43
- aiecs/infrastructure/persistence/file_storage.py +180 -103
- aiecs/infrastructure/persistence/redis_client.py +74 -21
- aiecs/llm/__init__.py +73 -25
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
- aiecs/llm/client_factory.py +230 -37
- aiecs/llm/client_resolver.py +155 -0
- aiecs/llm/clients/__init__.py +38 -0
- aiecs/llm/clients/base_client.py +328 -0
- aiecs/llm/clients/google_function_calling_mixin.py +415 -0
- aiecs/llm/clients/googleai_client.py +314 -0
- aiecs/llm/clients/openai_client.py +158 -0
- aiecs/llm/clients/openai_compatible_mixin.py +367 -0
- aiecs/llm/clients/vertex_client.py +1186 -0
- aiecs/llm/clients/xai_client.py +201 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +272 -0
- aiecs/llm/config/config_validator.py +206 -0
- aiecs/llm/config/model_config.py +143 -0
- aiecs/llm/protocols.py +149 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +89 -0
- aiecs/main.py +140 -121
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/module_checker.py +499 -0
- aiecs/scripts/aid/version_manager.py +235 -0
- aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
- aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
- aiecs/scripts/dependance_check/__init__.py +15 -0
- aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
- aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
- aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
- aiecs/scripts/knowledge_graph/__init__.py +3 -0
- aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
- aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
- aiecs/scripts/tools_develop/README.md +671 -0
- aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
- aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
- aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
- aiecs/scripts/tools_develop/schema_coverage.py +511 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
- aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
- aiecs/scripts/tools_develop/verify_tools.py +352 -0
- aiecs/tasks/__init__.py +0 -1
- aiecs/tasks/worker.py +115 -47
- aiecs/tools/__init__.py +194 -72
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +330 -0
- aiecs/tools/apisource/providers/__init__.py +112 -0
- aiecs/tools/apisource/providers/base.py +671 -0
- aiecs/tools/apisource/providers/census.py +397 -0
- aiecs/tools/apisource/providers/fred.py +535 -0
- aiecs/tools/apisource/providers/newsapi.py +409 -0
- aiecs/tools/apisource/providers/worldbank.py +352 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +363 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
- aiecs/tools/apisource/tool.py +832 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +334 -0
- aiecs/tools/base_tool.py +415 -21
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +607 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
- aiecs/tools/docs/content_insertion_tool.py +1320 -0
- aiecs/tools/docs/document_creator_tool.py +1464 -0
- aiecs/tools/docs/document_layout_tool.py +1160 -0
- aiecs/tools/docs/document_parser_tool.py +1016 -0
- aiecs/tools/docs/document_writer_tool.py +2008 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
- aiecs/tools/langchain_adapter.py +300 -138
- aiecs/tools/schema_generator.py +455 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +581 -0
- aiecs/tools/search_tool/cache.py +264 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +224 -0
- aiecs/tools/search_tool/core.py +778 -0
- aiecs/tools/search_tool/deduplicator.py +119 -0
- aiecs/tools/search_tool/error_handler.py +242 -0
- aiecs/tools/search_tool/metrics.py +343 -0
- aiecs/tools/search_tool/rate_limiter.py +172 -0
- aiecs/tools/search_tool/schemas.py +275 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
- aiecs/tools/statistics/data_loader_tool.py +555 -0
- aiecs/tools/statistics/data_profiler_tool.py +638 -0
- aiecs/tools/statistics/data_transformer_tool.py +580 -0
- aiecs/tools/statistics/data_visualizer_tool.py +498 -0
- aiecs/tools/statistics/model_trainer_tool.py +507 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
- aiecs/tools/task_tools/__init__.py +49 -36
- aiecs/tools/task_tools/chart_tool.py +200 -184
- aiecs/tools/task_tools/classfire_tool.py +268 -267
- aiecs/tools/task_tools/image_tool.py +220 -141
- aiecs/tools/task_tools/office_tool.py +226 -146
- aiecs/tools/task_tools/pandas_tool.py +477 -121
- aiecs/tools/task_tools/report_tool.py +390 -142
- aiecs/tools/task_tools/research_tool.py +149 -79
- aiecs/tools/task_tools/scraper_tool.py +339 -145
- aiecs/tools/task_tools/stats_tool.py +448 -209
- aiecs/tools/temp_file_manager.py +26 -24
- aiecs/tools/tool_executor/__init__.py +18 -16
- aiecs/tools/tool_executor/tool_executor.py +364 -52
- aiecs/utils/LLM_output_structor.py +74 -48
- aiecs/utils/__init__.py +14 -3
- aiecs/utils/base_callback.py +0 -3
- aiecs/utils/cache_provider.py +696 -0
- aiecs/utils/execution_utils.py +50 -31
- aiecs/utils/prompt_loader.py +1 -0
- aiecs/utils/token_usage_repository.py +37 -11
- aiecs/ws/socket_server.py +14 -4
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/METADATA +52 -15
- aiecs-1.7.17.dist-info/RECORD +337 -0
- aiecs-1.7.17.dist-info/entry_points.txt +13 -0
- aiecs/config/registry.py +0 -19
- aiecs/domain/context/content_engine.py +0 -982
- aiecs/llm/base_client.py +0 -99
- aiecs/llm/openai_client.py +0 -125
- aiecs/llm/vertex_client.py +0 -186
- aiecs/llm/xai_client.py +0 -184
- aiecs/scripts/dependency_checker.py +0 -857
- aiecs/scripts/quick_dependency_check.py +0 -269
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.1.dist-info/RECORD +0 -90
- aiecs-1.0.1.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/WHEEL +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Graph Memory Integration for ContextEngine
|
|
3
|
+
|
|
4
|
+
Extends ContextEngine with knowledge graph memory capabilities,
|
|
5
|
+
allowing agents to store and retrieve knowledge from the graph
|
|
6
|
+
during conversations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from typing import Dict, Any, Optional, List, TYPE_CHECKING
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
|
|
13
|
+
from aiecs.infrastructure.graph_storage.base import GraphStore
|
|
14
|
+
from aiecs.domain.knowledge_graph.models.entity import Entity
|
|
15
|
+
from aiecs.domain.knowledge_graph.models.relation import Relation
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from aiecs.infrastructure.graph_storage.protocols import GraphMemoryMixinProtocol
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GraphMemoryMixin:
|
|
24
|
+
"""
|
|
25
|
+
Mixin to add graph memory capabilities to ContextEngine.
|
|
26
|
+
|
|
27
|
+
This mixin extends ContextEngine with methods to:
|
|
28
|
+
- Store knowledge entities and relations
|
|
29
|
+
- Retrieve knowledge based on context
|
|
30
|
+
- Link conversation to knowledge graph
|
|
31
|
+
- Maintain graph-based conversation context
|
|
32
|
+
|
|
33
|
+
This mixin expects the class it's mixed into to implement `GraphMemoryMixinProtocol`,
|
|
34
|
+
specifically the `graph_store` attribute.
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
class ContextEngineWithGraph(ContextEngine, GraphMemoryMixin):
|
|
38
|
+
def __init__(self, graph_store: GraphStore, ...):
|
|
39
|
+
super().__init__(...)
|
|
40
|
+
self.graph_store = graph_store
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
# Type hint for mypy: this mixin expects GraphMemoryMixinProtocol
|
|
45
|
+
graph_store: Optional[GraphStore]
|
|
46
|
+
|
|
47
|
+
async def store_knowledge(
|
|
48
|
+
self,
|
|
49
|
+
session_id: str,
|
|
50
|
+
entity: Entity,
|
|
51
|
+
relations: Optional[List[Relation]] = None,
|
|
52
|
+
link_to_session: bool = True,
|
|
53
|
+
) -> bool:
|
|
54
|
+
"""
|
|
55
|
+
Store knowledge entity (and optional relations) to the graph.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
session_id: Session identifier
|
|
59
|
+
entity: Entity to store
|
|
60
|
+
relations: Optional list of relations involving this entity
|
|
61
|
+
link_to_session: Whether to create a relation linking entity to session
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
True if stored successfully, False otherwise
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
# Store a new person entity from conversation
|
|
68
|
+
person = Entity(
|
|
69
|
+
id="person_123",
|
|
70
|
+
entity_type="Person",
|
|
71
|
+
properties={"name": "Alice", "role": "Engineer"}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
await context_engine.store_knowledge(
|
|
75
|
+
session_id="session_1",
|
|
76
|
+
entity=person,
|
|
77
|
+
link_to_session=True
|
|
78
|
+
)
|
|
79
|
+
"""
|
|
80
|
+
if not hasattr(self, "graph_store") or self.graph_store is None:
|
|
81
|
+
logger.warning("GraphStore not available, cannot store knowledge")
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# Store entity
|
|
86
|
+
await self.graph_store.add_entity(entity)
|
|
87
|
+
logger.debug(f"Stored entity {entity.id} to graph")
|
|
88
|
+
|
|
89
|
+
# Store relations if provided
|
|
90
|
+
if relations:
|
|
91
|
+
for relation in relations:
|
|
92
|
+
await self.graph_store.add_relation(relation)
|
|
93
|
+
logger.debug(f"Stored {len(relations)} relations to graph")
|
|
94
|
+
|
|
95
|
+
# Link entity to session if requested
|
|
96
|
+
if link_to_session:
|
|
97
|
+
session_entity_id = f"session_{session_id}"
|
|
98
|
+
|
|
99
|
+
# Create session entity if it doesn't exist
|
|
100
|
+
session_entity = await self.graph_store.get_entity(session_entity_id)
|
|
101
|
+
if not session_entity:
|
|
102
|
+
session_entity = Entity(
|
|
103
|
+
id=session_entity_id,
|
|
104
|
+
entity_type="Session",
|
|
105
|
+
properties={
|
|
106
|
+
"session_id": session_id,
|
|
107
|
+
"created_at": datetime.utcnow().isoformat(),
|
|
108
|
+
},
|
|
109
|
+
)
|
|
110
|
+
await self.graph_store.add_entity(session_entity)
|
|
111
|
+
|
|
112
|
+
# Create MENTIONED_IN relation
|
|
113
|
+
relation = Relation(
|
|
114
|
+
id=f"mention_{entity.id}_{session_id}_{datetime.utcnow().timestamp()}",
|
|
115
|
+
source_id=entity.id,
|
|
116
|
+
target_id=session_entity_id,
|
|
117
|
+
relation_type="MENTIONED_IN",
|
|
118
|
+
properties={"timestamp": datetime.utcnow().isoformat()},
|
|
119
|
+
)
|
|
120
|
+
await self.graph_store.add_relation(relation)
|
|
121
|
+
logger.debug(f"Linked entity {entity.id} to session {session_id}")
|
|
122
|
+
|
|
123
|
+
return True
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.error(f"Failed to store knowledge: {e}")
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
async def retrieve_knowledge(
|
|
130
|
+
self,
|
|
131
|
+
session_id: str,
|
|
132
|
+
query: Optional[str] = None,
|
|
133
|
+
entity_types: Optional[List[str]] = None,
|
|
134
|
+
limit: int = 10,
|
|
135
|
+
include_session_context: bool = True,
|
|
136
|
+
) -> List[Entity]:
|
|
137
|
+
"""
|
|
138
|
+
Retrieve knowledge entities relevant to the session and/or query.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
session_id: Session identifier
|
|
142
|
+
query: Optional search query (uses embedding if available)
|
|
143
|
+
entity_types: Optional filter by entity types
|
|
144
|
+
limit: Maximum number of entities to retrieve
|
|
145
|
+
include_session_context: Whether to include entities mentioned in this session
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
List of relevant entities
|
|
149
|
+
|
|
150
|
+
Example:
|
|
151
|
+
# Retrieve people mentioned in this session
|
|
152
|
+
people = await context_engine.retrieve_knowledge(
|
|
153
|
+
session_id="session_1",
|
|
154
|
+
entity_types=["Person"],
|
|
155
|
+
limit=5
|
|
156
|
+
)
|
|
157
|
+
"""
|
|
158
|
+
if not hasattr(self, "graph_store") or self.graph_store is None:
|
|
159
|
+
logger.warning("GraphStore not available, cannot retrieve knowledge")
|
|
160
|
+
return []
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
entities = []
|
|
164
|
+
seen = set()
|
|
165
|
+
|
|
166
|
+
# 1. Get session-specific entities if requested
|
|
167
|
+
if include_session_context:
|
|
168
|
+
session_entities = await self._get_session_entities(session_id)
|
|
169
|
+
for entity in session_entities:
|
|
170
|
+
if entity.id not in seen:
|
|
171
|
+
seen.add(entity.id)
|
|
172
|
+
entities.append(entity)
|
|
173
|
+
|
|
174
|
+
# 2. If query provided, use embedding-based search (if available)
|
|
175
|
+
if query and len(entities) < limit:
|
|
176
|
+
remaining_limit = limit - len(entities)
|
|
177
|
+
|
|
178
|
+
# Try embedding-based search first
|
|
179
|
+
query_embedding = await self._generate_query_embedding(query)
|
|
180
|
+
|
|
181
|
+
if query_embedding:
|
|
182
|
+
# Use vector search with embedding
|
|
183
|
+
try:
|
|
184
|
+
# Handle entity_types: vector_search takes single entity_type
|
|
185
|
+
# If multiple types specified, search each separately and combine
|
|
186
|
+
vector_results = []
|
|
187
|
+
|
|
188
|
+
if entity_types:
|
|
189
|
+
# Search each entity type separately
|
|
190
|
+
for entity_type in entity_types:
|
|
191
|
+
type_results = await self.graph_store.vector_search(
|
|
192
|
+
query_embedding=query_embedding,
|
|
193
|
+
entity_type=entity_type,
|
|
194
|
+
max_results=remaining_limit,
|
|
195
|
+
score_threshold=0.0,
|
|
196
|
+
)
|
|
197
|
+
vector_results.extend(type_results)
|
|
198
|
+
else:
|
|
199
|
+
# No entity type filter - search all
|
|
200
|
+
vector_results = await self.graph_store.vector_search(
|
|
201
|
+
query_embedding=query_embedding,
|
|
202
|
+
entity_type=None,
|
|
203
|
+
max_results=remaining_limit,
|
|
204
|
+
score_threshold=0.0,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Extract entities from (entity, score) tuples
|
|
208
|
+
for entity, score in vector_results:
|
|
209
|
+
if entity.id not in seen:
|
|
210
|
+
seen.add(entity.id)
|
|
211
|
+
entities.append(entity)
|
|
212
|
+
if len(entities) >= limit:
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
logger.debug(f"Retrieved {len(vector_results)} entities via vector search")
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
logger.warning(f"Vector search failed: {e}, falling back to text search")
|
|
219
|
+
# Fallback to text search below
|
|
220
|
+
query_embedding = None
|
|
221
|
+
|
|
222
|
+
# Fallback to text search if embeddings unavailable or vector search failed
|
|
223
|
+
if not query_embedding and len(entities) < limit:
|
|
224
|
+
remaining_limit = limit - len(entities)
|
|
225
|
+
try:
|
|
226
|
+
# Handle entity_types: text_search takes single entity_type
|
|
227
|
+
text_results = []
|
|
228
|
+
|
|
229
|
+
if entity_types:
|
|
230
|
+
# Search each entity type separately
|
|
231
|
+
for entity_type in entity_types:
|
|
232
|
+
type_results = await self.graph_store.text_search(
|
|
233
|
+
query_text=query,
|
|
234
|
+
entity_type=entity_type,
|
|
235
|
+
max_results=remaining_limit,
|
|
236
|
+
score_threshold=0.0,
|
|
237
|
+
)
|
|
238
|
+
text_results.extend(type_results)
|
|
239
|
+
else:
|
|
240
|
+
# No entity type filter - search all
|
|
241
|
+
text_results = await self.graph_store.text_search(
|
|
242
|
+
query_text=query,
|
|
243
|
+
entity_type=None,
|
|
244
|
+
max_results=remaining_limit,
|
|
245
|
+
score_threshold=0.0,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Extract entities from (entity, score) tuples
|
|
249
|
+
for entity, score in text_results:
|
|
250
|
+
if entity.id not in seen:
|
|
251
|
+
seen.add(entity.id)
|
|
252
|
+
entities.append(entity)
|
|
253
|
+
if len(entities) >= limit:
|
|
254
|
+
break
|
|
255
|
+
|
|
256
|
+
logger.debug(f"Retrieved {len(text_results)} entities via text search")
|
|
257
|
+
|
|
258
|
+
except Exception as e:
|
|
259
|
+
logger.warning(f"Text search also failed: {e}")
|
|
260
|
+
|
|
261
|
+
# 3. Filter by entity types if specified (for session entities that weren't filtered)
|
|
262
|
+
if entity_types:
|
|
263
|
+
entities = [e for e in entities if e.entity_type in entity_types]
|
|
264
|
+
|
|
265
|
+
return entities[:limit]
|
|
266
|
+
|
|
267
|
+
except Exception as e:
|
|
268
|
+
logger.error(f"Failed to retrieve knowledge: {e}")
|
|
269
|
+
return []
|
|
270
|
+
|
|
271
|
+
async def _generate_query_embedding(self, query: str) -> Optional[List[float]]:
|
|
272
|
+
"""
|
|
273
|
+
Generate embedding for query text using available embedding service.
|
|
274
|
+
|
|
275
|
+
Checks if the class has an llm_client attribute that supports get_embeddings.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
query: Query text to embed
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Embedding vector or None if unavailable
|
|
282
|
+
"""
|
|
283
|
+
try:
|
|
284
|
+
# Check if class has llm_client attribute
|
|
285
|
+
if not hasattr(self, "llm_client") or self.llm_client is None:
|
|
286
|
+
logger.debug("No llm_client available for embedding generation")
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
# Check if llm_client supports get_embeddings
|
|
290
|
+
if not hasattr(self.llm_client, "get_embeddings"):
|
|
291
|
+
logger.debug(f"LLM client ({type(self.llm_client).__name__}) does not support embeddings")
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
# Verify the method is callable
|
|
295
|
+
get_embeddings_method = getattr(self.llm_client, "get_embeddings", None)
|
|
296
|
+
if not callable(get_embeddings_method):
|
|
297
|
+
logger.debug(f"LLM client has 'get_embeddings' attribute but it's not callable")
|
|
298
|
+
return None
|
|
299
|
+
|
|
300
|
+
# Generate embedding
|
|
301
|
+
embeddings = await self.llm_client.get_embeddings(
|
|
302
|
+
texts=[query],
|
|
303
|
+
model=None, # Use default embedding model
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
if embeddings and len(embeddings) > 0 and embeddings[0]:
|
|
307
|
+
logger.debug(f"Generated query embedding (dimension: {len(embeddings[0])})")
|
|
308
|
+
return embeddings[0]
|
|
309
|
+
|
|
310
|
+
return None
|
|
311
|
+
|
|
312
|
+
except NotImplementedError:
|
|
313
|
+
logger.debug("Embedding generation not implemented for this LLM client")
|
|
314
|
+
return None
|
|
315
|
+
except Exception as e:
|
|
316
|
+
logger.warning(f"Failed to generate query embedding: {e}")
|
|
317
|
+
return None
|
|
318
|
+
|
|
319
|
+
async def _get_session_entities(self, session_id: str) -> List[Entity]:
|
|
320
|
+
"""Get all entities mentioned in this session."""
|
|
321
|
+
if self.graph_store is None:
|
|
322
|
+
return []
|
|
323
|
+
try:
|
|
324
|
+
session_entity_id = f"session_{session_id}"
|
|
325
|
+
|
|
326
|
+
# Get session entity
|
|
327
|
+
session_entity = await self.graph_store.get_entity(session_entity_id)
|
|
328
|
+
if not session_entity:
|
|
329
|
+
return []
|
|
330
|
+
|
|
331
|
+
# Get all entities with MENTIONED_IN relation to this session
|
|
332
|
+
# Note: We need to traverse backwards from session to entities
|
|
333
|
+
# get_neighbors only accepts single relation_type, not a list
|
|
334
|
+
# neighbors = await self.graph_store.get_neighbors(
|
|
335
|
+
# session_entity_id,
|
|
336
|
+
# relation_type="MENTIONED_IN",
|
|
337
|
+
# direction="incoming" # Get entities that point TO the session
|
|
338
|
+
# ) # Reserved for future use
|
|
339
|
+
|
|
340
|
+
# Neighbors are entities that have MENTIONED_IN relation to session
|
|
341
|
+
# We need to get entities that point TO the session
|
|
342
|
+
# This requires iterating through all entities (not ideal, but
|
|
343
|
+
# functional)
|
|
344
|
+
|
|
345
|
+
# For now, return empty - proper implementation would require
|
|
346
|
+
# inverse index or traversal from session
|
|
347
|
+
# This is a simplified implementation
|
|
348
|
+
return []
|
|
349
|
+
|
|
350
|
+
except Exception as e:
|
|
351
|
+
logger.error(f"Failed to get session entities: {e}")
|
|
352
|
+
return []
|
|
353
|
+
|
|
354
|
+
async def add_graph_conversation_context(
|
|
355
|
+
self,
|
|
356
|
+
session_id: str,
|
|
357
|
+
entity_ids: List[str],
|
|
358
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
359
|
+
) -> bool:
|
|
360
|
+
"""
|
|
361
|
+
Add graph-based context to conversation.
|
|
362
|
+
|
|
363
|
+
Links specific entities to the current conversation session,
|
|
364
|
+
providing additional context for the agent.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
session_id: Session identifier
|
|
368
|
+
entity_ids: List of entity IDs to link to session
|
|
369
|
+
metadata: Optional metadata about the context
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
True if successful, False otherwise
|
|
373
|
+
|
|
374
|
+
Example:
|
|
375
|
+
# Add context entities to conversation
|
|
376
|
+
await context_engine.add_graph_conversation_context(
|
|
377
|
+
session_id="session_1",
|
|
378
|
+
entity_ids=["person_alice", "company_techcorp"],
|
|
379
|
+
metadata={"context_type": "background_knowledge"}
|
|
380
|
+
)
|
|
381
|
+
"""
|
|
382
|
+
if not hasattr(self, "graph_store") or self.graph_store is None:
|
|
383
|
+
logger.warning("GraphStore not available, cannot add graph context")
|
|
384
|
+
return False
|
|
385
|
+
|
|
386
|
+
try:
|
|
387
|
+
session_entity_id = f"session_{session_id}"
|
|
388
|
+
|
|
389
|
+
# Ensure session entity exists
|
|
390
|
+
session_entity = await self.graph_store.get_entity(session_entity_id)
|
|
391
|
+
if not session_entity:
|
|
392
|
+
session_entity = Entity(
|
|
393
|
+
id=session_entity_id,
|
|
394
|
+
entity_type="Session",
|
|
395
|
+
properties={
|
|
396
|
+
"session_id": session_id,
|
|
397
|
+
"created_at": datetime.utcnow().isoformat(),
|
|
398
|
+
},
|
|
399
|
+
)
|
|
400
|
+
await self.graph_store.add_entity(session_entity)
|
|
401
|
+
|
|
402
|
+
# Link each entity to session
|
|
403
|
+
for entity_id in entity_ids:
|
|
404
|
+
# Verify entity exists
|
|
405
|
+
entity = await self.graph_store.get_entity(entity_id)
|
|
406
|
+
if not entity:
|
|
407
|
+
logger.warning(f"Entity {entity_id} not found, skipping")
|
|
408
|
+
continue
|
|
409
|
+
|
|
410
|
+
# Create CONTEXT_FOR relation
|
|
411
|
+
relation = Relation(
|
|
412
|
+
id=f"context_{entity_id}_{session_id}_{datetime.utcnow().timestamp()}",
|
|
413
|
+
source_id=entity_id,
|
|
414
|
+
target_id=session_entity_id,
|
|
415
|
+
relation_type="CONTEXT_FOR",
|
|
416
|
+
properties={
|
|
417
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
418
|
+
"metadata": metadata or {},
|
|
419
|
+
},
|
|
420
|
+
)
|
|
421
|
+
await self.graph_store.add_relation(relation)
|
|
422
|
+
|
|
423
|
+
logger.info(f"Added {len(entity_ids)} entities as context for session {session_id}")
|
|
424
|
+
return True
|
|
425
|
+
|
|
426
|
+
except Exception as e:
|
|
427
|
+
logger.error(f"Failed to add graph conversation context: {e}")
|
|
428
|
+
return False
|
|
429
|
+
|
|
430
|
+
async def get_session_knowledge_graph(self, session_id: str, max_depth: int = 2) -> Dict[str, Any]:
|
|
431
|
+
"""
|
|
432
|
+
Get a subgraph of knowledge relevant to this session.
|
|
433
|
+
|
|
434
|
+
Returns entities and relations mentioned or used as context
|
|
435
|
+
in this session, up to a specified depth.
|
|
436
|
+
|
|
437
|
+
Args:
|
|
438
|
+
session_id: Session identifier
|
|
439
|
+
max_depth: Maximum depth for graph traversal
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
Dictionary with 'entities' and 'relations' lists
|
|
443
|
+
|
|
444
|
+
Example:
|
|
445
|
+
# Get knowledge graph for session
|
|
446
|
+
subgraph = await context_engine.get_session_knowledge_graph(
|
|
447
|
+
session_id="session_1",
|
|
448
|
+
max_depth=2
|
|
449
|
+
)
|
|
450
|
+
print(f"Entities: {len(subgraph['entities'])}")
|
|
451
|
+
print(f"Relations: {len(subgraph['relations'])}")
|
|
452
|
+
"""
|
|
453
|
+
if not hasattr(self, "graph_store") or self.graph_store is None:
|
|
454
|
+
logger.warning("GraphStore not available")
|
|
455
|
+
return {"entities": [], "relations": []}
|
|
456
|
+
|
|
457
|
+
try:
|
|
458
|
+
session_entity_id = f"session_{session_id}"
|
|
459
|
+
|
|
460
|
+
# Get session entity
|
|
461
|
+
session_entity = await self.graph_store.get_entity(session_entity_id)
|
|
462
|
+
if not session_entity:
|
|
463
|
+
return {"entities": [], "relations": []}
|
|
464
|
+
|
|
465
|
+
entities = [session_entity]
|
|
466
|
+
relations: List[Any] = []
|
|
467
|
+
visited = {session_entity_id}
|
|
468
|
+
|
|
469
|
+
# Traverse from session entity
|
|
470
|
+
current_level = [session_entity_id]
|
|
471
|
+
|
|
472
|
+
for depth in range(max_depth):
|
|
473
|
+
next_level = []
|
|
474
|
+
|
|
475
|
+
for entity_id in current_level:
|
|
476
|
+
# Get neighbors (check both relation types separately)
|
|
477
|
+
neighbors_mentioned = await self.graph_store.get_neighbors(
|
|
478
|
+
entity_id,
|
|
479
|
+
relation_type="MENTIONED_IN",
|
|
480
|
+
direction="both",
|
|
481
|
+
)
|
|
482
|
+
neighbors_context = await self.graph_store.get_neighbors(
|
|
483
|
+
entity_id,
|
|
484
|
+
relation_type="CONTEXT_FOR",
|
|
485
|
+
direction="both",
|
|
486
|
+
)
|
|
487
|
+
# Combine and deduplicate
|
|
488
|
+
neighbors = list({n.id: n for n in neighbors_mentioned + neighbors_context}.values())
|
|
489
|
+
|
|
490
|
+
for neighbor in neighbors:
|
|
491
|
+
if neighbor.id not in visited:
|
|
492
|
+
visited.add(neighbor.id)
|
|
493
|
+
entities.append(neighbor)
|
|
494
|
+
next_level.append(neighbor.id)
|
|
495
|
+
|
|
496
|
+
# Note: In a complete implementation, we'd also collect
|
|
497
|
+
# the relations between entities here
|
|
498
|
+
|
|
499
|
+
current_level = next_level
|
|
500
|
+
if not current_level:
|
|
501
|
+
break
|
|
502
|
+
|
|
503
|
+
return {
|
|
504
|
+
"entities": [e.model_dump() for e in entities],
|
|
505
|
+
"relations": relations, # Would be populated in full implementation
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
except Exception as e:
|
|
509
|
+
logger.error(f"Failed to get session knowledge graph: {e}")
|
|
510
|
+
return {"entities": [], "relations": []}
|
|
511
|
+
|
|
512
|
+
async def clear_session_knowledge(self, session_id: str, remove_entities: bool = False) -> bool:
|
|
513
|
+
"""
|
|
514
|
+
Clear knowledge graph associations for a session.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
session_id: Session identifier
|
|
518
|
+
remove_entities: If True, also remove the session entity itself
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
True if successful, False otherwise
|
|
522
|
+
"""
|
|
523
|
+
if not hasattr(self, "graph_store") or self.graph_store is None:
|
|
524
|
+
logger.warning("GraphStore not available")
|
|
525
|
+
return False
|
|
526
|
+
|
|
527
|
+
try:
|
|
528
|
+
session_entity_id = f"session_{session_id}"
|
|
529
|
+
|
|
530
|
+
if remove_entities:
|
|
531
|
+
# Check if delete_entity method exists (SQLite has it, InMemory
|
|
532
|
+
# might not)
|
|
533
|
+
if hasattr(self.graph_store, "delete_entity"):
|
|
534
|
+
await self.graph_store.delete_entity(session_entity_id)
|
|
535
|
+
logger.info(f"Removed session entity {session_entity_id}")
|
|
536
|
+
else:
|
|
537
|
+
# For InMemoryGraphStore, we can't easily delete entities
|
|
538
|
+
# Just log a warning
|
|
539
|
+
logger.warning(f"delete_entity not available for {type(self.graph_store).__name__}, " f"session entity {session_entity_id} not removed")
|
|
540
|
+
|
|
541
|
+
return True
|
|
542
|
+
|
|
543
|
+
except Exception as e:
|
|
544
|
+
logger.error(f"Failed to clear session knowledge: {e}")
|
|
545
|
+
return False
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class ContextEngineWithGraph(GraphMemoryMixin):
|
|
549
|
+
"""
|
|
550
|
+
ContextEngine extended with graph memory capabilities.
|
|
551
|
+
|
|
552
|
+
This class can be used as a standalone context engine with graph support,
|
|
553
|
+
or as a mixin to extend existing ContextEngine instances.
|
|
554
|
+
|
|
555
|
+
Example:
|
|
556
|
+
from aiecs.domain.context import ContextEngine
|
|
557
|
+
from aiecs.domain.context.graph_memory import ContextEngineWithGraph
|
|
558
|
+
from aiecs.infrastructure.graph_storage import InMemoryGraphStore
|
|
559
|
+
|
|
560
|
+
# Create graph store
|
|
561
|
+
graph_store = InMemoryGraphStore()
|
|
562
|
+
await graph_store.initialize()
|
|
563
|
+
|
|
564
|
+
# Create context engine with graph support
|
|
565
|
+
# Note: Actual usage would involve proper inheritance or composition
|
|
566
|
+
context_engine = ContextEngine()
|
|
567
|
+
context_engine.graph_store = graph_store
|
|
568
|
+
await context_engine.initialize()
|
|
569
|
+
|
|
570
|
+
# Now you can use graph memory methods
|
|
571
|
+
await context_engine.store_knowledge(session_id, entity)
|
|
572
|
+
"""
|
|
573
|
+
|
|
574
|
+
def __init__(self, graph_store: Optional[GraphStore] = None):
|
|
575
|
+
"""
|
|
576
|
+
Initialize with optional graph store.
|
|
577
|
+
|
|
578
|
+
Args:
|
|
579
|
+
graph_store: Optional knowledge graph store
|
|
580
|
+
"""
|
|
581
|
+
self.graph_store = graph_store
|
|
582
|
+
logger.info(f"ContextEngineWithGraph initialized with graph_store=" f"{'enabled' if graph_store else 'disabled'}")
|
aiecs/domain/execution/model.py
CHANGED
|
@@ -23,9 +23,17 @@ class ErrorCode(Enum):
|
|
|
23
23
|
|
|
24
24
|
class TaskStepResult:
|
|
25
25
|
"""Task step result model"""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
step: str,
|
|
30
|
+
result: Any,
|
|
31
|
+
completed: bool = False,
|
|
32
|
+
message: str = "",
|
|
33
|
+
status: str = "pending",
|
|
34
|
+
error_code: Optional[str] = None,
|
|
35
|
+
error_message: Optional[str] = None,
|
|
36
|
+
):
|
|
29
37
|
self.step = step
|
|
30
38
|
self.result = result
|
|
31
39
|
self.completed = completed
|
|
@@ -42,7 +50,7 @@ class TaskStepResult:
|
|
|
42
50
|
"message": self.message,
|
|
43
51
|
"status": self.status,
|
|
44
52
|
"error_code": self.error_code,
|
|
45
|
-
"error_message": self.error_message
|
|
53
|
+
"error_message": self.error_message,
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
def __repr__(self) -> str:
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Knowledge Graph Domain Layer
|
|
3
|
+
|
|
4
|
+
This module contains the domain models and business logic for the knowledge graph capability.
|
|
5
|
+
It provides entity models, relation models, schema definitions, and graph query abstractions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from aiecs.domain.knowledge_graph.models.entity import Entity
|
|
9
|
+
from aiecs.domain.knowledge_graph.models.relation import Relation
|
|
10
|
+
from aiecs.domain.knowledge_graph.models.path import Path
|
|
11
|
+
from aiecs.domain.knowledge_graph.models.query import GraphQuery, GraphResult
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Entity",
|
|
15
|
+
"Relation",
|
|
16
|
+
"Path",
|
|
17
|
+
"GraphQuery",
|
|
18
|
+
"GraphResult",
|
|
19
|
+
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Knowledge Graph Domain Models
|
|
3
|
+
|
|
4
|
+
Core domain models for knowledge graph entities, relations, and queries.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from aiecs.domain.knowledge_graph.models.entity import Entity
|
|
8
|
+
from aiecs.domain.knowledge_graph.models.relation import Relation
|
|
9
|
+
from aiecs.domain.knowledge_graph.models.path import Path
|
|
10
|
+
from aiecs.domain.knowledge_graph.models.path_pattern import (
|
|
11
|
+
PathPattern,
|
|
12
|
+
TraversalDirection,
|
|
13
|
+
)
|
|
14
|
+
from aiecs.domain.knowledge_graph.models.query import GraphQuery, GraphResult
|
|
15
|
+
from aiecs.domain.knowledge_graph.models.query_plan import (
|
|
16
|
+
QueryPlan,
|
|
17
|
+
QueryStep,
|
|
18
|
+
QueryOperation,
|
|
19
|
+
OptimizationStrategy,
|
|
20
|
+
)
|
|
21
|
+
from aiecs.domain.knowledge_graph.models.evidence import (
|
|
22
|
+
Evidence,
|
|
23
|
+
EvidenceType,
|
|
24
|
+
ReasoningResult,
|
|
25
|
+
)
|
|
26
|
+
from aiecs.domain.knowledge_graph.models.inference_rule import (
|
|
27
|
+
InferenceRule,
|
|
28
|
+
InferenceStep,
|
|
29
|
+
InferenceResult,
|
|
30
|
+
RuleType,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"Entity",
|
|
35
|
+
"Relation",
|
|
36
|
+
"Path",
|
|
37
|
+
"PathPattern",
|
|
38
|
+
"TraversalDirection",
|
|
39
|
+
"GraphQuery",
|
|
40
|
+
"GraphResult",
|
|
41
|
+
"QueryPlan",
|
|
42
|
+
"QueryStep",
|
|
43
|
+
"QueryOperation",
|
|
44
|
+
"OptimizationStrategy",
|
|
45
|
+
"Evidence",
|
|
46
|
+
"EvidenceType",
|
|
47
|
+
"ReasoningResult",
|
|
48
|
+
"InferenceRule",
|
|
49
|
+
"InferenceStep",
|
|
50
|
+
"InferenceResult",
|
|
51
|
+
"RuleType",
|
|
52
|
+
]
|