Files
ALwrity/lib/alwrity_ui/alwrity_researcher/dashboard.py
2025-06-30 07:49:48 +05:30

729 lines
34 KiB
Python

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("""
<style>
.main-header {
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
}
.category-header {
font-size: 20px;
font-weight: bold;
margin: 15px 0;
color: #0066cc;
}
/* Make the dashboard responsive */
.stTabs [data-baseweb="tab-list"] {
gap: 2px;
flex-wrap: wrap;
}
.stTabs [data-baseweb="tab"] {
white-space: pre-wrap;
min-width: fit-content;
font-size: 14px;
padding: 8px 16px;
}
/* Adjust container width */
.block-container {
max-width: 95% !important;
padding: 1rem 1rem 10rem !important;
}
/* Additional styling for better visibility */
.stApp {
background-color: #f8f9fa;
}
.stTabs [data-baseweb="tab"] [data-testid="stMarkdownContainer"] p {
font-size: 14px !important;
margin-bottom: 0px !important;
}
.stTabs [data-baseweb="tab-list"] button {
background-color: #ffffff;
border: 1px solid #e9ecef;
border-radius: 4px;
margin: 2px;
}
.stTabs [data-baseweb="tab-list"] button[aria-selected="true"] {
background-color: #e7f1ff;
border-color: #b8daff;
}
</style>
""", 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('<div class="main-nav-header">AI Web Researcher</div>', 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('<div class="main-header">AI Web Researcher Dashboard</div>', unsafe_allow_html=True)
# Introduction with better formatting
st.markdown("""
<div class="intro-container">
<p class="intro-text">Welcome to the <span class="intro-highlight">AI Web Researcher Dashboard</span>, 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.</p>
</div>
""", unsafe_allow_html=True)
# Quick access to tool categories with improved header
st.markdown('<div class="category-header">Research Tool Categories</div>', unsafe_allow_html=True)
# Use 2 columns with equal width for better layout
col1, col2 = st.columns([1, 1])
with col1:
st.markdown("""
<div class="tool-card">
<div class="tool-title">🔍 Search Engine Research</div>
<div class="tool-description">Powerful search tools to understand search intent, identify content gaps, and discover high-performing content in your niche</div>
<div class="tool-features"><b>Includes:</b> Google SERP Search • Tavily AI Search</div>
<div class="tool-features"><b>Use cases:</b> Keyword research, competitor analysis, content planning, identifying user questions</div>
<div style="margin-top: 12px;">
<span class="tool-badge">SERP Analysis</span>
<span class="tool-badge ai-powered">AI-Powered</span>
</div>
</div>
<div class="tool-card">
<div class="tool-title">🧠 Neural Search</div>
<div class="tool-description">Advanced semantic search technology that understands concepts rather than just keywords to find truly relevant content</div>
<div class="tool-features"><b>Includes:</b> Metaphor Neural Search</div>
<div class="tool-features"><b>Use cases:</b> Finding conceptually similar articles, discovering unique content angles, competitive research</div>
<div style="margin-top: 12px;">
<span class="tool-badge semantic">Semantic</span>
<span class="tool-badge deep-learning">Deep Learning</span>
</div>
</div>
""", unsafe_allow_html=True)
with col2:
st.markdown("""
<div class="tool-card">
<div class="tool-title">📈 Trend Analysis</div>
<div class="tool-description">Comprehensive trend analysis tools that track search term popularity over time to identify seasonal patterns and emerging topics</div>
<div class="tool-features"><b>Includes:</b> Google Trends Researcher</div>
<div class="tool-features"><b>Use cases:</b> Seasonal content planning, topic validation, identifying rising trends, content calendar optimization</div>
<div style="margin-top: 12px;">
<span class="tool-badge time-series">Time Series</span>
<span class="tool-badge forecasting">Forecasting</span>
</div>
</div>
<div class="tool-card">
<div class="tool-title">🕸️ Web Crawling & Analysis</div>
<div class="tool-description">Powerful web extraction tools that gather and structure content from websites for in-depth analysis and insights</div>
<div class="tool-features"><b>Includes:</b> Async Web Crawler • Firecrawl Web Crawler • Website Analyzer</div>
<div class="tool-features"><b>Use cases:</b> Content auditing, competitor analysis, data extraction, market research, content aggregation</div>
<div style="margin-top: 12px;">
<span class="tool-badge content-extraction">Content Extraction</span>
<span class="tool-badge data-analysis">Data Analysis</span>
</div>
</div>
""", unsafe_allow_html=True)
# Featured workflow with improved header
st.markdown('<div class="category-header">Featured Research Workflow</div>', unsafe_allow_html=True)
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Comprehensive Topic Research Workflow</div>
<p style="color: #4b5563; margin-bottom: 1.25rem;">Follow this proven research workflow to develop comprehensive, data-driven content that resonates with your audience and performs well in search.</p>
<div class="workflow-step-container">
<div class="workflow-step-number">1</div>
<div class="workflow-step-content">
<div class="step-title">Initial Exploration</div>
<div class="workflow-step-description">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.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">2</div>
<div class="workflow-step-content">
<div class="step-title">In-depth Research</div>
<div class="workflow-step-description">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.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">3</div>
<div class="workflow-step-content">
<div class="step-title">Competitive Analysis</div>
<div class="workflow-step-description">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.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">4</div>
<div class="workflow-step-content">
<div class="step-title">Trend Validation</div>
<div class="workflow-step-description">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.</div>
</div>
</div>
<div class="workflow-step-container">
<div class="workflow-step-number">5</div>
<div class="workflow-step-content">
<div class="step-title">Content Extraction</div>
<div class="workflow-step-description">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.</div>
</div>
</div>
</div>
""", unsafe_allow_html=True)
def display_search_tools():
st.markdown('<div class="main-header">Search Engine Research Tools</div>', unsafe_allow_html=True)
# Google SERP Search
st.markdown('<div class="category-header">Google SERP Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Google SERP Search</div>
<div class="tool-description">Retrieves organic search results, People Also Ask questions, and related searches</div>
<div class="tool-features">
<b>Best for:</b> Initial topic research, understanding search intent, and identifying content gaps<br>
<b>Key features:</b> Comprehensive search results with structured data extraction
</div>
</div>
""", 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('<div class="category-header">Tavily AI Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Tavily AI Search</div>
<div class="tool-description">Advanced AI-powered search with semantic understanding</div>
<div class="tool-features">
<b>Best for:</b> In-depth research requiring contextual understanding<br>
<b>Key features:</b> Provides direct answers to questions and follow-up question suggestions
</div>
</div>
""", 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('<div class="main-header">Neural Search Tools</div>', unsafe_allow_html=True)
# Metaphor Neural Search
st.markdown('<div class="category-header">Metaphor Neural Search</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Metaphor Neural Search</div>
<div class="tool-description">Semantic search technology for finding related content</div>
<div class="tool-features">
<b>Best for:</b> Discovering content based on conceptual similarity rather than keyword matching<br>
<b>Key features:</b> Find similar articles, competitor analysis, and content inspiration
</div>
</div>
""", 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('<div class="main-header">Trend Analysis Tools</div>', unsafe_allow_html=True)
# Google Trends Researcher
st.markdown('<div class="category-header">Google Trends Researcher</div>', unsafe_allow_html=True)
st.markdown("""
<div class="tool-card">
<div class="tool-title">Google Trends Researcher</div>
<div class="tool-description">Analyze search term popularity and related queries</div>
<div class="tool-features">
<b>Best for:</b> Content planning, trend forecasting, and seasonal content optimization<br>
<b>Key features:</b> Interest over time charts, related queries, and regional interest data
</div>
</div>
""", 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('<div class="main-header">Web Crawling & Analysis Tools</div>', 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("""
<div class="tool-card">
<div class="tool-title">Firecrawl Web Crawler</div>
<div class="tool-description">Extract structured content from websites</div>
<div class="tool-features">
<b>Best for:</b> Content extraction, competitor analysis, and website auditing<br>
<b>Key features:</b> Extracts titles, descriptions, headings, and content from web pages
</div>
</div>
""", 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("""
<div class="tool-card">
<div class="tool-title">Website Analyzer</div>
<div class="tool-description">Analyze website content and structure</div>
<div class="tool-features">
<b>Best for:</b> Content analysis, SEO auditing, and competitor research<br>
<b>Key features:</b> Content analysis, keyword extraction, and readability metrics
</div>
</div>
""", 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("""
<div class="tool-card">
<div class="tool-title">Async Web Crawler</div>
<div class="tool-description">High-performance asynchronous web crawler</div>
<div class="tool-features">
<b>Best for:</b> Large-scale crawling, data extraction, and content aggregation<br>
<b>Key features:</b> Fast, efficient crawling with customizable extraction rules
</div>
</div>
""", 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('<div class="main-header">Academic Research Tools</div>', unsafe_allow_html=True)
# ArXiv Search Section
st.markdown('<div class="category-header">ArXiv Scholarly Search</div>', 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('<div class="category-header">Research Notes</div>', 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('<div class="category-header">Citation Management</div>', 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('<div class="main-header">Research Workflows</div>', unsafe_allow_html=True)
st.markdown("""
<div class="workflow-description">
Research workflows combine multiple research tools to provide comprehensive insights for specific content creation tasks.
Select a workflow to get started.
</div>
""", unsafe_allow_html=True)
# Create tabs for different workflows
tab1, tab2, tab3 = st.tabs(["Topic Research", "Competitor Analysis", "Trend Discovery"])
with tab1:
st.markdown("""
<div class="workflow-card">
<div class="workflow-title">Comprehensive Topic Research</div>
<div class="workflow-description">
This workflow helps you thoroughly research a topic for content creation by combining search results,
semantic understanding, and trend analysis.
</div>
</div>
""", 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("""
<div class="workflow-card">
<div class="workflow-title">Competitor Content Analysis</div>
<div class="workflow-description">
This workflow analyzes your competitors' content to identify gaps and opportunities for your own content strategy.
</div>
</div>
""", 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("""
<div class="workflow-card">
<div class="workflow-title">Trend Discovery & Content Planning</div>
<div class="workflow-description">
This workflow identifies trending topics in your niche and helps you plan content around them.
</div>
</div>
""", 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.")