#!/usr/bin/env python3 """ Radar Social LGBTQIA+ V2 - Análise Completa da Base Space para análise completa dos 12.102 registros com o modelo RLHF final """ import gradio as gr import pandas as pd import torch from transformers import AutoTokenizer, AutoModelForSequenceClassification from pathlib import Path import logging from datetime import datetime from tqdm import tqdm import os # Configurar logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Versão: 1.2 - Build forçado com correções # Data: 2025-10-25 15:50 class RadarSocialV2: def __init__(self): self.model = None self.tokenizer = None self.dataset = None self.predictions = None self.load_model() self.load_dataset() def load_model(self): """Carrega o modelo RLHF final.""" try: logger.info("📥 Carregando modelo RLHF final...") # Usar modelo do Hugging Face Hub model_name = "Veronyka/tupi-bert-lgbtqia-trained" self.tokenizer = AutoTokenizer.from_pretrained(model_name) self.model = AutoModelForSequenceClassification.from_pretrained( model_name, num_labels=2, torch_dtype=torch.float32 ) logger.info(f"✅ Modelo carregado do Hub: {model_name}") self.model = self.model.to('cpu') self.model.eval() logger.info("🖥️ Modelo pronto para inferência") except Exception as e: logger.error(f"❌ Erro ao carregar modelo: {e}") raise def load_dataset(self): """Carrega a base de dados completa.""" try: logger.info("📊 Carregando base de dados completa...") # Tentar múltiplos caminhos possíveis possible_paths = [ Path("dataset_three_platforms_clean_20251020_140406.csv"), Path("data/dataset_three_platforms_clean_20251020_140406.csv"), Path("/home/user/app/dataset_three_platforms_clean_20251020_140406.csv"), Path("/home/user/app/data/dataset_three_platforms_clean_20251020_140406.csv") ] data_path = None for path in possible_paths: logger.info(f"🔍 Procurando em: {path}") if path.exists(): data_path = path logger.info(f"✅ Arquivo encontrado em: {path}") break if data_path is None: # Listar arquivos disponíveis para debug logger.error("❌ Arquivo não encontrado em nenhum local!") logger.error("📁 Arquivos disponíveis:") for root, dirs, files in os.walk("."): for file in files: logger.error(f" {os.path.join(root, file)}") raise FileNotFoundError("Base de dados não encontrada!") self.dataset = pd.read_csv(data_path) logger.info(f"✅ Base carregada: {len(self.dataset)} exemplos") except Exception as e: logger.error(f"❌ Erro ao carregar base: {e}") raise def predict_text(self, text): """Prediz hate speech para um texto.""" try: # Tokenizar inputs = self.tokenizer( text, truncation=True, padding=True, max_length=512, return_tensors='pt' ) # Predizer with torch.no_grad(): outputs = self.model(**inputs) probs = torch.softmax(outputs.logits, dim=-1) pred = torch.argmax(probs, dim=-1).item() confidence = probs.max().item() # Resultado label = "HATE" if pred == 1 else "NÃO-HATE" prob_hate = probs[0][1].item() return label, confidence, prob_hate except Exception as e: logger.error(f"❌ Erro na predição: {e}") return "ERRO", 0.0, 0.0 def analyze_complete_dataset(self): """Analisa a base completa de 12.102 registros.""" try: logger.info("🔍 Iniciando análise completa da base...") results = [] hate_count = 0 total_confidence = 0 # Processar todos os registros for idx, row in tqdm(self.dataset.iterrows(), total=len(self.dataset), desc="Analisando"): text = row['text'] platform = row['platform'] label, confidence, prob_hate = self.predict_text(text) if label == "HATE": hate_count += 1 total_confidence += confidence results.append({ 'id': row['id'], 'text': text, 'platform': platform, 'prediction': label, 'confidence': confidence, 'prob_hate': prob_hate }) # Calcular estatísticas total_examples = len(results) hate_percentage = (hate_count / total_examples) * 100 avg_confidence = total_confidence / total_examples # Salvar resultados self.predictions = pd.DataFrame(results) # Gerar relatório completo report = f""" # 🏳️‍🌈 ANÁLISE COMPLETA DA BASE - RADAR SOCIAL LGBTQIA+ V2 ## 📊 RESUMO GERAL - **Total de exemplos analisados**: {total_examples:,} - **HATE detectado**: {hate_count:,} ({hate_percentage:.1f}%) - **NÃO-HATE detectado**: {total_examples - hate_count:,} ({100-hate_percentage:.1f}%) - **Confiança média**: {avg_confidence:.1%} ## 📱 ANÁLISE POR PLATAFORMA """ # Estatísticas por plataforma platform_stats = self.predictions.groupby('platform').agg({ 'prediction': ['count', lambda x: (x == 'HATE').sum()], 'confidence': 'mean' }).round(3) platform_stats.columns = ['Total', 'Hate_Count', 'Avg_Confidence'] platform_stats['Hate_Percentage'] = (platform_stats['Hate_Count'] / platform_stats['Total'] * 100).round(1) for platform in platform_stats.index: stats = platform_stats.loc[platform] report += f""" ### {platform} - **Total**: {stats['Total']:,} exemplos - **HATE**: {stats['Hate_Count']:,} ({stats['Hate_Percentage']:.1f}%) - **Confiança média**: {stats['Avg_Confidence']:.1%} """ # Exemplos de alta confiança high_conf_hate = self.predictions[ (self.predictions['prediction'] == 'HATE') & (self.predictions['confidence'] > 0.95) ].head(10) high_conf_no_hate = self.predictions[ (self.predictions['prediction'] == 'NÃO-HATE') & (self.predictions['confidence'] > 0.95) ].head(10) report += f""" ## 🔥 EXEMPLOS DE HATE (Alta Confiança > 95%) """ for idx, row in high_conf_hate.iterrows(): report += f"- **{row['platform']}** ({row['confidence']:.1%}): {row['text'][:100]}...\n" report += f""" ## ✅ EXEMPLOS DE NÃO-HATE (Alta Confiança > 95%) """ for idx, row in high_conf_no_hate.iterrows(): report += f"- **{row['platform']}** ({row['confidence']:.1%}): {row['text'][:100]}...\n" # Distribuição de confiança conf_ranges = [ (0.9, 1.0, "Muito Alta (90-100%)"), (0.8, 0.9, "Alta (80-90%)"), (0.7, 0.8, "Média (70-80%)"), (0.6, 0.7, "Baixa (60-70%)"), (0.0, 0.6, "Muito Baixa (<60%)") ] report += f""" ## 📈 DISTRIBUIÇÃO DE CONFIANÇA """ for min_conf, max_conf, label in conf_ranges: count = len(self.predictions[ (self.predictions['confidence'] >= min_conf) & (self.predictions['confidence'] < max_conf) ]) percentage = (count / total_examples) * 100 report += f"- **{label}**: {count:,} exemplos ({percentage:.1f}%)\n" report += f""" ## 🎯 CONCLUSÕES - O modelo RLHF final apresenta **{avg_confidence:.1%}** de confiança média - **{hate_percentage:.1f}%** dos conteúdos foram classificados como hate speech - A distribuição varia por plataforma, indicando diferentes padrões de linguagem - O modelo está pronto para uso em produção com alta confiabilidade --- *Análise realizada em {datetime.now().strftime('%d/%m/%Y %H:%M')}* """ return report except Exception as e: logger.error(f"❌ Erro na análise completa: {e}") return f"❌ Erro na análise: {e}" # Inicializar o radar radar = RadarSocialV2() # Interface Gradio def create_interface(): with gr.Blocks( title="Radar Social LGBTQIA+ V2 - Análise Completa", theme=gr.themes.Soft(), css=""" .gradio-container { max-width: 1400px !important; } .main-header { text-align: center; padding: 20px; background: linear-gradient(90deg, #ff6b6b, #4ecdc4); color: white; border-radius: 10px; margin-bottom: 20px; } .warning-box { background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 8px; padding: 15px; margin: 20px 0; } """ ) as demo: gr.HTML("""

