Spaces:
Running
Running
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() | |