caarleexx commited on
Commit
62facc7
·
verified ·
1 Parent(s): 5d76e27

Upload app_v19_main.py

Browse files
Files changed (1) hide show
  1. app_v19_main.py +623 -0
app_v19_main.py ADDED
@@ -0,0 +1,623 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 APP v19 COMPLETO - MAIN INTEGRADO
2
+
3
+ ## Arquivo: `app_v19_main.py`
4
+
5
+ ```python
6
+ #!/usr/bin/env python3
7
+ # -*- coding: utf-8 -*-
8
+
9
+ """
10
+ PIPELINE v19 - MOTOR CAUSAL COMPLETO
11
+ Análise reflexiva com causalidade transparente e interface simplificada.
12
+
13
+ Estrutura:
14
+ 1. Engine causal (loop iterativo)
15
+ 2. Formulário universal (N0 → CENARIOS → PRINCIPIOS → METACOG → RESPOSTA)
16
+ 3. Interface Gradio v19 (chat + progresso + cópia)
17
+
18
+ Requisitos:
19
+ - pip install gradio google-generativeai
20
+ """
21
+
22
+ import json
23
+ import re
24
+ import sys
25
+ from typing import Dict, List, Tuple, Optional
26
+ from datetime import datetime
27
+ import gradio as gr
28
+
29
+ # ==================== CONFIG ====================
30
+
31
+ API_KEY = "" # Preencher com sua chave API Gemini
32
+ MODEL_NAME = "gemini-1.5-flash"
33
+ MAX_ITERACOES = 10
34
+ TEMPERATURA_PADRAO = 0.6
35
+
36
+ # ==================== IMPORTS (google generative AI) ====================
37
+
38
+ try:
39
+ import google.generativeai as genai
40
+ genai.configure(api_key=API_KEY)
41
+ counselor_model = genai.GenerativeModel(MODEL_NAME)
42
+ except Exception as e:
43
+ print(f"⚠️ Erro ao configurar Gemini: {e}")
44
+ print(" Usando mock para testes")
45
+ counselor_model = None
46
+
47
+
48
+ # ==================== DNA SCHEMA ====================
49
+
50
+ def criar_dna_vazio() -> Dict:
51
+ """Cria estrutura de DNA vazia para novo chat."""
52
+ return {
53
+ "versao": "19.0",
54
+ "criado_em": datetime.now().isoformat(),
55
+
56
+ "historico_chat": [],
57
+
58
+ "historico_passos": {
59
+ "passo_causal": [],
60
+ "passo_verificador": []
61
+ },
62
+
63
+ "memoria_contextual": {
64
+ "ultimos_10_turnos": {
65
+ "memoria_tipo": "clara",
66
+ "indices_chat": [],
67
+ "passos_completos": True
68
+ },
69
+ "turnos_anteriores": {
70
+ "memoria_tipo": "vaga",
71
+ "total_turnos_comprimidos": 0,
72
+ "resumo_contexto_global": "",
73
+ "temas_principais": [],
74
+ "aprendizados_chave": []
75
+ }
76
+ },
77
+
78
+ "metadados": {
79
+ "total_turnos": 0,
80
+ "ultimo_turno_limpeza": 0,
81
+ "total_iteracoes": 0,
82
+ "modo_sabio_enabled": False,
83
+ "modo_supervisor_enabled": True
84
+ }
85
+ }
86
+
87
+
88
+ # ==================== CHAMAR MODELO ====================
89
+
90
+ def chamar_gemini(prompt: str, temperatura: float = 0.6) -> str:
91
+ """Chama Gemini API com fallback para mock."""
92
+
93
+ if not counselor_model:
94
+ # Mock para testes
95
+ return json.dumps({
96
+ "tipo_input": "subjetiva_aberta",
97
+ "proximo_passo": "CENARIOS",
98
+ "cenarios": [
99
+ {"id": 1, "desc": "Cenário A", "probabilidade": "mais_provavel"},
100
+ {"id": 2, "desc": "Cenário B", "probabilidade": "menos_provavel"}
101
+ ]
102
+ })
103
+
104
+ try:
105
+ response = counselor_model.generate_content(
106
+ prompt,
107
+ generation_config=genai.types.GenerationConfig(temperature=temperatura)
108
+ )
109
+ return response.text
110
+ except Exception as e:
111
+ print(f"❌ Erro ao chamar Gemini: {e}")
112
+ return json.dumps({"erro": str(e)})
113
+
114
+
115
+ # ==================== FORMULÁRIO CAUSAL ====================
116
+
117
+ class FormularioCausal:
118
+ """Schema JSON do formulário universal."""
119
+
120
+ @staticmethod
121
+ def criar_inicial(
122
+ input_usuario: str,
123
+ ultimos_K_turnos: List[Dict],
124
+ ultimos_5_passos: List[Dict],
125
+ resumo_contextual: str = ""
126
+ ) -> Dict:
127
+ """Inicializa formulário para novo turno."""
128
+ return {
129
+ "turno_id": datetime.now().isoformat()[:19],
130
+ "input_usuario_atual": input_usuario,
131
+ "tipo_input": None,
132
+
133
+ "contexto": {
134
+ "ultimos_K_turnos": ultimos_K_turnos[-5:],
135
+ "ultimos_5_passos": ultimos_5_passos[-5:] if ultimos_5_passos else [],
136
+ "resumo_contextual": resumo_contextual
137
+ },
138
+
139
+ "formulario_causal": {
140
+ "questoes_herdadas": [],
141
+ "cenarios": [],
142
+ "principios": [],
143
+ "principios_ordenados": [],
144
+ "principio_dominante": None,
145
+ "solucao_parcial": "",
146
+ "justificativa": [],
147
+ "estado_duvida": None,
148
+ "motivo_nao_resolvida": "",
149
+ "proximo_passo": "N0",
150
+ "questoes_para_proximo_passo": [],
151
+ "o_que_ainda_nao_sei": []
152
+ },
153
+
154
+ "resposta_cognitiva": None,
155
+ "iteracao_atual": 0
156
+ }
157
+
158
+
159
+ # ==================== PARSER ====================
160
+
161
+ class ParserRespostaCausal:
162
+ """Extrai JSON + RESPOSTA COGNITIVA."""
163
+
164
+ @staticmethod
165
+ def parsear(resposta_raw: str) -> Tuple[Dict, Optional[str]]:
166
+ """Extrai formulário preenchido e RESPOSTA COGNITIVA."""
167
+
168
+ formulario_preenchido = {}
169
+ resposta_cognitiva = None
170
+
171
+ # 1. Extrair JSON
172
+ try:
173
+ match_json = re.search(r'\{[\s\S]*\}', resposta_raw)
174
+ if match_json:
175
+ json_str = match_json.group(0)
176
+ formulario_preenchido = json.loads(json_str)
177
+ except json.JSONDecodeError:
178
+ pass
179
+
180
+ # 2. Extrair RESPOSTA COGNITIVA
181
+ if "RESPOSTA COGNITIVA:" in resposta_raw:
182
+ parts = resposta_raw.split("RESPOSTA COGNITIVA:")
183
+ if len(parts) > 1:
184
+ resposta_cognitiva = parts[1].strip()
185
+
186
+ return formulario_preenchido, resposta_cognitiva
187
+
188
+ @staticmethod
189
+ def extrair_progresso_visual(formulario: Dict, iteracao: int) -> str:
190
+ """Gera textbox visual do progresso."""
191
+ form = formulario.get("formulario_causal", {})
192
+ linhas = []
193
+
194
+ linhas.append(f"📊 TURNO #{formulario.get('iteracao_atual', iteracao)}")
195
+ linhas.append("=" * 50)
196
+
197
+ # N0
198
+ tipo = form.get("tipo_input", "?")
199
+ linhas.append(f"\n🎓 PASSO N0: Aluno")
200
+ linhas.append(f" ├─ Tipo: {tipo}")
201
+ linhas.append(f" └─ ✓ Próximo: {form.get('proximo_passo', '?')}")
202
+
203
+ # Cenários
204
+ cenarios = form.get("cenarios", [])
205
+ if cenarios:
206
+ linhas.append(f"\n🎯 PASSO CENARIOS: {len(cenarios)} cenário(s)")
207
+ for i, cen in enumerate(cenarios[:6], 1):
208
+ prob_icon = "🟢" if cen.get("probabilidade") == "mais_provavel" else "🔵"
209
+ desc = cen.get('desc', '?')[:40]
210
+ linhas.append(f" {prob_icon} C{i}: {desc}...")
211
+ linhas.append(f" └─ ✓ Próximo: {form.get('proximo_passo', '?')}")
212
+
213
+ # Princípios
214
+ princ_ord = form.get("principios_ordenados", [])
215
+ if princ_ord:
216
+ linhas.append(f"\n🔀 PASSO PRINCIPIOS: {len(princ_ord)} princípio(s)")
217
+ medals = ["🥇", "🥈", "🥉"]
218
+ for i, nome in enumerate(princ_ord[:3], 1):
219
+ medal = medals[i-1] if i <= 3 else "▪"
220
+ linhas.append(f" {medal} {nome}")
221
+ linhas.append(f" └─ ✓ Próximo: {form.get('proximo_passo', '?')}")
222
+
223
+ # Metacognição
224
+ estado = form.get("estado_duvida")
225
+ if estado:
226
+ linhas.append(f"\n✨ PASSO METACOG: Avaliando...")
227
+ linhas.append(f" ├─ Estado: {estado.upper()}")
228
+ linhas.append(f" └─ ✓ Próximo: {form.get('proximo_passo', '?')}")
229
+
230
+ # Status final
231
+ linhas.append("\n" + "─" * 50)
232
+ proximo = form.get("proximo_passo", "?")
233
+ if proximo == "PERGUNTAR_USUARIO":
234
+ linhas.append("⚠️ AGUARDANDO SUA RESPOSTA...")
235
+ elif proximo == "SAIDA_FINAL":
236
+ linhas.append("✅ PREPARANDO RESPOSTA FINAL...")
237
+ else:
238
+ linhas.append(f"🔄 Processando: {proximo}...")
239
+
240
+ return "\n".join(linhas)
241
+
242
+
243
+ # ==================== CONSTRUTORES DE PROMPT ====================
244
+
245
+ class ConstrutorPromptsCausal:
246
+ """Prompts dinâmicos por passo."""
247
+
248
+ @staticmethod
249
+ def construir(
250
+ formulario: Dict,
251
+ modo_sabio: bool = False,
252
+ tipo_passo: str = "N0"
253
+ ) -> str:
254
+ """Constrói prompt para o passo."""
255
+
256
+ form = formulario["formulario_causal"]
257
+ contexto_str = json.dumps(formulario["contexto"], indent=2, ensure_ascii=False)
258
+ form_str = json.dumps(form, indent=2, ensure_ascii=False)
259
+ input_usuario = formulario["input_usuario_atual"]
260
+
261
+ if tipo_passo == "N0":
262
+ return f"""PASSO N0: ALUNO - CLASSIFICANDO INPUT
263
+
264
+ INPUT DO USUÁRIO:
265
+ "{input_usuario}"
266
+
267
+ CONTEXTO:
268
+ {contexto_str}
269
+
270
+ TAREFA:
271
+ 1. Classifique: factual | subjetiva_aberta | correcao | comentario | outro
272
+ 2. Próximo passo: N0 | CENARIOS | EXPLORACAO | PRINCIPIOS | METACOG | PERGUNTAR_USUARIO | SAIDA_FINAL
273
+
274
+ RETORNE JSON:
275
+ {{"tipo_input": "...", "proximo_passo": "..."}}
276
+ """
277
+
278
+ elif tipo_passo == "CENARIOS":
279
+ return f"""PASSO CENARIOS: MAPEANDO 1-6 CENÁRIOS
280
+
281
+ INPUT: "{input_usuario}"
282
+
283
+ CONTEXTO: {contexto_str}
284
+
285
+ TAREFA:
286
+ Mapeie 1-6 cenários com: desc, probabilidade (mais_provavel|menos_provavel), certezas, dúvidas.
287
+
288
+ RETORNE JSON:
289
+ {{"cenarios": [{{"id": 1, "desc": "...", "probabilidade": "...", "certezas": [...], "duvidas": [...]}}], "proximo_passo": "PRINCIPIOS"}}
290
+ """
291
+
292
+ elif tipo_passo == "PRINCIPIOS":
293
+ return f"""PASSO PRINCIPIOS: ORDENANDO
294
+
295
+ CENÁRIOS: {form_str}
296
+
297
+ TAREFA:
298
+ Identifique princípios (máx 5), atribua peso 1-5, ordene por relevância.
299
+
300
+ RETORNE JSON:
301
+ {{"principios": [...], "principios_ordenados": [...], "principio_dominante": "...", "proximo_passo": "METACOG"}}
302
+ """
303
+
304
+ elif tipo_passo == "METACOG":
305
+ return f"""PASSO METACOG: CERTEZAS vs DÚVIDAS
306
+
307
+ FORMULÁRIO: {form_str}
308
+
309
+ TAREFA:
310
+ Aplique princípio dominante. Se houver empate: estado_duvida="parcial", proximo_passo="PERGUNTAR_USUARIO".
311
+ Senão: estado_duvida="resolvida", proximo_passo="SAIDA_FINAL".
312
+
313
+ RETORNE JSON:
314
+ {{"estado_duvida": "...", "proximo_passo": "...", "pergunta_desempate": "..."}}
315
+ """
316
+
317
+ elif tipo_passo == "PERGUNTAR_USUARIO":
318
+ return f"""PASSO PERGUNTAR_USUARIO: DESEMPATE
319
+
320
+ CENÁRIOS EM QUESTÃO: {form_str}
321
+
322
+ Formule pergunta clara. Finalize com: RESPOSTA COGNITIVA: [pergunta]
323
+
324
+ RETORNE JSON:
325
+ {{"proximo_passo": "N0"}}
326
+
327
+ RESPOSTA:
328
+ """
329
+
330
+ else:
331
+ return f"Passo desconhecido: {tipo_passo}"
332
+
333
+
334
+ # ==================== ENGINE CAUSAL ====================
335
+
336
+ class EngineCausal:
337
+ """Motor iterativo v19."""
338
+
339
+ def __init__(self, dna: Dict, modo_sabio: bool = False, max_iteracoes: int = 10):
340
+ self.dna = dna
341
+ self.modo_sabio = modo_sabio
342
+ self.max_iteracoes = max_iteracoes
343
+
344
+ def processar_turno(self) -> Tuple[str, str, Dict]:
345
+ """Executa loop causal completo."""
346
+
347
+ if len(self.dna["historico_chat"]) == 0:
348
+ return "", "Erro: nenhuma mensagem", self.dna
349
+
350
+ mensagem_usuario = self.dna["historico_chat"][-1]["user"]
351
+
352
+ # Inicializar formulário
353
+ formulario = FormularioCausal.criar_inicial(
354
+ input_usuario=mensagem_usuario,
355
+ ultimos_K_turnos=self.dna["historico_chat"][-5:],
356
+ ultimos_5_passos=self.dna["historico_passos"]["passo_causal"][-5:],
357
+ resumo_contextual=self.dna["memoria_contextual"]["turnos_anteriores"].get(
358
+ "resumo_contexto_global", ""
359
+ )
360
+ )
361
+
362
+ resposta_final = None
363
+ progresso_text = ""
364
+
365
+ # Loop iterativo
366
+ for iteracao in range(1, self.max_iteracoes + 1):
367
+ formulario["iteracao_atual"] = iteracao
368
+
369
+ print(f"\n🔄 Iteração {iteracao}")
370
+ print(f" Passo: {formulario['formulario_causal']['proximo_passo']}")
371
+
372
+ # Construir e chamar
373
+ prompt = ConstrutorPromptsCausal.construir(
374
+ formulario=formulario,
375
+ modo_sabio=self.modo_sabio,
376
+ tipo_passo=formulario["formulario_causal"]["proximo_passo"]
377
+ )
378
+
379
+ resposta_raw = chamar_gemini(prompt, temperatura=TEMPERATURA_PADRAO)
380
+
381
+ # Parsear
382
+ formulario_novo, resposta_cognitiva = ParserRespostaCausal.parsear(resposta_raw)
383
+
384
+ # Mesclar
385
+ if formulario_novo and "formulario_causal" in formulario_novo:
386
+ formulario["formulario_causal"].update(formulario_novo["formulario_causal"])
387
+
388
+ # Progresso visual
389
+ progresso_text = ParserRespostaCausal.extrair_progresso_visual(formulario, iteracao)
390
+
391
+ # Registrar
392
+ self.dna["historico_passos"]["passo_causal"].append({
393
+ "iteracao": iteracao,
394
+ "passo_tipo": formulario["formulario_causal"].get("proximo_passo", "N0"),
395
+ "timestamp": datetime.now().isoformat()
396
+ })
397
+
398
+ # Verificar RESPOSTA COGNITIVA
399
+ if resposta_cognitiva:
400
+ print(f" ✅ RESPOSTA COGNITIVA em iteração {iteracao}")
401
+ resposta_final = resposta_cognitiva
402
+ break
403
+
404
+ # Fallback
405
+ if not resposta_final:
406
+ resposta_final = (
407
+ "Não consegui chegar a uma resposta dentro do limite. "
408
+ "Poderia esclarecer melhor sua pergunta?"
409
+ )
410
+
411
+ # Atualizar chat
412
+ self.dna["historico_chat"][-1]["assistant"] = resposta_final
413
+
414
+ return resposta_final, progresso_text, self.dna
415
+
416
+
417
+ # ==================== INTERFACE GRADIO ====================
418
+
419
+ def criar_interface_gradio() -> gr.Blocks:
420
+ """Cria interface Gradio v19."""
421
+
422
+ dna_global = criar_dna_vazio()
423
+
424
+ with gr.Blocks(title="Pipeline v19 - Causal", theme=gr.themes.Soft()) as interface:
425
+
426
+ gr.Markdown("""
427
+ # 🧠 Pipeline v19 - Motor Causal
428
+
429
+ Análise reflexiva com causalidade transparente.
430
+ O modelo escolhe os próximos passos com base em dúvidas abertas.
431
+ """)
432
+
433
+ with gr.Row():
434
+ with gr.Column(scale=3):
435
+
436
+ # Chat
437
+ chat_display = gr.Chatbot(
438
+ label="💬 Conversa",
439
+ height=400,
440
+ show_label=True
441
+ )
442
+
443
+ # Progresso
444
+ progresso_text = gr.Textbox(
445
+ label="📊 Progresso dos Passos",
446
+ lines=8,
447
+ interactive=False,
448
+ value="Aguardando primeira mensagem..."
449
+ )
450
+
451
+ with gr.Column(scale=1):
452
+ gr.Markdown("""
453
+ ### ⚙️ Configurações
454
+
455
+ **Modo Sábio**: Empatia
456
+
457
+ **Modo Supervisor**: Rigor
458
+ """)
459
+
460
+ # Input
461
+ msg_input = gr.Textbox(
462
+ label="Escreva sua pergunta",
463
+ placeholder="Digite sua pergunta...",
464
+ lines=2
465
+ )
466
+
467
+ # Botões
468
+ with gr.Row():
469
+ enviar_btn = gr.Button("📤 Enviar", variant="primary")
470
+ limpar_btn = gr.Button("🗑️ Limpar")
471
+ copiar_btn = gr.Button("📋 Copiar")
472
+
473
+ # Checkboxes
474
+ with gr.Row():
475
+ modo_sabio = gr.Checkbox(label="💚 Modo Sábio", value=False)
476
+ modo_supervisor = gr.Checkbox(label="🛡️ Supervisor", value=True)
477
+
478
+ # Cópia
479
+ copia_display = gr.Textbox(
480
+ label="📄 Cópia da Conversa",
481
+ lines=6,
482
+ interactive=False
483
+ )
484
+
485
+ # Callbacks
486
+ def processar():
487
+ msg = msg_input.value
488
+ if not msg.strip():
489
+ return chat_display.value, "", ""
490
+
491
+ # Adicionar ao chat
492
+ chat_list = chat_display.value if chat_display.value else []
493
+ dna_global["historico_chat"].append({
494
+ "user": msg,
495
+ "assistant": None,
496
+ "timestamp": datetime.now().isoformat()
497
+ })
498
+ dna_global["metadados"]["total_turnos"] += 1
499
+
500
+ # Processar
501
+ engine = EngineCausal(dna_global, modo_sabio=modo_sabio.value)
502
+ resposta, progresso, _ = engine.processar_turno()
503
+
504
+ # Atualizar displays
505
+ chat_list.append([msg, resposta])
506
+
507
+ copia_linhas = []
508
+ for i, (user, bot) in enumerate(chat_list, 1):
509
+ copia_linhas.append(f"Turno {i}:\n👤 {user}\n🤖 {bot}\n")
510
+ copia_text = "\n".join(copia_linhas)
511
+
512
+ return chat_list, progresso, copia_text
513
+
514
+ def limpar():
515
+ nonlocal dna_global
516
+ dna_global = criar_dna_vazio()
517
+ return [], "", ""
518
+
519
+ def copiar():
520
+ chat_list = chat_display.value if chat_display.value else []
521
+ copia_linhas = []
522
+ for i, (user, bot) in enumerate(chat_list, 1):
523
+ copia_linhas.append(f"Turno {i}:\n👤 {user}\n🤖 {bot}\n")
524
+ return "\n".join(copia_linhas)
525
+
526
+ enviar_btn.click(
527
+ processar,
528
+ inputs=[],
529
+ outputs=[chat_display, progresso_text, copia_display]
530
+ )
531
+
532
+ msg_input.submit(
533
+ processar,
534
+ inputs=[],
535
+ outputs=[chat_display, progresso_text, copia_display]
536
+ )
537
+
538
+ limpar_btn.click(
539
+ limpar,
540
+ inputs=[],
541
+ outputs=[chat_display, progresso_text, msg_input, copia_display]
542
+ )
543
+
544
+ copiar_btn.click(
545
+ copiar,
546
+ inputs=[],
547
+ outputs=[copia_display]
548
+ )
549
+
550
+ return interface
551
+
552
+
553
+ # ==================== MAIN ====================
554
+
555
+ if __name__ == "__main__":
556
+ print("\n" + "="*70)
557
+ print("🚀 PIPELINE v19 - MOTOR CAUSAL")
558
+ print("="*70)
559
+ print(f"Modelo: {MODEL_NAME}")
560
+ print(f"Max iterações: {MAX_ITERACOES}")
561
+ print("="*70 + "\n")
562
+
563
+ interface = criar_interface_gradio()
564
+ interface.launch(
565
+ share=False,
566
+ server_name="0.0.0.0",
567
+ server_port=7860
568
+ )
569
+ ```
570
+
571
+ ---
572
+
573
+ ## ✅ Como Rodar
574
+
575
+ ```bash
576
+ # 1. Instalar dependências
577
+ pip install gradio google-generativeai
578
+
579
+ # 2. Preencher API_KEY
580
+ # Editar app_v19_main.py, linha ~30:
581
+ # API_KEY = "sua_chave_aqui"
582
+
583
+ # 3. Rodar
584
+ python app_v19_main.py
585
+
586
+ # 4. Acessar
587
+ # http://localhost:7860
588
+ ```
589
+
590
+ ---
591
+
592
+ ## 🎯 Resumo da Integração
593
+
594
+ | Componente | Arquivo | Status |
595
+ |------------|---------|--------|
596
+ | **Engine Causal** | Inline (app_v19_main.py) | ✅ |
597
+ | **Formulário Único** | FormularioCausal class | ✅ |
598
+ | **Prompts Dinâmicos** | ConstrutorPromptsCausal class | ✅ |
599
+ | **Interface Gradio** | criar_interface_gradio() | ✅ |
600
+ | **DNA Schema** | criar_dna_vazio() | ✅ |
601
+ | **Parser JSON** | ParserRespostaCausal class | ✅ |
602
+
603
+ ---
604
+
605
+ ## 📋 Checklist de Funcionalidades v19
606
+
607
+ - [x] Loop iterativo (MAX 10 iterações)
608
+ - [x] Formulário causal único
609
+ - [x] N0 classifica tipo de input
610
+ - [x] CENARIOS mapeia 1-6 com mais/menos provável
611
+ - [x] PRINCIPIOS ordena por peso
612
+ - [x] METACOG detecta empates → PERGUNTAR_USUARIO
613
+ - [x] Interface limpa (sem DNA JSON)
614
+ - [x] Progresso visual em tempo real
615
+ - [x] Chat + Chatbot
616
+ - [x] Botão copiar conversa
617
+ - [x] Modo Sábio + Supervisor
618
+
619
+ ---
620
+
621
+ **Pronto para testar! 🚀**
622
+
623
+ Quer ajustar algo antes de rodar?