aldohenrique commited on
Commit
d548a42
·
verified ·
1 Parent(s): 5f8d463

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -298
app.py CHANGED
@@ -1,319 +1,92 @@
1
  import gradio as gr
2
- from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
3
  import torch
4
- import time
5
- import threading
6
- from collections import deque
7
 
8
- # === Modelos otimizados para velocidade ===
9
- MODEL_OPTIONS = {
10
- "Microsoft DialoGPT": "microsoft/DialoGPT-small", # Otimizado para conversas
11
- "DistilGPT2": "distilgpt2", # Backup rápido
12
- "GPT2 Small": "gpt2" # Fallback
13
- }
14
 
15
- # === Configurações otimizadas ===
16
- MODEL_NAME = MODEL_OPTIONS["Microsoft DialoGPT"]
17
- CACHE_SIZE = 50 # Cache das últimas respostas
18
- MAX_TOKENS = 100 # Reduzido para velocidade
19
- TEMPERATURE = 0.8 # Aumentado para criatividade
20
-
21
- # === Cache para respostas frequentes ===
22
- response_cache = {}
23
- recent_questions = deque(maxlen=CACHE_SIZE)
24
-
25
- # === Respostas pré-definidas para perguntas comuns ===
26
- QUICK_RESPONSES = {
27
- "ponteiros": """**Ponteiros em C** são variáveis que armazenam endereços de memória.
28
-
29
- **Exemplo básico:**
30
- ```c
31
- int x = 10;
32
- int *ptr = &x; // ptr aponta para x
33
- printf("%d", *ptr); // Imprime 10
34
- ```
35
-
36
- **Usos principais:**
37
- - Passagem por referência
38
- - Alocação dinâmica de memória
39
- - Estruturas de dados (listas, árvores)""",
40
-
41
- "java equals": """**Diferença entre == e equals() em Java:**
42
-
43
- **==** compara referências (endereços na memória)
44
- **equals()** compara conteúdo dos objetos
45
-
46
- **Exemplo:**
47
- ```java
48
- String a = new String("Hello");
49
- String b = new String("Hello");
50
- System.out.println(a == b); // false
51
- System.out.println(a.equals(b)); // true
52
- ```""",
53
-
54
- "machine learning": """**Machine Learning** é um subcampo da IA onde máquinas aprendem padrões a partir de dados.
55
-
56
- **Tipos principais:**
57
- 1. **Supervisionado**: Aprende com exemplos rotulados
58
- 2. **Não-supervisionado**: Encontra padrões em dados
59
- 3. **Por reforço**: Aprende através de tentativa e erro
60
-
61
- **Aplicações**: Reconhecimento de imagem, processamento de linguagem, recomendações.""",
62
-
63
- "html css javascript": """**Tecnologias Web Fundamentais:**
64
-
65
- **HTML**: Estrutura da página (esqueleto)
66
- **CSS**: Estilização e layout (aparência)
67
- **JavaScript**: Interatividade e lógica (comportamento)
68
-
69
- **Analogia**:
70
- - HTML = Estrutura da casa
71
- - CSS = Decoração e pintura
72
- - JavaScript = Eletricidade e automação""",
73
-
74
- "algoritmos ordenação": """**Algoritmos de Ordenação:**
75
-
76
- **Bubble Sort**: O(n²) - Simples, mas lento
77
- **Quick Sort**: O(n log n) - Rápido e eficiente
78
- **Merge Sort**: O(n log n) - Estável e confiável
79
 
80
- **Exemplo Quick Sort:**
81
- ```c
82
- void quickSort(int arr[], int low, int high) {
83
- if (low < high) {
84
- int pi = partition(arr, low, high);
85
- quickSort(arr, low, pi - 1);
86
- quickSort(arr, pi + 1, high);
87
- }
88
- }
89
- ```"""
90
- }
91
 
92
- def get_quick_response(pergunta):
93
- """Verifica se há uma resposta rápida para a pergunta"""
94
- pergunta_lower = pergunta.lower()
95
-
96
- for keyword, response in QUICK_RESPONSES.items():
97
- if keyword in pergunta_lower:
98
- return response
99
- return None
100
-
101
- def load_model_optimized():
102
- """Carrega modelo com configurações otimizadas"""
103
  try:
