JC321 commited on
Commit
a779edc
·
verified ·
1 Parent(s): 2d33a19

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -19
app.py CHANGED
@@ -13,13 +13,19 @@ HEADERS = {
13
  }
14
 
15
  # 格式化数值显示
16
- def format_value(value, is_money=True):
17
- """格式化数值:0显示为N/A,其他显示为带单位的格式"""
 
 
 
18
  if value is None or value == 0:
19
  return "N/A"
20
- if is_money:
 
21
  return f"${value:.2f}B"
22
- else:
 
 
23
  return f"{value:.2f}"
24
 
25
  # MCP 工具定义
@@ -100,11 +106,11 @@ def query_financial_data(company_name, query_type):
100
  return f"❌ JSON Parse Error: {str(e)}\n\nResponse: {search_resp.text[:500]}"
101
 
102
  if isinstance(company, dict) and company.get("error"):
103
- return f"❌ 错误: {company['error']}"
104
 
105
  result = f"# {company.get('name', 'Unknown')}\n\n"
106
- result += f"**股票代码**: {company.get('tickers', ['N/A'])[0] if company.get('tickers') else 'N/A'}\n"
107
- result += f"**行业**: {company.get('sic_description', 'N/A')}\n\n---\n\n"
108
 
109
  cik = company.get('cik')
110
 
@@ -139,7 +145,7 @@ def query_financial_data(company_name, query_type):
139
 
140
  result += f"- **Total Revenue**: {format_value(total_revenue)}\n"
141
  result += f"- **Net Income**: {format_value(net_income)}\n"
142
- result += f"- **Earnings Per Share**: {format_value(eps, False)}\n"
143
  result += f"- **Operating Expenses**: {format_value(opex)}\n"
144
  result += f"- **Operating Cash Flow**: {format_value(ocf)}\n"
145
  # 使用后端返回的 source_url
@@ -182,16 +188,17 @@ def query_financial_data(company_name, query_type):
182
 
183
  # 按期间降序排序,确保显示最近的3年数据
184
  # 使用更智能的排序:先按年份,再按是否是季度
 
185
  def sort_key(x):
186
  period = x.get('period', '0000')
187
  # 提取年份(前4位)
188
  year = period[:4] if len(period) >= 4 else '0000'
189
- # 如果有Q,提取季度号,否则设为5(让FY排在Q后面)
190
  if 'Q' in period:
191
  quarter = period[period.index('Q')+1] if period.index('Q')+1 < len(period) else '0'
192
- return (year, 0, 5 - int(quarter)) # Q4, Q3, Q2, Q1
193
  else:
194
- return (year, 1, 0) # FY 排在同年的所有Q之后
195
 
196
  unique_data = sorted(unique_data, key=sort_key, reverse=True)
197
 
@@ -218,7 +225,7 @@ def query_financial_data(company_name, query_type):
218
 
219
  source_link = create_source_link(source_form, source_url)
220
 
221
- result += f"| {display_period} | {format_value(rev)} | {format_value(inc)} | {format_value(eps_val, False)} | {format_value(opex)} | {format_value(ocf)} | {source_link} |\n"
222
 
223
  elif internal_query_type == "5年趋势":
