Spaces:
Runtime error
Runtime error
Shrijeeth-Suresh
feat: add Makefile and integrate live financial data with auto-refresh charts
01c92a0 | import datetime | |
| import gradio as gr | |
| import pandas as pd | |
| import plotly.express as px | |
| import requests | |
| from gradio.themes import Default | |
| def get_financial_summary(): | |
| try: | |
| response = requests.get( | |
| f"https://green-smoke-labs-dev--green-smoke-labs-expensynth-api-server.modal.run/api/transactions/monthly-summary/{datetime.datetime.now().year}", | |
| ) | |
| response.raise_for_status() | |
| data = response.json() | |
| except Exception: | |
| data = { | |
| "months": [ | |
| "Jan", | |
| "Feb", | |
| "Mar", | |
| "Apr", | |
| "May", | |
| "Jun", | |
| "Jul", | |
| "Aug", | |
| "Sep", | |
| "Oct", | |
| "Nov", | |
| "Dec", | |
| ], | |
| "credits": [1000, 1200, 900, 1300, 1500, 1700], | |
| "expenses": [400, 600, 500, 700, 800, 900], | |
| } | |
| return data | |
| def get_category_distribution(): | |
| try: | |
| response = requests.get( | |
| f"https://green-smoke-labs-dev--green-smoke-labs-expensynth-api-server.modal.run/api/transactions/category-distribution/{datetime.datetime.now().year}", | |
| ) | |
| response.raise_for_status() | |
| data = response.json() | |
| except Exception: | |
| data = { | |
| "categories": ["Food", "Retail", "Others"], | |
| "distribution": [40, 30, 30], | |
| } | |
| return data | |
| def display_financial_charts(): | |
| data = get_financial_summary() | |
| df = pd.DataFrame(data) | |
| df["savings"] = df["credits"] - df["expenses"] | |
| # fig1 = px.line(df, x="Month", y="Credit", title="Monthly Credit") | |
| fig2 = px.bar(df, x="months", y="expenses", title="Monthly Expenses") | |
| fig3 = px.area(df, x="months", y="credits", title="Monthly Savings") | |
| latest = get_category_distribution() | |
| fig4 = px.pie( | |
| names=latest["categories"], | |
| values=latest["distribution"], | |
| title="Latest Financial Distribution", | |
| ) | |
| return fig2, fig3, fig4 | |
| def chatbot_respond(user_message, history): | |
| history = history or [] | |
| if user_message: | |
| history.append({"role": "user", "content": user_message}) | |
| try: | |
| response = requests.post( | |
| "https://green-smoke-labs-dev--green-smoke-labs-expensynth-api-server.modal.run/bot/query", | |
| json={"messages": history}, | |
| ) | |
| response.raise_for_status() | |
| bot_reply = ( | |
| response.json().get("data", {}).get("raw", "Sorry, I didn't understand.") | |
| ) | |
| except Exception: | |
| bot_reply = "Server unavailable. This is a mocked reply." | |
| history.append({"role": "assistant", "content": bot_reply}) | |
| return "", history, history | |
| def reset_chat(): | |
| """Reset chat history and clear the chatbot text box.""" | |
| return "", [], [] | |
| def minimize_chat(): | |
| return gr.update(visible=False), gr.update(visible=True) | |
| def restore_chat(): | |
| return gr.update(visible=True), gr.update(visible=False) | |
| # Frontend | |
| with gr.Blocks( | |
| theme=Default(), | |
| css=""" | |
| #profile-pic-wrapper { | |
| width: 100px; | |
| height: 100px; | |
| border-radius: 50%; | |
| overflow: hidden; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin: 0 auto 10px auto; | |
| background: #fff; | |
| } | |
| #profile-icon { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| border-radius: 50%; | |
| display: block; | |
| margin: 0; | |
| } | |
| .header h1 { | |
| margin: 0; | |
| font-family: 'Arial', sans-serif; | |
| color: #333; | |
| } | |
| .left-navbar { | |
| background-color: #fff; | |
| padding: 20px; | |
| border-right: 1px solid #ddd; | |
| min-height: 80vh; | |
| } | |
| .chat-panel { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| left: auto; | |
| width: 350px; | |
| height: 620px; | |
| background: #fff; | |
| border: 1px solid #ddd; | |
| box-shadow: 2px 2px 10px rgba(0,0,0,0.1); | |
| border-radius: 8px; | |
| padding: 10px; | |
| overflow: visible; | |
| z-index: 1001; | |
| } | |
| #open-chat-btn { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| left: auto; | |
| z-index: 1000; | |
| } | |
| #chatbot-input { | |
| height: 150px; | |
| } | |
| """, | |
| ) as demo: | |
| chat_panel = gr.Column(visible=True, elem_classes="chat-panel") | |
| with chat_panel: | |
| gr.Markdown("### Financial Agent", height=200) | |
| chatbot_state = gr.State([]) | |
| chatbot_ui = gr.Chatbot(type="messages") | |
| chatbot_input = gr.Textbox( | |
| placeholder="Type your message...", | |
| label="Your Message", | |
| elem_id="chatbot-input", | |
| ) | |
| with gr.Row(): | |
| send_btn = gr.Button("Send") | |
| reset_btn = gr.Button("Reset Chat") | |
| minimize_btn = gr.Button("Minimize", elem_id="minimize-chat-btn") | |
| with gr.Row(): | |
| # gr.HTML( | |
| # '<div id="profile-pic-wrapper"><img id="profile-icon" src="assets/profile_pic.png" /></div>' | |
| # ) | |
| gr.Markdown("<h1>Financial Health Dashboard</h1>", elem_classes="header") | |
| with gr.Row(): | |
| # with gr.Column(scale=1, elem_classes="left-navbar"): | |
| # gr.Markdown("## Navigation") | |
| # for nav in ["Dashboard", "Reports", "Analytics", "Settings"]: | |
| # gr.Button(nav) | |
| with gr.Column(scale=3): | |
| with gr.Tabs(): | |
| with gr.TabItem("Charts"): | |
| chart1 = gr.Plot(label="Monthly Expenses") | |
| chart2 = gr.Plot(label="Monthly Savings") | |
| chart3 = gr.Plot(label="Latest Financial Distribution") | |
| def reload_charts(): | |
| fig2, fig3, fig4 = display_financial_charts() | |
| return fig2, fig3, fig4 | |
| # Initial load | |
| demo.load(reload_charts, outputs=[chart1, chart2, chart3]) | |
| # Auto-refresh every 1 hour (3600 seconds) | |
| timer = gr.Timer(value=60, active=True) | |
| timer.tick(fn=reload_charts, outputs=[chart1, chart2, chart3]) | |
| with gr.TabItem("Overview"): | |
| # summary = get_financial_summary() | |
| summary = chatbot_respond("What is the financial summary?", [])[-1][ | |
| -1 | |
| ]["content"] | |
| advice = chatbot_respond( | |
| "What financial advice can you give? Give general advice, do not give anything specific to my transactions", | |
| [], | |
| )[-1][-1]["content"] | |
| gr.Markdown( | |
| f"""### Summary\n{summary}\n\n### Financial Advice\n{advice}""" | |
| ) | |
| minimized_state = gr.State(False) | |
| open_btn = gr.Button("Open Chat", elem_id="open-chat-btn", visible=False) | |
| chatbot_input.submit( | |
| fn=chatbot_respond, | |
| inputs=[chatbot_input, chatbot_state], | |
| outputs=[chatbot_input, chatbot_state, chatbot_ui], | |
| queue=False, | |
| ) | |
| send_btn.click( | |
| fn=chatbot_respond, | |
| inputs=[chatbot_input, chatbot_state], | |
| outputs=[chatbot_input, chatbot_state, chatbot_ui], | |
| queue=False, | |
| ) | |
| reset_btn.click( | |
| fn=reset_chat, | |
| inputs=None, | |
| outputs=[chatbot_input, chatbot_state, chatbot_ui], | |
| queue=False, | |
| ) | |
| minimize_btn.click( | |
| fn=minimize_chat, | |
| inputs=None, | |
| outputs=[chat_panel, open_btn], | |
| queue=False, | |
| ) | |
| open_btn.click( | |
| fn=restore_chat, | |
| inputs=None, | |
| outputs=[chat_panel, open_btn], | |
| queue=False, | |
| ) | |
| demo.launch() | |