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
|
@@ -6,17 +6,20 @@ import logging
|
|
|
6
6
|
from typing import Dict, Any, List, Optional, Union, Tuple
|
|
7
7
|
from enum import Enum
|
|
8
8
|
|
|
9
|
-
from pydantic import BaseModel, Field, field_validator
|
|
9
|
+
from pydantic import BaseModel, Field, field_validator
|
|
10
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
10
11
|
import numpy as np
|
|
11
|
-
import pandas as pd
|
|
12
|
+
import pandas as pd # type: ignore[import-untyped]
|
|
12
13
|
import matplotlib.pyplot as plt
|
|
13
|
-
import seaborn as sns
|
|
14
|
+
import seaborn as sns # type: ignore[import-untyped]
|
|
14
15
|
|
|
15
16
|
from aiecs.tools import register_tool
|
|
16
17
|
from aiecs.tools.base_tool import BaseTool
|
|
17
18
|
from aiecs.tools.tool_executor import measure_execution_time
|
|
18
19
|
|
|
19
20
|
# Enums for configuration options
|
|
21
|
+
|
|
22
|
+
|
|
20
23
|
class ExportFormat(str, Enum):
|
|
21
24
|
JSON = "json"
|
|
22
25
|
CSV = "csv"
|
|
@@ -24,6 +27,7 @@ class ExportFormat(str, Enum):
|
|
|
24
27
|
EXCEL = "excel"
|
|
25
28
|
MARKDOWN = "markdown"
|
|
26
29
|
|
|
30
|
+
|
|
27
31
|
class VisualizationType(str, Enum):
|
|
28
32
|
HISTOGRAM = "histogram"
|
|
29
33
|
BOXPLOT = "boxplot"
|
|
@@ -33,177 +37,147 @@ class VisualizationType(str, Enum):
|
|
|
33
37
|
HEATMAP = "heatmap"
|
|
34
38
|
PAIR = "pair"
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
|
|
41
|
+
@register_tool("chart")
|
|
37
42
|
class ChartTool(BaseTool):
|
|
38
43
|
"""Chart and visualization tool: creates charts and exports data in various formats."""
|
|
39
44
|
|
|
40
45
|
# Configuration schema
|
|
41
|
-
class Config(
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
class Config(BaseSettings):
|
|
47
|
+
"""Configuration for the chart tool
|
|
48
|
+
|
|
49
|
+
Automatically reads from environment variables with CHART_TOOL_ prefix.
|
|
50
|
+
Example: CHART_TOOL_EXPORT_DIR -> export_dir
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
model_config = SettingsConfigDict(env_prefix="CHART_TOOL_")
|
|
54
|
+
|
|
44
55
|
export_dir: str = Field(
|
|
45
|
-
default=os.path.join(tempfile.gettempdir(),
|
|
46
|
-
description="Directory to export files to"
|
|
47
|
-
)
|
|
48
|
-
plot_dpi: int = Field(
|
|
49
|
-
default=100,
|
|
50
|
-
description="DPI for plot exports"
|
|
56
|
+
default=os.path.join(tempfile.gettempdir(), "chart_exports"),
|
|
57
|
+
description="Directory to export files to",
|
|
51
58
|
)
|
|
59
|
+
plot_dpi: int = Field(default=100, description="DPI for plot exports")
|
|
52
60
|
plot_figsize: Tuple[int, int] = Field(
|
|
53
61
|
default=(10, 6),
|
|
54
|
-
description="Default figure size (width, height) in inches"
|
|
62
|
+
description="Default figure size (width, height) in inches",
|
|
55
63
|
)
|
|
56
64
|
allowed_extensions: List[str] = Field(
|
|
57
|
-
default=[
|
|
58
|
-
|
|
65
|
+
default=[
|
|
66
|
+
".csv",
|
|
67
|
+
".xlsx",
|
|
68
|
+
".xls",
|
|
69
|
+
".json",
|
|
70
|
+
".parquet",
|
|
71
|
+
".feather",
|
|
72
|
+
".sav",
|
|
73
|
+
".sas7bdat",
|
|
74
|
+
".por",
|
|
75
|
+
],
|
|
76
|
+
description="Allowed file extensions",
|
|
59
77
|
)
|
|
60
78
|
|
|
61
79
|
# Input schemas for operations
|
|
62
|
-
class
|
|
63
|
-
"""Schema for
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
71
|
-
sheet_name: Optional[Union[str, int]] = Field(
|
|
72
|
-
default=0,
|
|
73
|
-
description="Sheet name or index for Excel files"
|
|
74
|
-
)
|
|
75
|
-
export_format: Optional[ExportFormat] = Field(
|
|
76
|
-
default=None,
|
|
77
|
-
description="Format to export results in"
|
|
78
|
-
)
|
|
79
|
-
export_path: Optional[str] = Field(
|
|
80
|
-
default=None,
|
|
81
|
-
description="Path to export results to"
|
|
82
|
-
)
|
|
80
|
+
class Read_dataSchema(BaseModel):
|
|
81
|
+
"""Schema for read_data operation"""
|
|
82
|
+
|
|
83
|
+
file_path: str = Field(description="Path to the data file")
|
|
84
|
+
nrows: Optional[int] = Field(default=None, description="Number of rows to read")
|
|
85
|
+
sheet_name: Optional[Union[str, int]] = Field(default=0, description="Sheet name or index for Excel files")
|
|
86
|
+
export_format: Optional[ExportFormat] = Field(default=None, description="Format to export results in")
|
|
87
|
+
export_path: Optional[str] = Field(default=None, description="Path to export results to")
|
|
83
88
|
|
|
84
|
-
@field_validator(
|
|
89
|
+
@field_validator("file_path")
|
|
85
90
|
@classmethod
|
|
86
91
|
def validate_file_path(cls, v):
|
|
87
92
|
if not os.path.isfile(v):
|
|
88
93
|
raise ValueError(f"File not found: {v}")
|
|
89
94
|
return v
|
|
90
95
|
|
|
91
|
-
@field_validator(
|
|
96
|
+
@field_validator("export_path")
|
|
92
97
|
@classmethod
|
|
93
98
|
def validate_export_path(cls, v, info):
|
|
94
|
-
if v and
|
|
99
|
+
if v and "export_format" not in info.data:
|
|
95
100
|
raise ValueError("export_format must be specified when export_path is provided")
|
|
96
101
|
return v
|
|
97
102
|
|
|
98
|
-
class
|
|
99
|
-
"""Schema for
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
-
x: Optional[str] = Field(
|
|
107
|
-
default=None,
|
|
108
|
-
description="Column to use for x-axis"
|
|
109
|
-
)
|
|
110
|
-
y: Optional[str] = Field(
|
|
111
|
-
default=None,
|
|
112
|
-
description="Column to use for y-axis"
|
|
113
|
-
)
|
|
114
|
-
hue: Optional[str] = Field(
|
|
115
|
-
default=None,
|
|
116
|
-
description="Column to use for color encoding"
|
|
117
|
-
)
|
|
103
|
+
class VisualizeSchema(BaseModel):
|
|
104
|
+
"""Schema for visualize operation"""
|
|
105
|
+
|
|
106
|
+
file_path: str = Field(description="Path to the data file")
|
|
107
|
+
plot_type: VisualizationType = Field(description="Type of visualization to create")
|
|
108
|
+
x: Optional[str] = Field(default=None, description="Column to use for x-axis")
|
|
109
|
+
y: Optional[str] = Field(default=None, description="Column to use for y-axis")
|
|
110
|
+
hue: Optional[str] = Field(default=None, description="Column to use for color encoding")
|
|
118
111
|
variables: Optional[List[str]] = Field(
|
|
119
112
|
default=None,
|
|
120
|
-
description="List of variables to include in the visualization"
|
|
113
|
+
description="List of variables to include in the visualization",
|
|
121
114
|
)
|
|
122
|
-
title: Optional[str] = Field(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
130
|
-
output_path: Optional[str] = Field(
|
|
131
|
-
default=None,
|
|
132
|
-
description="Path to save the visualization"
|
|
133
|
-
)
|
|
134
|
-
dpi: Optional[int] = Field(
|
|
135
|
-
default=None,
|
|
136
|
-
description="DPI for the visualization"
|
|
137
|
-
)
|
|
138
|
-
export_format: Optional[ExportFormat] = Field(
|
|
139
|
-
default=None,
|
|
140
|
-
description="Format to export results in"
|
|
141
|
-
)
|
|
142
|
-
export_path: Optional[str] = Field(
|
|
143
|
-
default=None,
|
|
144
|
-
description="Path to export results to"
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
@field_validator('file_path')
|
|
115
|
+
title: Optional[str] = Field(default=None, description="Title for the visualization")
|
|
116
|
+
figsize: Optional[Tuple[int, int]] = Field(default=None, description="Figure size (width, height) in inches")
|
|
117
|
+
output_path: Optional[str] = Field(default=None, description="Path to save the visualization")
|
|
118
|
+
dpi: Optional[int] = Field(default=None, description="DPI for the visualization")
|
|
119
|
+
export_format: Optional[ExportFormat] = Field(default=None, description="Format to export results in")
|
|
120
|
+
export_path: Optional[str] = Field(default=None, description="Path to export results to")
|
|
121
|
+
|
|
122
|
+
@field_validator("file_path")
|
|
148
123
|
@classmethod
|
|
149
124
|
def validate_file_path(cls, v):
|
|
150
125
|
if not os.path.isfile(v):
|
|
151
126
|
raise ValueError(f"File not found: {v}")
|
|
152
127
|
return v
|
|
153
128
|
|
|
154
|
-
@field_validator(
|
|
129
|
+
@field_validator("export_path")
|
|
155
130
|
@classmethod
|
|
156
131
|
def validate_export_path(cls, v, info):
|
|
157
|
-
if v and
|
|
132
|
+
if v and "export_format" not in info.data:
|
|
158
133
|
raise ValueError("export_format must be specified when export_path is provided")
|
|
159
134
|
return v
|
|
160
135
|
|
|
161
|
-
class
|
|
162
|
-
"""Schema for
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
)
|
|
136
|
+
class Export_dataSchema(BaseModel):
|
|
137
|
+
"""Schema for export_data operation"""
|
|
138
|
+
|
|
139
|
+
file_path: str = Field(description="Path to the data file")
|
|
166
140
|
variables: Optional[List[str]] = Field(
|
|
167
141
|
default=None,
|
|
168
|
-
description="List of variables to include in the export"
|
|
169
|
-
)
|
|
170
|
-
format: ExportFormat = Field(
|
|
171
|
-
description="Format to export data in"
|
|
172
|
-
)
|
|
173
|
-
export_path: Optional[str] = Field(
|
|
174
|
-
default=None,
|
|
175
|
-
description="Path to save the exported data"
|
|
176
|
-
)
|
|
177
|
-
export_format: Optional[ExportFormat] = Field(
|
|
178
|
-
default=None,
|
|
179
|
-
description="Format to export results in"
|
|
142
|
+
description="List of variables to include in the export",
|
|
180
143
|
)
|
|
144
|
+
format: ExportFormat = Field(description="Format to export data in")
|
|
145
|
+
export_path: Optional[str] = Field(default=None, description="Path to save the exported data")
|
|
146
|
+
export_format: Optional[ExportFormat] = Field(default=None, description="Format to export results in")
|
|
181
147
|
|
|
182
|
-
@field_validator(
|
|
148
|
+
@field_validator("file_path")
|
|
183
149
|
@classmethod
|
|
184
150
|
def validate_file_path(cls, v):
|
|
185
151
|
if not os.path.isfile(v):
|
|
186
152
|
raise ValueError(f"File not found: {v}")
|
|
187
153
|
return v
|
|
188
154
|
|
|
189
|
-
@field_validator(
|
|
155
|
+
@field_validator("export_path")
|
|
190
156
|
@classmethod
|
|
191
157
|
def validate_export_path(cls, v, info):
|
|
192
|
-
if v and
|
|
158
|
+
if v and "export_format" not in info.data:
|
|
193
159
|
raise ValueError("export_format must be specified when export_path is provided")
|
|
194
160
|
return v
|
|
195
161
|
|
|
196
|
-
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
|
162
|
+
def __init__(self, config: Optional[Dict[str, Any]] = None, **kwargs):
|
|
197
163
|
"""
|
|
198
164
|
Initialize the chart tool
|
|
199
165
|
|
|
200
166
|
Args:
|
|
201
167
|
config: Optional configuration for the tool
|
|
168
|
+
**kwargs: Additional arguments passed to BaseTool (e.g., tool_name)
|
|
169
|
+
|
|
170
|
+
Configuration is automatically loaded by BaseTool from:
|
|
171
|
+
1. Explicit config dict (highest priority)
|
|
172
|
+
2. YAML config files (config/tools/chart.yaml)
|
|
173
|
+
3. Environment variables (via dotenv from .env files)
|
|
174
|
+
4. Tool defaults (lowest priority)
|
|
202
175
|
"""
|
|
203
|
-
super().__init__(config)
|
|
176
|
+
super().__init__(config, **kwargs)
|
|
204
177
|
|
|
205
|
-
#
|
|
206
|
-
|
|
178
|
+
# Configuration is automatically loaded by BaseTool into self._config_obj
|
|
179
|
+
# Access config via self._config_obj (BaseSettings instance)
|
|
180
|
+
self.config = self._config_obj if self._config_obj else self.Config()
|
|
207
181
|
|
|
208
182
|
# Create export directory if it doesn't exist
|
|
209
183
|
os.makedirs(self.config.export_dir, exist_ok=True)
|
|
@@ -212,9 +186,14 @@ class ChartTool(BaseTool):
|
|
|
212
186
|
self.logger = logging.getLogger(__name__)
|
|
213
187
|
|
|
214
188
|
# Set default matplotlib style
|
|
215
|
-
plt.style.use(
|
|
216
|
-
|
|
217
|
-
def _load_data(
|
|
189
|
+
plt.style.use("seaborn-v0_8-whitegrid")
|
|
190
|
+
|
|
191
|
+
def _load_data(
|
|
192
|
+
self,
|
|
193
|
+
file_path: str,
|
|
194
|
+
nrows: Optional[int] = None,
|
|
195
|
+
sheet_name: Optional[Union[str, int]] = 0,
|
|
196
|
+
) -> pd.DataFrame:
|
|
218
197
|
"""
|
|
219
198
|
Load data from various file formats into a pandas DataFrame
|
|
220
199
|
|
|
@@ -230,34 +209,37 @@ class ChartTool(BaseTool):
|
|
|
230
209
|
ext = os.path.splitext(file_path)[1].lower()
|
|
231
210
|
|
|
232
211
|
try:
|
|
233
|
-
if ext ==
|
|
234
|
-
import pyreadstat
|
|
212
|
+
if ext == ".sav":
|
|
213
|
+
import pyreadstat # type: ignore[import-untyped]
|
|
214
|
+
|
|
235
215
|
df, meta = pyreadstat.read_sav(file_path)
|
|
236
216
|
return df
|
|
237
|
-
elif ext ==
|
|
238
|
-
import pyreadstat
|
|
217
|
+
elif ext == ".sas7bdat":
|
|
218
|
+
import pyreadstat # type: ignore[import-untyped]
|
|
219
|
+
|
|
239
220
|
df, meta = pyreadstat.read_sas7bdat(file_path)
|
|
240
221
|
return df
|
|
241
|
-
elif ext ==
|
|
242
|
-
import pyreadstat
|
|
222
|
+
elif ext == ".por":
|
|
223
|
+
import pyreadstat # type: ignore[import-untyped]
|
|
224
|
+
|
|
243
225
|
df, meta = pyreadstat.read_por(file_path)
|
|
244
226
|
return df
|
|
245
|
-
elif ext ==
|
|
227
|
+
elif ext == ".csv":
|
|
246
228
|
return pd.read_csv(file_path, nrows=nrows)
|
|
247
|
-
elif ext in [
|
|
229
|
+
elif ext in [".xlsx", ".xls"]:
|
|
248
230
|
return pd.read_excel(file_path, sheet_name=sheet_name, nrows=nrows)
|
|
249
|
-
elif ext ==
|
|
231
|
+
elif ext == ".json":
|
|
250
232
|
return pd.read_json(file_path)
|
|
251
|
-
elif ext ==
|
|
233
|
+
elif ext == ".parquet":
|
|
252
234
|
return pd.read_parquet(file_path)
|
|
253
|
-
elif ext ==
|
|
235
|
+
elif ext == ".feather":
|
|
254
236
|
return pd.read_feather(file_path)
|
|
255
237
|
else:
|
|
256
238
|
raise ValueError(f"Unsupported file format: {ext}")
|
|
257
239
|
except Exception as e:
|
|
258
240
|
raise ValueError(f"Error reading file {file_path}: {str(e)}")
|
|
259
241
|
|
|
260
|
-
def _export_result(self, result: Dict[str, Any], path: str, format: ExportFormat) ->
|
|
242
|
+
def _export_result(self, result: Dict[str, Any], path: str, format: ExportFormat) -> str:
|
|
261
243
|
"""
|
|
262
244
|
Export results to the specified format
|
|
263
245
|
|
|
@@ -279,10 +261,10 @@ class ChartTool(BaseTool):
|
|
|
279
261
|
elif isinstance(obj, np.ndarray):
|
|
280
262
|
return obj.tolist()
|
|
281
263
|
elif isinstance(obj, pd.DataFrame):
|
|
282
|
-
return obj.to_dict(orient=
|
|
264
|
+
return obj.to_dict(orient="records")
|
|
283
265
|
return str(obj)
|
|
284
266
|
|
|
285
|
-
with open(path,
|
|
267
|
+
with open(path, "w") as f:
|
|
286
268
|
json.dump(result, f, default=json_serialize, indent=2)
|
|
287
269
|
|
|
288
270
|
elif format == ExportFormat.CSV:
|
|
@@ -300,12 +282,12 @@ class ChartTool(BaseTool):
|
|
|
300
282
|
data_to_export.to_csv(path, index=False)
|
|
301
283
|
else:
|
|
302
284
|
# Fallback: convert the entire result to a flat structure
|
|
303
|
-
flat_data = {}
|
|
285
|
+
flat_data: Dict[str, Any] = {}
|
|
304
286
|
for k, v in result.items():
|
|
305
287
|
if not isinstance(v, (dict, list, pd.DataFrame)):
|
|
306
288
|
flat_data[k] = v
|
|
307
289
|
|
|
308
|
-
with open(path,
|
|
290
|
+
with open(path, "w", newline="") as f:
|
|
309
291
|
writer = csv.writer(f)
|
|
310
292
|
writer.writerow(flat_data.keys())
|
|
311
293
|
writer.writerow(flat_data.values())
|
|
@@ -326,21 +308,22 @@ class ChartTool(BaseTool):
|
|
|
326
308
|
html_content += f"<p>{value}</p>"
|
|
327
309
|
html_content += "</body></html>"
|
|
328
310
|
|
|
329
|
-
with open(path,
|
|
311
|
+
with open(path, "w") as f:
|
|
330
312
|
f.write(html_content)
|
|
331
313
|
|
|
332
314
|
elif format == ExportFormat.EXCEL:
|
|
333
315
|
with pd.ExcelWriter(path) as writer:
|
|
334
316
|
for key, value in result.items():
|
|
335
317
|
if isinstance(value, pd.DataFrame):
|
|
336
|
-
|
|
318
|
+
# Excel sheet names limited to 31 chars
|
|
319
|
+
value.to_excel(writer, sheet_name=key[:31])
|
|
337
320
|
elif isinstance(value, dict):
|
|
338
321
|
pd.DataFrame(value, index=[0]).to_excel(writer, sheet_name=key[:31])
|
|
339
322
|
else:
|
|
340
|
-
pd.DataFrame({key: [value]}).to_excel(writer, sheet_name=
|
|
323
|
+
pd.DataFrame({key: [value]}).to_excel(writer, sheet_name="Summary")
|
|
341
324
|
|
|
342
325
|
elif format == ExportFormat.MARKDOWN:
|
|
343
|
-
with open(path,
|
|
326
|
+
with open(path, "w") as f:
|
|
344
327
|
f.write("# Chart Results\n\n")
|
|
345
328
|
for key, value in result.items():
|
|
346
329
|
f.write(f"## {key}\n\n")
|
|
@@ -357,11 +340,19 @@ class ChartTool(BaseTool):
|
|
|
357
340
|
except Exception as e:
|
|
358
341
|
raise ValueError(f"Error exporting to {format}: {str(e)}")
|
|
359
342
|
|
|
360
|
-
def _create_visualization(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
343
|
+
def _create_visualization(
|
|
344
|
+
self,
|
|
345
|
+
df: pd.DataFrame,
|
|
346
|
+
plot_type: VisualizationType,
|
|
347
|
+
x: Optional[str] = None,
|
|
348
|
+
y: Optional[str] = None,
|
|
349
|
+
hue: Optional[str] = None,
|
|
350
|
+
variables: Optional[List[str]] = None,
|
|
351
|
+
title: Optional[str] = None,
|
|
352
|
+
figsize: Optional[Tuple[int, int]] = None,
|
|
353
|
+
output_path: Optional[str] = None,
|
|
354
|
+
dpi: Optional[int] = None,
|
|
355
|
+
) -> str:
|
|
365
356
|
"""
|
|
366
357
|
Create a visualization based on the parameters and return the path to the saved image
|
|
367
358
|
|
|
@@ -418,7 +409,7 @@ class ChartTool(BaseTool):
|
|
|
418
409
|
corr = df[variables].corr()
|
|
419
410
|
else:
|
|
420
411
|
corr = df.corr()
|
|
421
|
-
sns.heatmap(corr, annot=True, cmap=
|
|
412
|
+
sns.heatmap(corr, annot=True, cmap="coolwarm", fmt=".2f")
|
|
422
413
|
|
|
423
414
|
elif plot_type == VisualizationType.PAIR:
|
|
424
415
|
if variables:
|
|
@@ -455,9 +446,7 @@ class ChartTool(BaseTool):
|
|
|
455
446
|
available_columns = set(df.columns)
|
|
456
447
|
missing = [col for col in variables if col not in available_columns]
|
|
457
448
|
if missing:
|
|
458
|
-
raise ValueError(
|
|
459
|
-
f"Variables not found in dataset: {', '.join(missing)}. Available columns: {list(available_columns)}"
|
|
460
|
-
)
|
|
449
|
+
raise ValueError(f"Variables not found in dataset: {', '.join(missing)}. Available columns: {list(available_columns)}")
|
|
461
450
|
|
|
462
451
|
def _to_json_serializable(self, result: Union[pd.DataFrame, pd.Series, Dict]) -> Union[List[Dict], Dict]:
|
|
463
452
|
"""
|
|
@@ -471,12 +460,12 @@ class ChartTool(BaseTool):
|
|
|
471
460
|
"""
|
|
472
461
|
if isinstance(result, pd.DataFrame):
|
|
473
462
|
# Handle datetime columns
|
|
474
|
-
for col in result.select_dtypes(include=[
|
|
475
|
-
result[col] = result[col].dt.strftime(
|
|
463
|
+
for col in result.select_dtypes(include=["datetime64"]).columns:
|
|
464
|
+
result[col] = result[col].dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
476
465
|
return result.to_dict(orient="records")
|
|
477
466
|
elif isinstance(result, pd.Series):
|
|
478
467
|
if pd.api.types.is_datetime64_any_dtype(result):
|
|
479
|
-
result = result.dt.strftime(
|
|
468
|
+
result = result.dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
480
469
|
return result.to_dict()
|
|
481
470
|
elif isinstance(result, dict):
|
|
482
471
|
# Handle numpy types and datetime objects
|
|
@@ -497,10 +486,14 @@ class ChartTool(BaseTool):
|
|
|
497
486
|
return result
|
|
498
487
|
|
|
499
488
|
@measure_execution_time
|
|
500
|
-
def read_data(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
489
|
+
def read_data(
|
|
490
|
+
self,
|
|
491
|
+
file_path: str,
|
|
492
|
+
nrows: Optional[int] = None,
|
|
493
|
+
sheet_name: Optional[Union[str, int]] = 0,
|
|
494
|
+
export_format: Optional[ExportFormat] = None,
|
|
495
|
+
export_path: Optional[str] = None,
|
|
496
|
+
) -> Dict[str, Any]:
|
|
504
497
|
"""
|
|
505
498
|
Read data from various file formats
|
|
506
499
|
|
|
@@ -528,11 +521,12 @@ class ChartTool(BaseTool):
|
|
|
528
521
|
|
|
529
522
|
# Create result
|
|
530
523
|
result = {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
524
|
+
"variables": df.columns.tolist(),
|
|
525
|
+
"observations": len(df),
|
|
526
|
+
"dtypes": {col: str(dtype) for col, dtype in df.dtypes.items()},
|
|
527
|
+
# MB
|
|
528
|
+
"memory_usage": df.memory_usage(deep=True).sum() / (1024 * 1024),
|
|
529
|
+
"preview": df.head(5).to_dict(orient="records"),
|
|
536
530
|
}
|
|
537
531
|
|
|
538
532
|
# Handle export if requested
|
|
@@ -541,18 +535,26 @@ class ChartTool(BaseTool):
|
|
|
541
535
|
export_path = os.path.join(self.config.export_dir, export_path)
|
|
542
536
|
|
|
543
537
|
self._export_result(result, export_path, export_format)
|
|
544
|
-
result[
|
|
538
|
+
result["exported_to"] = export_path
|
|
545
539
|
|
|
546
540
|
return result
|
|
547
541
|
|
|
548
542
|
@measure_execution_time
|
|
549
|
-
def visualize(
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
543
|
+
def visualize(
|
|
544
|
+
self,
|
|
545
|
+
file_path: str,
|
|
546
|
+
plot_type: VisualizationType,
|
|
547
|
+
x: Optional[str] = None,
|
|
548
|
+
y: Optional[str] = None,
|
|
549
|
+
hue: Optional[str] = None,
|
|
550
|
+
variables: Optional[List[str]] = None,
|
|
551
|
+
title: Optional[str] = None,
|
|
552
|
+
figsize: Optional[Tuple[int, int]] = None,
|
|
553
|
+
output_path: Optional[str] = None,
|
|
554
|
+
dpi: Optional[int] = None,
|
|
555
|
+
export_format: Optional[ExportFormat] = None,
|
|
556
|
+
export_path: Optional[str] = None,
|
|
557
|
+
) -> Dict[str, Any]:
|
|
556
558
|
"""
|
|
557
559
|
Create data visualizations
|
|
558
560
|
|
|
@@ -600,15 +602,25 @@ class ChartTool(BaseTool):
|
|
|
600
602
|
|
|
601
603
|
# Create visualization
|
|
602
604
|
output_path = self._create_visualization(
|
|
603
|
-
df,
|
|
605
|
+
df,
|
|
606
|
+
plot_type,
|
|
607
|
+
x,
|
|
608
|
+
y,
|
|
609
|
+
hue,
|
|
610
|
+
variables,
|
|
611
|
+
title,
|
|
612
|
+
figsize,
|
|
613
|
+
output_path,
|
|
614
|
+
dpi,
|
|
604
615
|
)
|
|
605
616
|
|
|
606
|
-
# Create result
|
|
617
|
+
# Create result - filter out None values from variables
|
|
618
|
+
var_list = variables or [v for v in [x, y, hue] if v is not None]
|
|
607
619
|
result = {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
620
|
+
"plot_type": plot_type,
|
|
621
|
+
"output_path": output_path,
|
|
622
|
+
"variables": var_list,
|
|
623
|
+
"title": title or f"{plot_type.capitalize()} Plot",
|
|
612
624
|
}
|
|
613
625
|
|
|
614
626
|
# Handle export if requested
|
|
@@ -617,15 +629,19 @@ class ChartTool(BaseTool):
|
|
|
617
629
|
export_path = os.path.join(self.config.export_dir, export_path)
|
|
618
630
|
|
|
619
631
|
self._export_result(result, export_path, export_format)
|
|
620
|
-
result[
|
|
632
|
+
result["exported_to"] = export_path
|
|
621
633
|
|
|
622
634
|
return result
|
|
623
635
|
|
|
624
636
|
@measure_execution_time
|
|
625
|
-
def export_data(
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
637
|
+
def export_data(
|
|
638
|
+
self,
|
|
639
|
+
file_path: str,
|
|
640
|
+
format: ExportFormat,
|
|
641
|
+
variables: Optional[List[str]] = None,
|
|
642
|
+
export_path: Optional[str] = None,
|
|
643
|
+
export_format: Optional[ExportFormat] = None,
|
|
644
|
+
) -> Dict[str, Any]:
|
|
629
645
|
"""
|
|
630
646
|
Export data to various formats
|
|
631
647
|
|
|
@@ -671,7 +687,7 @@ class ChartTool(BaseTool):
|
|
|
671
687
|
# Export data
|
|
672
688
|
try:
|
|
673
689
|
if format == ExportFormat.JSON:
|
|
674
|
-
df.to_json(export_path, orient=
|
|
690
|
+
df.to_json(export_path, orient="records", indent=2)
|
|
675
691
|
elif format == ExportFormat.CSV:
|
|
676
692
|
df.to_csv(export_path, index=False)
|
|
677
693
|
elif format == ExportFormat.HTML:
|
|
@@ -679,18 +695,18 @@ class ChartTool(BaseTool):
|
|
|
679
695
|
elif format == ExportFormat.EXCEL:
|
|
680
696
|
df.to_excel(export_path, index=False)
|
|
681
697
|
elif format == ExportFormat.MARKDOWN:
|
|
682
|
-
with open(export_path,
|
|
698
|
+
with open(export_path, "w") as f:
|
|
683
699
|
f.write(df.to_markdown())
|
|
684
700
|
except Exception as e:
|
|
685
701
|
raise ValueError(f"Error exporting to {format}: {str(e)}")
|
|
686
702
|
|
|
687
703
|
# Create result
|
|
688
704
|
result = {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
705
|
+
"format": format,
|
|
706
|
+
"path": export_path,
|
|
707
|
+
"rows": len(df),
|
|
708
|
+
"columns": len(df.columns),
|
|
709
|
+
"variables": df.columns.tolist(),
|
|
694
710
|
}
|
|
695
711
|
|
|
696
712
|
# Handle export if requested
|
|
@@ -699,6 +715,6 @@ class ChartTool(BaseTool):
|
|
|
699
715
|
export_path = os.path.join(self.config.export_dir, export_path)
|
|
700
716
|
|
|
701
717
|
self._export_result(result, export_path, export_format)
|
|
702
|
-
result[
|
|
718
|
+
result["exported_to"] = export_path
|
|
703
719
|
|
|
704
720
|
return result
|