""" Technical Mindmap Generator - Main Streamlit Application Interactive web app for generating radial mindmaps from technical keywords Features: - Modern UI inspired by GPT, Claude, and Perplexity - Sequential API calls for optimal data quality - Interactive radial mindmaps with PyVis - Query history and session management - Real-time data from Tavily, Knowledge Graph, and Gemini APIs """ import streamlit as st import sys from pathlib import Path import time # Add project root to path project_root = Path(__file__).parent sys.path.insert(0, str(project_root)) # Import project modules try: from config.settings import settings, display_settings_info from utils.api_handler import fetch_mindmap_data from utils.mindmap_generator import MindmapGenerator except ImportError as e: st.error(f"Import Error: {e}") st.info("Make sure all project files are in the correct directories") st.stop() # ============================================================================ # PAGE CONFIGURATION # ============================================================================ st.set_page_config( page_title="Technical Mindmap Generator 🧠", page_icon="🧠", layout="wide", initial_sidebar_state="collapsed", menu_items={ 'Get Help': None, 'Report a bug': None, 'About': "# Technical Mindmap Generator\nPowered by Gemini, Tavily, and Knowledge Graph APIs" } ) # ============================================================================ # CUSTOM CSS STYLING # ============================================================================ st.markdown(""" """, unsafe_allow_html=True) # ============================================================================ # SESSION STATE MANAGEMENT # ============================================================================ def initialize_session_state(): """Initialize all session state variables""" if 'mindmap_history' not in st.session_state: st.session_state.mindmap_history = [] if 'current_mindmap' not in st.session_state: st.session_state.current_mindmap = None if 'query_count' not in st.session_state: st.session_state.query_count = 0 if 'last_keyword' not in st.session_state: st.session_state.last_keyword = "" # ============================================================================ # HELPER FUNCTIONS # ============================================================================ def validate_api_keys() -> tuple[bool, list[str]]: """ Validate that all required API keys are configured Returns: Tuple of (is_valid, missing_keys_list) """ return settings.validate_api_keys() def generate_mindmap(keyword: str) -> dict: """ Generate mindmap for given keyword using API handler Args: keyword: Technical keyword to analyze Returns: Dictionary with mindmap data and metadata """ try: result = fetch_mindmap_data( keyword=keyword, gemini_key=settings.gemini_api_key, tavily_key=settings.tavily_api_key, kg_api_key=settings.google_cloud_api_key ) return result except Exception as e: st.error(f"Error generating mindmap: {str(e)}") return None # ============================================================================ # MAIN APPLICATION # ============================================================================ def main(): """Main application logic""" # Initialize session state initialize_session_state() # ======================================================================== # HEADER SECTION # ======================================================================== st.markdown("

🧠 Technical Mindmap Generator

", unsafe_allow_html=True) st.markdown( "

Transform technical keywords into interactive visual mindmaps powered by AI

