agent-comment / app.py
BugZoid's picture
Update app.py
7127fcb verified
import tweepy
from transformers import pipeline, GPT2LMHeadModel, GPT2Tokenizer
import os
import streamlit as st
from datetime import datetime
import time
from tenacity import retry, stop_after_attempt, wait_exponential
import re
from collections import Counter
def debug_print(message):
"""Função para imprimir mensagens de debug tanto no console quanto no Streamlit"""
print(message)
st.text(message)
@retry(
stop=stop_after_attempt(2), # Reduzido para 2 tentativas
wait=wait_exponential(multiplier=1, min=2, max=4), # Tempo de espera reduzido
retry=lambda e: isinstance(e, tweepy.errors.TooManyRequests)
)
def fetch_tweets(client, query, tweet_fields):
try:
tweets = client.search_recent_tweets(
query=query,
max_results=10, # Reduzido para 10 tweets
tweet_fields=tweet_fields
)
if not hasattr(tweets, 'data') or tweets.data is None:
return None
return tweets
except Exception as e:
debug_print(f"Erro na busca: {str(e)}")
return None
def post_tweet(client, text):
try:
response = client.create_tweet(text=text)
return response
except Exception as e:
debug_print(f"Erro ao postar tweet: {str(e)}")
return None
def extract_context_from_tweets(tweets_data):
"""Versão simplificada da extração de contexto"""
all_text = " ".join([tweet.text for tweet in tweets_data])
clean_text = re.sub(r'http\S+|@\S+|RT|[^\w\s]', ' ', all_text)
# Encontrar nomes capitalizados frequentes
words = clean_text.split()
capitalized_words = [word for word in words if word.istitle() and len(word) > 2]
participants = Counter(capitalized_words).most_common(3) # Reduzido para 3
# Eventos simplificados
events = []
event_keywords = ['paredão', 'prova', 'líder', 'eliminação', 'briga']
for keyword in event_keywords:
if keyword in clean_text.lower():
events.append(keyword)
return {
'participants': [p[0] for p in participants],
'events': events[:2], # Limitado a 2 eventos
'raw_text': clean_text
}
def generate_comment(context, sentiment_ratio, model, tokenizer):
"""Versão otimizada da geração de comentários"""
# Determinar o tom com base no sentimento
if sentiment_ratio['positive'] > 0.5:
tone = "clima animado"
elif sentiment_ratio['negative'] > 0.5:
tone = "clima tenso"
else:
tone = "opiniões divididas"
# Construir prompt base
prompt = f"BBB25 com {tone}"
# Adicionar contexto se disponível
if context['participants']:
prompt += f", {context['participants'][0]}"
if context['events']:
prompt += f", {context['events'][0]}"
# Gerar texto
try:
inputs = tokenizer.encode(prompt, return_tensors='pt', max_length=100, truncation=True)
outputs = model.generate(
inputs,
max_length=150, # Reduzido para melhor performance
num_return_sequences=1, # Apenas uma sequência
temperature=0.8,
top_k=40,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
text = re.sub(r'\s+', ' ', text).strip()
# Adicionar hashtags
hashtags = " #BBB25"
if len(text) + len(hashtags) > 280:
text = text[:277-len(hashtags)] + "..."
return text + hashtags
except Exception as e:
debug_print(f"Erro na geração: {str(e)}")
return f"BBB25: {tone} hoje! #BBB25" # Fallback simples
def main():
try:
st.title("Análise de Sentimentos - BBB25")
# Verificação simplificada de variáveis de ambiente
required_vars = [
'TWITTER_API_KEY',
'TWITTER_API_SECRET_KEY',
'TWITTER_ACCESS_TOKEN',
'TWITTER_ACCESS_TOKEN_SECRET',
'TWITTER_BEARER_TOKEN'
]
if any(os.getenv(var) is None for var in required_vars):
raise ValueError("Faltam variáveis de ambiente necessárias")
# Autenticação Twitter
client = tweepy.Client(
bearer_token=os.getenv('TWITTER_BEARER_TOKEN'),
consumer_key=os.getenv('TWITTER_API_KEY'),
consumer_secret=os.getenv('TWITTER_API_SECRET_KEY'),
access_token=os.getenv('TWITTER_ACCESS_TOKEN'),
access_token_secret=os.getenv('TWITTER_ACCESS_TOKEN_SECRET'),
wait_on_rate_limit=True
)
# Inicializar modelo
model_name = "pierreguillou/gpt2-small-portuguese"
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
model = GPT2LMHeadModel.from_pretrained(model_name)
# Buscar tweets
query = 'BBB25 lang:pt -is:retweet -is:reply'
tweet_fields = ['text', 'created_at']
with st.spinner('Buscando tweets...'):
tweets = fetch_tweets(client, query, tweet_fields)
if tweets is None or not tweets.data:
st.error("Não foi possível obter tweets")
return
context = extract_context_from_tweets(tweets.data)
# Análise de sentimentos
with st.spinner('Analisando sentimentos...'):
sentiment_pipeline = pipeline(
"sentiment-analysis",
model="nlptown/bert-base-multilingual-uncased-sentiment"
)
sentiments = []
for tweet in tweets.data[:10]: # Limitado a 10 tweets
result = sentiment_pipeline(tweet.text[:512]) # Limitado a 512 caracteres
rating = int(result[0]['label'].split()[0])
if rating >= 4:
sentiments.append('positive')
elif rating <= 2:
sentiments.append('negative')
else:
sentiments.append('neutral')
# Calcular taxas
if sentiments:
total = len(sentiments)
sentiment_ratios = {
'positive': sentiments.count('positive') / total,
'negative': sentiments.count('negative') / total,
'neutral': sentiments.count('neutral') / total
}
# Gerar e postar tweet
with st.spinner('Gerando e postando tweet...'):
tweet_text = generate_comment(context, sentiment_ratios, model, tokenizer)
post_tweet(client, tweet_text)
# Interface
st.title("Resultados")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Positivo", f"{sentiment_ratios['positive']:.1%}")
with col2:
st.metric("Neutro", f"{sentiment_ratios['neutral']:.1%}")
with col3:
st.metric("Negativo", f"{sentiment_ratios['negative']:.1%}")
st.subheader("Tweet Gerado")
st.write(tweet_text)
# Log simplificado
with open('posting_log.txt', 'a') as f:
f.write(f"{datetime.now()}: {tweet_text}\n")
except Exception as e:
st.error(f"Erro: {str(e)}")
finally:
st.markdown("---")
st.markdown(
"""
<div style='text-align: center'>
<small>Desenvolvido com ❤️ usando Streamlit e Transformers</small>
</div>
""",
unsafe_allow_html=True
)
if __name__ == "__main__":
main()