caarleexx commited on
Commit
0e239d8
·
verified ·
1 Parent(s): cd5c320

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -163
app.py CHANGED
@@ -1,11 +1,13 @@
1
  # ╔════════════════════════════════════════════════════════════════════════════╗
2
- # ║ PIPELINE v22: ORQUESTRAÇÃO DE AGENTES (JSON-LIST)
3
- # ║ O Segredo: Uma lista de instruções que governa o pensamento.
4
  # ╚════════════════════════════════════════════════════════════════════════════╝
5
 
6
  import os
7
  import json
8
  import re
 
 
9
  import gradio as gr
10
  import google.generativeai as genai
11
 
@@ -13,194 +15,192 @@ import google.generativeai as genai
13
  api_key = os.getenv("GOOGLE_API_KEY", "SUA_API_KEY_AQUI")
14
  genai.configure(api_key=api_key)
15
 
16
- # Modelo Flash para raciocínio rápido, Pro para redação final
17
- model_fast = genai.GenerativeModel("gemini-flash-latest")
18
- model_pro = genai.GenerativeModel("gemini-pro-latest")
19
-
20
- # ==================== 2. O PROTOCOLO (A "ALMA" DA IA) ====================
21
- # É aqui que você define a inteligência. O código abaixo apenas obedece esta lista.
22
- # Adicione ou remova agentes aqui para mudar o comportamento do sistema.
23
-
24
- PROTOCOLO_OPERACIONAL = [
25
- {
26
- "nome": "ESCRIVÃO_DIGITAL",
27
- "tipo_saida": "json",
28
- "modelo": model_fast,
29
- "missao": """
30
- Leia o input do Usuário. Sua tarefa é extrair FATOS frios.
31
- Extraia:
32
- 1. Quem são as partes (Vítima/Acusado).
33
- 2. Cronologia (O que aconteceu e quando).
34
- 3. Inventário de Provas (O que foi citado: áudio, vídeo, testemunha).
35
- Retorne APENAS JSON.
36
- """
37
- },
38
- {
39
- "nome": "ANALISTA_COMPORTAMENTAL",
40
- "tipo_saida": "json",
41
- "modelo": model_fast,
42
- "missao": """
43
- Leia o input original e os fatos do Escrivão.
44
- Sua tarefa é analisar o SUBTEXTO e a PSICOLOGIA.
45
- 1. Analise o tom de voz descrito ou transcrito.
46
- 2. Identifique manipulação (Gaslighting, Inversão de Culpa).
47
- 3. Avalie a coerência emocional (Alguém calmo demais? Alguém desesperado?).
48
- Retorne APENAS JSON.
49
- """
50
- },
51
- {
52
- "nome": "AUDITOR_INVESTIGATIVO",
53
- "tipo_saida": "json",
54
- "modelo": model_fast,
55
- "missao": """
56
- Sua tarefa é encontrar a MENTIRA.
57
- Cruze o depoimento do acusado (Fatos) com a análise psicológica (Comportamental).
58
- Liste as contradições. Onde a versão dele não bate com a realidade do áudio/texto?
59
- Retorne APENAS JSON.
60
- """
61
- },
62
- {
63
- "nome": "PROMOTOR_SENIOR",
64
- "tipo_saida": "texto", # Gera o relatório final visível
65
- "modelo": model_pro, # Modelo mais potente para escrever bem
66
- "missao": """
67
- Escreva o PARECER TÉCNICO FINAL (Relatório Jurídico).
68
- Use Markdown. Seja detalhado (+600 palavras).
69
- Estrutura Obrigatória:
70
- 1. Cabeçalho (Data/Assunto).
71
- 2. Sumário dos Fatos (Baseado no Escrivão).
72
- 3. Análise Forense (Baseado no Analista e Auditor). Explique a manipulação.
73
- 4. Fundamentação Jurídica (Cite leis: Maria da Penha, Ameaça, Violência Psicológica).
74
- 5. Conclusão e Pedidos (Prisão? Medida Protetiva?).
75
- """
76
- }
77
- ]
78
-
79
- # ==================== 3. O MOTOR (CÓDIGO AGNÓSTICO) ====================
80
 
81
  def limpar_json(texto: str) -> dict:
82
- """Garante que o JSON venha limpo, sem markdown."""
83
  try:
84
- if "```" in texto:
85
- texto = re.search(r"```json?(.*?)```", texto, re.DOTALL).group(1)
86
  return json.loads(texto.strip())
87
- except:
88
- return {"conteudo_bruto": texto}
89
 
90
- def executar_agente(timeline: list, config: dict) -> dict:
91
- """Um agente entra na sala, a timeline e dá sua opinião."""
92
 
93
- # 1. O agente recebe todo o histórico anterior como contexto
94
  contexto_str = json.dumps(timeline, ensure_ascii=False, indent=2)
