caarleexx commited on
Commit
185db66
·
verified ·
1 Parent(s): 8c1057a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +1040 -0
app.py ADDED
@@ -0,0 +1,1040 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ╔════════════════════════════════════════════════════════════════════════════╗
2
+ # ║ PIPELINE v18: METACOGNIÇÃO CRUA ║
3
+ # ║ Passos 0-6 Telegráficos → Sintetizador Humanizado ║
4
+ # ║ ║
5
+ # ║ Arquitetura: ║
6
+ # ║ - Passos 0-6: Pensamento puro (sem polimento) ║
7
+ # ║ - Sintetizador: Transforma metacognição em prosa humana ║
8
+ # ║ - Passo 7: Verificação final (factual, lógica, ética) ║
9
+ # ║ - Gestão de Memória: Limpeza a cada 10 turnos ║
10
+ # ╚════════════════════════════════════════════════════════════════════════════╝
11
+
12
+ import os
13
+ import json
14
+ import re
15
+ from datetime import datetime
16
+ from typing import Dict, List, Optional, Tuple
17
+ import warnings
18
+
19
+ import gradio as gr
20
+ import google.generativeai as genai
21
+
22
+ warnings.filterwarnings("ignore", category=FutureWarning, module="google.api_core")
23
+
24
+ # ==================== CONFIGURAÇÃO GEMINI ====================
25
+
26
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY", "SUA_API_KEY_AQUI"))
27
+
28
+ counselor_model = genai.GenerativeModel("gemini-2.0-flash-exp")
29
+ supervisor_model = genai.GenerativeModel("gemini-2.0-flash-exp")
30
+
31
+ # ==================== CONTEXTO FILOSÓFICO ====================
32
+
33
+ def carregar_contexto_filosofico(caminho: str = "epct0.md") -> Optional[str]:
34
+ """Carrega contexto filosófico se disponível."""
35
+ try:
36
+ with open(caminho, "r", encoding="utf-8") as f:
37
+ print(f"✓ Contexto filosófico '{caminho}' carregado.")
38
+ return f.read()
39
+ except FileNotFoundError:
40
+ print(f"⚠ Arquivo '{caminho}' não encontrado.")
41
+ return None
42
+
43
+ CONTEXTO_FILOSOFICO = carregar_contexto_filosofico()
44
+
45
+ # ==================== INICIALIZAÇÃO DO DNA ====================
46
+
47
+ def criar_dna_vazio() -> Dict:
48
+ """Cria estrutura de DNA vazio."""
49
+ return {
50
+ "historico_chat": [],
51
+ "historico_passos": {
52
+ "passo0": [],
53
+ "passo1": [],
54
+ "passo2": [],
55
+ "passo3": [],
56
+ "passo4": [],
57
+ "passo5": [],
58
+ "passo6": [],
59
+ "passo7": [],
60
+ },
61
+ "memoria_contextual": {
62
+ "ultimos_10_turnos": {
63
+ "memoria_tipo": "clara",
64
+ "indices_chat": [],
65
+ "passos_completos": True
66
+ },
67
+ "turnos_anteriores": {
68
+ "memoria_tipo": "vaga",
69
+ "total_turnos_comprimidos": 0,
70
+ "resumo_contexto_global": "",
71
+ "temas_principais": [],
72
+ "aprendizados_chave": []
73
+ }
74
+ },
75
+ "metadados": {
76
+ "total_turnos": 0,
77
+ "ultimo_turno_limpeza": 0,
78
+ "total_correcoes_passo7": 0,
79
+ "tipos_correcoes": {"factuais": 0, "logicas": 0, "eticas": 0},
80
+ "aprendizados_usuario": [],
81
+ }
82
+ }
83
+
84
+ # ==================== UTILIDADES ====================
85
+
86
+ def parse_json_seguro(texto: str) -> Dict:
87
+ """Extrai JSON de resposta mesmo com markdown."""
88
+ try:
89
+ # Remove blocos markdown se existirem
90
+ if "```json" in texto:
91
+ texto = re.search(r"```json(.*?)```", texto, re.DOTALL).group(1)
92
+ elif "```" in texto:
93
+ texto = re.search(r"```(.*?)```", texto, re.DOTALL).group(1)
94
+
95
+ return json.loads(texto.strip())
96
+ except:
97
+ print(f"⚠ Erro parseando JSON: {texto[:100]}")
98
+ return {}
99
+
100
+ def chamar_gemini(model, prompt: str, temperatura: float = 0.7) -> str:
101
+ """Chamada segura ao Gemini com retry."""
102
+ try:
103
+ response = model.generate_content(
104
+ prompt,
105
+ generation_config=genai.types.GenerationConfig(
106
+ temperature=temperatura,
107
+ max_output_tokens=2000
108
+ )
109
+ )
110
+ return response.text
111
+ except Exception as e:
112
+ print(f"❌ Erro Gemini: {e}")
113
+ return "{}"
114
+
115
+ # ==================== PASSO 0: ALUNO ====================
116
+
117
+ def passo0_aluno(
118
+ mensagem_usuario: str,
119
+ turno_anterior: Optional[Dict],
120
+ memoria_contextual: Dict
121
+ ) -> Dict:
122
+ """
123
+ METACOGNIÇÃO PURA - Detecta feedback do turno anterior.
124
+ Formato: telegráfico, sem frases polidas.
125
+ """
126
+
127
+ if turno_anterior is None:
128
+ return {
129
+ "primeiro_turno": True,
130
+ "analise_feedback": "N/A - Primeira interação",
131
+ "decisao": "prosseguir_passo1"
132
+ }
133
+
134
+ prompt = f"""
135
+ Você é um METACOGNITIVO (pensamento interno, não comunicação).
136
+
137
+ TURNO ANTERIOR:
138
+ User: "{turno_anterior['user']}"
139
+ Assistant: "{turno_anterior['assistant']}"
140
+
141
+ NOVA MENSAGEM:
142
+ "{mensagem_usuario}"
143
+
144
+ CONTEXTO VAGO:
145
+ {memoria_contextual.get('turnos_anteriores', {}).get('resumo_contexto_global', 'N/A')}
146
+
147
+ ---
148
+
149
+ RESPONDA EM METACOGNIÇÃO PURA - TELEGRÁFICO:
150
+
151
+ Não use frases completas. APENAS essência semântica com conectores mínimos.
152
+
153
+ EXEMPLO CERTO:
154
+ "entendeu: sim | pergunta-nova | avança-tópico | não-reformulou"
155
+
156
+ RETORNE JSON:
157
+ {{
158
+ "usuario_entendeu": "sim|nao",
159
+ "evidencias": "pergunta-nova | avança-tópico | não-reformulou",
160
+ "usuario_corrigiu": "sim|nao",
161
+ "correcao_detectada": "...|null",
162
+ "correcao_valida": "sim|nao|null",
163
+ "o_que_melhorar": "...|null",
164
+ "decisao": "prosseguir_passo1|reexplicar_passo6|atualizar_resposta_anterior",
165
+ "motivo": "..."
166
+ }}
167
+ """
168
+
169
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.5)
170
+ registro = parse_json_seguro(resposta_raw)
171
+
172
+ return registro
173
+
174
+ # ==================== PASSO 1: TRIAGEM ====================
175
+
176
+ def passo1_triagem(
177
+ mensagem_usuario: str,
178
+ historico_recente: List[Dict],
179
+ contexto_vago: str
180
+ ) -> Dict:
181
+ """
182
+ METACOGNIÇÃO PURA - Classificação objetiva vs subjetiva.
183
+ Formato: telegráfico.
184
+ """
185
+
186
+ prompt = f"""
187
+ METACOGNIÇÃO - TRIAGEM INICIAL.
188
+
189
+ CONTEXTO VAGO:
190
+ {contexto_vago}
191
+
192
+ HISTÓRICO RECENTE (últimas 3):
193
+ {json.dumps(historico_recente[-3:], indent=2, ensure_ascii=False)}
194
+
195
+ PERGUNTA:
196
+ "{mensagem_usuario}"
197
+
198
+ ---
199
+
200
+ CLASSIFIQUE EM TELEGRÁFICO (sem frases):
201
+
202
+ RETORNE JSON:
203
+ {{
204
+ "tipo": "objetiva_factual|subjetiva_aberta",
205
+ "sinais": "tem-resposta-única | verificável | sem-contexto-pessoal",
206
+ "confianca": "alta|media|baixa",
207
+ "decisao": "responder_direto|analisar_profundamente",
208
+ "razao": "..."
209
+ }}
210
+ """
211
+
212
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.5)
213
+ registro = parse_json_seguro(resposta_raw)
214
+
215
+ return registro
216
+
217
+ # ==================== PASSO 2: CENÁRIOS ====================
218
+
219
+ def passo2_cenarios(
220
+ mensagem_usuario: str,
221
+ historico_chat: List[Dict],
222
+ analise_p1: Dict,
223
+ contexto_vago: str
224
+ ) -> Dict:
225
+ """
226
+ METACOGNIÇÃO PURA - Mapeamento de cenários.
227
+ Formato: telegráfico com contexto denso.
228
+ """
229
+
230
+ prompt = f"""
231
+ METACOGNIÇÃO - CENÁRIOS.
232
+
233
+ CONTEXTO VAGO:
234
+ {contexto_vago}
235
+
236
+ TRIAGEM (P1):
237
+ {json.dumps(analise_p1, indent=2, ensure_ascii=False)}
238
+
239
+ HISTÓRICO ÚLTIMAS 5:
240
+ {json.dumps(historico_chat[-5:], indent=2, ensure_ascii=False)}
241
+
242
+ PERGUNTA:
243
+ "{mensagem_usuario}"
244
+
245
+ ---
246
+
247
+ MAPEIE CENÁRIOS ONDE RESPOSTA MUDA - TELEGRÁFICO:
248
+
249
+ RETORNE JSON:
250
+ {{
251
+ "cenarios": [
252
+ {{
253
+ "desc": "cenário-1-comprimido | contexto-relevante",
254
+ "razao": "resposta-muda-porque",
255
+ "prob": "mais_provavel|menos_provavel"
256
+ }}
257
+ ],
258
+ "total": 2,
259
+ "tipo_resposta": "multipla|univoca",
260
+ "confianca": "alta|media|baixa",
261
+ "decisao": "prosseguir|pedir_esclarecimento",
262
+ "pergunta": "esclarecimento-necessário|null"
263
+ }}
264
+ """
265
+
266
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.6)
267
+ registro = parse_json_seguro(resposta_raw)
268
+
269
+ return registro
270
+
271
+ # ==================== PASSO 3: EXPLORAÇÃO ====================
272
+
273
+ def passo3_exploracao(
274
+ historico_chat: List[Dict],
275
+ analise_p1: Dict,
276
+ analise_p2: Dict
277
+ ) -> Dict:
278
+ """
279
+ METACOGNIÇÃO PURA - Para cada cenário, resposta essencial.
280
+ Formato: telegráfico, máximo contexto.
281
+ """
282
+
283
+ prompt = f"""
284
+ METACOGNIÇÃO - EXPLORAÇÃO.
285
+
286
+ CENÁRIOS (P2):
287
+ {json.dumps(analise_p2, indent=2, ensure_ascii=False)}
288
+
289
+ HISTÓRICO:
290
+ {json.dumps(historico_chat[-5:], indent=2, ensure_ascii=False)}
291
+
292
+ ---
293
+
294
+ PARA CADA CENÁRIO, RESPONDA ESSÊNCIA - TELEGRÁFICO:
295
+
296
+ Não descreva, apenas essência densa: "Python | curva: 3-6m | vagas: 40% data/backend | frameworks: Django/Flask"
297
+
298
+ RETORNE JSON:
299
+ {{
300
+ "exploracoes": [
301
+ {{
302
+ "cenario_ref": "cenário-1-comprimido",
303
+ "resposta_essencia": "palavra-chave | razão-1 | razão-2 | implicação",
304
+ "confianca": "alta|media|baixa",
305
+ "lacunas": "contexto-ausente|null"
306
+ }}
307
+ ],
308
+ "cenario_mais_confiante": "cenário-X",
309
+ "recomendacao": "prosseguir_sintese|pedir_esclarecimento",
310
+ "pergunta": "esclarecimento|null"
311
+ }}
312
+ """
313
+
314
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.6)
315
+ registro = parse_json_seguro(resposta_raw)
316
+
317
+ return registro
318
+
319
+ # ==================== PASSO 4: PRINCÍPIOS + SÍMBOLOS ====================
320
+
321
+ def passo4_principios_simbolos(
322
+ historico_chat: List[Dict],
323
+ analise_p1: Dict,
324
+ analise_p2: Dict,
325
+ analise_p3: Dict
326
+ ) -> Dict:
327
+ """
328
+ METACOGNIÇÃO PURA - Conhecimento fundamental.
329
+ Formato: telegráfico.
330
+ """
331
+
332
+ prompt = f"""
333
+ METACOGNIÇÃO - CONHECIMENTO FUNDAMENTAL.
334
+
335
+ EXPLORAÇÕES (P3):
336
+ {json.dumps(analise_p3, indent=2, ensure_ascii=False)}
337
+
338
+ ---
339
+
340
+ IDENTIFIQUE PRINCÍPIOS E SÍMBOLOS - TELEGRÁFICO:
341
+
342
+ RETORNE JSON:
343
+ {{
344
+ "principios": [
345
+ {{
346
+ "nome": "Custo-Oportunidade",
347
+ "cat": "economico|filosofico|matematico|psicologico",
348
+ "essencia": "escolher X = renunciar Y",
349
+ "aplica": ["cenário-1", "cenário-2"]
350
+ }}
351
+ ],
352
+ "simbolos": [
353
+ {{
354
+ "nome": "Jornada-Herói",
355
+ "tipo": "arquetipo|metafora|heuristica",
356
+ "essencia": "transformação-iminente | medo-natural",
357
+ "aplica": ["contexto-emocional"]
358
+ }}
359
+ ],
360
+ "principio_central": "...",
361
+ "simbolo_dominante": "...",
362
+ "tipo_situacao": "nova|mista|recordada"
363
+ }}
364
+ """
365
+
366
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.6)
367
+ registro = parse_json_seguro(resposta_raw)
368
+
369
+ return registro
370
+
371
+ # ==================== PASSO 5: METACOGNIÇÃO ====================
372
+
373
+ def passo5_metacognicao(
374
+ historico_chat: List[Dict],
375
+ analise_p1: Dict,
376
+ analise_p2: Dict,
377
+ analise_p3: Dict,
378
+ analise_p4: Dict
379
+ ) -> Dict:
380
+ """
381
+ METACOGNIÇÃO PURA - Certezas vs dúvidas.
382
+ Formato: telegráfico.
383
+ """
384
+
385
+ prompt = f"""
386
+ METACOGNIÇÃO - CERTEZAS vs DÚVIDAS.
387
+
388
+ EXPLORAÇÕES (P3):
389
+ {json.dumps(analise_p3, indent=2, ensure_ascii=False)}
390
+
391
+ PRINCÍPIOS (P4):
392
+ {json.dumps(analise_p4, indent=2, ensure_ascii=False)}
393
+
394
+ ---
395
+
396
+ AVALIE CERTEZAS vs DÚVIDAS - TELEGRÁFICO:
397
+
398
+ RETORNE JSON:
399
+ {{
400
+ "analise_cenarios": [
401
+ {{
402
+ "cenario": "cenário-X",
403
+ "certezas": "certeza-1 verificável | certeza-2 | certeza-3",
404
+ "duvidas": "dúvida-1 contextual | dúvida-2",
405
+ "confianca": "alta|media|baixa",
406
+ "balanco": "certezas_superam|equilibrado|duvidas_superam",
407
+ "razao": "3 certezas vs 2 dúvidas"
408
+ }}
409
+ ],
410
+ "confianca_global": "alta|media|baixa",
411
+ "evolucao_cognitiva": "expandiu|estavel|regrediu",
412
+ "decisao": "responder|questionar",
413
+ "razao_decisao": "certezas suficientes",
414
+ "questionamento": "esclarecimento-necessário|null",
415
+ "risco": "resposta-genérica|null"
416
+ }}
417
+ """
418
+
419
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.5)
420
+ registro = parse_json_seguro(resposta_raw)
421
+
422
+ return registro
423
+
424
+ # ==================== PASSO 6: JUIZ DA VERDADE ====================
425
+
426
+ def passo6_juiz_verdade(
427
+ historico_chat: List[Dict],
428
+ analise_p1: Dict,
429
+ analise_p2: Dict,
430
+ analise_p3: Dict,
431
+ analise_p4: Dict,
432
+ analise_p5: Dict,
433
+ rota_rapida: bool = False
434
+ ) -> Dict:
435
+ """
436
+ METACOGNIÇÃO PURA - Validação socrática.
437
+ Formato: telegráfico.
438
+ """
439
+
440
+ prompt = f"""
441
+ METACOGNIÇÃO - ARBITRAGEM SOCRÁTICA.
442
+
443
+ TODOS PASSOS:
444
+ P1: {json.dumps(analise_p1, indent=2, ensure_ascii=False)}
445
+ P2: {json.dumps(analise_p2, indent=2, ensure_ascii=False)}
446
+ P3: {json.dumps(analise_p3, indent=2, ensure_ascii=False)}
447
+ P4: {json.dumps(analise_p4, indent=2, ensure_ascii=False)}
448
+ P5: {json.dumps(analise_p5, indent=2, ensure_ascii=False)}
449
+
450
+ ROTA: {"rápida-factual" if rota_rapida else "completa"}
451
+
452
+ ---
453
+
454
+ VALIDE VERDADES SOCRÁTICAS - TELEGRÁFICO:
455
+
456
+ RETORNE JSON:
457
+ {{
458
+ "verdade1_nao_sei_que_sei": {{
459
+ "validada": true|false,
460
+ "evidencias": "P3-respostas | P4-princípios | P5-certezas",
461
+ "lacunas": "nenhuma|lacuna-X",
462
+ "confianca": "alta|media|baixa"
463
+ }},
464
+ "verdade2_nao_sei_que_nao_sei": {{
465
+ "validada": true|false,
466
+ "evidencias": "P2-cenários-exaustivos | P5-dúvidas-explícitas",
467
+ "lacunas": "contexto-X-ausente",
468
+ "confianca": "alta|media|baixa"
469
+ }},
470
+ "ambas_validadas": true|false,
471
+ "decisao": "exibir_resposta|exibir_falhas|reprocessar",
472
+ "nivel_consciencia": "alto|medio|baixo",
473
+ "falhas": [
474
+ {{
475
+ "tipo": "verdade1|verdade2",
476
+ "desc": "falha-X",
477
+ "impacto": "resposta-genérica",
478
+ "correcao": "perguntar-contexto"
479
+ }}
480
+ ]
481
+ }}
482
+ """
483
+
484
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.5)
485
+ registro = parse_json_seguro(resposta_raw)
486
+
487
+ return registro
488
+
489
+ # ==================== SINTETIZADOR: METACOGNIÇÃO → HUMANO ====================
490
+
491
+ def sintetizador_v18(
492
+ dna: Dict,
493
+ modo_sabio: bool = False,
494
+ turno_index: int = -1
495
+ ) -> str:
496
+ """
497
+ TRANSFORMA METACOGNIÇÃO CRUA EM PROSA HUMANIZADA.
498
+
499
+ Este é o ÚNICO lugar onde polimento acontece.
500
+ Recebe essência telegráfica dos passos, gera resposta fluida.
501
+ """
502
+
503
+ # Recupera última metacognição
504
+ analise_p1 = dna["historico_passos"]["passo1"][turno_index]["saida"] if dna["historico_passos"]["passo1"] else {}
505
+ analise_p2 = dna["historico_passos"]["passo2"][turno_index]["saida"] if dna["historico_passos"]["passo2"] else {}
506
+ analise_p3 = dna["historico_passos"]["passo3"][turno_index]["saida"] if dna["historico_passos"]["passo3"] else {}
507
+ analise_p4 = dna["historico_passos"]["passo4"][turno_index]["saida"] if dna["historico_passos"]["passo4"] else {}
508
+ analise_p5 = dna["historico_passos"]["passo5"][turno_index]["saida"] if dna["historico_passos"]["passo5"] else {}
509
+ analise_p6 = dna["historico_passos"]["passo6"][turno_index]["saida"] if dna["historico_passos"]["passo6"] else {}
510
+
511
+ contexto_filosofico_str = ""
512
+ if modo_sabio and CONTEXTO_FILOSOFICO:
513
+ contexto_filosofico_str = f"""
514
+ CONTEXTO FILOSÓFICO (use sutilmente se relevante):
515
+ {CONTEXTO_FILOSOFICO[:1000]}
516
+
517
+ Tom: Amigo Sábio - conversacional, empático, empoderador.
518
+ """
519
+
520
+ prompt = f"""
521
+ Você é um SINTETIZADOR - transforma METACOGNIÇÃO CRUA em PROSA HUMANIZADA.
522
+
523
+ METACOGNIÇÃO DOS PASSOS (formato telegráfico):
524
+
525
+ TRIAGEM (P1):
526
+ {json.dumps(analise_p1, indent=2, ensure_ascii=False)}
527
+
528
+ CENÁRIOS (P2):
529
+ {json.dumps(analise_p2, indent=2, ensure_ascii=False)}
530
+
531
+ EXPLORAÇÕES (P3):
532
+ {json.dumps(analise_p3, indent=2, ensure_ascii=False)}
533
+
534
+ PRINCÍPIOS (P4):
535
+ {json.dumps(analise_p4, indent=2, ensure_ascii=False)}
536
+
537
+ METACOGNIÇÃO (P5):
538
+ {json.dumps(analise_p5, indent=2, ensure_ascii=False)}
539
+
540
+ JUIZ (P6):
541
+ {json.dumps(analise_p6, indent=2, ensure_ascii=False)}
542
+
543
+ {contexto_filosofico_str}
544
+
545
+ ---
546
+
547
+ TAREFA: TRANSFORMAR METACOGNIÇÃO → PROSA HUMANIZADA
548
+
549
+ **EXEMPLO ENTRADA:** "Python | curva: 3-6m | vagas: 40% DS/backend | ROI: 2x-rápido"
550
+
551
+ **EXEMPLO SAÍDA:** "Python oferece uma curva de aprendizado mais rápida (3 a 6 meses), com 40% das vagas júnior em data science e backend. Você entra no mercado aproximadamente duas vezes mais rápido."
552
+
553
+ **INSTRUÇÕES:**
554
+
555
+ 1. Adicione conectores naturais: "porque", "portanto", "isso significa"
556
+ 2. Expanda abreviações: "curva-aprendizado" → "curva de aprendizado"
557
+ 3. Humanize números: "3-6m" → "3 a 6 meses"
558
+ 4. Estruture em parágrafos com introdução-desenvolvimento-nuances
559
+ 5. Se P4 identificou símbolos arquetípicos (ex: Jornada Herói) → tone empático
560
+ 6. Integre princípios naturalmente (não mencione "princípio de X")
561
+ 7. Se {modo_sabio} modo sábio → use metáforas, perguntas socráticas
562
+
563
+ **GERE RESPOSTA FINAL (texto fluido, natural, humano):**
564
+ """
565
+
566
+ resposta_raw = chamar_gemini(counselor_model, prompt, temperatura=0.8)
567
+
568
+ return resposta_raw.strip()
569
+
570
+ # ==================== PASSO 7: VERIFICADOR FINAL ====================
571
+
572
+ def passo7_verificador_final(
573
+ resposta_sintetizada: str,
574
+ analise_p6: Dict
575
+ ) -> Dict:
576
+ """
577
+ VERIFICAÇÃO FINAL - Factual, lógico, ético.
578
+ ENTRADA: Resposta humanizada do sintetizador + P6.
579
+ SAÍDA: Aprovado ou corrigido.
580
+ """
581
+
582
+ prompt = f"""
583
+ Você é um VERIFICADOR FINAL - guardião de qualidade.
584
+
585
+ RESPOSTA SINTETIZADA (prestes a ser enviada):
586
+ "{resposta_sintetizada}"
587
+
588
+ ANÁLISE DO PASSO 6 (Juiz):
589
+ {json.dumps(analise_p6, indent=2, ensure_ascii=False)}
590
+
591
+ ---
592
+
593
+ VERIFICAÇÃO TRIPLA (devolver JSON):
594
+
595
+ **1. VERIFICAÇÃO FACTUAL**
596
+ Contém fatos incorretos? Datas, nomes, estatísticas errados?
597
+
598
+ **2. VERIFICAÇÃO LÓGICA**
599
+ Contém falácias? Saltos lógicos injustificados?
600
+
601
+ **3. VERIFICAÇÃO ÉTICA**
602
+ Eticamente apropriada? Sem conselhos médicos/legais sem disclaimers?
603
+
604
+ RETORNE JSON:
605
+ {{
606
+ "verificacao_factual": {{
607
+ "aprovada": true|false,
608
+ "problemas": ["problema-1"]|[],
609
+ "correcoes": ["correção-1"]|[]
610
+ }},
611
+ "verificacao_logica": {{
612
+ "aprovada": true|false,
613
+ "falacias": ["falácia-1"]|[],
614
+ "correcoes": ["correção-1"]|[]
615
+ }},
616
+ "verificacao_etica": {{
617
+ "aprovada": true|false,
618
+ "problemas": ["problema-1"]|[],
619
+ "correcoes": ["correção-1"]|[]
620
+ }},
621
+ "todas_aprovadas": true|false,
622
+ "decisao": "exibir_resposta|corrigir_e_exibir",
623
+ "justificativa": "...",
624
+ "resposta_corrigida": "versão corrigida ou null",
625
+ "nota_correcao": "nota ao usuário ou null"
626
+ }}
627
+ """
628
+
629
+ resposta_raw = chamar_gemini(supervisor_model, prompt, temperatura=0.5)
630
+ registro = parse_json_seguro(resposta_raw)
631
+
632
+ return registro
633
+
634
+ # ==================== GESTÃO DE MEMÓRIA ====================
635
+
636
+ def gerar_resumo_contextual(turnos_antigos: List[Dict]) -> Dict:
637
+ """
638
+ Comprime turnos antigos em resumo vago mas útil.
639
+ Chamado quando há >10 turnos.
640
+ """
641
+
642
+ dialogo_antigo = "\n\n".join([
643
+ f"User: {t['user']}\nAssistant: {t['assistant']}"
644
+ for t in turnos_antigos[:5] # Amostra primeiros 5
645
+ ])
646
+
647
+ prompt = f"""
648
+ Você é um Compressor de Memória.
649
+
650
+ HISTÓRICO ANTIGO (primeiros turnos):
651
+ {dialogo_antigo}
652
+
653
+ ---
654
+
655
+ COMPRIMA EM RESUMO VAGO MAS ÚTIL (como professor que não lembra exatamente):
656
+
657
+ Não tente detalhar tudo. Apenas:
658
+ 1. Temas gerais discutidos
659
+ 2. Aprendizados importantes sobre o usuário
660
+ 3. Contexto útil para o futuro
661
+
662
+ RETORNE JSON:
663
+ {{
664
+ "resumo": "1-3 frases com contexto global",
665
+ "temas": ["tema-1", "tema-2"],
666
+ "aprendizados": ["aprendizado-1", "aprendizado-2"]
667
+ }}
668
+ """
669
+
670
+ resposta_raw = chamar_gemini(counselor_model, prompt)
671
+ resumo = parse_json_seguro(resposta_raw)
672
+
673
+ return {
674
+ "resumo": resumo.get("resumo", ""),
675
+ "temas": resumo.get("temas", []),
676
+ "aprendizados": resumo.get("aprendizados", [])
677
+ }
678
+
679
+ def limpar_memoria_cognitiva(dna: Dict) -> None:
680
+ """
681
+ Executa a cada 10 turnos.
682
+ Preserva: historico_chat + metadados
683
+ Limpa: historico_passos (mantém últimos 10)
684
+ Comprime: turnos antigos → resumo contextual
685
+ """
686
+
687
+ turno_atual = dna["metadados"]["total_turnos"]
688
+ ultimo_turno_limpeza = dna["metadados"].get("ultimo_turno_limpeza", 0)
689
+
690
+ if turno_atual - ultimo_turno_limpeza < 10:
691
+ return
692
+
693
+ print(f"\n{'='*70}")
694
+ print(f"🧹 LIMPEZA DE MEMÓRIA COGNITIVA (Turno {turno_atual})")
695
+ print(f"{'='*70}\n")
696
+
697
+ # 1. Preserva últimos 10 registros de cada passo
698
+ for passo_nome in ["passo0", "passo1", "passo2", "passo3", "passo4", "passo5", "passo6", "passo7"]:
699
+ historico_passo = dna["historico_passos"][passo_nome]
700
+
701
+ if len(historico_passo) > 10:
702
+ removidos = len(historico_passo) - 10
703
+ dna["historico_passos"][passo_nome] = historico_passo[-10:]
704
+ print(f" {passo_nome}: {len(historico_passo)} → 10 (removidos {removidos})")
705
+
706
+ # 2. Comprime turnos antigos
707
+ turnos_antigos_chat = dna["historico_chat"][:-10]
708
+
709
+ if len(turnos_antigos_chat) > 0:
710
+ print(f"\n Comprimindo {len(turnos_antigos_chat)} turnos antigos...\n")
711
+ resumo_contextual = gerar_resumo_contextual(turnos_antigos_chat)
712
+
713
+ dna["memoria_contextual"] = {
714
+ "ultimos_10_turnos": {
715
+ "memoria_tipo": "clara",
716
+ "indices_chat": list(range(max(0, len(dna["historico_chat"]) - 10), len(dna["historico_chat"]))),
717
+ "passos_completos": True
718
+ },
719
+ "turnos_anteriores": {
720
+ "memoria_tipo": "vaga",
721
+ "total_turnos_comprimidos": len(turnos_antigos_chat),
722
+ "resumo_contexto_global": resumo_contextual["resumo"],
723
+ "temas_principais": resumo_contextual["temas"],
724
+ "aprendizados_chave": resumo_contextual["aprendizados"]
725
+ }
726
+ }
727
+
728
+ # 3. Atualiza metadados
729
+ dna["metadados"]["ultimo_turno_limpeza"] = turno_atual
730
+
731
+ print(f"✅ Limpeza concluída")
732
+ print(f" Memória clara: últimos 10 turnos")
733
+ print(f" Memória vaga: {len(turnos_antigos_chat)} turnos comprimidos")
734
+ print(f"{'='*70}\n")
735
+
736
+ # ==================== PIPELINE PRINCIPAL v18 ====================
737
+
738
+ def processar_turno_v18(
739
+ mensagem_usuario: str,
740
+ dna: Dict,
741
+ modo_sabio: bool = False
742
+ ) -> Tuple[str, Dict]:
743
+ """
744
+ Pipeline completa v18: Metacognição → Síntese → Verificação
745
+ Retorna: (resposta_final, dna_atualizado)
746
+ """
747
+
748
+ print(f"\n{'='*70}")
749
+ print(f"📩 TURNO #{dna['metadados']['total_turnos'] + 1}")
750
+ print(f"{'='*70}\n")
751
+
752
+ # 0. PASSO 0: ALUNO (Feedback)
753
+ print("🎓 PASSO 0: Aluno (analisando feedback)...")
754
+
755
+ turno_anterior = dna["historico_chat"][-1] if len(dna["historico_chat"]) > 0 else None
756
+ memoria_contextual = dna["memoria_contextual"]
757
+
758
+ registro_p0 = passo0_aluno(mensagem_usuario, turno_anterior, memoria_contextual)
759
+
760
+ dna["historico_passos"]["passo0"].append({
761
+ "entrada": mensagem_usuario,
762
+ "saida": registro_p0,
763
+ "timestamp": datetime.now().isoformat()
764
+ })
765
+
766
+ # Adiciona turno ao chat
767
+ dna["historico_chat"].append({
768
+ "user": mensagem_usuario,
769
+ "assistant": None,
770
+ "timestamp": datetime.now().isoformat()
771
+ })
772
+ dna["metadados"]["total_turnos"] += 1
773
+
774
+ print(f" Decisão P0: {registro_p0.get('decisao', 'N/A')}\n")
775
+
776
+ # Verifica decisão P0
777
+ decisao_p0 = registro_p0.get("decisao")
778
+
779
+ if decisao_p0 == "prosseguir_passo1":
780
+ print("✅ Prosseguindo pipeline normal...\n")
781
+
782
+ # 1. PASSO 1: TRIAGEM
783
+ print("🔍 PASSO 1: Triagem...")
784
+ contexto_vago = memoria_contextual["turnos_anteriores"]["resumo_contexto_global"]
785
+ historico_recente = [{"user": t["user"], "assistant": t["assistant"]} for t in dna["historico_chat"][-4:-1]]
786
+
787
+ registro_p1 = passo1_triagem(mensagem_usuario, historico_recente, contexto_vago)
788
+
789
+ dna["historico_passos"]["passo1"].append({
790
+ "entrada": mensagem_usuario,
791
+ "saida": registro_p1,
792
+ "timestamp": datetime.now().isoformat()
793
+ })
794
+
795
+ print(f" Tipo: {registro_p1.get('tipo', 'N/A')}")
796
+ print(f" Decisão: {registro_p1.get('decisao', 'N/A')}\n")
797
+
798
+ # 2. PASSO 2: CENÁRIOS
799
+ print("🎯 PASSO 2: Cenários...")
800
+
801
+ registro_p2 = passo2_cenarios(
802
+ mensagem_usuario,
803
+ dna["historico_chat"],
804
+ registro_p1,
805
+ contexto_vago
806
+ )
807
+
808
+ dna["historico_passos"]["passo2"].append({
809
+ "entrada": mensagem_usuario,
810
+ "saida": registro_p2,
811
+ "timestamp": datetime.now().isoformat()
812
+ })
813
+
814
+ if registro_p2.get("decisao") == "pedir_esclarecimento":
815
+ resposta_final = registro_p2.get("pergunta", "Poderia esclarecer melhor?")
816
+ dna["historico_chat"][-1]["assistant"] = resposta_final
817
+ return resposta_final, dna
818
+
819
+ print(f" Cenários: {registro_p2.get('total', 0)}")
820
+ print(f" Decisão: {registro_p2.get('decisao', 'N/A')}\n")
821
+
822
+ # 3. PASSO 3: EXPLORAÇÃO
823
+ print("💡 PASSO 3: Exploração...")
824
+
825
+ registro_p3 = passo3_exploracao(
826
+ dna["historico_chat"],
827
+ registro_p1,
828
+ registro_p2
829
+ )
830
+
831
+ dna["historico_passos"]["passo3"].append({
832
+ "entrada": f"Explorando {registro_p2.get('total', 0)} cenários",
833
+ "saida": registro_p3,
834
+ "timestamp": datetime.now().isoformat()
835
+ })
836
+
837
+ if registro_p3.get("recomendacao") == "pedir_esclarecimento":
838
+ resposta_final = registro_p3.get("pergunta", "Poderia esclarecer melhor?")
839
+ dna["historico_chat"][-1]["assistant"] = resposta_final
840
+ return resposta_final, dna
841
+
842
+ print(f" Cenário mais confiante: {registro_p3.get('cenario_mais_confiante', 'N/A')}\n")
843
+
844
+ # 4. PASSO 4: PRINCÍPIOS
845
+ print("🔀 PASSO 4: Princípios + Símbolos...")
846
+
847
+ registro_p4 = passo4_principios_simbolos(
848
+ dna["historico_chat"],
849
+ registro_p1,
850
+ registro_p2,
851
+ registro_p3
852
+ )
853
+
854
+ dna["historico_passos"]["passo4"].append({
855
+ "entrada": "Analisando conhecimento fundamental",
856
+ "saida": registro_p4,
857
+ "timestamp": datetime.now().isoformat()
858
+ })
859
+
860
+ print(f" Princípio central: {registro_p4.get('principio_central', 'N/A')}\n")
861
+
862
+ # 5. PASSO 5: METACOGNIÇÃO
863
+ print("✨ PASSO 5: Metacognição...")
864
+
865
+ registro_p5 = passo5_metacognicao(
866
+ dna["historico_chat"],
867
+ registro_p1,
868
+ registro_p2,
869
+ registro_p3,
870
+ registro_p4
871
+ )
872
+
873
+ dna["historico_passos"]["passo5"].append({
874
+ "entrada": "Avaliação de certezas vs dúvidas",
875
+ "saida": registro_p5,
876
+ "timestamp": datetime.now().isoformat()
877
+ })
878
+
879
+ if registro_p5.get("decisao") == "questionar":
880
+ resposta_final = registro_p5.get("questionamento", "Poderia esclarecer melhor?")
881
+ dna["historico_chat"][-1]["assistant"] = resposta_final
882
+ return resposta_final, dna
883
+
884
+ print(f" Confiança global: {registro_p5.get('confianca_global', 'N/A')}\n")
885
+
886
+ # 6. PASSO 6: JUIZ
887
+ print("⚖️ PASSO 6: Juiz da Verdade...")
888
+
889
+ rota_rapida = registro_p1.get("decisao") == "responder_direto"
890
+
891
+ registro_p6 = passo6_juiz_verdade(
892
+ dna["historico_chat"],
893
+ registro_p1,
894
+ registro_p2,
895
+ registro_p3,
896
+ registro_p4,
897
+ registro_p5,
898
+ rota_rapida
899
+ )
900
+
901
+ dna["historico_passos"]["passo6"].append({
902
+ "entrada": "Validação socrática",
903
+ "saida": registro_p6,
904
+ "timestamp": datetime.now().isoformat()
905
+ })
906
+
907
+ if registro_p6.get("decisao") == "exibir_falhas":
908
+ resposta_final = registro_p6.get("pergunta_corretiva", "Há pontos que precisamos esclarecer melhor.")
909
+ dna["historico_chat"][-1]["assistant"] = resposta_final
910
+ return resposta_final, dna
911
+
912
+ print(f" Nível de consciência: {registro_p6.get('nivel_consciencia', 'N/A')}\n")
913
+
914
+ # 7. SINTETIZADOR: Transforma metacognição em prosa
915
+ print("🎯 Sintetizador: Transformando metacognição em prosa...")
916
+
917
+ resposta_sintetizada = sintetizador_v18(dna, modo_sabio)
918
+
919
+ print(f" Resposta gerada ({len(resposta_sintetizada)} caracteres)\n")
920
+
921
+ # 8. PASSO 7: VERIFICADOR FINAL
922
+ print("🔍 PASSO 7: Verificação Final...")
923
+
924
+ registro_p7 = passo7_verificador_final(resposta_sintetizada, registro_p6)
925
+
926
+ dna["historico_passos"]["passo7"].append({
927
+ "entrada": f"Verificando resposta ({len(resposta_sintetizada)} caracteres)",
928
+ "saida": registro_p7,
929
+ "timestamp": datetime.now().isoformat()
930
+ })
931
+
932
+ factual_ok = registro_p7.get("verificacao_factual", {}).get("aprovada", False)
933
+ logica_ok = registro_p7.get("verificacao_logica", {}).get("aprovada", False)
934
+ etica_ok = registro_p7.get("verificacao_etica", {}).get("aprovada", False)
935
+
936
+ print(f" Factual: {'✓' if factual_ok else '✗'}")
937
+ print(f" Lógica: {'✓' if logica_ok else '✗'}")
938
+ print(f" Ética: {'✓' if etica_ok else '✗'}\n")
939
+
940
+ # 9. DECISÃO FINAL
941
+ if registro_p7.get("decisao") == "exibir_resposta":
942
+ resposta_final = resposta_sintetizada
943
+ print("✅ Verificação aprovada - Resposta original exibida\n")
944
+ else:
945
+ resposta_corrigida = registro_p7.get("resposta_corrigida", resposta_sintetizada)
946
+ nota = registro_p7.get("nota_correcao", "")
947
+ resposta_final = f"{resposta_corrigida}\n\n---\n\n**Nota de Refinamento:** {nota}"
948
+ print("⚠️ Correções aplicadas - Resposta refinada exibida\n")
949
+
950
+ # Atualiza metadados
951
+ dna["metadados"]["total_correcoes_passo7"] += 1
952
+ tipo_correcao = []
953
+ if not factual_ok:
954
+ tipo_correcao.append("factuais")
955
+ if not logica_ok:
956
+ tipo_correcao.append("logicas")
957
+ if not etica_ok:
958
+ tipo_correcao.append("eticas")
959
+
960
+ for tipo in tipo_correcao:
961
+ if tipo in dna["metadados"]["tipos_correcoes"]:
962
+ dna["metadados"]["tipos_correcoes"][tipo] += 1
963
+
964
+ else:
965
+ # Rotas especiais (reexplicar ou atualizar)
966
+ resposta_final = f"[Rota especial: {decisao_p0}] - Em desenvolvimento"
967
+
968
+ # 10. ATUALIZA DNA
969
+ dna["historico_chat"][-1]["assistant"] = resposta_final
970
+
971
+ # 11. LIMPEZA DE MEMÓRIA (a cada 10 turnos)
972
+ limpar_memoria_cognitiva(dna)
973
+
974
+ print(f"✅ CONCLUÍDO\n{'='*70}\n")
975
+
976
+ return resposta_final, dna
977
+
978
+ # ==================== INTERFACE GRADIO ====================
979
+
980
+ def criar_interface():
981
+ """Cria interface Gradio."""
982
+
983
+ dna = criar_dna_vazio()
984
+
985
+ def chat(mensagem, modo_sabio_check, historia_chat):
986
+ """Callback para chat."""
987
+ nonlocal dna
988
+
989
+ resposta, dna = processar_turno_v18(mensagem, dna, modo_sabio_check)
990
+
991
+ # Formata histórico para Gradio
992
+ historia_chat.append((mensagem, resposta))
993
+
994
+ return "", historia_chat, json.dumps(dna, indent=2, ensure_ascii=False)
995
+
996
+ with gr.Blocks(title="Pipeline v18: Metacognição → Síntese") as interface:
997
+ gr.Markdown("""
998
+ # 🧠 Pipeline v18: Metacognição Pura
999
+
1000
+ **Arquitetura:**
1001
+ - Passos 0-6: Pensamento telegráfico (metacognição crua)
1002
+ - Sintetizador: Transforma em prosa humanizada
1003
+ - Passo 7: Verificação final (factual, lógica, ética)
1004
+ - Gestão de Memória: Limpeza a cada 10 turnos
1005
+ """)
1006
+
1007
+ with gr.Row():
1008
+ with gr.Column(scale=3):
1009
+ chat_display = gr.Chatbot(label="Conversa", height=500)
1010
+ msg_input = gr.Textbox(
1011
+ label="Sua mensagem",
1012
+ placeholder="Digite sua pergunta...",
1013
+ lines=2
1014
+ )
1015
+ modo_sabio = gr.Checkbox(label="🧙 Modo Sábio (Filosófico)")
1016
+
1017
+ enviar_btn = gr.Button("Enviar", variant="primary")
1018
+
1019
+ with gr.Column(scale=1):
1020
+ dna_display = gr.Code(label="DNA (JSON)", language="json", lines=30)
1021
+
1022
+ enviar_btn.click(
1023
+ chat,
1024
+ inputs=[msg_input, modo_sabio, chat_display],
1025
+ outputs=[msg_input, chat_display, dna_display]
1026
+ )
1027
+
1028
+ msg_input.submit(
1029
+ chat,
1030
+ inputs=[msg_input, modo_sabio, chat_display],
1031
+ outputs=[msg_input, chat_display, dna_display]
1032
+ )
1033
+
1034
+ return interface
1035
+
1036
+ # ==================== MAIN ====================
1037
+
1038
+ if __name__ == "__main__":
1039
+ interface = criar_interface()
1040
+ interface.launch(share=False)