proKBD commited on
Commit
bf4ee4b
·
verified ·
1 Parent(s): d9cc29f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -431
app.py CHANGED
@@ -1,431 +1,80 @@
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
- for diff in analysis["coverage_differences"]:
373
- st.write("- " + diff)
374
-
375
- # Display Final Sentiment and Audio
376
- st.header("🎯 Final Analysis")
377
- if "final_sentiment_analysis" in result:
378
- st.write(result["final_sentiment_analysis"])
379
-
380
- # Display sentiment indices in the sidebar if available
381
- if "sentiment_indices" in analysis and analysis["sentiment_indices"]:
382
- indices = analysis["sentiment_indices"]
383
- # Verify we have valid data
384
- if indices and any(isinstance(v, (int, float)) for v in indices.values()):
385
- st.sidebar.markdown("### Sentiment Indices")
386
- for idx_name, idx_value in indices.items():
387
- if isinstance(idx_value, (int, float)):
388
- formatted_name = " ".join(word.capitalize() for word in idx_name.replace("_", " ").split())
389
- st.sidebar.metric(formatted_name, f"{idx_value:.2f}")
390
-
391
- # Display ensemble model information if available
392
- if "ensemble_info" in result:
393
- with st.expander("Ensemble Model Details"):
394
- ensemble = result["ensemble_info"]
395
-
396
- # Model agreement
397
- if "agreement" in ensemble:
398
- st.metric("Model Agreement", f"{ensemble['agreement']*100:.1f}%")
399
-
400
- # Individual model results
401
- if "models" in ensemble:
402
- st.subheader("Individual Model Results")
403
- models_data = []
404
- for model_name, model_info in ensemble["models"].items():
405
- models_data.append({
406
- "Model": model_name,
407
- "Sentiment": model_info.get("sentiment", "N/A"),
408
- "Confidence": f"{model_info.get('confidence', 0)*100:.1f}%"
409
- })
410
-
411
- if models_data:
412
- st.table(pd.DataFrame(models_data))
413
-
414
- # Audio Playback Section
415
- st.subheader("🔊 Listen to Analysis (Hindi)")
416
- if 'audio_content' in result:
417
- st.audio(result['audio_content'], format='audio/mp3')
418
- else:
419
- st.warning("Hindi audio summary not available")
420
-
421
- # Total Articles
422
- if "total_articles" in analysis:
423
- st.sidebar.info(f"Found {analysis['total_articles']} articles")
424
-
425
- # Add a disclaimer
426
- st.sidebar.markdown("---")
427
- st.sidebar.markdown("### About")
428
- st.sidebar.write("This app analyzes news articles and provides sentiment analysis for any company.")
429
-
430
- if __name__ == "__main__":
431
- main()
 
1
+ """Streamlit frontend for the News Summarization application."""
2
+
3
+ import streamlit as st
4
+ import pandas as pd
5
+ import json
6
+ import os
7
+ import plotly.express as px
8
+ import altair as alt
9
+ from utils import analyze_company_data # Import the analysis function directly
10
+
11
+ st.set_page_config(
12
+ page_title="News Summarization App",
13
+ page_icon="📰",
14
+ layout="wide"
15
+ )
16
+
17
+ def process_company(company_name):
18
+ """Process company data directly."""
19
+ try:
20
+ # Call the analysis function directly from utils
21
+ data = analyze_company_data(company_name)
22
+
23
+ # Generate audio if needed
24
+ if 'summary' in data:
25
+ from gtts import gTTS
26
+ tts = gTTS(text=data['summary'], lang='en')
27
+ audio_path = os.path.join('audio_output', f'{company_name}_summary.mp3')
28
+ os.makedirs('audio_output', exist_ok=True)
29
+ tts.save(audio_path)
30
+ data['audio_path'] = audio_path
31
+
32
+ return data
33
+ except Exception as e:
34
+ st.error(f"Error processing company: {str(e)}")
35
+ return {"articles": [], "comparative_sentiment_score": {}, "final_sentiment_analysis": "", "audio_path": None}
36
+
37
+ def main():
38
+ st.title("📰 News Summarization and Analysis")
39
+
40
+ # Sidebar
41
+ st.sidebar.header("Settings")
42
+
43
+ # Company name input
44
+ company_name = st.text_input("Enter Company Name", "")
45
+
46
+ if company_name:
47
+ with st.spinner("Analyzing company news..."):
48
+ data = process_company(company_name)
49
+
50
+ # Display results
51
+ if data["articles"]:
52
+ st.subheader("📊 Analysis Results")
53
+
54
+ # Display sentiment analysis
55
+ if data["final_sentiment_analysis"]:
56
+ st.write("Sentiment Analysis:", data["final_sentiment_analysis"])
57
+
58
+ # Display articles
59
+ st.subheader("📰 Recent Articles")
60
+ for article in data["articles"]:
61
+ with st.expander(article["title"]):
62
+ st.write(article["summary"])
63
+ st.write("Source:", article["source"])
64
+ st.write("Sentiment:", article["sentiment"])
65
+
66
+ # Display audio if available
67
+ if data.get("audio_path"):
68
+ st.audio(data["audio_path"])
69
+
70
+ # Display visualizations
71
+ if data.get("comparative_sentiment_score"):
72
+ st.subheader("📈 Sentiment Distribution")
73
+ sentiment_df = pd.DataFrame(data["comparative_sentiment_score"])
74
+ fig = px.bar(sentiment_df, title="Sentiment Analysis by Source")
75
+ st.plotly_chart(fig)
76
+ else:
77
+ st.warning("No articles found for this company.")
78
+
79
+ if __name__ == "__main__":
80
+ main()