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( # '
' # ) gr.Markdown("

Financial Health Dashboard

", 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()