proKBD commited on
Commit
58961dd
·
verified ·
1 Parent(s): 24b279f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +265 -287
app.py CHANGED
@@ -1,435 +1,413 @@
1
  """Streamlit frontend for the News Summarization application."""
2
 
3
  import streamlit as st
4
- import requests
5
  import pandas as pd
6
  import json
7
- from config import API_BASE_URL
8
  import os
9
  import plotly.express as px
10
  import altair as alt
 
 
 
 
 
 
 
 
11
 
 
12
  st.set_page_config(
13
  page_title="News Summarization App",
14
  page_icon="📰",
15
  layout="wide"
16
  )
17
 
18
- def analyze_company(company_name):
19
- """Send analysis request to API."""
 
20
  try:
21
- response = requests.post(
22
- f"{API_BASE_URL}/api/analyze",
23
- json={"name": company_name}
24
- )
25
- if response.status_code == 200:
26
- data = response.json()
27
- # Print the response data for debugging
28
- print("API Response Data:")
29
- print(json.dumps(data, indent=2))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- # Download audio file if available
32
- if 'audio_url' in data:
33
- audio_response = requests.get(f"{API_BASE_URL}{data['audio_url']}")
34
- if audio_response.status_code == 200:
35
- data['audio_content'] = audio_response.content
36
- return data
37
- else:
38
- st.error(f"Error from API: {response.text}")
39
- return {"articles": [], "comparative_sentiment_score": {}, "final_sentiment_analysis": "", "audio_url": None}
40
  except Exception as e:
41
- st.error(f"Error analyzing company: {str(e)}")
42
- return {"articles": [], "comparative_sentiment_score": {}, "final_sentiment_analysis": "", "audio_url": None}
43
 
44
  def main():
45
  st.title("📰 News Summarization and Analysis")
46
-
47
- # Sidebar
48
- st.sidebar.header("Settings")
49
-
50
- # Replace dropdown with text input
51
- company = st.sidebar.text_input(
52
- "Enter Company Name",
53
- placeholder="e.g., Tesla, Apple, Microsoft, or any other company",
54
- help="Enter the name of any company you want to analyze"
55
- )
56
-
57
- if st.sidebar.button("Analyze") and company:
58
- if len(company.strip()) < 2:
59
  st.sidebar.error("Please enter a valid company name (at least 2 characters)")
60
  else:
61
  with st.spinner("Analyzing news articles..."):
62
- result = analyze_company(company)
63
-
64
- if result and result.get("articles"):
 
 
 
 
 
65
  # Display Articles
66
  st.header("📑 News Articles")
67
- for idx, article in enumerate(result["articles"], 1):
68
  with st.expander(f"Article {idx}: {article['title']}"):
69
- st.write("**Content:**", article.get("content", "No content available"))
70
- if "summary" in article:
71
- st.write("**Summary:**", article["summary"])
72
- st.write("**Source:**", article.get("source", "Unknown"))
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  # Enhanced sentiment display
75
  if "sentiment" in article:
76
  sentiment_col1, sentiment_col2 = st.columns(2)
77
  with sentiment_col1:
78
- st.write("**Sentiment:**", article["sentiment"])
79
- st.write("**Confidence Score:**", f"{article.get('sentiment_score', 0)*100:.1f}%")
 
 
80
 
81
  with sentiment_col2:
82
  # Display fine-grained sentiment if available
83
  if "fine_grained_sentiment" in article and article["fine_grained_sentiment"]:
 
84
  fine_grained = article["fine_grained_sentiment"]
85
  if "category" in fine_grained:
86
- st.write("**Detailed Sentiment:**", fine_grained["category"])
87
  if "confidence" in fine_grained:
88
- st.write("**Confidence:**", f"{fine_grained['confidence']*100:.1f}%")
89
 
90
  # Display sentiment indices if available
91
  if "sentiment_indices" in article and article["sentiment_indices"]:
