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,542 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Langchain Adapter: Converts BaseTool and its sub-functions into Langchain ReAct Agent compatible tool collections
|
|
3
|
+
|
|
4
|
+
Main Features:
|
|
5
|
+
1. Automatically discover all operation methods of BaseTool
|
|
6
|
+
2. Create independent Langchain Tool for each operation
|
|
7
|
+
3. Maintain all original functionality features (caching, validation, security, etc.)
|
|
8
|
+
4. Support synchronous and asynchronous execution
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import inspect
|
|
12
|
+
import logging
|
|
13
|
+
from typing import Any, Dict, List, Optional, Type
|
|
14
|
+
from pydantic import BaseModel
|
|
15
|
+
|
|
16
|
+
# Import schema generator
|
|
17
|
+
from aiecs.tools.schema_generator import generate_schema_from_method
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from langchain.tools import BaseTool as LangchainBaseTool
|
|
21
|
+
from langchain.callbacks.manager import (
|
|
22
|
+
CallbackManagerForToolRun,
|
|
23
|
+
AsyncCallbackManagerForToolRun,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
LANGCHAIN_AVAILABLE = True
|
|
27
|
+
except ImportError:
|
|
28
|
+
# If langchain is not installed, create simple base class for type checking
|
|
29
|
+
class LangchainBaseTool:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
CallbackManagerForToolRun = None
|
|
33
|
+
AsyncCallbackManagerForToolRun = None
|
|
34
|
+
LANGCHAIN_AVAILABLE = False
|
|
35
|
+
|
|
36
|
+
from aiecs.tools.base_tool import BaseTool
|
|
37
|
+
from aiecs.tools import get_tool, list_tools, TOOL_CLASSES
|
|
38
|
+
|
|
39
|
+
logger = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class LangchainToolAdapter(LangchainBaseTool):
|
|
43
|
+
"""
|
|
44
|
+
Langchain tool adapter for single operation
|
|
45
|
+
|
|
46
|
+
Wraps one operation method of BaseTool as an independent Langchain tool.
|
|
47
|
+
Supports both tool-level operations and provider-level operations.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
# Define class attributes
|
|
51
|
+
name: str = ""
|
|
52
|
+
description: str = ""
|
|
53
|
+
base_tool_name: str = ""
|
|
54
|
+
operation_name: str = ""
|
|
55
|
+
operation_schema: Optional[Type[BaseModel]] = None
|
|
56
|
+
is_provider_operation: bool = False
|
|
57
|
+
provider_name: Optional[str] = None
|
|
58
|
+
method_name: Optional[str] = None
|
|
59
|
+
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
base_tool_name: str,
|
|
63
|
+
operation_name: str,
|
|
64
|
+
operation_schema: Optional[Type[BaseModel]] = None,
|
|
65
|
+
description: Optional[str] = None,
|
|
66
|
+
is_provider_operation: bool = False,
|
|
67
|
+
provider_name: Optional[str] = None,
|
|
68
|
+
method_name: Optional[str] = None,
|
|
69
|
+
):
|
|
70
|
+
"""
|
|
71
|
+
Initialize adapter
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
base_tool_name: Original tool name
|
|
75
|
+
operation_name: Operation name
|
|
76
|
+
operation_schema: Pydantic Schema for the operation
|
|
77
|
+
description: Tool description
|
|
78
|
+
is_provider_operation: Whether this is a provider-level operation
|
|
79
|
+
provider_name: Provider name (for provider operations)
|
|
80
|
+
method_name: Original method name (for provider operations)
|
|
81
|
+
"""
|
|
82
|
+
# Construct tool name and description
|
|
83
|
+
tool_name = f"{base_tool_name}_{operation_name}"
|
|
84
|
+
tool_description = (
|
|
85
|
+
description or f"Execute {operation_name} operation from {base_tool_name} tool"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Initialize parent class with all required fields
|
|
89
|
+
super().__init__(
|
|
90
|
+
name=tool_name,
|
|
91
|
+
description=tool_description,
|
|
92
|
+
base_tool_name=base_tool_name,
|
|
93
|
+
operation_name=operation_name,
|
|
94
|
+
operation_schema=operation_schema,
|
|
95
|
+
args_schema=operation_schema,
|
|
96
|
+
is_provider_operation=is_provider_operation,
|
|
97
|
+
provider_name=provider_name,
|
|
98
|
+
method_name=method_name,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def _run(
|
|
102
|
+
self,
|
|
103
|
+
run_manager: Optional[CallbackManagerForToolRun] = None,
|
|
104
|
+
**kwargs: Any,
|
|
105
|
+
) -> Any:
|
|
106
|
+
"""Execute operation synchronously"""
|
|
107
|
+
try:
|
|
108
|
+
# Get original tool instance
|
|
109
|
+
base_tool = get_tool(self.base_tool_name)
|
|
110
|
+
|
|
111
|
+
# Handle provider operations differently
|
|
112
|
+
if self.is_provider_operation:
|
|
113
|
+
# For provider operations, call the query method with provider
|
|
114
|
+
# and operation
|
|
115
|
+
result = base_tool.run(
|
|
116
|
+
"query",
|
|
117
|
+
provider=self.provider_name,
|
|
118
|
+
operation=self.method_name,
|
|
119
|
+
params=kwargs,
|
|
120
|
+
)
|
|
121
|
+
else:
|
|
122
|
+
# For tool-level operations, call directly
|
|
123
|
+
result = base_tool.run(self.operation_name, **kwargs)
|
|
124
|
+
|
|
125
|
+
logger.info(f"Successfully executed {self.name} with result type: {type(result)}")
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.error(f"Error executing {self.name}: {str(e)}")
|
|
130
|
+
raise
|
|
131
|
+
|
|
132
|
+
async def _arun(
|
|
133
|
+
self,
|
|
134
|
+
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
|
|
135
|
+
**kwargs: Any,
|
|
136
|
+
) -> Any:
|
|
137
|
+
"""Execute operation asynchronously"""
|
|
138
|
+
try:
|
|
139
|
+
# Get original tool instance
|
|
140
|
+
base_tool = get_tool(self.base_tool_name)
|
|
141
|
+
|
|
142
|
+
# Execute asynchronous operation
|
|
143
|
+
result = await base_tool.run_async(self.operation_name, **kwargs)
|
|
144
|
+
|
|
145
|
+
logger.info(f"Successfully executed {self.name} async with result type: {type(result)}")
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
logger.error(f"Error executing {self.name} async: {str(e)}")
|
|
150
|
+
raise
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class ToolRegistry:
|
|
154
|
+
"""Tool Registry: Manages conversion from BaseTool to Langchain tools"""
|
|
155
|
+
|
|
156
|
+
def __init__(self):
|
|
157
|
+
self._langchain_tools: Dict[str, LangchainToolAdapter] = {}
|
|
158
|
+
|
|
159
|
+
def discover_operations(self, base_tool_class: Type[BaseTool]) -> List[Dict[str, Any]]:
|
|
160
|
+
"""
|
|
161
|
+
Discover all operation methods and Schemas of BaseTool class.
|
|
162
|
+
|
|
163
|
+
Enhanced to support provider-level operations for tools like APISourceTool
|
|
164
|
+
that expose fine-grained operations from underlying providers.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
base_tool_class: BaseTool subclass
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
List of operation information, including method names, Schemas, descriptions, etc.
|
|
171
|
+
"""
|
|
172
|
+
operations = []
|
|
173
|
+
|
|
174
|
+
# 1. Discover tool-level operations (existing logic)
|
|
175
|
+
tool_operations = self._discover_tool_operations(base_tool_class)
|
|
176
|
+
operations.extend(tool_operations)
|
|
177
|
+
|
|
178
|
+
# 2. Discover provider-level operations (new logic)
|
|
179
|
+
if hasattr(base_tool_class, "_discover_provider_operations"):
|
|
180
|
+
try:
|
|
181
|
+
provider_operations = base_tool_class._discover_provider_operations()
|
|
182
|
+
|
|
183
|
+
# Convert provider operations to the expected format
|
|
184
|
+
for provider_op in provider_operations:
|
|
185
|
+
operation_info = {
|
|
186
|
+
"name": provider_op["name"],
|
|
187
|
+
"method": None, # Will be handled specially in create_langchain_tools
|
|
188
|
+
"schema": provider_op["schema"],
|
|
189
|
+
"description": provider_op["description"],
|
|
190
|
+
"is_async": False,
|
|
191
|
+
"is_provider_operation": True, # Mark as provider operation
|
|
192
|
+
"provider_name": provider_op.get("provider_name"),
|
|
193
|
+
"method_name": provider_op.get("method_name"),
|
|
194
|
+
}
|
|
195
|
+
operations.append(operation_info)
|
|
196
|
+
logger.debug(f"Added provider operation: {provider_op['name']}")
|
|
197
|
+
|
|
198
|
+
logger.info(
|
|
199
|
+
f"Discovered {len(provider_operations)} provider operations for {base_tool_class.__name__}"
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
logger.warning(
|
|
204
|
+
f"Error discovering provider operations for {base_tool_class.__name__}: {e}"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
return operations
|
|
208
|
+
|
|
209
|
+
def _discover_tool_operations(self, base_tool_class: Type[BaseTool]) -> List[Dict[str, Any]]:
|
|
210
|
+
"""
|
|
211
|
+
Discover tool-level operations (original logic extracted to separate method).
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
base_tool_class: BaseTool subclass
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
List of tool-level operation information
|
|
218
|
+
"""
|
|
219
|
+
operations = []
|
|
220
|
+
|
|
221
|
+
# Get all Schema classes
|
|
222
|
+
# Build a mapping from normalized names to Schema classes
|
|
223
|
+
# Check both class-level and module-level schemas
|
|
224
|
+
schemas = {}
|
|
225
|
+
|
|
226
|
+
# 1. Check class-level schemas (e.g., ChartTool)
|
|
227
|
+
for attr_name in dir(base_tool_class):
|
|
228
|
+
attr = getattr(base_tool_class, attr_name)
|
|
229
|
+
if (
|
|
230
|
+
isinstance(attr, type)
|
|
231
|
+
and issubclass(attr, BaseModel)
|
|
232
|
+
and attr.__name__.endswith("Schema")
|
|
233
|
+
):
|
|
234
|
+
# Normalize: remove 'Schema' suffix, convert to lowercase,
|
|
235
|
+
# remove underscores
|
|
236
|
+
schema_base_name = attr.__name__.replace("Schema", "")
|
|
237
|
+
normalized_name = schema_base_name.replace("_", "").lower()
|
|
238
|
+
schemas[normalized_name] = attr
|
|
239
|
+
logger.debug(
|
|
240
|
+
f"Found class-level schema {attr.__name__} -> normalized: {normalized_name}"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# 2. Check module-level schemas (e.g., ImageTool)
|
|
244
|
+
tool_module = inspect.getmodule(base_tool_class)
|
|
245
|
+
if tool_module:
|
|
246
|
+
for attr_name in dir(tool_module):
|
|
247
|
+
if attr_name.startswith("_"):
|
|
248
|
+
continue
|
|
249
|
+
attr = getattr(tool_module, attr_name)
|
|
250
|
+
if (
|
|
251
|
+
isinstance(attr, type)
|
|
252
|
+
and issubclass(attr, BaseModel)
|
|
253
|
+
and attr.__name__.endswith("Schema")
|
|
254
|
+
):
|
|
255
|
+
# Skip if already found at class level
|
|
256
|
+
schema_base_name = attr.__name__.replace("Schema", "")
|
|
257
|
+
normalized_name = schema_base_name.replace("_", "").lower()
|
|
258
|
+
if normalized_name not in schemas:
|
|
259
|
+
schemas[normalized_name] = attr
|
|
260
|
+
logger.debug(
|
|
261
|
+
f"Found module-level schema {attr.__name__} -> normalized: {normalized_name}"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# Get all public methods
|
|
265
|
+
for method_name in dir(base_tool_class):
|
|
266
|
+
if method_name.startswith("_"):
|
|
267
|
+
continue
|
|
268
|
+
|
|
269
|
+
method = getattr(base_tool_class, method_name)
|
|
270
|
+
if not callable(method):
|
|
271
|
+
continue
|
|
272
|
+
|
|
273
|
+
# Skip base class methods and Schema classes themselves
|
|
274
|
+
if method_name in ["run", "run_async", "run_batch"]:
|
|
275
|
+
continue
|
|
276
|
+
|
|
277
|
+
# Skip if it's a class (like Config or Schema classes)
|
|
278
|
+
if isinstance(method, type):
|
|
279
|
+
continue
|
|
280
|
+
|
|
281
|
+
# Normalize method name: remove underscores and convert to
|
|
282
|
+
# lowercase
|
|
283
|
+
normalized_method_name = method_name.replace("_", "").lower()
|
|
284
|
+
|
|
285
|
+
# Try to find matching schema
|
|
286
|
+
matching_schema = schemas.get(normalized_method_name)
|
|
287
|
+
|
|
288
|
+
if matching_schema:
|
|
289
|
+
logger.debug(
|
|
290
|
+
f"Matched method {method_name} with manual schema {matching_schema.__name__}"
|
|
291
|
+
)
|
|
292
|
+
else:
|
|
293
|
+
# Auto-generate schema if not found
|
|
294
|
+
auto_schema = generate_schema_from_method(method, method_name)
|
|
295
|
+
if auto_schema:
|
|
296
|
+
matching_schema = auto_schema
|
|
297
|
+
logger.debug(
|
|
298
|
+
f"Auto-generated schema for method {method_name}: {auto_schema.__name__}"
|
|
299
|
+
)
|
|
300
|
+
else:
|
|
301
|
+
logger.debug(f"No schema found or generated for method {method_name}")
|
|
302
|
+
|
|
303
|
+
# Get method information
|
|
304
|
+
operation_info = {
|
|
305
|
+
"name": method_name,
|
|
306
|
+
"method": method,
|
|
307
|
+
"schema": matching_schema,
|
|
308
|
+
"description": inspect.getdoc(method) or f"Execute {method_name} operation",
|
|
309
|
+
"is_async": inspect.iscoroutinefunction(method),
|
|
310
|
+
"is_provider_operation": False, # Mark as tool-level operation
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
operations.append(operation_info)
|
|
314
|
+
|
|
315
|
+
return operations
|
|
316
|
+
|
|
317
|
+
def _extract_description(
|
|
318
|
+
self,
|
|
319
|
+
method,
|
|
320
|
+
base_tool_name: str,
|
|
321
|
+
operation_name: str,
|
|
322
|
+
schema: Optional[Type[BaseModel]] = None,
|
|
323
|
+
) -> str:
|
|
324
|
+
"""Extract detailed description from method docstring and schema"""
|
|
325
|
+
doc = inspect.getdoc(method)
|
|
326
|
+
|
|
327
|
+
# Base description
|
|
328
|
+
if doc:
|
|
329
|
+
base_desc = doc.split("\n")[0].strip()
|
|
330
|
+
else:
|
|
331
|
+
base_desc = f"Execute {operation_name} operation"
|
|
332
|
+
|
|
333
|
+
# Enhanced description - add specific tool functionality description
|
|
334
|
+
enhanced_desc = f"{base_desc}"
|
|
335
|
+
|
|
336
|
+
# Add specific descriptions based on tool name and operation
|
|
337
|
+
if base_tool_name == "chart":
|
|
338
|
+
if operation_name == "read_data":
|
|
339
|
+
enhanced_desc = "Read and analyze data files in multiple formats (CSV, Excel, JSON, Parquet, etc.). Returns data structure summary, preview, and optional export functionality."
|
|
340
|
+
elif operation_name == "visualize":
|
|
341
|
+
enhanced_desc = "Create data visualizations including histograms, scatter plots, bar charts, line charts, heatmaps, and pair plots. Supports customizable styling, colors, and high-resolution output."
|
|
342
|
+
elif operation_name == "export_data":
|
|
343
|
+
enhanced_desc = "Export data to various formats (JSON, CSV, HTML, Excel, Markdown) with optional variable selection and path customization."
|
|
344
|
+
elif base_tool_name == "pandas":
|
|
345
|
+
enhanced_desc = f"Pandas data manipulation: {base_desc}. Supports DataFrame operations with built-in validation and error handling."
|
|
346
|
+
elif base_tool_name == "stats":
|
|
347
|
+
enhanced_desc = f"Statistical analysis: {base_desc}. Provides statistical tests, regression analysis, and data preprocessing capabilities."
|
|
348
|
+
|
|
349
|
+
# Add parameter information
|
|
350
|
+
if schema:
|
|
351
|
+
try:
|
|
352
|
+
fields = schema.__fields__ if hasattr(schema, "__fields__") else {}
|
|
353
|
+
if fields:
|
|
354
|
+
required_params = [
|
|
355
|
+
name for name, field in fields.items() if field.is_required()
|
|
356
|
+
]
|
|
357
|
+
optional_params = [
|
|
358
|
+
name for name, field in fields.items() if not field.is_required()
|
|
359
|
+
]
|
|
360
|
+
|
|
361
|
+
param_desc = ""
|
|
362
|
+
if required_params:
|
|
363
|
+
param_desc += f" Required: {', '.join(required_params)}."
|
|
364
|
+
if optional_params:
|
|
365
|
+
param_desc += f" Optional: {', '.join(optional_params)}."
|
|
366
|
+
|
|
367
|
+
enhanced_desc += param_desc
|
|
368
|
+
except Exception:
|
|
369
|
+
pass
|
|
370
|
+
|
|
371
|
+
return enhanced_desc
|
|
372
|
+
|
|
373
|
+
def create_langchain_tools(self, tool_name: str) -> List[LangchainToolAdapter]:
|
|
374
|
+
"""
|
|
375
|
+
Create all Langchain adapters for specified tool
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
tool_name: Tool name
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
List of Langchain tool adapters
|
|
382
|
+
"""
|
|
383
|
+
if not LANGCHAIN_AVAILABLE:
|
|
384
|
+
raise ImportError("langchain is not installed. Please install it to use this adapter.")
|
|
385
|
+
|
|
386
|
+
if tool_name not in TOOL_CLASSES:
|
|
387
|
+
raise ValueError(f"Tool '{tool_name}' not found in registry")
|
|
388
|
+
|
|
389
|
+
base_tool_class = TOOL_CLASSES[tool_name]
|
|
390
|
+
operations = self.discover_operations(base_tool_class)
|
|
391
|
+
|
|
392
|
+
langchain_tools = []
|
|
393
|
+
for op_info in operations:
|
|
394
|
+
# Generate enhanced description
|
|
395
|
+
# For provider operations, use the description directly
|
|
396
|
+
if op_info.get("is_provider_operation", False):
|
|
397
|
+
enhanced_description = op_info["description"]
|
|
398
|
+
else:
|
|
399
|
+
enhanced_description = self._extract_description(
|
|
400
|
+
op_info["method"],
|
|
401
|
+
tool_name,
|
|
402
|
+
op_info["name"],
|
|
403
|
+
op_info["schema"],
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
# Create adapter with provider operation support
|
|
407
|
+
adapter = LangchainToolAdapter(
|
|
408
|
+
base_tool_name=tool_name,
|
|
409
|
+
operation_name=op_info["name"],
|
|
410
|
+
operation_schema=op_info["schema"],
|
|
411
|
+
description=enhanced_description,
|
|
412
|
+
is_provider_operation=op_info.get("is_provider_operation", False),
|
|
413
|
+
provider_name=op_info.get("provider_name"),
|
|
414
|
+
method_name=op_info.get("method_name"),
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
langchain_tools.append(adapter)
|
|
418
|
+
self._langchain_tools[adapter.name] = adapter
|
|
419
|
+
|
|
420
|
+
logger.info(f"Created {len(langchain_tools)} Langchain tools for {tool_name}")
|
|
421
|
+
return langchain_tools
|
|
422
|
+
|
|
423
|
+
def create_all_langchain_tools(self) -> List[LangchainToolAdapter]:
|
|
424
|
+
"""
|
|
425
|
+
Create Langchain adapters for all registered BaseTools
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
List of all Langchain tool adapters
|
|
429
|
+
"""
|
|
430
|
+
all_tools = []
|
|
431
|
+
|
|
432
|
+
# list_tools() returns a list of dicts, extract tool names
|
|
433
|
+
tool_infos = list_tools()
|
|
434
|
+
for tool_info in tool_infos:
|
|
435
|
+
tool_name = tool_info["name"]
|
|
436
|
+
try:
|
|
437
|
+
tools = self.create_langchain_tools(tool_name)
|
|
438
|
+
all_tools.extend(tools)
|
|
439
|
+
except Exception as e:
|
|
440
|
+
logger.error(f"Failed to create Langchain tools for {tool_name}: {e}")
|
|
441
|
+
|
|
442
|
+
logger.info(
|
|
443
|
+
f"Created total {len(all_tools)} Langchain tools from {len(tool_infos)} base tools"
|
|
444
|
+
)
|
|
445
|
+
return all_tools
|
|
446
|
+
|
|
447
|
+
def get_tool(self, name: str) -> Optional[LangchainToolAdapter]:
|
|
448
|
+
"""Get Langchain tool with specified name"""
|
|
449
|
+
return self._langchain_tools.get(name)
|
|
450
|
+
|
|
451
|
+
def list_langchain_tools(self) -> List[str]:
|
|
452
|
+
"""List all Langchain tool names"""
|
|
453
|
+
return list(self._langchain_tools.keys())
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
# Global registry instance
|
|
457
|
+
tool_registry = ToolRegistry()
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def get_langchain_tools(
|
|
461
|
+
tool_names: Optional[List[str]] = None,
|
|
462
|
+
) -> List[LangchainToolAdapter]:
|
|
463
|
+
"""
|
|
464
|
+
Get Langchain tool collection
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
tool_names: List of tool names to convert, None means convert all tools
|
|
468
|
+
|
|
469
|
+
Returns:
|
|
470
|
+
List of Langchain tool adapters
|
|
471
|
+
"""
|
|
472
|
+
if tool_names is None:
|
|
473
|
+
return tool_registry.create_all_langchain_tools()
|
|
474
|
+
|
|
475
|
+
all_tools = []
|
|
476
|
+
for tool_name in tool_names:
|
|
477
|
+
tools = tool_registry.create_langchain_tools(tool_name)
|
|
478
|
+
all_tools.extend(tools)
|
|
479
|
+
|
|
480
|
+
return all_tools
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def create_react_agent_tools() -> List[LangchainToolAdapter]:
|
|
484
|
+
"""
|
|
485
|
+
Create complete tool collection for ReAct Agent
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
List of adapted Langchain tools
|
|
489
|
+
"""
|
|
490
|
+
return get_langchain_tools()
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def create_tool_calling_agent_tools() -> List[LangchainToolAdapter]:
|
|
494
|
+
"""
|
|
495
|
+
Create complete tool collection for Tool Calling Agent
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
List of adapted Langchain tools optimized for tool calling
|
|
499
|
+
"""
|
|
500
|
+
return get_langchain_tools()
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
# Compatibility check functionality
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def check_langchain_compatibility() -> Dict[str, Any]:
|
|
507
|
+
"""
|
|
508
|
+
Check compatibility between current environment and Langchain
|
|
509
|
+
|
|
510
|
+
Returns:
|
|
511
|
+
Compatibility check results
|
|
512
|
+
"""
|
|
513
|
+
result = {
|
|
514
|
+
"langchain_available": LANGCHAIN_AVAILABLE,
|
|
515
|
+
"total_base_tools": len(list_tools()),
|
|
516
|
+
"compatible_tools": [],
|
|
517
|
+
"incompatible_tools": [],
|
|
518
|
+
"total_operations": 0,
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if not LANGCHAIN_AVAILABLE:
|
|
522
|
+
result["error"] = "Langchain not installed"
|
|
523
|
+
return result
|
|
524
|
+
|
|
525
|
+
for tool_name in list_tools():
|
|
526
|
+
try:
|
|
527
|
+
tool_class = TOOL_CLASSES[tool_name]
|
|
528
|
+
operations = tool_registry.discover_operations(tool_class)
|
|
529
|
+
|
|
530
|
+
result["compatible_tools"].append(
|
|
531
|
+
{
|
|
532
|
+
"name": tool_name,
|
|
533
|
+
"operations_count": len(operations),
|
|
534
|
+
"operations": [op["name"] for op in operations],
|
|
535
|
+
}
|
|
536
|
+
)
|
|
537
|
+
result["total_operations"] += len(operations)
|
|
538
|
+
|
|
539
|
+
except Exception as e:
|
|
540
|
+
result["incompatible_tools"].append({"name": tool_name, "error": str(e)})
|
|
541
|
+
|
|
542
|
+
return result
|