Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -41,6 +41,47 @@ def normalize_cik(cik):
|
|
| 41 |
# 填充前导 0 至 10 位
|
| 42 |
return cik_str.zfill(10) if cik_str else None
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
# MCP 工具定义
|
| 45 |
def create_mcp_tools():
|
| 46 |
"""创建 MCP 工具列表"""
|
|
@@ -121,16 +162,8 @@ def query_financial_data(company_name, query_type):
|
|
| 121 |
|
| 122 |
try:
|
| 123 |
result = search_resp.json()
|
| 124 |
-
# MCP
|
| 125 |
-
|
| 126 |
-
content = result.get("content", [])
|
| 127 |
-
if content and len(content) > 0:
|
| 128 |
-
text_content = content[0].get("text", "{}")
|
| 129 |
-
company = json.loads(text_content) if isinstance(text_content, str) else text_content
|
| 130 |
-
else:
|
| 131 |
-
company = {}
|
| 132 |
-
else:
|
| 133 |
-
company = result
|
| 134 |
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
| 135 |
return f"❌ JSON Parse Error: {str(e)}\n\nResponse: {search_resp.text[:500]}"
|
| 136 |
|
|
@@ -172,17 +205,9 @@ def query_financial_data(company_name, query_type):
|
|
| 172 |
|
| 173 |
try:
|
| 174 |
data_result = data_resp.json()
|
| 175 |
-
# MCP
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
if content and len(content) > 0:
|
| 179 |
-
text_content = content[0].get("text", "{}")
|
| 180 |
-
data = json.loads(text_content) if isinstance(text_content, str) else text_content
|
| 181 |
-
else:
|
| 182 |
-
data = {}
|
| 183 |
-
else:
|
| 184 |
-
data = data_result
|
| 185 |
-
except (ValueError, KeyError) as e:
|
| 186 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{data_resp.text[:500]}"
|
| 187 |
|
| 188 |
if isinstance(data, dict) and data.get("error"):
|
|
@@ -226,17 +251,9 @@ def query_financial_data(company_name, query_type):
|
|
| 226 |
|
| 227 |
try:
|
| 228 |
metrics_result = metrics_resp.json()
|
| 229 |
-
# MCP
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
if content and len(content) > 0:
|
| 233 |
-
text_content = content[0].get("text", "{}")
|
| 234 |
-
metrics = json.loads(text_content) if isinstance(text_content, str) else text_content
|
| 235 |
-
else:
|
| 236 |
-
metrics = {}
|
| 237 |
-
else:
|
| 238 |
-
metrics = metrics_result
|
| 239 |
-
except (ValueError, KeyError) as e:
|
| 240 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{metrics_resp.text[:500]}"
|
| 241 |
|
| 242 |
if isinstance(metrics, dict) and metrics.get("error"):
|
|
@@ -316,17 +333,9 @@ def query_financial_data(company_name, query_type):
|
|
| 316 |
|
| 317 |
try:
|
| 318 |
metrics_result = metrics_resp.json()
|
| 319 |
-
# MCP
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
if content and len(content) > 0:
|
| 323 |
-
text_content = content[0].get("text", "{}")
|
| 324 |
-
metrics = json.loads(text_content) if isinstance(text_content, str) else text_content
|
| 325 |
-
else:
|
| 326 |
-
metrics = {}
|
| 327 |
-
else:
|
| 328 |
-
metrics = metrics_result
|
| 329 |
-
except (ValueError, KeyError) as e:
|
| 330 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{metrics_resp.text[:500]}"
|
| 331 |
|
| 332 |
if isinstance(metrics, dict) and metrics.get("error"):
|
|
@@ -406,17 +415,9 @@ def query_financial_data(company_name, query_type):
|
|
| 406 |
|
| 407 |
try:
|
| 408 |
filings_result = filings_resp.json()
|
| 409 |
-
# MCP
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
if content and len(content) > 0:
|
| 413 |
-
text_content = content[0].get("text", "{}")
|
| 414 |
-
filings_data = json.loads(text_content) if isinstance(text_content, str) else text_content
|
| 415 |
-
else:
|
| 416 |
-
filings_data = {}
|
| 417 |
-
else:
|
| 418 |
-
filings_data = filings_result
|
| 419 |
-
except (ValueError, KeyError) as e:
|
| 420 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{filings_resp.text[:500]}"
|
| 421 |
|
| 422 |
if isinstance(filings_data, dict) and filings_data.get("error"):
|
|
|
|
| 41 |
# 填充前导 0 至 10 位
|
| 42 |
return cik_str.zfill(10) if cik_str else None
|
| 43 |
|
| 44 |
+
def parse_mcp_response(response_data):
|
| 45 |
+
"""
|
| 46 |
+
解析 MCP 协议响应数据
|
| 47 |
+
支持格式:
|
| 48 |
+
1. {"result": {"content": [{"type": "text", "text": "..."}]}}
|
| 49 |
+
2. {"content": [{"type": "text", "text": "..."}]}
|
| 50 |
+
3. 直接的 JSON 数据
|
| 51 |
+
"""
|
| 52 |
+
if not isinstance(response_data, dict):
|
| 53 |
+
return response_data
|
| 54 |
+
|
| 55 |
+
# 格式 1: {"result": {"content": [...]}}
|
| 56 |
+
if "result" in response_data and "content" in response_data["result"]:
|
| 57 |
+
content = response_data["result"]["content"]
|
| 58 |
+
if content and len(content) > 0:
|
| 59 |
+
text_content = content[0].get("text", "{}")
|
| 60 |
+
# 移除 emoji 前缀(如 "🔍 Search Result:\n\n")
|
| 61 |
+
if ":\n\n" in text_content:
|
| 62 |
+
text_content = text_content.split(":\n\n", 1)[1]
|
| 63 |
+
try:
|
| 64 |
+
return json.loads(text_content)
|
| 65 |
+
except json.JSONDecodeError:
|
| 66 |
+
return text_content
|
| 67 |
+
return {}
|
| 68 |
+
|
| 69 |
+
# 格式 2: {"content": [...]}
|
| 70 |
+
elif "content" in response_data:
|
| 71 |
+
content = response_data.get("content", [])
|
| 72 |
+
if content and len(content) > 0:
|
| 73 |
+
text_content = content[0].get("text", "{}")
|
| 74 |
+
if ":\n\n" in text_content:
|
| 75 |
+
text_content = text_content.split(":\n\n", 1)[1]
|
| 76 |
+
try:
|
| 77 |
+
return json.loads(text_content)
|
| 78 |
+
except json.JSONDecodeError:
|
| 79 |
+
return text_content
|
| 80 |
+
return {}
|
| 81 |
+
|
| 82 |
+
# 格式 3: 直接返回
|
| 83 |
+
return response_data
|
| 84 |
+
|
| 85 |
# MCP 工具定义
|
| 86 |
def create_mcp_tools():
|
| 87 |
"""创建 MCP 工具列表"""
|
|
|
|
| 162 |
|
| 163 |
try:
|
| 164 |
result = search_resp.json()
|
| 165 |
+
# 使用统一的 MCP 响应解析函数
|
| 166 |
+
company = parse_mcp_response(result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
| 168 |
return f"❌ JSON Parse Error: {str(e)}\n\nResponse: {search_resp.text[:500]}"
|
| 169 |
|
|
|
|
| 205 |
|
| 206 |
try:
|
| 207 |
data_result = data_resp.json()
|
| 208 |
+
# 使用统一的 MCP 响应解析函数
|
| 209 |
+
data = parse_mcp_response(data_result)
|
| 210 |
+
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{data_resp.text[:500]}"
|
| 212 |
|
| 213 |
if isinstance(data, dict) and data.get("error"):
|
|
|
|
| 251 |
|
| 252 |
try:
|
| 253 |
metrics_result = metrics_resp.json()
|
| 254 |
+
# 使用统一的 MCP 响应解析函数
|
| 255 |
+
metrics = parse_mcp_response(metrics_result)
|
| 256 |
+
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{metrics_resp.text[:500]}"
|
| 258 |
|
| 259 |
if isinstance(metrics, dict) and metrics.get("error"):
|
|
|
|
| 333 |
|
| 334 |
try:
|
| 335 |
metrics_result = metrics_resp.json()
|
| 336 |
+
# 使用统一的 MCP 响应解析函数
|
| 337 |
+
metrics = parse_mcp_response(metrics_result)
|
| 338 |
+
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{metrics_resp.text[:500]}"
|
| 340 |
|
| 341 |
if isinstance(metrics, dict) and metrics.get("error"):
|
|
|
|
| 415 |
|
| 416 |
try:
|
| 417 |
filings_result = filings_resp.json()
|
| 418 |
+
# 使用统一的 MCP 响应解析函数
|
| 419 |
+
filings_data = parse_mcp_response(filings_result)
|
| 420 |
+
except (ValueError, KeyError, json.JSONDecodeError) as e:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
return result + f"❌ JSON Parse Error: {str(e)}\n\n{filings_resp.text[:500]}"
|
| 422 |
|
| 423 |
if isinstance(filings_data, dict) and filings_data.get("error"):
|