92
- st.markdown("**Sentiment Indices:**")
93
- indices = article["sentiment_indices"]
94
-
95
- # Create columns for displaying indices
96
- idx_cols = st.columns(3)
97
-
98
- # Display positivity and negativity in first column
99
- with idx_cols[0]:
100
- if "positivity_index" in indices:
101
- st.markdown(f"**Positivity:** {indices['positivity_index']:.2f}")
102
- if "negativity_index" in indices:
103
- st.markdown(f"**Negativity:** {indices['negativity_index']:.2f}")
104
-
105
- # Display emotional intensity and controversy in second column
106
- with idx_cols[1]:
107
- if "emotional_intensity" in indices:
108
- st.markdown(f"**Emotional Intensity:** {indices['emotional_intensity']:.2f}")
109
- if "controversy_score" in indices:
110
- st.markdown(f"**Controversy:** {indices['controversy_score']:.2f}")
111
-
112
- # Display confidence and ESG in third column
113
- with idx_cols[2]:
114
- if "confidence_score" in indices:
115
- st.markdown(f"**Confidence:** {indices['confidence_score']:.2f}")
116
- if "esg_relevance" in indices:
117
- st.markdown(f"**ESG Relevance:** {indices['esg_relevance']:.2f}")
118
-
119
- # Display entities if available
120
- if "entities" in article and article["entities"]:
121
- st.markdown("**Named Entities:**")
122
- entities = article["entities"]
123
-
124
- # Organizations
125
- if "ORG" in entities and entities["ORG"]:
126
- st.write("**Organizations:**", ", ".join(entities["ORG"]))
127
-
128
- # People
129
- if "PERSON" in entities and entities["PERSON"]:
130
- st.write("**People:**", ", ".join(entities["PERSON"]))
131
-
132
- # Locations
133
- if "GPE" in entities and entities["GPE"]:
134
- st.write("**Locations:**", ", ".join(entities["GPE"]))
135
-
136
- # Money
137
- if "MONEY" in entities and entities["MONEY"]:
138
- st.write("**Financial Values:**", ", ".join(entities["MONEY"]))
139
-
140
- # Display sentiment targets if available
141
- if "sentiment_targets" in article and article["sentiment_targets"]:
142
- st.markdown("**Sentiment Targets:**")
143
- targets = article["sentiment_targets"]
144
- for target in targets:
145
- st.markdown(f"**{target['entity']}** ({target['type']}): {target['sentiment']} ({target['confidence']*100:.1f}%)")
146
  st.markdown(f"> {target['context']}")
147
  st.markdown("---")
148
 
 
149
  if "url" in article:
150
- st.write("**[Read More](%s)**" % article["url"])
151
 
152
  # Display Comparative Analysis
153
  st.header("📊 Comparative Analysis")
154
- analysis = result.get("comparative_sentiment_score", {})
155
 
156
  # Sentiment Distribution
157
  if "sentiment_distribution" in analysis:
158
  st.subheader("Sentiment Distribution")
159
 
160
- # Debug: Print sentiment distribution data
161
- print("Sentiment Distribution Data:")
162
- print(json.dumps(analysis["sentiment_distribution"], indent=2))
163
-
164
  sentiment_dist = analysis["sentiment_distribution"]
165
 
166
- # Create a very simple visualization that will definitely work
167
  try:
168
  # Extract basic sentiment data
169
  if isinstance(sentiment_dist, dict):
170
- if "basic" in sentiment_dist and isinstance(sentiment_dist["basic"], dict):
171
- basic_dist = sentiment_dist["basic"]
172
- elif any(k in sentiment_dist for k in ['positive', 'negative', 'neutral']):
173
- basic_dist = {k: v for k, v in sentiment_dist.items()
174
- if k in ['positive', 'negative', 'neutral']}
175
- else:
176
- basic_dist = {'positive': 0, 'negative': 0, 'neutral': 1}
177
- else:
178
- basic_dist = {'positive': 0, 'negative': 0, 'neutral': 1}
179
-
180
- # Calculate percentages
181
- total_articles = sum(basic_dist.values())
182
- if total_articles > 0:
183
- percentages = {
184
- k: (v / total_articles) * 100
185
- for k, v in basic_dist.items()
186
- }
187
  else:
