File size: 2,573 Bytes
2a7171f
 
 
 
e63cc01
2a7171f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e63cc01
 
2a7171f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e63cc01
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""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()