95
-
96
- prompt = f"""
97
- --- CONTEXTO DO PROCESSO (TIMELINE) ---
98
- {contexto_str}
99
- ---------------------------------------
100
-
101
- VOCÊ É O AGENTE: {config['nome']}
102
- SUA MISSÃO: {config['missao']}
103
-
104
- IMPORTANTE: Não converse. Apenas execute a missão.
105
  """
106
 
 
 
 
107
  try:
108
- # 2. Chamada à API
109
- response = config['modelo'].generate_content(prompt)
110
- conteudo_raw = response.text
 
111
 
112
- # 3. Processamento da Saída
113
- if config['tipo_saida'] == 'json':
114
- conteudo_processado = limpar_json(conteudo_raw)
115
- else:
116
- conteudo_processado = conteudo_raw # Texto/Markdown
117
 
118
- return {
119
- "role": "assistant",
120
- "agent_name": config['nome'],
121
- "content": conteudo_processado
122
- }
123
 
124
  except Exception as e:
125
- return {"role": "system", "error": str(e)}
126
 
127
- def orquestrador(texto_usuario: str):
128
- """Loop principal que roda a lista de agentes."""
129
- if not texto_usuario.strip(): return "Insira um caso.", []
130
 
131
- # 1. Inicia a Timeline com a entrada do usuário
132
- timeline = [
133
- {"role": "user", "content": texto_usuario}
134
- ]
 
 
 
 
 
135
 
136
- relatorio_final = ""
 
 
137
 
138
- # 2. O Loop Mágico (Itera sobre o Protocolo)
139
- for passo in PROTOCOLO_OPERACIONAL:
140
- # Executa o agente atual
141
- resultado = executar_agente(timeline, passo)
142
-
143
- # Adiciona o resultado à timeline para os próximos agentes verem
 
 
 
 
 
 
 
 
 
 
 
144
  timeline.append(resultado)
 
145
 
146
- # Se for o Promotor (texto), salvamos para exibir na tela principal
147
- if passo['tipo_saida'] == 'texto':
148
  relatorio_final = resultado['content']
 
 
 
 
149
 
150
- # Retorna o texto formatado e a timeline completa (JSON) para inspeção
151
- return relatorio_final, timeline
152
 
153
- # ==================== 4. INTERFACE GRÁFICA ====================
154
 
155
- def interface():
156
- with gr.Blocks(title="Orquestrador v22", theme=gr.themes.Soft()) as app:
157
-
158
- gr.Markdown("# ⚖️ Pipeline Cognitiva: Orquestração de Agentes")
159
- gr.Markdown("Este sistema não usa um prompt único. Ele usa uma cadeia de especialistas virtuais definidos em JSON.")
160
-
161
- with gr.Row():
162
- # Entrada
163
- inp = gr.Textbox(
164
- label="Dossiê do Caso (Texto/Transcrições)",
165
- lines=8,
166
- placeholder="Cole aqui o BO, depoimentos e transcrições..."
167
- )
168
-
169
- btn = gr.Button("🚀 INICIAR ORQUESTRAÇÃO", variant="primary", size="lg")
170
 
171
- with gr.Row():
172
- # Saída Final (Markdown Renderizado)
173
- out_relatorio = gr.Markdown(label="Parecer Final do Promotor")
174
-
175
- # Saída de Debug (O "Cérebro" da máquina)
176
- out_timeline = gr.JSON(label="Timeline de Consciência (Passo a Passo)")
177
 
178
- btn.click(orquestrador, inp, [out_relatorio, out_timeline])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  return app
181
 
182
- # ==================== PSEUDO-CÓDIGO (DOCUMENTAÇÃO) ====================
183
- """
184
- COMO ESTE CÓDIGO PENSA (Lógica Humanizada):
185
-
186
- 1. RECEBER(Caso) -> Cria uma Lista: [Caso]
187
-
188
- 2. PARA CADA Agente NA Lista_de_Instruções:
189
- A. O Agente LÊ toda a Lista até agora (memória perfeita).
190
- B. O Agente EXECUTA sua instrução específica (ex: "Ache mentiras").
191
- C. O Agente ESCREVE sua conclusão no final da Lista.
192
-
193
- Exemplo Visual da Lista crescendo:
194
- [
195
- {User: "Ele disse que não bateu..."},
196
- {Escrivão: "Fatos: Agressão dia 20..."},
197
- {Psicólogo: "Tom: Ele está manipulando..."},
198
- {Investigador: "Mentira detectada: Ele nega mas o áudio prova..."},
199
- {Promotor: "Relatório Final: Com base na mentira detectada pelo Investigador..."}
200
- ]
201
-
202
- 3. EXIBIR o trabalho do último Agente (Promotor).
203
- """
204
-
205
  if __name__ == "__main__":
