import streamlit as st st.set_page_config( page_title="Central Bank AI", page_icon="🏦", layout="wide", initial_sidebar_state="expanded" ) import pandas as pd import plotly.express as px import time import json from utils import ( validate_email, validate_password_strength, format_currency, get_timestamp, save_chat_session, load_chat_session, delete_chat_session, clear_all_chat_history, persist_user, get_persisted_users, save_active_session, get_active_session, clear_active_session, get_ai_response, stream_ai_response, check_ollama_connection, get_active_backend, get_all_chat_sessions, get_faq_response, is_banking_query, hash_password, verify_password, is_admin, create_admin_account, get_user_data, update_user_data, get_balance, update_balance, add_transaction, get_transactions, transfer_funds, migrate_plaintext_passwords, check_fraud_alerts, get_fraud_alerts_summary, extract_text_from_pdf, load_intents, save_intents, calculate_loan_eligibility ) # ─── Multi-Language Support ─────────────────────────────────────────────────── TRANSLATIONS = { "English": { "dashboard": "📊 Dashboard", "assistant": "💬 Banking Assistant", "calculators": "🧮 Calculators", "admin_panel": "⚙️ Admin Panel", "logout": "Logout", "language": "Language", "navigation": "Navigation", "recent_chats": "Recent Chats", "new_chat": "➕ New Chat", "clear_all": "🗑️ Clear All", "balance": "Account Balance", "interest_rate": "Interest Rate", "active_loans": "Active Loans", "health_score": "🟢 Financial Health Score", "insights": "💡 Smart Insights", "net_worth": "💎 Net Worth", "upcoming_payments": "📅 Upcoming Payments", "fund_transfer": "💸 Fund Transfer", "recipient": "Recipient Username", "amount": "Amount (₹)", "description": "Description", "transfer_btn": "🚀 Transfer Funds", "history": "📝 Recent Transaction History", "chat_input": "Ask about your finances or banking services...", "popular_questions": "Popular Questions:", "upload_statement": "📂 Upload Bank Statement (PDF)", "analyzing": "Analyzing document...", "btn_balance": "💰 Balance?", "btn_interest": "📈 Interest?", "btn_support": "📞 Support", "btn_hours": "🕒 Hours", "btn_min_bal": "🏦 Min Bal", "btn_fd_rates": "📋 FD Rates" }, "Hindi": { "dashboard": "📊 डैशबोर्ड", "assistant": "💬 बैंकिंग सहायक", "calculators": "🧮 कैलकुलेटर", "admin_panel": "⚙️ एडमिन पैनल", "logout": "लॉगआउट", "language": "भाषा", "navigation": "नेविगेशन", "recent_chats": "हालिया चैट", "new_chat": "➕ नई चैट", "clear_all": "🗑️ सभी हटाएं", "balance": "खाता शेष", "interest_rate": "ब्याज दर", "active_loans": "सक्रिय ऋण", "health_score": "🟢 वित्तीय स्वास्थ्य स्कोर", "insights": "💡 स्मार्ट अंतर्दृष्टि", "net_worth": "💎 कुल संपत्ति", "upcoming_payments": "📅 आगामी भुगतान", "fund_transfer": "💸 फंड ट्रांसफर", "recipient": "प्राप्तकर्ता उपयोगकर्ता नाम", "amount": "राशि (₹)", "description": "विवरण", "transfer_btn": "🚀 फंड ट्रांसफर करें", "history": "📝 हालिया लेनदेन इतिहास", "chat_input": "अपने वित्त या बैंकिंग सेवाओं के बारे में पूछें...", "popular_questions": "लोकप्रिय प्रश्न:", "upload_statement": "📂 बैंक स्टेटमेंट अपलोड करें (PDF)", "analyzing": "दस्तावेज़ का विश्लेषण किया जा रहा है...", "btn_balance": "💰 बैलेंस?", "btn_interest": "📈 ब्याज?", "btn_support": "📞 सहायता", "btn_hours": "🕒 समय", "btn_min_bal": "🏦 न्यून. शेष", "btn_fd_rates": "📋 FD दरें" }, "Marathi": { "dashboard": "📊 डॅशबोर्ड", "assistant": "💬 बँकिंग सहाय्यक", "calculators": "🧮 कॅल्क्युलेटर", "admin_panel": "⚙️ ॲडमिन पॅनल", "logout": "लॉगआउट", "language": "भाषा", "navigation": "नेविगेशन", "recent_chats": "अलीकडील चॅट्स", "new_chat": "➕ नवीन चॅट", "clear_all": "🗑️ सर्व पुसून टाका", "balance": "खाते शिल्लक", "interest_rate": "व्याज दर", "active_loans": "सक्रिय कर्ज", "health_score": "🟢 वित्तीय आरोग्य स्कोर", "insights": "💡 स्मार्ट अंतर्दृष्टी", "net_worth": "💎 एकूण संपत्ती", "upcoming_payments": "📅 आगामी देयके", "fund_transfer": "💸 फंड ट्रान्सफर", "recipient": "प्राप्तकर्ता वापरकर्तानाव", "amount": "रक्कम (₹)", "description": "वर्णन", "transfer_btn": "🚀 फंड ट्रान्सफर करा", "history": "📝 अलीकडील व्यवहार इतिहास", "chat_input": "तुमच्या वित्ताबद्दल किंवा बँकिंग सेवांबद्दल विचारा...", "popular_questions": "लोकप्रिय प्रश्न:", "upload_statement": "📂 बँक स्टेटमेंट अपलोड करा (PDF)", "analyzing": "दस्तऐवजाचे विश्लेषण केले जात आहे...", "btn_balance": "💰 शिल्लक?", "btn_interest": "📈 व्याज?", "btn_support": "📞 समर्थन", "btn_hours": "🕒 वेळ", "btn_min_bal": "🏦 किमान शिल्लक", "btn_fd_rates": "📋 FD दर" } } def t(key): """Translation helper function.""" lang = st.session_state.get("language", "English") return TRANSLATIONS.get(lang, TRANSLATIONS["English"]).get(key, key) def apply_custom_style(theme="dark"): # Define color palette based on theme if theme == "dark": colors = { "bg": "#0B1220", "card_bg": "#111827", "text": "#f1f5f9", "text_secondary": "#94a3b8", "primary": "#2563EB", "secondary": "#0ea5e9", "border": "#1F2937", "input_bg": "rgba(30, 41, 59, 0.8)", "shadow": "rgba(0, 0, 0, 0.4)", "success": "#10B981", "warning": "#f59e0b", "danger": "#EF4444", "sidebar_bg": "#0F172A", "hover": "rgba(255, 255, 255, 0.05)" } else: colors = { "bg": "#F8FAFC", "card_bg": "#FFFFFF", "text": "#0F172A", "text_secondary": "#64748B", "primary": "#1E40AF", "secondary": "#2563EB", "border": "#E2E8F0", "input_bg": "#F8FAFC", "shadow": "rgba(0, 0, 0, 0.04)", "success": "#10B981", "warning": "#d97706", "danger": "#EF4444", "sidebar_bg": "#F1F5F9", "hover": "#EFF6FF" } st.session_state.colors = colors st.markdown(f""" """, unsafe_allow_html=True) def init_session_state(): if "users" not in st.session_state: st.session_state.users = get_persisted_users() if "logged_in" not in st.session_state: last_user = get_active_session() if last_user and last_user in st.session_state.users: st.session_state.logged_in = True st.session_state.username = last_user st.session_state.email = st.session_state.users[last_user]["email"] st.session_state.is_admin = is_admin(last_user) # Fetch fresh data for the user refresh_user_data(last_user) else: st.session_state.logged_in = False if "is_admin" not in st.session_state: st.session_state.is_admin = False if "theme" not in st.session_state: st.session_state.theme = "light" apply_custom_style(st.session_state.theme) if "username" not in st.session_state: st.session_state.username = "" if "email" not in st.session_state: st.session_state.email = "" if "current_page" not in st.session_state: st.session_state.current_page = "login" if "chat_sessions" not in st.session_state: if st.session_state.logged_in and st.session_state.username: st.session_state.chat_sessions = get_all_chat_sessions(st.session_state.username) else: st.session_state.chat_sessions = [] if "current_chat_id" not in st.session_state: st.session_state.current_chat_id = None if "messages" not in st.session_state: st.session_state.messages = [] def refresh_user_data(username): """Refreshes session state with fresh data from the backend.""" user_data = get_user_data(username) st.session_state.balance = user_data.get("balance", 0.0) st.session_state.interest_rate = user_data.get("interest_rate", 6.5) st.session_state.accrued_interest = user_data.get("accrued_interest", 0.0) st.session_state.active_loans = len([l for l in user_data.get("transactions", []) if l.get("category") == "Loan"]) st.session_state.total_loan_amount = user_data.get("total_loan_amount", 0.0) st.session_state.language = user_data.get("language", "English") init_session_state() def login(username, password): users = get_persisted_users() if username in users: if verify_password(users[username]["password"], password): st.session_state.logged_in = True st.session_state.username = username st.session_state.email = users[username]["email"] st.session_state.is_admin = is_admin(username) # Ensure fresh data is loaded refresh_user_data(username) st.session_state.current_page = "dashboard" st.session_state.chat_sessions = get_all_chat_sessions(username) save_active_session(username) return True return False def signup(username, email, password): users = get_persisted_users() if username in users: return False, "Username already exists" persist_user(username, email, password) return True, "Account created successfully!" def logout(): st.session_state.logged_in = False st.session_state.username = "" st.session_state.email = "" st.session_state.current_page = "login" st.session_state.messages = [] st.session_state.current_chat_id = None clear_active_session() def get_user_transactions_df(username): """Builds a dashboard-friendly DataFrame from stored user transactions.""" transactions = get_transactions(username) if not transactions: return pd.DataFrame(columns=["Date", "Category", "Type", "Amount", "Details", "Direction"]) rows = [] for txn in transactions: raw_type = str(txn.get("type", "")).lower() rows.append({ "Date": pd.to_datetime(txn.get("date"), errors="coerce"), "Category": txn.get("category", "Other") or "Other", "Type": "Income" if raw_type == "credit" else "Expense", "Amount": float(txn.get("amount", 0) or 0), "Details": txn.get("details", ""), "Direction": raw_type.title() if raw_type else "Unknown" }) df = pd.DataFrame(rows) df["Date"] = df["Date"].fillna(pd.Timestamp.now()) return df.sort_values(by="Date", ascending=False).reset_index(drop=True) def show_login_page(): col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.title("🏦 Central Bank AI") st.subheader("Login") st.divider() with st.form("login_form"): username = st.text_input("Username", placeholder="Enter your username") password = st.text_input("Password", type="password", placeholder="Enter your password") submit = st.form_submit_button("Login", use_container_width=True, type="primary") if submit: if login(username, password): st.success("Login successful!") st.rerun() else: st.error("Invalid username or password") st.divider() if st.button("Don't have an account? Sign Up", use_container_width=True): st.session_state.current_page = "signup" st.rerun() def show_signup_page(): col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.title("🏦 Central Bank AI") st.subheader("Create Account") st.divider() with st.form("signup_form"): username = st.text_input("Username", placeholder="Choose a username") email = st.text_input("Email", placeholder="Enter your email") password = st.text_input("Password", type="password", placeholder="Create a password") confirm_password = st.text_input("Confirm Password", type="password", placeholder="Re-enter your password") submit = st.form_submit_button("Create Account", use_container_width=True, type="primary") if submit: if not username or not email or not password or not confirm_password: st.error("All fields are required") elif password != confirm_password: st.error("Passwords do not match") else: success, msg = signup(username, email, password) if success: st.success(msg) st.info("Please login with your credentials") st.session_state.current_page = "login" time.sleep(1) st.rerun() else: st.error(msg) st.divider() if st.button("Already have an account? Login", use_container_width=True): st.session_state.current_page = "login" st.rerun() def show_dashboard(): with st.sidebar: st.markdown(f"""
🏦