188
  percentages = {k: 0 for k in basic_dist}
189
 
190
- # Display as simple text and metrics
191
  st.write("**Sentiment Distribution:**")
192
 
193
  col1, col2, col3 = st.columns(3)
194
- with col1:
195
- st.metric(
196
- "Positive",
197
- basic_dist.get('positive', 0),
198
- f"{percentages.get('positive', 0):.1f}%"
199
- )
200
- with col2:
201
- st.metric(
202
- "Negative",
203
- basic_dist.get('negative', 0),
204
- f"{percentages.get('negative', 0):.1f}%"
205
- )
206
- with col3:
207
- st.metric(
208
- "Neutral",
209
- basic_dist.get('neutral', 0),
210
  f"{percentages.get('neutral', 0):.1f}%"
211
  )
212
 
213
- # Create a simple bar chart using Altair
214
-
215
- # Create a simple DataFrame with consistent capitalization and percentages
216
  chart_data = pd.DataFrame({
217
  'Sentiment': ['Positive', 'Negative', 'Neutral'],
218
  'Count': [
219
- basic_dist.get('positive', 0), # Map lowercase keys to capitalized display
220
  basic_dist.get('negative', 0),
221
  basic_dist.get('neutral', 0)
222
  ],
223
- 'Percentage': [
224
- f"{percentages.get('positive', 0):.1f}%",
225
- f"{percentages.get('negative', 0):.1f}%",
226
- f"{percentages.get('neutral', 0):.1f}%"
227
  ]
228
  })
229
 
230
- # Add debug output to see what's in the data
231
- print("Chart Data for Sentiment Distribution:")
232
- print(chart_data)
233
-
234
- # Create a simple bar chart with percentages
235
  chart = alt.Chart(chart_data).mark_bar().encode(
236
- y='Sentiment', # Changed from x to y for horizontal bars
237
- x='Count', # Changed from y to x for horizontal bars
238
  color=alt.Color('Sentiment', scale=alt.Scale(
239
  domain=['Positive', 'Negative', 'Neutral'],
240
  range=['green', 'red', 'gray']
241
  )),
242
- tooltip=['Sentiment', 'Count', 'Percentage'] # Add tooltip with percentage
243
  ).properties(
244
  width=600,
245
  height=300
246
  )
247
 
248
- # Add text labels with percentages
249
  text = chart.mark_text(
250
  align='left',
251
  baseline='middle',
252
- dx=3 # Nudge text to the right so it doesn't overlap with the bar
253
  ).encode(
254
  text='Percentage'
255
  )
256
 
257
- # Combine the chart and text
258
  chart_with_text = (chart + text)
259
-
260
  st.altair_chart(chart_with_text, use_container_width=True)
261
 
262
  except Exception as e:
263
  st.error(f"Error creating visualization: {str(e)}")
264
- st.write("Fallback to simple text display:")
265
- if isinstance(sentiment_dist, dict):
266
- if "basic" in sentiment_dist:
267
- st.write(f"Positive: {sentiment_dist['basic'].get('positive', 0)}")
268
- st.write(f"Negative: {sentiment_dist['basic'].get('negative', 0)}")
269
- st.write(f"Neutral: {sentiment_dist['basic'].get('neutral', 0)}")
270
- else:
271
- st.write(f"Positive: {sentiment_dist.get('positive', 0)}")
272
- st.write(f"Negative: {sentiment_dist.get('negative', 0)}")
273
- st.write(f"Neutral: {sentiment_dist.get('neutral', 0)}")
274
- else:
275
- st.write("No valid sentiment data available")
276
 
277
  # Display sentiment indices if available
278
  if "sentiment_indices" in analysis and analysis["sentiment_indices"]:
279
  st.subheader("Sentiment Indices")
280
 
281
- # Debug: Print sentiment indices
282
- print("Sentiment Indices:")
283
- print(json.dumps(analysis["sentiment_indices"], indent=2))
284
-
285
- # Get the indices data
286
  indices = analysis["sentiment_indices"]
287
 
288
- # Create a very simple visualization that will definitely work
289
  try:
290
  if isinstance(indices, dict):
