import streamlit as st import pandas as pd import plotly.express as px import plotly.graph_objects as go 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 research modules (placeholder imports for now) try: from ai_web_researcher import ( google_serp_search, tavily_ai_search, metaphor_basic_neural_web_search, google_trends_researcher, firecrawl_web_crawler ) except ImportError: # For development/testing without actual modules pass def load_css(): """Load custom CSS""" css_file = Path(__file__).parent / "style.css" with open(css_file) as f: css_content = f.read() # Use session state to track if CSS has been loaded if 'css_loaded' not in st.session_state: st.session_state['css_loaded'] = False # Always apply CSS on each page load to ensure styles persist during navigation st.markdown(f"", unsafe_allow_html=True) st.session_state['css_loaded'] = True def display_google_serp_results(results): """Display Google SERP search results""" # Check if results are available if not results: st.warning("No search results available. Please try a different query or check your API configuration.") return st.markdown('
', unsafe_allow_html=True) # Display organic results st.markdown('
Search Results
', unsafe_allow_html=True) # Display actual organic results organic_results = results.get('organic', []) if organic_results: for result in organic_results: st.markdown(f"""
{result.get('title', 'No Title')}
{result.get('link', '#')}
{result.get('snippet', 'No description available.')}
""", unsafe_allow_html=True) else: st.info("No organic search results found.") # Display People Also Ask paa_results = results.get('peopleAlsoAsk', []) if paa_results: st.markdown('
People Also Ask
', unsafe_allow_html=True) for question in paa_results: st.markdown(f"""
{question.get('question', 'No Question')}
{question.get('snippet', 'No answer available.')}
""", unsafe_allow_html=True) # Display Related Searches if available related_searches = results.get('relatedSearches', []) if related_searches: st.markdown('
Related Searches
', unsafe_allow_html=True) for search in related_searches: st.markdown(f"""
{search}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) def display_tavily_results(results): """Display Tavily AI search results""" # Check if results are available if not results: st.warning("No Tavily search results available. Please try a different query or check your API configuration.") return st.markdown('
', unsafe_allow_html=True) # Display answer if available answer = results.get('answer', '') if answer: st.markdown('
Answer
', unsafe_allow_html=True) st.markdown(f"""
{answer}
""", unsafe_allow_html=True) # Display search results search_results = results.get('results', []) if search_results: st.markdown('
Search Results
', unsafe_allow_html=True) for result in search_results: st.markdown(f"""
{result.get('title', 'No Title')}
{result.get('url', '#')}
{result.get('content', 'No content available.')}
""", unsafe_allow_html=True) else: st.info("No search results found.") # Display follow-up questions if available follow_up_questions = results.get('follow_up_questions', []) if follow_up_questions: st.markdown('
Follow-up Questions
', unsafe_allow_html=True) for question in follow_up_questions: st.markdown(f"""
{question}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) def display_metaphor_results(results): """Display Metaphor Neural Search results""" # Check if results are available if not results: st.warning("No Metaphor search results available. Please try a different query or check your API configuration.") return st.markdown('
', unsafe_allow_html=True) # Display search results st.markdown('
Similar Content
', unsafe_allow_html=True) # Display actual results documents = results.get('documents', []) if documents: for doc in documents: title = doc.get('title', 'No Title') url = doc.get('url', '#') extract = doc.get('extract', 'No content available.') st.markdown(f"""
{title}
{url}
{extract}
""", unsafe_allow_html=True) else: st.info("No similar content found.") # Display summary if available summary = results.get('summary', '') if summary: st.markdown('
Content Summary
', unsafe_allow_html=True) st.markdown(f"""
{summary}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) def display_google_trends_results(results): """Display Google Trends results""" # Check if results are available if not results: st.warning("No Google Trends results available. Please try a different query or check your API configuration.") return st.markdown('
', unsafe_allow_html=True) # Display interest over time chart if available interest_over_time = results.get('interest_over_time') if interest_over_time is not None and not interest_over_time.empty: st.markdown('
Interest Over Time
', unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) st.markdown('
Search Interest Over Time
', unsafe_allow_html=True) # Convert to DataFrame if it's not already if not isinstance(interest_over_time, pd.DataFrame): interest_over_time = pd.DataFrame(interest_over_time) # Prepare data for visualization if 'date' in interest_over_time.columns: # Melt the DataFrame to get it in the right format for plotting terms = [col for col in interest_over_time.columns if col != 'date'] df = interest_over_time.melt('date', value_vars=terms, var_name='Term', value_name='Interest') # Create and display the chart fig = px.line(df, x='date', y='Interest', color='Term', title='Search Interest Over Time') st.plotly_chart(fig, use_container_width=True) else: st.error("Interest over time data is not in the expected format.") st.markdown('
', unsafe_allow_html=True) # Display related queries if available related_queries = results.get('related_queries', {}) if related_queries: st.markdown('
Related Queries
', unsafe_allow_html=True) # Display top related queries for term, queries in related_queries.items(): if 'top' in queries: st.markdown(f'
Top queries for "{term}"
', unsafe_allow_html=True) for query in queries['top'].get('query', []): st.markdown(f"""
{query}
""", unsafe_allow_html=True) if 'rising' in queries: st.markdown(f'
Rising queries for "{term}"
', unsafe_allow_html=True) for query in queries['rising'].get('query', []): st.markdown(f"""
{query}
""", unsafe_allow_html=True) # Display related topics if available related_topics = results.get('related_topics', {}) if related_topics: st.markdown('
Related Topics
', unsafe_allow_html=True) # Display top related topics for term, topics in related_topics.items(): if 'top' in topics: st.markdown(f'
Top topics for "{term}"
', unsafe_allow_html=True) for topic in topics['top'].get('topic', []): st.markdown(f"""
{topic}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) def display_crawler_results(results): """Display Web Crawler results""" # Check if results are available if not results: st.warning("No web crawler results available. Please try a different URL or check your API configuration.") return st.markdown('
', unsafe_allow_html=True) # Display crawled pages st.markdown('
Crawled Pages
', unsafe_allow_html=True) # Handle different result formats if isinstance(results, dict): # Single page result page_data = results st.markdown(f"""
{page_data.get('title', 'No Title')}
{page_data.get('url', '#')}
Title: {page_data.get('title', 'No Title')}
Description: {page_data.get('description', 'No description available.')}
Word Count: {page_data.get('word_count', 'Unknown')}
""", unsafe_allow_html=True) # Display content sections if available content = page_data.get('content', []) if content: st.markdown('
Page Content
', unsafe_allow_html=True) for section in content: if isinstance(section, dict): section_type = section.get('type', '') section_content = section.get('content', '') if section_type and section_content: st.markdown(f"""
{section_type}
{section_content}
""", unsafe_allow_html=True) elif isinstance(results, list): # Multiple pages result for page_data in results: if isinstance(page_data, dict): st.markdown(f"""
{page_data.get('title', 'No Title')}
{page_data.get('url', '#')}
Title: {page_data.get('title', 'No Title')}
Description: {page_data.get('description', 'No description available.')}
Word Count: {page_data.get('word_count', 'Unknown')}
""", unsafe_allow_html=True) # Display content structure st.markdown('
Content Structure
', unsafe_allow_html=True) # Placeholder data for chart labels = ['Blog Posts', 'Product Pages', 'Category Pages', 'About Pages', 'Contact Pages'] values = [38, 27, 18, 10, 7] fig = go.Figure(data=[go.Pie(labels=labels, values=values, hole=.3)]) fig.update_layout(title_text='Content Type Distribution') st.plotly_chart(fig, use_container_width=True) st.markdown('
', unsafe_allow_html=True) def display_analyzer_results(results): """Display Website Analyzer results""" # This is a placeholder function that will be implemented when integrated with actual modules st.markdown('
', unsafe_allow_html=True) # Display content quality metrics st.markdown('
Content Quality Metrics
', unsafe_allow_html=True) # Placeholder data for chart categories = ['Readability', 'Engagement', 'Relevance', 'Uniqueness', 'Comprehensiveness'] values = [4.2, 3.8, 4.5, 3.9, 4.1] fig = go.Figure() fig.add_trace(go.Scatterpolar( r=values, theta=categories, fill='toself', name='Content Quality' )) fig.update_layout( polar=dict( radialaxis=dict( visible=True, range=[0, 5] )), showlegend=False ) st.plotly_chart(fig, use_container_width=True) # Display SEO recommendations st.markdown('
SEO Recommendations
', unsafe_allow_html=True) # Placeholder data recommendations = [ "Improve meta descriptions for better click-through rates", "Add more internal links to related content", "Optimize images with descriptive alt text", "Improve page loading speed by optimizing images", "Add structured data markup for better search visibility" ] for recommendation in recommendations: st.markdown(f"""
{recommendation}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True)