aiecs 1.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiecs/__init__.py +72 -0
- aiecs/__main__.py +41 -0
- aiecs/aiecs_client.py +469 -0
- aiecs/application/__init__.py +10 -0
- aiecs/application/executors/__init__.py +10 -0
- aiecs/application/executors/operation_executor.py +363 -0
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +100 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -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 +347 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -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 +630 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
- aiecs/application/knowledge_graph/search/reranker.py +295 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +484 -0
- aiecs/config/__init__.py +16 -0
- aiecs/config/config.py +498 -0
- aiecs/config/graph_config.py +137 -0
- aiecs/config/registry.py +23 -0
- aiecs/core/__init__.py +46 -0
- aiecs/core/interface/__init__.py +34 -0
- aiecs/core/interface/execution_interface.py +152 -0
- aiecs/core/interface/storage_interface.py +171 -0
- aiecs/domain/__init__.py +289 -0
- aiecs/domain/agent/__init__.py +189 -0
- aiecs/domain/agent/base_agent.py +697 -0
- aiecs/domain/agent/exceptions.py +103 -0
- aiecs/domain/agent/graph_aware_mixin.py +559 -0
- aiecs/domain/agent/hybrid_agent.py +490 -0
- aiecs/domain/agent/integration/__init__.py +26 -0
- aiecs/domain/agent/integration/context_compressor.py +222 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
- aiecs/domain/agent/integration/retry_policy.py +219 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +646 -0
- aiecs/domain/agent/lifecycle.py +296 -0
- aiecs/domain/agent/llm_agent.py +300 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +197 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +160 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
- aiecs/domain/agent/models.py +317 -0
- aiecs/domain/agent/observability.py +407 -0
- aiecs/domain/agent/persistence.py +289 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +161 -0
- aiecs/domain/agent/prompts/formatters.py +189 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +260 -0
- aiecs/domain/agent/tool_agent.py +257 -0
- aiecs/domain/agent/tools/__init__.py +12 -0
- aiecs/domain/agent/tools/schema_generator.py +221 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +477 -0
- aiecs/domain/community/analytics.py +481 -0
- aiecs/domain/community/collaborative_workflow.py +642 -0
- aiecs/domain/community/communication_hub.py +645 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +800 -0
- aiecs/domain/community/community_manager.py +813 -0
- aiecs/domain/community/decision_engine.py +879 -0
- aiecs/domain/community/exceptions.py +225 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +268 -0
- aiecs/domain/community/resource_manager.py +457 -0
- aiecs/domain/community/shared_context_manager.py +603 -0
- aiecs/domain/context/__init__.py +58 -0
- aiecs/domain/context/context_engine.py +989 -0
- aiecs/domain/context/conversation_models.py +354 -0
- aiecs/domain/context/graph_memory.py +467 -0
- aiecs/domain/execution/__init__.py +12 -0
- aiecs/domain/execution/model.py +57 -0
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +130 -0
- aiecs/domain/knowledge_graph/models/evidence.py +194 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
- aiecs/domain/knowledge_graph/models/path.py +179 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
- aiecs/domain/knowledge_graph/models/query.py +272 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
- aiecs/domain/knowledge_graph/models/relation.py +136 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
- aiecs/domain/task/__init__.py +13 -0
- aiecs/domain/task/dsl_processor.py +613 -0
- aiecs/domain/task/model.py +62 -0
- aiecs/domain/task/task_context.py +268 -0
- aiecs/infrastructure/__init__.py +24 -0
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +601 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
- aiecs/infrastructure/graph_storage/cache.py +429 -0
- aiecs/infrastructure/graph_storage/distributed.py +226 -0
- aiecs/infrastructure/graph_storage/error_handling.py +390 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +514 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
- aiecs/infrastructure/graph_storage/metrics.py +357 -0
- aiecs/infrastructure/graph_storage/migration.py +413 -0
- aiecs/infrastructure/graph_storage/pagination.py +471 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
- aiecs/infrastructure/graph_storage/postgres.py +871 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +623 -0
- aiecs/infrastructure/graph_storage/streaming.py +495 -0
- aiecs/infrastructure/messaging/__init__.py +13 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
- aiecs/infrastructure/messaging/websocket_manager.py +298 -0
- aiecs/infrastructure/monitoring/__init__.py +34 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
- aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
- aiecs/infrastructure/monitoring/structured_logger.py +48 -0
- aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
- aiecs/infrastructure/persistence/__init__.py +24 -0
- aiecs/infrastructure/persistence/context_engine_client.py +187 -0
- aiecs/infrastructure/persistence/database_manager.py +333 -0
- aiecs/infrastructure/persistence/file_storage.py +754 -0
- aiecs/infrastructure/persistence/redis_client.py +220 -0
- aiecs/llm/__init__.py +86 -0
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/callbacks/custom_callbacks.py +264 -0
- aiecs/llm/client_factory.py +420 -0
- aiecs/llm/clients/__init__.py +33 -0
- aiecs/llm/clients/base_client.py +193 -0
- aiecs/llm/clients/googleai_client.py +181 -0
- aiecs/llm/clients/openai_client.py +131 -0
- aiecs/llm/clients/vertex_client.py +437 -0
- aiecs/llm/clients/xai_client.py +184 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +275 -0
- aiecs/llm/config/config_validator.py +236 -0
- aiecs/llm/config/model_config.py +151 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +91 -0
- aiecs/main.py +363 -0
- aiecs/scripts/__init__.py +3 -0
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/version_manager.py +215 -0
- aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
- aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
- aiecs/scripts/dependance_check/__init__.py +17 -0
- aiecs/scripts/dependance_check/dependency_checker.py +938 -0
- aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
- aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
- aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
- aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
- aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
- aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
- aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
- aiecs/scripts/tools_develop/README.md +449 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
- aiecs/scripts/tools_develop/verify_tools.py +356 -0
- aiecs/tasks/__init__.py +1 -0
- aiecs/tasks/worker.py +172 -0
- aiecs/tools/__init__.py +299 -0
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +303 -0
- aiecs/tools/apisource/providers/__init__.py +115 -0
- aiecs/tools/apisource/providers/base.py +664 -0
- aiecs/tools/apisource/providers/census.py +401 -0
- aiecs/tools/apisource/providers/fred.py +564 -0
- aiecs/tools/apisource/providers/newsapi.py +412 -0
- aiecs/tools/apisource/providers/worldbank.py +357 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +375 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
- aiecs/tools/apisource/tool.py +850 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +338 -0
- aiecs/tools/base_tool.py +201 -0
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +599 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
- aiecs/tools/docs/content_insertion_tool.py +1333 -0
- aiecs/tools/docs/document_creator_tool.py +1317 -0
- aiecs/tools/docs/document_layout_tool.py +1166 -0
- aiecs/tools/docs/document_parser_tool.py +994 -0
- aiecs/tools/docs/document_writer_tool.py +1818 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
- aiecs/tools/langchain_adapter.py +542 -0
- aiecs/tools/schema_generator.py +275 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +589 -0
- aiecs/tools/search_tool/cache.py +260 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +216 -0
- aiecs/tools/search_tool/core.py +749 -0
- aiecs/tools/search_tool/deduplicator.py +123 -0
- aiecs/tools/search_tool/error_handler.py +271 -0
- aiecs/tools/search_tool/metrics.py +371 -0
- aiecs/tools/search_tool/rate_limiter.py +178 -0
- aiecs/tools/search_tool/schemas.py +277 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
- aiecs/tools/statistics/data_loader_tool.py +564 -0
- aiecs/tools/statistics/data_profiler_tool.py +658 -0
- aiecs/tools/statistics/data_transformer_tool.py +573 -0
- aiecs/tools/statistics/data_visualizer_tool.py +495 -0
- aiecs/tools/statistics/model_trainer_tool.py +487 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
- aiecs/tools/task_tools/__init__.py +86 -0
- aiecs/tools/task_tools/chart_tool.py +732 -0
- aiecs/tools/task_tools/classfire_tool.py +922 -0
- aiecs/tools/task_tools/image_tool.py +447 -0
- aiecs/tools/task_tools/office_tool.py +684 -0
- aiecs/tools/task_tools/pandas_tool.py +635 -0
- aiecs/tools/task_tools/report_tool.py +635 -0
- aiecs/tools/task_tools/research_tool.py +392 -0
- aiecs/tools/task_tools/scraper_tool.py +715 -0
- aiecs/tools/task_tools/stats_tool.py +688 -0
- aiecs/tools/temp_file_manager.py +130 -0
- aiecs/tools/tool_executor/__init__.py +37 -0
- aiecs/tools/tool_executor/tool_executor.py +881 -0
- aiecs/utils/LLM_output_structor.py +445 -0
- aiecs/utils/__init__.py +34 -0
- aiecs/utils/base_callback.py +47 -0
- aiecs/utils/cache_provider.py +695 -0
- aiecs/utils/execution_utils.py +184 -0
- aiecs/utils/logging.py +1 -0
- aiecs/utils/prompt_loader.py +14 -0
- aiecs/utils/token_usage_repository.py +323 -0
- aiecs/ws/__init__.py +0 -0
- aiecs/ws/socket_server.py +52 -0
- aiecs-1.5.1.dist-info/METADATA +608 -0
- aiecs-1.5.1.dist-info/RECORD +302 -0
- aiecs-1.5.1.dist-info/WHEEL +5 -0
- aiecs-1.5.1.dist-info/entry_points.txt +10 -0
- aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
- aiecs-1.5.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
快速验证脚本:展示 aiecs.tools 注册的所有工具和功能
|
|
4
|
+
|
|
5
|
+
使用方法:
|
|
6
|
+
poetry run python -m aiecs.scripts.tools_develop.verify_tools
|
|
7
|
+
|
|
8
|
+
功能:
|
|
9
|
+
1. 列出所有注册的工具(按类别分组)
|
|
10
|
+
2. 交互式选择工具查看详细功能
|
|
11
|
+
3. 实际加载指定工具,展示真实的原子功能
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
import os
|
|
16
|
+
import inspect
|
|
17
|
+
from typing import List, Dict
|
|
18
|
+
from collections import defaultdict
|
|
19
|
+
|
|
20
|
+
# 添加项目根目录到 Python 路径
|
|
21
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
22
|
+
project_root = os.path.abspath(os.path.join(current_dir, "../../../"))
|
|
23
|
+
sys.path.insert(0, project_root)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_tool_methods(tool_instance) -> List[str]:
|
|
27
|
+
"""获取工具实例的所有公共方法(原子功能)"""
|
|
28
|
+
methods = []
|
|
29
|
+
for name, method in inspect.getmembers(tool_instance, predicate=inspect.ismethod):
|
|
30
|
+
# 只获取公共方法,排除私有方法和特殊方法
|
|
31
|
+
if not name.startswith("_"):
|
|
32
|
+
methods.append(name)
|
|
33
|
+
return sorted(methods)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def display_tools_by_category(tools: List[Dict]):
|
|
37
|
+
"""按类别分组显示工具"""
|
|
38
|
+
# 按类别分组
|
|
39
|
+
categories = defaultdict(list)
|
|
40
|
+
for tool in tools:
|
|
41
|
+
category = tool.get("category", "unknown")
|
|
42
|
+
categories[category].append(tool)
|
|
43
|
+
|
|
44
|
+
# 显示每个类别
|
|
45
|
+
category_names = {
|
|
46
|
+
"task": "任务工具",
|
|
47
|
+
"docs": "文档工具",
|
|
48
|
+
"statistics": "数据统计工具",
|
|
49
|
+
"unknown": "其他工具",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
tool_index = 1
|
|
53
|
+
tool_map = {} # 用于存储序号到工具名的映射
|
|
54
|
+
|
|
55
|
+
for category in ["task", "docs", "statistics", "unknown"]:
|
|
56
|
+
if category not in categories:
|
|
57
|
+
continue
|
|
58
|
+
|
|
59
|
+
category_tools = categories[category]
|
|
60
|
+
category_display = category_names.get(category, category.upper())
|
|
61
|
+
|
|
62
|
+
print(f"\n{'=' * 80}")
|
|
63
|
+
print(f"📁 {category_display} ({len(category_tools)} 个)")
|
|
64
|
+
print(f"{'=' * 80}")
|
|
65
|
+
|
|
66
|
+
for tool in category_tools:
|
|
67
|
+
tool_name = tool["name"]
|
|
68
|
+
tool_map[tool_index] = tool_name
|
|
69
|
+
|
|
70
|
+
print(f"\n[{tool_index}] {tool_name}")
|
|
71
|
+
print(f" 描述: {tool.get('description', '无描述')}")
|
|
72
|
+
print(f" 状态: {tool.get('status', '未知')}")
|
|
73
|
+
|
|
74
|
+
tool_index += 1
|
|
75
|
+
|
|
76
|
+
return tool_map
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def auto_discover_tool_modules():
|
|
80
|
+
"""自动发现工具模块映射,无需手动维护"""
|
|
81
|
+
import os
|
|
82
|
+
import re
|
|
83
|
+
|
|
84
|
+
tool_module_map = {}
|
|
85
|
+
|
|
86
|
+
# 扫描 aiecs/tools 目录
|
|
87
|
+
tools_dir = os.path.join(project_root, "aiecs", "tools")
|
|
88
|
+
|
|
89
|
+
# 定义工具目录
|
|
90
|
+
tool_dirs = {
|
|
91
|
+
"task_tools": "aiecs.tools.task_tools",
|
|
92
|
+
"docs": "aiecs.tools.docs",
|
|
93
|
+
"statistics": "aiecs.tools.statistics",
|
|
94
|
+
"api_sources": "aiecs.tools.api_sources", # 旧的 API sources (如果存在)
|
|
95
|
+
"apisource": "aiecs.tools.apisource", # 新的 APISource Tool
|
|
96
|
+
"search_tool": "aiecs.tools.search_tool",
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for dir_name, package_name in tool_dirs.items():
|
|
100
|
+
dir_path = os.path.join(tools_dir, dir_name)
|
|
101
|
+
if not os.path.exists(dir_path):
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
# Check if this is a package (has __init__.py) or a directory of
|
|
105
|
+
# modules
|
|
106
|
+
init_file = os.path.join(dir_path, "__init__.py")
|
|
107
|
+
files_to_scan = []
|
|
108
|
+
|
|
109
|
+
if os.path.isfile(init_file):
|
|
110
|
+
# For packages, scan __init__.py and use package name directly
|
|
111
|
+
files_to_scan.append(("__init__.py", init_file, package_name))
|
|
112
|
+
|
|
113
|
+
# 扫描目录中的所有其他 Python 文件
|
|
114
|
+
for filename in os.listdir(dir_path):
|
|
115
|
+
if filename.endswith(".py") and not filename.startswith("__"):
|
|
116
|
+
file_path = os.path.join(dir_path, filename)
|
|
117
|
+
module_name = filename[:-3] # 去掉 .py 扩展名
|
|
118
|
+
module_path = f"{package_name}.{module_name}"
|
|
119
|
+
files_to_scan.append((filename, file_path, module_path))
|
|
120
|
+
|
|
121
|
+
# Process all files
|
|
122
|
+
for filename, file_path, module_path in files_to_scan:
|
|
123
|
+
try:
|
|
124
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
125
|
+
content = f.read()
|
|
126
|
+
|
|
127
|
+
# 查找 @register_tool 装饰器 (两种模式)
|
|
128
|
+
# Pattern 1: @register_tool("name") decorator syntax
|
|
129
|
+
decorator_pattern = r'@register_tool\([\'"]([^\'"]+)[\'"]\)'
|
|
130
|
+
decorator_matches = re.findall(decorator_pattern, content)
|
|
131
|
+
|
|
132
|
+
# Pattern 2: register_tool("name")(ClassName) function call
|
|
133
|
+
# syntax
|
|
134
|
+
function_pattern = (
|
|
135
|
+
r'register_tool\([\'"]([^\'"]+)[\'"]\)\([A-Za-z_][A-Za-z0-9_]*\)'
|
|
136
|
+
)
|
|
137
|
+
function_matches = re.findall(function_pattern, content)
|
|
138
|
+
|
|
139
|
+
# Combine all matches
|
|
140
|
+
all_matches = list(set(decorator_matches + function_matches))
|
|
141
|
+
|
|
142
|
+
for tool_name in all_matches:
|
|
143
|
+
tool_module_map[tool_name] = {
|
|
144
|
+
"module_file": (
|
|
145
|
+
filename[:-3] if filename != "__init__.py" else "__init__"
|
|
146
|
+
),
|
|
147
|
+
"package": package_name,
|
|
148
|
+
"module_path": module_path,
|
|
149
|
+
"category": dir_name,
|
|
150
|
+
}
|
|
151
|
+
except Exception:
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
return tool_module_map
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def load_and_inspect_tool(tool_name: str):
|
|
158
|
+
"""加载并检查指定工具的详细功能"""
|
|
159
|
+
from aiecs.tools import get_tool
|
|
160
|
+
import importlib
|
|
161
|
+
|
|
162
|
+
print(f"\n{'=' * 80}")
|
|
163
|
+
print(f"🔍 加载工具: {tool_name}")
|
|
164
|
+
print(f"{'=' * 80}")
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
# 自动发现工具模块
|
|
168
|
+
print("\n⏳ 正在加载...")
|
|
169
|
+
|
|
170
|
+
tool_module_map = auto_discover_tool_modules()
|
|
171
|
+
|
|
172
|
+
# 如果找到了工具的模块信息,预加载模块
|
|
173
|
+
if tool_name in tool_module_map:
|
|
174
|
+
info = tool_module_map[tool_name]
|
|
175
|
+
module_path = info.get("module_path") or f"{info['package']}.{info['module_file']}"
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
importlib.import_module(module_path)
|
|
179
|
+
print(f" 已触发 {module_path} 模块加载")
|
|
180
|
+
except Exception as e:
|
|
181
|
+
print(f" 警告: 无法预加载模块 ({e})")
|
|
182
|
+
else:
|
|
183
|
+
print(" 未找到工具模块映射,尝试直接加载...")
|
|
184
|
+
|
|
185
|
+
# 获取工具实例
|
|
186
|
+
tool = get_tool(tool_name)
|
|
187
|
+
|
|
188
|
+
# 检查是否为占位符
|
|
189
|
+
is_placeholder = getattr(tool, "is_placeholder", False)
|
|
190
|
+
|
|
191
|
+
if is_placeholder:
|
|
192
|
+
print("\n⚠️ 工具仍处于占位符状态")
|
|
193
|
+
print(f" 描述: {tool.description}")
|
|
194
|
+
print(" 提示: 此工具需要在调用具体方法时才会完全实例化")
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
# 显示工具基本信息
|
|
198
|
+
print("\n✅ 工具已成功加载")
|
|
199
|
+
print(f" 类名: {tool.__class__.__name__}")
|
|
200
|
+
print(f" 模块: {tool.__class__.__module__}")
|
|
201
|
+
|
|
202
|
+
if hasattr(tool, "description"):
|
|
203
|
+
print(f" 描述: {tool.description}")
|
|
204
|
+
|
|
205
|
+
if hasattr(tool, "category"):
|
|
206
|
+
print(f" 类别: {tool.category}")
|
|
207
|
+
|
|
208
|
+
# 获取所有方法(原子功能)
|
|
209
|
+
methods = get_tool_methods(tool)
|
|
210
|
+
|
|
211
|
+
if not methods:
|
|
212
|
+
print("\n❌ 未发现公共方法")
|
|
213
|
+
return
|
|
214
|
+
|
|
215
|
+
print(f"\n📋 原子功能列表 (共 {len(methods)} 个方法):")
|
|
216
|
+
print("-" * 80)
|
|
217
|
+
|
|
218
|
+
for i, method_name in enumerate(methods, 1):
|
|
219
|
+
try:
|
|
220
|
+
method = getattr(tool, method_name)
|
|
221
|
+
|
|
222
|
+
# 获取方法签名
|
|
223
|
+
sig = inspect.signature(method)
|
|
224
|
+
params = []
|
|
225
|
+
for param_name, param in sig.parameters.items():
|
|
226
|
+
if param_name == "self":
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
# 构建参数字符串
|
|
230
|
+
param_str = param_name
|
|
231
|
+
if param.annotation != inspect.Parameter.empty:
|
|
232
|
+
param_str += f": {param.annotation.__name__ if hasattr(param.annotation, '__name__') else str(param.annotation)}"
|
|
233
|
+
if param.default != inspect.Parameter.empty:
|
|
234
|
+
param_str += f" = {param.default!r}"
|
|
235
|
+
params.append(param_str)
|
|
236
|
+
|
|
237
|
+
# 获取返回类型
|
|
238
|
+
return_annotation = ""
|
|
239
|
+
if sig.return_annotation != inspect.Signature.empty:
|
|
240
|
+
return_type = sig.return_annotation
|
|
241
|
+
return_annotation = f" -> {return_type.__name__ if hasattr(return_type, '__name__') else str(return_type)}"
|
|
242
|
+
|
|
243
|
+
# 显示方法签名
|
|
244
|
+
print(f"\n [{i}] {method_name}({', '.join(params)}){return_annotation}")
|
|
245
|
+
|
|
246
|
+
# 获取文档字符串
|
|
247
|
+
if method.__doc__:
|
|
248
|
+
doc_lines = method.__doc__.strip().split("\n")
|
|
249
|
+
first_line = doc_lines[0].strip()
|
|
250
|
+
if first_line:
|
|
251
|
+
print(f" {first_line}")
|
|
252
|
+
|
|
253
|
+
except Exception as e:
|
|
254
|
+
print(f"\n [{i}] {method_name}")
|
|
255
|
+
print(f" (无法获取详细信息: {e})")
|
|
256
|
+
|
|
257
|
+
print(f"\n{'-' * 80}")
|
|
258
|
+
|
|
259
|
+
except Exception as e:
|
|
260
|
+
print(f"\n❌ 加载工具失败: {e}")
|
|
261
|
+
import traceback
|
|
262
|
+
|
|
263
|
+
traceback.print_exc()
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def interactive_mode(tool_map: Dict[int, str]):
|
|
267
|
+
"""交互式模式"""
|
|
268
|
+
print(f"\n{'=' * 80}")
|
|
269
|
+
print("🎮 交互模式")
|
|
270
|
+
print(f"{'=' * 80}")
|
|
271
|
+
print("\n提示:")
|
|
272
|
+
print(" - 输入工具序号 (1-{}) 查看详细功能".format(len(tool_map)))
|
|
273
|
+
print(" - 输入工具名称查看详细功能")
|
|
274
|
+
print(" - 输入 'list' 重新显示工具列表")
|
|
275
|
+
print(" - 输入 'q' 或 'quit' 退出")
|
|
276
|
+
|
|
277
|
+
while True:
|
|
278
|
+
try:
|
|
279
|
+
user_input = input("\n👉 请选择工具 > ").strip()
|
|
280
|
+
|
|
281
|
+
if not user_input:
|
|
282
|
+
continue
|
|
283
|
+
|
|
284
|
+
if user_input.lower() in ["q", "quit", "exit"]:
|
|
285
|
+
print("\n👋 再见!")
|
|
286
|
+
break
|
|
287
|
+
|
|
288
|
+
if user_input.lower() == "list":
|
|
289
|
+
from aiecs.tools import list_tools
|
|
290
|
+
|
|
291
|
+
tools = list_tools()
|
|
292
|
+
display_tools_by_category(tools)
|
|
293
|
+
continue
|
|
294
|
+
|
|
295
|
+
# 尝试作为序号解析
|
|
296
|
+
tool_name = None
|
|
297
|
+
try:
|
|
298
|
+
index = int(user_input)
|
|
299
|
+
if index in tool_map:
|
|
300
|
+
tool_name = tool_map[index]
|
|
301
|
+
else:
|
|
302
|
+
print(f"❌ 无效的序号: {index}")
|
|
303
|
+
continue
|
|
304
|
+
except ValueError:
|
|
305
|
+
# 作为工具名称
|
|
306
|
+
tool_name = user_input
|
|
307
|
+
|
|
308
|
+
if tool_name:
|
|
309
|
+
load_and_inspect_tool(tool_name)
|
|
310
|
+
|
|
311
|
+
except KeyboardInterrupt:
|
|
312
|
+
print("\n\n👋 再见!")
|
|
313
|
+
break
|
|
314
|
+
except EOFError:
|
|
315
|
+
print("\n\n👋 再见!")
|
|
316
|
+
break
|
|
317
|
+
except Exception as e:
|
|
318
|
+
print(f"\n❌ 错误: {e}")
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def main():
|
|
322
|
+
"""主函数:验证和展示所有注册的工具"""
|
|
323
|
+
print("=" * 80)
|
|
324
|
+
print("AIECS Tools 注册工具验证")
|
|
325
|
+
print("=" * 80)
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
from aiecs.tools import list_tools
|
|
329
|
+
|
|
330
|
+
# 获取所有注册的工具
|
|
331
|
+
tools = list_tools()
|
|
332
|
+
|
|
333
|
+
print(f"\n发现 {len(tools)} 个注册的工具")
|
|
334
|
+
|
|
335
|
+
# 按类别显示工具
|
|
336
|
+
tool_map = display_tools_by_category(tools)
|
|
337
|
+
|
|
338
|
+
print(f"\n{'=' * 80}")
|
|
339
|
+
print(f"✅ 工具列表显示完成! 共 {len(tools)} 个工具")
|
|
340
|
+
print(f"{'=' * 80}")
|
|
341
|
+
|
|
342
|
+
# 进入交互模式
|
|
343
|
+
interactive_mode(tool_map)
|
|
344
|
+
|
|
345
|
+
except ImportError as e:
|
|
346
|
+
print(f"❌ 导入错误: {e}")
|
|
347
|
+
print("请确保在正确的项目目录中运行此脚本")
|
|
348
|
+
except Exception as e:
|
|
349
|
+
print(f"❌ 运行错误: {e}")
|
|
350
|
+
import traceback
|
|
351
|
+
|
|
352
|
+
traceback.print_exc()
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
if __name__ == "__main__":
|
|
356
|
+
main()
|
aiecs/tasks/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# This file makes the app/tasks directory a Python package
|
aiecs/tasks/worker.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from aiecs.domain.execution.model import TaskStatus
|
|
2
|
+
from celery import Celery
|
|
3
|
+
from aiecs.config.config import get_settings
|
|
4
|
+
from aiecs.config.registry import get_ai_service
|
|
5
|
+
from aiecs.ws.socket_server import push_progress
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Dict, Any
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
settings = get_settings()
|
|
12
|
+
celery_app = Celery("ai_worker", broker=settings.celery_broker_url)
|
|
13
|
+
|
|
14
|
+
# Configure Celery
|
|
15
|
+
celery_app.conf.update(
|
|
16
|
+
task_serializer="json",
|
|
17
|
+
accept_content=["json"],
|
|
18
|
+
result_serializer="json",
|
|
19
|
+
timezone="UTC",
|
|
20
|
+
enable_utc=True,
|
|
21
|
+
task_queues={
|
|
22
|
+
"fast_tasks": {"exchange": "fast_tasks", "routing_key": "fast_tasks"},
|
|
23
|
+
"heavy_tasks": {
|
|
24
|
+
"exchange": "heavy_tasks",
|
|
25
|
+
"routing_key": "heavy_tasks",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
task_routes={
|
|
29
|
+
"aiecs.tasks.worker.execute_task": {"queue": "fast_tasks"},
|
|
30
|
+
"aiecs.tasks.worker.execute_heavy_task": {"queue": "heavy_tasks"},
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@celery_app.task(bind=True, name="aiecs.tasks.worker.execute_task")
|
|
36
|
+
def execute_task(
|
|
37
|
+
self,
|
|
38
|
+
task_name: str,
|
|
39
|
+
user_id: str,
|
|
40
|
+
task_id: str,
|
|
41
|
+
step: int,
|
|
42
|
+
mode: str,
|
|
43
|
+
service: str,
|
|
44
|
+
input_data: Dict[str, Any],
|
|
45
|
+
context: Dict[str, Any],
|
|
46
|
+
):
|
|
47
|
+
"""
|
|
48
|
+
Execute a fast task from the service executor queue.
|
|
49
|
+
This task is used for operations that should complete quickly.
|
|
50
|
+
"""
|
|
51
|
+
logger.info(f"Executing fast task: {task_name} for user {user_id}, task {task_id}, step {step}")
|
|
52
|
+
return _execute_service_task(
|
|
53
|
+
self,
|
|
54
|
+
task_name,
|
|
55
|
+
user_id,
|
|
56
|
+
task_id,
|
|
57
|
+
step,
|
|
58
|
+
mode,
|
|
59
|
+
service,
|
|
60
|
+
input_data,
|
|
61
|
+
context,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@celery_app.task(bind=True, name="aiecs.tasks.worker.execute_heavy_task")
|
|
66
|
+
def execute_heavy_task(
|
|
67
|
+
self,
|
|
68
|
+
task_name: str,
|
|
69
|
+
user_id: str,
|
|
70
|
+
task_id: str,
|
|
71
|
+
step: int,
|
|
72
|
+
mode: str,
|
|
73
|
+
service: str,
|
|
74
|
+
input_data: Dict[str, Any],
|
|
75
|
+
context: Dict[str, Any],
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Execute a heavy task from the service executor queue.
|
|
79
|
+
This task is used for operations that may take longer to complete.
|
|
80
|
+
"""
|
|
81
|
+
logger.info(
|
|
82
|
+
f"Executing heavy task: {task_name} for user {user_id}, task {task_id}, step {step}"
|
|
83
|
+
)
|
|
84
|
+
return _execute_service_task(
|
|
85
|
+
self,
|
|
86
|
+
task_name,
|
|
87
|
+
user_id,
|
|
88
|
+
task_id,
|
|
89
|
+
step,
|
|
90
|
+
mode,
|
|
91
|
+
service,
|
|
92
|
+
input_data,
|
|
93
|
+
context,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _execute_service_task(
|
|
98
|
+
self,
|
|
99
|
+
task_name: str,
|
|
100
|
+
user_id: str,
|
|
101
|
+
task_id: str,
|
|
102
|
+
step: int,
|
|
103
|
+
mode: str,
|
|
104
|
+
service: str,
|
|
105
|
+
input_data: Dict[str, Any],
|
|
106
|
+
context: Dict[str, Any],
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Common implementation for executing both fast and heavy tasks.
|
|
110
|
+
This function handles the actual task execution logic.
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
# 1. Push started status
|
|
114
|
+
push_progress(
|
|
115
|
+
user_id,
|
|
116
|
+
{
|
|
117
|
+
"status": TaskStatus.RUNNING.value,
|
|
118
|
+
"step": step,
|
|
119
|
+
"task": task_name,
|
|
120
|
+
"message": f"Executing task: {task_name}",
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# 2. Get the service instance
|
|
125
|
+
service_cls = get_ai_service(mode, service)
|
|
126
|
+
service_instance = service_cls()
|
|
127
|
+
|
|
128
|
+
# 3. Execute the task
|
|
129
|
+
if hasattr(service_instance, task_name) and callable(getattr(service_instance, task_name)):
|
|
130
|
+
method = getattr(service_instance, task_name)
|
|
131
|
+
result = method(input_data, context)
|
|
132
|
+
else:
|
|
133
|
+
# Fallback to a generic execution method if the specific task
|
|
134
|
+
# method doesn't exist
|
|
135
|
+
result = service_instance.execute_task(task_name, input_data, context)
|
|
136
|
+
|
|
137
|
+
# 4. Push completed status
|
|
138
|
+
push_progress(
|
|
139
|
+
user_id,
|
|
140
|
+
{
|
|
141
|
+
"status": TaskStatus.COMPLETED.value,
|
|
142
|
+
"step": step,
|
|
143
|
+
"task": task_name,
|
|
144
|
+
"result": result,
|
|
145
|
+
"message": f"Completed task: {task_name}",
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
"status": TaskStatus.COMPLETED.value,
|
|
151
|
+
"task": task_name,
|
|
152
|
+
"result": result,
|
|
153
|
+
}
|
|
154
|
+
except Exception as e:
|
|
155
|
+
logger.error(f"Error executing task {task_name}: {str(e)}", exc_info=True)
|
|
156
|
+
# Push error status
|
|
157
|
+
push_progress(
|
|
158
|
+
user_id,
|
|
159
|
+
{
|
|
160
|
+
"status": TaskStatus.FAILED.value,
|
|
161
|
+
"step": step,
|
|
162
|
+
"task": task_name,
|
|
163
|
+
"error": str(e),
|
|
164
|
+
"message": f"Failed to execute task: {task_name}",
|
|
165
|
+
},
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
"status": TaskStatus.FAILED.value,
|
|
170
|
+
"task": task_name,
|
|
171
|
+
"error": str(e),
|
|
172
|
+
}
|