Files
ALwrity/ToBeMigrated/ai_writers/ai_blog_faqs_writer/faqs_ui.py
2025-08-06 16:29:49 +05:30

312 lines
13 KiB
Python

"""
Streamlit UI for FAQ Generator
This module provides a user-friendly interface for generating FAQs from various content sources.
"""
import streamlit as st
from pathlib import Path
from typing import Optional
import json
import requests
from bs4 import BeautifulSoup
import logging
import pyperclip
from .faqs_generator_blog import FAQGenerator, FAQConfig, TargetAudience, FAQStyle, SearchDepth
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def copy_to_clipboard(text: str) -> None:
"""Copy text to clipboard and show success message."""
try:
pyperclip.copy(text)
st.success("Copied to clipboard!")
except Exception as e:
st.error(f"Failed to copy to clipboard: {str(e)}")
def fetch_url_content(url):
"""Fetch and extract content from a URL."""
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Remove script and style elements
for script in soup(["script", "style"]):
script.decompose()
# Get text
text = soup.get_text()
# Break into lines and remove leading and trailing space
lines = (line.strip() for line in text.splitlines())
# Break multi-headlines into a line each
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
# Drop blank lines
text = '\n'.join(chunk for chunk in chunks if chunk)
return text
except Exception as e:
st.error(f"Error fetching URL content: {str(e)}")
return None
def main():
st.title("FAQ Generator")
st.markdown("Generate comprehensive FAQs from your content with research integration.")
# Initialize session state variables if they don't exist
if 'search_queries' not in st.session_state:
st.session_state.search_queries = []
if 'selected_queries' not in st.session_state:
st.session_state.selected_queries = []
if 'research_completed' not in st.session_state:
st.session_state.research_completed = False
if 'research_results' not in st.session_state:
st.session_state.research_results = {}
if 'faq_config' not in st.session_state:
st.session_state.faq_config = None
if 'generator' not in st.session_state:
st.session_state.generator = FAQGenerator()
if 'generated_faqs' not in st.session_state:
st.session_state.generated_faqs = None
if 'output_format' not in st.session_state:
st.session_state.output_format = "Preview"
# Sidebar for configuration
with st.sidebar:
st.header("Configuration")
# Basic settings
num_faqs = st.slider("Number of FAQs", 1, 20, 5)
target_audience = st.selectbox(
"Target Audience",
[audience.value for audience in TargetAudience]
)
faq_style = st.selectbox(
"FAQ Style",
[style.value for style in FAQStyle]
)
# Advanced settings
with st.expander("Advanced Settings"):
include_emojis = st.checkbox("Include Emojis", value=True)
include_code_examples = st.checkbox("Include Code Examples", value=True)
include_references = st.checkbox("Include References", value=True)
search_depth = st.selectbox(
"Search Depth",
[depth.value for depth in SearchDepth]
)
time_range = st.selectbox(
"Time Range",
["last_month", "last_6_months", "last_year", "all_time"]
)
language = st.text_input("Language", value="English")
# Main content area
content_type = st.radio(
"Content Source",
["Direct Input", "File Upload", "URL"]
)
content = ""
if content_type == "Direct Input":
content = st.text_area("Enter your content", height=300)
elif content_type == "URL":
url = st.text_input("Enter URL")
if url:
content = fetch_url_content(url)
if content:
st.text_area("Extracted Content", content, height=300)
# Step 1: Generate search queries
if content and not st.session_state.search_queries:
if st.button("Generate Search Queries"):
with st.spinner("Generating search queries..."):
search_queries = st.session_state.generator.generate_search_queries(content)
if search_queries:
st.session_state.search_queries = search_queries
st.session_state.selected_queries = [] # Reset selected queries
st.session_state.research_completed = False # Reset research status
st.session_state.research_results = {} # Reset research results
st.session_state.faq_config = None # Reset config
st.session_state.generated_faqs = None # Reset generated FAQs
st.success("Search queries generated successfully!")
# Step 2: Display and select search queries
if st.session_state.search_queries:
st.subheader("Select Search Queries")
st.info("Select the queries you want to use for web research. You can select multiple queries.")
# Create checkboxes for each search query
selected_queries = []
for query in st.session_state.search_queries:
if st.checkbox(query, key=f"query_{query}", value=query in st.session_state.selected_queries):
selected_queries.append(query)
# Update selected queries in session state
st.session_state.selected_queries = selected_queries
# Step 3: Do web research
if st.session_state.selected_queries and not st.session_state.research_completed:
if st.button("Do Web Research"):
try:
# Create config with selected queries
config = FAQConfig(
num_faqs=num_faqs,
target_audience=TargetAudience(target_audience),
faq_style=FAQStyle(faq_style),
include_emojis=include_emojis,
include_code_examples=include_code_examples,
include_references=include_references,
search_depth=SearchDepth(search_depth),
time_range=time_range,
language=language,
selected_search_queries=selected_queries
)
# Store config in session state
st.session_state.faq_config = config
# Update generator with config
st.session_state.generator.config = config
# Do research
with st.spinner("Conducting web research..."):
research_results = st.session_state.generator._conduct_research(content)
st.session_state.research_completed = True
st.session_state.research_results = research_results
st.success("Web research completed successfully!")
# Display research results
st.subheader("Research Results")
for query, results in research_results.items():
with st.expander(f"Results for: {query}"):
if isinstance(results, dict):
st.json(results)
else:
st.text(results)
except Exception as e:
st.error(f"Error during web research: {str(e)}")
st.error("Please try again with different search queries or adjust the search depth.")
# Step 4: Generate FAQs
if st.session_state.research_completed and st.session_state.research_results and st.session_state.faq_config:
if st.button("Generate FAQs"):
try:
# Update generator with stored config
st.session_state.generator.config = st.session_state.faq_config
# Generate FAQs
with st.spinner("Generating FAQs..."):
logger.info("Starting FAQ generation...")
faqs = st.session_state.generator.generate_faqs(content)
logger.info(f"Generated {len(faqs) if faqs else 0} FAQs")
if not faqs:
st.error("No FAQs were generated. Please try again.")
return
st.session_state.generated_faqs = faqs
st.success("FAQs generated successfully!")
except Exception as e:
logger.error(f"Error generating FAQs: {str(e)}")
st.error(f"Error generating FAQs: {str(e)}")
st.error("Please try again or adjust your settings.")
# Display generated FAQs if they exist
if st.session_state.generated_faqs:
st.subheader("Generated FAQs")
# Output format selection
output_format = st.radio(
"Output Format",
["Preview", "Markdown", "HTML", "JSON"],
key="output_format"
)
# Create columns for copy and download buttons
col1, col2 = st.columns(2)
if output_format == "Preview":
# Create a formatted text for copying
preview_text = ""
for i, faq in enumerate(st.session_state.generated_faqs, 1):
preview_text += f"{i}. {faq.question}\n"
preview_text += f"{faq.answer}\n\n"
if faq.code_example:
preview_text += f"Code Example:\n{faq.code_example}\n\n"
if faq.references:
preview_text += "References:\n"
for ref in faq.references:
preview_text += f"- {ref['source']}\n"
preview_text += "\n"
with col1:
if st.button("Copy to Clipboard", key="copy_preview"):
copy_to_clipboard(preview_text)
# Display the FAQs
for i, faq in enumerate(st.session_state.generated_faqs, 1):
with st.expander(f"{i}. {faq.question}"):
st.markdown(faq.answer)
if faq.code_example:
st.code(faq.code_example)
if faq.references:
st.markdown("**References:**")
for ref in faq.references:
st.markdown(f"- {ref['source']}")
elif output_format == "Markdown":
markdown_output = st.session_state.generator.to_markdown()
st.code(markdown_output, language="markdown")
with col1:
if st.button("Copy to Clipboard", key="copy_markdown"):
copy_to_clipboard(markdown_output)
with col2:
st.download_button(
"Download Markdown",
markdown_output,
file_name="faqs.md",
mime="text/markdown"
)
elif output_format == "HTML":
html_output = st.session_state.generator.to_html()
st.code(html_output, language="html")
with col1:
if st.button("Copy to Clipboard", key="copy_html"):
copy_to_clipboard(html_output)
with col2:
st.download_button(
"Download HTML",
html_output,
file_name="faqs.html",
mime="text/html"
)
elif output_format == "JSON":
json_output = json.dumps([faq.__dict__ for faq in st.session_state.generated_faqs], indent=2)
st.code(json_output, language="json")
with col1:
if st.button("Copy to Clipboard", key="copy_json"):
copy_to_clipboard(json_output)
with col2:
st.download_button(
"Download JSON",
json_output,
file_name="faqs.json",
mime="application/json"
)
if __name__ == "__main__":
main()