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
aiecs/__init__.py
CHANGED
|
@@ -5,24 +5,24 @@ A powerful Python middleware framework for building AI-powered applications
|
|
|
5
5
|
with tool orchestration, task execution, and multi-provider LLM support.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "1.
|
|
8
|
+
__version__ = "1.7.17"
|
|
9
9
|
__author__ = "AIECS Team"
|
|
10
10
|
__email__ = "iretbl@gmail.com"
|
|
11
11
|
|
|
12
12
|
# Core imports - these should work without configuration
|
|
13
|
-
from .aiecs_client import
|
|
13
|
+
from .aiecs_client import (
|
|
14
|
+
AIECS,
|
|
15
|
+
create_aiecs_client,
|
|
16
|
+
create_simple_client,
|
|
17
|
+
create_full_client,
|
|
18
|
+
)
|
|
14
19
|
from .domain.task.task_context import TaskContext
|
|
15
20
|
|
|
16
21
|
# Configuration
|
|
17
22
|
from .config.config import get_settings, validate_required_settings
|
|
18
23
|
|
|
19
24
|
# Tool system - safe to import
|
|
20
|
-
from .tools import
|
|
21
|
-
discover_tools,
|
|
22
|
-
list_tools,
|
|
23
|
-
get_tool,
|
|
24
|
-
register_tool
|
|
25
|
-
)
|
|
25
|
+
from .tools import discover_tools, list_tools, get_tool, register_tool
|
|
26
26
|
|
|
27
27
|
# Infrastructure components - can be imported safely (for advanced usage)
|
|
28
28
|
# These classes only require configuration when actually used
|
|
@@ -39,37 +39,34 @@ def get_fastapi_app():
|
|
|
39
39
|
Only loads when explicitly requested to avoid import-time configuration validation
|
|
40
40
|
"""
|
|
41
41
|
from .main import app
|
|
42
|
+
|
|
42
43
|
return app
|
|
43
44
|
|
|
45
|
+
|
|
44
46
|
__all__ = [
|
|
45
47
|
# Core API
|
|
46
48
|
"AIECS",
|
|
47
49
|
"create_aiecs_client",
|
|
48
50
|
"create_simple_client",
|
|
49
|
-
"create_full_client",
|
|
51
|
+
"create_full_client",
|
|
50
52
|
"TaskContext",
|
|
51
|
-
|
|
52
53
|
# FastAPI application (lazy loading)
|
|
53
54
|
"get_fastapi_app",
|
|
54
|
-
|
|
55
55
|
# Tool system
|
|
56
56
|
"discover_tools",
|
|
57
|
-
"list_tools",
|
|
57
|
+
"list_tools",
|
|
58
58
|
"get_tool",
|
|
59
59
|
"register_tool",
|
|
60
|
-
|
|
61
60
|
# Configuration
|
|
62
61
|
"get_settings",
|
|
63
62
|
"validate_required_settings",
|
|
64
|
-
|
|
65
63
|
# Infrastructure (advanced)
|
|
66
64
|
"DatabaseManager",
|
|
67
65
|
"CeleryTaskManager",
|
|
68
66
|
"LLMClientFactory",
|
|
69
67
|
"AIProvider",
|
|
70
|
-
|
|
71
68
|
# Metadata
|
|
72
69
|
"__version__",
|
|
73
70
|
"__author__",
|
|
74
71
|
"__email__",
|
|
75
|
-
]
|
|
72
|
+
]
|
aiecs/__main__.py
CHANGED
|
@@ -12,28 +12,28 @@ def main():
|
|
|
12
12
|
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
13
13
|
if parent_dir not in sys.path:
|
|
14
14
|
sys.path.insert(0, parent_dir)
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
# Import and run uvicorn
|
|
17
17
|
import uvicorn
|
|
18
18
|
from aiecs.main import app
|
|
19
19
|
from aiecs.ws.socket_server import sio
|
|
20
|
-
import socketio
|
|
21
|
-
|
|
20
|
+
import socketio # type: ignore[import-untyped]
|
|
21
|
+
|
|
22
22
|
# Create the combined Socket.IO + FastAPI app
|
|
23
23
|
socket_app = socketio.ASGIApp(sio, other_asgi_app=app)
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
# Get port from environment or use default
|
|
26
26
|
port = int(os.environ.get("PORT", 8000))
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
print(f"Starting AIECS server on port {port}...")
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
# Run the application with Socket.IO support
|
|
31
31
|
uvicorn.run(
|
|
32
32
|
socket_app,
|
|
33
33
|
host="0.0.0.0",
|
|
34
34
|
port=port,
|
|
35
35
|
log_level="info",
|
|
36
|
-
reload=bool(os.environ.get("RELOAD", False))
|
|
36
|
+
reload=bool(os.environ.get("RELOAD", False)),
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
|
aiecs/aiecs_client.py
CHANGED
|
@@ -11,7 +11,12 @@ from contextlib import asynccontextmanager
|
|
|
11
11
|
from aiecs.config.config import get_settings, validate_required_settings
|
|
12
12
|
from aiecs.domain.task.task_context import TaskContext
|
|
13
13
|
from aiecs.tools import discover_tools, list_tools, get_tool
|
|
14
|
-
from aiecs.llm.client_factory import
|
|
14
|
+
from aiecs.llm.client_factory import (
|
|
15
|
+
LLMClientFactory,
|
|
16
|
+
LLMClientManager,
|
|
17
|
+
AIProvider,
|
|
18
|
+
)
|
|
19
|
+
from aiecs.llm.clients.base_client import LLMMessage
|
|
15
20
|
|
|
16
21
|
logger = logging.getLogger(__name__)
|
|
17
22
|
|
|
@@ -19,21 +24,21 @@ logger = logging.getLogger(__name__)
|
|
|
19
24
|
class AIECS:
|
|
20
25
|
"""
|
|
21
26
|
Main AIECS client for programmatic usage
|
|
22
|
-
|
|
27
|
+
|
|
23
28
|
This class provides a high-level API for:
|
|
24
29
|
- Executing tasks with AI providers
|
|
25
30
|
- Managing tool orchestration
|
|
26
31
|
- Configuration management
|
|
27
|
-
|
|
32
|
+
|
|
28
33
|
Two operation modes:
|
|
29
34
|
- Simple mode: Tools and basic AI functionality (no database/Celery)
|
|
30
35
|
- Full mode: Complete infrastructure (requires database/Redis)
|
|
31
36
|
"""
|
|
32
|
-
|
|
37
|
+
|
|
33
38
|
def __init__(self, config: Optional[Dict[str, Any]] = None, mode: str = "simple"):
|
|
34
39
|
"""
|
|
35
40
|
Initialize AIECS client
|
|
36
|
-
|
|
41
|
+
|
|
37
42
|
Args:
|
|
38
43
|
config: Optional configuration override
|
|
39
44
|
mode: Operation mode - "simple" or "full"
|
|
@@ -41,97 +46,110 @@ class AIECS:
|
|
|
41
46
|
self.settings = get_settings()
|
|
42
47
|
self.config = config or {}
|
|
43
48
|
self.mode = mode
|
|
44
|
-
|
|
49
|
+
|
|
45
50
|
# Core components (loaded based on mode)
|
|
46
51
|
self.db_manager = None
|
|
47
52
|
self.task_manager = None
|
|
48
53
|
self.operation_executor = None
|
|
49
|
-
|
|
54
|
+
self.llm_manager = None
|
|
55
|
+
|
|
50
56
|
# State
|
|
51
57
|
self._initialized = False
|
|
52
58
|
self._tools_discovered = False
|
|
53
|
-
|
|
59
|
+
|
|
54
60
|
async def initialize(self):
|
|
55
61
|
"""Initialize AIECS services based on mode"""
|
|
56
62
|
if self._initialized:
|
|
57
63
|
return
|
|
58
|
-
|
|
64
|
+
|
|
59
65
|
logger.info(f"Initializing AIECS client in {self.mode} mode...")
|
|
60
|
-
|
|
66
|
+
|
|
61
67
|
try:
|
|
62
68
|
# Always discover tools
|
|
63
69
|
if not self._tools_discovered:
|
|
64
70
|
discover_tools("aiecs.tools")
|
|
65
71
|
self._tools_discovered = True
|
|
66
72
|
logger.info("Tools discovered and registered")
|
|
67
|
-
|
|
73
|
+
|
|
74
|
+
# Initialize LLM manager (available in both modes)
|
|
75
|
+
self.llm_manager = LLMClientManager()
|
|
76
|
+
logger.info("LLM manager initialized")
|
|
77
|
+
|
|
68
78
|
if self.mode == "simple":
|
|
69
79
|
# Simple mode: only tools, no database/Celery
|
|
70
80
|
logger.info("Simple mode: tools only")
|
|
71
|
-
|
|
81
|
+
|
|
72
82
|
elif self.mode == "full":
|
|
73
83
|
# Full mode: with database and task queue
|
|
74
84
|
try:
|
|
75
85
|
# Check configuration first
|
|
76
86
|
validate_required_settings("database")
|
|
77
|
-
|
|
87
|
+
|
|
78
88
|
# Initialize database connection
|
|
79
|
-
from aiecs.infrastructure.persistence.database_manager import
|
|
89
|
+
from aiecs.infrastructure.persistence.database_manager import (
|
|
90
|
+
DatabaseManager,
|
|
91
|
+
)
|
|
92
|
+
|
|
80
93
|
self.db_manager = DatabaseManager()
|
|
81
94
|
await self.db_manager.init_connection_pool()
|
|
82
95
|
logger.info("Database connection pool established")
|
|
83
|
-
|
|
96
|
+
|
|
84
97
|
# Initialize task manager
|
|
85
|
-
from aiecs.infrastructure.messaging.celery_task_manager import
|
|
98
|
+
from aiecs.infrastructure.messaging.celery_task_manager import (
|
|
99
|
+
CeleryTaskManager,
|
|
100
|
+
)
|
|
101
|
+
|
|
86
102
|
celery_config = {
|
|
87
103
|
"broker_url": self.settings.celery_broker_url,
|
|
88
104
|
"backend_url": self.settings.celery_broker_url,
|
|
89
105
|
}
|
|
90
106
|
self.task_manager = CeleryTaskManager(celery_config)
|
|
91
107
|
logger.info("Task manager initialized")
|
|
92
|
-
|
|
108
|
+
|
|
93
109
|
# Initialize operation executor
|
|
94
|
-
from aiecs.application.executors.operation_executor import
|
|
110
|
+
from aiecs.application.executors.operation_executor import (
|
|
111
|
+
OperationExecutor,
|
|
112
|
+
)
|
|
95
113
|
from aiecs.tools.tool_executor import ToolExecutor
|
|
96
114
|
from aiecs.utils.execution_utils import ExecutionUtils
|
|
97
|
-
|
|
115
|
+
|
|
98
116
|
tool_executor = ToolExecutor()
|
|
99
117
|
execution_utils = ExecutionUtils()
|
|
100
118
|
self.operation_executor = OperationExecutor(
|
|
101
119
|
tool_executor=tool_executor,
|
|
102
120
|
execution_utils=execution_utils,
|
|
103
|
-
config=self.config
|
|
121
|
+
config=self.config,
|
|
104
122
|
)
|
|
105
|
-
|
|
123
|
+
|
|
106
124
|
except Exception as e:
|
|
107
125
|
logger.warning(f"Full mode initialization failed: {e}")
|
|
108
126
|
logger.info("Falling back to simple mode")
|
|
109
127
|
self.mode = "simple"
|
|
110
|
-
|
|
128
|
+
|
|
111
129
|
self._initialized = True
|
|
112
130
|
logger.info(f"AIECS client initialized successfully in {self.mode} mode")
|
|
113
|
-
|
|
131
|
+
|
|
114
132
|
except Exception as e:
|
|
115
133
|
logger.error(f"Failed to initialize AIECS: {e}")
|
|
116
134
|
raise
|
|
117
|
-
|
|
135
|
+
|
|
118
136
|
async def execute(self, context: TaskContext) -> Dict[str, Any]:
|
|
119
137
|
"""
|
|
120
138
|
Execute a task with the given context
|
|
121
|
-
|
|
139
|
+
|
|
122
140
|
Args:
|
|
123
141
|
context: TaskContext with task parameters
|
|
124
|
-
|
|
142
|
+
|
|
125
143
|
Returns:
|
|
126
144
|
Task execution result
|
|
127
145
|
"""
|
|
128
146
|
if not self._initialized:
|
|
129
147
|
await self.initialize()
|
|
130
|
-
|
|
148
|
+
|
|
131
149
|
if self.mode == "simple":
|
|
132
150
|
# Simple mode: direct execution without queue
|
|
133
151
|
logger.info("Executing task in simple mode (direct execution)")
|
|
134
|
-
|
|
152
|
+
|
|
135
153
|
# Basic validation
|
|
136
154
|
try:
|
|
137
155
|
validate_required_settings("llm")
|
|
@@ -139,127 +157,299 @@ class AIECS:
|
|
|
139
157
|
return {
|
|
140
158
|
"status": "failed",
|
|
141
159
|
"error": f"LLM configuration required: {e}",
|
|
142
|
-
"mode": "simple"
|
|
160
|
+
"mode": "simple",
|
|
143
161
|
}
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
|
|
163
|
+
# Direct task execution using process_task_async (no Celery required)
|
|
164
|
+
try:
|
|
165
|
+
result = await self.process_task_async(context)
|
|
166
|
+
return {
|
|
167
|
+
**result,
|
|
168
|
+
"mode": "simple",
|
|
169
|
+
}
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.error(f"Simple mode execution failed: {e}", exc_info=True)
|
|
172
|
+
return {
|
|
173
|
+
"status": "failed",
|
|
174
|
+
"error": str(e),
|
|
175
|
+
"mode": "simple",
|
|
176
|
+
"context_id": context.user_id if hasattr(context, "user_id") else "unknown",
|
|
177
|
+
}
|
|
178
|
+
|
|
154
179
|
elif self.mode == "full":
|
|
155
180
|
if not self.task_manager:
|
|
156
181
|
raise RuntimeError("Task manager not initialized in full mode")
|
|
157
|
-
|
|
182
|
+
|
|
158
183
|
# Submit task to queue and get result
|
|
159
|
-
task_id = await self.task_manager.submit_task(
|
|
160
|
-
|
|
161
|
-
task_type="task"
|
|
162
|
-
)
|
|
163
|
-
|
|
184
|
+
task_id = await self.task_manager.submit_task(context=context, task_type="task")
|
|
185
|
+
|
|
164
186
|
# Wait for task completion
|
|
165
187
|
result = await self._wait_for_task_completion(task_id)
|
|
166
188
|
return result
|
|
167
|
-
|
|
189
|
+
|
|
168
190
|
else:
|
|
169
191
|
raise ValueError(f"Unknown mode: {self.mode}")
|
|
170
|
-
|
|
192
|
+
|
|
171
193
|
async def execute_tool(self, tool_name: str, operation: str, params: Dict[str, Any]) -> Any:
|
|
172
194
|
"""
|
|
173
195
|
Execute a specific tool operation directly
|
|
174
|
-
|
|
196
|
+
|
|
175
197
|
Args:
|
|
176
198
|
tool_name: Name of the tool
|
|
177
|
-
operation: Operation to execute
|
|
199
|
+
operation: Operation to execute
|
|
178
200
|
params: Parameters for the operation
|
|
179
|
-
|
|
201
|
+
|
|
180
202
|
Returns:
|
|
181
203
|
Operation result
|
|
182
204
|
"""
|
|
183
205
|
if not self._initialized:
|
|
184
206
|
await self.initialize()
|
|
185
|
-
|
|
207
|
+
|
|
186
208
|
# Get tool and execute directly (works in both modes)
|
|
187
209
|
tool = get_tool(tool_name)
|
|
188
210
|
if not tool:
|
|
189
211
|
raise ValueError(f"Tool '{tool_name}' not found")
|
|
212
|
+
|
|
213
|
+
# Check if tool has execute() method (some tools like KnowledgeGraphBuilderTool)
|
|
214
|
+
if hasattr(tool, "execute") and callable(getattr(tool, "execute")):
|
|
215
|
+
# Tools with execute() method expect kwargs unpacked
|
|
216
|
+
# Some tools use "op", others use "action" - include both for compatibility
|
|
217
|
+
tool_params = {**params, "op": operation, "action": operation}
|
|
218
|
+
return await tool.execute(**tool_params)
|
|
190
219
|
|
|
191
|
-
#
|
|
192
|
-
|
|
220
|
+
# Check if tool has run_async() method (BaseTool-based tools)
|
|
221
|
+
elif hasattr(tool, "run_async") and callable(getattr(tool, "run_async")):
|
|
222
|
+
# BaseTool.run_async expects op as first parameter, then kwargs
|
|
223
|
+
return await tool.run_async(operation, **params)
|
|
193
224
|
|
|
194
|
-
#
|
|
195
|
-
|
|
196
|
-
|
|
225
|
+
# Check if tool has run() method (synchronous BaseTool)
|
|
226
|
+
elif hasattr(tool, "run") and callable(getattr(tool, "run")):
|
|
227
|
+
# BaseTool.run expects op as first parameter, then kwargs
|
|
228
|
+
return tool.run(operation, **params)
|
|
229
|
+
|
|
230
|
+
else:
|
|
231
|
+
raise ValueError(
|
|
232
|
+
f"Tool '{tool_name}' does not have an 'execute()', 'run_async()', or 'run()' method. "
|
|
233
|
+
f"Available methods: {[m for m in dir(tool) if not m.startswith('_')]}"
|
|
234
|
+
)
|
|
235
|
+
|
|
197
236
|
async def get_available_tools(self) -> List[Dict[str, Any]]:
|
|
198
237
|
"""Get list of all available tools"""
|
|
199
238
|
if not self._tools_discovered:
|
|
200
239
|
discover_tools("aiecs.tools")
|
|
201
240
|
self._tools_discovered = True
|
|
202
|
-
|
|
241
|
+
|
|
203
242
|
return list_tools()
|
|
204
|
-
|
|
243
|
+
|
|
205
244
|
async def get_tool(self, tool_name: str):
|
|
206
245
|
"""Get a specific tool instance"""
|
|
207
246
|
if not self._tools_discovered:
|
|
208
247
|
discover_tools("aiecs.tools")
|
|
209
248
|
self._tools_discovered = True
|
|
210
|
-
|
|
249
|
+
|
|
211
250
|
return get_tool(tool_name)
|
|
212
|
-
|
|
251
|
+
|
|
252
|
+
def process_task(self, task_context: TaskContext) -> Dict[str, Any]:
|
|
253
|
+
"""
|
|
254
|
+
Process a task synchronously (for compatibility with synchronous tool calls)
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
task_context: TaskContext containing the task data
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
Task processing result with AI-generated response
|
|
261
|
+
"""
|
|
262
|
+
# Run the async method in a new event loop if needed
|
|
263
|
+
try:
|
|
264
|
+
loop = asyncio.get_event_loop()
|
|
265
|
+
if loop.is_running():
|
|
266
|
+
# If called from async context, create a new thread
|
|
267
|
+
import concurrent.futures
|
|
268
|
+
|
|
269
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
270
|
+
future = executor.submit(asyncio.run, self.process_task_async(task_context))
|
|
271
|
+
return future.result()
|
|
272
|
+
else:
|
|
273
|
+
# Run in current event loop
|
|
274
|
+
return loop.run_until_complete(self.process_task_async(task_context))
|
|
275
|
+
except RuntimeError:
|
|
276
|
+
# No event loop, create one
|
|
277
|
+
return asyncio.run(self.process_task_async(task_context))
|
|
278
|
+
|
|
279
|
+
async def process_task_async(self, task_context: TaskContext) -> Dict[str, Any]:
|
|
280
|
+
"""
|
|
281
|
+
Process a task asynchronously using AI providers
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
task_context: TaskContext containing the task data
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Task processing result with AI-generated response
|
|
288
|
+
"""
|
|
289
|
+
if not self._initialized:
|
|
290
|
+
await self.initialize()
|
|
291
|
+
|
|
292
|
+
if not self.llm_manager:
|
|
293
|
+
raise RuntimeError("LLM manager not initialized")
|
|
294
|
+
|
|
295
|
+
try:
|
|
296
|
+
# Extract data from TaskContext
|
|
297
|
+
context_dict = task_context.to_dict()
|
|
298
|
+
metadata = context_dict.get("metadata", {})
|
|
299
|
+
|
|
300
|
+
# Get AI provider preference from metadata
|
|
301
|
+
ai_preference = metadata.get("aiPreference", "default")
|
|
302
|
+
provider = None
|
|
303
|
+
model = None
|
|
304
|
+
|
|
305
|
+
# Parse AI preference
|
|
306
|
+
if isinstance(ai_preference, str):
|
|
307
|
+
# Simple string preference
|
|
308
|
+
if ai_preference.lower() != "default":
|
|
309
|
+
try:
|
|
310
|
+
provider = AIProvider(ai_preference)
|
|
311
|
+
except ValueError:
|
|
312
|
+
logger.warning(f"Unknown AI provider: {ai_preference}, using default")
|
|
313
|
+
elif isinstance(ai_preference, dict):
|
|
314
|
+
# Dictionary with provider and model
|
|
315
|
+
provider_str = ai_preference.get("provider")
|
|
316
|
+
if provider_str:
|
|
317
|
+
try:
|
|
318
|
+
provider = AIProvider(provider_str)
|
|
319
|
+
except ValueError:
|
|
320
|
+
logger.warning(f"Unknown AI provider: {provider_str}, using default")
|
|
321
|
+
model = ai_preference.get("model")
|
|
322
|
+
|
|
323
|
+
# Build prompt from context data
|
|
324
|
+
# The prompt could come from various sources in the context
|
|
325
|
+
prompt = None
|
|
326
|
+
|
|
327
|
+
# Check for direct prompt in metadata
|
|
328
|
+
if "prompt" in metadata:
|
|
329
|
+
prompt = metadata["prompt"]
|
|
330
|
+
# Check for input_data (common in document generation)
|
|
331
|
+
elif "input_data" in context_dict:
|
|
332
|
+
input_data = context_dict["input_data"]
|
|
333
|
+
if isinstance(input_data, dict) and "prompt" in input_data:
|
|
334
|
+
prompt = input_data["prompt"]
|
|
335
|
+
elif isinstance(input_data, str):
|
|
336
|
+
prompt = input_data
|
|
337
|
+
|
|
338
|
+
if not prompt:
|
|
339
|
+
# Fallback: construct a simple prompt from available data
|
|
340
|
+
prompt = f"Task: {context_dict.get('task_type', 'general')}\nData: {context_dict}"
|
|
341
|
+
|
|
342
|
+
# Get temperature and other parameters from metadata
|
|
343
|
+
temperature = metadata.get("temperature", 0.7)
|
|
344
|
+
max_tokens = metadata.get("max_tokens", 2000)
|
|
345
|
+
|
|
346
|
+
# Generate text using LLM manager
|
|
347
|
+
messages = [LLMMessage(role="user", content=prompt)]
|
|
348
|
+
|
|
349
|
+
response = await self.llm_manager.generate_text(
|
|
350
|
+
messages=messages,
|
|
351
|
+
provider=provider,
|
|
352
|
+
model=model,
|
|
353
|
+
context=context_dict,
|
|
354
|
+
temperature=temperature,
|
|
355
|
+
max_tokens=max_tokens,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
# Track model usage in context
|
|
359
|
+
if hasattr(task_context, "track_model_usage"):
|
|
360
|
+
task_context.track_model_usage(
|
|
361
|
+
model_id=response.model,
|
|
362
|
+
provider_id=response.provider,
|
|
363
|
+
mode="generate",
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Return result in expected format
|
|
367
|
+
return {
|
|
368
|
+
"status": "completed",
|
|
369
|
+
"response": response.content,
|
|
370
|
+
"provider": response.provider,
|
|
371
|
+
"model": response.model,
|
|
372
|
+
"tokens_used": response.tokens_used,
|
|
373
|
+
"cost_estimate": response.cost_estimate,
|
|
374
|
+
"context_id": context_dict.get("chat_id", "unknown"),
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
except Exception as e:
|
|
378
|
+
logger.error(f"Task processing failed: {e}", exc_info=True)
|
|
379
|
+
|
|
380
|
+
# For testing/development, provide a mock response when AI provider
|
|
381
|
+
# is unavailable
|
|
382
|
+
error_str = str(e).lower()
|
|
383
|
+
if "api key not configured" in error_str or "providernotavailable" in error_str:
|
|
384
|
+
logger.warning("AI provider unavailable, using mock response for testing")
|
|
385
|
+
mock_content = f"Mock AI-generated content for prompt: {prompt[:100] if len(prompt) > 100 else prompt}..."
|
|
386
|
+
return {
|
|
387
|
+
"status": "completed",
|
|
388
|
+
"response": mock_content,
|
|
389
|
+
"provider": "mock",
|
|
390
|
+
"model": "mock-model",
|
|
391
|
+
"tokens_used": len(mock_content.split()),
|
|
392
|
+
"cost_estimate": 0.0,
|
|
393
|
+
"context_id": context_dict.get("chat_id", "unknown"),
|
|
394
|
+
"mock": True,
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return {
|
|
398
|
+
"status": "failed",
|
|
399
|
+
"error": str(e),
|
|
400
|
+
"context_id": (task_context.chat_id if hasattr(task_context, "chat_id") else "unknown"),
|
|
401
|
+
}
|
|
402
|
+
|
|
213
403
|
async def _wait_for_task_completion(self, task_id: str, timeout: int = 300) -> Dict[str, Any]:
|
|
214
404
|
"""
|
|
215
405
|
Wait for task completion with timeout
|
|
216
|
-
|
|
406
|
+
|
|
217
407
|
Args:
|
|
218
408
|
task_id: Task ID to wait for
|
|
219
409
|
timeout: Maximum wait time in seconds
|
|
220
|
-
|
|
410
|
+
|
|
221
411
|
Returns:
|
|
222
412
|
Task result
|
|
223
413
|
"""
|
|
224
414
|
if not self.task_manager:
|
|
225
415
|
raise RuntimeError("Task manager not initialized")
|
|
226
|
-
|
|
416
|
+
|
|
227
417
|
start_time = asyncio.get_event_loop().time()
|
|
228
|
-
|
|
418
|
+
|
|
229
419
|
while True:
|
|
230
420
|
status = await self.task_manager.get_task_status(task_id)
|
|
231
|
-
|
|
421
|
+
|
|
232
422
|
if status.get("status") in ["completed", "failed", "cancelled"]:
|
|
233
423
|
return status
|
|
234
|
-
|
|
424
|
+
|
|
235
425
|
# Check timeout
|
|
236
426
|
if asyncio.get_event_loop().time() - start_time > timeout:
|
|
237
427
|
raise TimeoutError(f"Task {task_id} did not complete within {timeout} seconds")
|
|
238
|
-
|
|
428
|
+
|
|
239
429
|
# Wait before checking again
|
|
240
430
|
await asyncio.sleep(1)
|
|
241
|
-
|
|
431
|
+
|
|
242
432
|
async def close(self):
|
|
243
433
|
"""Close AIECS client and cleanup resources"""
|
|
244
434
|
logger.info("Shutting down AIECS client...")
|
|
245
|
-
|
|
435
|
+
|
|
246
436
|
if self.mode == "full" and self.db_manager:
|
|
247
437
|
try:
|
|
248
438
|
await self.db_manager.close_connection_pool()
|
|
249
439
|
logger.info("Database connection pool closed")
|
|
250
440
|
except Exception as e:
|
|
251
441
|
logger.error(f"Error closing database: {e}")
|
|
252
|
-
|
|
442
|
+
|
|
253
443
|
# Close all LLM clients
|
|
254
444
|
try:
|
|
255
445
|
await LLMClientFactory.close_all()
|
|
256
446
|
logger.info("LLM clients closed")
|
|
257
447
|
except Exception as e:
|
|
258
448
|
logger.error(f"Error closing LLM clients: {e}")
|
|
259
|
-
|
|
449
|
+
|
|
260
450
|
self._initialized = False
|
|
261
451
|
logger.info("AIECS client shutdown complete")
|
|
262
|
-
|
|
452
|
+
|
|
263
453
|
@asynccontextmanager
|
|
264
454
|
async def session(self):
|
|
265
455
|
"""Context manager for AIECS session"""
|
|
@@ -274,11 +464,11 @@ class AIECS:
|
|
|
274
464
|
async def create_aiecs_client(config: Optional[Dict[str, Any]] = None, mode: str = "simple") -> AIECS:
|
|
275
465
|
"""
|
|
276
466
|
Create and initialize an AIECS client
|
|
277
|
-
|
|
467
|
+
|
|
278
468
|
Args:
|
|
279
469
|
config: Optional configuration override
|
|
280
470
|
mode: Operation mode - "simple" or "full"
|
|
281
|
-
|
|
471
|
+
|
|
282
472
|
Returns:
|
|
283
473
|
Initialized AIECS client
|
|
284
474
|
"""
|
|
@@ -286,10 +476,14 @@ async def create_aiecs_client(config: Optional[Dict[str, Any]] = None, mode: str
|
|
|
286
476
|
await client.initialize()
|
|
287
477
|
return client
|
|
288
478
|
|
|
289
|
-
|
|
479
|
+
|
|
480
|
+
async def create_simple_client(
|
|
481
|
+
config: Optional[Dict[str, Any]] = None,
|
|
482
|
+
) -> AIECS:
|
|
290
483
|
"""Create a simple AIECS client (tools only, no database/Celery)"""
|
|
291
484
|
return await create_aiecs_client(config, "simple")
|
|
292
485
|
|
|
486
|
+
|
|
293
487
|
async def create_full_client(config: Optional[Dict[str, Any]] = None) -> AIECS:
|
|
294
488
|
"""Create a full AIECS client (with database and Celery)"""
|
|
295
489
|
return await create_aiecs_client(config, "full")
|