pentarosarium commited on
Commit
aebf0a2
·
1 Parent(s): db7fce3

progress more 71

Browse files
Files changed (1) hide show
  1. app.py +92 -76
app.py CHANGED
@@ -80,7 +80,56 @@ rubert1 = pipeline("sentiment-analysis", model = "DeepPavlov/rubert-base-cased")
80
  rubert2 = pipeline("sentiment-analysis", model = "blanchefort/rubert-base-cased-sentiment")
81
 
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
  @st.cache_resource
86
  def load_model(model_id):
@@ -343,78 +392,66 @@ def process_file(uploaded_file):
343
 
344
  st.write(f"Из {original_news_count} новостных сообщений удалены {duplicates_removed} дублирующих. Осталось {remaining_news_count}.")
345
 
346
- st.write("Начинаем предобработку и анализ текстов...")
347
-
348
- texts = df['Выдержки из текста'].tolist()
349
- texts = [str(text) if not pd.isna(text) else "" for text in texts]
350
-
351
- lemmatized_texts = [lemmatize_text(text) for text in texts]
352
- translated_texts = batch_translate(lemmatized_texts)
353
- df['Translated'] = translated_texts
354
-
355
- # Perform sentiment analysis
356
- df['ruBERT2'] = [get_rubert2_sentiment(text) for text in texts]
357
- df['FinBERT'] = [get_finbert_sentiment(text) for text in translated_texts]
358
- df['RoBERTa'] = [get_roberta_sentiment(text) for text in translated_texts]
359
- df['FinBERT-Tone'] = [get_finbert_tone_sentiment(text) for text in translated_texts]
360
-
361
  # Initialize LLM
362
  llm = init_langchain_llm()
363
  if not llm:
364
  st.error("Не удалось инициализировать нейросеть. Пожалуйста, проверьте настройки и попробуйте снова.")
365
  st.stop()
366
 
367
- # Perform LLM analysis
368
- df['LLM_Impact'] = ''
369
- df['LLM_Reasoning'] = ''
 
370
 
371
  progress_bar = st.progress(0)
372
  status_text = st.empty()
373
 
 
374
  for index, row in df.iterrows():
375
- if any(row[model] in ['Negative', 'Positive'] for model in ['FinBERT', 'RoBERTa', 'FinBERT-Tone']):
376
- impact, reasoning = estimate_impact(llm, row['Translated'], row['Объект'])
377
- df.at[index, 'LLM_Impact'] = impact
378
- df.at[index, 'LLM_Reasoning'] = reasoning
379
-
380
- st.write(f"Объект: {row['Объект']}")
381
- st.write(f"Новость: {row['Заголовок']}")
382
- st.write(f"Эффект: {impact}")
383
- st.write(f"Обоснование: {reasoning}")
384
- st.write("---")
385
-
386
  progress = (index + 1) / len(df)
387
  progress_bar.progress(progress)
388
  status_text.text(f"Проанализировано {index + 1} из {len(df)} новостей")
389
-
 
 
 
 
 
 
 
 
390
  progress_bar.empty()
391
  status_text.empty()
392
 
 
393
  visualization = generate_sentiment_visualization(df)
394
  if visualization:
395
  st.pyplot(visualization)
396
 
397
  return df
398
 
399
- def create_output_file(df, uploaded_file, analysis_df):
400
- # Load the sample file to use as a template
401
  wb = load_workbook("sample_file.xlsx")
402
 
403
- # Process data for 'Сводка' sheet
404
- entities = df['Объект'].unique()
405
- summary_data = []
406
- for entity in entities:
407
- entity_df = df[df['Объект'] == entity]
408
- total_news = len(entity_df)
409
- negative_news = sum((entity_df['FinBERT'] == 'Negative') |
410
- (entity_df['RoBERTa'] == 'Negative') |
411
- (entity_df['FinBERT-Tone'] == 'Negative'))
412
- positive_news = sum((entity_df['FinBERT'] == 'Positive') |
413
- (entity_df['RoBERTa'] == 'Positive') |
414
- (entity_df['FinBERT-Tone'] == 'Positive'))
415
- summary_data.append([entity, total_news, negative_news, positive_news])
416
-
417
- summary_df = pd.DataFrame(summary_data, columns=['Объект', 'Всего новостей', 'Отрицательные', 'Положительные'])
418
  summary_df = summary_df.sort_values('Отрицательные', ascending=False)
