import streamlit as st import pandas as pd import requests import json import base64 import plotly.express as px import plotly.graph_objects as go import os from io import BytesIO from datetime import datetime # Set page configuration st.set_page_config( page_title="News Summarization & Analysis", page_icon="📰", layout="wide", initial_sidebar_state="expanded" ) # API endpoint (Flask backend) API_URL = "http://0.0.0.0:8000" def get_company_news(company_name): """Fetch news articles for a given company via API""" try: response = requests.get(f"{API_URL}/news/{company_name}") if response.status_code == 200: return response.json() else: st.error(f"Error fetching news: {response.text}") return None except Exception as e: st.error(f"API connection error: {str(e)}") return None def get_analysis(company_name, articles): """Get sentiment analysis and comparative analysis via API""" try: response = requests.post( f"{API_URL}/analyze", json={ "company": company_name, "articles": articles } ) if response.status_code == 200: return response.json() else: st.error(f"Error analyzing content: {response.text}") return None except Exception as e: st.error(f"API connection error: {str(e)}") return None def get_tts(text, language='hi'): """Get TTS audio in the specified language via API""" try: response = requests.post( f"{API_URL}/tts", json={ "text": text, "language": language } ) if response.status_code == 200: return response.content, language else: st.error(f"Error generating speech: {response.text}") return None, language except Exception as e: st.error(f"API connection error: {str(e)}") return None, language def create_audio_player(audio_bytes): """Create an HTML audio player for the TTS audio""" audio_base64 = base64.b64encode(audio_bytes).decode() audio_html = f""" """ return audio_html def display_article_details(articles): """Display detailed information about each article in a card layout""" st.markdown(""" """, unsafe_allow_html=True) cols = st.columns(1) for i, article in enumerate(articles): sentiment = article['Sentiment'] sentiment_class = "" tag_class = "" if sentiment == "Positive": sentiment_class = "article-positive" tag_class = "sentiment-positive" elif sentiment == "Negative": sentiment_class = "article-negative" tag_class = "sentiment-negative" else: sentiment_class = "article-neutral" tag_class = "sentiment-neutral" article_html = f"""
{article['Title']}
Source: {article.get('Source', 'Unknown')} | Date: {article.get('Date', 'N/A')}
{article['Summary']}
{sentiment}
""" # Add topics as tags if 'Topics' in article and article['Topics']: article_html += '
' for topic in article['Topics']: article_html += f'{topic}' article_html += '
' article_html += f"""
Read original article →
""" cols[0].markdown(article_html, unsafe_allow_html=True) def display_sentiment_distribution(analysis): """Display sentiment distribution chart with enhanced styling""" if 'Comparative Sentiment Score' in analysis and 'Sentiment Distribution' in analysis['Comparative Sentiment Score']: dist = analysis['Comparative Sentiment Score']['Sentiment Distribution'] data = { 'Sentiment': list(dist.keys()), 'Count': list(dist.values()) } df = pd.DataFrame(data) # Create color map color_map = { 'Positive': '#4CAF50', 'Negative': '#F44336', 'Neutral': '#9E9E9E' } # Create a card container for the chart st.markdown("""

Sentiment Distribution

""", unsafe_allow_html=True) # Create pie chart for sentiment distribution labels = list(dist.keys()) values = list(dist.values()) colors = [color_map[label] for label in labels] # Create two columns for different chart types col1, col2 = st.columns(2) with col1: # Bar chart fig_bar = px.bar( df, x='Sentiment', y='Count', color='Sentiment', color_discrete_map=color_map, title="Sentiment Distribution (Bar Chart)" ) fig_bar.update_layout( plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(size=14), margin=dict(l=20, r=20, t=40, b=20), height=350 ) st.plotly_chart(fig_bar, use_container_width=True) with col2: # Pie chart fig_pie = go.Figure(data=[go.Pie( labels=labels, values=values, marker=dict(colors=colors), textinfo='percent+label', hole=.4 )]) fig_pie.update_layout( title_text="Sentiment Distribution (Pie Chart)", annotations=[dict(text='Sentiment', x=0.5, y=0.5, font_size=14, showarrow=False)], plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(size=14), margin=dict(l=20, r=20, t=40, b=20), height=350 ) st.plotly_chart(fig_pie, use_container_width=True) # Add a summary of the sentiment distribution total = sum(values) if total > 0: percentages = {label: (count/total*100) for label, count in zip(labels, values)} # Create a summary card summary_html = """

Summary

""" for label in labels: if label in percentages: color = color_map[label] summary_html += f'{label}: {percentages[label]:.1f}% | ' summary_html = summary_html.rstrip(' | ') + '

' st.markdown(summary_html, unsafe_allow_html=True) def display_topic_analysis(analysis): """Display topic analysis visualization""" if 'Comparative Sentiment Score' in analysis and 'Topic Overlap' in analysis['Comparative Sentiment Score']: topic_data = analysis['Comparative Sentiment Score']['Topic Overlap'] # Prepare data for visualization all_topics = set() if 'Common Topics' in topic_data: all_topics.update(topic_data['Common Topics']) for i in range(1, 11): # Check for unique topics in each article key = f"Unique Topics in Article {i}" if key in topic_data and topic_data[key]: all_topics.update(topic_data[key]) # Count topic occurrences across articles topic_counts = {} for topic in all_topics: count = 0 if 'Common Topics' in topic_data and topic in topic_data['Common Topics']: count += len(analysis['Articles']) # All articles have common topics for i in range(1, 11): key = f"Unique Topics in Article {i}" if key in topic_data and topic in topic_data[key]: count += 1 topic_counts[topic] = count # Create DataFrame and visualization topic_df = pd.DataFrame({ 'Topic': list(topic_counts.keys()), 'Occurrence': list(topic_counts.values()) }).sort_values('Occurrence', ascending=False) fig = px.bar( topic_df, x='Topic', y='Occurrence', title="Topic Distribution Across Articles", color='Occurrence', color_continuous_scale=px.colors.sequential.Viridis ) st.plotly_chart(fig, use_container_width=True) def display_comparative_analysis(analysis): """Display comparative analysis details""" if 'Comparative Sentiment Score' in analysis and 'Coverage Differences' in analysis['Comparative Sentiment Score']: differences = analysis['Comparative Sentiment Score']['Coverage Differences'] st.subheader("Comparative Analysis") for i, diff in enumerate(differences): with st.expander(f"Comparison {i+1}"): st.write(f"**Comparison**: {diff['Comparison']}") st.write(f"**Impact**: {diff['Impact']}") # Main app layout with enhanced design and better readability st.markdown("""
📰 News Summarization & Sentiment Analysis