224
  metrics_resp = requests.post(
@@ -253,16 +260,17 @@ def query_financial_data(company_name, query_type):
253
 
254
  # 按期间降序排序,确保显示最近的5年数据
255
  # 使用更智能的排序:先按年份,再按是否是季度
 
256
  def sort_key(x):
257
  period = x.get('period', '0000')
258
  # 提取年份(前4位)
259
  year = period[:4] if len(period) >= 4 else '0000'
260
- # 如果有Q,提取季度号,否则设为5(让FY排在Q后面)
261
  if 'Q' in period:
262
  quarter = period[period.index('Q')+1] if period.index('Q')+1 < len(period) else '0'
263
- return (year, 0, 5 - int(quarter)) # Q4, Q3, Q2, Q1
264
  else:
265
- return (year, 1, 0) # FY 排在同年的所有Q之后
266
 
267
  unique_data = sorted(unique_data, key=sort_key, reverse=True)
268
 
@@ -290,7 +298,7 @@ def query_financial_data(company_name, query_type):
290
 
291
  source_link = create_source_link(source_form, source_url)
292
 
293
- result += f"| {display_period} | {format_value(rev)} | {format_value(inc)} | {format_value(eps_val, False)} | {format_value(opex)} | {format_value(ocf)} | {source_link} |\n"
294
 
295
  elif internal_query_type == "公司报表列表":
296
  # 查询公司所有报表
@@ -388,6 +396,23 @@ def chatbot_response(message, history):
388
  except Exception as e:
389
  return f"Sorry, I encountered an error: {str(e)}. Please try asking about financial data for specific companies like Apple, Microsoft, NVIDIA, Tesla, etc."
390
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  # 创建 Gradio 界面
392
  with gr.Blocks(title="SEC Financial Data Query Assistant") as demo:
393
  gr.Markdown("# 🤖 SEC Financial Data Query Assistant")
@@ -412,6 +437,7 @@ with gr.Blocks(title="SEC Financial Data Query Assistant") as demo:
412
 
413
  with gr.Tab("Direct Query"):
414
  gr.Markdown("## 🔍 Direct Financial Data Query")
 
415
 
416
  with gr.Row():
417
  company_input = gr.Textbox(
@@ -426,7 +452,12 @@ with gr.Blocks(title="SEC Financial Data Query Assistant") as demo:
426
  scale=1
427
  )
428
 
429
- submit_btn = gr.Button("🔍 Query", variant="primary", size="lg")
 
 
 
 
 
430
  output = gr.Markdown(label="Query Results")
431
 
432
  # 示例
@@ -445,9 +476,10 @@ with gr.Blocks(title="SEC Financial Data Query Assistant") as demo:
445
  )
446
 
447
  submit_btn.click(
448
- fn=query_financial_data,
449
  inputs=[company_input, query_type],
450
- outputs=output
 
451
  )
452
 
453
  gr.Markdown("---")
 
13
  }
14
 
15
  # 格式化数值显示
16
+ def format_value(value, value_type="money"):
17
+ """
18
+ 格式化数值:0显示为N/A,其他显示为带单位的格式
19
+ value_type: "money" (金额), "eps" (每股收益), "number" (普通数字)
20
+ """
21
  if value is None or value == 0:
22
  return "N/A"
23
+
24
+ if value_type == "money":
25
  return f"${value:.2f}B"
26
+ elif value_type == "eps":
27
+ return f"${value:.2f}"
28
+ else: # number
29
  return f"{value:.2f}"
30
 
31
  # MCP 工具定义
 
106
  return f"❌ JSON Parse Error: {str(e)}\n\nResponse: {search_resp.text[:500]}"
107
 
108
  if isinstance(company, dict) and company.get("error"):
109
+ return f"❌ Error: {company['error']}"
110
 
111
  result = f"# {company.get('name', 'Unknown')}\n\n"
112
+ result += f"**Stock Symbol**: {company.get('tickers', ['N/A'])[0] if company.get('tickers') else 'N/A'}\n"
113
+ result += f"**Industry**: {company.get('sic_description', 'N/A')}\n\n---\n\n"
114
 
115
  cik = company.get('cik')
116
 
 
145
 
146
  result += f"- **Total Revenue**: {format_value(total_revenue)}\n"
147
  result += f"- **Net Income**: {format_value(net_income)}\n"
148
+ result += f"- **Earnings Per Share**: {format_value(eps, 'eps')}\n"
149
  result += f"- **Operating Expenses**: {format_value(opex)}\n"
150
  result += f"- **Operating Cash Flow**: {format_value(ocf)}\n"
151
  # 使用后端返回的 source_url
 
188
 
189
  # 按期间降序排序,确保显示最近的3年数据
190
  # 使用更智能的排序:先按年份,再按是否是季度
191
+ # 正确顺序:FY2024 → 2024Q3 → 2024Q2 → 2024Q1 → FY2023
192
  def sort_key(x):
193
  period = x.get('period', '0000')
194
  # 提取年份(前4位)
195
  year = period[:4] if len(period) >= 4 else '0000'
196
+ # 如果有Q,提取季度号
197
  if 'Q' in period:
198
  quarter = period[period.index('Q')+1] if period.index('Q')+1 < len(period) else '0'
199
+ return (year, 1, 4 - int(quarter)) # Q在FY后面:Q3, Q2, Q1 (4-3=1, 4-2=2, 4-1=3)
200
  else:
201
+ return (year, 0, 0) # FY 排在同年的所有Q之前
202
 
203
  unique_data = sorted(unique_data, key=sort_key, reverse=True)
204
 
 
225
 
226
  source_link = create_source_link(source_form, source_url)
227
 
228
+ result += f"| {display_period} | {format_value(rev)} | {format_value(inc)} | {format_value(eps_val, 'eps')} | {format_value(opex)} | {format_value(ocf)} | {source_link} |\n"
229
 
230
  elif internal_query_type == "5年趋势":
231
  metrics_resp = requests.post(
 
260
 
261
  # 按期间降序排序,确保显示最近的5年数据
262
  # 使用更智能的排序:先按年份,再按是否是季度
263
+ # 正确顺序:FY2024 → 2024Q3 → 2024Q2 → 2024Q1 → FY2023
264
  def sort_key(x):
265
  period = x.get('period', '0000')
266
  # 提取年份(前4位)
267
  year = period[:4] if len(period) >= 4 else '0000'
268
+ # 如果有Q,提取季度号
269
  if 'Q' in period:
270
  quarter = period[period.index('Q')+1] if period.index('Q')+1 < len(period) else '0'
271
+ return (year, 1, 4 - int(quarter)) # Q在FY后面:Q3, Q2, Q1 (4-3=1, 4-2=2, 4-1=3)
272
  else:
273
+ return (year, 0, 0) # FY 排在同年的所有Q之前
274
 
275
  unique_data = sorted(unique_data, key=sort_key, reverse=True)
276
 
 
298
 
299
  source_link = create_source_link(source_form, source_url)
300
 
301
+ result += f"| {display_period} | {format_value(rev)} | {format_value(inc)} | {format_value(eps_val, 'eps')} | {format_value(opex)} | {format_value(ocf)} | {source_link} |\n"
302
 
303
  elif internal_query_type == "公司报表列表":
304
  # 查询公司所有报表
 
396
  except Exception as e:
397
  return f"Sorry, I encountered an error: {str(e)}. Please try asking about financial data for specific companies like Apple, Microsoft, NVIDIA, Tesla, etc."
398
 
399
+ # 包装函数,显示加载状态
400
+ def query_with_status(company, query_type):
401
+ """Query with loading status indicator"""
402
+ try:
403
+ # 返回加载状态和结果
404
+ yield "<div style='padding: 10px; background: #e3f2fd; border-left: 4px solid #2196f3; margin: 10px 0;'>🔄 <strong>Loading...</strong> Querying SEC EDGAR data for <strong>{}</strong>...</div>".format(company), ""
405
+
406
+ # 执行实际查询
407
+ result = query_financial_data(company, query_type)
408
+
409
+ # 返回成功状态和结果
410
+ yield "<div style='padding: 10px; background: #e8f5e9; border-left: 4px solid #4caf50; margin: 10px 0;'>✅ <strong>Query completed successfully!</strong></div>", result
411
+
412
+ except Exception as e:
413
+ # 返回错误状态
414
+ yield "<div style='padding: 10px; background: #ffebee; border-left: 4px solid #f44336; margin: 10px 0;'>❌ <strong>Error:</strong> {}</div>".format(str(e)), ""
415
+
416
  # 创建 Gradio 界面
417
  with gr.Blocks(title="SEC Financial Data Query Assistant") as demo:
418
  gr.Markdown("# 🤖 SEC Financial Data Query Assistant")
 
437
 
438
  with gr.Tab("Direct Query"):
439
  gr.Markdown("## 🔍 Direct Financial Data Query")
440
+ gr.Markdown("Select a company and query type to retrieve financial information.")
441
 
442
  with gr.Row():
443
  company_input = gr.Textbox(
 
452
  scale=1
453
  )
454
 
455
+ submit_btn = gr.Button("🔍 Query Financial Data", variant="primary", size="lg")
456
+
457
+ # 添加加载状态指示器
458
+ with gr.Row():
459
+ status_text = gr.Markdown("")
460
+
461
  output = gr.Markdown(label="Query Results")
462
 
463
  # 示例
 
476
  )
477
 
478
  submit_btn.click(
479
+ fn=query_with_status,
480
  inputs=[company_input, query_type],
481
+ outputs=[status_text, output],
482
+ show_progress="full" # 显示完整的进度条
483
  )
484
 
485
  gr.Markdown("---")