import streamlit as st import sys import os from pathlib import Path # Add parent directory to path to import modules sys.path.append(str(Path(__file__).parent.parent.parent)) # Import utils module from utils import ( load_css, display_google_serp_results, display_tavily_results, display_metaphor_results, display_google_trends_results, display_crawler_results, display_analyzer_results ) # Configure Streamlit page settings st.set_page_config( page_title="AI Web Researcher Dashboard", page_icon="πŸ”", layout="wide", initial_sidebar_state="expanded" ) # Apply custom CSS immediately st.markdown(""" """, unsafe_allow_html=True) # CSS is now loaded at the top of the file # Initialize session state variables def init_session_state(): if 'current_section' not in st.session_state: st.session_state['current_section'] = 'Dashboard Home' # Initialize session state at startup init_session_state() def main(): # Initialize session state before accessing it init_session_state() # Main navigation header st.markdown('', unsafe_allow_html=True) # Create tabs for navigation selected_section = st.tabs([ "🏠 Dashboard Home", "πŸ” Search Tools", "🧠 Neural Search", "πŸ“ˆ Trend Analysis", "πŸ•ΈοΈ Web Crawling", "πŸ“š Academic Research", "πŸ“‹ Research Workflows" ]) # Display appropriate section based on selected tab with selected_section[0]: display_home() with selected_section[1]: display_search_tools() with selected_section[2]: display_neural_search() with selected_section[3]: display_trend_analysis() with selected_section[4]: display_web_crawling() with selected_section[5]: display_academic_research() with selected_section[6]: display_research_workflows() # Ensure CSS is consistently applied load_css() def display_home(): # Main header with improved styling st.markdown('
AI Web Researcher Dashboard
', unsafe_allow_html=True) # Introduction with better formatting st.markdown("""

Welcome to the AI Web Researcher Dashboard, a comprehensive suite of research tools designed specifically for content creators and digital marketing professionals. This dashboard integrates various web research modules to streamline your content research process, enhance content quality, and improve workflow efficiency.

""", unsafe_allow_html=True) # Quick access to tool categories with improved header st.markdown('
Research Tool Categories
', unsafe_allow_html=True) # Use 2 columns with equal width for better layout col1, col2 = st.columns([1, 1]) with col1: st.markdown("""
πŸ” Search Engine Research
Powerful search tools to understand search intent, identify content gaps, and discover high-performing content in your niche
Includes: Google SERP Search β€’ Tavily AI Search
Use cases: Keyword research, competitor analysis, content planning, identifying user questions
SERP Analysis AI-Powered
🧠 Neural Search
Advanced semantic search technology that understands concepts rather than just keywords to find truly relevant content
Includes: Metaphor Neural Search
Use cases: Finding conceptually similar articles, discovering unique content angles, competitive research
Semantic Deep Learning
""", unsafe_allow_html=True) with col2: st.markdown("""
πŸ“ˆ Trend Analysis
Comprehensive trend analysis tools that track search term popularity over time to identify seasonal patterns and emerging topics
Includes: Google Trends Researcher
Use cases: Seasonal content planning, topic validation, identifying rising trends, content calendar optimization
Time Series Forecasting
πŸ•ΈοΈ Web Crawling & Analysis
Powerful web extraction tools that gather and structure content from websites for in-depth analysis and insights
Includes: Async Web Crawler β€’ Firecrawl Web Crawler β€’ Website Analyzer
Use cases: Content auditing, competitor analysis, data extraction, market research, content aggregation
Content Extraction Data Analysis
""", unsafe_allow_html=True) # Featured workflow with improved header st.markdown('
Featured Research Workflow
', unsafe_allow_html=True) st.markdown("""
Comprehensive Topic Research Workflow

Follow this proven research workflow to develop comprehensive, data-driven content that resonates with your audience and performs well in search.

