Spaces:
Running
Running
import gradio as gr | |
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM | |
import torch | |
import time | |
import threading | |
from collections import deque | |
# === Modelos otimizados para velocidade === | |
MODEL_OPTIONS = { | |
"Microsoft DialoGPT": "microsoft/DialoGPT-small", # Otimizado para conversas | |
"DistilGPT2": "distilgpt2", # Backup rápido | |
"GPT2 Small": "gpt2" # Fallback | |
} | |
# === Configurações otimizadas === | |
MODEL_NAME = MODEL_OPTIONS["Microsoft DialoGPT"] | |
CACHE_SIZE = 50 # Cache das últimas respostas | |
MAX_TOKENS = 100 # Reduzido para velocidade | |
TEMPERATURE = 0.8 # Aumentado para criatividade | |
# === Cache para respostas frequentes === | |
response_cache = {} | |
recent_questions = deque(maxlen=CACHE_SIZE) | |
# === Respostas pré-definidas para perguntas comuns === | |
QUICK_RESPONSES = { | |
"ponteiros": """**Ponteiros em C** são variáveis que armazenam endereços de memória. | |
**Exemplo básico:** | |
```c | |
int x = 10; | |
int *ptr = &x; // ptr aponta para x | |
printf("%d", *ptr); // Imprime 10 | |
``` | |
**Usos principais:** | |
- Passagem por referência | |
- Alocação dinâmica de memória | |
- Estruturas de dados (listas, árvores)""", | |
"java equals": """**Diferença entre == e equals() em Java:** | |
**==** compara referências (endereços na memória) | |
**equals()** compara conteúdo dos objetos | |
**Exemplo:** | |
```java | |
String a = new String("Hello"); | |
String b = new String("Hello"); | |
System.out.println(a == b); // false | |
System.out.println(a.equals(b)); // true | |
```""", | |
"machine learning": """**Machine Learning** é um subcampo da IA onde máquinas aprendem padrões a partir de dados. | |
**Tipos principais:** | |
1. **Supervisionado**: Aprende com exemplos rotulados | |
2. **Não-supervisionado**: Encontra padrões em dados | |
3. **Por reforço**: Aprende através de tentativa e erro | |
**Aplicações**: Reconhecimento de imagem, processamento de linguagem, recomendações.""", | |
"html css javascript": """**Tecnologias Web Fundamentais:** | |
**HTML**: Estrutura da página (esqueleto) | |
**CSS**: Estilização e layout (aparência) | |
**JavaScript**: Interatividade e lógica (comportamento) | |
**Analogia**: | |
- HTML = Estrutura da casa | |
- CSS = Decoração e pintura | |
- JavaScript = Eletricidade e automação""", | |
"algoritmos ordenação": """**Algoritmos de Ordenação:** | |
**Bubble Sort**: O(n²) - Simples, mas lento | |
**Quick Sort**: O(n log n) - Rápido e eficiente | |
**Merge Sort**: O(n log n) - Estável e confiável | |
**Exemplo Quick Sort:** | |
```c | |
void quickSort(int arr[], int low, int high) { | |
if (low < high) { | |
int pi = partition(arr, low, high); | |
quickSort(arr, low, pi - 1); | |
quickSort(arr, pi + 1, high); | |
} | |
} | |
```""" | |
} | |
def get_quick_response(pergunta): | |
"""Verifica se há uma resposta rápida para a pergunta""" | |
pergunta_lower = pergunta.lower() | |
for keyword, response in QUICK_RESPONSES.items(): | |
if keyword in pergunta_lower: | |
return response | |
return None | |
def load_model_optimized(): | |
"""Carrega modelo com configurações otimizadas""" | |
try: | |
print(f"🚀 Carregando modelo otimizado: {MODEL_NAME}") | |
# Carrega com configurações de velocidade | |
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, padding_side='left') | |
if tokenizer.pad_token is None: | |
tokenizer.pad_token = tokenizer.eos_token | |
model = AutoModelForCausalLM.from_pretrained( | |
MODEL_NAME, | |
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32, | |
low_cpu_mem_usage=True | |
) | |
# Pipeline otimizado | |
gerador = pipeline( | |
"text-generation", | |
model=model, | |
tokenizer=tokenizer, | |
device=0 if torch.cuda.is_available() else -1, | |
max_new_tokens=MAX_TOKENS, | |
temperature=TEMPERATURE, | |
top_p=0.9, | |
do_sample=True, | |
pad_token_id=tokenizer.eos_token_id | |
) | |
print("✅ Modelo carregado com sucesso!") | |
return gerador, tokenizer | |
except Exception as e: | |
print(f"❌ Erro ao carregar {MODEL_NAME}: {e}") | |
# Fallback para DistilGPT2 | |
return load_fallback_model() | |
def load_fallback_model(): | |
"""Carrega modelo de fallback""" | |
try: | |
print("🔄 Carregando modelo de fallback...") | |
fallback_name = MODEL_OPTIONS["DistilGPT2"] | |
tokenizer = AutoTokenizer.from_pretrained(fallback_name) | |
if tokenizer.pad_token is None: | |
tokenizer.pad_token = tokenizer.eos_token | |
model = AutoModelForCausalLM.from_pretrained(fallback_name) | |
gerador = pipeline( | |
"text-generation", | |
model=model, | |
tokenizer=tokenizer, | |
device=-1, # Força CPU para economia | |
max_new_tokens=MAX_TOKENS, | |
temperature=TEMPERATURE, | |
do_sample=True | |
) | |
print("✅ Modelo de fallback carregado!") | |
return gerador, tokenizer | |
except Exception as e: | |
raise Exception(f"Falha ao carregar qualquer modelo: {e}") | |
# === Carrega modelo na inicialização === | |
gerador, tokenizer = load_model_optimized() | |
def responder_como_aldo(pergunta): | |
"""Função principal otimizada""" | |
if not pergunta.strip(): | |
return "Por favor, faça uma pergunta específica." | |
start_time = time.time() | |
# 1. Verifica cache de respostas rápidas | |
quick_response = get_quick_response(pergunta) | |
if quick_response: | |
return f"📚 **Resposta Rápida do Dr. Aldo:**\n\n{quick_response}" | |
# 2. Verifica cache de respostas anteriores | |
pergunta_hash = hash(pergunta.lower().strip()) | |
if pergunta_hash in response_cache: | |
cached_response = response_cache[pergunta_hash] | |
return f"💾 **Dr. Aldo responde:**\n\n{cached_response}" | |
# 3. Gera nova resposta | |
try: | |
# Prompt otimizado e conciso | |
if "DialoGPT" in MODEL_NAME: | |
prompt = f"Professor: {pergunta}\nDr. Aldo:" | |
else: | |
prompt = f"Pergunta: {pergunta}\nDr. Aldo Henrique responde:" | |
# Geração com timeout implícito | |
response = gerador( | |
prompt, | |
max_new_tokens=MAX_TOKENS, | |
num_return_sequences=1, | |
truncation=True | |
)[0]["generated_text"] | |
# Limpa resposta | |
if "Dr. Aldo:" in response: | |
resposta_limpa = response.split("Dr. Aldo:")[-1].strip() | |
elif "responde:" in response: | |
resposta_limpa = response.split("responde:")[-1].strip() | |
else: | |
resposta_limpa = response.replace(prompt, "").strip() | |
# Remove repetições comuns | |
resposta_limpa = resposta_limpa.replace(pergunta, "").strip() | |
if not resposta_limpa or len(resposta_limpa) < 10: | |
resposta_limpa = "Desculpe, não consegui gerar uma resposta adequada. Tente reformular sua pergunta." | |
# Salva no cache | |
response_cache[pergunta_hash] = resposta_limpa | |
recent_questions.append(pergunta) | |
elapsed_time = time.time() - start_time | |
return f"🎓 **Dr. Aldo responde** ⚡ *({elapsed_time:.1f}s)*:\n\n{resposta_limpa}" | |
except Exception as e: | |
return f"❌ **Erro temporário**: {str(e)}\n\nTente novamente ou reformule sua pergunta." | |
# === Interface Gradio otimizada === | |
def create_interface(): | |
with gr.Blocks( | |
title="Dr. Aldo Henrique - IA Educacional", | |
theme=gr.themes.Soft(), | |
css=""" | |
.gradio-container { max-width: 900px; margin: auto; } | |
.output-text { font-family: 'Segoe UI', Arial, sans-serif; } | |
.quick-stats { background: #f0f0f0; padding: 10px; border-radius: 5px; } | |
""" | |
) as interface: | |
gr.Markdown(""" | |
# 🎓 Dr. Aldo Henrique - Professor Virtual | |
### 💻 Especialista em C, Java, Web e Inteligência Artificial | |
""") | |
with gr.Row(): | |
gr.Markdown(f""" | |
<div class="quick-stats"> | |
📊 <strong>Status:</strong> Modelo {MODEL_NAME.split('/')[-1]} carregado<br> | |
⚡ <strong>Performance:</strong> Otimizado para respostas rápidas<br> | |
💾 <strong>Cache:</strong> {len(QUICK_RESPONSES)} respostas instantâneas | |
</div> | |
""") | |
with gr.Row(): | |
with gr.Column(scale=2): | |
entrada = gr.Textbox( | |
label="🤔 Sua pergunta para o Dr. Aldo", | |
placeholder="Ex: Como usar ponteiros em C? ou Explique machine learning", | |
lines=3, | |
max_lines=5 | |
) | |
with gr.Row(): | |
botao = gr.Button("🚀 Perguntar", variant="primary", size="lg") | |
limpar = gr.Button("🗑️ Limpar", variant="secondary") | |
with gr.Column(scale=3): | |
saida = gr.Textbox( | |
label="💡 Resposta do Dr. Aldo", | |
lines=12, | |
max_lines=20, | |
interactive=False, | |
elem_classes=["output-text"] | |
) | |
# Exemplos organizados por categoria | |
with gr.Accordion("📚 Exemplos de Perguntas", open=False): | |
gr.Examples( | |
examples=[ | |
["Como usar ponteiros em C?"], | |
["Diferença entre == e equals() em Java"], | |
["O que é machine learning?"], | |
["Explique HTML, CSS e JavaScript"], | |
["Quais são os algoritmos de ordenação?"], | |
["Como implementar uma lista ligada?"], | |
["O que são estruturas de dados?"], | |
["Como funciona recursão?"], | |
["Diferença entre pilha e fila"], | |
["O que é programação orientada a objetos?"] | |
], | |
inputs=entrada, | |
label="Clique em qualquer exemplo" | |
) | |
# Eventos | |
botao.click(fn=responder_como_aldo, inputs=entrada, outputs=saida) | |
limpar.click(fn=lambda: ("", ""), outputs=[entrada, saida]) | |
entrada.submit(fn=responder_como_aldo, inputs=entrada, outputs=saida) | |
gr.Markdown(""" | |
--- | |
<center> | |
✨ <strong>Dica:</strong> Para respostas mais rápidas, use palavras-chave como "ponteiros", "java equals", "machine learning"<br> | |
🔧 <strong>Desenvolvido com:</strong> Transformers + Gradio | <strong>Otimizado para:</strong> Educação em Programação | |
</center> | |
""") | |
return interface | |
# === Lançamento === | |
if __name__ == "__main__": | |
print("🎯 Iniciando Dr. Aldo Henrique - Versão Otimizada") | |
interface = create_interface() | |
interface.launch( | |
server_name="0.0.0.0", | |
server_port=7860, | |
share=False, | |
show_error=True, | |
show_tips=False, | |
quiet=False | |
) |