ToM / app.py
caarleexx's picture
Create app.py
fd8ef38 verified
raw
history blame
13.7 kB
# ╔════════════════════════════════════════════════════════════════════════════╗
# ║ PIPELINE v29: PLANEJADOR AUTO-AGENTE | SUPERA PARADOXO MEHON ║
# ║ 1º: PLANEJA → 2º-N: EXECUTA → N+1: CONVERGE COM HISTÓRICO ║
# ╚════════════════════════════════════════════════════════════════════════════╝
import os
import json
import re
import time
from datetime import datetime
import gradio as gr
import google.generativeai as genai
# ==================== 1. CONFIGURAÇÃO GLOBAL ====================
api_key = os.getenv("GOOGLE_API_KEY")
if api_key:
genai.configure(api_key=api_key)
model_flash = genai.GenerativeModel("gemini-flash-latest")
model_pro = genai.GenerativeModel("gemini-pro-latest")
else:
model_flash = model_pro = None
print("⚠️ GOOGLE_API_KEY não encontrada. Configure via export GOOGLE_API_KEY=...")
ARQUIVO_HISTORY = "history_v29.json"
# ==================== 2. UTILIDADES DE PERSISTÊNCIA ====================
def carregar_history():
"""Carrega histórico persistente"""
try:
with open(ARQUIVO_HISTORY, "r", encoding="utf-8") as f:
return json.load(f)
except:
return []
def salvar_history(history):
"""Salva histórico automaticamente"""
try:
with open(ARQUIVO_HISTORY, "w", encoding="utf-8") as f:
json.dump(history, f, ensure_ascii=False, indent=2)
return True
except:
return False
def ler_anexo(arquivo):
"""Processa arquivos anexados"""
if not arquivo: return ""
try:
with open(arquivo.name, "r", encoding="utf-8") as f:
nome = os.path.basename(arquivo.name)
return f"\n\n📎 ANEXO: {nome}\n{f.read()}\n[FIM ANEXO]\n"
except:
return "❌ Erro lendo anexo"
def exportar_chat(history):
"""Gera TXT para download"""
if not history: return ""
timestamp = datetime.now().strftime('%Y-%m-%d_%H%M%S')
chat_txt = f"MEHON v29 EXPORT - {timestamp}\n\n"
for i, msg in enumerate(history, 1):
role = "👤 USUÁRIO" if i % 2 == 1 else "🤖 MEHON"
chat_txt += f"{role}:\n{msg}\n\n{'-'*80}\n\n"
return chat_txt
# ==================== 3. AGENTE PLANEJADOR (SUPERA MEHON) ====================
def gerar_plano_auto(input_completo, history_contexto):
"""AGENTE 1: CRIA PLANO DINÂMICO baseando-se em histórico + input"""
if not model_pro:
return None, "❌ Sem API_KEY"
# Compacta histórico (últimas 5 trocas, 200 chars cada)
history_resumo = ""
if len(history_contexto) >= 2:
history_resumo = "\n".join([
f"👤: {h[0][:200]}... | 🤖: {h[1][:200]}..."
for h in history_contexto[-5:]
])
prompt_planejador = f"""🚀 PLANEJADOR AUTO-AGENTE v29 - SUPERA PARADOXO MEHON
CONTEXTO HISTÓRICO DO USUÁRIO:
{history_resumo}
INPUT ATUAL: {input_completo}
---
CRIE PLANO ESTRUTURADO DE 3-6 AGENTES para resolver PERFEITAMENTE:
📋 FORMATO OBRIGATÓRIO (JSON VÁLIDO):
[
{{"nome": "NomeClaro", "missao": "InstruçãoPrecisade200palavras", "modelo": "flash", "tipo_saida": "texto"}},
...
]
✅ CRITÉRIOS DO PLANO:
• DECOMPONHA: problema → análise → cenários → validação → síntese
• IDENTIFIQUE ambiguidades/possibilidades do input
• PERSONALIZE com histórico do usuário
• ÚLTIMO agente SEMPRE gera saída FINAL pro usuário
• Evite resposta direta - USE CADEIA DE PENSAMENTO
EXEMPLO PLANO BOM:
[
{{"nome": "AnalisadorInput", "missao": "Identifique elementos principais, ambiguidades e contexto", "modelo": "flash", "tipo_saida": "json"}},
{{"nome": "ExploradorCenários", "missao": "Liste 3-5 cenários possíveis com probabilidades", "modelo": "pro", "tipo_saida": "json"}},
{{"nome": "SintetizadorFinal", "missao": "Converja tudo em resposta única e acionável", "modelo": "pro", "tipo_saida": "texto"}}
]
APENAS JSON VÁLIDO - SEM TEXTO EXTRA!"""
try:
resp = model_pro.generate_content(prompt_planejador, temperature=0.3)
plano_raw = resp.text.strip().replace('``````','').replace('json','')
plano = json.loads(plano_raw)
# Valida estrutura mínima
if not isinstance(plano, list) or len(plano) < 2:
return None, "❌ Plano inválido (precisa 2+ agentes)"
return plano, f"✅ Plano: {len(plano)} agentes gerados"
except Exception as e:
return None, f"❌ Erro plano: {str(e)[:100]}"
# ==================== 4. EXECUTOR DE AGENTES DINÂMICOS ====================
def executar_agente_especifico(timeline, agente_config, history_contexto):
"""Executa agente específico do plano dinâmico"""
if not (model_flash or model_pro):
return {"role": "system", "error": "Sem API"}, "(ERRO: API)", "Sem Google API Key"
modelo = model_pro if agente_config.get("modelo") == "pro" else model_flash
# Contexto: últimos 8 passos da timeline + histórico
contexto_timeline = json.dumps(timeline[-8:], ensure_ascii=False, indent=2)
history_resumo = "\n".join([f"👤: {h[0][:100]}... | 🤖: {h[1][:100]}..." for h in history_contexto[-3:]])
prompt = f"""CONTEXTO DA CADEIA DE PENSAMENTO:
{contexto_timeline}
HISTÓRICO RECENTE:
{history_resumo}
AGENTE ATIVO: {agente_config['nome']}
MISSÃO ESPECÍFICA: {agente_config['missao']}
{ 'JSON estruturado e válido' if agente_config['tipo_saida']=='json' else 'Resposta clara, completa e finalizada pro usuário' }:"""
log = f"🔸 {agente_config['nome']} ({agente_config['modelo']})"
try:
inicio = time.time()
resp = modelo.generate_content(prompt, temperature=0.1 if agente_config['tipo_saida']=='json' else 0.7)
out = resp.text.strip()
# Parse output
content = json.loads(out.replace('``````','')) if agente_config['tipo_saida']=='json' else out
tempo = time.time() - inicio
log += f" ✓ {tempo:.1f}s"
return {"role": "assistant", "agent": agente_config['nome'], "content": content}, log, out
except Exception as e:
log += f" ✗ {str(e)[:50]}"
return {"role": "system", "error": str(e)}, log, str(e)
# ==================== 5. ORQUESTRADOR PRINCIPAL (MEHON) ====================
def pipeline_mehon_completo(texto, arquivo, history):
"""Pipeline completo: PLANEJA → EXECUTA → CONVERGE"""
# Processa input
anexo = ler_anexo(arquivo)
full_input = f"{texto}{anexo}".strip()
if not full_input:
yield history, [], "ℹ️ Input vazio - digite algo!"
return
# Inicializa pipeline
history = history + [[full_input, "🧠 Iniciando raciocínio MEHON..."]]
timeline = [{"role": "user", "content": full_input, "timestamp": datetime.now().isoformat()}]
logs = f"🚀 MEHON v29 | {datetime.now().strftime('%H:%M:%S')}\n"
yield history, timeline, logs
# PASSO 1: PLANEJADOR AUTO-GERA plano dinâmico
history[-1][1] = "🎯 Planejador criando agentes sob medida..."
yield history, timeline, logs
plano, log_plano = gerar_plano_auto(full_input, history)
if not plano:
history[-1][1] = f"❌ {log_plano}"
yield history, timeline, logs
return
logs += f"{log_plano}\n"
timeline.append({"role": "system", "plano_gerado": plano, "step": "PLANEJAMENTO"})
yield history, timeline, logs
# PASSO 2: EXECUTA plano dinâmico sequencialmente
resposta_acumulada = ""
for i, agente in enumerate(plano):
history[-1][1] = f"⚙️ [{i+1}/{len(plano)}] {agente['nome']} pensando..."
yield history, timeline, logs
resultado, log_add, raw = executar_agente_especifico(timeline, agente, history)
timeline.append(resultado)
logs += f" {log_add}\n"
# Atualiza chat com output textual
if agente.get('tipo_saida') == 'texto' and 'content' in resultado:
resposta_acumulada = resultado['content']
preview = resposta_acumulada[:900] + "..." if len(resposta_acumulada) > 900 else resposta_acumulada
history[-1][1] = preview
yield history, timeline, logs
# Finaliza
logs += f"\n✅ Pipeline MEHON concluído | {len(plano)} agentes | {len(timeline)} passos"
salvar_history(history) # Auto-save
yield history, timeline, logs
# ==================== 6. INTERFACE GRADIO COMPLETA ====================
def criar_app_mehon_v29():
"""UI completa e funcional"""
css = """
footer { display: none !important; }
.gradio-container { max-width: 1400px; }
.mehon-title { font-size: 1.6em; font-weight: bold; color: #1e40af; text-align: center; }
.status-bar { background: linear-gradient(90deg, #3b82f6, #1e40af); color: white; padding: 8px; border-radius: 8px; }
"""
history_inicial = carregar_history()
with gr.Blocks(title="🚀 PIPELINE MEHON v29", css=css, theme=gr.themes.Soft()) as app:
# HEADER
gr.Markdown("### 🧠 PIPELINE MEHON v29 - Raciocínio Estruturado Automático")
gr.Markdown("*O modelo planeja → executa → converge. Supera respostas probabilísticas diretas.*")
with gr.Tabs():
# ABA 1: EXECUÇÃO PRINCIPAL
with gr.Tab("💭 Raciocínio MEHON", icon="🧠"):
chatbot = gr.Chatbot(
value=history_inicial,
height=550,
show_copy_button=True,
show_label=False,
render_markdown=True
)
with gr.Row():
with gr.Column(scale=8):
txt_input = gr.Textbox(
placeholder="""Qualquer pergunta complexa...
O modelo CRIARÁ seu plano de agentes e executará em cadeia!""",
lines=4,
container=False
)
with gr.Column(scale=1):
file_input = gr.File(
label="📎 Anexo",
file_types=[".txt", ".py", ".json", ".md", ".yaml", ".csv"]
)
with gr.Column(scale=1):
btn_executar = gr.Button("🚀 EXECUTAR PLANO", variant="primary")
status_atual = gr.Markdown("Status: Pronto", visible=True)
# ABA 2: DEBUG COMPLETO
with gr.Tab("🔍 Plano & Execução", icon="🔬"):
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 📋 Plano Gerado")
json_plano = gr.JSON(label="Agentes Dinâmicos", lines=15)
with gr.Column(scale=1):
gr.Markdown("### 📊 Timeline Completa")
timeline_json = gr.JSON(label="Cadeia de Pensamento", lines=15)
gr.Markdown("### 📈 Logs de Execução")
logs_execucao = gr.Textbox(label="Runtime Logs", lines=12)
# ABA 3: GERENCIAMENTO
with gr.Tab("📁 Histórico & Export", icon="💾"):
gr.Markdown("**Histórico persistente em `history_v29.json`**")
with gr.Row():
btn_limpar_chat = gr.Button("🗑️ Limpar Chat", variant="stop")
btn_export_txt = gr.Button("📥 Download TXT", variant="secondary")
btn_salvar_manual = gr.Button("💾 Salvar Manual", variant="secondary")
export_content = gr.Textbox(label="Conteúdo para Download", lines=20, max_lines=30)
status_ops = gr.Label("Status: OK", visible=True)
# ==================== EVENTOS ====================
def executar_pipeline_completo(txt, file, hist):
"""Wrapper para generator do pipeline"""
for resultado in pipeline_mehon_completo(txt, file, hist):
yield resultado # [chatbot, timeline, logs]
# Trigger principal
btn_executar.click(
executar_pipeline_completo,
inputs=[txt_input, file_input, chatbot],
outputs=[chatbot, timeline_json, logs_execucao]
).then(
lambda: gr.update(value=""),
outputs=[txt_input]
)
txt_input.submit(
executar_pipeline_completo,
inputs=[txt_input, file_input, chatbot],
outputs=[chatbot, timeline_json, logs_execucao]
)
# Controles
btn_limpar_chat.click(lambda: [], chatbot)
btn_export_txt.click(exportar_chat, chatbot, export_content)
btn_salvar_manual.click(lambda h: salvar_history(h) or "Salvo!", chatbot, status_ops)
return app
# ==================== LAUNCH ====================
if __name__ == "__main__":
print("🚀 Iniciando PIPELINE MEHON v29...")
print("💡 Configure GOOGLE_API_KEY para uso completo")
print("📁 History salvo em history_v29.json")
app = criar_app_mehon_v29()
app.launch(
server_name="0.0.0.0",
server_port=7861,
share=False,
show_error=True,
quiet=False
)