Files
ALwrity/ToBeMigrated/alwrity_ui/content_performance_predictor_ui.py
2025-08-06 16:29:49 +05:30

684 lines
25 KiB
Python

"""
Streamlit UI for Content Performance Predictor
Interactive interface for predicting and optimizing content performance
"""
import streamlit as st
import asyncio
import json
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime, timedelta
import pandas as pd
from typing import Dict, List, Any, Optional
import logging
# Import the predictor
try:
from lib.content_performance_predictor.content_performance_predictor import (
ContentPerformancePredictor,
ContentType,
predict_content_performance
)
except ImportError:
st.error("Content Performance Predictor module not found. Please check the installation.")
logger = logging.getLogger(__name__)
class ContentPerformancePredictorUI:
"""Streamlit UI for Content Performance Predictor"""
def __init__(self):
self.predictor = None
self.initialize_predictor()
def initialize_predictor(self):
"""Initialize the predictor with error handling"""
try:
self.predictor = ContentPerformancePredictor()
except Exception as e:
st.error(f"Failed to initialize predictor: {str(e)}")
self.predictor = None
def render_main_interface(self):
"""Render the main Content Performance Predictor interface"""
st.title("🎯 Content Performance Predictor")
st.markdown("### Predict content success before you publish!")
# Create tabs for different features
tab1, tab2, tab3, tab4 = st.tabs([
"📊 Predict Performance",
"📈 Batch Analysis",
"🔧 Optimization Tools",
"📚 Performance History"
])
with tab1:
self.render_single_prediction_tab()
with tab2:
self.render_batch_analysis_tab()
with tab3:
self.render_optimization_tab()
with tab4:
self.render_history_tab()
def render_single_prediction_tab(self):
"""Render single content prediction interface"""
st.header("Single Content Analysis")
# Input section
col1, col2 = st.columns([2, 1])
with col1:
# Content input
content_input = st.text_area(
"Enter your content:",
height=200,
placeholder="Paste your content here...\n\nExample:\n🚀 Just discovered an amazing AI writing tool that's changing the game!\n\n#AIWriting #ContentCreation"
)
# Target keywords
keywords_input = st.text_input(
"Target Keywords (optional):",
placeholder="AI writing, content creation, SEO"
)
with col2:
# Content type selection
content_type = st.selectbox(
"Content Type:",
["twitter", "linkedin", "facebook", "instagram", "blog_post", "email", "youtube"],
help="Select the platform where you plan to publish"
)
# Analysis options
st.subheader("Analysis Options")
include_seo = st.checkbox("Include SEO Analysis", value=True)
include_trends = st.checkbox("Include Trend Analysis", value=True)
include_competitor = st.checkbox("Include Competitor Analysis", value=False)
# Advanced settings
with st.expander("Advanced Settings"):
target_audience = st.selectbox(
"Target Audience:",
["General", "Business", "Tech", "Marketing", "Education", "Entertainment"]
)
urgency_level = st.slider(
"Content Urgency:",
0.0, 1.0, 0.5,
help="How time-sensitive is this content?"
)
# Predict button
if st.button("🎯 Predict Performance", type="primary", use_container_width=True):
if not content_input.strip():
st.error("Please enter content to analyze")
return
# Process keywords
keywords = [k.strip() for k in keywords_input.split(",")] if keywords_input else None
# Show loading spinner
with st.spinner("Analyzing content performance..."):
# Run prediction
prediction_result = self.run_prediction(
content_input,
content_type,
keywords,
include_seo,
include_trends,
include_competitor
)
if prediction_result:
self.display_prediction_results(prediction_result)
else:
st.error("Failed to analyze content. Please try again.")
def run_prediction(
self,
content: str,
content_type: str,
keywords: Optional[List[str]],
include_seo: bool,
include_trends: bool,
include_competitor: bool
) -> Optional[Dict[str, Any]]:
"""Run the content performance prediction"""
try:
# Run async prediction
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(
predict_content_performance(
content=content,
content_type=content_type,
target_keywords=keywords
)
)
loop.close()
return result
except Exception as e:
logger.error(f"Error in prediction: {str(e)}")
st.error(f"Prediction failed: {str(e)}")
return None
def display_prediction_results(self, result: Dict[str, Any]):
"""Display the prediction results with visualizations"""
st.success("✅ Analysis Complete!")
# Overall score section
st.subheader("📊 Overall Performance Score")
col1, col2, col3 = st.columns(3)
with col1:
# Overall score gauge
score = result.get("overall_score", 0)
self.render_score_gauge(score, "Overall Score")
with col2:
# Success probability
prob = result.get("success_probability", 0) * 100
self.render_score_gauge(prob, "Success Probability")
with col3:
# Performance rating
rating = self.get_performance_rating(score)
st.metric(
"Performance Rating",
rating["label"],
help=rating["description"]
)
# Detailed scores breakdown
st.subheader("🔍 Detailed Score Breakdown")
scores = result.get("individual_scores", {})
if scores:
self.render_scores_breakdown(scores)
# Recommendations section
st.subheader("💡 Optimization Recommendations")
recommendations = result.get("recommendations", [])
if recommendations:
for i, rec in enumerate(recommendations, 1):
st.markdown(f"**{i}.** {rec}")
else:
st.info("No specific recommendations available")
# Predicted metrics
st.subheader("📊 Predicted Performance Metrics")
metrics = result.get("predicted_metrics", {})
if metrics:
self.render_predicted_metrics(metrics)
# Content analysis details
st.subheader("📝 Content Analysis Details")
analysis = result.get("content_analysis", {})
if analysis:
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Word Count", analysis.get("word_count", 0))
with col2:
st.metric("Character Count", analysis.get("character_count", 0))
with col3:
st.metric("Hashtags", analysis.get("hashtag_count", 0))
with col4:
st.metric("Readability", f"{analysis.get('readability_score', 0):.1f}")
# Export options
st.subheader("📤 Export Results")
col1, col2 = st.columns(2)
with col1:
if st.button("📄 Generate Report"):
report = self.generate_text_report(result)
st.text_area("Report:", value=report, height=200)
with col2:
if st.button("📊 Download JSON"):
json_str = json.dumps(result, indent=2)
st.download_button(
label="Download JSON",
data=json_str,
file_name=f"content_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
mime="application/json"
)
def render_score_gauge(self, score: float, title: str):
"""Render a gauge chart for scores"""
fig = go.Figure(go.Indicator(
mode = "gauge+number+delta",
value = score,
domain = {'x': [0, 1], 'y': [0, 1]},
title = {'text': title},
delta = {'reference': 50},
gauge = {
'axis': {'range': [None, 100]},
'bar': {'color': "darkblue"},
'steps': [
{'range': [0, 25], 'color': "lightgray"},
{'range': [25, 50], 'color': "yellow"},
{'range': [50, 75], 'color': "orange"},
{'range': [75, 100], 'color': "green"}],
'threshold': {
'line': {'color': "red", 'width': 4},
'thickness': 0.75,
'value': 90}}))
fig.update_layout(height=300)
st.plotly_chart(fig, use_container_width=True)
def render_scores_breakdown(self, scores: Dict[str, float]):
"""Render radar chart for score breakdown"""
categories = list(scores.keys())
values = list(scores.values())
# Close the radar chart
categories.append(categories[0])
values.append(values[0])
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=values,
theta=categories,
fill='toself',
name='Performance Scores'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 100]
)),
showlegend=True,
title="Performance Score Breakdown"
)
st.plotly_chart(fig, use_container_width=True)
# Display scores as metrics
cols = st.columns(len(scores))
for i, (category, score) in enumerate(scores.items()):
with cols[i]:
st.metric(category.title(), f"{score:.1f}")
def render_predicted_metrics(self, metrics: Dict[str, Any]):
"""Render predicted performance metrics"""
cols = st.columns(len(metrics))
for i, (metric, value) in enumerate(metrics.items()):
with cols[i]:
# Format metric name
display_name = metric.replace("predicted_", "").replace("_", " ").title()
st.metric(display_name, f"{value:,}")
def get_performance_rating(self, score: float) -> Dict[str, str]:
"""Get performance rating based on score"""
if score >= 80:
return {"label": "Excellent", "description": "High chance of success"}
elif score >= 60:
return {"label": "Good", "description": "Solid performance expected"}
elif score >= 40:
return {"label": "Average", "description": "Room for improvement"}
else:
return {"label": "Needs Work", "description": "Optimization recommended"}
def render_batch_analysis_tab(self):
"""Render batch analysis interface"""
st.header("Batch Content Analysis")
st.info("Analyze multiple pieces of content at once")
# File upload
uploaded_file = st.file_uploader(
"Upload CSV with content",
type=['csv'],
help="CSV should have columns: 'content', 'content_type', 'keywords' (optional)"
)
if uploaded_file is not None:
try:
df = pd.read_csv(uploaded_file)
# Validate required columns
required_cols = ['content', 'content_type']
missing_cols = [col for col in required_cols if col not in df.columns]
if missing_cols:
st.error(f"Missing required columns: {', '.join(missing_cols)}")
return
st.success(f"✅ Loaded {len(df)} content items")
# Preview data
with st.expander("Preview Data"):
st.dataframe(df.head())
# Analysis options
col1, col2 = st.columns(2)
with col1:
max_items = st.number_input(
"Max items to analyze:",
min_value=1,
max_value=100,
value=min(10, len(df))
)
with col2:
export_format = st.selectbox(
"Export format:",
["CSV", "JSON", "Excel"]
)
# Run batch analysis
if st.button("🚀 Run Batch Analysis", type="primary"):
with st.spinner(f"Analyzing {max_items} content items..."):
batch_df = df.head(max_items)
results = self.run_batch_analysis(batch_df)
if results:
self.display_batch_results(results)
else:
st.error("Batch analysis failed")
except Exception as e:
st.error(f"Error processing file: {str(e)}")
def run_batch_analysis(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Run batch analysis on multiple content items"""
results = []
progress = st.progress(0)
for i, row in df.iterrows():
try:
content = row['content']
content_type = row['content_type']
keywords = row.get('keywords', '').split(',') if row.get('keywords') else None
result = self.run_prediction(content, content_type, keywords, True, True, False)
if result:
result['original_content'] = content
result['content_type'] = content_type
results.append(result)
progress.progress((i + 1) / len(df))
except Exception as e:
st.warning(f"Error analyzing row {i}: {str(e)}")
continue
return results
def display_batch_results(self, results: List[Dict[str, Any]]):
"""Display batch analysis results"""
st.success(f"✅ Analyzed {len(results)} content items")
# Summary statistics
st.subheader("📊 Batch Summary")
scores = [r.get('overall_score', 0) for r in results]
avg_score = sum(scores) / len(scores) if scores else 0
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Average Score", f"{avg_score:.1f}")
with col2:
st.metric("Best Score", f"{max(scores):.1f}" if scores else "0")
with col3:
st.metric("Worst Score", f"{min(scores):.1f}" if scores else "0")
with col4:
good_content = len([s for s in scores if s >= 60])
st.metric("Good Content", f"{good_content}/{len(scores)}")
# Results table
st.subheader("📋 Detailed Results")
# Create summary DataFrame
summary_data = []
for i, result in enumerate(results):
summary_data.append({
"Content": result['original_content'][:50] + "..." if len(result['original_content']) > 50 else result['original_content'],
"Type": result['content_type'],
"Overall Score": result.get('overall_score', 0),
"Success Probability": result.get('success_probability', 0) * 100,
"Engagement": result.get('individual_scores', {}).get('engagement', 0),
"SEO": result.get('individual_scores', {}).get('seo', 0),
"Virality": result.get('individual_scores', {}).get('virality', 0)
})
summary_df = pd.DataFrame(summary_data)
st.dataframe(summary_df, use_container_width=True)
# Download results
if st.button("📥 Download Results"):
csv = summary_df.to_csv(index=False)
st.download_button(
label="Download CSV",
data=csv,
file_name=f"batch_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
def render_optimization_tab(self):
"""Render content optimization tools"""
st.header("🔧 Content Optimization Tools")
# A/B Testing section
st.subheader("🧪 A/B Content Testing")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Version A**")
content_a = st.text_area(
"Content A:",
height=150,
key="content_a",
placeholder="Enter first version of your content..."
)
with col2:
st.markdown("**Version B**")
content_b = st.text_area(
"Content B:",
height=150,
key="content_b",
placeholder="Enter second version of your content..."
)
# Common settings
content_type = st.selectbox(
"Content Type for both:",
["twitter", "linkedin", "facebook", "instagram", "blog_post", "email", "youtube"],
key="ab_content_type"
)
if st.button("⚡ Compare Versions", type="primary"):
if not content_a.strip() or not content_b.strip():
st.error("Please enter both versions of content")
return
with st.spinner("Comparing content versions..."):
result_a = self.run_prediction(content_a, content_type, None, True, True, False)
result_b = self.run_prediction(content_b, content_type, None, True, True, False)
if result_a and result_b:
self.display_ab_comparison(result_a, result_b)
# Optimization suggestions
st.subheader("💡 Optimization Suggestions")
optimization_content = st.text_area(
"Content to optimize:",
height=150,
placeholder="Enter content for optimization suggestions..."
)
if st.button("🚀 Get Suggestions") and optimization_content.strip():
with st.spinner("Generating optimization suggestions..."):
suggestions = self.generate_optimization_suggestions(optimization_content)
if suggestions:
st.success("✅ Optimization suggestions generated!")
for i, suggestion in enumerate(suggestions, 1):
st.markdown(f"**{i}.** {suggestion}")
def display_ab_comparison(self, result_a: Dict[str, Any], result_b: Dict[str, Any]):
"""Display A/B test comparison results"""
st.success("✅ A/B Comparison Complete!")
# Overall comparison
col1, col2, col3 = st.columns(3)
score_a = result_a.get('overall_score', 0)
score_b = result_b.get('overall_score', 0)
winner = "A" if score_a > score_b else "B" if score_b > score_a else "Tie"
with col1:
st.metric("Version A Score", f"{score_a:.1f}")
with col2:
st.metric("Version B Score", f"{score_b:.1f}")
with col3:
st.metric("Winner", winner, delta=f"{abs(score_a - score_b):.1f} point difference")
# Detailed comparison chart
scores_a = result_a.get('individual_scores', {})
scores_b = result_b.get('individual_scores', {})
categories = list(scores_a.keys())
values_a = list(scores_a.values())
values_b = list(scores_b.values())
# Create comparison bar chart
fig = go.Figure(data=[
go.Bar(name='Version A', x=categories, y=values_a),
go.Bar(name='Version B', x=categories, y=values_b)
])
fig.update_layout(
barmode='group',
title="Detailed Score Comparison",
yaxis_title="Score",
xaxis_title="Category"
)
st.plotly_chart(fig, use_container_width=True)
# Recommendations comparison
st.subheader("📋 Recommendations Comparison")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Version A Recommendations:**")
recs_a = result_a.get('recommendations', [])
for rec in recs_a[:5]:
st.markdown(f"{rec}")
with col2:
st.markdown("**Version B Recommendations:**")
recs_b = result_b.get('recommendations', [])
for rec in recs_b[:5]:
st.markdown(f"{rec}")
def generate_optimization_suggestions(self, content: str) -> List[str]:
"""Generate optimization suggestions for content"""
suggestions = []
# Basic content analysis
word_count = len(content.split())
char_count = len(content)
hashtag_count = content.count('#')
# Length optimization
if word_count < 10:
suggestions.append("Consider adding more detail to your content for better engagement")
elif word_count > 50:
suggestions.append("Consider shortening your content for better social media performance")
# Hashtag optimization
if hashtag_count == 0:
suggestions.append("Add relevant hashtags to increase discoverability")
elif hashtag_count > 5:
suggestions.append("Reduce the number of hashtags for better readability")
# Engagement optimization
if '?' not in content:
suggestions.append("Consider adding a question to encourage engagement")
if '!' not in content and '.' in content:
suggestions.append("Add some excitement with exclamation marks")
# Call to action
cta_words = ['click', 'share', 'comment', 'like', 'follow', 'subscribe']
has_cta = any(word in content.lower() for word in cta_words)
if not has_cta:
suggestions.append("Include a clear call-to-action (like, share, comment)")
# Emoji usage
emoji_count = len([char for char in content if ord(char) > 127])
if emoji_count == 0:
suggestions.append("Consider adding relevant emojis to make content more engaging")
return suggestions[:5] # Limit to top 5 suggestions
def render_history_tab(self):
"""Render performance history interface"""
st.header("📚 Performance History")
st.info("Performance history tracking coming soon!")
st.markdown("This feature will allow you to:")
st.markdown("• Track your content performance over time")
st.markdown("• Compare predicted vs actual performance")
st.markdown("• Identify your best-performing content patterns")
st.markdown("• Generate performance reports")
def generate_text_report(self, result: Dict[str, Any]) -> str:
"""Generate a text report of the analysis"""
report = f"""
CONTENT PERFORMANCE ANALYSIS REPORT
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
OVERALL PERFORMANCE
Overall Score: {result.get('overall_score', 0):.1f}/100
Success Probability: {result.get('success_probability', 0)*100:.1f}%
Performance Rating: {self.get_performance_rating(result.get('overall_score', 0))['label']}
DETAILED SCORES
"""
scores = result.get('individual_scores', {})
for category, score in scores.items():
report += f"{category.title()}: {score:.1f}/100\n"
report += "\nCONTENT ANALYSIS\n"
analysis = result.get('content_analysis', {})
for key, value in analysis.items():
report += f"{key.replace('_', ' ').title()}: {value}\n"
report += "\nRECOMMENDATIONS\n"
recommendations = result.get('recommendations', [])
for i, rec in enumerate(recommendations, 1):
report += f"{i}. {rec}\n"
return report
def render_content_performance_predictor():
"""Main function to render the Content Performance Predictor UI"""
ui = ContentPerformancePredictorUI()
ui.render_main_interface()
if __name__ == "__main__":
render_content_performance_predictor()