206
- interface().launch()
 
 
1
  # ╔════════════════════════════════════════════════════════════════════════════╗
2
+ # ║ PIPELINE v25: ORQUESTRAÇÃO COM UPLOAD DE EVIDÊNCIAS
3
+ # ║ Novidade: Upload de arquivos de texto (.txt, .md, .csv) no input
4
  # ╚════════════════════════════════════════════════════════════════════════════╝
5
 
6
  import os
7
  import json
8
  import re
9
+ import time
10
+ from datetime import datetime
11
  import gradio as gr
12
  import google.generativeai as genai
13
 
 
15
  api_key = os.getenv("GOOGLE_API_KEY", "SUA_API_KEY_AQUI")
16
  genai.configure(api_key=api_key)
17
 
18
+ model_flash = genai.GenerativeModel("gemini-1.5-flash-latest")
19
+ model_pro = genai.GenerativeModel("gemini-1.5-pro-latest")
20
+
21
+ ARQUIVO_CONFIG = "protocolo.json"
22
+
23
+ # ==================== 2. MANIPULAÇÃO DE ARQUIVOS ====================
24
+
25
+ def carregar_protocolo_padrao():
26
+ try:
27
+ with open(ARQUIVO_CONFIG, "r", encoding="utf-8") as f: return f.read()
28
+ except: return "[]"
29
+
30
+ def salvar_protocolo_disco(conteudo_json):
31
+ try:
32
+ json.loads(conteudo_json) # Valida JSON
33
+ with open(ARQUIVO_CONFIG, "w", encoding="utf-8") as f: f.write(conteudo_json)
34
+ return "✅ Salvo!"
35
+ except Exception as e: return f"❌ Erro: {e}"
36
+
37
+ def ler_arquivo_input(arquivo):
38
+ """
39
+ Lê o conteúdo de um arquivo de texto enviado pelo usuário.
40
+ """
41
+ if arquivo is None:
42
+ return ""
43
+
44
+ try:
45
+ # Tenta ler como UTF-8
46
+ with open(arquivo.name, "r", encoding="utf-8") as f:
47
+ conteudo = f.read()
48
+ return f"\n\n=== CONTEÚDO DO ARQUIVO ANEXADO ({os.path.basename(arquivo.name)}) ===\n{conteudo}\n=======================================\n"
49
+ except UnicodeDecodeError:
50
+ return "\n\n[ERRO: O arquivo anexado não é um texto válido ou tem codificação desconhecida.]"
51
+ except Exception as e:
52
+ return f"\n\n[ERRO AO LER ARQUIVO: {str(e)}]"
53
+
54
+ # ==================== 3. ENGINE DE EXECUÇÃO ====================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  def limpar_json(texto: str) -> dict:
 
57
  try:
58
+ if "```" in texto: texto = re.search(r"```json?(.*?)```", texto, re.DOTALL).group(1)
 
59
  return json.loads(texto.strip())
60
+ except: return {"conteudo_texto": texto}
 
61
 
62
+ def executar_no(timeline: list, config: dict):
63
+ modelo_ativo = model_pro if config.get("modelo") == "pro" else model_flash
64
 
 
65
  contexto_str = json.dumps(timeline, ensure_ascii=False, indent=2)
66
+ prompt_bruto = f"""
67
+ --- TIMELINE DO CASO ---
68
+ {contexto_str}
69
+ ------------------------
70
+ AGENTE: {config['nome']}
71
+ MISSÃO: {config['missao']}
 
 
 
 
72
  """
73
 
74
+ log_entry = f"\n{'='*40}\n🔶 EXECUTANDO: {config['nome']}\n{'='*40}\n"
75
+ log_entry += f"📤 PROMPT:\n{prompt_bruto[:1000]}... [truncado para visualização]\n"
76
+
77
  try:
78
+ inicio = time.time()
79
+ response = modelo_ativo.generate_content(prompt_bruto)
80
+ output_bruto = response.text
81
+ tempo = time.time() - inicio
82
 
83
+ log_entry += f"📥 OUTPUT ({tempo:.2f}s):\n{output_bruto}\n"
84
+
85
+ if config['tipo_saida'] == 'json': conteudo = limpar_json(output_bruto)
86
+ else: conteudo = output_bruto
 
87
 
88
+ return {"role": "assistant", "agent": config['nome'], "content": conteudo}, log_entry
 
 
 
 
89
 
90
  except Exception as e:
91
+ return {"role": "system", "error": str(e)}, log_entry + f"\n❌ ERRO: {str(e)}\n"
92
 
93
+ # ==================== 4. ORQUESTRADOR ====================
 
 
94
 
