| | """ |
| | AI Messaging System - Visualization Tool |
| | Main entry point with authentication and brand selection. |
| | """ |
| |
|
| | import streamlit as st |
| | import sys |
| | from pathlib import Path |
| | from dotenv import load_dotenv |
| |
|
| | |
| | env_path = Path(__file__).parent / '.env' |
| | if env_path.exists(): |
| | load_dotenv(env_path) |
| | else: |
| | |
| | parent_env_path = Path(__file__).parent.parent / '.env' |
| | if parent_env_path.exists(): |
| | load_dotenv(parent_env_path) |
| |
|
| | |
| | sys.path.insert(0, str(Path(__file__).parent.parent)) |
| |
|
| | from utils.auth import verify_login, check_authentication, get_current_user, logout |
| | from utils.theme import apply_theme, get_brand_emoji, get_brand_theme |
| | from utils.data_loader import DataLoader |
| | from utils.config_manager import ConfigManager |
| | from snowflake.snowpark import Session |
| | import os |
| |
|
| | |
| | st.set_page_config( |
| | page_title="AI Messaging System - Visualization", |
| | page_icon="π΅", |
| | layout="wide", |
| | initial_sidebar_state="expanded" |
| | ) |
| |
|
| | |
| | def create_snowflake_session() -> Session: |
| | """Create a Snowflake session using environment variables.""" |
| | conn_params = { |
| | "user": os.getenv("SNOWFLAKE_USER"), |
| | "password": os.getenv("SNOWFLAKE_PASSWORD"), |
| | "account": os.getenv("SNOWFLAKE_ACCOUNT"), |
| | "role": os.getenv("SNOWFLAKE_ROLE"), |
| | "database": os.getenv("SNOWFLAKE_DATABASE"), |
| | "warehouse": os.getenv("SNOWFLAKE_WAREHOUSE"), |
| | "schema": os.getenv("SNOWFLAKE_SCHEMA"), |
| | } |
| | return Session.builder.configs(conn_params).create() |
| |
|
| |
|
| | |
| | def init_session_state(): |
| | """Initialize session state variables.""" |
| | defaults = { |
| | |
| | "authenticated": False, |
| | "user_email": "", |
| |
|
| | |
| | "selected_brand": None, |
| | "cached_configs": {}, |
| | "configs_loaded": False, |
| |
|
| | |
| | "current_experiment_id": None, |
| | "ui_log_data": None, |
| | "current_experiment_metadata": [], |
| | "current_feedbacks": [], |
| |
|
| | |
| | "ab_testing_mode": False, |
| | "ui_log_data_a": None, |
| | "ui_log_data_b": None, |
| | "experiment_a_id": None, |
| | "experiment_b_id": None, |
| | "experiment_a_metadata": [], |
| | "experiment_b_metadata": [], |
| | "feedbacks_a": [], |
| | "feedbacks_b": [], |
| | } |
| | for key, value in defaults.items(): |
| | if key not in st.session_state: |
| | st.session_state[key] = value |
| |
|
| |
|
| | init_session_state() |
| |
|
| | |
| | if not check_authentication(): |
| | |
| | st.title("π AI Messaging System - Login") |
| |
|
| | st.markdown(""" |
| | Welcome to the **AI Messaging System Visualization Tool**! |
| | |
| | This tool enables you to: |
| | - ποΈ Build and configure message campaigns |
| | - π Visualize generated messages across all stages |
| | - π Analyze performance and provide feedback |
| | - π§ͺ Run A/B tests to compare different approaches |
| | |
| | --- |
| | |
| | **Access is restricted to authorized team members only.** |
| | Please enter your credentials below. |
| | """) |
| |
|
| | with st.form("login_form"): |
| | email = st.text_input("π§ Email Address", placeholder="your.name@musora.com") |
| | token = st.text_input("π Access Token", type="password", placeholder="Enter your access token") |
| | submit = st.form_submit_button("π Login", use_container_width=True) |
| |
|
| | if submit: |
| | if verify_login(email, token): |
| | st.session_state.authenticated = True |
| | st.session_state.user_email = email |
| | st.success("β
Login successful! Redirecting...") |
| | st.rerun() |
| | else: |
| | st.error("β Invalid email or access token. Please try again.") |
| |
|
| | st.stop() |
| |
|
| | |
| | |
| | apply_theme("base") |
| |
|
| | |
| | with st.sidebar: |
| | st.title("π΅ AI Messaging System") |
| |
|
| | st.markdown(f"**Logged in as:** {get_current_user()}") |
| |
|
| | if st.button("πͺ Logout", use_container_width=True): |
| | logout() |
| | st.rerun() |
| |
|
| | st.markdown("---") |
| |
|
| | |
| | st.subheader("π¨ Select Brand") |
| |
|
| | brands = ["drumeo", "pianote", "guitareo", "singeo"] |
| | brand_labels = { |
| | "drumeo": "π₯ Drumeo", |
| | "pianote": "πΉ Pianote", |
| | "guitareo": "πΈ Guitareo", |
| | "singeo": "π€ Singeo" |
| | } |
| |
|
| | |
| | current_brand = st.session_state.get("selected_brand", brands[0]) |
| |
|
| | selected_brand = st.selectbox( |
| | "Brand", |
| | brands, |
| | index=brands.index(current_brand) if current_brand in brands else 0, |
| | format_func=lambda x: brand_labels[x], |
| | key="brand_selector", |
| | label_visibility="collapsed" |
| | ) |
| |
|
| | |
| | brand_changed = (st.session_state.selected_brand != selected_brand) |
| |
|
| | |
| | st.session_state.selected_brand = selected_brand |
| |
|
| | |
| | if brand_changed or not st.session_state.get("configs_loaded", False): |
| | if selected_brand: |
| | with st.spinner(f"Loading configurations for {selected_brand}..."): |
| | try: |
| | |
| | session = create_snowflake_session() |
| |
|
| | |
| | config_manager = ConfigManager(session) |
| |
|
| | |
| | configs = config_manager.get_all_configs(selected_brand) |
| |
|
| | |
| | if selected_brand not in st.session_state.cached_configs: |
| | st.session_state.cached_configs[selected_brand] = {} |
| | st.session_state.cached_configs[selected_brand] = configs |
| | st.session_state.configs_loaded = True |
| |
|
| | |
| | session.close() |
| |
|
| | st.success(f"β
Loaded {len(configs)} configurations from Snowflake") |
| |
|
| | except Exception as e: |
| | st.error(f"β Error loading configs from Snowflake: {e}") |
| | st.info("π‘ Make sure Snowflake credentials are set in .env file") |
| |
|
| | |
| | if selected_brand: |
| | apply_theme(selected_brand) |
| |
|
| | st.markdown("---") |
| |
|
| | |
| | st.subheader("π Navigation") |
| | st.markdown(""" |
| | Use the pages in the sidebar to navigate: |
| | - **Campaign Builder**: Create campaigns & A/B tests |
| | - **Message Viewer**: Review messages |
| | - **Analytics**: View current performance |
| | - **Historical Analytics**: Track improvements |
| | """) |
| |
|
| | |
| | if not selected_brand: |
| | st.title("π΅ Welcome to AI Messaging System") |
| |
|
| | st.markdown(""" |
| | ### Get Started |
| | |
| | **Please select a brand from the sidebar to begin.** |
| | |
| | Once you've selected a brand, you can: |
| | |
| | 1. **Build Campaigns** - Configure and generate personalized messages |
| | 2. **View Messages** - Browse and provide feedback on generated messages |
| | 3. **Run A/B Tests** - Compare different configurations side-by-side |
| | 4. **Analyze Results** - Review performance metrics and insights |
| | """) |
| |
|
| | |
| | col1, col2 = st.columns(2) |
| |
|
| | with col1: |
| | st.markdown(""" |
| | #### ποΈ Campaign Builder |
| | - Configure multi-stage campaigns |
| | - Built-in A/B testing mode |
| | - Parallel experiment processing |
| | - Automatic experiment archiving |
| | - Save custom configurations |
| | """) |
| |
|
| | st.markdown(""" |
| | #### π Message Viewer |
| | - View all generated messages |
| | - Side-by-side A/B comparison |
| | - User-centric or stage-centric views |
| | - Search and filter messages |
| | - Provide detailed feedback |
| | """) |
| |
|
| | with col2: |
| | st.markdown(""" |
| | #### π Analytics Dashboard |
| | - Real-time performance metrics |
| | - A/B test winner determination |
| | - Rejection reason analysis |
| | - Stage-by-stage performance |
| | - Export capabilities |
| | """) |
| |
|
| | st.markdown(""" |
| | #### π Historical Analytics |
| | - Track all past experiments |
| | - Rejection rate trends over time |
| | - Compare historical A/B tests |
| | - Export historical data |
| | """) |
| |
|
| | else: |
| | |
| | emoji = get_brand_emoji(selected_brand) |
| | theme = get_brand_theme(selected_brand) |
| |
|
| | st.title(f"{emoji} {selected_brand.title()} - AI Messaging System") |
| |
|
| | st.markdown(f""" |
| | ### Welcome to {selected_brand.title()} Message Generation! |
| | |
| | You're all set to create personalized messages for {selected_brand.title()} users. |
| | """) |
| |
|
| | |
| | data_loader = DataLoader() |
| |
|
| | |
| | has_users = data_loader.has_brand_users(selected_brand) |
| |
|
| | |
| | messages_df = data_loader.load_generated_messages() |
| | has_messages = messages_df is not None and len(messages_df) > 0 |
| |
|
| | st.markdown("---") |
| |
|
| | |
| | col1, col2, col3 = st.columns(3) |
| |
|
| | with col1: |
| | st.markdown("### π₯ Available Users") |
| | if has_users: |
| | user_count = data_loader.get_brand_user_count(selected_brand) |
| | st.metric("Users Available", user_count) |
| | st.success(f"β
{user_count} users ready") |
| | else: |
| | st.metric("Users Available", 0) |
| | st.info("βΉοΈ No users available") |
| |
|
| | with col2: |
| | st.markdown("### π¨ Generated Messages") |
| | if has_messages: |
| | stats = data_loader.get_message_stats() |
| | st.metric("Total Messages", stats['total_messages']) |
| | st.success(f"β
{stats['total_stages']} stages") |
| | else: |
| | st.metric("Total Messages", 0) |
| | st.info("βΉοΈ No messages generated yet") |
| |
|
| | with col3: |
| | st.markdown("### π― Quick Actions") |
| | st.markdown("") |
| | if st.button("ποΈ Build Campaign", use_container_width=True): |
| | st.switch_page("pages/1_Campaign_Builder.py") |
| | if has_messages: |
| | if st.button("π View Messages", use_container_width=True): |
| | st.switch_page("pages/2_Message_Viewer.py") |
| |
|
| | st.markdown("---") |
| |
|
| | |
| | st.markdown("### π Quick Start Guide") |
| |
|
| | st.markdown(""" |
| | #### Step 1: Build a Campaign |
| | Navigate to **Campaign Builder** to: |
| | - Toggle A/B testing mode on/off as needed |
| | - Select number of users to experiment with (1-25) |
| | - Configure campaign stages (or two experiments side-by-side) |
| | - Set LLM models and instructions |
| | - Generate personalized messages with automatic archiving |
| | |
| | #### Step 2: Review Messages |
| | Go to **Message Viewer** to: |
| | - Browse all generated messages |
| | - View A/B tests side-by-side automatically |
| | - Switch between user-centric and stage-centric views |
| | - Provide detailed feedback with rejection reasons |
| | - Track message headers and content |
| | |
| | #### Step 3: Analyze Performance |
| | Check **Analytics Dashboard** for: |
| | - Real-time approval and rejection rates |
| | - A/B test comparisons with winner determination |
| | - Common rejection reasons with visual charts |
| | - Stage-by-stage performance insights |
| | - Export analytics data |
| | |
| | #### Step 4: Track Improvements |
| | View **Historical Analytics** to: |
| | - See all past experiments over time |
| | - Identify rejection rate trends |
| | - Compare historical A/B tests |
| | - Export comprehensive historical data |
| | """) |
| |
|
| | st.markdown("---") |
| |
|
| | |
| | with st.expander("π‘ Tips & Best Practices"): |
| | st.markdown(""" |
| | - **User Selection**: Select 1-25 users for quick experimentation |
| | - **Configuration Templates**: Start with default configurations and customize as needed |
| | - **A/B Testing**: Enable A/B mode in Campaign Builder to compare two configurations in parallel |
| | - **Feedback**: Reject poor messages with specific categories including the new 'Similar To Previous' option |
| | - **Historical Tracking**: Check Historical Analytics regularly to track improvements over time |
| | - **Stage Design**: Each stage should build upon previous stages with varied messaging approaches |
| | - **Automatic Archiving**: Previous experiments are automatically archived when you start a new one |
| | """) |
| |
|
| | st.markdown("---") |
| | st.markdown("**Built with β€οΈ for the Musora team**") |
| |
|