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,413 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Query Intent Analysis and Enhancement
|
|
3
|
+
|
|
4
|
+
Provides intelligent query understanding and parameter auto-completion:
|
|
5
|
+
- Detect query intent (time_series, comparison, search, metadata)
|
|
6
|
+
- Extract entities (economic indicators, countries, etc.)
|
|
7
|
+
- Parse time ranges and geographic scope
|
|
8
|
+
- Suggest appropriate providers and operations
|
|
9
|
+
- Auto-complete missing parameters based on intent
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import re
|
|
14
|
+
from typing import Any, Dict, List, Optional
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class QueryIntentAnalyzer:
|
|
20
|
+
"""
|
|
21
|
+
Analyzes query intent to help route requests and optimize parameters.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# Intent keywords
|
|
25
|
+
INTENT_KEYWORDS = {
|
|
26
|
+
"time_series": [
|
|
27
|
+
"trend",
|
|
28
|
+
"over time",
|
|
29
|
+
"historical",
|
|
30
|
+
"series",
|
|
31
|
+
"change",
|
|
32
|
+
"growth",
|
|
33
|
+
"history",
|
|
34
|
+
],
|
|
35
|
+
"comparison": [
|
|
36
|
+
"compare",
|
|
37
|
+
"versus",
|
|
38
|
+
"vs",
|
|
39
|
+
"difference",
|
|
40
|
+
"between",
|
|
41
|
+
"against",
|
|
42
|
+
"relative to",
|
|
43
|
+
],
|
|
44
|
+
"search": [
|
|
45
|
+
"search",
|
|
46
|
+
"find",
|
|
47
|
+
"look for",
|
|
48
|
+
"list",
|
|
49
|
+
"show me",
|
|
50
|
+
"what are",
|
|
51
|
+
],
|
|
52
|
+
"metadata": [
|
|
53
|
+
"info",
|
|
54
|
+
"information",
|
|
55
|
+
"about",
|
|
56
|
+
"describe",
|
|
57
|
+
"details",
|
|
58
|
+
"metadata",
|
|
59
|
+
],
|
|
60
|
+
"recent": [
|
|
61
|
+
"recent",
|
|
62
|
+
"latest",
|
|
63
|
+
"current",
|
|
64
|
+
"now",
|
|
65
|
+
"today",
|
|
66
|
+
"this week",
|
|
67
|
+
"this month",
|
|
68
|
+
],
|
|
69
|
+
"forecast": ["forecast", "predict", "future", "project", "estimate"],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Economic indicators mapping
|
|
73
|
+
ECONOMIC_INDICATORS = {
|
|
74
|
+
"gdp": {
|
|
75
|
+
"keywords": ["gdp", "gross domestic product", "economic output"],
|
|
76
|
+
"providers": ["fred", "worldbank"],
|
|
77
|
+
"fred_series": ["GDP", "GDPC1"],
|
|
78
|
+
"wb_indicator": "NY.GDP.MKTP.CD",
|
|
79
|
+
},
|
|
80
|
+
"unemployment": {
|
|
81
|
+
"keywords": ["unemployment", "jobless", "labor force"],
|
|
82
|
+
"providers": ["fred"],
|
|
83
|
+
"fred_series": ["UNRATE", "UNEMPLOY"],
|
|
84
|
+
},
|
|
85
|
+
"inflation": {
|
|
86
|
+
"keywords": ["inflation", "cpi", "consumer price", "price index"],
|
|
87
|
+
"providers": ["fred", "worldbank"],
|
|
88
|
+
"fred_series": ["CPIAUCSL", "CPILFESL"],
|
|
89
|
+
"wb_indicator": "FP.CPI.TOTL",
|
|
90
|
+
},
|
|
91
|
+
"interest_rate": {
|
|
92
|
+
"keywords": [
|
|
93
|
+
"interest rate",
|
|
94
|
+
"fed rate",
|
|
95
|
+
"federal funds",
|
|
96
|
+
"treasury",
|
|
97
|
+
],
|
|
98
|
+
"providers": ["fred"],
|
|
99
|
+
"fred_series": ["DFF", "DGS10", "DGS30"],
|
|
100
|
+
},
|
|
101
|
+
"population": {
|
|
102
|
+
"keywords": ["population", "demographic", "people count"],
|
|
103
|
+
"providers": ["census", "worldbank"],
|
|
104
|
+
"wb_indicator": "SP.POP.TOTL",
|
|
105
|
+
},
|
|
106
|
+
"trade": {
|
|
107
|
+
"keywords": ["trade", "export", "import", "trade balance"],
|
|
108
|
+
"providers": ["fred", "worldbank"],
|
|
109
|
+
"fred_series": ["BOPGSTB"],
|
|
110
|
+
"wb_indicator": "NE.EXP.GNFS.CD",
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Country codes and names
|
|
115
|
+
COUNTRIES = {
|
|
116
|
+
"us": ["us", "usa", "united states", "america"],
|
|
117
|
+
"uk": ["uk", "united kingdom", "britain"],
|
|
118
|
+
"china": ["china", "cn"],
|
|
119
|
+
"japan": ["japan", "jp"],
|
|
120
|
+
"germany": ["germany", "de"],
|
|
121
|
+
"france": ["france", "fr"],
|
|
122
|
+
"india": ["india", "in"],
|
|
123
|
+
"canada": ["canada", "ca"],
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
def analyze_intent(self, query_text: str) -> Dict[str, Any]:
|
|
127
|
+
"""
|
|
128
|
+
Analyze query intent and extract key information.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
query_text: Natural language query string
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Dictionary with:
|
|
135
|
+
- intent_type: Primary intent (time_series, comparison, search, etc.)
|
|
136
|
+
- entities: Extracted entities (indicators, countries, etc.)
|
|
137
|
+
- time_range: Extracted time information
|
|
138
|
+
- geographic_scope: Geographic context
|
|
139
|
+
- suggested_providers: Recommended providers
|
|
140
|
+
- suggested_operations: Recommended operations
|
|
141
|
+
- confidence: Confidence score (0-1)
|
|
142
|
+
"""
|
|
143
|
+
query_lower = query_text.lower()
|
|
144
|
+
|
|
145
|
+
intent_result = {
|
|
146
|
+
"intent_type": "search", # Default
|
|
147
|
+
"entities": [],
|
|
148
|
+
"time_range": None,
|
|
149
|
+
"geographic_scope": None,
|
|
150
|
+
"suggested_providers": [],
|
|
151
|
+
"suggested_operations": [],
|
|
152
|
+
"confidence": 0.0,
|
|
153
|
+
"keywords_matched": [],
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# Detect intent type
|
|
157
|
+
intent_scores = {}
|
|
158
|
+
for intent_type, keywords in self.INTENT_KEYWORDS.items():
|
|
159
|
+
score = sum(1 for kw in keywords if kw in query_lower)
|
|
160
|
+
if score > 0:
|
|
161
|
+
intent_scores[intent_type] = score
|
|
162
|
+
|
|
163
|
+
if intent_scores:
|
|
164
|
+
# Primary intent is the one with highest score
|
|
165
|
+
primary_intent = max(intent_scores.items(), key=lambda x: x[1])
|
|
166
|
+
intent_result["intent_type"] = primary_intent[0]
|
|
167
|
+
intent_result["confidence"] += 0.3
|
|
168
|
+
|
|
169
|
+
# Extract economic indicators
|
|
170
|
+
for indicator_name, indicator_info in self.ECONOMIC_INDICATORS.items():
|
|
171
|
+
for keyword in indicator_info["keywords"]:
|
|
172
|
+
if keyword in query_lower:
|
|
173
|
+
intent_result["entities"].append(
|
|
174
|
+
{
|
|
175
|
+
"type": "indicator",
|
|
176
|
+
"name": indicator_name,
|
|
177
|
+
"matched_keyword": keyword,
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
intent_result["suggested_providers"].extend(indicator_info["providers"])
|
|
181
|
+
intent_result["confidence"] += 0.2
|
|
182
|
+
intent_result["keywords_matched"].append(keyword)
|
|
183
|
+
break
|
|
184
|
+
|
|
185
|
+
# Extract countries
|
|
186
|
+
for country_code, country_names in self.COUNTRIES.items():
|
|
187
|
+
for country_name in country_names:
|
|
188
|
+
if country_name in query_lower:
|
|
189
|
+
intent_result["geographic_scope"] = country_code.upper()
|
|
190
|
+
intent_result["confidence"] += 0.2
|
|
191
|
+
break
|
|
192
|
+
|
|
193
|
+
# Extract time range
|
|
194
|
+
time_info = self._extract_time_range(query_lower)
|
|
195
|
+
if time_info:
|
|
196
|
+
intent_result["time_range"] = time_info
|
|
197
|
+
intent_result["confidence"] += 0.2
|
|
198
|
+
|
|
199
|
+
# Suggest operations based on intent
|
|
200
|
+
intent_result["suggested_operations"] = self._suggest_operations(
|
|
201
|
+
intent_result["intent_type"], intent_result["suggested_providers"]
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Remove duplicates from providers
|
|
205
|
+
intent_result["suggested_providers"] = list(set(intent_result["suggested_providers"]))
|
|
206
|
+
|
|
207
|
+
# Cap confidence at 1.0
|
|
208
|
+
intent_result["confidence"] = min(1.0, intent_result["confidence"])
|
|
209
|
+
|
|
210
|
+
return intent_result
|
|
211
|
+
|
|
212
|
+
def _extract_time_range(self, query_lower: str) -> Optional[Dict[str, Any]]:
|
|
213
|
+
"""
|
|
214
|
+
Extract time range information from query.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
query_lower: Lowercase query string
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Dictionary with start_date, end_date, or None
|
|
221
|
+
"""
|
|
222
|
+
time_range = {}
|
|
223
|
+
|
|
224
|
+
# Look for year patterns (4 digits)
|
|
225
|
+
year_pattern = r"\b(19|20)\d{2}\b"
|
|
226
|
+
years = re.findall(year_pattern, query_lower)
|
|
227
|
+
|
|
228
|
+
if len(years) >= 2:
|
|
229
|
+
# Found multiple years
|
|
230
|
+
years_int = sorted([int(y) for y in years])
|
|
231
|
+
time_range["start_date"] = f"{years_int[0]}-01-01"
|
|
232
|
+
time_range["end_date"] = f"{years_int[-1]}-12-31"
|
|
233
|
+
time_range["type"] = "explicit_range"
|
|
234
|
+
elif len(years) == 1:
|
|
235
|
+
# Single year mentioned
|
|
236
|
+
year = int(years[0])
|
|
237
|
+
time_range["start_date"] = f"{year}-01-01"
|
|
238
|
+
time_range["end_date"] = f"{year}-12-31"
|
|
239
|
+
time_range["type"] = "single_year"
|
|
240
|
+
|
|
241
|
+
# Look for relative time expressions
|
|
242
|
+
if "last" in query_lower or "past" in query_lower:
|
|
243
|
+
# Extract number
|
|
244
|
+
number_pattern = r"(last|past)\s+(\d+)\s+(year|month|day|week)"
|
|
245
|
+
match = re.search(number_pattern, query_lower)
|
|
246
|
+
if match:
|
|
247
|
+
quantity = int(match.group(2))
|
|
248
|
+
unit = match.group(3)
|
|
249
|
+
time_range["type"] = "relative"
|
|
250
|
+
time_range["quantity"] = quantity
|
|
251
|
+
time_range["unit"] = unit
|
|
252
|
+
|
|
253
|
+
return time_range if time_range else None
|
|
254
|
+
|
|
255
|
+
def _suggest_operations(self, intent_type: str, providers: List[str]) -> List[Dict[str, str]]:
|
|
256
|
+
"""
|
|
257
|
+
Suggest appropriate operations based on intent and providers.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
intent_type: Detected intent type
|
|
261
|
+
providers: List of suggested providers
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
List of {provider, operation} dictionaries
|
|
265
|
+
"""
|
|
266
|
+
suggestions = []
|
|
267
|
+
|
|
268
|
+
for provider in providers:
|
|
269
|
+
if intent_type == "time_series":
|
|
270
|
+
if provider == "fred":
|
|
271
|
+
suggestions.append(
|
|
272
|
+
{
|
|
273
|
+
"provider": "fred",
|
|
274
|
+
"operation": "get_series_observations",
|
|
275
|
+
}
|
|
276
|
+
)
|
|
277
|
+
elif provider == "worldbank":
|
|
278
|
+
suggestions.append({"provider": "worldbank", "operation": "get_indicator"})
|
|
279
|
+
|
|
280
|
+
elif intent_type == "search":
|
|
281
|
+
if provider == "fred":
|
|
282
|
+
suggestions.append({"provider": "fred", "operation": "search_series"})
|
|
283
|
+
elif provider == "worldbank":
|
|
284
|
+
suggestions.append(
|
|
285
|
+
{
|
|
286
|
+
"provider": "worldbank",
|
|
287
|
+
"operation": "search_indicators",
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
elif provider == "newsapi":
|
|
291
|
+
suggestions.append(
|
|
292
|
+
{
|
|
293
|
+
"provider": "newsapi",
|
|
294
|
+
"operation": "search_everything",
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
elif intent_type == "metadata":
|
|
299
|
+
if provider == "fred":
|
|
300
|
+
suggestions.append({"provider": "fred", "operation": "get_series_info"})
|
|
301
|
+
|
|
302
|
+
return suggestions
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class QueryEnhancer:
|
|
306
|
+
"""
|
|
307
|
+
Enhances queries by auto-completing parameters based on intent.
|
|
308
|
+
"""
|
|
309
|
+
|
|
310
|
+
def __init__(self, intent_analyzer: Optional[QueryIntentAnalyzer] = None):
|
|
311
|
+
"""
|
|
312
|
+
Initialize query enhancer.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
intent_analyzer: Intent analyzer instance (creates new if not provided)
|
|
316
|
+
"""
|
|
317
|
+
self.intent_analyzer = intent_analyzer or QueryIntentAnalyzer()
|
|
318
|
+
|
|
319
|
+
def auto_complete_params(
|
|
320
|
+
self,
|
|
321
|
+
provider: str,
|
|
322
|
+
operation: str,
|
|
323
|
+
params: Dict[str, Any],
|
|
324
|
+
query_text: Optional[str] = None,
|
|
325
|
+
) -> Dict[str, Any]:
|
|
326
|
+
"""
|
|
327
|
+
Auto-complete missing parameters based on query intent.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
provider: Provider name
|
|
331
|
+
operation: Operation name
|
|
332
|
+
params: Current parameters
|
|
333
|
+
query_text: Optional natural language query for intent analysis
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
Enhanced parameters dictionary
|
|
337
|
+
"""
|
|
338
|
+
completed_params = params.copy()
|
|
339
|
+
|
|
340
|
+
# Analyze intent if query text provided
|
|
341
|
+
intent = None
|
|
342
|
+
if query_text:
|
|
343
|
+
intent = self.intent_analyzer.analyze_intent(query_text)
|
|
344
|
+
|
|
345
|
+
# Add time range parameters if detected and not present
|
|
346
|
+
if intent and intent.get("time_range") and provider == "fred":
|
|
347
|
+
time_range = intent["time_range"]
|
|
348
|
+
if time_range.get("type") in ["explicit_range", "single_year"]:
|
|
349
|
+
if "observation_start" not in params and "start_date" in time_range:
|
|
350
|
+
completed_params["observation_start"] = time_range["start_date"]
|
|
351
|
+
if "observation_end" not in params and "end_date" in time_range:
|
|
352
|
+
completed_params["observation_end"] = time_range["end_date"]
|
|
353
|
+
|
|
354
|
+
# Add reasonable limits if not specified
|
|
355
|
+
if "limit" not in params and "page_size" not in params:
|
|
356
|
+
if intent and intent.get("intent_type") == "time_series":
|
|
357
|
+
# Time series typically need more data
|
|
358
|
+
if provider == "fred":
|
|
359
|
+
# FRED API max is 100000, but 1000 is reasonable default
|
|
360
|
+
completed_params["limit"] = 1000
|
|
361
|
+
elif provider == "worldbank":
|
|
362
|
+
completed_params["per_page"] = 1000
|
|
363
|
+
else:
|
|
364
|
+
# Search results typically need fewer
|
|
365
|
+
if provider == "fred":
|
|
366
|
+
completed_params["limit"] = 20
|
|
367
|
+
elif provider == "worldbank":
|
|
368
|
+
completed_params["limit"] = 20
|
|
369
|
+
elif provider == "newsapi":
|
|
370
|
+
completed_params["page_size"] = 10
|
|
371
|
+
|
|
372
|
+
# Add sort order for time series
|
|
373
|
+
if intent and intent.get("intent_type") == "time_series":
|
|
374
|
+
if provider == "fred" and "sort_order" not in params:
|
|
375
|
+
completed_params["sort_order"] = "desc" # Most recent first
|
|
376
|
+
|
|
377
|
+
# Add country code if detected and needed
|
|
378
|
+
if intent and intent.get("geographic_scope"):
|
|
379
|
+
if provider == "worldbank" and "country_code" not in params:
|
|
380
|
+
completed_params["country_code"] = intent["geographic_scope"]
|
|
381
|
+
|
|
382
|
+
return completed_params
|
|
383
|
+
|
|
384
|
+
def enhance_query_text(self, query_text: str, provider: str) -> str:
|
|
385
|
+
"""
|
|
386
|
+
Enhance query text for better search results.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
query_text: Original query text
|
|
390
|
+
provider: Target provider
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
Enhanced query text
|
|
394
|
+
"""
|
|
395
|
+
# Analyze intent
|
|
396
|
+
intent = self.intent_analyzer.analyze_intent(query_text)
|
|
397
|
+
|
|
398
|
+
# For searches, add indicator-specific terms
|
|
399
|
+
enhanced = query_text
|
|
400
|
+
|
|
401
|
+
if provider == "fred" and intent.get("entities"):
|
|
402
|
+
# Add FRED series IDs if we recognize the indicator
|
|
403
|
+
for entity in intent["entities"]:
|
|
404
|
+
if entity["type"] == "indicator":
|
|
405
|
+
indicator_name = entity["name"]
|
|
406
|
+
indicator_info = QueryIntentAnalyzer.ECONOMIC_INDICATORS.get(indicator_name, {})
|
|
407
|
+
if "fred_series" in indicator_info:
|
|
408
|
+
# Add common series IDs to improve search
|
|
409
|
+
series_ids = " ".join(indicator_info["fred_series"])
|
|
410
|
+
enhanced = f"{query_text} {series_ids}"
|
|
411
|
+
break
|
|
412
|
+
|
|
413
|
+
return enhanced
|