104
- print(f"🚀 Carregando modelo otimizado: {MODEL_NAME}")
105
-
106
- # Carrega com configurações de velocidade
107
- tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, padding_side='left')
108
- if tokenizer.pad_token is None:
109
- tokenizer.pad_token = tokenizer.eos_token
110
-
111
- model = AutoModelForCausalLM.from_pretrained(
112
- MODEL_NAME,
113
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
114
- low_cpu_mem_usage=True
115
- )
116
-
117
- # Pipeline otimizado
118
- gerador = pipeline(
119
- "text-generation",
120
- model=model,
121
- tokenizer=tokenizer,
122
- device=0 if torch.cuda.is_available() else -1,
123
- max_new_tokens=MAX_TOKENS,
124
- temperature=TEMPERATURE,
125
  top_p=0.9,
126
  do_sample=True,
127
  pad_token_id=tokenizer.eos_token_id
128
  )
129
-
130
- print(" Modelo carregado com sucesso!")
131
- return gerador, tokenizer
132
-
133
- except Exception as e:
134
- print(f"❌ Erro ao carregar {MODEL_NAME}: {e}")
135
- # Fallback para DistilGPT2
136
- return load_fallback_model()
137
-
138
- def load_fallback_model():
139
- """Carrega modelo de fallback"""
140
- try:
141
- print("🔄 Carregando modelo de fallback...")
142
- fallback_name = MODEL_OPTIONS["DistilGPT2"]
143
-
144
- tokenizer = AutoTokenizer.from_pretrained(fallback_name)
145
- if tokenizer.pad_token is None:
146
- tokenizer.pad_token = tokenizer.eos_token
147
-
148
- model = AutoModelForCausalLM.from_pretrained(fallback_name)
149
-
150
- gerador = pipeline(
151
- "text-generation",
152
- model=model,
153
- tokenizer=tokenizer,
154
- device=-1, # Força CPU para economia
155
- max_new_tokens=MAX_TOKENS,
156
- temperature=TEMPERATURE,
157
- do_sample=True
158
- )
159
-
160
- print("✅ Modelo de fallback carregado!")
161
- return gerador, tokenizer
162
-
163
  except Exception as e:
164
- raise Exception(f"Falha ao carregar qualquer modelo: {e}")
165
-
166
- # === Carrega modelo na inicialização ===
167
- gerador, tokenizer = load_model_optimized()
168
 
169
- def responder_como_aldo(pergunta):
170
- """Função principal otimizada"""
171
- if not pergunta.strip():
172
- return "Por favor, faça uma pergunta específica."
173
-
174
- start_time = time.time()
175
 
176
- # 1. Verifica cache de respostas rápidas
177
- quick_response = get_quick_response(pergunta)
178
- if quick_response:
179
- return f"📚 **Resposta Rápida do Dr. Aldo:**\n\n{quick_response}"
180
 
