agent-comment / app.py
BugZoid's picture
Update app.py
7127fcb verified
raw
history blame contribute delete
7.78 kB
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()