Central Bank AI

""", unsafe_allow_html=True) # User Info Section (New CSS Class) st.markdown(f"""
{st.session_state.username[0].upper() if st.session_state.username else 'U'}
{st.session_state.username}
{st.session_state.email}
""", unsafe_allow_html=True) if "current_tab" not in st.session_state: st.session_state.current_tab = "Dashboard" st.markdown("
Navigation
", unsafe_allow_html=True) nav_btn_style1 = "primary" if st.session_state.current_tab == "Dashboard" else "secondary" if st.button(t("dashboard"), use_container_width=True, type=nav_btn_style1): st.session_state.current_tab = "Dashboard" st.rerun() nav_btn_style2 = "primary" if st.session_state.current_tab == "Banking Assistant" else "secondary" if st.button(t("assistant"), use_container_width=True, type=nav_btn_style2): st.session_state.current_tab = "Banking Assistant" st.rerun() nav_btn_style_calc = "primary" if st.session_state.current_tab == "Calculators" else "secondary" if st.button(t("calculators"), use_container_width=True, type=nav_btn_style_calc): st.session_state.current_tab = "Calculators" st.rerun() if st.session_state.is_admin: nav_btn_style_admin = "primary" if st.session_state.current_tab == "Admin Panel" else "secondary" if st.button(t("admin_panel"), use_container_width=True, type=nav_btn_style_admin): st.session_state.current_tab = "Admin Panel" st.rerun() st.markdown(f"
{t('language')}
", unsafe_allow_html=True) language_options = ["English", "Hindi", "Marathi"] selected_language = st.selectbox( "Select Language", language_options, index=language_options.index(st.session_state.get("language", "English")), label_visibility="collapsed" ) if selected_language != st.session_state.get("language", "English"): st.session_state.language = selected_language user_data = get_user_data(st.session_state.username) user_data["language"] = selected_language update_user_data(st.session_state.username, user_data) st.rerun() page = st.session_state.current_tab st.markdown("
", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) if st.button(t("logout"), use_container_width=True): logout() st.rerun() st.markdown("
", unsafe_allow_html=True) # Push Chat History to the bottom st.markdown("
", unsafe_allow_html=True) st.markdown(f"
{t('recent_chats')}
", unsafe_allow_html=True) new_col, clear_col = st.columns([1, 1]) with new_col: if st.button(t("new_chat"), use_container_width=True): st.session_state.messages = [] st.session_state.current_chat_id = None st.rerun() with clear_col: if st.session_state.chat_sessions and st.button(t("clear_all"), use_container_width=True): clear_all_chat_history(st.session_state.username, st.session_state) st.session_state.messages = [] st.session_state.current_chat_id = None st.rerun() # Chat Sessions st.markdown("
", unsafe_allow_html=True) if st.session_state.chat_sessions: # Display only top 5 initially, or all if "show_all_chats" is True if "show_all_chats" not in st.session_state: st.session_state.show_all_chats = False display_chats = st.session_state.chat_sessions if st.session_state.show_all_chats else st.session_state.chat_sessions[:5] for chat in display_chats: preview = chat.get('preview', 'No messages') chat_id = chat['session_id'] chat_col1, chat_col2 = st.columns([4, 1]) with chat_col1: if st.button(f"📄 {preview}", key=f"chat_{chat_id}", use_container_width=True): st.session_state.messages = chat['messages'] st.session_state.current_chat_id = chat_id st.rerun() with chat_col2: if st.button("❌", key=f"del_{chat_id}", use_container_width=True): delete_chat_session(st.session_state.username, st.session_state, chat_id) if st.session_state.current_chat_id == chat_id: st.session_state.messages = [] st.session_state.current_chat_id = None st.rerun() # Show "See all" button if there are more than 5 chats if len(st.session_state.chat_sessions) > 5: if st.session_state.show_all_chats: if st.button("See Less", use_container_width=True): st.session_state.show_all_chats = False st.rerun() else: if st.button(f"See All ({len(st.session_state.chat_sessions)})", use_container_width=True): st.session_state.show_all_chats = True st.rerun() else: st.caption("No recent chats") st.markdown("
", unsafe_allow_html=True) st.title("Dashboard" if page == "Dashboard" else t("assistant") if page == "Banking Assistant" else t("calculators") if page == "Calculators" else t("admin_panel")) if page == "Dashboard": st.markdown("## 📊 Dashboard Overview") # Custom Metric Cards st.markdown(f"""
{t('balance')}
{format_currency(st.session_state.balance)}
{t('interest_rate')}
{st.session_state.interest_rate}%
{t('active_loans')}
{st.session_state.active_loans}
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # 2 & 3. Insights & Health Score col_health, col_insights = st.columns(2) with col_health: st.markdown(f"""

