| """ |
| Fintech Multi-Agent Orchestrator - HuggingFace Spaces Demo |
| Uses Gemma 3 via HuggingFace Inference API |
| """ |
|
|
| import gradio as gr |
| import matplotlib |
| matplotlib.use('Agg') |
| import matplotlib.pyplot as plt |
| import numpy as np |
| from io import BytesIO |
| import base64 |
| from PIL import Image |
|
|
| from graph import run_orchestrator |
|
|
|
|
| def create_chart(chart_data: dict) -> Image.Image: |
| """Generate chart from chart_data dict.""" |
| chart_type = chart_data.get("type", "bar") |
| title = chart_data.get("title", "Chart") |
| data = chart_data.get("data", {}) |
| |
| fig, ax = plt.subplots(figsize=(10, 6)) |
| |
| if chart_type == "pie": |
| labels = list(data.keys()) |
| values = list(data.values()) |
| colors = plt.cm.Set3(np.linspace(0, 1, len(labels))) |
| ax.pie(values, labels=labels, autopct='%1.1f%%', colors=colors, startangle=90) |
| ax.set_title(title, fontsize=14, fontweight='bold') |
| |
| elif chart_type == "bar": |
| labels = list(data.keys()) |
| values = list(data.values()) |
| colors = plt.cm.viridis(np.linspace(0.3, 0.9, len(labels))) |
| bars = ax.bar(labels, values, color=colors) |
| ax.set_title(title, fontsize=14, fontweight='bold') |
| ax.set_ylabel('Amount ($)') |
| plt.xticks(rotation=45, ha='right') |
| for bar, val in zip(bars, values): |
| ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + max(values)*0.02, |
| f'${val:,.0f}', ha='center', va='bottom', fontsize=9) |
| |
| elif chart_type == "line": |
| x = list(range(len(data))) |
| y = list(data.values()) |
| ax.plot(x, y, marker='o', linewidth=2, markersize=8, color='#2E86AB') |
| ax.fill_between(x, y, alpha=0.3, color='#2E86AB') |
| ax.set_xticks(x) |
| ax.set_xticklabels(list(data.keys())) |
| ax.set_title(title, fontsize=14, fontweight='bold') |
| ax.set_ylabel('Amount ($)') |
| ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'${x:,.0f}')) |
| |
| plt.tight_layout() |
| |
| |
| buf = BytesIO() |
| plt.savefig(buf, format='png', dpi=150, bbox_inches='tight') |
| buf.seek(0) |
| plt.close() |
| |
| return Image.open(buf) |
|
|
|
|
| def respond(query: str, history: list): |
| """Main chat handler.""" |
| if not query.strip(): |
| return history, None |
| |
| |
| response, chart_data = run_orchestrator(query) |
| |
| |
| chart_image = None |
| if chart_data: |
| chart_image = create_chart(chart_data) |
| |
| |
| history = history or [] |
| history.append({"role": "user", "content": query}) |
| history.append({"role": "assistant", "content": response}) |
| |
| return history, chart_image |
|
|
|
|
| |
| with gr.Blocks( |
| title="Fintech Multi-Agent Orchestrator", |
| ) as demo: |
| |
| gr.Markdown(""" |
| # 🏦 Fintech Multi-Agent Orchestrator |
| |
| **Powered by Gemma 3 via HuggingFace Inference API** |
| |
| Ask questions about your finances, request calculations, or generate charts! |
| |
| ### Example queries: |
| - "What is my net worth?" |
| - "Show my portfolio as a pie chart" |
| - "Calculate compound interest on $10000 at 8% for 5 years" |
| - "Show my assets breakdown" |
| - "Show net worth projection" |
| """) |
| |
| with gr.Row(): |
| with gr.Column(scale=2): |
| chatbot = gr.Chatbot( |
| label="Chat", |
| height=400, |
| type="messages" |
| ) |
| |
| with gr.Row(): |
| query_input = gr.Textbox( |
| label="Your Question", |
| placeholder="Ask about your finances...", |
| scale=4, |
| ) |
| submit_btn = gr.Button("Send", variant="primary", scale=1) |
| |
| with gr.Column(scale=1): |
| chart_output = gr.Image( |
| label="Generated Chart", |
| height=400, |
| ) |
| |
| with gr.Row(): |
| clear_btn = gr.Button("Clear Chat") |
| |
| submit_btn.click( |
| respond, |
| inputs=[query_input, chatbot], |
| outputs=[chatbot, chart_output], |
| ).then( |
| lambda: "", |
| outputs=[query_input], |
| ) |
| |
| query_input.submit( |
| respond, |
| inputs=[query_input, chatbot], |
| outputs=[chatbot, chart_output], |
| ).then( |
| lambda: "", |
| outputs=[query_input], |
| ) |
| |
| clear_btn.click( |
| lambda: ([], None), |
| outputs=[chatbot, chart_output], |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|