181
- # 2. Verifica cache de respostas anteriores
182
- pergunta_hash = hash(pergunta.lower().strip())
183
- if pergunta_hash in response_cache:
184
- cached_response = response_cache[pergunta_hash]
185
- return f"💾 **Dr. Aldo responde:**\n\n{cached_response}"
186
-
187
- # 3. Gera nova resposta
188
- try:
189
- # Prompt otimizado e conciso
190
- if "DialoGPT" in MODEL_NAME:
191
- prompt = f"Professor: {pergunta}\nDr. Aldo:"
192
- else:
193
- prompt = f"Pergunta: {pergunta}\nDr. Aldo Henrique responde:"
194
-
195
- # Geração com timeout implícito
196
- response = gerador(
197
- prompt,
198
- max_new_tokens=MAX_TOKENS,
199
- num_return_sequences=1,
200
- truncation=True
201
- )[0]["generated_text"]
202
-
203
- # Limpa resposta
204
- if "Dr. Aldo:" in response:
205
- resposta_limpa = response.split("Dr. Aldo:")[-1].strip()
206
- elif "responde:" in response:
207
- resposta_limpa = response.split("responde:")[-1].strip()
208
- else:
209
- resposta_limpa = response.replace(prompt, "").strip()
210
-
211
- # Remove repetições comuns
212
- resposta_limpa = resposta_limpa.replace(pergunta, "").strip()
213
-
214
- if not resposta_limpa or len(resposta_limpa) < 10:
215
- resposta_limpa = "Desculpe, não consegui gerar uma resposta adequada. Tente reformular sua pergunta."
216
-
217
- # Salva no cache
218
- response_cache[pergunta_hash] = resposta_limpa
219
- recent_questions.append(pergunta)
220
-
221
- elapsed_time = time.time() - start_time
222
-
223
- return f"🎓 **Dr. Aldo responde** ⚡ *({elapsed_time:.1f}s)*:\n\n{resposta_limpa}"
224
-
225
- except Exception as e:
226
- return f"❌ **Erro temporário**: {str(e)}\n\nTente novamente ou reformule sua pergunta."
227
-
228
- # === Interface Gradio otimizada ===
229
- def create_interface():
230
- with gr.Blocks(
231
- title="Dr. Aldo Henrique - IA Educacional",
232
- theme=gr.themes.Soft(),
233
- css="""
234
- .gradio-container { max-width: 900px; margin: auto; }
235
- .output-text { font-family: 'Segoe UI', Arial, sans-serif; }
236
- .quick-stats { background: #f0f0f0; padding: 10px; border-radius: 5px; }
237
- """
238
- ) as interface:
239
-
240
- gr.Markdown("""
241
- # 🎓 Dr. Aldo Henrique - Professor Virtual
242
- ### 💻 Especialista em C, Java, Web e Inteligência Artificial
243
- """)
244
-
245
- with gr.Row():
246
- gr.Markdown(f"""
247
- <div class="quick-stats">
248
- 📊 <strong>Status:</strong> Modelo {MODEL_NAME.split('/')[-1]} carregado<br>
249
- ⚡ <strong>Performance:</strong> Otimizado para respostas rápidas<br>
250
- 💾 <strong>Cache:</strong> {len(QUICK_RESPONSES)} respostas instantâneas
251
- </div>
252
- """)
253
-
254
- with gr.Row():
255
- with gr.Column(scale=2):
256
- entrada = gr.Textbox(
257
- label="🤔 Sua pergunta para o Dr. Aldo",
258
- placeholder="Ex: Como usar ponteiros em C? ou Explique machine learning",
259
- lines=3,
260
- max_lines=5
261
- )
262
-
263
- with gr.Row():
264
- botao = gr.Button("🚀 Perguntar", variant="primary", size="lg")
265
- limpar = gr.Button("🗑️ Limpar", variant="secondary")
266
-
267
- with gr.Column(scale=3):
268
- saida = gr.Textbox(
269
- label="💡 Resposta do Dr. Aldo",
270
- lines=12,
271
- max_lines=20,
272
- interactive=False,
273
- elem_classes=["output-text"]
274
- )
275
-
276
- # Exemplos organizados por categoria
277
- with gr.Accordion("📚 Exemplos de Perguntas", open=False):
278
- gr.Examples(
279
- examples=[
280
- ["Como usar ponteiros em C?"],
281
- ["Diferença entre == e equals() em Java"],
282
- ["O que é machine learning?"],
283
- ["Explique HTML, CSS e JavaScript"],
284
- ["Quais são os algoritmos de ordenação?"],
285
- ["Como implementar uma lista ligada?"],
286
- ["O que são estruturas de dados?"],
287
- ["Como funciona recursão?"],
288
- ["Diferença entre pilha e fila"],
289
- ["O que é programação orientada a objetos?"]
290
- ],
291
- inputs=entrada,
292
- label="Clique em qualquer exemplo"
293
- )
294
-
295
- # Eventos
296
- botao.click(fn=responder_como_aldo, inputs=entrada, outputs=saida)
297
- limpar.click(fn=lambda: ("", ""), outputs=[entrada, saida])
298
- entrada.submit(fn=responder_como_aldo, inputs=entrada, outputs=saida)
299
-
300
- gr.Markdown("""
301
- ---
302
- <center>
303
- ✨ <strong>Dica:</strong> Para respostas mais rápidas, use palavras-chave como "ponteiros", "java equals", "machine learning"<br>
304
- 🔧 <strong>Desenvolvido com:</strong> Transformers + Gradio | <strong>Otimizado para:</strong> Educação em Programação
305
- </center>
306
- """)
307
-
308
- return interface
309
-
310
- # === Lançamento ===
311
  if __name__ == "__main__":
312
- print("🎯 Iniciando Dr. Aldo Henrique - Versão Otimizada")
313
- interface = create_interface()
314
  interface.launch(
315
  server_name="0.0.0.0",
316
  server_port=7860,
317
  share=False,
318
- show_error=True
 
319
  )
 
1
  import gradio as gr
2
+ from transformers import AutoTokenizer, AutoModelForCausalLM
3
  import torch
4
+ import os
 
 
5
 
