aiecs 1.2.1__py3-none-any.whl → 1.3.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.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (56) hide show
  1. aiecs/__init__.py +1 -1
  2. aiecs/config/config.py +2 -1
  3. aiecs/llm/clients/vertex_client.py +5 -0
  4. aiecs/main.py +2 -2
  5. aiecs/scripts/tools_develop/README.md +111 -2
  6. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  7. aiecs/scripts/tools_develop/validate_tool_schemas.py +80 -21
  8. aiecs/scripts/tools_develop/verify_tools.py +347 -0
  9. aiecs/tools/__init__.py +94 -30
  10. aiecs/tools/apisource/__init__.py +106 -0
  11. aiecs/tools/apisource/intelligence/__init__.py +20 -0
  12. aiecs/tools/apisource/intelligence/data_fusion.py +378 -0
  13. aiecs/tools/apisource/intelligence/query_analyzer.py +387 -0
  14. aiecs/tools/apisource/intelligence/search_enhancer.py +384 -0
  15. aiecs/tools/apisource/monitoring/__init__.py +12 -0
  16. aiecs/tools/apisource/monitoring/metrics.py +308 -0
  17. aiecs/tools/apisource/providers/__init__.py +114 -0
  18. aiecs/tools/apisource/providers/base.py +684 -0
  19. aiecs/tools/apisource/providers/census.py +412 -0
  20. aiecs/tools/apisource/providers/fred.py +575 -0
  21. aiecs/tools/apisource/providers/newsapi.py +402 -0
  22. aiecs/tools/apisource/providers/worldbank.py +346 -0
  23. aiecs/tools/apisource/reliability/__init__.py +14 -0
  24. aiecs/tools/apisource/reliability/error_handler.py +362 -0
  25. aiecs/tools/apisource/reliability/fallback_strategy.py +420 -0
  26. aiecs/tools/apisource/tool.py +814 -0
  27. aiecs/tools/apisource/utils/__init__.py +12 -0
  28. aiecs/tools/apisource/utils/validators.py +343 -0
  29. aiecs/tools/langchain_adapter.py +95 -17
  30. aiecs/tools/search_tool/__init__.py +102 -0
  31. aiecs/tools/search_tool/analyzers.py +583 -0
  32. aiecs/tools/search_tool/cache.py +280 -0
  33. aiecs/tools/search_tool/constants.py +127 -0
  34. aiecs/tools/search_tool/context.py +219 -0
  35. aiecs/tools/search_tool/core.py +773 -0
  36. aiecs/tools/search_tool/deduplicator.py +123 -0
  37. aiecs/tools/search_tool/error_handler.py +257 -0
  38. aiecs/tools/search_tool/metrics.py +375 -0
  39. aiecs/tools/search_tool/rate_limiter.py +177 -0
  40. aiecs/tools/search_tool/schemas.py +297 -0
  41. aiecs/tools/statistics/data_loader_tool.py +2 -2
  42. aiecs/tools/statistics/data_transformer_tool.py +1 -1
  43. aiecs/tools/task_tools/__init__.py +8 -8
  44. aiecs/tools/task_tools/report_tool.py +1 -1
  45. aiecs/tools/tool_executor/__init__.py +2 -0
  46. aiecs/tools/tool_executor/tool_executor.py +284 -14
  47. aiecs/utils/__init__.py +11 -0
  48. aiecs/utils/cache_provider.py +698 -0
  49. aiecs/utils/execution_utils.py +5 -5
  50. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/METADATA +1 -1
  51. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/RECORD +55 -23
  52. aiecs/tools/task_tools/search_tool.py +0 -1123
  53. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/WHEEL +0 -0
  54. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/entry_points.txt +0 -0
  55. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/licenses/LICENSE +0 -0
  56. {aiecs-1.2.1.dist-info → aiecs-1.3.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ 快速验证脚本:展示 aiecs.tools 注册的所有工具和功能
4
+
5
+ 使用方法:
6
+ poetry run python -m aiecs.scripts.tools_develop.verify_tools
7
+
8
+ 功能:
9
+ 1. 列出所有注册的工具(按类别分组)
10
+ 2. 交互式选择工具查看详细功能
11
+ 3. 实际加载指定工具,展示真实的原子功能
12
+ """
13
+
14
+ import sys
15
+ import os
16
+ import inspect
17
+ from typing import List, Dict
18
+ from collections import defaultdict
19
+
20
+ # 添加项目根目录到 Python 路径
21
+ current_dir = os.path.dirname(os.path.abspath(__file__))
22
+ project_root = os.path.abspath(os.path.join(current_dir, '../../../'))
23
+ sys.path.insert(0, project_root)
24
+
25
+
26
+ def get_tool_methods(tool_instance) -> List[str]:
27
+ """获取工具实例的所有公共方法(原子功能)"""
28
+ methods = []
29
+ for name, method in inspect.getmembers(tool_instance, predicate=inspect.ismethod):
30
+ # 只获取公共方法,排除私有方法和特殊方法
31
+ if not name.startswith('_'):
32
+ methods.append(name)
33
+ return sorted(methods)
34
+
35
+
36
+ def display_tools_by_category(tools: List[Dict]):
37
+ """按类别分组显示工具"""
38
+ # 按类别分组
39
+ categories = defaultdict(list)
40
+ for tool in tools:
41
+ category = tool.get('category', 'unknown')
42
+ categories[category].append(tool)
43
+
44
+ # 显示每个类别
45
+ category_names = {
46
+ 'task': '任务工具',
47
+ 'docs': '文档工具',
48
+ 'statistics': '数据统计工具',
49
+ 'unknown': '其他工具'
50
+ }
51
+
52
+ tool_index = 1
53
+ tool_map = {} # 用于存储序号到工具名的映射
54
+
55
+ for category in ['task', 'docs', 'statistics', 'unknown']:
56
+ if category not in categories:
57
+ continue
58
+
59
+ category_tools = categories[category]
60
+ category_display = category_names.get(category, category.upper())
61
+
62
+ print(f"\n{'=' * 80}")
63
+ print(f"📁 {category_display} ({len(category_tools)} 个)")
64
+ print(f"{'=' * 80}")
65
+
66
+ for tool in category_tools:
67
+ tool_name = tool['name']
68
+ tool_map[tool_index] = tool_name
69
+
70
+ print(f"\n[{tool_index}] {tool_name}")
71
+ print(f" 描述: {tool.get('description', '无描述')}")
72
+ print(f" 状态: {tool.get('status', '未知')}")
73
+
74
+ tool_index += 1
75
+
76
+ return tool_map
77
+
78
+
79
+ def auto_discover_tool_modules():
80
+ """自动发现工具模块映射,无需手动维护"""
81
+ import os
82
+ import re
83
+
84
+ tool_module_map = {}
85
+
86
+ # 扫描 aiecs/tools 目录
87
+ tools_dir = os.path.join(project_root, 'aiecs', 'tools')
88
+
89
+ # 定义工具目录
90
+ tool_dirs = {
91
+ 'task_tools': 'aiecs.tools.task_tools',
92
+ 'docs': 'aiecs.tools.docs',
93
+ 'statistics': 'aiecs.tools.statistics',
94
+ 'api_sources': 'aiecs.tools.api_sources', # 旧的 API sources (如果存在)
95
+ 'apisource': 'aiecs.tools.apisource', # 新的 APISource Tool
96
+ 'search_tool': 'aiecs.tools.search_tool',
97
+ }
98
+
99
+ for dir_name, package_name in tool_dirs.items():
100
+ dir_path = os.path.join(tools_dir, dir_name)
101
+ if not os.path.exists(dir_path):
102
+ continue
103
+
104
+ # Check if this is a package (has __init__.py) or a directory of modules
105
+ init_file = os.path.join(dir_path, '__init__.py')
106
+ files_to_scan = []
107
+
108
+ if os.path.isfile(init_file):
109
+ # For packages, scan __init__.py and use package name directly
110
+ files_to_scan.append(('__init__.py', init_file, package_name))
111
+
112
+ # 扫描目录中的所有其他 Python 文件
113
+ for filename in os.listdir(dir_path):
114
+ if filename.endswith('.py') and not filename.startswith('__'):
115
+ file_path = os.path.join(dir_path, filename)
116
+ module_name = filename[:-3] # 去掉 .py 扩展名
117
+ module_path = f"{package_name}.{module_name}"
118
+ files_to_scan.append((filename, file_path, module_path))
119
+
120
+ # Process all files
121
+ for filename, file_path, module_path in files_to_scan:
122
+ try:
123
+ with open(file_path, 'r', encoding='utf-8') as f:
124
+ content = f.read()
125
+
126
+ # 查找 @register_tool 装饰器 (两种模式)
127
+ # Pattern 1: @register_tool("name") decorator syntax
128
+ decorator_pattern = r'@register_tool\([\'"]([^\'"]+)[\'"]\)'
129
+ decorator_matches = re.findall(decorator_pattern, content)
130
+
131
+ # Pattern 2: register_tool("name")(ClassName) function call syntax
132
+ function_pattern = r'register_tool\([\'"]([^\'"]+)[\'"]\)\([A-Za-z_][A-Za-z0-9_]*\)'
133
+ function_matches = re.findall(function_pattern, content)
134
+
135
+ # Combine all matches
136
+ all_matches = list(set(decorator_matches + function_matches))
137
+
138
+ for tool_name in all_matches:
139
+ tool_module_map[tool_name] = {
140
+ 'module_file': filename[:-3] if filename != '__init__.py' else '__init__',
141
+ 'package': package_name,
142
+ 'module_path': module_path,
143
+ 'category': dir_name,
144
+ }
145
+ except Exception:
146
+ pass
147
+
148
+ return tool_module_map
149
+
150
+
151
+ def load_and_inspect_tool(tool_name: str):
152
+ """加载并检查指定工具的详细功能"""
153
+ from aiecs.tools import get_tool
154
+ import importlib
155
+
156
+ print(f"\n{'=' * 80}")
157
+ print(f"🔍 加载工具: {tool_name}")
158
+ print(f"{'=' * 80}")
159
+
160
+ try:
161
+ # 自动发现工具模块
162
+ print(f"\n⏳ 正在加载...")
163
+
164
+ tool_module_map = auto_discover_tool_modules()
165
+
166
+ # 如果找到了工具的模块信息,预加载模块
167
+ if tool_name in tool_module_map:
168
+ info = tool_module_map[tool_name]
169
+ module_path = info.get('module_path') or f"{info['package']}.{info['module_file']}"
170
+
171
+ try:
172
+ importlib.import_module(module_path)
173
+ print(f" 已触发 {module_path} 模块加载")
174
+ except Exception as e:
175
+ print(f" 警告: 无法预加载模块 ({e})")
176
+ else:
177
+ print(f" 未找到工具模块映射,尝试直接加载...")
178
+
179
+ # 获取工具实例
180
+ tool = get_tool(tool_name)
181
+
182
+ # 检查是否为占位符
183
+ is_placeholder = getattr(tool, 'is_placeholder', False)
184
+
185
+ if is_placeholder:
186
+ print(f"\n⚠️ 工具仍处于占位符状态")
187
+ print(f" 描述: {tool.description}")
188
+ print(f" 提示: 此工具需要在调用具体方法时才会完全实例化")
189
+ return
190
+
191
+ # 显示工具基本信息
192
+ print(f"\n✅ 工具已成功加载")
193
+ print(f" 类名: {tool.__class__.__name__}")
194
+ print(f" 模块: {tool.__class__.__module__}")
195
+
196
+ if hasattr(tool, 'description'):
197
+ print(f" 描述: {tool.description}")
198
+
199
+ if hasattr(tool, 'category'):
200
+ print(f" 类别: {tool.category}")
201
+
202
+ # 获取所有方法(原子功能)
203
+ methods = get_tool_methods(tool)
204
+
205
+ if not methods:
206
+ print(f"\n❌ 未发现公共方法")
207
+ return
208
+
209
+ print(f"\n📋 原子功能列表 (共 {len(methods)} 个方法):")
210
+ print(f"{'-' * 80}")
211
+
212
+ for i, method_name in enumerate(methods, 1):
213
+ try:
214
+ method = getattr(tool, method_name)
215
+
216
+ # 获取方法签名
217
+ sig = inspect.signature(method)
218
+ params = []
219
+ for param_name, param in sig.parameters.items():
220
+ if param_name == 'self':
221
+ continue
222
+
223
+ # 构建参数字符串
224
+ param_str = param_name
225
+ if param.annotation != inspect.Parameter.empty:
226
+ param_str += f": {param.annotation.__name__ if hasattr(param.annotation, '__name__') else str(param.annotation)}"
227
+ if param.default != inspect.Parameter.empty:
228
+ param_str += f" = {param.default!r}"
229
+ params.append(param_str)
230
+
231
+ # 获取返回类型
232
+ return_annotation = ""
233
+ if sig.return_annotation != inspect.Signature.empty:
234
+ return_type = sig.return_annotation
235
+ return_annotation = f" -> {return_type.__name__ if hasattr(return_type, '__name__') else str(return_type)}"
236
+
237
+ # 显示方法签名
238
+ print(f"\n [{i}] {method_name}({', '.join(params)}){return_annotation}")
239
+
240
+ # 获取文档字符串
241
+ if method.__doc__:
242
+ doc_lines = method.__doc__.strip().split('\n')
243
+ first_line = doc_lines[0].strip()
244
+ if first_line:
245
+ print(f" {first_line}")
246
+
247
+ except Exception as e:
248
+ print(f"\n [{i}] {method_name}")
249
+ print(f" (无法获取详细信息: {e})")
250
+
251
+ print(f"\n{'-' * 80}")
252
+
253
+ except Exception as e:
254
+ print(f"\n❌ 加载工具失败: {e}")
255
+ import traceback
256
+ traceback.print_exc()
257
+
258
+
259
+ def interactive_mode(tool_map: Dict[int, str]):
260
+ """交互式模式"""
261
+ print(f"\n{'=' * 80}")
262
+ print("🎮 交互模式")
263
+ print(f"{'=' * 80}")
264
+ print("\n提示:")
265
+ print(" - 输入工具序号 (1-{}) 查看详细功能".format(len(tool_map)))
266
+ print(" - 输入工具名称查看详细功能")
267
+ print(" - 输入 'list' 重新显示工具列表")
268
+ print(" - 输入 'q' 或 'quit' 退出")
269
+
270
+ while True:
271
+ try:
272
+ user_input = input("\n👉 请选择工具 > ").strip()
273
+
274
+ if not user_input:
275
+ continue
276
+
277
+ if user_input.lower() in ['q', 'quit', 'exit']:
278
+ print("\n👋 再见!")
279
+ break
280
+
281
+ if user_input.lower() == 'list':
282
+ from aiecs.tools import list_tools
283
+ tools = list_tools()
284
+ display_tools_by_category(tools)
285
+ continue
286
+
287
+ # 尝试作为序号解析
288
+ tool_name = None
289
+ try:
290
+ index = int(user_input)
291
+ if index in tool_map:
292
+ tool_name = tool_map[index]
293
+ else:
294
+ print(f"❌ 无效的序号: {index}")
295
+ continue
296
+ except ValueError:
297
+ # 作为工具名称
298
+ tool_name = user_input
299
+
300
+ if tool_name:
301
+ load_and_inspect_tool(tool_name)
302
+
303
+ except KeyboardInterrupt:
304
+ print("\n\n👋 再见!")
305
+ break
306
+ except EOFError:
307
+ print("\n\n👋 再见!")
308
+ break
309
+ except Exception as e:
310
+ print(f"\n❌ 错误: {e}")
311
+
312
+
313
+ def main():
314
+ """主函数:验证和展示所有注册的工具"""
315
+ print("=" * 80)
316
+ print("AIECS Tools 注册工具验证")
317
+ print("=" * 80)
318
+
319
+ try:
320
+ from aiecs.tools import list_tools
321
+
322
+ # 获取所有注册的工具
323
+ tools = list_tools()
324
+
325
+ print(f"\n发现 {len(tools)} 个注册的工具")
326
+
327
+ # 按类别显示工具
328
+ tool_map = display_tools_by_category(tools)
329
+
330
+ print(f"\n{'=' * 80}")
331
+ print(f"✅ 工具列表显示完成! 共 {len(tools)} 个工具")
332
+ print(f"{'=' * 80}")
333
+
334
+ # 进入交互模式
335
+ interactive_mode(tool_map)
336
+
337
+ except ImportError as e:
338
+ print(f"❌ 导入错误: {e}")
339
+ print("请确保在正确的项目目录中运行此脚本")
340
+ except Exception as e:
341
+ print(f"❌ 运行错误: {e}")
342
+ import traceback
343
+ traceback.print_exc()
344
+
345
+
346
+ if __name__ == "__main__":
347
+ main()
aiecs/tools/__init__.py CHANGED
@@ -155,48 +155,112 @@ def _ensure_task_tools_available():
155
155
  logger.error(f"Failed to import task_tools: {e}")
156
156
  return False
157
157
 
158
+ def _auto_discover_tools():
159
+ """Automatically discover all tools by scanning tool directories"""
160
+ import re
161
+
162
+ # Define tool directories and their categories
163
+ tool_dirs = [
164
+ ('task_tools', 'task'),
165
+ ('docs', 'docs'),
166
+ ('statistics', 'statistics'),
167
+ ('search_tool', 'task'), # Enhanced search tool
168
+ ('api_sources', 'task'), # API data sources (legacy)
169
+ ('apisource', 'task'), # API Source Tool (new modular version)
170
+ ]
171
+
172
+ discovered_tools = []
173
+
174
+ for dir_name, category in tool_dirs:
175
+ dir_path = os.path.join(os.path.dirname(__file__), dir_name)
176
+ if not os.path.exists(dir_path):
177
+ continue
178
+
179
+ # Check if this is a package (has __init__.py) or a directory of modules
180
+ init_file = os.path.join(dir_path, '__init__.py')
181
+ files_to_scan = []
182
+
183
+ if os.path.isfile(init_file):
184
+ # Scan __init__.py for package-level registrations
185
+ files_to_scan.append(('__init__.py', init_file))
186
+
187
+ # Scan all other Python files in the directory
188
+ for filename in os.listdir(dir_path):
189
+ if filename.endswith('.py') and not filename.startswith('__'):
190
+ file_path = os.path.join(dir_path, filename)
191
+ files_to_scan.append((filename, file_path))
192
+
193
+ # Process all files
194
+ for filename, file_path in files_to_scan:
195
+ try:
196
+ with open(file_path, 'r', encoding='utf-8') as f:
197
+ content = f.read()
198
+
199
+ # Find @register_tool decorators (two patterns)
200
+ # Pattern 1: @register_tool("name") decorator syntax
201
+ decorator_pattern = r'@register_tool\([\'"]([^\'"]+)[\'"]\)'
202
+ decorator_matches = re.findall(decorator_pattern, content)
203
+
204
+ # Pattern 2: register_tool("name")(ClassName) function call syntax
205
+ function_pattern = r'register_tool\([\'"]([^\'"]+)[\'"]\)\([A-Za-z_][A-Za-z0-9_]*\)'
206
+ function_matches = re.findall(function_pattern, content)
207
+
208
+ # Combine all matches
209
+ all_matches = list(set(decorator_matches + function_matches))
210
+
211
+ for tool_name in all_matches:
212
+ # Try to extract description from class docstring or module docstring
213
+ description = f"{tool_name} tool"
214
+
215
+ # Method 1: Look for class definition after the decorator
216
+ class_pattern = rf'@register_tool\([\'"]({tool_name})[\'"]\)\s*class\s+\w+.*?"""(.*?)"""'
217
+ class_match = re.search(class_pattern, content, re.DOTALL)
218
+ if class_match:
219
+ doc = class_match.group(2).strip()
220
+ # Get first line of docstring
221
+ first_line = doc.split('\n')[0].strip()
222
+ if first_line and len(first_line) < 200:
223
+ description = first_line
224
+
225
+ # Method 2: For __init__.py files, try to extract from module docstring
226
+ if not class_match and filename == '__init__.py':
227
+ module_doc_pattern = r'^"""(.*?)"""'
228
+ module_doc_match = re.search(module_doc_pattern, content, re.DOTALL | re.MULTILINE)
229
+ if module_doc_match:
230
+ doc = module_doc_match.group(1).strip()
231
+ # Get first non-empty line
232
+ for line in doc.split('\n'):
233
+ line = line.strip()
234
+ if line and not line.startswith('#') and len(line) < 200:
235
+ description = line
236
+ break
237
+
238
+ discovered_tools.append((tool_name, description, category))
239
+ except Exception as e:
240
+ logger.debug(f"Error scanning {filename}: {e}")
241
+
242
+ return discovered_tools
243
+
158
244
  def _register_known_tools():
159
245
  """Register known tools without importing heavy dependencies"""
160
- # Pre-register tool classes for discovery without importing modules
161
- # This allows list_tools() to work before actual tool loading
162
- #
163
- # NOTE: Tool names must match the names used in @register_tool decorators:
164
- # - chart (not chart_tool)
165
- # - classifier (not classfire_tool)
166
- # - image (not image_tool)
167
- # - office (not office_tool)
168
- # - pandas (not pandas_tool)
169
- # - report (not report_tool)
170
- # - research (not research_tool)
171
- # - scraper (not scraper_tool)
172
- # - search_api (same)
173
- # - stats (not stats_tool)
246
+ # Automatically discover all tools
247
+ discovered_tools = _auto_discover_tools()
174
248
 
175
- known_tools = [
176
- ("chart", "Chart and visualization operations"),
177
- ("classifier", "Text classification and keyword extraction"),
178
- ("image", "Image processing and OCR operations"),
179
- ("office", "Office document processing"),
180
- ("pandas", "Data analysis and manipulation"),
181
- ("report", "Report generation and formatting"),
182
- ("research", "Research and information gathering"),
183
- ("scraper", "Web scraping and data extraction"),
184
- ("search_api", "Search API integration"),
185
- ("stats", "Statistical analysis and computation")
186
- ]
249
+ logger.info(f"Auto-discovered {len(discovered_tools)} tools")
187
250
 
188
251
  # Register as placeholder until actually loaded
189
- for tool_name, description in known_tools:
252
+ for tool_info in discovered_tools:
253
+ tool_name, description, category = tool_info
190
254
  if tool_name not in TOOL_REGISTRY and tool_name not in TOOL_CLASSES:
191
255
  # Create a placeholder class for discovery
192
256
  class ToolPlaceholder:
193
- def __init__(self, name, desc):
257
+ def __init__(self, name, desc, cat):
194
258
  self.name = name
195
259
  self.description = desc
196
- self.category = "task"
260
+ self.category = cat
197
261
  self.is_placeholder = True
198
262
 
199
- TOOL_REGISTRY[tool_name] = ToolPlaceholder(tool_name, description)
263
+ TOOL_REGISTRY[tool_name] = ToolPlaceholder(tool_name, description, category)
200
264
 
201
265
  # Register known tools for discovery
202
266
  _register_known_tools()
@@ -0,0 +1,106 @@
1
+ """
2
+ APISource Tool - Unified API Data Source Interface
3
+
4
+ A comprehensive tool for querying external API data sources with advanced features:
5
+ - Multi-provider support (FRED, World Bank, News API, Census Bureau)
6
+ - Intelligent query understanding and parameter enhancement
7
+ - Cross-provider data fusion
8
+ - Automatic fallback and retry logic
9
+ - Advanced search with relevance ranking
10
+ - Comprehensive metrics and health monitoring
11
+
12
+ Usage:
13
+ from aiecs.tools.apisource import APISourceTool
14
+
15
+ tool = APISourceTool({
16
+ 'fred_api_key': 'YOUR_KEY',
17
+ 'enable_fallback': True,
18
+ 'enable_query_enhancement': True
19
+ })
20
+
21
+ # Query with natural language
22
+ result = tool.query(
23
+ provider='fred',
24
+ operation='get_series_observations',
25
+ params={'series_id': 'GDP'},
26
+ query_text="Get GDP data for last 5 years"
27
+ )
28
+
29
+ # Multi-provider search with fusion
30
+ results = tool.search(
31
+ query="unemployment trends",
32
+ enable_fusion=True
33
+ )
34
+ """
35
+
36
+ from aiecs.tools.apisource.tool import (
37
+ APISourceTool,
38
+ APISourceError,
39
+ ProviderNotFoundError,
40
+ APIRateLimitError,
41
+ APIAuthenticationError
42
+ )
43
+
44
+ # Import providers for convenience
45
+ from aiecs.tools.apisource.providers import (
46
+ BaseAPIProvider,
47
+ get_provider,
48
+ list_providers,
49
+ PROVIDER_REGISTRY
50
+ )
51
+
52
+ # Import intelligence components
53
+ from aiecs.tools.apisource.intelligence import (
54
+ QueryIntentAnalyzer,
55
+ QueryEnhancer,
56
+ DataFusionEngine,
57
+ SearchEnhancer
58
+ )
59
+
60
+ # Import reliability components
61
+ from aiecs.tools.apisource.reliability import (
62
+ SmartErrorHandler,
63
+ FallbackStrategy
64
+ )
65
+
66
+ # Import monitoring components
67
+ from aiecs.tools.apisource.monitoring import DetailedMetrics
68
+
69
+ # Import utilities
70
+ from aiecs.tools.apisource.utils import DataValidator
71
+
72
+ __version__ = '2.0.0'
73
+
74
+ __all__ = [
75
+ # Main tool
76
+ 'APISourceTool',
77
+
78
+ # Exceptions
79
+ 'APISourceError',
80
+ 'ProviderNotFoundError',
81
+ 'APIRateLimitError',
82
+ 'APIAuthenticationError',
83
+
84
+ # Providers
85
+ 'BaseAPIProvider',
86
+ 'get_provider',
87
+ 'list_providers',
88
+ 'PROVIDER_REGISTRY',
89
+
90
+ # Intelligence
91
+ 'QueryIntentAnalyzer',
92
+ 'QueryEnhancer',
93
+ 'DataFusionEngine',
94
+ 'SearchEnhancer',
95
+
96
+ # Reliability
97
+ 'SmartErrorHandler',
98
+ 'FallbackStrategy',
99
+
100
+ # Monitoring
101
+ 'DetailedMetrics',
102
+
103
+ # Utils
104
+ 'DataValidator'
105
+ ]
106
+
@@ -0,0 +1,20 @@
1
+ """
2
+ Intelligence Module
3
+
4
+ Contains query analysis, data fusion, and search enhancement components.
5
+ """
6
+
7
+ from aiecs.tools.apisource.intelligence.query_analyzer import (
8
+ QueryIntentAnalyzer,
9
+ QueryEnhancer
10
+ )
11
+ from aiecs.tools.apisource.intelligence.data_fusion import DataFusionEngine
12
+ from aiecs.tools.apisource.intelligence.search_enhancer import SearchEnhancer
13
+
14
+ __all__ = [
15
+ 'QueryIntentAnalyzer',
16
+ 'QueryEnhancer',
17
+ 'DataFusionEngine',
18
+ 'SearchEnhancer'
19
+ ]
20
+