financemanager / app.py
spacedout-bits's picture
Rebuild: finance manager chat assistant with HF CSV storage and Telegram bot
2a7171f
"""Gradio web UI for the personal finance manager."""
import os
import threading
import gradio as gr
import bot
from ledger import get_ledger
from agent import stream_response, execute
logging_format = "%(asctime)s %(levelname)s %(name)s: %(message)s"
import logging
logging.basicConfig(level=logging.INFO, format=logging_format)
ledger = get_ledger()
threading.Thread(target=bot.start, args=(ledger,), daemon=True).start()
# ── chat handler ──────────────────────────────────────────────────────────────
def respond(message: str, history: list[dict], hf_token: gr.OAuthToken):
token = hf_token.token if hf_token else os.getenv("HF_TOKEN", "")
if not token:
yield "Please log in with HuggingFace to use the assistant."
return
final_reply, final_action = "", None
for partial, action in stream_response(message, history, ledger, token):
final_reply, final_action = partial, action
yield partial
if final_action:
confirmation = execute(final_action, ledger, message)
if confirmation:
yield final_reply + "\n\n" + confirmation
# ── ledger tab helpers ────────────────────────────────────────────────────────
def refresh_ledger():
return ledger.recent(50), f"### πŸ’° Total: ${ledger.total():.2f}"
# ── layout ────────────────────────────────────────────────────────────────────
with gr.Blocks(theme=gr.themes.Soft(), title="πŸ’Έ Finance Manager") as demo:
with gr.Sidebar():
gr.LoginButton()
gr.Markdown(f"**Storage:** {ledger.status}")
with gr.Tabs():
with gr.Tab("πŸ’¬ Chat"):
gr.ChatInterface(
respond,
type="messages",
placeholder="e.g. 'Spent $12 on lunch' or 'How much did I spend on food?'",
)
with gr.Tab("πŸ“Š Ledger"):
refresh_btn = gr.Button("πŸ”„ Refresh", variant="secondary")
table = gr.Dataframe(value=ledger.recent(50), interactive=False)
total_md = gr.Markdown(f"### πŸ’° Total: ${ledger.total():.2f}")
refresh_btn.click(fn=refresh_ledger, outputs=[table, total_md])
if __name__ == "__main__":
demo.launch()