JC321 commited on
Commit
be3a0ca
·
verified ·
1 Parent(s): d3bf78b

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +1 -1
  2. app_simplified.py +236 -0
app.py CHANGED
@@ -25,7 +25,7 @@ MCP_TOOLS = [
25
 
26
  # ========== MCP 服务配置 ==========
27
  MCP_SERVICES = {
28
- "financial": {"url": "https://jc321-easyreportdatemcp.hf.space/mcp", "type": "fastmcp"},
29
  "market": {"url": "https://jc321-marketandstockmcp.hf.space", "type": "gradio"}
30
  }
31
 
 
25
 
26
  # ========== MCP 服务配置 ==========
27
  MCP_SERVICES = {
28
+ "financial": {"url": "https://huggingface.co/spaces/JC321/EasyReportDataMCP", "type": "fastmcp"},
29
  "market": {"url": "https://jc321-marketandstockmcp.hf.space", "type": "gradio"}
30
  }
31
 
app_simplified.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ import os
5
+ from huggingface_hub import InferenceClient
6
+
7
+ # ========== 配置两个 MCP 服务 ==========
8
+ MCP_SERVICES = {
9
+ "financial": {
10
+ "name": "SEC Financial Reports",
11
+ "url": "https://huggingface.co/spaces/JC321/EasyReportDataMCP",
12
+ "tools": [
13
+ {
14
+ "type": "function",
15
+ "function": {
16
+ "name": "advanced_search_company",
17
+ "description": "Search for US listed companies by name or ticker to get CIK and basic info",
18
+ "parameters": {
19
+ "type": "object",
20
+ "properties": {
21
+ "company_input": {"type": "string", "description": "Company name or ticker (e.g., 'Apple', 'AAPL')"}
22
+ },
23
+ "required": ["company_input"]
24
+ }
25
+ }
26
+ },
27
+ {
28
+ "type": "function",
29
+ "function": {
30
+ "name": "get_latest_financial_data",
31
+ "description": "Get latest financial data (revenue, net income, EPS, etc.) for a company",
32
+ "parameters": {
33
+ "type": "object",
34
+ "properties": {
35
+ "cik": {"type": "string", "description": "10-digit CIK number"}
36
+ },
37
+ "required": ["cik"]
38
+ }
39
+ }
40
+ },
41
+ {
42
+ "type": "function",
43
+ "function": {
44
+ "name": "extract_financial_metrics",
45
+ "description": "Get multi-year financial trends (3 or 5 years)",
46
+ "parameters": {
47
+ "type": "object",
48
+ "properties": {
49
+ "cik": {"type": "string", "description": "10-digit CIK number"},
50
+ "years": {"type": "integer", "enum": [3, 5]}
51
+ },
52
+ "required": ["cik", "years"]
53
+ }
54
+ }
55
+ }
56
+ ]
57
+ },
58
+ "market": {
59
+ "name": "Market & Stock Data",
60
+ "url": "https://jc321-marketandstockmcp.hf.space/mcp",
61
+ "tools": [] # 需要获取实际工具列表
62
+ }
63
+ }
64
+
65
+ # 合并所有工具
66
+ ALL_TOOLS = []
67
+ TOOL_ROUTING = {} # tool_name -> mcp_url 的映射
68
+
69
+ for service_key, service in MCP_SERVICES.items():
70
+ for tool in service["tools"]:
71
+ tool_name = tool["function"]["name"]
72
+ ALL_TOOLS.append(tool)
73
+ TOOL_ROUTING[tool_name] = service["url"]
74
+
75
+ # ========== 初始化 LLM 客户端 ==========
76
+ hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
77
+ client = InferenceClient(api_key=hf_token) if hf_token else InferenceClient()
78
+ print(f"✅ LLM client initialized (Qwen/Qwen2.5-72B-Instruct:novita)")
79
+
80
+ # ========== 系统提示词 ==========
81
+ SYSTEM_PROMPT = """You are an intelligent financial and market analysis assistant with access to real-time data.
82
+
83
+ You have access to two powerful data sources:
84
+ 1. **SEC Financial Reports** - Get official financial data for US-listed companies (revenue, earnings, cash flow, etc.)
85
+ 2. **Market & Stock Data** - Get real-time market data, stock prices, and market analysis
86
+
87
+ When users ask about:
88
+ - Company financials, earnings, revenue → Use SEC Financial Reports tools
89
+ - Stock prices, market trends, trading data → Use Market & Stock Data tools
90
+
91
+ Be conversational, insightful, and provide data-driven analysis. Automatically fetch data when needed."""
92
+
93
+ # ========== 核心函数:调用 MCP 工具 ==========
94
+ def call_mcp_tool(tool_name, arguments):
95
+ """调用 MCP 工具"""
96
+ mcp_url = TOOL_ROUTING.get(tool_name)
97
+ if not mcp_url:
98
+ return {"error": f"Unknown tool: {tool_name}"}
99
+
100
+ try:
101
+ response = requests.post(
102
+ mcp_url,
103
+ json={
104
+ "jsonrpc": "2.0",
105
+ "method": "tools/call",
106
+ "params": {"name": tool_name, "arguments": arguments},
107
+ "id": 1
108
+ },
109
+ headers={"Content-Type": "application/json"},
110
+ timeout=60
111
+ )
112
+
113
+ if response.status_code == 200:
114
+ return response.json()
115
+ else:
116
+ return {"error": f"HTTP {response.status_code}", "detail": response.text[:200]}
117
+ except Exception as e:
118
+ return {"error": str(e)}
119
+
120
+ # ========== 核心函数:AI 助手 ==========
121
+ def chatbot_response(message, history):
122
+ """AI 助手主函数"""
123
+ try:
124
+ # 构建消息历史
125
+ messages = [{"role": "system", "content": SYSTEM_PROMPT}]
126
+
127
+ # 添加对话历史(最近5轮)
128
+ if history:
129
+ for item in history[-5:]:
130
+ if isinstance(item, dict):
131
+ messages.append(item)
132
+ elif isinstance(item, (list, tuple)) and len(item) == 2:
133
+ user_msg, assistant_msg = item
134
+ messages.append({"role": "user", "content": user_msg})
135
+ messages.append({"role": "assistant", "content": assistant_msg})
136
+
137
+ messages.append({"role": "user", "content": message})
138
+
139
+ # LLM 调用循环(支持多轮工具调用)
140
+ tool_calls_log = []
141
+ max_iterations = 5
142
+
143
+ for iteration in range(max_iterations):
144
+ # 调用 LLM
145
+ response = client.chat_completion(
146
+ messages=messages,
147
+ model="Qwen/Qwen2.5-72B-Instruct:novita",
148
+ tools=ALL_TOOLS,
149
+ max_tokens=3000,
150
+ temperature=0.7,
151
+ tool_choice="auto"
152
+ )
153
+
154
+ choice = response.choices[0]
155
+
156
+ # 检查是否有工具调用
157
+ if choice.message.tool_calls:
158
+ messages.append(choice.message)
159
+
160
+ for tool_call in choice.message.tool_calls:
161
+ tool_name = tool_call.function.name
162
+ tool_args = json.loads(tool_call.function.arguments)
163
+
164
+ # 记录工具调用
165
+ tool_calls_log.append({"name": tool_name, "arguments": tool_args})
166
+
167
+ # 调用 MCP 工具
168
+ tool_result = call_mcp_tool(tool_name, tool_args)
169
+
170
+ # 添加工具结果到消息
171
+ messages.append({
172
+ "role": "tool",
173
+ "name": tool_name,
174
+ "content": json.dumps(tool_result),
175
+ "tool_call_id": tool_call.id
176
+ })
177
+
178
+ continue # 继续下一轮
179
+ else:
180
+ # 无工具调用,返回最终答案
181
+ response_text = choice.message.content
182
+ break
183
+
184
+ # 构建最终响应
185
+ final_response = ""
186
+
187
+ # 显示模型信息
188
+ final_response += f"<div style='padding: 8px; background: #e3f2fd; border-left: 3px solid #2196f3; margin-bottom: 10px; font-size: 0.9em;'>🤖 <strong>Model:</strong> Qwen/Qwen2.5-72B-Instruct:novita</div>\n\n"
189
+
190
+ # 显示工具调用日志
191
+ if tool_calls_log:
192
+ final_response += "**🛠️ MCP Tools Used:**\n\n"
193
+ for i, tool_call in enumerate(tool_calls_log, 1):
194
+ final_response += f"{i}. `{tool_call['name']}` - {json.dumps(tool_call['arguments'])}\n"
195
+ final_response += "\n---\n\n"
196
+
197
+ final_response += response_text
198
+
199
+ return final_response
200
+
201
+ except Exception as e:
202
+ return f"❌ Error: {str(e)}"
203
+
204
+ # ========== Gradio 界面 ==========
205
+ with gr.Blocks(title="Financial & Market AI Assistant") as demo:
206
+ gr.Markdown("# 🤖 Financial & Market AI Assistant")
207
+
208
+ gr.Markdown("""
209
+ <div style='padding: 15px; background: #d4edda; border-left: 4px solid #28a745; margin: 10px 0; border-radius: 4px;'>
210
+ <strong>✅ AI Powered by:</strong> Qwen/Qwen2.5-72B-Instruct:novita
211
+ <br>
212
+ <strong>📊 Data Sources:</strong> SEC Financial Reports + Market & Stock Data
213
+ </div>
214
+ """)
215
+
216
+ chat = gr.ChatInterface(
217
+ fn=chatbot_response,
218
+ examples=[
219
+ "What's Apple's latest revenue and profit?",
220
+ "Show me NVIDIA's 3-year financial trends",
221
+ "How is Tesla's stock performing today?",
222
+ "Compare Microsoft's earnings with its stock price",
223
+ "Analyze Amazon's cash flow and market cap",
224
+ ],
225
+ title="💬 AI Assistant",
226
+ description="Ask me about company financials, stock prices, or market trends. I'll automatically fetch the data you need!"
227
+ )
228
+
229
+ # 启动应用
230
+ if __name__ == "__main__":
231
+ demo.launch(
232
+ server_name="0.0.0.0",
233
+ server_port=7860,
234
+ show_error=True,
235
+ ssr_mode=False
236
+ )