{t('health_score')}

78 / 100
✓ Good savings ratio
✓ Low EMI burden
✓ Stable spending
""", unsafe_allow_html=True) with col_insights: st.markdown(f"""

{t('insights')}

📈 This month your spending increased by 12% compared to last month.
🛍️ Most spending category: Shopping.
⚠️ EMI due in 5 days.
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # 4 & 5. Net Worth & Upcoming Dues col_nw, col_dues = st.columns(2) with col_nw: st.markdown(f"""

{t('net_worth')}

Assets (Savings + FD + Investments) {format_currency(st.session_state.balance + 3500000)}
Liabilities (Loans + Credit Dues) {format_currency(st.session_state.total_loan_amount)}
Total Net Worth {format_currency(st.session_state.balance + 3500000 - st.session_state.total_loan_amount)}
""", unsafe_allow_html=True) with col_dues: st.markdown(f"""

{t('upcoming_payments')}

Home Loan EMI
₹12,000 due 5 Mar
Credit Card Bill
₹8,400 due 9 Mar
Electricity Bill
₹1,500 due 2 Mar
""", unsafe_allow_html=True) # 6. Fraud Alerts & Fund Transfer col_alerts, col_transfer = st.columns(2) with col_alerts: st.markdown(f"### 🚨 Security Alerts") alerts_summary = get_fraud_alerts_summary(st.session_state.username) if alerts_summary["total"] > 0: for alert in alerts_summary["alerts"]: severity_color = st.session_state.colors['danger'] if alert['severity'] == 'high' else st.session_state.colors['warning'] st.markdown(f"""
{alert['message']}
{alert['timestamp']}
""", unsafe_allow_html=True) else: st.success("Your account is secure. No suspicious activity detected.") with col_transfer: st.markdown(f"### {t('fund_transfer')}") with st.form("transfer_form", clear_on_submit=True): recipient = st.text_input(t("recipient")) amount = st.number_input(t("amount"), min_value=1.0, max_value=float(st.session_state.balance) if st.session_state.balance > 1.0 else 1.0, step=100.0) desc = st.text_input(t("description"), placeholder="Optional") submit_transfer = st.form_submit_button(t("transfer_btn"), use_container_width=True, type="primary") if submit_transfer: if not recipient: st.error("Recipient username is required") elif recipient == st.session_state.username: st.error("Cannot transfer to yourself") else: success, msg = transfer_funds(st.session_state.username, recipient, amount, category="Transfer", details=desc) if success: st.success(msg) refresh_user_data(st.session_state.username) time.sleep(1) st.rerun() else: st.error(msg) st.divider() # Visualizations col_left, col_right = st.columns([2, 1]) df = get_user_transactions_df(st.session_state.username) with col_left: st.write("### 📉 Income vs Expenses") if df.empty: st.info("No transactions yet. Make a transfer or add account activity to see your trends.") else: daily_data = df.groupby([pd.Grouper(key="Date", freq="D"), "Type"])["Amount"].sum().reset_index() fig_bar = px.bar( daily_data, x='Date', y='Amount', color='Type', barmode='group', color_discrete_map={"Income": st.session_state.colors['success'], "Expense": st.session_state.colors['danger']} ) fig_bar.update_layout(margin=dict(t=0, b=0, l=0, r=0), height=300, paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", showlegend=True, legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)) if st.session_state.theme == "dark": fig_bar.update_layout(font_color="white") else: fig_bar.update_layout(font_color="black") st.plotly_chart(fig_bar, use_container_width=True) with col_right: st.write("### 🍰 Expenses Breakdown") expense_df = df[df['Type'] == 'Expense'] if expense_df.empty: st.info("No expense transactions recorded yet.") else: category_data = expense_df.groupby('Category')['Amount'].sum().reset_index() fig = px.pie( category_data, values='Amount', names='Category', hole=0.4, color_discrete_sequence=[st.session_state.colors['primary'], st.session_state.colors['secondary'], '#38bdf8', '#818cf8', '#a78bfa', '#f472b6'] ) fig.update_layout( margin=dict(t=0, b=0, l=0, r=0), height=300, showlegend=False ) # Ensure transparent background for the chart fig.update_layout(paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)") if st.session_state.theme == "dark": fig.update_layout(font_color="white") else: fig.update_layout(font_color="black") st.plotly_chart(fig, use_container_width=True) st.divider() # Consolidated Transactions st.markdown("### 📝 Recent Transaction History") if df.empty: st.info("Your transaction history will appear here after your first account activity.") else: history_df = df.copy() history_df["Date"] = history_df["Date"].dt.strftime("%Y-%m-%d %H:%M:%S") history_df["Amount"] = history_df["Amount"].map(format_currency) st.dataframe( history_df[["Date", "Direction", "Type", "Category", "Amount", "Details"]], use_container_width=True, hide_index=True ) elif page == "Banking Assistant": is_connected = check_ollama_connection() col_h1, col_h2 = st.columns([4, 1]) with col_h2: backend = get_active_backend() if is_connected: label = "☁️ Groq AI" if backend == "groq" else "🟢 Ollama" st.markdown(f'
{label}
', unsafe_allow_html=True) else: st.markdown('
Offline
', unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # FAQ Suggestions st.markdown(f"
{t('popular_questions')}
", unsafe_allow_html=True) faq_row1_col1, faq_row1_col2, faq_row1_col3 = st.columns(3) with faq_row1_col1: if st.button(t("btn_balance"), use_container_width=True): st.session_state.faq_trigger = "What is my balance?" st.rerun() with faq_row1_col2: if st.button(t("btn_interest"), use_container_width=True): st.session_state.faq_trigger = "What are the current interest rates?" st.rerun() with faq_row1_col3: if st.button(t("btn_support"), use_container_width=True): st.session_state.faq_trigger = "How do I contact customer care?" st.rerun() faq_row2_col1, faq_row2_col2, faq_row2_col3 = st.columns(3) with faq_row2_col1: if st.button(t("btn_hours"), use_container_width=True): st.session_state.faq_trigger = "What are the working hours?" st.rerun() with faq_row2_col2: if st.button(t("btn_min_bal"), use_container_width=True): st.session_state.faq_trigger = "What is the minimum balance?" st.rerun() with faq_row2_col3: if st.button(t("btn_fd_rates"), use_container_width=True): st.session_state.faq_trigger = "What are the FD rates?" st.rerun() st.markdown(f"
{t('upload_statement')}
", unsafe_allow_html=True) uploaded_file = st.file_uploader(t("upload_statement"), type=["pdf"], label_visibility="collapsed") if uploaded_file: if st.button("Analyze Statement", type="primary"): with st.spinner(t("analyzing")): text, error = extract_text_from_pdf(uploaded_file) if text: st.session_state.faq_trigger = "I have uploaded a bank statement. Please summarize it: " + text[:1500] st.session_state.faq_display = "I have uploaded a bank statement. Please summarize it." else: st.error(f"Failed to extract text from PDF: {error}") # 🎙️ Voice Support UI chat_container = st.container(height=400, border=False) with chat_container: for message in st.session_state.messages: role = message["role"] display_content = message.get("display_content", message["content"]) if role == "user": st.markdown(f'
{display_content}
', unsafe_allow_html=True) else: st.markdown(f'
{display_content}
', unsafe_allow_html=True) prompt = st.chat_input(t("chat_input")) display_prompt = prompt is_pdf_analysis = False if getattr(st.session_state, 'faq_trigger', None): prompt = st.session_state.faq_trigger display_prompt = getattr(st.session_state, 'faq_display', None) or prompt is_pdf_analysis = (st.session_state.get('faq_display') or '').startswith("I have uploaded") st.session_state.faq_trigger = None st.session_state.faq_display = None if prompt: st.session_state.messages.append({"role": "user", "content": prompt, "display_content": display_prompt}) with chat_container: st.markdown(f'
{display_prompt}
', unsafe_allow_html=True) # Skip FAQ for PDF analysis — send directly to AI faq_response = None if is_pdf_analysis else get_faq_response(prompt, language=st.session_state.get("language", "English")) res_box = st.empty() full_response = "" if faq_response: full_response = faq_response res_box.markdown(f'
{full_response}
', unsafe_allow_html=True) elif is_pdf_analysis or is_banking_query(prompt): if check_ollama_connection(): last_update_time = time.time() for chunk in stream_ai_response(prompt, history=st.session_state.messages[:-1]): if chunk: full_response += chunk current_time = time.time() if current_time - last_update_time > 0.05: res_box.markdown(f'
{full_response}▌
', unsafe_allow_html=True) last_update_time = current_time res_box.markdown(f'
{full_response}
', unsafe_allow_html=True) else: full_response = "I'm having trouble reaching the AI engine right now. However, I can still help with basic queries like your balance or interest rates. How can I assist you?" res_box.markdown(f'
{full_response}
', unsafe_allow_html=True) else: # Non-banking refusal full_response = "I am a banking assistant and can only answer banking-related queries. Please feel free to ask about accounts, loans, cards, or other financial services." res_box.markdown(f'
{full_response}
', unsafe_allow_html=True) if not full_response: full_response = "I'm having trouble reaching the main AI engine right now. However, I can still help with basic queries like your balance or interest rates. How can I assist you?" st.session_state.messages.append({"role": "assistant", "content": full_response}) # 🔊 Handle Text-to-Speech # Voice input and TTS removed # Save using the persistent utility new_id = save_chat_session(st.session_state.username, st.session_state, st.session_state.messages, st.session_state.current_chat_id) if not st.session_state.current_chat_id: st.session_state.current_chat_id = new_id st.rerun() elif page == "Calculators": calc_tab1, calc_tab2, calc_tab3 = st.tabs(["EMI Calculator", "FD Calculator", "RD Calculator"]) with calc_tab1: st.markdown("### EMI Calculator") p = st.number_input("Principal Amount (₹)", min_value=1000, max_value=100000000, value=100000, step=1000) r = st.number_input("Annual Interest Rate (%)", min_value=1.0, max_value=30.0, value=8.5, step=0.1) n = st.number_input("Loan Tenure (Years)", min_value=1, max_value=30, value=5, step=1) if st.button("Calculate EMI"): r_monthly = (r / 12) / 100 n_months = n * 12 emi = (p * r_monthly * (1 + r_monthly)**n_months) / ((1 + r_monthly)**n_months - 1) st.success(f"Your Monthly EMI is: {format_currency(emi)}") st.info(f"Total Amount Payable: {format_currency(emi * n_months)}") st.info(f"Total Interest: {format_currency((emi * n_months) - p)}") with calc_tab2: st.markdown("### Fixed Deposit (FD) Calculator") p_fd = st.number_input("Deposit Amount (₹)", min_value=1000, max_value=100000000, value=100000, step=1000, key="fd_p") r_fd = st.number_input("Annual Interest Rate (%)", min_value=1.0, max_value=15.0, value=7.0, step=0.1, key="fd_r") n_fd = st.number_input("Time Period (Years)", min_value=1, max_value=20, value=1, step=1, key="fd_n") if st.button("Calculate FD Maturity"): amount = p_fd * (1 + (r_fd/100)/4)**(4*n_fd) st.success(f"Maturity Amount: {format_currency(amount)}") st.info(f"Wealth Gained: {format_currency(amount - p_fd)}") with calc_tab3: st.markdown("### Recurring Deposit (RD) Calculator") p_rd = st.number_input("Monthly Investment (₹)", min_value=100, max_value=1000000, value=1000, step=100, key="rd_p") r_rd = st.number_input("Annual Interest Rate (%)", min_value=1.0, max_value=15.0, value=6.5, step=0.1, key="rd_r") n_rd = st.number_input("Time Period (Years)", min_value=1, max_value=20, value=1, step=1, key="rd_n") if st.button("Calculate RD Maturity"): months = n_rd * 12 i = (r_rd / 100) / 12 amount = p_rd * (((1+i)**months - 1) / i) * (1+i) total_invested = p_rd * months st.success(f"Maturity Amount: {format_currency(amount)}") st.info(f"Total Invested: {format_currency(total_invested)}") st.info(f"Wealth Gained: {format_currency(amount - total_invested)}") with st.expander("🚀 Loan Eligibility Calculator"): st.markdown("### Check Your Loan Eligibility") monthly_income = st.number_input("Your Monthly Income (₹)", min_value=5000, value=50000, step=1000) existing_emis = st.number_input("Existing Monthly EMIs (₹)", min_value=0, value=0, step=500) tenure_elig = st.slider("Loan Tenure (Years)", 1, 30, 5) if st.button("Check Eligibility"): max_p, possible_emi = calculate_loan_eligibility(monthly_income, existing_emis, tenure_elig) if max_p > 0: st.success(f"You are eligible for a loan up to: **{format_currency(max_p)}**") st.info(f"Estimated Monthly EMI: {format_currency(possible_emi)}") else: st.error("Based on your current income and EMIs, you may not be eligible for a new loan at this time.") elif page == "Admin Panel" and st.session_state.is_admin: st.write("Welcome to the Admin Dashboard.") users = get_persisted_users() st.markdown("### 👥 User Management") user_data_list = [] for uname, udata in users.items(): user_data_list.append({ "Username": uname, "Email": udata.get("email", ""), "Admin": udata.get("is_admin", False), "Balance": udata.get("balance", 0.0), "Language": udata.get("language", "English") }) if user_data_list: st.dataframe(pd.DataFrame(user_data_list), use_container_width=True) st.markdown("### 🚨 Fraud Alerts Overview") all_alerts = [] for uname in users: alerts = check_fraud_alerts(uname) for a in alerts: a['username'] = uname all_alerts.append(a) if all_alerts: for alert in all_alerts: if alert['severity'] == 'high': st.error(f"**{alert['username']}**: {alert['message']} ({alert['timestamp']})") else: st.warning(f"**{alert['username']}**: {alert['message']} ({alert['timestamp']})") else: st.success("No fraud alerts at the moment.") st.markdown("### 📚 Knowledge Base (Intents)") intents = load_intents() if intents: with st.expander("Edit Intents JSON"): intents_json = st.text_area("Intents JSON", value=json.dumps(intents, indent=4), height=300) if st.button("Save Intents"): try: new_intents = json.loads(intents_json) if save_intents(new_intents): st.success("Intents updated successfully!") st.cache_data.clear() else: st.error("Failed to save intents") except Exception as e: st.error(f"Invalid JSON: {e}") if not st.session_state.logged_in: if st.session_state.current_page == "login": show_login_page() elif st.session_state.current_page == "signup": show_signup_page() else: show_dashboard()