ChatBot / app.py
Malleficarum's picture
Update app.py
c976e6a verified
import gradio as gr
import re
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
# Modelos utilizados
MODELOS = {
"primario": "google/flan-t5-small",
"secundario": "google/flan-t5-base",
"arbitro": "google/flan-t5-large"
}
# Carregamento dos modelos e tokenizers
tokenizers = {nome: AutoTokenizer.from_pretrained(modelo)
for nome, modelo in MODELOS.items()}
modelos = {nome: AutoModelForSeq2SeqLM.from_pretrained(modelo)
for nome, modelo in MODELOS.items()}
# Base de capitais com erros comuns
BASE_CAPITAIS = {
'brazil': {
'correta': 'Brasília',
'erros_comuns': ['sao paulo', 'rio de janeiro', 'brazil']
},
'germany': {
'correta': 'Berlin',
'erros_comuns': ['munich', 'frankfurt']
},
'france': {
'correta': 'Paris',
'erros_comuns': ['lyon', 'marseille']
},
# Adicione mais países conforme necessário
}
def gerar_resposta(nome_modelo, pergunta):
"""Gera resposta com o modelo especificado"""
prompt = f"""Aja como um especialista em geografia. Responda APENAS com o nome da capital oficial.
Exemplos:
Q: Capital da França? A: Paris
Q: Capital do Brasil? A: Brasília
Q: Capital da Alemanha? A: Berlin
Q: {pergunta}
A:"""
entrada = tokenizers[nome_modelo](prompt, return_tensors="pt")
saida = modelos[nome_modelo].generate(**entrada, max_length=20)
return tokenizers[nome_modelo].decode(saida[0], skip_special_tokens=True).strip()
def validar_corrigir(pergunta, resposta_bruta):
"""Valida e corrige a resposta com base na base de capitais"""
pergunta = pergunta.lower()
resposta = resposta_bruta.lower()
for pais, dados in BASE_CAPITAIS.items():
if pais in pergunta:
if resposta in dados['erros_comuns']:
return dados['correta']
if resposta == dados['correta'].lower():
return dados['correta']
return dados['correta']
return resposta_bruta.title()
def esta_confiante(resposta, pergunta):
"""Avalia se a resposta pode ser considerada confiável"""
pergunta = pergunta.lower()
resposta = resposta.lower()
for pais, dados in BASE_CAPITAIS.items():
if pais in pergunta:
if resposta == dados['correta'].lower():
return True
if resposta in dados['erros_comuns']:
return False
return False
def arbitrar(pergunta, resposta1, resposta2):
"""Usa o modelo árbitro para escolher a melhor resposta"""
corrigida1 = validar_corrigir(pergunta, resposta1)
corrigida2 = validar_corrigir(pergunta, resposta2)
for pais, dados in BASE_CAPITAIS.items():
if pais in pergunta.lower():
if corrigida1 == dados['correta']:
return corrigida1, "Modelo 1 (validado)"
if corrigida2 == dados['correta']:
return corrigida2, "Modelo 2 (validado)"
prompt = f"""Você é professor de geografia. Escolha a capital correta:
Pergunta: {pergunta}
Opção 1: {corrigida1}
Opção 2: {corrigida2}
Responda SOMENTE com "1" ou "2"."""
entrada = tokenizers['arbitro'](prompt, return_tensors="pt")
saida = modelos['arbitro'].generate(**entrada, max_length=3)
escolha = tokenizers['arbitro'].decode(saida[0], skip_special_tokens=True).strip()
if escolha == "1":
return corrigida1, "Modelo 1 (árbitro)"
else:
return corrigida2, "Modelo 2 (árbitro)"
def chatbot(pergunta):
"""Pipeline em cascata para determinar a capital"""
resposta1 = gerar_resposta("primario", pergunta)
corrigida1 = validar_corrigir(pergunta, resposta1)
if corrigida1 == resposta1 and esta_confiante(corrigida1, pergunta):
return [
f"Resposta Selecionada: {corrigida1}\nModelo Escolhido: Modelo 1 (primário confiante)",
f"Modelo 1 (primário): {resposta1}",
f"Modelo 2 (secundário): Pulado"
]
resposta2 = gerar_resposta("secundario", pergunta)
corrigida2 = validar_corrigir(pergunta, resposta2)
if corrigida2 == resposta2 and esta_confiante(corrigida2, pergunta):
return [
f"Resposta Selecionada: {corrigida2}\nModelo Escolhido: Modelo 2 (secundário confiante)",
f"Modelo 1 (primário): {resposta1}",
f"Modelo 2 (secundário): {resposta2}"
]
resposta_final, modelo_escolhido = arbitrar(pergunta, resposta1, resposta2)
return [
f"Resposta Selecionada: {resposta_final}\nModelo Escolhido: {modelo_escolhido}",
f"Modelo 1 (primário): {resposta1}",
f"Modelo 2 (secundário): {resposta2}"
]
# Markdown content for the article section
article_markdown = """
Gustavo Henrique Xavier da Silva 1758309
Mateus Teixeira Maciel 1650601
Laís Aranda de Souza 1656007
Gustavo Queiroz Fonseca 1771365
### 1. Modelo Primário (google/flan-t5-small)
**Função**: Primeira linha de resposta
**Características**:
- Modelo menor e mais rápido (80M parâmetros)
- Responsável por gerar a resposta inicial
- Ideal para casos simples e óbvios (como capitais bem conhecidas)
**Fluxo no código**:
- Chamado primeiro através da função `gerar_resposta("primario", pergunta)`
- Se sua resposta for validada como confiável (`esta_confiante()` retorna `True`), o sistema retorna imediatamente sem consultar outros modelos
- Caso contrário, o sistema prossegue para o modelo secundário
### 2. Modelo Secundário (google/flan-t5-base)
**Função**: Segunda opinião para casos mais complexos
**Características**:
- Modelo médio (250M parâmetros)
- Maior capacidade que o primário
- Usado quando o primário não tem confiança suficiente
**Fluxo no código**:
- Chamado apenas se o primário não for confiável
- Se sua resposta for validada como confiável, o sistema retorna aqui
- Caso ambos (primário e secundário) não sejam confiáveis, o sistema chama o árbitro
### 3. Modelo Árbitro (google/flan-t5-large)
**Função**: Decisor final em casos de discordância
**Características**:
- Modelo maior e mais capaz (800M parâmetros)
- Atua como "juiz" entre as respostas do primário e secundário
- Só é acionado quando os dois primeiros modelos dão respostas diferentes e não confiáveis
**Fluxo no código**:
- Chamado através da função `arbitrar()`
- Recebe a pergunta original e as duas respostas corrigidas
- Decide qual das duas respostas é mais provavelmente correta
- Pode também corrigir ambas as respostas se necessário
## Sistema de Validação e Correção
Além dos modelos, o sistema possui:
- **Base de Conhecimento**: `BASE_CAPITAIS` com respostas corretas e erros comuns
- **Função `validar_corrigir()`**: Compara respostas com a base de conhecimento
- **Função `esta_confiante()`**: Determina se uma resposta pode ser aceita sem arbitragem
## Fluxo de Decisão
1. Tenta primeiro com o modelo pequeno (rápido)
2. Se não confiável, tenta com o modelo médio
3. Se ainda não resolvido, usa o modelo grande como árbitro
4. Sempre aplica validação/correção baseada na base de conhecimento
Essa abordagem em cascata equilibra velocidade e precisão, usando modelos maiores apenas quando necessário.
"""
# Interface Gradio
interface = gr.Interface(
fn=chatbot,
inputs=gr.Textbox(label="Pergunte a capital de um país", placeholder="Qual é a capital do Brasil?"),
outputs=[
gr.Textbox(label="Resposta Final"),
gr.Textbox(label="Resposta do Modelo 1"),
gr.Textbox(label="Resposta do Modelo 2")
],
title="🗺️ Especialista em Capitais (Cascata com Correção Automática)",
description="Sistema com três modelos em cascata. Pergunte sobre a capital de qualquer país. Exemplos: Brasil, Alemanha, França...",
article=article_markdown
)
if __name__ == "__main__":
interface.launch()