Spaces:
Sleeping
Sleeping
| # ╔════════════════════════════════════════════════════════════════════════════╗ | |
| # ║ 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 | |
| ) | |