BugZoid commited on
Commit
fe176a4
·
verified ·
1 Parent(s): af4dae9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -56
app.py CHANGED
@@ -5,6 +5,9 @@ import streamlit as st
5
  from datetime import datetime
6
  import time
7
  from tenacity import retry, stop_after_attempt, wait_exponential
 
 
 
8
 
9
  def debug_print(message):
10
  """Função para imprimir mensagens de debug tanto no console quanto no Streamlit"""
@@ -23,7 +26,7 @@ def fetch_tweets(client, query, tweet_fields):
23
 
24
  tweets = client.search_recent_tweets(
25
  query=query,
26
- max_results=10,
27
  tweet_fields=tweet_fields
28
  )
29
 
@@ -64,6 +67,116 @@ def post_tweet(client, text):
64
  debug_print(f"Erro ao postar tweet: {str(e)}")
65
  raise e
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  def main():
68
  try:
69
  st.title("Análise de Sentimentos - BBB25")
@@ -92,7 +205,7 @@ def main():
92
 
93
  debug_print("Iniciando autenticação com Twitter...")
94
 
95
- # Autenticação com Twitter para leitura e escrita
96
  client = tweepy.Client(
97
  bearer_token=os.getenv('TWITTER_BEARER_TOKEN'),
98
  consumer_key=os.getenv('TWITTER_API_KEY'),
@@ -102,15 +215,9 @@ def main():
102
  wait_on_rate_limit=True
103
  )
104
 
105
- # Vamos testar a autenticação com uma query simples
106
- debug_print("Testando autenticação...")
107
- try:
108
- test_query = "test"
109
- test_response = client.search_recent_tweets(query=test_query, max_results=10)
110
- debug_print("Teste de autenticação bem sucedido")
111
- except Exception as e:
112
- debug_print(f"Erro no teste de autenticação: {str(e)}")
113
- raise e
114
 
115
  # Query principal
116
  query = 'BBB25 lang:pt -is:retweet -is:reply'
@@ -132,16 +239,16 @@ def main():
132
 
133
  debug_print(f"Encontrados {len(tweets.data)} tweets")
134
 
135
- # Mostrar alguns tweets encontrados para debug
136
- st.subheader("Tweets encontrados (preview):")
137
- for i, tweet in enumerate(tweets.data[:3]):
138
- st.text(f"Tweet {i+1}: {tweet.text[:100]}...")
 
139
 
140
  # Análise de sentimentos
141
  with st.spinner('Analisando sentimentos...'):
142
  debug_print("Iniciando análise de sentimentos...")
143
 
