aiecs 1.2.2__py3-none-any.whl → 1.3.3__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 (55) hide show
  1. aiecs/__init__.py +1 -1
  2. aiecs/llm/clients/vertex_client.py +22 -2
  3. aiecs/main.py +2 -2
  4. aiecs/scripts/tools_develop/README.md +111 -2
  5. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  6. aiecs/scripts/tools_develop/validate_tool_schemas.py +80 -21
  7. aiecs/scripts/tools_develop/verify_tools.py +347 -0
  8. aiecs/tools/__init__.py +94 -30
  9. aiecs/tools/apisource/__init__.py +106 -0
  10. aiecs/tools/apisource/intelligence/__init__.py +20 -0
  11. aiecs/tools/apisource/intelligence/data_fusion.py +378 -0
  12. aiecs/tools/apisource/intelligence/query_analyzer.py +387 -0
  13. aiecs/tools/apisource/intelligence/search_enhancer.py +384 -0
  14. aiecs/tools/apisource/monitoring/__init__.py +12 -0
  15. aiecs/tools/apisource/monitoring/metrics.py +308 -0
  16. aiecs/tools/apisource/providers/__init__.py +114 -0
  17. aiecs/tools/apisource/providers/base.py +684 -0
  18. aiecs/tools/apisource/providers/census.py +412 -0
  19. aiecs/tools/apisource/providers/fred.py +575 -0
  20. aiecs/tools/apisource/providers/newsapi.py +402 -0
  21. aiecs/tools/apisource/providers/worldbank.py +346 -0
  22. aiecs/tools/apisource/reliability/__init__.py +14 -0
  23. aiecs/tools/apisource/reliability/error_handler.py +362 -0
  24. aiecs/tools/apisource/reliability/fallback_strategy.py +420 -0
  25. aiecs/tools/apisource/tool.py +814 -0
  26. aiecs/tools/apisource/utils/__init__.py +12 -0
  27. aiecs/tools/apisource/utils/validators.py +343 -0
  28. aiecs/tools/langchain_adapter.py +95 -17
  29. aiecs/tools/search_tool/__init__.py +102 -0
  30. aiecs/tools/search_tool/analyzers.py +583 -0
  31. aiecs/tools/search_tool/cache.py +280 -0
  32. aiecs/tools/search_tool/constants.py +127 -0
  33. aiecs/tools/search_tool/context.py +219 -0
  34. aiecs/tools/search_tool/core.py +773 -0
  35. aiecs/tools/search_tool/deduplicator.py +123 -0
  36. aiecs/tools/search_tool/error_handler.py +257 -0
  37. aiecs/tools/search_tool/metrics.py +375 -0
  38. aiecs/tools/search_tool/rate_limiter.py +177 -0
  39. aiecs/tools/search_tool/schemas.py +297 -0
  40. aiecs/tools/statistics/data_loader_tool.py +2 -2
  41. aiecs/tools/statistics/data_transformer_tool.py +1 -1
  42. aiecs/tools/task_tools/__init__.py +8 -8
  43. aiecs/tools/task_tools/report_tool.py +1 -1
  44. aiecs/tools/tool_executor/__init__.py +2 -0
  45. aiecs/tools/tool_executor/tool_executor.py +284 -14
  46. aiecs/utils/__init__.py +11 -0
  47. aiecs/utils/cache_provider.py +698 -0
  48. aiecs/utils/execution_utils.py +5 -5
  49. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/METADATA +1 -1
  50. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/RECORD +54 -22
  51. aiecs/tools/task_tools/search_tool.py +0 -1123
  52. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/WHEEL +0 -0
  53. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/entry_points.txt +0 -0
  54. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/licenses/LICENSE +0 -0
  55. {aiecs-1.2.2.dist-info → aiecs-1.3.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,412 @@
1
+ """
2
+ US Census Bureau API Provider
3
+
4
+ Provides access to US Census Bureau data including demographic,
5
+ economic, and geographic information.
6
+
7
+ API Documentation: https://www.census.gov/data/developers/guidance/api-user-guide.html
8
+ """
9
+
10
+ import logging
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+ from aiecs.tools.apisource.providers.base import BaseAPIProvider, expose_operation
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ # Optional HTTP client
18
+ try:
19
+ import requests
20
+ REQUESTS_AVAILABLE = True
21
+ except ImportError:
22
+ REQUESTS_AVAILABLE = False
23
+
24
+
25
+ class CensusProvider(BaseAPIProvider):
26
+ """
27
+ US Census Bureau API provider for demographic and economic data.
28
+
29
+ Provides access to:
30
+ - American Community Survey (ACS) data
31
+ - Decennial Census
32
+ - Economic indicators
33
+ - Population estimates
34
+ - Geographic data
35
+ """
36
+
37
+ BASE_URL = "https://api.census.gov/data"
38
+
39
+ @property
40
+ def name(self) -> str:
41
+ return "census"
42
+
43
+ @property
44
+ def description(self) -> str:
45
+ return "US Census Bureau API for demographic, economic, and geographic data"
46
+
47
+ @property
48
+ def supported_operations(self) -> List[str]:
49
+ return [
50
+ 'get_acs_data',
51
+ 'get_population',
52
+ 'get_economic_data',
53
+ 'list_datasets',
54
+ 'list_variables'
55
+ ]
56
+
57
+ def validate_params(self, operation: str, params: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
58
+ """Validate parameters for Census API operations"""
59
+
60
+ if operation == 'get_acs_data':
61
+ if 'variables' not in params:
62
+ return False, "Missing required parameter: variables"
63
+ if 'geography' not in params:
64
+ return False, "Missing required parameter: geography"
65
+
66
+ elif operation == 'get_population':
67
+ if 'geography' not in params:
68
+ return False, "Missing required parameter: geography"
69
+
70
+ elif operation == 'get_economic_data':
71
+ if 'variables' not in params:
72
+ return False, "Missing required parameter: variables"
73
+
74
+ return True, None
75
+
76
+ # Exposed operations for AI agent visibility
77
+
78
+ @expose_operation(
79
+ operation_name='get_acs_data',
80
+ description='Get American Community Survey (ACS) demographic and economic data'
81
+ )
82
+ def get_acs_data(
83
+ self,
84
+ variables: str,
85
+ geography: str,
86
+ year: Optional[int] = None
87
+ ) -> Dict[str, Any]:
88
+ """
89
+ Get ACS data.
90
+
91
+ Args:
92
+ variables: Comma-separated variable codes (e.g., 'B01001_001E,B19013_001E')
93
+ geography: Geographic level (e.g., 'state:*', 'county:*', 'tract:*')
94
+ year: Year for data (default: latest available)
95
+
96
+ Returns:
97
+ Dictionary containing ACS data and metadata
98
+ """
99
+ params = {
100
+ 'variables': variables,
101
+ 'geography': geography
102
+ }
103
+ if year:
104
+ params['year'] = year
105
+
106
+ return self.execute('get_acs_data', params)
107
+
108
+ @expose_operation(
109
+ operation_name='get_population',
110
+ description='Get population estimates and demographic data'
111
+ )
112
+ def get_population(
113
+ self,
114
+ geography: str,
115
+ year: Optional[int] = None
116
+ ) -> Dict[str, Any]:
117
+ """
118
+ Get population data.
119
+
120
+ Args:
121
+ geography: Geographic level (e.g., 'state:06', 'county:*')
122
+ year: Year for data (default: latest available)
123
+
124
+ Returns:
125
+ Dictionary containing population data
126
+ """
127
+ params = {'geography': geography}
128
+ if year:
129
+ params['year'] = year
130
+
131
+ return self.execute('get_population', params)
132
+
133
+ @expose_operation(
134
+ operation_name='get_economic_data',
135
+ description='Get economic indicators and business statistics'
136
+ )
137
+ def get_economic_data(
138
+ self,
139
+ variables: str,
140
+ geography: Optional[str] = None,
141
+ year: Optional[int] = None
142
+ ) -> Dict[str, Any]:
143
+ """
144
+ Get economic data.
145
+
146
+ Args:
147
+ variables: Comma-separated variable codes
148
+ geography: Geographic level (optional)
149
+ year: Year for data (default: latest available)
150
+
151
+ Returns:
152
+ Dictionary containing economic data
153
+ """
154
+ params = {'variables': variables}
155
+ if geography:
156
+ params['geography'] = geography
157
+ if year:
158
+ params['year'] = year
159
+
160
+ return self.execute('get_economic_data', params)
161
+
162
+ @expose_operation(
163
+ operation_name='list_datasets',
164
+ description='List all available Census datasets'
165
+ )
166
+ def list_datasets(self) -> Dict[str, Any]:
167
+ """
168
+ List available datasets.
169
+
170
+ Returns:
171
+ Dictionary containing list of datasets
172
+ """
173
+ return self.execute('list_datasets', {})
174
+
175
+ @expose_operation(
176
+ operation_name='list_variables',
177
+ description='List available variables for a specific dataset'
178
+ )
179
+ def list_variables(
180
+ self,
181
+ dataset: Optional[str] = None,
182
+ year: Optional[int] = None
183
+ ) -> Dict[str, Any]:
184
+ """
185
+ List available variables.
186
+
187
+ Args:
188
+ dataset: Dataset name (e.g., 'acs/acs5')
189
+ year: Year for dataset
190
+
191
+ Returns:
192
+ Dictionary containing list of variables
193
+ """
194
+ params = {}
195
+ if dataset:
196
+ params['dataset'] = dataset
197
+ if year:
198
+ params['year'] = year
199
+
200
+ return self.execute('list_variables', params)
201
+
202
+ def fetch(self, operation: str, params: Dict[str, Any]) -> Dict[str, Any]:
203
+ """Fetch data from Census API"""
204
+
205
+ if not REQUESTS_AVAILABLE:
206
+ raise ImportError("requests library is required for Census provider")
207
+
208
+ # Census API may require a key for some datasets
209
+ api_key = self._get_api_key('CENSUS_API_KEY')
210
+ timeout = self.config.get('timeout', 30)
211
+
212
+ # Build endpoint based on operation
213
+ if operation == 'get_acs_data':
214
+ # American Community Survey 5-Year Data
215
+ year = params.get('year', '2021')
216
+ endpoint = f"{self.BASE_URL}/{year}/acs/acs5"
217
+
218
+ # Build query parameters
219
+ variables = params['variables']
220
+ if isinstance(variables, list):
221
+ variables = ','.join(variables)
222
+
223
+ geography = params['geography']
224
+
225
+ query_params = {
226
+ 'get': variables,
227
+ 'for': geography
228
+ }
229
+
230
+ if api_key:
231
+ query_params['key'] = api_key
232
+
233
+ elif operation == 'get_population':
234
+ # Population Estimates
235
+ year = params.get('year', '2021')
236
+ endpoint = f"{self.BASE_URL}/{year}/pep/population"
237
+
238
+ geography = params['geography']
239
+ variables = params.get('variables', 'POP')
240
+
241
+ query_params = {
242
+ 'get': variables,
243
+ 'for': geography
244
+ }
245
+
246
+ if api_key:
247
+ query_params['key'] = api_key
248
+
249
+ elif operation == 'get_economic_data':
250
+ # Economic Census or other economic data
251
+ year = params.get('year', '2017')
252
+ dataset = params.get('dataset', 'ecnbasic')
253
+ endpoint = f"{self.BASE_URL}/{year}/ecnbasic"
254
+
255
+ variables = params['variables']
256
+ if isinstance(variables, list):
257
+ variables = ','.join(variables)
258
+
259
+ geography = params.get('geography', 'state:*')
260
+
261
+ query_params = {
262
+ 'get': variables,
263
+ 'for': geography
264
+ }
265
+
266
+ if api_key:
267
+ query_params['key'] = api_key
268
+
269
+ elif operation == 'list_datasets':
270
+ # List available datasets
271
+ endpoint = f"{self.BASE_URL}.json"
272
+ query_params = {}
273
+
274
+ elif operation == 'list_variables':
275
+ # List variables for a dataset
276
+ year = params.get('year', '2021')
277
+ dataset = params.get('dataset', 'acs/acs5')
278
+ endpoint = f"{self.BASE_URL}/{year}/{dataset}/variables.json"
279
+ query_params = {}
280
+
281
+ else:
282
+ raise ValueError(f"Unknown operation: {operation}")
283
+
284
+ # Make API request
285
+ try:
286
+ response = requests.get(
287
+ endpoint,
288
+ params=query_params,
289
+ timeout=timeout
290
+ )
291
+ response.raise_for_status()
292
+
293
+ data = response.json()
294
+
295
+ # Census API typically returns array of arrays
296
+ # First row is headers, subsequent rows are data
297
+ if operation in ['get_acs_data', 'get_population', 'get_economic_data']:
298
+ if isinstance(data, list) and len(data) > 1:
299
+ headers = data[0]
300
+ rows = data[1:]
301
+
302
+ # Convert to list of dictionaries
303
+ result_data = [
304
+ dict(zip(headers, row)) for row in rows
305
+ ]
306
+ else:
307
+ result_data = data
308
+ else:
309
+ result_data = data
310
+
311
+ return self._format_response(
312
+ operation=operation,
313
+ data=result_data,
314
+ source=f"US Census Bureau - {endpoint}"
315
+ )
316
+
317
+ except requests.exceptions.RequestException as e:
318
+ self.logger.error(f"Census API request failed: {e}")
319
+ raise Exception(f"Census API request failed: {str(e)}")
320
+
321
+ def get_operation_schema(self, operation: str) -> Optional[Dict[str, Any]]:
322
+ """Get detailed schema for Census API operations"""
323
+
324
+ schemas = {
325
+ 'get_acs_data': {
326
+ 'description': 'Get American Community Survey data',
327
+ 'parameters': {
328
+ 'variables': {
329
+ 'type': 'string',
330
+ 'required': True,
331
+ 'description': 'Comma-separated variable codes',
332
+ 'examples': ['B01001_001E', 'B19013_001E', 'B25077_001E']
333
+ },
334
+ 'geography': {
335
+ 'type': 'string',
336
+ 'required': True,
337
+ 'description': 'Geographic level specification',
338
+ 'examples': ['state:*', 'county:*', 'state:06', 'county:037']
339
+ },
340
+ 'year': {
341
+ 'type': 'integer',
342
+ 'required': False,
343
+ 'description': 'Year for data',
344
+ 'examples': [2020, 2021, 2022]
345
+ }
346
+ }
347
+ },
348
+ 'get_population': {
349
+ 'description': 'Get population estimates',
350
+ 'parameters': {
351
+ 'geography': {
352
+ 'type': 'string',
353
+ 'required': True,
354
+ 'description': 'Geographic level specification',
355
+ 'examples': ['state:*', 'state:06', 'county:*']
356
+ },
357
+ 'year': {
358
+ 'type': 'integer',
359
+ 'required': False,
360
+ 'description': 'Year for data',
361
+ 'examples': [2020, 2021, 2022]
362
+ }
363
+ }
364
+ },
365
+ 'get_economic_data': {
366
+ 'description': 'Get economic indicators',
367
+ 'parameters': {
368
+ 'variables': {
369
+ 'type': 'string',
370
+ 'required': True,
371
+ 'description': 'Comma-separated variable codes',
372
+ 'examples': ['EMP', 'PAYANN', 'ESTAB']
373
+ },
374
+ 'geography': {
375
+ 'type': 'string',
376
+ 'required': False,
377
+ 'description': 'Geographic level specification',
378
+ 'examples': ['state:*', 'county:*']
379
+ },
380
+ 'year': {
381
+ 'type': 'integer',
382
+ 'required': False,
383
+ 'description': 'Year for data',
384
+ 'examples': [2020, 2021, 2022]
385
+ }
386
+ }
387
+ },
388
+ 'list_datasets': {
389
+ 'description': 'List all available datasets',
390
+ 'parameters': {}
391
+ },
392
+ 'list_variables': {
393
+ 'description': 'List available variables',
394
+ 'parameters': {
395
+ 'dataset': {
396
+ 'type': 'string',
397
+ 'required': False,
398
+ 'description': 'Dataset name',
399
+ 'examples': ['acs/acs5', 'acs/acs1', 'pep/population']
400
+ },
401
+ 'year': {
402
+ 'type': 'integer',
403
+ 'required': False,
404
+ 'description': 'Year for dataset',
405
+ 'examples': [2020, 2021, 2022]
406
+ }
407
+ }
408
+ }
409
+ }
410
+
411
+ return schemas.get(operation)
412
+