", unsafe_allow_html=True ) # ======================================================================== # API KEY VALIDATION # ======================================================================== is_valid, missing_keys = validate_api_keys() if not is_valid: st.error(f"⚠️ Missing API Keys: {', '.join(missing_keys)}") st.info("Please configure your API keys in the `.env` file before using the application.") with st.expander("πŸ“ How to set up API keys"): st.markdown(""" 1. Create a `.env` file in the project root 2. Add your API keys: ``` GEMINI_API_KEY=your_gemini_key TAVILY_API_KEY=your_tavily_key ``` 3. Restart the application **Get API Keys:** - Gemini: https://ai.google.dev/ - Tavily: https://tavily.com/ - Google Cloud: https://console.cloud.google.com/ """) st.stop() # ======================================================================== # INPUT SECTION # ======================================================================== # Center the input field col1, col2, col3 = st.columns([1, 3, 1]) with col2: keyword = st.text_input( "", placeholder="e.g., Machine Learning, Blockchain, Kubernetes, Neural Networks...", key=f"keyword_input_{st.session_state.query_count}", label_visibility="collapsed", help="Enter any technical keyword or concept" ) # Center the button btn_col1, btn_col2, btn_col3 = st.columns([1, 1, 1]) with btn_col2: generate_button = st.button( "πŸš€ Generate Mindmap", use_container_width=True, type="primary" ) # ======================================================================== # MINDMAP GENERATION # ======================================================================== if generate_button and keyword: # Validate keyword if len(keyword.strip()) < 2: st.warning("⚠️ Please enter a longer keyword (at least 2 characters)") else: # Show loading animation with st.spinner(f"πŸ” Analyzing '{keyword}'...\n\n⚑ This may take 10-15 seconds..."): # Add progress messages progress_placeholder = st.empty() progress_placeholder.info("πŸ“‘ Step 1/3: Fetching web data from Tavily...") time.sleep(1) progress_placeholder.info("πŸ”— Step 2/3: Querying Knowledge Graph...") time.sleep(1) progress_placeholder.info("πŸ€– Step 3/3: Synthesizing with Gemini AI...") # Generate mindmap result = generate_mindmap(keyword) # Clear progress messages progress_placeholder.empty() if result: # Store in session state st.session_state.current_mindmap = result st.session_state.mindmap_history.append({ 'keyword': keyword, 'data': result, 'timestamp': time.time() }) st.session_state.query_count += 1 st.session_state.last_keyword = keyword st.success(f"βœ… Mindmap generated successfully for '{keyword}'!") else: st.error("❌ Failed to generate mindmap. Please try again.") # ======================================================================== # DISPLAY MINDMAP # ======================================================================== if st.session_state.current_mindmap: st.markdown("
", unsafe_allow_html=True) # Display mindmap mindmap_data = st.session_state.current_mindmap['mindmap'] st.markdown(f"### πŸ—ΊοΈ Mindmap: {st.session_state.last_keyword}") st.markdown("*Zoom, pan, and hover over nodes for details*") try: generator = MindmapGenerator(height="700px", width="100%") generator.render_in_streamlit(mindmap_data) except Exception as e: st.error(f"Error rendering mindmap: {e}") st.markdown("
", unsafe_allow_html=True) # ==================================================================== # METADATA SECTION # ==================================================================== with st.expander("πŸ“Š View Generation Details", expanded=False): metadata = st.session_state.current_mindmap['metadata'] # Metrics in columns metric_col1, metric_col2, metric_col3, metric_col4 = st.columns(4) with metric_col1: st.metric("🎯 Keyword", metadata['keyword']) with metric_col2: st.metric("πŸ”— Total Nodes", metadata.get('total_nodes', 0)) with metric_col3: st.metric("πŸ“š Sources", len(metadata.get('tavily_sources', []))) with metric_col4: st.metric("πŸ” KG Entities", metadata.get('kg_entities_count', 0)) st.markdown("---") # Display sources if metadata.get('tavily_sources'): st.subheader("πŸ“š Information Sources") for i, source in enumerate(metadata['tavily_sources'][:8], 1): st.markdown(f"{i}. [{source}]({source})") else: # ==================================================================== # WELCOME / INFO SECTION # ==================================================================== st.markdown("""

πŸ’‘ How it works:

  1. Tavily API: Gathers real-time web context and discovers related terms
  2. Knowledge Graph API: Provides structured entity relationships and descriptions
  3. Gemini AI: Synthesizes all data into a comprehensive mindmap structure

Simply enter a technical keyword above and click "Generate Mindmap" to begin!

πŸ’‘ Tip: Try keywords like "Kubernetes", "Machine Learning", "Quantum Computing", or "Blockchain"

""", unsafe_allow_html=True) # ======================================================================== # SIDEBAR - HISTORY & SETTINGS # ======================================================================== with st.sidebar: st.title("πŸ“œ Query History") if st.session_state.mindmap_history: st.markdown(f"**Total Queries:** {len(st.session_state.mindmap_history)}") st.markdown("---") # Display history in reverse order (most recent first) for i, item in enumerate(reversed(st.session_state.mindmap_history)): keyword_display = item['keyword'] # Create button with emoji if st.button( f"πŸ”„ {keyword_display}", key=f"history_{i}", help=f"Load mindmap for '{keyword_display}'" ): st.session_state.current_mindmap = item['data'] st.session_state.last_keyword = item['keyword'] st.rerun() else: st.info("No queries yet.\nGenerate your first mindmap!") st.markdown("---") # Settings section st.markdown("### βš™οΈ Settings") st.markdown(f"**Max Nodes:** {settings.max_nodes}") st.markdown(f"**Max Depth:** {settings.max_depth}") st.markdown(f"**Caching:** {'Enabled' if settings.cache_enabled else 'Disabled'}") st.markdown("---") # About section with st.expander("ℹ️ About"): st.markdown(""" **Technical Mindmap Generator** Version 1.0.0 A proof-of-concept application that creates interactive visual mindmaps for technical concepts using AI-powered APIs. **Technologies:** - Streamlit - PyVis - Gemini AI - Tavily Search - Knowledge Graph **Created by:** Your Name """) # ============================================================================ # APPLICATION ENTRY POINT # ============================================================================ if __name__ == "__main__": main()