291
- # Display as simple metrics in columns
292
  cols = st.columns(3)
293
 
294
- # Define display names and descriptions
295
  display_names = {
296
  "positivity_index": "Positivity",
297
  "negativity_index": "Negativity",
298
- "emotional_intensity": "Emotional Intensity",
299
- "controversy_score": "Controversy",
300
- "confidence_score": "Confidence",
301
  "esg_relevance": "ESG Relevance"
302
  }
303
 
304
- # Display each index as a metric
305
  for i, (key, value) in enumerate(indices.items()):
306
  if isinstance(value, (int, float)):
307
  with cols[i % 3]:
308
  display_name = display_names.get(key, key.replace("_", " ").title())
309
  st.metric(display_name, f"{value:.2f}")
310
 
311
- # Create a simple bar chart using Altair
312
-
313
- # Create a simple DataFrame
314
  chart_data = pd.DataFrame({
315
  'Index': [display_names.get(k, k.replace("_", " ").title()) for k in indices.keys()],
316
  'Value': [v if isinstance(v, (int, float)) else 0 for v in indices.values()]
317
  })
318
 
319
- # Create a simple bar chart
320
  chart = alt.Chart(chart_data).mark_bar().encode(
321
  x='Value',
322
  y='Index',
323
- color=alt.Color('Index')
324
- ).properties(
325
- width=600,
326
- height=300
327
- )
328
-
329
- st.altair_chart(chart, use_container_width=True)
330
-
331
- # Add descriptions
332
- with st.expander("Sentiment Indices Explained"):
333
- st.markdown("""
334
- - **Positivity**: Measures the positive sentiment in the articles (0-1)
335
- - **Negativity**: Measures the negative sentiment in the articles (0-1)
336
- - **Emotional Intensity**: Measures the overall emotional content (0-1)
337
- - **Controversy**: High when both positive and negative sentiments are strong (0-1)
338
  - **Confidence**: Confidence in the sentiment analysis (0-1)
339
  - **ESG Relevance**: Relevance to Environmental, Social, and Governance topics (0-1)
340
  """)
341
- else:
342
- st.warning("Sentiment indices data is not in the expected format.")
343
- st.write("No valid sentiment indices available")
344
  except Exception as e:
345
  st.error(f"Error creating indices visualization: {str(e)}")
346
- st.write("Fallback to simple text display:")
347
- if isinstance(indices, dict):
348
- for key, value in indices.items():
349
- if isinstance(value, (int, float)):
350
- st.write(f"{key.replace('_', ' ').title()}: {value:.2f}")
351
- else:
352
- st.write("No valid sentiment indices data available")
353
-
354
- # Source Distribution
355
- if "source_distribution" in analysis:
356
- st.subheader("Source Distribution")
357
- source_df = pd.DataFrame.from_dict(
358
- analysis["source_distribution"],
359
- orient='index',
360
- columns=['Count']
361
- )
362
- st.bar_chart(source_df)
363
 
364
- # Common Topics
365
- if "common_topics" in analysis:
366
- st.subheader("Common Topics")
367
- st.write(", ".join(analysis["common_topics"]) if analysis["common_topics"] else "No common topics found")
 
 
 
 
 
368
 
369
- # Coverage Differences
370
- if "coverage_differences" in analysis:
371
- st.subheader("Coverage Analysis")
372
- coverage_diffs = analysis["coverage_differences"]
373
- if coverage_diffs:
374
- for diff in coverage_diffs:
375
- st.markdown(f"- {diff}")
 
 
 
 
 
376
  else:
377
- st.info("No significant coverage differences found across sources.")
 
 
 
 
 
 
 
 
378
 
379
- # Display Final Sentiment and Audio
380
- st.header("🎯 Final Analysis")
381
- if "final_sentiment_analysis" in result:
382
- st.write(result["final_sentiment_analysis"])
383
 
