Spaces:
Paused
Paused
| """ | |
| app.py - COMPLETE WORKING VERSION | |
| No duplicate headers, clean structure | |
| app.py - A-GRADE VERSION | |
| Added scenario state management for interactive visualizations | |
| PRODUCTION READY VERSION: | |
| 1. Fixed: Suggestions NEVER recycle (even after 7+ messages) | |
| 2. Fixed: Proper state tracking with message history analysis | |
| 3. Fixed: Detects NEW topics vs continuation | |
| 4. Added: Gap reduction CSS class for .st-emotion-cache-wfksow | |
| 5. Fixed: All edge cases (bitcoin, options trading, etc) | |
| """ | |
| import streamlit as st | |
| from llm_agent import aqua_response, get_default_profile | |
| from components import render_left_panel, render_chat_panel, check_query_for_scenario | |
| from styles import get_custom_css | |
| st.set_page_config(layout="wide", page_title="Aqua Thistle", page_icon="π") | |
| st.markdown(get_custom_css(), unsafe_allow_html=True) | |
| # Main header | |
| st.markdown(""" | |
| <div style='text-align: center; padding: 1rem 0 1.5rem 0;'> | |
| <h1 style='font-size: 2.5rem; margin: 0 0 0.5rem 0;'>π Aqua Thistle</h1> | |
| <p style='color: #4a4a4a; font-size: 1rem; margin: 0;'>Your Personal GenZ Mentor for Life, Finance & Education</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Initialize session state | |
| if "profile" not in st.session_state: | |
| st.session_state.profile = get_default_profile() | |
| if "seed_chat" not in st.session_state: | |
| st.session_state.seed_chat = None | |
| if "current_category" not in st.session_state: | |
| st.session_state.current_category = "Finance" | |
| # Scenario state for interactive visualizations | |
| if "scenario_mode" not in st.session_state: | |
| st.session_state.scenario_mode = False | |
| if "scenario_profile" not in st.session_state: | |
| st.session_state.scenario_profile = None | |
| if "whatif_mode" not in st.session_state: | |
| st.session_state.whatif_mode = False | |
| # Initialize chat histories for each category | |
| categories_list = ["Finance", "Education", "Family", "Friends", "Weekend/Vacation"] | |
| for cat in categories_list: | |
| if f"chat_{cat}" not in st.session_state: | |
| st.session_state[f"chat_{cat}"] = [] | |
| # Category icons | |
| category_icons = { | |
| "Finance": "π°", | |
| "Education": "π", | |
| "Family": "π¨βπ©βπ§", | |
| "Friends": "π₯", | |
| "Weekend/Vacation": "ποΈ" | |
| } | |
| # Category selector | |
| st.markdown("### π― Focus Area") | |
| selected = st.selectbox( | |
| "cat", | |
| categories_list, | |
| index=categories_list.index(st.session_state.current_category), | |
| format_func=lambda x: f"{category_icons[x]} {x}", | |
| key="cat_select", | |
| label_visibility="collapsed" | |
| ) | |
| if selected != st.session_state.current_category: | |
| st.session_state.current_category = selected | |
| # Reset scenario mode when switching categories | |
| st.session_state.scenario_mode = False | |
| st.session_state.whatif_mode = False | |
| st.session_state.scenario_profile = None | |
| st.rerun() | |
| category = st.session_state.current_category | |
| st.markdown("---") | |
| # Two-column layout | |
| left_col, right_col = st.columns([2, 3]) | |
| with left_col: | |
| render_left_panel(st.session_state, category) | |
| with right_col: | |
| chat_key = f"chat_{category}" | |
| # Render chat panel (includes header, reset, messages, quick actions) | |
| render_chat_panel(chat_key, category) | |
| # Chat input | |
| prompt = st.chat_input(f"Ask about {category.lower()}...") | |
| # Handle seed chat (from Quick Actions or Ask buttons) | |
| if st.session_state.seed_chat: | |
| prompt = st.session_state.seed_chat | |
| st.session_state.seed_chat = None | |
| # Process user message | |
| if prompt: | |
| # Check if query contains a scenario (what-if question) | |
| scenario_profile = check_query_for_scenario(prompt, st.session_state.profile) | |
| if scenario_profile: | |
| # Enter scenario mode | |
| st.session_state.scenario_mode = True | |
| st.session_state.scenario_profile = scenario_profile | |
| # Add to chat history | |
| st.session_state[chat_key].append({"role": "user", "content": prompt}) | |
| with st.spinner("π Thinking..."): | |
| ai_response = aqua_response(prompt, st.session_state.profile, category) | |
| st.session_state[chat_key].append({"role": "assistant", "content": ai_response}) | |
| st.rerun() | |
| # Footer | |
| st.markdown("---") | |
| st.markdown("<div style='text-align: center; color: #4a4a4a; font-size: 0.875rem;'><p>Built with π for GenZ</p></div>", unsafe_allow_html=True) | |