Analyze recent news articles about any company. Get sentiment analysis, topic extraction, and multilingual text-to-speech summaries instantly in 10 different languages.

✅ Real-time News Analysis
📊 Sentiment Visualization
🔍 Topic Extraction
🎧 Multilingual Text-to-Speech
""", unsafe_allow_html=True) # Input form with enhanced styling st.markdown("""
🔍 Search for Company News
Enter a company name below to analyze its recent news coverage. Try companies like Tesla, Apple, Microsoft, Google, or Amazon.
""", unsafe_allow_html=True) with st.form("search_form"): col1, col2 = st.columns([3, 1]) with col1: company_name = st.text_input("Company Name", placeholder="Enter company name (e.g., Tesla)", label_visibility="collapsed") with col2: submit_button = st.form_submit_button("🔍 Analyze News") # Add some example buttons below the form st.markdown("""
Try analyzing news for:
Tesla
Apple
Microsoft
Google
Amazon
""", unsafe_allow_html=True) # Process form submission if submit_button and company_name: with st.spinner(f"Fetching news articles about {company_name}..."): articles_data = get_company_news(company_name) if articles_data and 'articles' in articles_data and len(articles_data['articles']) > 0: articles = articles_data['articles'] with st.spinner("Performing sentiment analysis..."): analysis_result = get_analysis(company_name, articles) if analysis_result: # Store complete analysis in session state st.session_state.analysis = analysis_result # Display summary and stats st.header(f"Analysis Results for {company_name}") # Create a nice header with company logo or icon company_icon = "🏢" # Default company icon if company_name.lower() == "tesla": company_icon = "🚗" elif company_name.lower() == "apple": company_icon = "🍎" elif company_name.lower() == "microsoft": company_icon = "💻" elif company_name.lower() == "amazon": company_icon = "📦" elif company_name.lower() == "google": company_icon = "🔍" st.markdown(f"""

{company_icon} {company_name} News Analysis

Analysis of {len(analysis_result['Articles'])} news articles | Generated on {datetime.now().strftime('%B %d, %Y')}

""", unsafe_allow_html=True) # Display visualization tabs with custom styling st.markdown(""" """, unsafe_allow_html=True) tab1, tab2, tab3, tab4 = st.tabs(["📊 Overview", "😊 Sentiment Analysis", "🔍 Topic Analysis", "📰 Article Details"]) with tab1: # Create a card-style container for the summary st.markdown("""

Executive Summary

""", unsafe_allow_html=True) summary_text = analysis_result.get("Final Sentiment Analysis", "No summary available") st.markdown(f"

{summary_text}

", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) if "Final Sentiment Analysis" in analysis_result: # Language selection for TTS language_options = { "hi": "Hindi", "en": "English", "es": "Spanish", "fr": "French", "de": "German", "ja": "Japanese", "zh-CN": "Chinese", "ru": "Russian", "ar": "Arabic", "it": "Italian" } selected_language = st.selectbox( "Select Language for Text-to-Speech", options=list(language_options.keys()), format_func=lambda x: language_options[x], index=0 # Default to Hindi ) with st.spinner(f"Generating {language_options[selected_language]} text-to-speech..."): audio_bytes, language = get_tts(analysis_result["Final Sentiment Analysis"], selected_language) if audio_bytes: st.markdown(f"""

🔊 {language_options[language]} Text-to-Speech Summary

""", unsafe_allow_html=True) st.markdown(create_audio_player(audio_bytes), unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) with tab2: st.subheader("Sentiment Distribution") display_sentiment_distribution(analysis_result) display_comparative_analysis(analysis_result) with tab3: st.subheader("Topic Analysis") display_topic_analysis(analysis_result) with tab4: st.subheader("Article Details") display_article_details(analysis_result['Articles']) # Add video download tab tab5 = st.tabs(["📹 Demo Video"])[0] with tab5: st.subheader("Record and Download Demo") if st.button("Record Demo (30s)"): with st.spinner("Recording demo video..."): try: from record_demo import record_demo record_demo() st.success("Recording completed!") # Display download button with open('demo_video.mp4', 'rb') as video_file: video_bytes = video_file.read() st.download_button( label="Download Demo Video", data=video_bytes, file_name="company_analysis_demo.mp4", mime="video/mp4" ) except Exception as e: st.error(f"Error recording video: {str(e)}") # Display JSON output option st.subheader("Raw JSON Output") with st.expander("Show JSON"): st.json(analysis_result) else: st.error("Failed to perform analysis. Please try again.") else: st.warning(f"No news articles found for {company_name}. Please try another company name.") # Footer with enhanced design and improved readability st.markdown(""" """, unsafe_allow_html=True)