""" 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()