144
- # Usando modelo multilingual que suporta português
145
  sentiment_pipeline = pipeline(
146
  "sentiment-analysis",
147
  model="nlptown/bert-base-multilingual-uncased-sentiment"
@@ -151,8 +258,6 @@ def main():
151
  for tweet in tweets.data:
152
  if hasattr(tweet, 'lang') and tweet.lang == 'pt':
153
  result = sentiment_pipeline(tweet.text)
154
- # Este modelo retorna ratings de 1 a 5 estrelas
155
- # Vamos mapear para nossos sentimentos
156
  rating = int(result[0]['label'].split()[0])
157
  if rating >= 4:
158
  sentiments.append('positive')
@@ -173,42 +278,23 @@ def main():
173
 
174
  debug_print(f"Total de sentimentos analisados: {total}")
175
 
176
- positive_ratio = positive / total
177
- negative_ratio = negative / total
178
- neutral_ratio = neutral / total
 
 
179
 
180
- # Gerar mensagem com IA
181
- with st.spinner('Gerando novo tweet...'):
182
- debug_print("Iniciando geração de texto...")
183
- tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
184
- model = GPT2LMHeadModel.from_pretrained('gpt2')
185
-
186
- if positive_ratio > 0.6:
187
- prompt = "Write an exciting tweet about BBB25 with a positive tone in Portuguese."
188
- elif negative_ratio > 0.6:
189
- prompt = "Write an informative tweet about BBB25 with a neutral tone in Portuguese."
190
- else:
191
- prompt = "Write a buzzing tweet about BBB25 with an engaging tone in Portuguese."
192
-
193
- debug_print(f"Usando prompt: {prompt}")
194
-
195
- input_ids = tokenizer.encode(prompt, return_tensors='pt')
196
- outputs = model.generate(
197
- input_ids,
198
- max_length=25,
199
- do_sample=True,
200
- pad_token_id=tokenizer.eos_token_id
201
- )
202
-
203
- generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
204
- generated_text = generated_text[:280]
205
- debug_print(f"Texto gerado: {generated_text}")
206
 
207
  # Postar tweet
208
  with st.spinner('Postando tweet...'):
209
  debug_print("Tentando postar tweet...")
210
  try:
211
- post_tweet(client, generated_text)
212
  st.success("Tweet postado com sucesso!")
213
  debug_print("Tweet postado com sucesso")
214
  except Exception as e:
@@ -221,24 +307,30 @@ def main():
221
  # Mostrar estatísticas
222
  col1, col2, col3 = st.columns(3)
223
  with col1:
224
- st.metric("Sentimento Positivo", f"{positive_ratio:.1%}")
225
  with col2:
226
- st.metric("Sentimento Neutro", f"{neutral_ratio:.1%}")
227
  with col3:
228
- st.metric("Sentimento Negativo", f"{negative_ratio:.1%}")
 
 
 
 
 
229
 
230
  # Mostrar tweet gerado
231
  st.subheader("Tweet Gerado e Postado")
232
- st.write(generated_text)
233
 
234
  # Logging
235
  debug_print("Salvando log...")
236
  log_entry = {
237
  'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
238
- 'positive_ratio': positive_ratio,
239
- 'negative_ratio': negative_ratio,
240
- 'neutral_ratio': neutral_ratio,
241
- 'tweet': generated_text
 
242
  }
243
 
244
  with open('posting_log.txt', 'a') as f:
 
5
  from datetime import datetime
6
  import time
7
  from tenacity import retry, stop_after_attempt, wait_exponential
8
+ import torch
9
+ from collections import Counter
10
+ import re
11
 
12
  def debug_print(message):
13
  """Função para imprimir mensagens de debug tanto no console quanto no Streamlit"""
 
26
 
27
  tweets = client.search_recent_tweets(
28
  query=query,
29
+ max_results=100, # Aumentado para ter mais contexto
30
  tweet_fields=tweet_fields
31
  )
32
 
 
67
  debug_print(f"Erro ao postar tweet: {str(e)}")
68
  raise e
69
 
70
+ def initialize_text_generator():
71
+ """Inicializa o modelo de geração de texto"""
72
+ # Usando um modelo GPT-2 em português maior para melhor qualidade
73
+ model_name = "pierreguillou/gpt2-small-portuguese"
74
+ tokenizer = GPT2Tokenizer.from_pretrained(model_name)
75
+ model = GPT2LMHeadModel.from_pretrained(model_name)
76
+ return model, tokenizer
77
+
78
+ def extract_context_from_tweets(tweets_data):
79
+ """Extrai contexto relevante dos tweets"""
80
+ all_text = " ".join([tweet.text for tweet in tweets_data])
81
+
82
+ # Remover URLs, mentions, RTs e caracteres especiais
83
+ clean_text = re.sub(r'http\S+|@\S+|RT|[^\w\s]', ' ', all_text)
84
+
85
+ # Encontrar nomes de participantes (palavras capitalizadas frequentes)
86
+ words = clean_text.split()
87
+ capitalized_words = [word for word in words if word.istitle() and len(word) > 2]
88
+ participants = Counter(capitalized_words).most_common(5)
89
+
90
+ # Encontrar temas/eventos importantes
91
+ # Procurar por frases comuns que indicam eventos
92
+ event_patterns = [
93
+ r'paredão entre.*?(?=\s|$)',
94
+ r'prova do líder.*?(?=\s|$)',
95
+ r'prova do anjo.*?(?=\s|$)',
96
+ r'eliminação.*?(?=\s|$)',
97
+ r'briga entre.*?(?=\s|$)',
98
+ r'jogo da discórdia.*?(?=\s|$)'
99
+ ]
100
+
101
+ events = []
102
+ for pattern in event_patterns:
103
+ matches = re.findall(pattern, all_text.lower())
104
+ if matches:
105
+ events.extend(matches)
106
+
107
+ return {
108
+ 'participants': [p[0] for p in participants],
109
+ 'events': list(set(events))[:3], # Top 3 eventos únicos
110
+ 'raw_text': clean_text
111
+ }
112
+
113
+ def generate_comment(context, sentiment_ratio, model, tokenizer):
114
+ """Gera um comentário contextualizado sobre o BBB"""
115
+
116
+ # Criar prompt baseado no contexto e sentimento
117
+ sentiment_tone = ""
118
+ if sentiment_ratio['positive'] > 0.5:
119
+ sentiment_tone = "positivo"
120
+ elif sentiment_ratio['negative'] > 0.5:
121
+ sentiment_tone = "negativo"
122
+ else:
123
+ sentiment_tone = "dividido"
124
+
125
+ # Construir contexto para o prompt
126
+ prompt = f"No BBB25, com clima {sentiment_tone}"
127
+
128
+ # Adicionar participantes relevantes
129
+ if context['participants']:
130
+ participants_str = ", ".join(context['participants'][:2])
131
+ prompt += f", {participants_str} se destacam"
132
+
133
+ # Adicionar eventos relevantes
134
+ if context['events']:
135
+ event_str = context['events'][0]
136
+ prompt += f". {event_str.capitalize()}"
137
+
138
+ # Gerar texto
139
+ inputs = tokenizer.encode(prompt, return_tensors='pt', max_length=150, truncation=True)
140
+
141
+ outputs = model.generate(
142
+ inputs,
143
+ max_length=200,
144
+ num_return_sequences=3,
145
+ temperature=0.9,
146
+ top_k=50,
147
+ top_p=0.95,
148
+ do_sample=True,
149
+ no_repeat_ngram_size=2,
150
+ pad_token_id=tokenizer.eos_token_id
151
+ )
152
+
153
+ # Gerar múltiplas opções e escolher a melhor
154
+ generated_texts = []
155
+ for output in outputs:
156
+ text = tokenizer.decode(output, skip_special_tokens=True)
157
+ # Limpar e formatar o texto
158
+ text = re.sub(r'\s+', ' ', text).strip()
159
+ if len(text) > 30: # Garantir que temos um texto substancial
160
+ generated_texts.append(text)
161
+
162
+ # Escolher o melhor texto
163
+ best_text = max(generated_texts, key=len) if generated_texts else prompt
164
+
165
+ # Adicionar hashtags relevantes
166
+ hashtags = " #BBB25"
167
+ if context['participants']:
168
+ hashtags += f" #{context['participants'][0].replace(' ', '')}"
169
+ if context['events']:
170
+ event_tag = context['events'][0].split()[0].capitalize()
171
+ hashtags += f" #{event_tag}"
172
+
173
+ # Garantir que está dentro do limite do Twitter
174
+ max_length = 280 - len(hashtags)
175
+ if len(best_text) > max_length:
176
+ best_text = best_text[:max_length-3] + "..."
177
+
178
+ return best_text + hashtags
179
+
180
  def main():
181
  try:
182
  st.title("Análise de Sentimentos - BBB25")
 
205
 
206
  debug_print("Iniciando autenticação com Twitter...")
207
 
208
+ # Autenticação com Twitter
209
  client = tweepy.Client(
210
  bearer_token=os.getenv('TWITTER_BEARER_TOKEN'),
211
  consumer_key=os.getenv('TWITTER_API_KEY'),
 
215
  wait_on_rate_limit=True
216
  )
217
 
218
+ # Inicializar modelo de geração de texto
219
+ debug_print("Inicializando modelo de geração de texto...")
220
+ model, tokenizer = initialize_text_generator()
 
 
 
 
 
 
221
 
222
  # Query principal
223
  query = 'BBB25 lang:pt -is:retweet -is:reply'
 
239
 
240
  debug_print(f"Encontrados {len(tweets.data)} tweets")
241
 
242
+ # Extrair contexto dos tweets
243
+ context = extract_context_from_tweets(tweets.data)
244
+ debug_print("Contexto extraído dos tweets:")
245
+ debug_print(f"Participantes mencionados: {context['participants']}")
246
+ debug_print(f"Eventos detectados: {context['events']}")
247
 
248
  # Análise de sentimentos
249
  with st.spinner('Analisando sentimentos...'):
250
  debug_print("Iniciando análise de sentimentos...")
251
 
 
252
  sentiment_pipeline = pipeline(
253
  "sentiment-analysis",
254
  model="nlptown/bert-base-multilingual-uncased-sentiment"
 
258
  for tweet in tweets.data:
259
  if hasattr(tweet, 'lang') and tweet.lang == 'pt':
260
  result = sentiment_pipeline(tweet.text)
 
 
261
  rating = int(result[0]['label'].split()[0])
262
  if rating >= 4:
263
  sentiments.append('positive')
 
278
 
279
  debug_print(f"Total de sentimentos analisados: {total}")
280
 
281
+ sentiment_ratios = {
282
+ 'positive': positive / total,
283
+ 'negative': negative / total,
284
+ 'neutral': neutral / total
285
+ }
286
 
287
+ # Gerar comentário usando IA
288
+ with st.spinner('Gerando novo comentário...'):
289
+ debug_print("Iniciando geração de comentário com IA...")
290
+ tweet_text = generate_comment(context, sentiment_ratios, model, tokenizer)
291
+ debug_print(f"Comentário gerado: {tweet_text}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
  # Postar tweet
294
  with st.spinner('Postando tweet...'):
295
  debug_print("Tentando postar tweet...")
296
  try:
297
+ post_tweet(client, tweet_text)
298
  st.success("Tweet postado com sucesso!")
299
  debug_print("Tweet postado com sucesso")
300
  except Exception as e:
 
307
  # Mostrar estatísticas
308
  col1, col2, col3 = st.columns(3)
309
  with col1:
310
+ st.metric("Sentimento Positivo", f"{sentiment_ratios['positive']:.1%}")
311
  with col2:
312
+ st.metric("Sentimento Neutro", f"{sentiment_ratios['neutral']:.1%}")
313
  with col3:
314
+ st.metric("Sentimento Negativo", f"{sentiment_ratios['negative']:.1%}")
315
+
316
+ # Mostrar contexto extraído
317
+ st.subheader("Contexto Analisado")
318
+ st.write("Participantes em destaque:", ", ".join(context['participants']))
319
+ st.write("Eventos detectados:", ", ".join(context['events']))
320
 
321
  # Mostrar tweet gerado
322
  st.subheader("Tweet Gerado e Postado")
323
+ st.write(tweet_text)
324
 
325
  # Logging
326
  debug_print("Salvando log...")
327
  log_entry = {
328
  'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
329
+ 'positive_ratio': sentiment_ratios['positive'],
330
+ 'negative_ratio': sentiment_ratios['negative'],
331
+ 'neutral_ratio': sentiment_ratios['neutral'],
332
+ 'context': context,
333
+ 'tweet': tweet_text
334
  }
335
 
336
  with open('posting_log.txt', 'a') as f: