Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -174,11 +174,13 @@ def chatbot_response(message, history):
|
|
| 174 |
for tool_call in choice.message.tool_calls:
|
| 175 |
tool_name = tool_call.function.name
|
| 176 |
tool_args = json.loads(tool_call.function.arguments)
|
| 177 |
-
tool_calls_log.append({"name": tool_name, "arguments": tool_args})
|
| 178 |
|
| 179 |
# 调用 MCP 工具
|
| 180 |
tool_result = call_mcp_tool(tool_name, tool_args)
|
| 181 |
|
|
|
|
|
|
|
|
|
|
| 182 |
messages.append({
|
| 183 |
"role": "tool",
|
| 184 |
"name": tool_name,
|
|
@@ -195,18 +197,56 @@ def chatbot_response(message, history):
|
|
| 195 |
response_prefix += "<span style='color: white; font-size: 0.9em;'>🤖 <strong>Qwen2.5-72B</strong></span>\n"
|
| 196 |
response_prefix += "</div>\n\n"
|
| 197 |
|
| 198 |
-
# 显示工具调用
|
| 199 |
if tool_calls_log:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
response_prefix += "<div style='background: #f8f9fa; border-radius: 6px; padding: 10px; margin-bottom: 12px;'>\n"
|
| 201 |
response_prefix += "<div style='font-weight: 600; color: #495057; margin-bottom: 8px;'>🛠️ Tools Used</div>\n"
|
| 202 |
|
| 203 |
tool_icons = {"advanced_search_company": "🔍", "get_latest_financial_data": "📊", "extract_financial_metrics": "📈",
|
| 204 |
"get_quote": "💹", "get_market_news": "📰", "get_company_news": "📢"}
|
| 205 |
|
| 206 |
-
for tool_call in tool_calls_log:
|
| 207 |
icon = tool_icons.get(tool_call['name'], "⚙️")
|
| 208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
response_prefix += f"<span style='color: #28a745; font-weight: 600;'>{icon} {tool_call['name']}</span>\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
response_prefix += "</div>\n"
|
| 211 |
|
| 212 |
response_prefix += "</div>\n\n"
|
|
@@ -233,17 +273,13 @@ def chatbot_response(message, history):
|
|
| 233 |
yield f"❌ Error: {str(e)}"
|
| 234 |
|
| 235 |
# ========== Gradio 界面 ==========
|
| 236 |
-
with gr.Blocks(title="Financial & Market AI Assistant"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
gr.Markdown("# 🤖 Financial & Market AI Assistant")
|
| 238 |
|
| 239 |
-
gr.Markdown("""
|
| 240 |
-
<div style='padding: 15px; background: #d4edda; border-left: 4px solid #28a745; margin: 10px 0; border-radius: 4px;'>
|
| 241 |
-
<strong>✅ AI Powered by:</strong> Qwen/Qwen2.5-72B-Instruct:novita
|
| 242 |
-
<br>
|
| 243 |
-
<strong>📊 Data Sources:</strong> SEC Financial Reports + Market & Stock Data
|
| 244 |
-
</div>
|
| 245 |
-
""")
|
| 246 |
-
|
| 247 |
chat = gr.ChatInterface(
|
| 248 |
fn=chatbot_response,
|
| 249 |
examples=[
|
|
@@ -253,9 +289,16 @@ with gr.Blocks(title="Financial & Market AI Assistant") as demo:
|
|
| 253 |
"Get the latest market news about crypto",
|
| 254 |
"Compare Microsoft's latest earnings with its current stock price",
|
| 255 |
],
|
| 256 |
-
title="💬 AI
|
| 257 |
-
|
| 258 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
|
| 260 |
# 启动应用
|
| 261 |
if __name__ == "__main__":
|
|
|
|
| 174 |
for tool_call in choice.message.tool_calls:
|
| 175 |
tool_name = tool_call.function.name
|
| 176 |
tool_args = json.loads(tool_call.function.arguments)
|
|
|
|
| 177 |
|
| 178 |
# 调用 MCP 工具
|
| 179 |
tool_result = call_mcp_tool(tool_name, tool_args)
|
| 180 |
|
| 181 |
+
# 记录工具调用(包含结果)
|
| 182 |
+
tool_calls_log.append({"name": tool_name, "arguments": tool_args, "result": tool_result})
|
| 183 |
+
|
| 184 |
messages.append({
|
| 185 |
"role": "tool",
|
| 186 |
"name": tool_name,
|
|
|
|
| 197 |
response_prefix += "<span style='color: white; font-size: 0.9em;'>🤖 <strong>Qwen2.5-72B</strong></span>\n"
|
| 198 |
response_prefix += "</div>\n\n"
|
| 199 |
|
| 200 |
+
# 显示工具调用(可展开/折叠)
|
| 201 |
if tool_calls_log:
|
| 202 |
+
# 添加 JavaScript 脚本用于切换展开/折叠
|
| 203 |
+
response_prefix += """<script>
|
| 204 |
+
function toggleToolDetails(id) {
|
| 205 |
+
var details = document.getElementById('tool-details-' + id);
|
| 206 |
+
var arrow = document.getElementById('tool-arrow-' + id);
|
| 207 |
+
if (details.style.display === 'none' || details.style.display === '') {
|
| 208 |
+
details.style.display = 'block';
|
| 209 |
+
arrow.innerHTML = '▼';
|
| 210 |
+
} else {
|
| 211 |
+
details.style.display = 'none';
|
| 212 |
+
arrow.innerHTML = '▶';
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
</script>\n"""
|
| 216 |
+
|
| 217 |
response_prefix += "<div style='background: #f8f9fa; border-radius: 6px; padding: 10px; margin-bottom: 12px;'>\n"
|
| 218 |
response_prefix += "<div style='font-weight: 600; color: #495057; margin-bottom: 8px;'>🛠️ Tools Used</div>\n"
|
| 219 |
|
| 220 |
tool_icons = {"advanced_search_company": "🔍", "get_latest_financial_data": "📊", "extract_financial_metrics": "📈",
|
| 221 |
"get_quote": "💹", "get_market_news": "📰", "get_company_news": "📢"}
|
| 222 |
|
| 223 |
+
for idx, tool_call in enumerate(tool_calls_log):
|
| 224 |
icon = tool_icons.get(tool_call['name'], "⚙️")
|
| 225 |
+
tool_id = f"tool_{idx}"
|
| 226 |
+
|
| 227 |
+
# 工具主体(可点击)
|
| 228 |
+
response_prefix += f"<div style='background: white; padding: 8px 10px; margin: 6px 0; border-radius: 4px; border-left: 3px solid #28a745; cursor: pointer;' onclick='toggleToolDetails(\"{tool_id}\")'>\n"
|
| 229 |
+
response_prefix += f"<span id='tool-arrow-{tool_id}' style='color: #666; margin-right: 6px; font-size: 0.8em;'>▶</span>"
|
| 230 |
response_prefix += f"<span style='color: #28a745; font-weight: 600;'>{icon} {tool_call['name']}</span>\n"
|
| 231 |
+
response_prefix += f"</div>\n"
|
| 232 |
+
|
| 233 |
+
# 工具详情(默认隐藏)
|
| 234 |
+
response_prefix += f"<div id='tool-details-{tool_id}' style='display: none; background: #fff; padding: 10px; margin: 0 0 6px 20px; border-radius: 4px; border: 1px solid #e0e0e0; font-size: 0.85em;'>\n"
|
| 235 |
+
|
| 236 |
+
# 输入参数
|
| 237 |
+
response_prefix += "<div style='margin-bottom: 8px;'>\n"
|
| 238 |
+
response_prefix += "<strong style='color: #2196f3;'>📝 Input:</strong>\n"
|
| 239 |
+
response_prefix += f"<pre style='background: #f5f5f5; padding: 8px; border-radius: 4px; margin: 4px 0; overflow-x: auto;'>{json.dumps(tool_call['arguments'], indent=2, ensure_ascii=False)}</pre>\n"
|
| 240 |
+
response_prefix += "</div>\n"
|
| 241 |
+
|
| 242 |
+
# 输出结果
|
| 243 |
+
if 'result' in tool_call:
|
| 244 |
+
response_prefix += "<div>\n"
|
| 245 |
+
response_prefix += "<strong style='color: #4caf50;'>✅ Output:</strong>\n"
|
| 246 |
+
result_preview = str(tool_call['result'])[:200] + '...' if len(str(tool_call['result'])) > 200 else str(tool_call['result'])
|
| 247 |
+
response_prefix += f"<pre style='background: #f5f5f5; padding: 8px; border-radius: 4px; margin: 4px 0; overflow-x: auto;'>{result_preview}</pre>\n"
|
| 248 |
+
response_prefix += "</div>\n"
|
| 249 |
+
|
| 250 |
response_prefix += "</div>\n"
|
| 251 |
|
| 252 |
response_prefix += "</div>\n\n"
|
|
|
|
| 273 |
yield f"❌ Error: {str(e)}"
|
| 274 |
|
| 275 |
# ========== Gradio 界面 ==========
|
| 276 |
+
with gr.Blocks(title="Financial & Market AI Assistant", css="""
|
| 277 |
+
.contain { max-width: 100% !important; padding: 0 !important; }
|
| 278 |
+
#component-0 { height: 100vh !important; }
|
| 279 |
+
.chatbot { height: calc(100vh - 200px) !important; }
|
| 280 |
+
""") as demo:
|
| 281 |
gr.Markdown("# 🤖 Financial & Market AI Assistant")
|
| 282 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
chat = gr.ChatInterface(
|
| 284 |
fn=chatbot_response,
|
| 285 |
examples=[
|
|
|
|
| 289 |
"Get the latest market news about crypto",
|
| 290 |
"Compare Microsoft's latest earnings with its current stock price",
|
| 291 |
],
|
| 292 |
+
title="💬 Chat with AI",
|
| 293 |
+
chatbot=gr.Chatbot(height=700, show_copy_button=True),
|
| 294 |
)
|
| 295 |
+
|
| 296 |
+
# 底部信息栏(缩小)
|
| 297 |
+
gr.Markdown("""
|
| 298 |
+
<div style='padding: 8px; background: #f8f9fa; border-top: 1px solid #dee2e6; margin-top: 10px; font-size: 0.75em; color: #6c757d; text-align: center;'>
|
| 299 |
+
✅ <strong>AI:</strong> Qwen/Qwen2.5-72B-Instruct:novita | 📊 <strong>Data:</strong> SEC Financial Reports + Market & Stock Data
|
| 300 |
+
</div>
|
| 301 |
+
""")
|
| 302 |
|
| 303 |
# 启动应用
|
| 304 |
if __name__ == "__main__":
|