1
Initial Exploration
Use Google SERP Search to understand the search landscape, identify user intent, and discover what content currently ranks well. Analyze People Also Ask questions to identify key user concerns.
2
In-depth Research
Use Tavily AI Search for deeper research on identified subtopics. The AI-powered search provides more contextual information and helps uncover expert insights that might be missed in traditional searches.
3
Competitive Analysis
Use Metaphor Neural Search to find conceptually similar content from competitors. Analyze their approach, identify content gaps, and discover unique angles that differentiate your content.
4
Trend Validation
Use Google Trends Researcher to verify topic popularity, identify seasonal patterns, and discover related trending topics. This ensures your content is timely and aligned with current audience interests.
5
Content Extraction
Use Web Crawling tools to extract specific content from top-performing pages for detailed analysis. This helps identify content structure, depth, and formatting approaches that resonate with your audience.
""", unsafe_allow_html=True) def display_search_tools(): st.markdown('
Search Engine Research Tools
', unsafe_allow_html=True) # Google SERP Search st.markdown('
Google SERP Search
', unsafe_allow_html=True) st.markdown("""
Google SERP Search
Retrieves organic search results, People Also Ask questions, and related searches
Best for: Initial topic research, understanding search intent, and identifying content gaps
Key features: Comprehensive search results with structured data extraction
""", unsafe_allow_html=True) # Input form for Google SERP Search with st.form("google_serp_search_form"): search_query = st.text_input("Enter your search query") col1, col2 = st.columns(2) with col1: num_results = st.slider("Number of results", 5, 30, 10) with col2: include_paa = st.checkbox("Include People Also Ask", value=True) submitted = st.form_submit_button("Search") if submitted and search_query: try: with st.spinner("Searching Google SERP..."): # Import the actual module from ai_web_researcher.google_serp_search import google_search # Call the actual implementation results = google_search(search_query) # Display the results if results: display_google_serp_results(results) else: st.error("No results found. Please try a different query.") except Exception as e: st.error(f"Error performing Google SERP search: {str(e)}") st.info("Please check your API configuration in the .env file.") st.info("Required API: SERPER_API_KEY for Google SERP Search") display_google_serp_results(None) # Tavily AI Search st.markdown('
Tavily AI Search
', unsafe_allow_html=True) st.markdown("""
Tavily AI Search
Advanced AI-powered search with semantic understanding
Best for: In-depth research requiring contextual understanding
Key features: Provides direct answers to questions and follow-up question suggestions
""", unsafe_allow_html=True) # Input form for Tavily AI Search with st.form("tavily_ai_search_form"): search_query = st.text_input("Enter your search query or question") search_depth = st.select_slider("Search depth", options=["basic", "medium", "deep"], value="medium") submitted = st.form_submit_button("Search with Tavily AI") if submitted and search_query: try: with st.spinner("Searching with Tavily AI..."): # Import the actual module from ai_web_researcher.tavily_ai_search import do_tavily_ai_search # Call the actual implementation results = do_tavily_ai_search(search_query, search_depth=search_depth) # Display the results if results: display_tavily_results(results) else: st.error("No results found. Please try a different query.") except Exception as e: st.error(f"Error performing Tavily AI search: {str(e)}") st.info("Please check your API configuration in the .env file.") st.info("Required API: TAVILY_API_KEY for Tavily AI Search") display_tavily_results(None) def display_neural_search(): st.markdown('
Neural Search Tools
', unsafe_allow_html=True) # Metaphor Neural Search st.markdown('
Metaphor Neural Search
', unsafe_allow_html=True) st.markdown("""
Metaphor Neural Search
Semantic search technology for finding related content
Best for: Discovering content based on conceptual similarity rather than keyword matching
Key features: Find similar articles, competitor analysis, and content inspiration
""", unsafe_allow_html=True) # Input form for Metaphor Neural Search with st.form("metaphor_search_form"): st.markdown("**Search by keyword or find similar content to a URL**") search_type = st.radio("Search type", ["Keyword Search", "Similar Content Search"]) if search_type == "Keyword Search": search_query = st.text_input("Enter your search query") url_input = "" else: search_query = "" url_input = st.text_input("Enter a URL to find similar content") num_results = st.slider("Number of results", 3, 20, 5) submitted = st.form_submit_button("Search with Metaphor") if submitted and (search_query or url_input): try: with st.spinner("Searching with Metaphor Neural Search..."): # Import the actual module from ai_web_researcher.metaphor_basic_neural_web_search import metaphor_search_articles, metaphor_find_similar # Call the actual implementation if search_query: results = metaphor_search_articles(search_query, num_results=num_results) else: results = metaphor_find_similar(url_input, num_results=num_results) # Display the results if results: display_metaphor_results(results) else: st.error("No results found. Please try a different query.") except Exception as e: st.error(f"Error performing Metaphor Neural search: {str(e)}") st.info("Please check your API configuration in the .env file.") st.info("Required API: METAPHOR_API_KEY for Metaphor Neural Search") display_metaphor_results(None) def display_trend_analysis(): st.markdown('
Trend Analysis Tools
', unsafe_allow_html=True) # Google Trends Researcher st.markdown('
Google Trends Researcher
', unsafe_allow_html=True) st.markdown("""
Google Trends Researcher
Analyze search term popularity and related queries
Best for: Content planning, trend forecasting, and seasonal content optimization
Key features: Interest over time charts, related queries, and regional interest data
""", unsafe_allow_html=True) # Input form for Google Trends Researcher with st.form("google_trends_form"): search_terms = st.text_area("Enter search terms (one per line)") col1, col2 = st.columns(2) with col1: time_frame = st.select_slider("Time range", options=["past_hour", "past_day", "past_week", "past_month", "past_90_days", "past_12_months", "past_5_years"], value="past_12_months") with col2: geo = st.text_input("Geographic region (ISO country code, e.g., 'US')", value="US") submitted = st.form_submit_button("Analyze Trends") if submitted and search_terms: try: with st.spinner("Analyzing Google Trends..."): # Import the actual module from ai_web_researcher.google_trends_researcher import do_google_trends_analysis # Call the actual implementation search_terms_list = [term.strip() for term in search_terms.split('\n') if term.strip()] results = do_google_trends_analysis(search_terms_list, time_frame=time_frame, geo=geo) # Display the results if results: display_google_trends_results(results) else: st.error("No trend data found. Please try different search terms.") except Exception as e: st.error(f"Error analyzing Google Trends: {str(e)}") st.info("Google Trends analysis doesn't require an API key, but there might be rate limiting or network issues.") display_google_trends_results(None) def display_web_crawling(): st.markdown('
Web Crawling & Analysis Tools
', unsafe_allow_html=True) # Create tabs for different crawling tools tab1, tab2, tab3 = st.tabs(["Firecrawl Web Crawler", "Website Analyzer", "Async Web Crawler"]) with tab1: st.markdown("""
Firecrawl Web Crawler
Extract structured content from websites
Best for: Content extraction, competitor analysis, and website auditing
Key features: Extracts titles, descriptions, headings, and content from web pages
""", unsafe_allow_html=True) # Input form for Firecrawl Web Crawler with st.form("firecrawl_form"): website_url = st.text_input("Enter website URL") depth = st.slider("Crawl depth", 1, 5, 1) max_pages = st.slider("Maximum pages", 1, 50, 10) submitted = st.form_submit_button("Crawl Website") if submitted and website_url: try: with st.spinner("Crawling website..."): # Import the actual module from ai_web_researcher.firecrawl_web_crawler import scrape_website # Call the actual implementation results = scrape_website(website_url, depth=depth, max_pages=max_pages) # Display the results if results: display_crawler_results(results) else: st.error("No crawler results found. Please try a different URL.") except Exception as e: st.error(f"Error crawling website: {str(e)}") st.info("Please check your API configuration in the .env file.") st.info("Required API: FIRECRAWL_API_KEY for Web Crawler") display_crawler_results(None) with tab2: st.markdown("""
Website Analyzer
Analyze website content and structure
Best for: Content analysis, SEO auditing, and competitor research
Key features: Content analysis, keyword extraction, and readability metrics
""", unsafe_allow_html=True) # Input form for Website Analyzer with st.form("website_analyzer_form"): website_url = st.text_input("Enter website URL") analyze_type = st.selectbox("Analysis type", ["Basic Analysis", "SEO Analysis", "Content Analysis", "Competitor Analysis"]) submitted = st.form_submit_button("Analyze Website") if submitted and website_url: st.info("Website Analyzer is coming soon. This feature is under development.") with tab3: st.markdown("""
Async Web Crawler
High-performance asynchronous web crawler
Best for: Large-scale crawling, data extraction, and content aggregation
Key features: Fast, efficient crawling with customizable extraction rules
""", unsafe_allow_html=True) # Input form for Async Web Crawler with st.form("async_crawler_form"): website_url = st.text_input("Enter website URL") max_urls = st.slider("Maximum URLs to crawl", 10, 100, 30) submitted = st.form_submit_button("Start Crawling") if submitted and website_url: st.info("Async Web Crawler is coming soon. This feature is under development.") def display_academic_research(): st.markdown('
Academic Research Tools
', unsafe_allow_html=True) # ArXiv Search Section st.markdown('
ArXiv Scholarly Search
', unsafe_allow_html=True) # Search Parameters search_col1, search_col2 = st.columns([2, 1]) with search_col1: search_query = st.text_input("πŸ” Enter research topic or keywords", key="arxiv_search") with search_col2: max_results = st.number_input("Maximum Results", min_value=1, max_value=50, value=10) # Search Button if st.button("πŸ”Ž Search ArXiv", key="arxiv_search_button"): if search_query: with st.spinner("Searching ArXiv database..."): try: # Import arxiv search function from ai_web_researcher.arxiv_schlorly_research import fetch_arxiv_data, create_dataframe # Fetch results results = fetch_arxiv_data(search_query, max_results) if results: # Create DataFrame df = create_dataframe(results, ["Title", "Published Date", "ArXiv ID", "Summary", "PDF URL"]) # Display results in an expander with st.expander("πŸ“š Search Results", expanded=True): # Display each paper with options to view abstract and download for idx, row in df.iterrows(): st.markdown(f"### {row['Title']}") st.markdown(f"*Published: {row['Published Date']}*") # Create columns for buttons btn_col1, btn_col2, btn_col3 = st.columns([1, 1, 1]) with btn_col1: if st.button(f"πŸ“„ View Abstract #{idx}"): st.markdown(f"**Abstract:**\n{row['Summary']}") with btn_col2: st.markdown(f"[πŸ“₯ Download PDF]({row['PDF URL']})") if st.button(f"πŸ“ Summarize #{idx}"): with st.spinner("Generating summary..."): try: from ai_web_researcher.gpt_summarize_web_content import summarize_web_content summary = summarize_web_content(row['PDF URL']) if summary: st.markdown("### GPT Summary") st.markdown(summary) # Add export option for the summary st.download_button( label="πŸ“₯ Export Summary", data=summary, file_name=f"summary_{row['ArXiv ID']}.txt", mime="text/plain" ) except Exception as e: st.error(f"Error generating summary: {str(e)}") with btn_col3: if st.button(f"πŸ” Related Web Content #{idx}"): # Use Google SERP to find related content from ai_web_researcher.google_serp_search import google_search web_results = google_search(row['Title']) if web_results: st.markdown("### Related Web Content") for result in web_results['organic'][:3]: st.markdown(f"- [{result['title']}]({result['link']})\n {result['snippet']}") st.markdown("---") else: st.warning("No results found. Try modifying your search terms.") except Exception as e: st.error(f"An error occurred while searching: {str(e)}") else: st.warning("Please enter a search query.") # Research Notes Section st.markdown('
Research Notes
', unsafe_allow_html=True) # Initialize session state for notes if not exists if 'research_notes' not in st.session_state: st.session_state.research_notes = {} notes_col1, notes_col2 = st.columns([2, 1]) with notes_col1: paper_id = st.text_input("ArXiv ID or Paper Title", key="notes_paper_id") notes_content = st.text_area("Research Notes", height=200, key="notes_content") if st.button("Save Notes"): if paper_id: st.session_state.research_notes[paper_id] = notes_content st.success("Notes saved successfully!") else: st.warning("Please enter a paper identifier.") with notes_col2: st.markdown("### Saved Notes") for paper_id, notes in st.session_state.research_notes.items(): with st.expander(f"πŸ“ {paper_id}"): st.text_area("Saved Notes", value=notes, height=150, key=f"saved_{paper_id}", disabled=True) if st.button("Export Notes", key=f"export_{paper_id}"): notes_export = f"Research Notes for {paper_id}\n\n{notes}" st.download_button( label="πŸ“₯ Download Notes", data=notes_export, file_name=f"research_notes_{paper_id}.txt", mime="text/plain" ) # Citation Management Section st.markdown('
Citation Management
', unsafe_allow_html=True) # BibTeX Export st.markdown("### Export Citations") arxiv_id = st.text_input("Enter ArXiv ID for citation export") if arxiv_id and st.button("Generate BibTeX"): try: from ai_web_researcher.arxiv_schlorly_research import arxiv_bibtex bibtex = arxiv_bibtex(arxiv_id) if bibtex: st.code(bibtex, language="bibtex") st.download_button( label="πŸ“₯ Download BibTeX", data=bibtex, file_name=f"citation_{arxiv_id}.bib", mime="text/plain" ) except Exception as e: st.error(f"Error generating citation: {str(e)}") def display_research_workflows(): st.markdown('
Research Workflows
', unsafe_allow_html=True) st.markdown("""
Research workflows combine multiple research tools to provide comprehensive insights for specific content creation tasks. Select a workflow to get started.
""", unsafe_allow_html=True) # Create tabs for different workflows tab1, tab2, tab3 = st.tabs(["Topic Research", "Competitor Analysis", "Trend Discovery"]) with tab1: st.markdown("""
Comprehensive Topic Research
This workflow helps you thoroughly research a topic for content creation by combining search results, semantic understanding, and trend analysis.
""", unsafe_allow_html=True) # Input form for Topic Research workflow with st.form("topic_research_form"): topic = st.text_input("Enter your topic") include_trends = st.checkbox("Include trend analysis", value=True) include_competitors = st.checkbox("Include competitor analysis", value=True) submitted = st.form_submit_button("Start Research Workflow") if submitted and topic: st.info("Research workflows are coming soon. This feature is under development.") with tab2: st.markdown("""
Competitor Content Analysis
This workflow analyzes your competitors' content to identify gaps and opportunities for your own content strategy.
""", unsafe_allow_html=True) # Input form for Competitor Analysis workflow with st.form("competitor_analysis_form"): competitor_urls = st.text_area("Enter competitor URLs (one per line)") topic_focus = st.text_input("Topic focus (optional)") submitted = st.form_submit_button("Start Competitor Analysis") if submitted and competitor_urls: st.info("Research workflows are coming soon. This feature is under development.") with tab3: st.markdown("""
Trend Discovery & Content Planning
This workflow identifies trending topics in your niche and helps you plan content around them.
""", unsafe_allow_html=True) # Input form for Trend Discovery workflow with st.form("trend_discovery_form"): niche = st.text_input("Enter your niche or industry") time_period = st.select_slider("Time period", options=["past_week", "past_month", "past_90_days", "past_12_months"], value="past_month") submitted = st.form_submit_button("Discover Trends") if submitted and niche: st.info("Research workflows are coming soon. This feature is under development.")