aigroup-econ-mcp 0.4.2__py3-none-any.whl → 1.4.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.
- .gitignore +253 -0
- PKG-INFO +710 -0
- README.md +672 -0
- __init__.py +14 -0
- aigroup_econ_mcp-1.4.3.dist-info/METADATA +710 -0
- aigroup_econ_mcp-1.4.3.dist-info/RECORD +92 -0
- aigroup_econ_mcp-1.4.3.dist-info/entry_points.txt +2 -0
- aigroup_econ_mcp-1.4.3.dist-info/licenses/LICENSE +21 -0
- cli.py +28 -0
- econometrics/README.md +18 -0
- econometrics/__init__.py +191 -0
- econometrics/advanced_methods/modern_computing_machine_learning/__init__.py +0 -0
- econometrics/basic_parametric_estimation/__init__.py +31 -0
- econometrics/basic_parametric_estimation/gmm/__init__.py +13 -0
- econometrics/basic_parametric_estimation/gmm/gmm_model.py +256 -0
- econometrics/basic_parametric_estimation/mle/__init__.py +13 -0
- econometrics/basic_parametric_estimation/mle/mle_model.py +241 -0
- econometrics/basic_parametric_estimation/ols/__init__.py +13 -0
- econometrics/basic_parametric_estimation/ols/ols_model.py +141 -0
- econometrics/causal_inference/causal_identification_strategy/__init__.py +0 -0
- econometrics/missing_data/missing_data_measurement_error/__init__.py +0 -0
- econometrics/model_specification_diagnostics_robust_inference/README.md +173 -0
- econometrics/model_specification_diagnostics_robust_inference/__init__.py +78 -0
- econometrics/model_specification_diagnostics_robust_inference/diagnostic_tests/__init__.py +20 -0
- econometrics/model_specification_diagnostics_robust_inference/diagnostic_tests/diagnostic_tests_model.py +149 -0
- econometrics/model_specification_diagnostics_robust_inference/generalized_least_squares/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/generalized_least_squares/gls_model.py +130 -0
- econometrics/model_specification_diagnostics_robust_inference/model_selection/__init__.py +18 -0
- econometrics/model_specification_diagnostics_robust_inference/model_selection/model_selection_model.py +286 -0
- econometrics/model_specification_diagnostics_robust_inference/regularization/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/regularization/regularization_model.py +177 -0
- econometrics/model_specification_diagnostics_robust_inference/robust_errors/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/robust_errors/robust_errors_model.py +122 -0
- econometrics/model_specification_diagnostics_robust_inference/simultaneous_equations/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/simultaneous_equations/simultaneous_equations_model.py +246 -0
- econometrics/model_specification_diagnostics_robust_inference/weighted_least_squares/__init__.py +15 -0
- econometrics/model_specification_diagnostics_robust_inference/weighted_least_squares/wls_model.py +127 -0
- econometrics/nonparametric/nonparametric_semiparametric_methods/__init__.py +0 -0
- econometrics/spatial_econometrics/spatial_econometrics_new/__init__.py +0 -0
- econometrics/specific_data_modeling/micro_discrete_limited_data/__init__.py +0 -0
- econometrics/specific_data_modeling/survival_duration_data/__init__.py +0 -0
- econometrics/specific_data_modeling/time_series_panel_data/__init__.py +143 -0
- econometrics/specific_data_modeling/time_series_panel_data/arima_model.py +104 -0
- econometrics/specific_data_modeling/time_series_panel_data/cointegration_vecm.py +334 -0
- econometrics/specific_data_modeling/time_series_panel_data/dynamic_panel_models.py +653 -0
- econometrics/specific_data_modeling/time_series_panel_data/exponential_smoothing.py +176 -0
- econometrics/specific_data_modeling/time_series_panel_data/garch_model.py +198 -0
- econometrics/specific_data_modeling/time_series_panel_data/panel_diagnostics.py +125 -0
- econometrics/specific_data_modeling/time_series_panel_data/panel_var.py +60 -0
- econometrics/specific_data_modeling/time_series_panel_data/structural_break_tests.py +87 -0
- econometrics/specific_data_modeling/time_series_panel_data/time_varying_parameter_models.py +106 -0
- econometrics/specific_data_modeling/time_series_panel_data/unit_root_tests.py +204 -0
- econometrics/specific_data_modeling/time_series_panel_data/var_svar_model.py +372 -0
- econometrics/statistical_inference/statistical_inference_techniques/__init__.py +0 -0
- econometrics/statistics/distribution_decomposition_methods/__init__.py +0 -0
- econometrics/tests/basic_parametric_estimation_tests/__init__.py +3 -0
- econometrics/tests/basic_parametric_estimation_tests/test_gmm.py +128 -0
- econometrics/tests/basic_parametric_estimation_tests/test_mle.py +127 -0
- econometrics/tests/basic_parametric_estimation_tests/test_ols.py +100 -0
- econometrics/tests/model_specification_diagnostics_tests/__init__.py +3 -0
- econometrics/tests/model_specification_diagnostics_tests/test_diagnostic_tests.py +86 -0
- econometrics/tests/model_specification_diagnostics_tests/test_robust_errors.py +89 -0
- econometrics/tests/specific_data_modeling_tests/__init__.py +3 -0
- econometrics/tests/specific_data_modeling_tests/test_arima.py +98 -0
- econometrics/tests/specific_data_modeling_tests/test_dynamic_panel.py +198 -0
- econometrics/tests/specific_data_modeling_tests/test_exponential_smoothing.py +105 -0
- econometrics/tests/specific_data_modeling_tests/test_garch.py +118 -0
- econometrics/tests/specific_data_modeling_tests/test_unit_root.py +156 -0
- econometrics/tests/specific_data_modeling_tests/test_var.py +124 -0
- prompts/__init__.py +0 -0
- prompts/analysis_guides.py +43 -0
- pyproject.toml +78 -0
- resources/MCP_MASTER_GUIDE.md +422 -0
- resources/MCP_TOOLS_DATA_FORMAT_GUIDE.md +185 -0
- resources/__init__.py +0 -0
- server.py +83 -0
- tools/README.md +88 -0
- tools/__init__.py +45 -0
- tools/data_loader.py +213 -0
- tools/decorators.py +38 -0
- tools/econometrics_adapter.py +286 -0
- tools/mcp_tool_groups/__init__.py +1 -0
- tools/mcp_tool_groups/basic_parametric_tools.py +173 -0
- tools/mcp_tool_groups/model_specification_tools.py +402 -0
- tools/mcp_tool_groups/time_series_tools.py +494 -0
- tools/mcp_tools_registry.py +114 -0
- tools/model_specification_adapter.py +369 -0
- tools/output_formatter.py +563 -0
- tools/time_series_panel_data_adapter.py +858 -0
- tools/time_series_panel_data_tools.py +65 -0
- aigroup_econ_mcp/__init__.py +0 -19
- aigroup_econ_mcp/cli.py +0 -82
- aigroup_econ_mcp/config.py +0 -561
- aigroup_econ_mcp/server.py +0 -452
- aigroup_econ_mcp/tools/__init__.py +0 -18
- aigroup_econ_mcp/tools/base.py +0 -470
- aigroup_econ_mcp/tools/cache.py +0 -533
- aigroup_econ_mcp/tools/data_loader.py +0 -171
- aigroup_econ_mcp/tools/file_parser.py +0 -829
- aigroup_econ_mcp/tools/machine_learning.py +0 -60
- aigroup_econ_mcp/tools/ml_ensemble.py +0 -210
- aigroup_econ_mcp/tools/ml_evaluation.py +0 -272
- aigroup_econ_mcp/tools/ml_models.py +0 -54
- aigroup_econ_mcp/tools/ml_regularization.py +0 -172
- aigroup_econ_mcp/tools/monitoring.py +0 -555
- aigroup_econ_mcp/tools/optimized_example.py +0 -229
- aigroup_econ_mcp/tools/panel_data.py +0 -553
- aigroup_econ_mcp/tools/regression.py +0 -214
- aigroup_econ_mcp/tools/statistics.py +0 -154
- aigroup_econ_mcp/tools/time_series.py +0 -667
- aigroup_econ_mcp/tools/timeout.py +0 -283
- aigroup_econ_mcp/tools/tool_handlers.py +0 -378
- aigroup_econ_mcp/tools/tool_registry.py +0 -170
- aigroup_econ_mcp/tools/validation.py +0 -482
- aigroup_econ_mcp-0.4.2.dist-info/METADATA +0 -360
- aigroup_econ_mcp-0.4.2.dist-info/RECORD +0 -29
- aigroup_econ_mcp-0.4.2.dist-info/entry_points.txt +0 -2
- /aigroup_econ_mcp-0.4.2.dist-info/licenses/LICENSE → /LICENSE +0 -0
- {aigroup_econ_mcp-0.4.2.dist-info → aigroup_econ_mcp-1.4.3.dist-info}/WHEEL +0 -0
aigroup_econ_mcp/tools/cache.py
DELETED
|
@@ -1,533 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
缓存机制模块
|
|
3
|
-
提供LRU缓存策略和结果缓存功能
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import time
|
|
7
|
-
import hashlib
|
|
8
|
-
import pickle
|
|
9
|
-
import threading
|
|
10
|
-
from typing import Any, Dict, List, Optional, Callable, Tuple
|
|
11
|
-
from collections import OrderedDict
|
|
12
|
-
from dataclasses import dataclass
|
|
13
|
-
from enum import Enum
|
|
14
|
-
import json
|
|
15
|
-
import warnings
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class CachePolicy(Enum):
|
|
19
|
-
"""缓存策略"""
|
|
20
|
-
LRU = "lru" # 最近最少使用
|
|
21
|
-
FIFO = "fifo" # 先进先出
|
|
22
|
-
LFU = "lfu" # 最不经常使用
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@dataclass
|
|
26
|
-
class CacheEntry:
|
|
27
|
-
"""缓存条目"""
|
|
28
|
-
key: str
|
|
29
|
-
value: Any
|
|
30
|
-
timestamp: float
|
|
31
|
-
access_count: int = 0
|
|
32
|
-
size: int = 0
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class LRUCache:
|
|
36
|
-
"""
|
|
37
|
-
LRU缓存实现
|
|
38
|
-
使用最近最少使用策略管理缓存
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
def __init__(self, max_size: int = 1000, ttl: Optional[int] = None):
|
|
42
|
-
"""
|
|
43
|
-
初始化LRU缓存
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
max_size: 最大缓存条目数
|
|
47
|
-
ttl: 缓存生存时间(秒),None表示永不过期
|
|
48
|
-
"""
|
|
49
|
-
self.max_size = max_size
|
|
50
|
-
self.ttl = ttl
|
|
51
|
-
self._cache: OrderedDict[str, CacheEntry] = OrderedDict()
|
|
52
|
-
self._lock = threading.RLock()
|
|
53
|
-
self._hits = 0
|
|
54
|
-
self._misses = 0
|
|
55
|
-
self._evictions = 0
|
|
56
|
-
|
|
57
|
-
def get(self, key: str) -> Optional[Any]:
|
|
58
|
-
"""
|
|
59
|
-
获取缓存值
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
key: 缓存键
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
Optional[Any]: 缓存值,如果不存在或过期则返回None
|
|
66
|
-
"""
|
|
67
|
-
with self._lock:
|
|
68
|
-
if key not in self._cache:
|
|
69
|
-
self._misses += 1
|
|
70
|
-
return None
|
|
71
|
-
|
|
72
|
-
entry = self._cache[key]
|
|
73
|
-
|
|
74
|
-
# 检查是否过期
|
|
75
|
-
if self.ttl and (time.time() - entry.timestamp) > self.ttl:
|
|
76
|
-
del self._cache[key]
|
|
77
|
-
self._misses += 1
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
# 更新访问时间和计数
|
|
81
|
-
entry.timestamp = time.time()
|
|
82
|
-
entry.access_count += 1
|
|
83
|
-
self._cache.move_to_end(key)
|
|
84
|
-
|
|
85
|
-
self._hits += 1
|
|
86
|
-
return entry.value
|
|
87
|
-
|
|
88
|
-
def set(self, key: str, value: Any, size: int = 0) -> None:
|
|
89
|
-
"""
|
|
90
|
-
设置缓存值
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
key: 缓存键
|
|
94
|
-
value: 缓存值
|
|
95
|
-
size: 缓存大小(字节),用于大小限制
|
|
96
|
-
"""
|
|
97
|
-
with self._lock:
|
|
98
|
-
# 如果键已存在,先删除
|
|
99
|
-
if key in self._cache:
|
|
100
|
-
del self._cache[key]
|
|
101
|
-
|
|
102
|
-
# 创建新的缓存条目
|
|
103
|
-
entry = CacheEntry(
|
|
104
|
-
key=key,
|
|
105
|
-
value=value,
|
|
106
|
-
timestamp=time.time(),
|
|
107
|
-
size=size
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
self._cache[key] = entry
|
|
111
|
-
self._cache.move_to_end(key)
|
|
112
|
-
|
|
113
|
-
# 如果超过最大大小,移除最旧的条目
|
|
114
|
-
while len(self._cache) > self.max_size:
|
|
115
|
-
oldest_key, oldest_entry = next(iter(self._cache.items()))
|
|
116
|
-
del self._cache[oldest_key]
|
|
117
|
-
self._evictions += 1
|
|
118
|
-
|
|
119
|
-
def delete(self, key: str) -> bool:
|
|
120
|
-
"""
|
|
121
|
-
删除缓存条目
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
key: 缓存键
|
|
125
|
-
|
|
126
|
-
Returns:
|
|
127
|
-
bool: 是否成功删除
|
|
128
|
-
"""
|
|
129
|
-
with self._lock:
|
|
130
|
-
if key in self._cache:
|
|
131
|
-
del self._cache[key]
|
|
132
|
-
return True
|
|
133
|
-
return False
|
|
134
|
-
|
|
135
|
-
def clear(self) -> None:
|
|
136
|
-
"""清空缓存"""
|
|
137
|
-
with self._lock:
|
|
138
|
-
self._cache.clear()
|
|
139
|
-
self._hits = 0
|
|
140
|
-
self._misses = 0
|
|
141
|
-
self._evictions = 0
|
|
142
|
-
|
|
143
|
-
def contains(self, key: str) -> bool:
|
|
144
|
-
"""
|
|
145
|
-
检查缓存是否包含指定键
|
|
146
|
-
|
|
147
|
-
Args:
|
|
148
|
-
key: 缓存键
|
|
149
|
-
|
|
150
|
-
Returns:
|
|
151
|
-
bool: 是否包含
|
|
152
|
-
"""
|
|
153
|
-
with self._lock:
|
|
154
|
-
if key not in self._cache:
|
|
155
|
-
return False
|
|
156
|
-
|
|
157
|
-
# 检查是否过期
|
|
158
|
-
entry = self._cache[key]
|
|
159
|
-
if self.ttl and (time.time() - entry.timestamp) > self.ttl:
|
|
160
|
-
del self._cache[key]
|
|
161
|
-
return False
|
|
162
|
-
|
|
163
|
-
return True
|
|
164
|
-
|
|
165
|
-
def get_stats(self) -> Dict[str, Any]:
|
|
166
|
-
"""
|
|
167
|
-
获取缓存统计信息
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
Dict[str, Any]: 统计信息
|
|
171
|
-
"""
|
|
172
|
-
with self._lock:
|
|
173
|
-
total_requests = self._hits + self._misses
|
|
174
|
-
hit_rate = self._hits / total_requests if total_requests > 0 else 0
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
"size": len(self._cache),
|
|
178
|
-
"max_size": self.max_size,
|
|
179
|
-
"hits": self._hits,
|
|
180
|
-
"misses": self._misses,
|
|
181
|
-
"evictions": self._evictions,
|
|
182
|
-
"hit_rate": hit_rate,
|
|
183
|
-
"memory_usage": sum(entry.size for entry in self._cache.values())
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
def keys(self) -> List[str]:
|
|
187
|
-
"""
|
|
188
|
-
获取所有缓存键
|
|
189
|
-
|
|
190
|
-
Returns:
|
|
191
|
-
List[str]: 缓存键列表
|
|
192
|
-
"""
|
|
193
|
-
with self._lock:
|
|
194
|
-
return list(self._cache.keys())
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class ResultCache:
|
|
198
|
-
"""
|
|
199
|
-
结果缓存管理器
|
|
200
|
-
提供函数结果缓存和智能缓存管理
|
|
201
|
-
"""
|
|
202
|
-
|
|
203
|
-
def __init__(self, max_size: int = 1000, ttl: int = 3600):
|
|
204
|
-
"""
|
|
205
|
-
初始化结果缓存
|
|
206
|
-
|
|
207
|
-
Args:
|
|
208
|
-
max_size: 最大缓存条目数
|
|
209
|
-
ttl: 缓存生存时间(秒)
|
|
210
|
-
"""
|
|
211
|
-
self.cache = LRUCache(max_size=max_size, ttl=ttl)
|
|
212
|
-
self._function_cache: Dict[str, LRUCache] = {}
|
|
213
|
-
|
|
214
|
-
def generate_key(self, func_name: str, *args, **kwargs) -> str:
|
|
215
|
-
"""
|
|
216
|
-
生成缓存键
|
|
217
|
-
|
|
218
|
-
Args:
|
|
219
|
-
func_name: 函数名称
|
|
220
|
-
*args: 位置参数
|
|
221
|
-
**kwargs: 关键字参数
|
|
222
|
-
|
|
223
|
-
Returns:
|
|
224
|
-
str: 缓存键
|
|
225
|
-
"""
|
|
226
|
-
# 序列化参数
|
|
227
|
-
try:
|
|
228
|
-
# 使用JSON序列化,处理基本数据类型
|
|
229
|
-
args_str = json.dumps(args, sort_keys=True, default=str)
|
|
230
|
-
kwargs_str = json.dumps(kwargs, sort_keys=True, default=str)
|
|
231
|
-
key_data = f"{func_name}:{args_str}:{kwargs_str}"
|
|
232
|
-
except (TypeError, ValueError):
|
|
233
|
-
# 如果JSON序列化失败,使用pickle
|
|
234
|
-
key_data = f"{func_name}:{pickle.dumps((args, kwargs))}"
|
|
235
|
-
|
|
236
|
-
# 生成哈希键
|
|
237
|
-
return hashlib.md5(key_data.encode()).hexdigest()
|
|
238
|
-
|
|
239
|
-
def cached(self, func: Callable = None, *, ttl: Optional[int] = None, max_size: int = 100):
|
|
240
|
-
"""
|
|
241
|
-
缓存装饰器
|
|
242
|
-
|
|
243
|
-
Args:
|
|
244
|
-
func: 被装饰的函数
|
|
245
|
-
ttl: 缓存生存时间(秒)
|
|
246
|
-
max_size: 函数特定的最大缓存大小
|
|
247
|
-
|
|
248
|
-
Returns:
|
|
249
|
-
Callable: 装饰后的函数
|
|
250
|
-
"""
|
|
251
|
-
def decorator(f):
|
|
252
|
-
func_name = f.__name__
|
|
253
|
-
|
|
254
|
-
# 为每个函数创建独立的缓存
|
|
255
|
-
if func_name not in self._function_cache:
|
|
256
|
-
self._function_cache[func_name] = LRUCache(
|
|
257
|
-
max_size=max_size,
|
|
258
|
-
ttl=ttl or self.cache.ttl
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
func_cache = self._function_cache[func_name]
|
|
262
|
-
|
|
263
|
-
def wrapper(*args, **kwargs):
|
|
264
|
-
# 生成缓存键
|
|
265
|
-
cache_key = self.generate_key(func_name, *args, **kwargs)
|
|
266
|
-
|
|
267
|
-
# 尝试从缓存获取结果
|
|
268
|
-
cached_result = func_cache.get(cache_key)
|
|
269
|
-
if cached_result is not None:
|
|
270
|
-
return cached_result
|
|
271
|
-
|
|
272
|
-
# 执行函数并缓存结果
|
|
273
|
-
result = f(*args, **kwargs)
|
|
274
|
-
func_cache.set(cache_key, result)
|
|
275
|
-
|
|
276
|
-
return result
|
|
277
|
-
|
|
278
|
-
# 保留原始函数的元数据
|
|
279
|
-
wrapper.__name__ = f.__name__
|
|
280
|
-
wrapper.__doc__ = f.__doc__
|
|
281
|
-
wrapper.__module__ = f.__module__
|
|
282
|
-
|
|
283
|
-
return wrapper
|
|
284
|
-
|
|
285
|
-
if func is None:
|
|
286
|
-
return decorator
|
|
287
|
-
else:
|
|
288
|
-
return decorator(func)
|
|
289
|
-
|
|
290
|
-
def get_function_cache_stats(self, func_name: str) -> Optional[Dict[str, Any]]:
|
|
291
|
-
"""
|
|
292
|
-
获取函数缓存统计信息
|
|
293
|
-
|
|
294
|
-
Args:
|
|
295
|
-
func_name: 函数名称
|
|
296
|
-
|
|
297
|
-
Returns:
|
|
298
|
-
Optional[Dict[str, Any]]: 统计信息,如果函数没有缓存则返回None
|
|
299
|
-
"""
|
|
300
|
-
if func_name in self._function_cache:
|
|
301
|
-
return self._function_cache[func_name].get_stats()
|
|
302
|
-
return None
|
|
303
|
-
|
|
304
|
-
def clear_function_cache(self, func_name: str) -> bool:
|
|
305
|
-
"""
|
|
306
|
-
清空指定函数的缓存
|
|
307
|
-
|
|
308
|
-
Args:
|
|
309
|
-
func_name: 函数名称
|
|
310
|
-
|
|
311
|
-
Returns:
|
|
312
|
-
bool: 是否成功清空
|
|
313
|
-
"""
|
|
314
|
-
if func_name in self._function_cache:
|
|
315
|
-
self._function_cache[func_name].clear()
|
|
316
|
-
return True
|
|
317
|
-
return False
|
|
318
|
-
|
|
319
|
-
def clear_all(self) -> None:
|
|
320
|
-
"""清空所有缓存"""
|
|
321
|
-
for cache in self._function_cache.values():
|
|
322
|
-
cache.clear()
|
|
323
|
-
|
|
324
|
-
def get_global_stats(self) -> Dict[str, Any]:
|
|
325
|
-
"""
|
|
326
|
-
获取全局缓存统计信息
|
|
327
|
-
|
|
328
|
-
Returns:
|
|
329
|
-
Dict[str, Any]: 全局统计信息
|
|
330
|
-
"""
|
|
331
|
-
total_hits = 0
|
|
332
|
-
total_misses = 0
|
|
333
|
-
total_size = 0
|
|
334
|
-
function_stats = {}
|
|
335
|
-
|
|
336
|
-
for func_name, cache in self._function_cache.items():
|
|
337
|
-
stats = cache.get_stats()
|
|
338
|
-
total_hits += stats["hits"]
|
|
339
|
-
total_misses += stats["misses"]
|
|
340
|
-
total_size += stats["memory_usage"]
|
|
341
|
-
function_stats[func_name] = stats
|
|
342
|
-
|
|
343
|
-
total_requests = total_hits + total_misses
|
|
344
|
-
global_hit_rate = total_hits / total_requests if total_requests > 0 else 0
|
|
345
|
-
|
|
346
|
-
return {
|
|
347
|
-
"total_functions": len(self._function_cache),
|
|
348
|
-
"total_hits": total_hits,
|
|
349
|
-
"total_misses": total_misses,
|
|
350
|
-
"global_hit_rate": global_hit_rate,
|
|
351
|
-
"total_memory_usage": total_size,
|
|
352
|
-
"function_stats": function_stats
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
class EconometricCache:
|
|
357
|
-
"""
|
|
358
|
-
计量经济学专用缓存
|
|
359
|
-
针对计量经济学计算结果的优化缓存
|
|
360
|
-
"""
|
|
361
|
-
|
|
362
|
-
def __init__(self):
|
|
363
|
-
self.result_cache = ResultCache(max_size=500, ttl=7200) # 2小时TTL
|
|
364
|
-
self._model_cache: Dict[str, Any] = {}
|
|
365
|
-
self._data_cache: Dict[str, Any] = {}
|
|
366
|
-
|
|
367
|
-
def cache_model_result(self, model_type: str, data_hash: str, parameters: Dict, result: Any) -> str:
|
|
368
|
-
"""
|
|
369
|
-
缓存模型结果
|
|
370
|
-
|
|
371
|
-
Args:
|
|
372
|
-
model_type: 模型类型
|
|
373
|
-
data_hash: 数据哈希
|
|
374
|
-
parameters: 模型参数
|
|
375
|
-
result: 模型结果
|
|
376
|
-
|
|
377
|
-
Returns:
|
|
378
|
-
str: 缓存键
|
|
379
|
-
"""
|
|
380
|
-
cache_key = f"{model_type}:{data_hash}:{hash(str(parameters))}"
|
|
381
|
-
self._model_cache[cache_key] = {
|
|
382
|
-
"result": result,
|
|
383
|
-
"timestamp": time.time(),
|
|
384
|
-
"model_type": model_type,
|
|
385
|
-
"parameters": parameters
|
|
386
|
-
}
|
|
387
|
-
return cache_key
|
|
388
|
-
|
|
389
|
-
def get_cached_model_result(self, model_type: str, data_hash: str, parameters: Dict) -> Optional[Any]:
|
|
390
|
-
"""
|
|
391
|
-
获取缓存的模型结果
|
|
392
|
-
|
|
393
|
-
Args:
|
|
394
|
-
model_type: 模型类型
|
|
395
|
-
data_hash: 数据哈希
|
|
396
|
-
parameters: 模型参数
|
|
397
|
-
|
|
398
|
-
Returns:
|
|
399
|
-
Optional[Any]: 缓存的结果,如果不存在则返回None
|
|
400
|
-
"""
|
|
401
|
-
cache_key = f"{model_type}:{data_hash}:{hash(str(parameters))}"
|
|
402
|
-
return self._model_cache.get(cache_key, {}).get("result")
|
|
403
|
-
|
|
404
|
-
def cache_data_analysis(self, data_hash: str, analysis_type: str, result: Any) -> str:
|
|
405
|
-
"""
|
|
406
|
-
缓存数据分析结果
|
|
407
|
-
|
|
408
|
-
Args:
|
|
409
|
-
data_hash: 数据哈希
|
|
410
|
-
analysis_type: 分析类型
|
|
411
|
-
result: 分析结果
|
|
412
|
-
|
|
413
|
-
Returns:
|
|
414
|
-
str: 缓存键
|
|
415
|
-
"""
|
|
416
|
-
cache_key = f"analysis:{analysis_type}:{data_hash}"
|
|
417
|
-
self._data_cache[cache_key] = {
|
|
418
|
-
"result": result,
|
|
419
|
-
"timestamp": time.time(),
|
|
420
|
-
"analysis_type": analysis_type
|
|
421
|
-
}
|
|
422
|
-
return cache_key
|
|
423
|
-
|
|
424
|
-
def get_cached_data_analysis(self, data_hash: str, analysis_type: str) -> Optional[Any]:
|
|
425
|
-
"""
|
|
426
|
-
获取缓存的数据分析结果
|
|
427
|
-
|
|
428
|
-
Args:
|
|
429
|
-
data_hash: 数据哈希
|
|
430
|
-
analysis_type: 分析类型
|
|
431
|
-
|
|
432
|
-
Returns:
|
|
433
|
-
Optional[Any]: 缓存的结果,如果不存在则返回None
|
|
434
|
-
"""
|
|
435
|
-
cache_key = f"analysis:{analysis_type}:{data_hash}"
|
|
436
|
-
return self._data_cache.get(cache_key, {}).get("result")
|
|
437
|
-
|
|
438
|
-
def clear_old_entries(self, max_age: int = 86400) -> int:
|
|
439
|
-
"""
|
|
440
|
-
清理过期的缓存条目
|
|
441
|
-
|
|
442
|
-
Args:
|
|
443
|
-
max_age: 最大年龄(秒)
|
|
444
|
-
|
|
445
|
-
Returns:
|
|
446
|
-
int: 清理的条目数量
|
|
447
|
-
"""
|
|
448
|
-
current_time = time.time()
|
|
449
|
-
removed_count = 0
|
|
450
|
-
|
|
451
|
-
# 清理模型缓存
|
|
452
|
-
keys_to_remove = []
|
|
453
|
-
for key, entry in self._model_cache.items():
|
|
454
|
-
if current_time - entry["timestamp"] > max_age:
|
|
455
|
-
keys_to_remove.append(key)
|
|
456
|
-
|
|
457
|
-
for key in keys_to_remove:
|
|
458
|
-
del self._model_cache[key]
|
|
459
|
-
removed_count += 1
|
|
460
|
-
|
|
461
|
-
# 清理数据缓存
|
|
462
|
-
keys_to_remove = []
|
|
463
|
-
for key, entry in self._data_cache.items():
|
|
464
|
-
if current_time - entry["timestamp"] > max_age:
|
|
465
|
-
keys_to_remove.append(key)
|
|
466
|
-
|
|
467
|
-
for key in keys_to_remove:
|
|
468
|
-
del self._data_cache[key]
|
|
469
|
-
removed_count += 1
|
|
470
|
-
|
|
471
|
-
return removed_count
|
|
472
|
-
|
|
473
|
-
def get_cache_info(self) -> Dict[str, Any]:
|
|
474
|
-
"""
|
|
475
|
-
获取缓存信息
|
|
476
|
-
|
|
477
|
-
Returns:
|
|
478
|
-
Dict[str, Any]: 缓存信息
|
|
479
|
-
"""
|
|
480
|
-
return {
|
|
481
|
-
"model_cache_size": len(self._model_cache),
|
|
482
|
-
"data_cache_size": len(self._data_cache),
|
|
483
|
-
"result_cache_stats": self.result_cache.get_global_stats()
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
# 全局缓存实例
|
|
488
|
-
global_econometric_cache = EconometricCache()
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
# 便捷缓存装饰器
|
|
492
|
-
def cache_result(ttl: int = 3600, max_size: int = 100):
|
|
493
|
-
"""
|
|
494
|
-
便捷的结果缓存装饰器
|
|
495
|
-
|
|
496
|
-
Args:
|
|
497
|
-
ttl: 缓存生存时间(秒)
|
|
498
|
-
max_size: 最大缓存大小
|
|
499
|
-
|
|
500
|
-
Returns:
|
|
501
|
-
Callable: 装饰器函数
|
|
502
|
-
"""
|
|
503
|
-
return global_econometric_cache.result_cache.cached(ttl=ttl, max_size=max_size)
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
def cache_model(ttl: int = 7200):
|
|
507
|
-
"""
|
|
508
|
-
模型结果缓存装饰器
|
|
509
|
-
|
|
510
|
-
Args:
|
|
511
|
-
ttl: 缓存生存时间(秒)
|
|
512
|
-
|
|
513
|
-
Returns:
|
|
514
|
-
Callable: 装饰器函数
|
|
515
|
-
"""
|
|
516
|
-
def decorator(func):
|
|
517
|
-
@cache_result(ttl=ttl, max_size=50)
|
|
518
|
-
def wrapper(*args, **kwargs):
|
|
519
|
-
return func(*args, **kwargs)
|
|
520
|
-
return wrapper
|
|
521
|
-
return decorator
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
# 导出主要类和函数
|
|
525
|
-
__all__ = [
|
|
526
|
-
"CachePolicy",
|
|
527
|
-
"LRUCache",
|
|
528
|
-
"ResultCache",
|
|
529
|
-
"EconometricCache",
|
|
530
|
-
"global_econometric_cache",
|
|
531
|
-
"cache_result",
|
|
532
|
-
"cache_model"
|
|
533
|
-
]
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
数据加载辅助模块
|
|
3
|
-
提供通用的CSV文件加载功能
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from typing import Dict, List, Union
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
import pandas as pd
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async def load_data_if_path(
|
|
12
|
-
data: Union[Dict[str, List[float]], str],
|
|
13
|
-
ctx = None
|
|
14
|
-
) -> Dict[str, List[float]]:
|
|
15
|
-
"""
|
|
16
|
-
智能加载数据:如果是字符串则作为文件路径加载,否则直接返回
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
data: 数据字典或CSV文件路径
|
|
20
|
-
ctx: MCP上下文对象(可选,用于日志)
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
数据字典
|
|
24
|
-
|
|
25
|
-
Raises:
|
|
26
|
-
ValueError: 文件不存在或读取失败
|
|
27
|
-
"""
|
|
28
|
-
# 如果已经是字典,直接返回
|
|
29
|
-
if isinstance(data, dict):
|
|
30
|
-
return data
|
|
31
|
-
|
|
32
|
-
# 如果是字符串,作为文件路径处理
|
|
33
|
-
if isinstance(data, str):
|
|
34
|
-
if ctx:
|
|
35
|
-
await ctx.info(f"📁 检测到文件路径,正在加载: {data}")
|
|
36
|
-
|
|
37
|
-
try:
|
|
38
|
-
# 检查文件是否存在
|
|
39
|
-
path = Path(data)
|
|
40
|
-
if not path.exists():
|
|
41
|
-
raise ValueError(f"文件不存在: {data}")
|
|
42
|
-
|
|
43
|
-
# 读取CSV文件
|
|
44
|
-
df = pd.read_csv(path)
|
|
45
|
-
|
|
46
|
-
# 转换为字典格式
|
|
47
|
-
result = {col: df[col].tolist() for col in df.columns}
|
|
48
|
-
|
|
49
|
-
if ctx:
|
|
50
|
-
await ctx.info(f"✅ CSV文件加载成功:{len(df.columns)}个变量,{len(df)}个观测")
|
|
51
|
-
|
|
52
|
-
return result
|
|
53
|
-
|
|
54
|
-
except FileNotFoundError:
|
|
55
|
-
raise ValueError(f"文件不存在: {data}")
|
|
56
|
-
except Exception as e:
|
|
57
|
-
raise ValueError(f"CSV文件读取失败: {str(e)}")
|
|
58
|
-
|
|
59
|
-
# 其他类型报错
|
|
60
|
-
|
|
61
|
-
async def load_single_var_if_path(
|
|
62
|
-
data: Union[List[float], str],
|
|
63
|
-
ctx = None,
|
|
64
|
-
column_name: str = None
|
|
65
|
-
) -> List[float]:
|
|
66
|
-
"""
|
|
67
|
-
智能加载单变量数据:如果是字符串则作为文件路径加载,否则直接返回
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
data: 数据列表或CSV文件路径
|
|
71
|
-
ctx: MCP上下文对象(可选,用于日志)
|
|
72
|
-
column_name: CSV文件中要读取的列名(可选,默认读取第一列)
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
数据列表
|
|
76
|
-
|
|
77
|
-
Raises:
|
|
78
|
-
ValueError: 文件不存在或读取失败
|
|
79
|
-
"""
|
|
80
|
-
# 如果已经是列表,直接返回
|
|
81
|
-
if isinstance(data, list):
|
|
82
|
-
return data
|
|
83
|
-
|
|
84
|
-
# 如果是字符串,作为文件路径处理
|
|
85
|
-
if isinstance(data, str):
|
|
86
|
-
if ctx:
|
|
87
|
-
await ctx.info(f"📁 检测到文件路径,正在加载: {data}")
|
|
88
|
-
|
|
89
|
-
try:
|
|
90
|
-
# 检查文件是否存在
|
|
91
|
-
path = Path(data)
|
|
92
|
-
if not path.exists():
|
|
93
|
-
raise ValueError(f"文件不存在: {data}")
|
|
94
|
-
|
|
95
|
-
# 读取CSV文件
|
|
96
|
-
df = pd.read_csv(path)
|
|
97
|
-
|
|
98
|
-
# 确定要读取的列
|
|
99
|
-
if column_name:
|
|
100
|
-
if column_name not in df.columns:
|
|
101
|
-
raise ValueError(f"列'{column_name}'不存在于CSV文件中。可用列: {list(df.columns)}")
|
|
102
|
-
result = df[column_name].tolist()
|
|
103
|
-
else:
|
|
104
|
-
# 默认读取第一列
|
|
105
|
-
result = df.iloc[:, 0].tolist()
|
|
106
|
-
if ctx:
|
|
107
|
-
await ctx.info(f"未指定列名,使用第一列: {df.columns[0]}")
|
|
108
|
-
|
|
109
|
-
if ctx:
|
|
110
|
-
await ctx.info(f"✅ CSV文件加载成功:{len(result)}个观测")
|
|
111
|
-
|
|
112
|
-
return result
|
|
113
|
-
|
|
114
|
-
except FileNotFoundError:
|
|
115
|
-
raise ValueError(f"文件不存在: {data}")
|
|
116
|
-
except Exception as e:
|
|
117
|
-
raise ValueError(f"CSV文件读取失败: {str(e)}")
|
|
118
|
-
|
|
119
|
-
# 其他类型报错
|
|
120
|
-
raise TypeError(f"不支持的数据类型: {type(data)},期望List或str")
|
|
121
|
-
async def load_x_data_if_path(
|
|
122
|
-
data: Union[List[List[float]], str],
|
|
123
|
-
ctx = None
|
|
124
|
-
) -> List[List[float]]:
|
|
125
|
-
"""
|
|
126
|
-
智能加载自变量数据:如果是字符串则作为文件路径加载,否则直接返回
|
|
127
|
-
|
|
128
|
-
Args:
|
|
129
|
-
data: 自变量数据(二维列表)或CSV文件路径
|
|
130
|
-
ctx: MCP上下文对象(可选,用于日志)
|
|
131
|
-
|
|
132
|
-
Returns:
|
|
133
|
-
自变量数据(二维列表)
|
|
134
|
-
|
|
135
|
-
Raises:
|
|
136
|
-
ValueError: 文件不存在或读取失败
|
|
137
|
-
"""
|
|
138
|
-
# 如果已经是二维列表,直接返回
|
|
139
|
-
if isinstance(data, list) and all(isinstance(item, list) for item in data):
|
|
140
|
-
return data
|
|
141
|
-
|
|
142
|
-
# 如果是字符串,作为文件路径处理
|
|
143
|
-
if isinstance(data, str):
|
|
144
|
-
if ctx:
|
|
145
|
-
await ctx.info(f"📁 检测到自变量文件路径,正在加载: {data}")
|
|
146
|
-
|
|
147
|
-
try:
|
|
148
|
-
# 检查文件是否存在
|
|
149
|
-
path = Path(data)
|
|
150
|
-
if not path.exists():
|
|
151
|
-
raise ValueError(f"文件不存在: {data}")
|
|
152
|
-
|
|
153
|
-
# 读取CSV文件
|
|
154
|
-
df = pd.read_csv(path)
|
|
155
|
-
|
|
156
|
-
# 转换为二维列表格式
|
|
157
|
-
result = df.values.tolist()
|
|
158
|
-
|
|
159
|
-
if ctx:
|
|
160
|
-
await ctx.info(f"✅ 自变量CSV文件加载成功:{len(result)}个观测,{len(result[0]) if result else 0}个自变量")
|
|
161
|
-
|
|
162
|
-
return result
|
|
163
|
-
|
|
164
|
-
except FileNotFoundError:
|
|
165
|
-
raise ValueError(f"文件不存在: {data}")
|
|
166
|
-
except Exception as e:
|
|
167
|
-
raise ValueError(f"自变量CSV文件读取失败: {str(e)}")
|
|
168
|
-
|
|
169
|
-
# 其他类型报错
|
|
170
|
-
raise TypeError(f"不支持的数据类型: {type(data)},期望List[List[float]]或str")
|
|
171
|
-
raise TypeError(f"不支持的数据类型: {type(data)},期望Dict或str")
|