95
+ def orquestrador(texto_caso, arquivo_anexo, json_protocolo_str):
96
+ """
97
+ Recebe texto + arquivo, combina ambos e inicia a pipeline.
98
+ """
99
+ # 1. Processa o arquivo anexado
100
+ conteudo_anexo = ler_arquivo_input(arquivo_anexo)
101
+
102
+ # 2. Combina Inputs
103
+ input_completo = f"{texto_caso}\n{conteudo_anexo}".strip()
104
 
105
+ if not input_completo:
106
+ yield "⚠️ Erro: Insira texto ou anexe um arquivo.", "", {}
107
+ return
108
 
109
+ try:
110
+ protocolo = json.loads(json_protocolo_str)
111
+ except Exception as e:
112
+ yield f"⚠️ Erro no JSON de Configuração: {e}", "", {}
113
+ return
114
+
115
+ # 3. Inicializa
116
+ info_anexo = "Sim" if conteudo_anexo else "Não"
117
+ logs_totais = f"🚀 INICIANDO (Anexo: {info_anexo})...\n"
118
+ timeline = [{"role": "user", "content": input_completo}]
119
+ relatorio_final = "⏳ Aguardando..."
120
+
121
+ yield logs_totais, relatorio_final, timeline
122
+
123
+ # 4. Loop de Agentes
124
+ for config_agente in protocolo:
125
+ resultado, log_no = executar_no(timeline, config_agente)
126
  timeline.append(resultado)
127
+ logs_totais += log_no
128
 
129
+ if config_agente['tipo_saida'] == 'texto':
 
130
  relatorio_final = resultado['content']
131
+ else:
132
+ relatorio_final = f"⏳ {config_agente['nome']} trabalhando..."
133
+
134
+ yield logs_totais, relatorio_final, timeline
135
 
136
+ logs_totais += "\n🏁 FINALIZADO."
137
+ yield logs_totais, relatorio_final, timeline
138
 
139
+ # ==================== 5. INTERFACE ====================
140
 
141
+ def construir_interface():
142
+ config_inicial = carregar_protocolo_padrao()
143
+
144
+ with gr.Blocks(title="Pipeline v25 - Com Upload", theme=gr.themes.Base()) as app:
145
+ gr.Markdown("# 🕵️‍♂️ Pipeline Forense v25: Input Multimodal (Texto + Arquivo)")
 
 
 
 
 
 
 
 
 
 
146
 
147
+ with gr.Tabs():
 
 
 
 
 
148
 
149
+ # === ABA EXECUÇÃO ===
150
+ with gr.TabItem("🚀 Execução"):
151
+ with gr.Row():
152
+ with gr.Column(scale=1):
153
+ inp_caso = gr.Textbox(
154
+ label="Instruções / Resumo do Caso",
155
+ lines=5,
156
+ placeholder="Digite instruções adicionais aqui..."
157
+ )
158
+ # NOVO COMPONENTE DE UPLOAD
159
+ inp_arquivo = gr.File(
160
+ label="Anexar Evidências (Texto/Logs/Transcrições)",
161
+ file_types=[".txt", ".md", ".csv", ".json"],
162
+ file_count="single"
163
+ )
164
+ btn_executar = gr.Button("⚡ EXECUTAR ANÁLISE COMPLETA", variant="primary", size="lg")
165
+
166
+ with gr.Column(scale=1):
167
+ out_logs = gr.Textbox(
168
+ label="📟 Console de Logs (Raw I/O)",
169
+ lines=15,
170
+ interactive=False,
171
+ elem_id="logs"
172
+ )
173
+
174
+ gr.Markdown("---")
175
+
176
+ with gr.Row():
177
+ out_relatorio = gr.Markdown(label="📄 Parecer Final")
178
+ out_timeline = gr.JSON(label="🧠 Memória JSON")
179
+
180
+ # === ABA CONFIGURAÇÃO ===
181
+ with gr.TabItem("⚙️ Configuração (JSON)"):
182
+ with gr.Row():
183
+ btn_save_config = gr.Button("💾 Salvar Protocolo")
184
+ lbl_config = gr.Label()
185
+
186
+ editor_json = gr.Code(
187
+ label="protocolo.json",
188
+ language="json",
189
+ value=config_inicial,
190
+ lines=20
191
+ )
192
+
193
+ btn_save_config.click(salvar_protocolo_disco, editor_json, lbl_config)
194
+
195
+ # EVENTO DE EXECUÇÃO
196
+ btn_executar.click(
197
+ orquestrador,
198
+ inputs=[inp_caso, inp_arquivo, editor_json], # Passa Texto + Arquivo + Config
199
+ outputs=[out_logs, out_relatorio, out_timeline]
200
+ )
201
 
202
  return app
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  if __name__ == "__main__":
205
+ print("Iniciando v25...")
206
+ construir_interface().launch()