384
- # Display sentiment indices in the sidebar if available
385
- if "sentiment_indices" in analysis and analysis["sentiment_indices"]:
386
- indices = analysis["sentiment_indices"]
387
- # Verify we have valid data
388
- if indices and any(isinstance(v, (int, float)) for v in indices.values()):
389
- st.sidebar.markdown("### Sentiment Indices")
390
- for idx_name, idx_value in indices.items():
391
- if isinstance(idx_value, (int, float)):
392
- formatted_name = " ".join(word.capitalize() for word in idx_name.replace("_", " ").split())
393
- st.sidebar.metric(formatted_name, f"{idx_value:.2f}")
394
 
395
- # Display ensemble model information if available
396
- if "ensemble_info" in result:
397
- with st.expander("Ensemble Model Details"):
398
- ensemble = result["ensemble_info"]
399
-
400
- # Model agreement
401
- if "agreement" in ensemble:
402
- st.metric("Model Agreement", f"{ensemble['agreement']*100:.1f}%")
403
-
404
- # Individual model results
405
- if "models" in ensemble:
406
- st.subheader("Individual Model Results")
407
- models_data = []
408
- for model_name, model_info in ensemble["models"].items():
409
- models_data.append({
410
- "Model": model_name,
411
- "Sentiment": model_info.get("sentiment", "N/A"),
412
- "Confidence": f"{model_info.get('confidence', 0)*100:.1f}%"
413
- })
414
-
415
- if models_data:
416
- st.table(pd.DataFrame(models_data))
417
 
418
- # Audio Playback Section
419
- st.subheader("🔊 Listen to Analysis (Hindi)")
420
- if 'audio_content' in result:
421
- st.audio(result['audio_content'], format='audio/mp3')
422
- else:
423
- st.warning("Hindi audio summary not available")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
425
  # Total Articles
426
  if "total_articles" in analysis:
427
  st.sidebar.info(f"Found {analysis['total_articles']} articles")
 
 
 
 
428
 
429
  # Add a disclaimer
430
- st.sidebar.markdown("---")
431
- st.sidebar.markdown("### About")
432
- st.sidebar.write("This app analyzes news articles and provides sentiment analysis for any company.")
433
-
434
- if __name__ == "__main__":
435
- main()
 
1
  """Streamlit frontend for the News Summarization application."""
2
 
3
  import streamlit as st
4
+
5
  import pandas as pd
6
  import json
7
+
8
  import os
9
  import plotly.express as px
10
  import altair as alt
11
+ from utils import (
12
+ analyze_company_data,
13
+ TextToSpeechConverter,
14
+ get_translator,
15
+ NewsExtractor,
16
+ SentimentAnalyzer,
17
+ TextSummarizer
18
+ )
19
 
20
+ # Set page config
21
  st.set_page_config(
22
  page_title="News Summarization App",
23
  page_icon="📰",
24
  layout="wide"
25
  )
26
 
27
+ # Show loading message
28
+ with st.spinner("Initializing the application... Please wait while we load the models."):
29
+ # Initialize components
30
  try:
31
+ st.success("Application initialized successfully!")
32
+ except Exception as e:
33
+ st.error(f"Error initializing application: {str(e)}")
34
+ st.info("Please try refreshing the page.")
35
+
36
+ def process_company(company_name):
37
+ """Process company data directly."""
38
+ try:
39
+ # Call the analysis function directly from utils
40
+ data = analyze_company_data(company_name)
41
+
42
+ # Generate Hindi audio from final analysis
43
+ if data.get("final_sentiment_analysis"):
44
+ # Get the translator
45
+ translator = get_translator()
46
+ if translator:
47
+ try:
48
+ # Create a more detailed Hindi explanation
49
+ sentiment_explanation = f"""
50
+ {company_name} के समाचारों का विश्लेषण:
51
+
52
+ समग्र भावना: {data['final_sentiment_analysis']}
53
+
54
+ भावनात्मक विश्लेषण:
55
+ - सकारात्मक भावना: {data.get('comparative_sentiment_score', {}).get('sentiment_indices', {}).get('positivity_index', 0):.2f}
56
+ - नकारात्मक भावना: {data.get('comparative_sentiment_score', {}).get('sentiment_indices', {}).get('negativity_index', 0):.2f}
57
+ - भावनात्मक तीव्रता: {data.get('comparative_sentiment_score', {}).get('sentiment_indices', {}).get('emotional_intensity', 0):.2f}
58
+
59
+ विश्वसनीयता स्कोर: {data.get('comparative_sentiment_score', {}).get('sentiment_indices', {}).get('confidence_score', 0):.2f}
60
+ """
61
+
62
+ # Generate Hindi audio
63
+ tts_converter = TextToSpeechConverter()
64
+ audio_path = tts_converter.generate_audio(
65
+ sentiment_explanation,
66
+ f'{company_name}_summary'
67
+ )
68
+ data['audio_path'] = audio_path
69
+ except Exception as e:
70
+ print(f"Error generating Hindi audio: {str(e)}")
71
+ data['audio_path'] = None
72
+ else:
73
+ print("Translator not available")
74
+ data['audio_path'] = None
75
 