6
+ # Model configuration: Qwen2.5-0.5B-Instruct (lightweight, PT-BR optimized)
7
+ MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
8
+ USE_QUANTIZATION = True # Enable 4-bit quantization for speed and low memory
 
 
 
9
 
10
+ # Load model and tokenizer
11
+ def load_model():
12
+ try:
13
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
14
+ model_config = {
15
+ "pretrained_model_name_or_path": MODEL_NAME,
16
+ "torch_dtype": torch.bfloat16,
17
+ }
18
+ if USE_QUANTIZATION and torch.cuda.is_available():
19
+ from transformers import BitsAndBytesConfig
20
+ model_config["quantization_config"] = BitsAndBytesConfig(
21
+ load_in_4bit=True,
22
+ bnb_4bit_compute_dtype=torch.bfloat16,
23
+ bnb_4bit_quant_type="nf4",
24
+ bnb_4bit_use_double_quant=True
25
+ )
26
+ model_config["device_map"] = "auto" # Requires accelerate
27
+ else:
28
+ model_config["device"] = "cpu" # Fallback to CPU if no GPU or accelerate
29
+ model = AutoModelForCausalLM.from_pretrained(**model_config)
30
+ return model, tokenizer
31
+ except Exception as e:
32
+ raise gr.Error(f"Erro ao carregar o modelo: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ model, tokenizer = load_model()
 
 
 
 
 
 
 
 
 
 
35
 
36
+ # Main function for generating responses
37
+ def responder_como_aldo(pergunta):
 
 
 
 
 
 
 
 
 
38
  try:
39
+ # Format prompt using chat template
40
+ messages = [
41
+ {"role": "system", "content": "Você é o professor Dr. Aldo Henrique, especialista em C, Java, desenvolvimento web e inteligência artificial. Responda com clareza, profundidade e tom acadêmico, como um professor experiente. Evite respostas genéricas e forneça exemplos práticos, se aplicável."},
42
+ {"role": "user", "content": pergunta}
43
+ ]
44
+ input_text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
45
+ inputs = tokenizer(input_text, return_tensors="pt").to(model.device)
46
+
47
+ # Generate response
48
+ outputs = model.generate(
49
+ **inputs,
50
+ max_new_tokens=100, # Reduced for faster responses
51
+ temperature=0.7,
 
 
 
 
 
 
 
 
52
  top_p=0.9,
53
  do_sample=True,
54
  pad_token_id=tokenizer.eos_token_id
55
  )
56
+ resposta = tokenizer.decode(outputs[0], skip_special_tokens=True)
57
+ return resposta.split("Resposta:")[-1].strip() if "Resposta:" in resposta else resposta.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
+ return f"Erro ao gerar resposta: {str(e)}"
 
 
 
60
 
61
+ # Gradio interface
62
+ with gr.Blocks(title="Pergunte ao Dr. Aldo Henrique") as interface:
63
+ gr.Markdown("## 🤖 Pergunte ao Dr. Aldo Henrique")
64
+ gr.Markdown(f"**Modelo carregado:** {MODEL_NAME} (leve e otimizado para PT-BR)")
65
+ gr.Markdown("Dúvidas sobre C, Java, desenvolvimento web ou IA? O Dr. Aldo responde com clareza e profundidade.")
 
66
 
67
+ with gr.Row():
68
+ entrada = gr.Textbox(label="Pergunta", placeholder="Ex: Como usar ponteiros em C?", lines=4)
69
+ saida = gr.Textbox(label="Resposta do Dr. Aldo", lines=8, interactive=False)
 
70
 
71
+ botao = gr.Button("Responder")
72
+ exemplos = gr.Examples(
73
+ examples=[
74
+ ["Como implementar uma lista ligada em C?"],
75
+ ["Qual a diferença entre == e equals() em Java?"],
76
+ ["Como funciona o machine learning?"],
77
+ ["Explique os conceitos de HTML, CSS e JavaScript"],
78
+ ["O que são algoritmos de ordenação?"]
79
+ ],
80
+ inputs=entrada
81
+ )
82
+ botao.click(fn=responder_como_aldo, inputs=entrada, outputs=saida)
83
+
84
+ # Launch with optimized settings
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  if __name__ == "__main__":
 
 
86
  interface.launch(
87
  server_name="0.0.0.0",
88
  server_port=7860,
89
  share=False,
90
+ queue_concurrency_count=2, # Limit concurrent requests
91
+ max_threads=4 # Optimize for 2 vCPUs
92
  )