"""AI research setup component for the API key manager.""" import streamlit as st from loguru import logger from typing import Dict, Any from ..manager import APIKeyManager from .base import render_navigation_buttons import os from dotenv import load_dotenv import sys # Configure logger logger.remove() # Remove default handler logger.add( "logs/ai_research_setup.log", rotation="500 MB", retention="10 days", level="DEBUG", format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}" ) logger.add( sys.stdout, level="INFO", format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {message}" ) def get_existing_api_key(key_name: str) -> str: """Get existing API key from environment or .env file. Args: key_name (str): Name of the API key to retrieve Returns: str: The API key value if found, empty string otherwise """ # First try to get from environment api_key = os.getenv(key_name) # If not in environment, try to get from .env file if not api_key and os.path.exists('.env'): try: with open('.env', 'r') as f: for line in f: if line.strip().startswith(f"{key_name}="): api_key = line.strip().split('=')[1] break except Exception as e: logger.error(f"[get_existing_api_key] Failed to read {key_name} from .env: {str(e)}") return api_key if api_key else "" def update_env_file(api_keys: Dict[str, str]) -> None: """Update the .env file with new API keys, avoiding duplicates. Args: api_keys (Dict[str, str]): Dictionary of API keys to update """ try: # Read existing .env file content env_content = [] if os.path.exists('.env'): with open('.env', 'r') as f: env_content = f.readlines() # Remove trailing newlines and empty lines env_content = [line.strip() for line in env_content if line.strip()] # Create a dictionary of existing variables env_dict = {} for line in env_content: if '=' in line: key, value = line.split('=', 1) env_dict[key.strip()] = value.strip() # Update with new values env_dict.update(api_keys) # Write back to .env file with open('.env', 'w') as f: for key, value in env_dict.items(): f.write(f"{key}={value}\n") logger.info("[update_env_file] Successfully updated .env file with API keys") except Exception as e: logger.error(f"[update_env_file] Error updating .env file: {str(e)}") raise def render_ai_research_setup(api_key_manager: APIKeyManager) -> Dict[str, Any]: """Render the AI research setup step.""" logger.info("[render_ai_research_setup] Rendering AI research setup component") st.markdown("""

🔍 AI Web Research API Setup

""", unsafe_allow_html=True) # Create two columns for different search types col1, col2 = st.columns(2) with col1: st.markdown("### The Usual") # Get existing API keys existing_serpapi_key = get_existing_api_key("SERPAPI_KEY") existing_firecrawl_key = get_existing_api_key("FIRECRAWL_API_KEY") serpapi_key = st.text_input( "## Enter 🔎 SerpAPI", value=existing_serpapi_key, type="password", key="serpapi_key", help="Enter your SerpAPI key", placeholder="Access search engine results for research" ) if serpapi_key or existing_serpapi_key: st.markdown("""
✓ API key configured
""", unsafe_allow_html=True) st.markdown("""
📋 How to get your SerpAPI key

Step-by-step guide:

  1. Visit SerpAPI
  2. Create an account
  3. Go to your dashboard
  4. Copy your API key
  5. Paste it here

Note: SerpAPI provides real-time search results from multiple engines.

""", unsafe_allow_html=True) st.markdown("", unsafe_allow_html=True) firecrawl_key = st.text_input( "Enter 🕷️ Firecrawl API Key", value=existing_firecrawl_key, type="password", key="firecrawl_key", help="Enter your Firecrawl API key", placeholder="Web content extraction and analysis" ) if firecrawl_key or existing_firecrawl_key: st.markdown("""
✓ Firecrawl API key configured
""", unsafe_allow_html=True) st.markdown("""
📋 How to get your Firecrawl API key

Step-by-step guide:

  1. Visit Firecrawl
  2. Create an account
  3. Go to your dashboard
  4. Generate your API key
  5. Copy and paste it here

Note: Firecrawl provides powerful web content extraction and analysis capabilities.

""", unsafe_allow_html=True) st.markdown("", unsafe_allow_html=True) with col2: st.markdown("### AI Deep Research") # Get existing API keys existing_tavily_key = get_existing_api_key("TAVILY_API_KEY") existing_metaphor_key = get_existing_api_key("METAPHOR_API_KEY") tavily_key = st.text_input( "Enter 🤖 Tavily API Key", value=existing_tavily_key, type="password", key="tavily_key", help="Enter your Tavily API key", placeholder="AI-powered search with semantic understanding" ) if tavily_key or existing_tavily_key: st.markdown("""
✓ Tavily API key configured
""", unsafe_allow_html=True) st.markdown("""
📋 How to get your Tavily API key

Step-by-step guide:

  1. Visit Tavily
  2. Create an account
  3. Go to API settings
  4. Generate a new API key
  5. Copy and paste it here