76
+ return data
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
  except Exception as e:
86
+ st.error(f"Error processing company: {str(e)}")
87
+ return {"articles": [], "comparative_sentiment_score": {}, "final_sentiment_analysis": "", "audio_path": None}
88
 
89
  def main():
90
  st.title("📰 News Summarization and Analysis")
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  st.sidebar.error("Please enter a valid company name (at least 2 characters)")
92
  else:
93
  with st.spinner("Analyzing news articles..."):
94
+ try:
95
+ # Process company data
96
+ data = process_company(company)
97
+
98
+ if not data["articles"]:
99
+ st.error("No articles found for analysis.")
100
+ return
101
+
102
  # Display Articles
103
  st.header("📑 News Articles")
104
+ for idx, article in enumerate(data["articles"], 1):
105
  with st.expander(f"Article {idx}: {article['title']}"):
106
+ # Display content with proper formatting
107
+ if article.get("content"):
108
+ st.markdown("**Content:**")
109
+ st.write(article["content"])
110
+ else:
111
+ st.warning("No content available for this article")
112
+
113
+ # Display summary if available
114
+ if article.get("summary"):
115
+ st.markdown("**Summary:**")
116
+ st.write(article["summary"])
117
+
118
+ # Display source
119
+ if article.get("source"):
120
+ st.markdown("**Source:**")
121
+ st.write(article["source"])
122
 
123
  # Enhanced sentiment display
124
  if "sentiment" in article:
125
  sentiment_col1, sentiment_col2 = st.columns(2)
126
  with sentiment_col1:
127
+ st.markdown("**Basic Sentiment:**")
128
+ st.write(article["sentiment"])
129
+ if "sentiment_score" in article:
130
+ st.write(f"**Confidence Score:** {article['sentiment_score']*100:.1f}%")
131
 
132
  with sentiment_col2:
133
  # Display fine-grained sentiment if available
134
  if "fine_grained_sentiment" in article and article["fine_grained_sentiment"]:
135
+ st.markdown("**Detailed Sentiment:**")
136
  fine_grained = article["fine_grained_sentiment"]
137
  if "category" in fine_grained:
138
+ st.write(f"Category: {fine_grained['category']}")
139
  if "confidence" in fine_grained:
140
+ st.write(f"Confidence: {fine_grained['confidence']*100:.1f}%")
141
 
142
  # Display sentiment indices if available
143
  if "sentiment_indices" in article and article["sentiment_indices"]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  st.markdown(f"> {target['context']}")
145
  st.markdown("---")
146
 
147
+ # Display URL if available
148
  if "url" in article:
149
+ st.markdown(f"**[Read More]({article['url']})**")
150
 
151
  # Display Comparative Analysis
152
  st.header("📊 Comparative Analysis")
153
+ analysis = data.get("comparative_sentiment_score", {})
154
 
155
  # Sentiment Distribution
156
  if "sentiment_distribution" in analysis:
157
  st.subheader("Sentiment Distribution")
158
 
159
+
160
+
161
+
162
+
163
  sentiment_dist = analysis["sentiment_distribution"]
164
 
165
+
166
  try:
167
  # Extract basic sentiment data
168
  if isinstance(sentiment_dist, dict):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  else:
170
  percentages = {k: 0 for k in basic_dist}
171
 
172
+ # Display as metrics
173
  st.write("**Sentiment Distribution:**")
174
 
175
  col1, col2, col3 = st.columns(3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  f"{percentages.get('neutral', 0):.1f}%"
177
  )
178
 
179
+ # Create visualization
180
+
181
+
182
  chart_data = pd.DataFrame({
183
  'Sentiment': ['Positive', 'Negative', 'Neutral'],
184
  'Count': [
185
+ basic_dist.get('positive', 0),
186
  basic_dist.get('negative', 0),
187
  basic_dist.get('neutral', 0)
188
  ],
 
 
 
 
189
  ]
190
  })
191
 
192
+
193
+
194
+
195
+
196
+
197
  chart = alt.Chart(chart_data).mark_bar().encode(
198
+ y='Sentiment',
199
+ x='Count',
200
  color=alt.Color('Sentiment', scale=alt.Scale(
201
  domain=['Positive', 'Negative', 'Neutral'],
202
  range=['green', 'red', 'gray']
203
  )),
204
+ tooltip=['Sentiment', 'Count', 'Percentage']
205
  ).properties(
206
  width=600,
207
  height=300
208
  )
209
 
210
+
211
  text = chart.mark_text(
212
  align='left',
213
  baseline='middle',
214
+ dx=3
215
  ).encode(
216
  text='Percentage'
217
  )
218
 
219
+
220
  chart_with_text = (chart + text)
221
+
222
  st.altair_chart(chart_with_text, use_container_width=True)
223
 
224
  except Exception as e:
225
  st.error(f"Error creating visualization: {str(e)}")
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
 
239
  # Display sentiment indices if available
240
  if "sentiment_indices" in analysis and analysis["sentiment_indices"]:
241
  st.subheader("Sentiment Indices")
242
 
243
+
244
+
245
+
246
+
247
+
248
  indices = analysis["sentiment_indices"]
249
 
250
+
251
  try:
252
  if isinstance(indices, dict):
253
+ # Display as metrics in columns
254
  cols = st.columns(3)
255
 
256
+
257
  display_names = {
258
  "positivity_index": "Positivity",
259
  "negativity_index": "Negativity",
 
 
 
260
  "esg_relevance": "ESG Relevance"
261
  }
262
 
263
+
264
  for i, (key, value) in enumerate(indices.items()):
265
  if isinstance(value, (int, float)):
266
  with cols[i % 3]:
267
  display_name = display_names.get(key, key.replace("_", " ").title())
268
  st.metric(display_name, f"{value:.2f}")
269
 
270
+ # Create visualization
271
+
272
+
273
  chart_data = pd.DataFrame({
274
  'Index': [display_names.get(k, k.replace("_", " ").title()) for k in indices.keys()],
275
  'Value': [v if isinstance(v, (int, float)) else 0 for v in indices.values()]
276
  })
277
 
278
+
279
  chart = alt.Chart(chart_data).mark_bar().encode(
280
  x='Value',
281
  y='Index',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  - **Confidence**: Confidence in the sentiment analysis (0-1)
283
  - **ESG Relevance**: Relevance to Environmental, Social, and Governance topics (0-1)
284
  """)
285
+
286
+
287
+
288
  except Exception as e:
289
  st.error(f"Error creating indices visualization: {str(e)}")
290
+
291
+
292
+
293
+
294
+
295
+
296
+
 
 
 
 
 
 
 
 
 
 
297
 
298
+ # Display Final Analysis
299
+ st.header("📊 Final Analysis")
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
 
308
+ # Display overall sentiment analysis with enhanced formatting
309
+ if data.get("final_sentiment_analysis"):
310
+ st.markdown("### Overall Sentiment Analysis")
311
+ analysis_parts = data["final_sentiment_analysis"].split(". ")
312
+ if len(analysis_parts) >= 2:
313
+ # First sentence - Overall sentiment
314
+ st.markdown(f"**{analysis_parts[0]}.**")
315
+ # Second sentence - Key findings
316
+ st.markdown(f"**{analysis_parts[1]}.**")
317
+ # Third sentence - Additional insights (if available)
318
+ if len(analysis_parts) > 2:
319
+ st.markdown(f"**{analysis_parts[2]}.**")
320
  else:
321
+ st.write(data["final_sentiment_analysis"])
322
+
323
+ # Add sentiment strength indicator
324
+ if data.get("ensemble_info"):
325
+ ensemble_info = data["ensemble_info"]
326
+ if "model_agreement" in ensemble_info:
327
+ agreement = ensemble_info["model_agreement"]
328
+ strength = "Strong" if agreement > 0.8 else "Moderate" if agreement > 0.6 else "Weak"
329
+ st.markdown(f"**Sentiment Strength:** {strength} (Agreement: {agreement:.2f})")
330
 
331
+ # Display ensemble model details
332
+ if data.get("ensemble_info"):
333
+ st.subheader("Ensemble Model Details")
334
+ ensemble_info = data["ensemble_info"]
335
 
336
+ # Create columns for model details
337
+ model_cols = st.columns(3)
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
 
347
+ with model_cols[0]:
348
+ st.markdown("**Primary Model:**")
349
+ if "models" in ensemble_info and "transformer" in ensemble_info["models"]:
350
+ model = ensemble_info["models"]["transformer"]
351
+ st.write(f"Sentiment: {model['sentiment']}")
352
+ st.write(f"Score: {model['score']:.3f}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
 
354
+ with model_cols[1]:
355
+ st.markdown("**TextBlob Analysis:**")
356
+ if "models" in ensemble_info and "textblob" in ensemble_info["models"]:
357
+ model = ensemble_info["models"]["textblob"]
358
+ st.write(f"Sentiment: {model['sentiment']}")
359
+ st.write(f"Score: {model['score']:.3f}")
360
+
361
+ with model_cols[2]:
362
+ st.markdown("**VADER Analysis:**")
363
+ if "models" in ensemble_info and "vader" in ensemble_info["models"]:
364
+ model = ensemble_info["models"]["vader"]
365
+ st.write(f"Sentiment: {model['sentiment']}")
366
+ st.write(f"Score: {model['score']:.3f}")
367
+
368
+ # Display ensemble agreement if available
369
+ if "model_agreement" in ensemble_info:
370
+ st.markdown(f"**Model Agreement:** {ensemble_info['model_agreement']:.3f}")
371
+
372
+ # Display Hindi audio player
373
+ st.subheader("🔊 Listen to Analysis (Hindi)")
374
+ if data.get("audio_path") and os.path.exists(data["audio_path"]):
375
+ st.audio(data["audio_path"])
376
+ else:
377
+ st.info("Generating Hindi audio summary...")
378
+ with st.spinner("Please wait while we generate the Hindi audio summary..."):
379
+ # Try to generate audio again
380
+ translator = get_translator()
381
+ if translator and data.get("final_sentiment_analysis"):
382
+ try:
383
+ # Translate final analysis to Hindi
384
+ translated_analysis = translator.translate(
385
+ data["final_sentiment_analysis"],
386
+ dest='hi'
387
+ ).text
388
+
389
+ # Generate Hindi audio
390
+ tts_converter = TextToSpeechConverter()
391
+ audio_path = tts_converter.generate_audio(
392
+ translated_analysis,
393
+ f'{company}_summary'
394
+ )
395
+ if audio_path and os.path.exists(audio_path):
396
+ st.audio(audio_path)
397
+ else:
398
+ st.error("Hindi audio summary not available")
399
+ except Exception as e:
400
+ st.error(f"Error generating Hindi audio: {str(e)}")
401
+ else:
402
+ st.error("Hindi audio summary not available")
403
 
404
  # Total Articles
405
  if "total_articles" in analysis:
406
  st.sidebar.info(f"Found {analysis['total_articles']} articles")
407
+
408
+ except Exception as e:
409
+ st.error(f"Error analyzing company data: {str(e)}")
410
+ print(f"Error: {str(e)}")
411
 
412
  # Add a disclaimer
413
+ st.sidebar.markdown("---")