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,202 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Relation Domain Model
|
|
3
|
+
|
|
4
|
+
Represents an edge/relationship between two entities in the knowledge graph.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
10
|
+
|
|
11
|
+
from aiecs.infrastructure.graph_storage.tenant import validate_tenant_id, InvalidTenantIdError, CrossTenantRelationError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Relation(BaseModel):
|
|
15
|
+
"""
|
|
16
|
+
Knowledge Graph Relation
|
|
17
|
+
|
|
18
|
+
Represents a directed edge between two entities in the knowledge graph.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
id: Unique identifier for the relation
|
|
22
|
+
relation_type: Type of relation (e.g., "WORKS_FOR", "KNOWS")
|
|
23
|
+
source_id: ID of the source entity
|
|
24
|
+
target_id: ID of the target entity
|
|
25
|
+
properties: Additional properties of the relation
|
|
26
|
+
weight: Optional weight/strength of the relation (0.0-1.0)
|
|
27
|
+
created_at: Creation timestamp
|
|
28
|
+
source: Source of the relation data
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
```python
|
|
32
|
+
relation = Relation(
|
|
33
|
+
id="rel_001",
|
|
34
|
+
relation_type="WORKS_FOR",
|
|
35
|
+
source_id="person_001",
|
|
36
|
+
target_id="company_001",
|
|
37
|
+
properties={"role": "Engineer", "since": "2020-01-01"},
|
|
38
|
+
weight=1.0
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
id: str = Field(..., description="Unique identifier for the relation")
|
|
44
|
+
|
|
45
|
+
relation_type: str = Field(..., description="Type of the relation (e.g., 'WORKS_FOR', 'KNOWS')")
|
|
46
|
+
|
|
47
|
+
source_id: str = Field(..., description="ID of the source entity")
|
|
48
|
+
|
|
49
|
+
target_id: str = Field(..., description="ID of the target entity")
|
|
50
|
+
|
|
51
|
+
properties: dict[str, Any] = Field(
|
|
52
|
+
default_factory=dict,
|
|
53
|
+
description="Additional properties of the relation",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
weight: float = Field(
|
|
57
|
+
default=1.0,
|
|
58
|
+
ge=0.0,
|
|
59
|
+
le=1.0,
|
|
60
|
+
description="Weight/strength of the relation (0.0-1.0)",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
created_at: datetime = Field(
|
|
64
|
+
default_factory=datetime.utcnow,
|
|
65
|
+
description="Timestamp when relation was created",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
source: Optional[str] = Field(default=None, description="Source of the relation data")
|
|
69
|
+
|
|
70
|
+
tenant_id: Optional[str] = Field(
|
|
71
|
+
default=None,
|
|
72
|
+
description="Tenant identifier for multi-tenant isolation (alphanumeric, hyphens, underscores only)",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
class Config:
|
|
76
|
+
json_encoders = {datetime: lambda v: v.isoformat()}
|
|
77
|
+
|
|
78
|
+
@field_validator("source_id", "target_id")
|
|
79
|
+
@classmethod
|
|
80
|
+
def validate_entity_ids(cls, v: str) -> str:
|
|
81
|
+
"""Validate entity IDs are non-empty"""
|
|
82
|
+
if not v or not v.strip():
|
|
83
|
+
raise ValueError("Entity IDs must be non-empty strings")
|
|
84
|
+
return v
|
|
85
|
+
|
|
86
|
+
@field_validator("source_id")
|
|
87
|
+
@classmethod
|
|
88
|
+
def validate_no_self_loop(cls, v: str, info) -> str:
|
|
89
|
+
"""Prevent self-loops (optional validation)"""
|
|
90
|
+
# Note: We allow self-loops for now, but this validator can be enabled if needed
|
|
91
|
+
# if info.data.get('target_id') and v == info.data['target_id']:
|
|
92
|
+
# raise ValueError("Self-loops are not allowed (source_id == target_id)")
|
|
93
|
+
return v
|
|
94
|
+
|
|
95
|
+
@model_validator(mode="before")
|
|
96
|
+
@classmethod
|
|
97
|
+
def validate_tenant_id_before(cls, data: Any) -> Any:
|
|
98
|
+
"""Validate tenant_id format before model creation"""
|
|
99
|
+
# Pydantic converts keyword arguments to dict before calling model_validator
|
|
100
|
+
if isinstance(data, dict):
|
|
101
|
+
tenant_id = data.get("tenant_id")
|
|
102
|
+
if tenant_id is not None:
|
|
103
|
+
# Validate and raise InvalidTenantIdError directly
|
|
104
|
+
# Note: Pydantic will wrap this in ValidationError, but the error info is preserved
|
|
105
|
+
validate_tenant_id(tenant_id)
|
|
106
|
+
return data
|
|
107
|
+
|
|
108
|
+
def validate_tenant_consistency(self, source_entity_tenant_id: Optional[str], target_entity_tenant_id: Optional[str]) -> Optional[str]:
|
|
109
|
+
"""
|
|
110
|
+
Validate that relation tenant_id matches source and target entity tenant_ids.
|
|
111
|
+
|
|
112
|
+
This should be called when creating a relation to ensure tenant isolation.
|
|
113
|
+
Returns the effective tenant_id that should be used for this relation.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
source_entity_tenant_id: Tenant ID of the source entity
|
|
117
|
+
target_entity_tenant_id: Tenant ID of the target entity
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The effective tenant_id for this relation (relation's tenant_id if set,
|
|
121
|
+
otherwise inferred from entities). Callers should use this value to
|
|
122
|
+
set the relation's tenant_id if needed.
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
CrossTenantRelationError: If tenant IDs don't match
|
|
126
|
+
"""
|
|
127
|
+
# If relation has tenant_id, it must match both entities
|
|
128
|
+
if self.tenant_id is not None:
|
|
129
|
+
if source_entity_tenant_id != self.tenant_id:
|
|
130
|
+
raise CrossTenantRelationError(source_entity_tenant_id, self.tenant_id)
|
|
131
|
+
if target_entity_tenant_id != self.tenant_id:
|
|
132
|
+
raise CrossTenantRelationError(self.tenant_id, target_entity_tenant_id)
|
|
133
|
+
|
|
134
|
+
# Both entities must have the same tenant_id (or both None)
|
|
135
|
+
if source_entity_tenant_id != target_entity_tenant_id:
|
|
136
|
+
raise CrossTenantRelationError(source_entity_tenant_id, target_entity_tenant_id)
|
|
137
|
+
|
|
138
|
+
# Return the effective tenant_id (relation's own or inferred from entities)
|
|
139
|
+
# Callers can use this to set the relation's tenant_id if needed
|
|
140
|
+
return self.tenant_id if self.tenant_id is not None else source_entity_tenant_id
|
|
141
|
+
|
|
142
|
+
def with_tenant_id(self, tenant_id: Optional[str]) -> "Relation":
|
|
143
|
+
"""
|
|
144
|
+
Create a copy of this relation with a new tenant_id.
|
|
145
|
+
|
|
146
|
+
This is the Pydantic-idiomatic way to create a modified copy
|
|
147
|
+
without mutating the original instance.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
tenant_id: The tenant_id to set on the new relation
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
A new Relation instance with the updated tenant_id
|
|
154
|
+
"""
|
|
155
|
+
return self.model_copy(update={"tenant_id": tenant_id})
|
|
156
|
+
|
|
157
|
+
def get_property(self, key: str, default: Any = None) -> Any:
|
|
158
|
+
"""
|
|
159
|
+
Get a specific property value
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
key: Property key
|
|
163
|
+
default: Default value if key not found
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Property value or default
|
|
167
|
+
"""
|
|
168
|
+
return self.properties.get(key, default)
|
|
169
|
+
|
|
170
|
+
def set_property(self, key: str, value: Any) -> None:
|
|
171
|
+
"""
|
|
172
|
+
Set a property value
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
key: Property key
|
|
176
|
+
value: Property value
|
|
177
|
+
"""
|
|
178
|
+
self.properties[key] = value
|
|
179
|
+
|
|
180
|
+
def reverse(self) -> "Relation":
|
|
181
|
+
"""
|
|
182
|
+
Create a reversed relation (swap source and target)
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
New Relation with swapped source and target
|
|
186
|
+
"""
|
|
187
|
+
return Relation(
|
|
188
|
+
id=f"{self.id}_reversed",
|
|
189
|
+
relation_type=f"{self.relation_type}_REVERSE",
|
|
190
|
+
source_id=self.target_id,
|
|
191
|
+
target_id=self.source_id,
|
|
192
|
+
properties=self.properties.copy(),
|
|
193
|
+
weight=self.weight,
|
|
194
|
+
created_at=self.created_at,
|
|
195
|
+
source=self.source,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def __str__(self) -> str:
|
|
199
|
+
return f"Relation({self.source_id} -[{self.relation_type}]-> {self.target_id})"
|
|
200
|
+
|
|
201
|
+
def __repr__(self) -> str:
|
|
202
|
+
return f"Relation(id='{self.id}', type='{self.relation_type}', " f"source='{self.source_id}', target='{self.target_id}', weight={self.weight})"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Knowledge Graph Schema Management
|
|
3
|
+
|
|
4
|
+
Schema definitions for entity types, relation types, and properties.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from aiecs.domain.knowledge_graph.schema.property_schema import (
|
|
8
|
+
PropertySchema,
|
|
9
|
+
PropertyType,
|
|
10
|
+
)
|
|
11
|
+
from aiecs.domain.knowledge_graph.schema.entity_type import EntityType
|
|
12
|
+
from aiecs.domain.knowledge_graph.schema.relation_type import RelationType
|
|
13
|
+
from aiecs.domain.knowledge_graph.schema.graph_schema import GraphSchema
|
|
14
|
+
from aiecs.domain.knowledge_graph.schema.schema_manager import SchemaManager
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"PropertySchema",
|
|
18
|
+
"PropertyType",
|
|
19
|
+
"EntityType",
|
|
20
|
+
"RelationType",
|
|
21
|
+
"GraphSchema",
|
|
22
|
+
"SchemaManager",
|
|
23
|
+
]
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Entity Type Schema Definition
|
|
3
|
+
|
|
4
|
+
Defines the schema for entity types in the knowledge graph.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Optional, Any
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from aiecs.domain.knowledge_graph.schema.property_schema import PropertySchema
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EntityType(BaseModel):
|
|
13
|
+
"""
|
|
14
|
+
Entity Type Schema
|
|
15
|
+
|
|
16
|
+
Defines the schema for a type of entity in the knowledge graph,
|
|
17
|
+
including its properties and constraints.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
name: Entity type name (e.g., "Person", "Company")
|
|
21
|
+
description: Human-readable description
|
|
22
|
+
properties: Dictionary of property schemas
|
|
23
|
+
parent_type: Optional parent entity type for inheritance
|
|
24
|
+
is_abstract: Whether this is an abstract type (cannot be instantiated)
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
```python
|
|
28
|
+
person_type = EntityType(
|
|
29
|
+
name="Person",
|
|
30
|
+
description="A person entity",
|
|
31
|
+
properties={
|
|
32
|
+
"name": PropertySchema(name="name", property_type=PropertyType.STRING, required=True),
|
|
33
|
+
"age": PropertySchema(name="age", property_type=PropertyType.INTEGER),
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
name: str = Field(..., description="Entity type name (must be unique)")
|
|
40
|
+
|
|
41
|
+
description: Optional[str] = Field(
|
|
42
|
+
default=None,
|
|
43
|
+
description="Human-readable description of this entity type",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
properties: Dict[str, PropertySchema] = Field(
|
|
47
|
+
default_factory=dict,
|
|
48
|
+
description="Dictionary of property schemas (key=property name)",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
parent_type: Optional[str] = Field(default=None, description="Parent entity type name for inheritance")
|
|
52
|
+
|
|
53
|
+
is_abstract: bool = Field(
|
|
54
|
+
default=False,
|
|
55
|
+
description="Whether this is an abstract type (cannot be instantiated)",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
class Config:
|
|
59
|
+
arbitrary_types_allowed = True
|
|
60
|
+
|
|
61
|
+
def add_property(self, prop: PropertySchema) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Add a property to this entity type
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
prop: Property schema to add
|
|
67
|
+
"""
|
|
68
|
+
self.properties[prop.name] = prop
|
|
69
|
+
|
|
70
|
+
def remove_property(self, property_name: str) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Remove a property from this entity type
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
property_name: Name of property to remove
|
|
76
|
+
"""
|
|
77
|
+
if property_name in self.properties:
|
|
78
|
+
del self.properties[property_name]
|
|
79
|
+
|
|
80
|
+
def get_property(self, property_name: str) -> Optional[PropertySchema]:
|
|
81
|
+
"""
|
|
82
|
+
Get a property schema by name
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
property_name: Name of property to get
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Property schema or None if not found
|
|
89
|
+
"""
|
|
90
|
+
return self.properties.get(property_name)
|
|
91
|
+
|
|
92
|
+
def validate_properties(self, properties: Dict[str, Any]) -> bool:
|
|
93
|
+
"""
|
|
94
|
+
Validate a dictionary of properties against this schema
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
properties: Dictionary of properties to validate
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
True if all properties are valid
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
ValueError: If validation fails
|
|
104
|
+
"""
|
|
105
|
+
# Check required properties
|
|
106
|
+
for prop_name, prop_schema in self.properties.items():
|
|
107
|
+
if prop_schema.required and prop_name not in properties:
|
|
108
|
+
raise ValueError(f"Required property '{prop_name}' missing for entity type '{self.name}'")
|
|
109
|
+
|
|
110
|
+
# Validate each provided property
|
|
111
|
+
for prop_name, prop_value in properties.items():
|
|
112
|
+
if prop_name in self.properties:
|
|
113
|
+
prop_schema = self.properties[prop_name]
|
|
114
|
+
prop_schema.validate_value(prop_value)
|
|
115
|
+
|
|
116
|
+
return True
|
|
117
|
+
|
|
118
|
+
def get_required_properties(self) -> List[str]:
|
|
119
|
+
"""
|
|
120
|
+
Get list of required property names
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
List of required property names
|
|
124
|
+
"""
|
|
125
|
+
return [prop.name for prop in self.properties.values() if prop.required]
|
|
126
|
+
|
|
127
|
+
def __str__(self) -> str:
|
|
128
|
+
return f"EntityType(name='{self.name}', properties={len(self.properties)})"
|
|
129
|
+
|
|
130
|
+
def __repr__(self) -> str:
|
|
131
|
+
return self.__str__()
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Graph Schema Container
|
|
3
|
+
|
|
4
|
+
Container for all entity types and relation types in the knowledge graph.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Optional
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from aiecs.domain.knowledge_graph.schema.entity_type import EntityType
|
|
10
|
+
from aiecs.domain.knowledge_graph.schema.relation_type import RelationType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GraphSchema(BaseModel):
|
|
14
|
+
"""
|
|
15
|
+
Knowledge Graph Schema
|
|
16
|
+
|
|
17
|
+
Container for all entity types and relation types in the knowledge graph.
|
|
18
|
+
Provides methods for schema management and validation.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
version: Schema version identifier
|
|
22
|
+
entity_types: Dictionary of entity type schemas
|
|
23
|
+
relation_types: Dictionary of relation type schemas
|
|
24
|
+
description: Human-readable description of the schema
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
```python
|
|
28
|
+
schema = GraphSchema(
|
|
29
|
+
version="1.0",
|
|
30
|
+
description="Company knowledge graph schema"
|
|
31
|
+
)
|
|
32
|
+
schema.add_entity_type(person_type)
|
|
33
|
+
schema.add_entity_type(company_type)
|
|
34
|
+
schema.add_relation_type(works_for_type)
|
|
35
|
+
```
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
version: str = Field(default="1.0", description="Schema version identifier")
|
|
39
|
+
|
|
40
|
+
entity_types: Dict[str, EntityType] = Field(
|
|
41
|
+
default_factory=dict,
|
|
42
|
+
description="Dictionary of entity type schemas (key=type name)",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
relation_types: Dict[str, RelationType] = Field(
|
|
46
|
+
default_factory=dict,
|
|
47
|
+
description="Dictionary of relation type schemas (key=type name)",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
description: Optional[str] = Field(default=None, description="Human-readable description of this schema")
|
|
51
|
+
|
|
52
|
+
class Config:
|
|
53
|
+
arbitrary_types_allowed = True
|
|
54
|
+
|
|
55
|
+
# Entity Type Management
|
|
56
|
+
|
|
57
|
+
def add_entity_type(self, entity_type: EntityType) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Add an entity type to the schema
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
entity_type: Entity type to add
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValueError: If entity type already exists
|
|
66
|
+
"""
|
|
67
|
+
if entity_type.name in self.entity_types:
|
|
68
|
+
raise ValueError(f"Entity type '{entity_type.name}' already exists in schema")
|
|
69
|
+
self.entity_types[entity_type.name] = entity_type
|
|
70
|
+
|
|
71
|
+
def update_entity_type(self, entity_type: EntityType) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Update an existing entity type
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
entity_type: Updated entity type
|
|
77
|
+
|
|
78
|
+
Raises:
|
|
79
|
+
ValueError: If entity type doesn't exist
|
|
80
|
+
"""
|
|
81
|
+
if entity_type.name not in self.entity_types:
|
|
82
|
+
raise ValueError(f"Entity type '{entity_type.name}' not found in schema")
|
|
83
|
+
self.entity_types[entity_type.name] = entity_type
|
|
84
|
+
|
|
85
|
+
def delete_entity_type(self, type_name: str) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Delete an entity type from the schema
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
type_name: Name of entity type to delete
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If entity type doesn't exist or is in use
|
|
94
|
+
"""
|
|
95
|
+
if type_name not in self.entity_types:
|
|
96
|
+
raise ValueError(f"Entity type '{type_name}' not found in schema")
|
|
97
|
+
|
|
98
|
+
# Check if any relation types reference this entity type
|
|
99
|
+
for rel_type in self.relation_types.values():
|
|
100
|
+
if rel_type.source_entity_types and type_name in rel_type.source_entity_types:
|
|
101
|
+
raise ValueError(f"Cannot delete entity type '{type_name}': " f"referenced by relation '{rel_type.name}' as source")
|
|
102
|
+
if rel_type.target_entity_types and type_name in rel_type.target_entity_types:
|
|
103
|
+
raise ValueError(f"Cannot delete entity type '{type_name}': " f"referenced by relation '{rel_type.name}' as target")
|
|
104
|
+
|
|
105
|
+
del self.entity_types[type_name]
|
|
106
|
+
|
|
107
|
+
def get_entity_type(self, type_name: str) -> Optional[EntityType]:
|
|
108
|
+
"""
|
|
109
|
+
Get an entity type by name
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
type_name: Name of entity type
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Entity type or None if not found
|
|
116
|
+
"""
|
|
117
|
+
return self.entity_types.get(type_name)
|
|
118
|
+
|
|
119
|
+
def has_entity_type(self, type_name: str) -> bool:
|
|
120
|
+
"""
|
|
121
|
+
Check if entity type exists
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
type_name: Name of entity type
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
True if entity type exists
|
|
128
|
+
"""
|
|
129
|
+
return type_name in self.entity_types
|
|
130
|
+
|
|
131
|
+
# Relation Type Management
|
|
132
|
+
|
|
133
|
+
def add_relation_type(self, relation_type: RelationType) -> None:
|
|
134
|
+
"""
|
|
135
|
+
Add a relation type to the schema
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
relation_type: Relation type to add
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
ValueError: If relation type already exists
|
|
142
|
+
"""
|
|
143
|
+
if relation_type.name in self.relation_types:
|
|
144
|
+
raise ValueError(f"Relation type '{relation_type.name}' already exists in schema")
|
|
145
|
+
self.relation_types[relation_type.name] = relation_type
|
|
146
|
+
|
|
147
|
+
def update_relation_type(self, relation_type: RelationType) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Update an existing relation type
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
relation_type: Updated relation type
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
ValueError: If relation type doesn't exist
|
|
156
|
+
"""
|
|
157
|
+
if relation_type.name not in self.relation_types:
|
|
158
|
+
raise ValueError(f"Relation type '{relation_type.name}' not found in schema")
|
|
159
|
+
self.relation_types[relation_type.name] = relation_type
|
|
160
|
+
|
|
161
|
+
def delete_relation_type(self, type_name: str) -> None:
|
|
162
|
+
"""
|
|
163
|
+
Delete a relation type from the schema
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
type_name: Name of relation type to delete
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
ValueError: If relation type doesn't exist
|
|
170
|
+
"""
|
|
171
|
+
if type_name not in self.relation_types:
|
|
172
|
+
raise ValueError(f"Relation type '{type_name}' not found in schema")
|
|
173
|
+
del self.relation_types[type_name]
|
|
174
|
+
|
|
175
|
+
def get_relation_type(self, type_name: str) -> Optional[RelationType]:
|
|
176
|
+
"""
|
|
177
|
+
Get a relation type by name
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
type_name: Name of relation type
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Relation type or None if not found
|
|
184
|
+
"""
|
|
185
|
+
return self.relation_types.get(type_name)
|
|
186
|
+
|
|
187
|
+
def has_relation_type(self, type_name: str) -> bool:
|
|
188
|
+
"""
|
|
189
|
+
Check if relation type exists
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
type_name: Name of relation type
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
True if relation type exists
|
|
196
|
+
"""
|
|
197
|
+
return type_name in self.relation_types
|
|
198
|
+
|
|
199
|
+
# Schema Queries
|
|
200
|
+
|
|
201
|
+
def get_entity_type_names(self) -> List[str]:
|
|
202
|
+
"""Get list of all entity type names"""
|
|
203
|
+
return list(self.entity_types.keys())
|
|
204
|
+
|
|
205
|
+
def get_relation_type_names(self) -> List[str]:
|
|
206
|
+
"""Get list of all relation type names"""
|
|
207
|
+
return list(self.relation_types.keys())
|
|
208
|
+
|
|
209
|
+
def get_entity_types_with_property(self, property_name: str) -> List[EntityType]:
|
|
210
|
+
"""
|
|
211
|
+
Get all entity types that have a specific property
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
property_name: Name of property to search for
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
List of entity types with that property
|
|
218
|
+
"""
|
|
219
|
+
return [entity_type for entity_type in self.entity_types.values() if property_name in entity_type.properties]
|
|
220
|
+
|
|
221
|
+
def get_relation_types_for_entities(self, source_type: str, target_type: str) -> List[RelationType]:
|
|
222
|
+
"""
|
|
223
|
+
Get all relation types allowed between two entity types
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
source_type: Source entity type name
|
|
227
|
+
target_type: Target entity type name
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
List of allowed relation types
|
|
231
|
+
"""
|
|
232
|
+
allowed_relations = []
|
|
233
|
+
|
|
234
|
+
for rel_type in self.relation_types.values():
|
|
235
|
+
# Check if source type is allowed
|
|
236
|
+
if rel_type.source_entity_types is not None:
|
|
237
|
+
if source_type not in rel_type.source_entity_types:
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
# Check if target type is allowed
|
|
241
|
+
if rel_type.target_entity_types is not None:
|
|
242
|
+
if target_type not in rel_type.target_entity_types:
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
allowed_relations.append(rel_type)
|
|
246
|
+
|
|
247
|
+
return allowed_relations
|
|
248
|
+
|
|
249
|
+
def __str__(self) -> str:
|
|
250
|
+
return f"GraphSchema(version='{self.version}', " f"entity_types={len(self.entity_types)}, " f"relation_types={len(self.relation_types)})"
|
|
251
|
+
|
|
252
|
+
def __repr__(self) -> str:
|
|
253
|
+
return self.__str__()
|