Note: Tavily provides AI-powered semantic search capabilities.

""", unsafe_allow_html=True) st.markdown("", unsafe_allow_html=True) metaphor_key = st.text_input( "Enter 🧠 Metaphor/Exa API Key", value=existing_metaphor_key, type="password", key="metaphor_key", help="Enter your Metaphor/Exa API key", placeholder="Neural search engine for deep research" ) if metaphor_key or existing_metaphor_key: st.markdown("""
✓ API key configured
""", unsafe_allow_html=True) st.markdown("""
📋 How to get your Metaphor/Exa API key

Step-by-step guide:

  1. Visit Metaphor/Exa
  2. Create an account
  3. Navigate to API settings
  4. Generate your API key
  5. Copy and paste it here

Note: Metaphor/Exa provides neural search capabilities for deep research.

""", unsafe_allow_html=True) st.markdown("", unsafe_allow_html=True) # Track changes changes_made = bool(serpapi_key or tavily_key or metaphor_key or firecrawl_key) # Navigation buttons with correct arguments if render_navigation_buttons(3, 5, changes_made): if changes_made: try: # Prepare API keys dictionary with only non-empty values api_keys = {} if serpapi_key: api_keys['SERPAPI_KEY'] = serpapi_key if tavily_key: api_keys['TAVILY_API_KEY'] = tavily_key if metaphor_key: api_keys['METAPHOR_API_KEY'] = metaphor_key if firecrawl_key: api_keys['FIRECRAWL_API_KEY'] = firecrawl_key # Update .env file with new API keys update_env_file(api_keys) # Update environment variables for key, value in api_keys.items(): os.environ[key] = value # Store the API keys in session state st.session_state['api_keys'] = { 'serpapi': serpapi_key, 'tavily': tavily_key, 'metaphor': metaphor_key, 'firecrawl': firecrawl_key } # Update progress and move to next step st.session_state['current_step'] = 4 st.rerun() except Exception as e: error_msg = f"Error saving API keys: {str(e)}" logger.error(f"[render_ai_research_setup] {error_msg}") st.error(error_msg) else: st.error("Please configure at least one research provider to continue") # Detailed Information Section st.markdown("---") st.markdown("### Understanding Your Research Options") # Create four columns for the information popovers info_col1, info_col2, info_col3, info_col4 = st.columns(4) # The Usual: Traditional Search Popover with info_col1: with st.popover("#### The Usual: Traditional Search"): st.markdown(""" **SerpAPI** - Real-time search results from multiple search engines - Access to structured data from search results - Great for gathering general information and market research - Includes features like: - Web search results - News articles - Knowledge graphs - Related questions """) # AI Deep Research Popover with info_col2: with st.popover("#### AI Deep Research: Advanced Search Capabilities"): st.markdown(""" **Tavily AI** - AI-powered search with semantic understanding - Automatically summarizes and analyzes search results - Perfect for: - Deep research tasks - Academic research - Fact-checking - Real-time information gathering **Metaphor/Exa** - Neural search engine that understands context and meaning - Specialized in finding highly relevant content - Ideal for: - Technical research - Finding similar content - Discovering patterns in research - Understanding topic landscapes """) # Choosing the Right Tool Popover with info_col3: with st.popover("#### Choosing the Right Tool"): st.markdown(""" 1. **For General Research:** - Start with SerpAPI for broad coverage and structured data 2. **For Deep Analysis:** - Use Tavily AI when you need AI-powered insights - Choose Metaphor/Exa for neural search and pattern discovery 3. **For Comprehensive Research:** - Combine multiple tools to get the most complete picture - Use SerpAPI for initial research - Follow up with AI tools for deeper insights > **Pro Tip:** Configure multiple providers to ensure you have backup options and can cross-reference results for better accuracy. """) # Coming Soon Popover with info_col4: with st.popover("#### 🔜 Coming Soon - More Search Options"): st.markdown(""" **Bing Search API** - Microsoft's powerful search API with comprehensive capabilities - Features include: - Web search with advanced filtering - News articles with sentiment analysis - Image search with visual recognition - Video search with content understanding - Custom search parameters for targeted results **Google Search API** - Google's programmable search engine with extensive features - Capabilities include: - Custom search engine creation - Site-specific search - Image and video search - News search with time-based filtering - Knowledge graph integration **Additional Planned Integrations:** - **DuckDuckGo API**: Privacy-focused search with no tracking - **Brave Search API**: Independent search engine with unique features - **Perplexity API**: AI-powered research assistant with real-time data > **Note:** These integrations are under active development and will be available in future updates. """) return {"current_step": 3, "changes_made": changes_made}