shaheerawan3 commited on
Commit
318abcf
·
verified ·
1 Parent(s): 2a2426e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -322
app.py CHANGED
@@ -1,52 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
- import pandas as pd
3
- import numpy as np
4
- import plotly.graph_objects as go
5
- import plotly.express as px
6
- from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
7
- from nltk.tokenize import sent_tokenize, word_tokenize
8
- from nltk.corpus import stopwords
9
- from nltk.sentiment import SentimentIntensityAnalyzer
10
- from gensim import corpora, models
11
- import spacy
12
- import requests
13
- from langdetect import detect
14
- import json
15
- import base64
16
- from datetime import datetime
17
- import tempfile
18
- from fpdf import FPDF
19
- import os
20
- from functools import lru_cache
21
  import logging
22
- from concurrent.futures import ThreadPoolExecutor
23
- from typing import Dict, List, Any, Optional
24
- import io
25
 
26
- # Configure logging
27
- logging.basicConfig(
28
- level=logging.INFO,
29
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
30
- )
31
- logger = logging.getLogger(__name__)
32
 
33
  class TextProcessor:
34
- """Handles text input processing and validation"""
 
 
 
35
 
36
- @staticmethod
37
- def process_file_upload(uploaded_file) -> Optional[str]:
38
- """Process uploaded file and return text content"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  try:
40
- if uploaded_file is None:
41
  return None
42
 
43
- # Get file extension
44
- file_extension = uploaded_file.name.split('.')[-1].lower()
45
-
46
- if file_extension == 'txt':
47
- return uploaded_file.read().decode('utf-8')
48
- else:
49
- raise ValueError(f"Unsupported file type: {file_extension}")
50
 
51
  except Exception as e:
52
  logger.error(f"Error processing file upload: {str(e)}")
@@ -54,31 +92,41 @@ class TextProcessor:
54
  return None
55
 
56
  @staticmethod
57
- def validate_text(text: str) -> bool:
58
- """Validate input text"""
59
  if not text or len(text.strip()) == 0:
60
  st.error("Please enter some text to analyze")
61
  return False
62
- if len(text.split()) > 10000: # Arbitrary limit
63
- st.error("Text is too long. Please enter a shorter text")
64
  return False
65
  return True
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  class AdvancedAnalyzer:
68
- """Handles text analysis using various NLP techniques"""
69
-
70
- def __init__(self):
71
  self._initialize_models()
72
-
73
- @lru_cache(maxsize=1)
74
  def _initialize_models(self):
75
- """Initialize all required models with caching"""
76
  try:
77
  self.sentiment_analyzer = SentimentIntensityAnalyzer()
78
- self.nlp = spacy.load('en_core_web_sm')
79
  self.sentiment_model = pipeline(
80
  "sentiment-analysis",
81
- model="nlptown/bert-base-multilingual-uncased-sentiment",
82
  return_all_scores=True
83
  )
84
  logger.info("Models initialized successfully")
@@ -86,200 +134,172 @@ class AdvancedAnalyzer:
86
  logger.error(f"Error initializing models: {str(e)}")
87
  raise
88
 
89
- def analyze_sentiment_batch(self, text: str, batch_size: int = 1000) -> Dict:
90
- """Analyze sentiment in batches for better performance"""
91
- sentences = sent_tokenize(text)
92
- results = []
93
-
94
- with ThreadPoolExecutor() as executor:
95
- for i in range(0, len(sentences), batch_size):
96
- batch = sentences[i:i + batch_size]
97
- results.extend(executor.map(self.analyze_sentiment, batch))
98
 
99
- # Aggregate results
100
- compound = np.mean([r['compound'] for r in results])
101
- emotions = {
102
- 'positive': np.mean([r['emotions']['positive'] for r in results]),
103
- 'negative': np.mean([r['emotions']['negative'] for r in results]),
104
- 'neutral': np.mean([r['emotions']['neutral'] for r in results])
105
- }
106
 
107
- return {'compound': compound, 'emotions': emotions}
108
-
109
- def analyze_sentiment(self, text: str, language: str = 'en') -> Dict:
110
- """Analyze sentiment with emotion detection"""
111
- try:
112
- if language != 'en':
113
- sentiments = self.sentiment_model(text)[0]
114
- return {
115
- 'compound': max(s['score'] for s in sentiments),
116
- 'emotions': {s['label']: s['score'] for s in sentiments}
117
- }
118
- else:
119
- scores = self.sentiment_analyzer.polarity_scores(text)
120
- return {
121
- 'compound': scores['compound'],
122
- 'emotions': {
123
- 'positive': scores['pos'],
124
- 'negative': scores['neg'],
125
- 'neutral': scores['neu']
126
- }
127
- }
128
- except Exception as e:
129
- logger.error(f"Error in sentiment analysis: {str(e)}")
130
- raise
131
-
132
- def extract_entities(self, text: str) -> Dict[str, List[str]]:
133
- """Extract named entities with confidence scores"""
134
- try:
135
- doc = self.nlp(text)
136
- entities = {}
137
- for ent in doc.ents:
138
- if ent.label_ not in entities:
139
- entities[ent.label_] = []
140
- # Only include entities with high confidence
141
- if ent.label_prob >= 0.8:
142
- entities[ent.label_].append({
143
- 'text': ent.text,
144
- 'confidence': round(ent.label_prob, 3)
145
- })
146
- return entities
147
- except Exception as e:
148
- logger.error(f"Error in entity extraction: {str(e)}")
149
- raise
150
-
151
- def topic_modeling(self, text: str, num_topics: int = 3) -> List[Dict]:
152
- """Extract main topics using LDA with preprocessing"""
153
  try:
154
- # Tokenize and clean text
155
- doc = self.nlp(text.lower())
156
- tokens = [
157
- token.lemma_ for token in doc
158
- if not token.is_stop and not token.is_punct and token.is_alpha
159
- ]
160
-
161
- # Create dictionary and corpus
162
- texts = [tokens]
163
- dictionary = corpora.Dictionary(texts)
164
- corpus = [dictionary.doc2bow(text) for text in texts]
165
 
166
- # Train LDA model with coherence optimization
167
- lda_model = models.LdaModel(
168
- corpus=corpus,
169
- id2word=dictionary,
170
- num_topics=num_topics,
171
- random_state=42,
172
- passes=15,
173
- alpha='auto',
174
- per_word_topics=True
175
  )
 
176
 
177
- # Extract topics with probabilities
178
- topics = []
179
- for idx, topic in lda_model.show_topics(formatted=False):
180
- topics.append({
181
- 'id': idx,
182
- 'words': [(word, round(prob, 4))
183
- for word, prob in topic],
184
- 'coherence': round(lda_model.get_topic_coherence(topic), 4)
185
- })
186
 
187
- return sorted(topics, key=lambda x: x['coherence'], reverse=True)
188
  except Exception as e:
189
- logger.error(f"Error in topic modeling: {str(e)}")
190
  raise
 
 
 
191
 
192
- class PDFGenerator:
193
- """Generates professional PDF reports with visualizations"""
194
-
195
- def __init__(self):
196
- self.pdf = FPDF()
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- def generate_report(self, analysis_results: Dict) -> str:
199
- """Generate a detailed PDF report with charts"""
200
- try:
201
- self.pdf.add_page()
202
- self._add_header()
203
- self._add_summary(analysis_results)
204
- self._add_sentiment_analysis(analysis_results)
205
- self._add_topics(analysis_results)
206
- self._add_entities(analysis_results)
207
- self._add_footer()
208
-
209
- # Save to temporary file
210
- with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp:
211
- self.pdf.output(tmp.name)
212
- return tmp.name
213
- except Exception as e:
214
- logger.error(f"Error generating PDF report: {str(e)}")
215
- raise
216
 
217
- def _add_header(self):
218
- """Add report header"""
219
- self.pdf.set_font('Arial', 'B', 16)
220
- self.pdf.cell(190, 10, 'AI Output Analysis Report', 0, 1, 'C')
221
- self.pdf.ln(10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
- def _add_summary(self, results: Dict):
224
- """Add analysis summary"""
225
- self.pdf.set_font('Arial', 'B', 12)
226
- self.pdf.cell(190, 10, 'Analysis Summary', 0, 1, 'L')
227
- self.pdf.set_font('Arial', '', 10)
228
 
229
- compound_score = results['sentiment']['compound']
230
- sentiment_label = (
231
- 'Positive' if compound_score > 0.05
232
- else 'Negative' if compound_score < -0.05
233
- else 'Neutral'
234
- )
 
 
 
 
 
 
 
 
 
 
 
235
 
236
- self.pdf.cell(190, 10,
237
- f"Overall Sentiment: {sentiment_label} ({compound_score:.2f})",
238
- 0, 1, 'L')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
  def main():
241
- st.set_page_config(
242
- page_title="Enhanced AI Output Analyzer",
243
- layout="wide",
244
- initial_sidebar_state="expanded"
245
- )
246
 
247
- # Load custom CSS
248
- st.markdown("""
249
- <style>
250
- .main { padding: 2rem; }
251
- .stMetric {
252
- background-color: #f0f2f6;
253
- padding: 1rem;
254
- border-radius: 0.5rem;
255
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
256
- }
257
- .entity-tag {
258
- background-color: #e9ecef;
259
- padding: 0.2rem 0.5rem;
260
- border-radius: 0.25rem;
261
- margin: 0.2rem;
262
- display: inline-block;
263
- }
264
- </style>
265
- """, unsafe_allow_html=True)
266
 
267
- # Initialize session state
268
- if 'analysis_history' not in st.session_state:
269
- st.session_state.analysis_history = []
270
 
271
  # Sidebar configuration
272
  with st.sidebar:
273
  st.title("Analysis Settings")
274
-
275
- # Analysis options
276
- st.subheader("Analysis Options")
277
- num_topics = st.slider("Number of Topics", 2, 10, 3)
278
- min_entity_confidence = st.slider("Entity Confidence Threshold", 0.0, 1.0, 0.8)
279
- batch_size = st.select_slider(
280
- "Processing Batch Size",
281
- options=[500, 1000, 2000, 5000],
282
- value=1000
283
  )
284
 
285
  # Main content
@@ -288,7 +308,6 @@ def main():
288
  # Input section
289
  input_method = st.radio("Choose input method:", ["Text Input", "File Upload"])
290
 
291
- text_processor = TextProcessor()
292
  if input_method == "File Upload":
293
  text = text_processor.process_file_upload(
294
  st.file_uploader("Upload a text file", type=['txt'])
@@ -297,108 +316,16 @@ def main():
297
  text = st.text_area("Enter text to analyze:", height=200)
298
 
299
  # Analysis section
300
- if st.button("Analyze", type="primary") and text_processor.validate_text(text):
 
 
301
  try:
302
- with st.spinner("Performing analysis..."):
303
- analyzer = AdvancedAnalyzer()
304
-
305
- # Perform analysis with progress tracking
306
- progress_bar = st.progress(0)
307
-
308
- # Sentiment analysis
309
- results = {
310
- 'sentiment': analyzer.analyze_sentiment_batch(
311
- text, batch_size=batch_size
312
- )
313
- }
314
- progress_bar.progress(0.33)
315
-
316
- # Topic modeling
317
- results['topics'] = analyzer.topic_modeling(
318
- text, num_topics=num_topics
319
- )
320
- progress_bar.progress(0.66)
321
-
322
- # Entity extraction
323
- results['entities'] = analyzer.extract_entities(text)
324
- progress_bar.progress(1.0)
325
-
326
- # Display results
327
- st.success("Analysis complete!")
328
-
329
- # Save to history
330
- st.session_state.analysis_history.append({
331
- 'timestamp': datetime.now(),
332
- 'results': results
333
- })
334
-
335
- # Display visualizations
336
- display_results(results)
337
-
338
- # Generate report
339
- generate_downloadable_report(results)
340
 
341
  except Exception as e:
342
- logger.error(f"Error during analysis: {str(e)}")
343
  st.error(f"An error occurred during analysis: {str(e)}")
344
 
345
- def display_results(results: Dict):
346
- """Display analysis results with interactive visualizations"""
347
- # Sentiment Analysis
348
- st.subheader("Sentiment Analysis")
349
- col1, col2 = st.columns(2)
350
-
351
- with col1:
352
- # Sentiment gauge
353
- fig = go.Figure(go.Indicator(
354
- mode="gauge+number",
355
- value=results['sentiment']['compound'],
356
- domain={'x': [0, 1], 'y': [0, 1]},
357
- gauge={
358
- 'axis': {'range': [-1, 1]},
359
- 'bar': {'color': "darkblue"},
360
- 'steps': [
361
- {'range': [-1, -0.05], 'color': "lightcoral"},
362
- {'range': [-0.05, 0.05], 'color': "lightgray"},
363
- {'range': [0.05, 1], 'color': "lightgreen"}
364
- ]
365
- }
366
- ))
367
- st.plotly_chart(fig)
368
-
369
- with col2:
370
- # Emotions pie chart
371
- emotions_df = pd.DataFrame(
372
- results['sentiment']['emotions'].items(),
373
- columns=['Emotion', 'Score']
374
- )
375
- fig = px.pie(
376
- emotions_df,
377
- values='Score',
378
- names='Emotion',
379
- title="Emotional Distribution"
380
- )
381
- st.plotly_chart(fig)
382
-
383
- def generate_downloadable_report(results: Dict):
384
- """Generate and provide downloadable report"""
385
- try:
386
- pdf_generator = PDFGenerator()
387
- pdf_path = pdf_generator.generate_report(results)
388
-
389
- with open(pdf_path, "rb") as pdf_file:
390
- st.download_button(
391
- label="📊 Download Analysis Report (PDF)",
392
- data=pdf_file,
393
- file_name=f"analysis_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
394
- mime="application/pdf"
395
- )
396
-
397
- # Clean up
398
- os.unlink(pdf_path)
399
- except Exception as e:
400
- logger.error(f"Error generating downloadable report: {str(e)}")
401
- st.error("Failed to generate report. Please try again.")
402
-
403
  if __name__ == "__main__":
404
  main()
 
1
+ # config.yaml
2
+ config_yaml = """
3
+ models:
4
+ spacy: en_core_web_sm
5
+ sentiment: nlptown/bert-base-multilingual-uncased-sentiment
6
+
7
+ analysis:
8
+ batch_size: 1000
9
+ min_entity_confidence: 0.8
10
+ num_topics: 3
11
+ max_text_length: 50000
12
+
13
+ security:
14
+ max_file_size: 5242880 # 5MB
15
+ allowed_extensions: [txt]
16
+
17
+ logging:
18
+ level: INFO
19
+ format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
20
+ """
21
+
22
+ # utils/config.py
23
+ import yaml
24
+ from pathlib import Path
25
+
26
+ def load_config():
27
+ config_path = Path("config.yaml")
28
+ if not config_path.exists():
29
+ with open(config_path, "w") as f:
30
+ f.write(config_yaml)
31
+ with open(config_path) as f:
32
+ return yaml.safe_load(f)
33
+
34
+ # utils/logger.py
35
+ import logging
36
+ from typing import Optional
37
+
38
+ def setup_logger(name: Optional[str] = None) -> logging.Logger:
39
+ config = load_config()
40
+ logger = logging.getLogger(name or __name__)
41
+ logger.setLevel(config['logging']['level'])
42
+
43
+ if not logger.handlers:
44
+ handler = logging.StreamHandler()
45
+ formatter = logging.Formatter(config['logging']['format'])
46
+ handler.setFormatter(formatter)
47
+ logger.addHandler(handler)
48
+
49
+ return logger
50
+
51
+ # text_processing.py
52
+ from typing import Optional, Dict
53
  import streamlit as st
54
+ from pathlib import Path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  import logging
 
 
 
56
 
57
+ logger = setup_logger("text_processing")
 
 
 
 
 
58
 
59
  class TextProcessor:
60
+ def __init__(self, config: Dict):
61
+ self.config = config
62
+ self.max_file_size = config['security']['max_file_size']
63
+ self.allowed_extensions = config['security']['allowed_extensions']
64
 
65
+ def validate_file(self, uploaded_file) -> bool:
66
+ if uploaded_file is None:
67
+ return False
68
+
69
+ # Check file size
70
+ if uploaded_file.size > self.max_file_size:
71
+ st.error(f"File size exceeds {self.max_file_size/1024/1024}MB limit")
72
+ return False
73
+
74
+ # Check extension
75
+ ext = Path(uploaded_file.name).suffix[1:].lower()
76
+ if ext not in self.allowed_extensions:
77
+ st.error(f"Unsupported file type. Allowed types: {', '.join(self.allowed_extensions)}")
78
+ return False
79
+
80
+ return True
81
+
82
+ def process_file_upload(self, uploaded_file) -> Optional[str]:
83
  try:
84
+ if not self.validate_file(uploaded_file):
85
  return None
86
 
87
+ return uploaded_file.read().decode('utf-8')
 
 
 
 
 
 
88
 
89
  except Exception as e:
90
  logger.error(f"Error processing file upload: {str(e)}")
 
92
  return None
93
 
94
  @staticmethod
95
+ def validate_text(text: str, max_length: int) -> bool:
 
96
  if not text or len(text.strip()) == 0:
97
  st.error("Please enter some text to analyze")
98
  return False
99
+ if len(text) > max_length:
100
+ st.error(f"Text exceeds maximum length of {max_length} characters")
101
  return False
102
  return True
103
 
104
+ # analysis.py
105
+ from typing import Dict, List
106
+ import spacy
107
+ from transformers import pipeline
108
+ from nltk.sentiment import SentimentIntensityAnalyzer
109
+ from nltk.tokenize import sent_tokenize
110
+ from gensim import corpora, models
111
+ import numpy as np
112
+ from concurrent.futures import ThreadPoolExecutor
113
+ import streamlit as st
114
+
115
+ logger = setup_logger("analysis")
116
+
117
  class AdvancedAnalyzer:
118
+ def __init__(self, config: Dict):
119
+ self.config = config
 
120
  self._initialize_models()
121
+
122
+ @st.cache_resource
123
  def _initialize_models(self):
 
124
  try:
125
  self.sentiment_analyzer = SentimentIntensityAnalyzer()
126
+ self.nlp = spacy.load(self.config['models']['spacy'])
127
  self.sentiment_model = pipeline(
128
  "sentiment-analysis",
129
+ model=self.config['models']['sentiment'],
130
  return_all_scores=True
131
  )
132
  logger.info("Models initialized successfully")
 
134
  logger.error(f"Error initializing models: {str(e)}")
135
  raise
136
 
137
+ def analyze_text(self, text: str) -> Dict:
138
+ """Complete text analysis pipeline"""
139
+ results = {}
 
 
 
 
 
 
140
 
141
+ # Use st.progress to show analysis progress
142
+ progress_bar = st.progress(0)
143
+ status_text = st.empty()
 
 
 
 
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  try:
146
+ # Sentiment Analysis
147
+ status_text.text("Analyzing sentiment...")
148
+ results['sentiment'] = self.analyze_sentiment_batch(
149
+ text,
150
+ self.config['analysis']['batch_size']
151
+ )
152
+ progress_bar.progress(0.33)
 
 
 
 
153
 
154
+ # Topic Modeling
155
+ status_text.text("Extracting topics...")
156
+ results['topics'] = self.topic_modeling(
157
+ text,
158
+ self.config['analysis']['num_topics']
 
 
 
 
159
  )
160
+ progress_bar.progress(0.66)
161
 
162
+ # Entity Extraction
163
+ status_text.text("Identifying entities...")
164
+ results['entities'] = self.extract_entities(text)
165
+ progress_bar.progress(1.0)
166
+
167
+ status_text.text("Analysis complete!")
168
+ return results
 
 
169
 
 
170
  except Exception as e:
171
+ logger.error(f"Error in analysis pipeline: {str(e)}")
172
  raise
173
+ finally:
174
+ progress_bar.empty()
175
+ status_text.empty()
176
 
177
+ # Rest of the AdvancedAnalyzer methods remain the same...
178
+
179
+ # ui.py
180
+ import streamlit as st
181
+ import plotly.graph_objects as go
182
+ import plotly.express as px
183
+ import pandas as pd
184
+ from typing import Dict
185
+
186
+ class UI:
187
+ @staticmethod
188
+ def setup_page():
189
+ st.set_page_config(
190
+ page_title="Enhanced AI Output Analyzer",
191
+ layout="wide",
192
+ initial_sidebar_state="expanded"
193
+ )
194
 
195
+ st.markdown("""
196
+ <style>
197
+ .main { padding: 2rem; }
198
+ .stMetric {
199
+ background-color: var(--background-color);
200
+ padding: 1rem;
201
+ border-radius: 0.5rem;
202
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
203
+ }
204
+ .entity-tag {
205
+ background-color: var(--secondary-background-color);
206
+ padding: 0.2rem 0.5rem;
207
+ border-radius: 0.25rem;
208
+ margin: 0.2rem;
209
+ display: inline-block;
210
+ }
211
+ </style>
212
+ """, unsafe_allow_html=True)
213
 
214
+ @staticmethod
215
+ def display_results(results: Dict):
216
+ """Display analysis results with interactive visualizations"""
217
+ st.subheader("Analysis Results")
218
+
219
+ # Create tabs for different analyses
220
+ sentiment_tab, topics_tab, entities_tab = st.tabs([
221
+ "Sentiment Analysis",
222
+ "Topic Modeling",
223
+ "Named Entities"
224
+ ])
225
+
226
+ with sentiment_tab:
227
+ UI._display_sentiment(results['sentiment'])
228
+
229
+ with topics_tab:
230
+ UI._display_topics(results['topics'])
231
+
232
+ with entities_tab:
233
+ UI._display_entities(results['entities'])
234
 
235
+ @staticmethod
236
+ def _display_sentiment(sentiment_results: Dict):
237
+ col1, col2 = st.columns(2)
 
 
238
 
239
+ with col1:
240
+ # Sentiment gauge
241
+ fig = go.Figure(go.Indicator(
242
+ mode="gauge+number",
243
+ value=sentiment_results['compound'],
244
+ domain={'x': [0, 1], 'y': [0, 1]},
245
+ gauge={
246
+ 'axis': {'range': [-1, 1]},
247
+ 'bar': {'color': "darkblue"},
248
+ 'steps': [
249
+ {'range': [-1, -0.05], 'color': "lightcoral"},
250
+ {'range': [-0.05, 0.05], 'color': "lightgray"},
251
+ {'range': [0.05, 1], 'color': "lightgreen"}
252
+ ]
253
+ }
254
+ ))
255
+ st.plotly_chart(fig)
256
 
257
+ with col2:
258
+ # Emotions pie chart
259
+ emotions_df = pd.DataFrame(
260
+ sentiment_results['emotions'].items(),
261
+ columns=['Emotion', 'Score']
262
+ )
263
+ fig = px.pie(
264
+ emotions_df,
265
+ values='Score',
266
+ names='Emotion',
267
+ title="Emotional Distribution"
268
+ )
269
+ st.plotly_chart(fig)
270
+
271
+ # Rest of the UI methods...
272
+
273
+ # main.py
274
+ import streamlit as st
275
+ from utils.config import load_config
276
+ from text_processing import TextProcessor
277
+ from analysis import AdvancedAnalyzer
278
+ from ui import UI
279
 
280
  def main():
281
+ # Load configuration
282
+ config = load_config()
 
 
 
283
 
284
+ # Setup UI
285
+ UI.setup_page()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
 
287
+ # Initialize processors
288
+ text_processor = TextProcessor(config)
289
+ analyzer = AdvancedAnalyzer(config)
290
 
291
  # Sidebar configuration
292
  with st.sidebar:
293
  st.title("Analysis Settings")
294
+ config['analysis']['num_topics'] = st.slider(
295
+ "Number of Topics",
296
+ 2, 10,
297
+ config['analysis']['num_topics']
298
+ )
299
+ config['analysis']['min_entity_confidence'] = st.slider(
300
+ "Entity Confidence Threshold",
301
+ 0.0, 1.0,
302
+ config['analysis']['min_entity_confidence']
303
  )
304
 
305
  # Main content
 
308
  # Input section
309
  input_method = st.radio("Choose input method:", ["Text Input", "File Upload"])
310
 
 
311
  if input_method == "File Upload":
312
  text = text_processor.process_file_upload(
313
  st.file_uploader("Upload a text file", type=['txt'])
 
316
  text = st.text_area("Enter text to analyze:", height=200)
317
 
318
  # Analysis section
319
+ if st.button("Analyze", type="primary") and text_processor.validate_text(
320
+ text, config['analysis']['max_text_length']
321
+ ):
322
  try:
323
+ with st.spinner("Analyzing text..."):
324
+ results = analyzer.analyze_text(text)
325
+ UI.display_results(results)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
  except Exception as e:
 
328
  st.error(f"An error occurred during analysis: {str(e)}")
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  if __name__ == "__main__":
331
  main()