419
 
420
  # Write 'Сводка' sheet
@@ -467,7 +504,7 @@ def create_output_file(df, uploaded_file, analysis_df):
467
 
468
  def generate_sentiment_visualization(df):
469
  # Filter for negative sentiments
470
- negative_df = df[df[['FinBERT', 'RoBERTa', 'FinBERT-Tone']].eq('Negative').any(axis=1)]
471
 
472
  if negative_df.empty:
473
  st.warning("Не обнаружено негативных упоминаний. Отображаем общую статистику по объектам.")
@@ -479,38 +516,17 @@ def generate_sentiment_visualization(df):
479
  st.warning("Нет данных для визуализации.")
480
  return None
481
 
482
- if len(entity_counts) == 1:
483
- st.warning("Обнаружен только один объект. Отображаем статистику в виде столбчатой диаграммы.")
484
- fig, ax = plt.subplots()
485
- entity_counts.plot(kind='bar', ax=ax)
486
- ax.set_title('Количество упоминаний объекта')
487
- ax.set_ylabel('Количество упоминаний')
488
- plt.tight_layout()
489
- return fig
490
-
491
- if len(entity_counts) <= 5:
492
- st.info("Обнаружено малое количество объектов. Отображаем статистику в виде столбчатой диаграммы.")
493
- fig, ax = plt.subplots(figsize=(10, 5))
494
- entity_counts.plot(kind='bar', ax=ax)
495
- ax.set_title('Количество упоминаний объектов')
496
- ax.set_ylabel('Количество упоминаний')
497
- plt.xticks(rotation=45, ha='right')
498
- plt.tight_layout()
499
- return fig
500
-
501
- # If we have enough data, create a word cloud
502
- wordcloud = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(entity_counts)
503
-
504
- fig, ax = plt.subplots(figsize=(10, 5))
505
- ax.imshow(wordcloud, interpolation='bilinear')
506
- ax.axis('off')
507
- ax.set_title('Облако слов: Объекты с негативными упоминаниями' if not negative_df.empty else 'Облако слов: Все упоминания объектов')
508
-
509
  return fig
510
 
511
 
512
  def main():
513
- st.title("... приступим к анализу... версия 70")
514
 
515
  # Initialize session state
516
  if 'processed_df' not in st.session_state:
 
80
  rubert2 = pipeline("sentiment-analysis", model = "blanchefort/rubert-base-cased-sentiment")
81
 
82
 
83
+ def estimate_sentiment_and_impact(llm, news_text, entity):
84
+ template = """
85
+ Проанализируйте следующую новость об объекте "{entity}" и определите:
86
+ 1. Тональность новости (Позитивная/Негативная/Нейтральная)
87
+ 2. Оцените потенциальное финансовое влияние в рублях для этого объекта в ближайшие 6 месяцев.
88
+
89
+ Если точную денежную оценку дать невозможно, категоризируйте влияние как одно из следующих:
90
+ 1. "Значительный риск убытков"
91
+ 2. "Умеренный риск убытков"
92
+ 3. "Незначительный риск убытков"
93
+ 4. "Вероятность прибыли"
94
+ 5. "Неопределенный эффект"
95
+
96
+ Также предоставьте краткое обоснование (максимум 100 слов).
97
 
98
+ Новость: {news}
99
+
100
+ Ответ дайте в следующем формате:
101
+ Sentiment: [Positive/Negative/Neutral]
102
+ Impact: [Ваша оценка или категория]
103
+ Reasoning: [Ваше обоснование]
104
+ """
105
+ prompt = PromptTemplate(template=template, input_variables=["entity", "news"])
106
+ chain = prompt | llm | RunnablePassthrough()
107
+ response = chain.invoke({"entity": entity, "news": news_text})
108
+
109
+ # Parse the response
110
+ sentiment = "Neutral"
111
+ impact = "Неопределенный эффект"
112
+ reasoning = "Не удалось получить обоснование"
113
+
114
+ if isinstance(response, str):
115
+ try:
116
+ # Extract sentiment
117
+ if "Sentiment:" in response:
118
+ sentiment_part = response.split("Sentiment:")[1].split("\n")[0].strip().lower()
119
+ if "positive" in sentiment_part:
120
+ sentiment = "Positive"
121
+ elif "negative" in sentiment_part:
122
+ sentiment = "Negative"
123
+
124
+ # Extract impact and reasoning
125
+ if "Impact:" in response and "Reasoning:" in response:
126
+ impact_part, reasoning_part = response.split("Reasoning:")
127
+ impact = impact_part.split("Impact:")[1].strip()
128
+ reasoning = reasoning_part.strip()
129
+ except Exception as e:
130
+ st.error(f"Error parsing LLM response: {str(e)}")
131
+
132
+ return sentiment, impact, reasoning
133
 
