import gradio as gr import pandas as pd import re import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression import joblib import pickle import os from datetime import datetime # ====================== CONFIGURAÇÕES ====================== AREAS = { "IP": "Instituto de Pesquisa", "FD": "Faculdade de Direito", "FE": "Faculdade de Educação", "Reitoria": "Reitoria" } TIPO_MANIFESTACAO = ["Reclamação", "Sugestão"] # ====================== SISTEMA DE VALIDAÇÃO ====================== class ValidadorManifestacoes: def __init__(self): self.carregar_datasets() self.preparar_modelos() def carregar_datasets(self): """Carrega os datasets de validação""" # Palavras ofensivas padrão self.palavras_ofensivas = [ "idiota", "burro", "imbecil", "estupido", "cretino", "analfabeto", "incompetente", "ignorante", "nojento", "asco", "vergonha", "lixo" ] # Frases sem sentido padrão self.frases_sem_sentido = [ "asdfghjkl", "qwertyuiop", "123456789", "aaa bbb ccc", "teste teste", "xyz abc", "mmmm nnnn oooo" ] # Padrões de frases incompletas self.padroes_incompletos = [ "e depois não sei", "mas não", "porque sim", "sem motivo", "só isso", "nada mais", "e pronto" ] def preparar_modelos(self): """Prepara modelos ML para validação de sentido""" self.criar_modelo_sentido_padrao() def criar_modelo_sentido_padrao(self): """Cria modelo padrão se não existir""" # Dados de treino para frases com/sem sentido frases_com_sentido = [ "gostaria de reclamar do atendimento", "sugiro melhorar a limpeza", "o serviço está muito lento", "precisamos de mais computadores", "a internet está caindo muito", "as salas de aula precisam de ar condicionado", "a biblioteca deveria ficar aberta até mais tarde", "os banheiros precisam de manutenção urgente" ] frases_sem_sentido = [ "asdf ghjk qwert", "123 456 789", "teste teste teste", "aaa bbb ccc ddd", "xyz abc def ghi", "mmmm nnnn oooo pppp", "111 222 333 444", "qqqq wwww eeee rrrr" ] textos = frases_com_sentido + frases_sem_sentido labels = [1] * len(frases_com_sentido) + [0] * len(frases_sem_sentido) self.vectorizer_sentido = TfidfVectorizer(max_features=50) X = self.vectorizer_sentido.fit_transform(textos) self.modelo_sentido = LogisticRegression() self.modelo_sentido.fit(X, labels) print("✅ Modelo de validação de sentido criado com sucesso!") def validar_ofensas(self, texto): """Verifica palavras ofensivas""" texto_lower = texto.lower() ofensas_encontradas = [] for palavra in self.palavras_ofensivas: if re.search(r'\b' + re.escape(palavra) + r'\b', texto_lower): ofensas_encontradas.append(palavra) return { "tem_ofensa": len(ofensas_encontradas) > 0, "palavras": ofensas_encontradas, "nivel": "ALTO" if len(ofensas_encontradas) > 2 else "MÉDIO" if len(ofensas_encontradas) > 0 else "BAIXO" } def validar_sentido(self, texto): """Verifica se a frase faz sentido usando ML""" if len(texto.split()) < 3: return {"tem_problema": True, "tipo": "FRASE_MUITO_CURTA"} # Verificar padrões de spam texto_lower = texto.lower() for padrao in self.frases_sem_sentido: if padrao in texto_lower: return {"tem_problema": True, "tipo": "PADRAO_SPAM"} # Usar modelo ML try: X = self.vectorizer_sentido.transform([texto]) predicao = self.modelo_sentido.predict(X)[0] proba = self.modelo_sentido.predict_proba(X)[0][1] if predicao == 0 or proba < 0.3: return {"tem_problema": True, "tipo": "SEM_SENTIDO", "confianca": proba} else: return {"tem_problema": False, "tipo": "OK", "confianca": proba} except Exception as e: print(f"⚠️ Erro no modelo de sentido: {e}") return {"tem_problema": False, "tipo": "OK", "confianca": 0.5} def validar_completude(self, texto): """Verifica se a frase está completa""" texto_limpo = texto.strip() # Verifica se termina com pontuação termina_pontuacao = texto_limpo.endswith(('.', '!', '?', ';', ':')) # Verifica tamanho mínimo palavras = texto_limpo.split() tem_tamanho_minimo = len(palavras) >= 5 # Verifica padrões incompletos texto_lower = texto_limpo.lower() tem_padrao_incompleto = any( padrao in texto_lower for padrao in self.padroes_incompletos ) # Verifica se começa com conectores e não continua conectores = ["e", "mas", "porque", "então", "porém", "contudo"] primeira_palavra = palavras[0].lower() if palavras else "" comeca_conector = primeira_palavra in conectores problemas = [] if not termina_pontuacao: problemas.append("FALTA_PONTUACAO") if not tem_tamanho_minimo: problemas.append("FRASE_MUITO_CURTA") if tem_padrao_incompleto: problemas.append("PADRAO_INCOMPLETO") if comeca_conector and len(palavras) < 4: problemas.append("INICIO_INCOMPLETO") return { "tem_problema": len(problemas) > 0, "problemas": problemas, "pontuacao_ok": termina_pontuacao, "tamanho_ok": tem_tamanho_minimo } def validar_tudo(self, texto): """Executa todas as validações""" resultado_ofensas = self.validar_ofensas(texto) resultado_sentido = self.validar_sentido(texto) resultado_completude = self.validar_completude(texto) alertas = [] if resultado_ofensas["tem_ofensa"]: alertas.append({ "tipo": "🚫 OFENSA", "mensagem": f"Palavras ofensivas detectadas: {', '.join(resultado_ofensas['palavras'])}", "nivel": "ALTO", "cor": "#FF0000" }) if resultado_sentido["tem_problema"]: alertas.append({ "tipo": "🤔 SEM SENTIDO", "mensagem": f"Frase pode não fazer sentido ({resultado_sentido['tipo']})", "nivel": "MÉDIO", "cor": "#FF9900" }) if resultado_completude["tem_problema"]: problemas_texto = ", ".join(resultado_completude["problemas"]) alertas.append({ "tipo": "📝 INCOMPLETO", "mensagem": f"Frase incompleta ou mal estruturada: {problemas_texto}", "nivel": "BAIXO", "cor": "#FFCC00" }) return { "alertas": alertas, "ofensas": resultado_ofensas, "sentido": resultado_sentido, "completude": resultado_completude, "aprovado": len(alertas) == 0 } # ====================== SISTEMA DE CLASSIFICAÇÃO ====================== class ClassificadorAreas: def __init__(self): self.modelo = None self.vectorizer = None self.criar_modelo_padrao() def criar_modelo_padrao(self): """Cria modelo padrão baseado em palavras-chave""" # Dados de treino para cada área dados_treino = { "IP": [ "pesquisa científica", "laboratório", "experimento", "artigo científico", "publicação", "projeto de pesquisa", "cientista", "dados de pesquisa", "metodologia", "análise estatística" ], "FD": [ "direito constitucional", "processo judicial", "advogado", "tribunal", "lei", "jurisprudência", "contrato", "ação judicial", "penal", "civil" ], "FE": [ "educação infantil", "professor", "pedagogia", "ensino fundamental", "currículo escolar", "didática", "aprendizagem", "avaliação", "alfabetização" ], "Reitoria": [ "administração universitária", "reitor", "decisão institucional", "gestão acadêmica", "políticas da universidade", "coordenação geral", "orçamento universitário", "planejamento institucional" ] } textos = [] labels = [] for area, frases in dados_treino.items(): for frase in frases: textos.append(frase) labels.append(area) self.vectorizer = TfidfVectorizer(max_features=100) X = self.vectorizer.fit_transform(textos) self.modelo = LogisticRegression() self.modelo.fit(X, labels) print("✅ Modelo de classificação de áreas criado com sucesso!") def classificar_area(self, texto, area_selecionada): """Classifica a área baseada no texto""" try: X = self.vectorizer.transform([texto]) predicao = self.modelo.predict(X)[0] probabilidade = np.max(self.modelo.predict_proba(X)[0]) # Se a área predita for diferente da selecionada e tiver boa confiança, alertar if predicao != area_selecionada and probabilidade > 0.6: return predicao, probabilidade else: return area_selecionada, probabilidade except Exception as e: print(f"⚠️ Erro na classificação de área: {e}") return area_selecionada, 1.0 # ====================== INICIALIZAR SISTEMAS ====================== print("🔄 Inicializando sistemas...") validador = ValidadorManifestacoes() classificador = ClassificadorAreas() print("✅ Sistemas inicializados com sucesso!") # ====================== FUNÇÕES DA INTERFACE ====================== def processar_manifestacao(tipo, area, mensagem): """Processa a manifestação com todas as validações""" if not mensagem.strip(): return ( "
🔍 Palavras ofensivas: {len(validacao['ofensas']['palavras'])} encontradas
🧠 Faz sentido: {'✅ Sim' if not validacao['sentido']['tem_problema'] else '❌ Não'} ({validacao['sentido'].get('confianca', 0.5):.1%})
📝 Frase completa: {'✅ Sim' if not validacao['completude']['tem_problema'] else '❌ Não'}
🏛️ Área sugerida pelo sistema: {area_sugerida} ({confianca_area:.1%} de confiança)
📊 Status final: {resultado['status']}
Registre reclamações ou sugestões para as áreas da universidade
🚫 Detecção de ofensas: Verifica palavras inadequadas no texto
🤔 Análise de sentido: Identifica frases sem sentido ou spam
📝 Verificação de completude: Checa se a mensagem está bem estruturada
Sugere a área mais apropriada baseada no conteúdo
Compara com a área selecionada pelo usuário
Mostra nível de confiança da sugestão
Status claro (APROVADA ou REQUER REVISÃO)
Alertas detalhados com cores por gravidade
Histórico das últimas manifestações
Dados exportáveis em JSON