🏳️‍🌈 Radar Social LGBTQIA+ V2

Análise Completa da Base de 12.102 Registros

Modelo RLHF Final | Análise Detalhada | Relatório Completo

""") gr.HTML("""

⚠️ Importante

Esta análise processará todos os 12.102 registros da base completa. O processo pode levar alguns minutos para ser concluído.

O resultado será um relatório detalhado com estatísticas por plataforma, exemplos de alta confiança e distribuição de confiança do modelo.

""") with gr.Row(): with gr.Column(scale=1): gr.Markdown(""" ### 🎯 Sobre a Análise Esta análise completa irá: - ✅ Processar todos os **12.102 registros** - 📊 Gerar estatísticas por plataforma - 🔥 Mostrar exemplos de hate speech detectados - ✅ Mostrar exemplos de não-hate detectados - 📈 Calcular distribuição de confiança - 🎯 Fornecer conclusões sobre o modelo ### 🤖 Modelo Utilizado - **Nome**: Veronyka/tupi-bert-lgbtqia-trained - **Tipo**: Tupi-BERT-Large + RLHF - **Performance**: 98.4% accuracy - **Confiança média**: 93.8% """) analyze_btn = gr.Button( "🚀 INICIAR ANÁLISE COMPLETA", variant="primary", size="lg" ) gr.Markdown(""" ### 📊 Informações da Base - **Total**: 12.102 exemplos - **Plataformas**: Instagram, TikTok, YouTube - **Período**: 2024-2025 - **Anotação**: Manual + IA + RLHF """) with gr.Column(scale=2): gr.Markdown("### 📋 Relatório de Análise") analysis_output = gr.Markdown( value="👆 Clique no botão acima para iniciar a análise completa da base de dados.", show_copy_button=True ) # Footer gr.HTML("""

🏳️‍🌈 Radar Social LGBTQIA+ V2 | Análise Completa da Base

Desenvolvido com ❤️ para a comunidade LGBTQIA+ brasileira

Última atualização: """ + datetime.now().strftime("%d/%m/%Y %H:%M") + """

""") # Conectar o botão à função de análise analyze_btn.click( fn=radar.analyze_complete_dataset, outputs=analysis_output ) return demo # Criar e lançar a interface if __name__ == "__main__": demo = create_interface() demo.launch( server_name="0.0.0.0", server_port=7860, share=False, show_error=True )