| """ |
| Exemplo de uso do Radar Legislativo LGBTQIA+ |
| Sistema de classificação de Projetos de Lei por Ensemble Híbrido |
| """ |
|
|
| from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification |
| import re |
|
|
| print("🏳️🌈 Radar Legislativo LGBTQIA+ - Exemplo de Uso\n") |
|
|
| |
| |
| |
|
|
| print("📦 Carregando modelos...") |
|
|
| |
| print(" Carregando Radar Social...") |
| radar = pipeline( |
| "text-classification", |
| model="Veronyka/radar-social-lgbtqia-v2.1", |
| device=-1 |
| ) |
|
|
| |
| print(" Carregando AzMina...") |
| try: |
| tokenizer = AutoTokenizer.from_pretrained("neuralmind/bert-base-portuguese-cased") |
| azmina_model = AutoModelForSequenceClassification.from_pretrained("azmina/ia-feminista-bert-posicao") |
| azmina = pipeline( |
| "text-classification", |
| model=azmina_model, |
| tokenizer=tokenizer, |
| device=-1 |
| ) |
| print(" ✅ Ambos os modelos carregados com sucesso!\n") |
| except Exception as e: |
| print(f" ⚠️ Erro ao carregar AzMina: {e}") |
| print(" ℹ️ Sistema funcionará sem AzMina\n") |
| azmina = None |
|
|
| |
| |
| |
|
|
| KEYWORDS_DESFAVORAVEIS = [ |
| r"proíbe.*gênero", r"ideologia de gênero", r"sexo biológico", |
| r"terapia.*conversão", r"cura.*gay", r"família.*tradicional", |
| r"veda.*gênero", r"restringe.*gênero" |
| ] |
|
|
| PADROES_ALTA_PRIORIDADE = [ |
| r"(proíbe|veda).*(uso|exibição).*(símbolo|símbolos).*religios.*(parada|lgbt)", |
| r"(impede|proíbe).*(menor|criança).*(evento|parada).*(lgbt|comunidade)" |
| ] |
|
|
| PADROES_RESTRITIVOS = [ |
| r"define.*(sexo|gênero).*biolog", |
| r"(proíbe|proibição).*(ensino|divulgação).*gênero", |
| r"exclusivamente.*(homem|mulher).*(cis|biologic)" |
| ] |
|
|
| |
| |
| |
|
|
| def classificar_pl(ementa: str) -> dict: |
| """ |
| Classifica uma PL usando Ensemble Híbrido |
| |
| Args: |
| ementa: Texto da ementa da PL |
| |
| Returns: |
| dict com classificação, score e detalhes |
| """ |
| |
| |
| radar_result = radar(ementa, truncation=True, max_length=256) |
| label_radar = radar_result[0]['label'] |
| score_radar_raw = radar_result[0]['score'] |
| score_radar = score_radar_raw if label_radar == 'HATE' else 1 - score_radar_raw |
| |
| |
| if azmina: |
| azmina_result = azmina(ementa, truncation=True, max_length=256) |
| label_azmina = azmina_result[0]['label'] |
| score_azmina_raw = azmina_result[0]['score'] |
| score_azmina = 1 - score_azmina_raw if label_azmina == 'LABEL_1' else score_azmina_raw |
| peso_azmina = 0.15 |
| else: |
| score_azmina = 0.5 |
| peso_azmina = 0.0 |
| |
| |
| ementa_lower = ementa.lower() |
| kw_desfav = sum(1 for kw in KEYWORDS_DESFAVORAVEIS if re.search(kw, ementa_lower, re.IGNORECASE)) |
| score_keywords = min(kw_desfav / 5, 1.0) |
| peso_keywords = 0.40 if not azmina else 0.35 |
| |
| |
| matches_alta = sum(1 for padrao in PADROES_ALTA_PRIORIDADE if re.search(padrao, ementa_lower, re.IGNORECASE)) |
| matches_normais = sum(1 for padrao in PADROES_RESTRITIVOS if re.search(padrao, ementa_lower, re.IGNORECASE)) |
| |
| if matches_alta > 0: |
| score_padroes = 0.99 |
| else: |
| score_padroes = min(matches_normais / 3, 1.0) |
| |
| peso_padroes = 0.40 if not azmina else 0.30 |
| peso_radar = 0.20 |
| |
| |
| score_final = ( |
| peso_radar * score_radar + |
| peso_azmina * score_azmina + |
| peso_keywords * score_keywords + |
| peso_padroes * score_padroes |
| ) |
| |
| |
| if score_final >= 0.5: |
| classificacao = "DESFAVORÁVEL" |
| emoji = "❌" |
| elif score_final >= 0.3: |
| classificacao = "REVISÃO" |
| emoji = "⚠️" |
| else: |
| classificacao = "FAVORÁVEL" |
| emoji = "✅" |
| |
| return { |
| 'classificacao': classificacao, |
| 'emoji': emoji, |
| 'score_final': score_final, |
| 'sinais': { |
| 'radar': score_radar, |
| 'azmina': score_azmina if azmina else None, |
| 'keywords': score_keywords, |
| 'padroes': score_padroes |
| }, |
| 'pesos': { |
| 'radar': peso_radar, |
| 'azmina': peso_azmina, |
| 'keywords': peso_keywords, |
| 'padroes': peso_padroes |
| }, |
| 'detalhes': { |
| 'keywords_encontradas': kw_desfav, |
| 'padroes_alta_prioridade': matches_alta, |
| 'padroes_normais': matches_normais |
| } |
| } |
|
|
| |
| |
| |
|
|
| print("=" * 70) |
| print("🧪 TESTANDO CLASSIFICAÇÃO DE PLs") |
| print("=" * 70) |
|
|
| exemplos = [ |
| { |
| 'id': 'PL 106/2023', |
| 'ementa': 'Proíbe o uso de símbolos religiosos em paradas LGBTQIA+', |
| 'esperado': 'DESFAVORÁVEL' |
| }, |
| { |
| 'id': 'PL 5034/2020', |
| 'ementa': 'Equipara terapias de conversão à tortura', |
| 'esperado': 'FAVORÁVEL' |
| }, |
| { |
| 'id': 'PL 906/2024', |
| 'ementa': 'Impede a presença de menores em eventos da comunidade LGBTQIA+', |
| 'esperado': 'DESFAVORÁVEL' |
| }, |
| { |
| 'id': 'PL 1234/2022', |
| 'ementa': 'Dispõe sobre identidade de gênero e nome social em documentos oficiais', |
| 'esperado': 'FAVORÁVEL' |
| } |
| ] |
|
|
| for exemplo in exemplos: |
| print(f"\n📄 {exemplo['id']}") |
| print(f" Ementa: \"{exemplo['ementa']}\"") |
| print(f" Esperado: {exemplo['esperado']}") |
| |
| resultado = classificar_pl(exemplo['ementa']) |
| |
| print(f" {resultado['emoji']} Classificação: {resultado['classificacao']}") |
| print(f" 📊 Score Final: {resultado['score_final']:.2%}") |
| print(f" 🔍 Detalhes:") |
| print(f" - Radar Social: {resultado['sinais']['radar']:.2%} (peso {resultado['pesos']['radar']:.0%})") |
| if resultado['sinais']['azmina'] is not None: |
| print(f" - AzMina: {resultado['sinais']['azmina']:.2%} (peso {resultado['pesos']['azmina']:.0%})") |
| print(f" - Keywords: {resultado['sinais']['keywords']:.2%} (peso {resultado['pesos']['keywords']:.0%})") |
| print(f" - Padrões: {resultado['sinais']['padroes']:.2%} (peso {resultado['pesos']['padroes']:.0%})") |
| |
| |
| acertou = "✅" if resultado['classificacao'] == exemplo['esperado'] else "❌" |
| print(f" {acertou} Classificação correta? {resultado['classificacao'] == exemplo['esperado']}") |
|
|
| print("\n" + "=" * 70) |
| print("✅ Exemplos concluídos!") |
| print("=" * 70) |
|
|
| |
| |
| |
|
|
| print("\n💡 Dica: Para usar interativamente, chame:") |
| print(" resultado = classificar_pl('sua ementa aqui')") |
| print(" print(resultado)") |
|
|
|
|