134
  @st.cache_resource
135
  def load_model(model_id):
 
392
 
393
  st.write(f"Из {original_news_count} новостных сообщений удалены {duplicates_removed} дублирующих. Осталось {remaining_news_count}.")
394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  # Initialize LLM
396
  llm = init_langchain_llm()
397
  if not llm:
398
  st.error("Не удалось инициализировать нейросеть. Пожалуйста, проверьте настройки и попробуйте снова.")
399
  st.stop()
400
 
401
+ # Initialize columns for results
402
+ df['Sentiment'] = ''
403
+ df['Impact'] = ''
404
+ df['Reasoning'] = ''
405
 
406
  progress_bar = st.progress(0)
407
  status_text = st.empty()
408
 
409
+ # Process each news item
410
  for index, row in df.iterrows():
411
+ sentiment, impact, reasoning = estimate_sentiment_and_impact(
412
+ llm,
413
+ row['Выдержки из текста'],
414
+ row['Объект']
415
+ )
416
+
417
+ df.at[index, 'Sentiment'] = sentiment
418
+ df.at[index, 'Impact'] = impact
419
+ df.at[index, 'Reasoning'] = reasoning
420
+
421
+ # Display progress
422
  progress = (index + 1) / len(df)
423
  progress_bar.progress(progress)
424
  status_text.text(f"Проанализировано {index + 1} из {len(df)} новостей")
425
+
426
+ # Display each analysis result
427
+ st.write(f"Объект: {row['Объект']}")
428
+ st.write(f"Новость: {row['Заголовок']}")
429
+ st.write(f"Тональность: {sentiment}")
430
+ st.write(f"Эффект: {impact}")
431
+ st.write(f"Обоснование: {reasoning}")
432
+ st.write("---")
433
+
434
  progress_bar.empty()
435
  status_text.empty()
436
 
437
+ # Generate visualization after processing
438
  visualization = generate_sentiment_visualization(df)
439
  if visualization:
440
  st.pyplot(visualization)
441
 
442
  return df
443
 
444
+ def create_output_file(df, uploaded_file):
 
445
  wb = load_workbook("sample_file.xlsx")
446
 
447
+ # Update summary sheet
448
+ summary_df = pd.DataFrame({
449
+ 'Объект': df['Объект'].unique(),
450
+ 'Всего новостей': df.groupby('Объект').size(),
451
+ 'Негативные': df[df['Sentiment'] == 'Negative'].groupby('Объект').size(),
452
+ 'Позитивные': df[df['Sentiment'] == 'Positive'].groupby('Объект').size(),
453
+ 'Преобладающий эффект': df.groupby('Объект')['Impact'].agg(lambda x: x.value_counts().index[0])
454
+ })
 
 
 
 
 
 
 
455
  summary_df = summary_df.sort_values('Отрицательные', ascending=False)
456
 
457
  # Write 'Сводка' sheet
 
504
 
505
  def generate_sentiment_visualization(df):
506
  # Filter for negative sentiments
507
+ negative_df = df[df['Sentiment'] == 'Negative']
508
 
509
  if negative_df.empty:
510
  st.warning("Не обнаружено негативных упоминаний. Отображаем общую статистику по объектам.")
 
516
  st.warning("Нет данных для визуализации.")
517
  return None
518
 
519
+ # Create a horizontal bar chart showing entity risk levels
520
+ fig, ax = plt.subplots(figsize=(12, max(6, len(entity_counts) * 0.5)))
521
+ entity_counts.plot(kind='barh', ax=ax)
522
+ ax.set_title('Количество негативных упоминаний по объектам')
523
+ ax.set_xlabel('Количество упоминаний')
524
+ plt.tight_layout()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  return fig
526
 
527
 
528
  def main():
529
+ st.title("... приступим к анализу... версия 71")
530
 
531
  # Initialize session state
532
  if 'processed_df' not in st.session_state: