# app.py — Multi-Agent Debate System | ATLAS vs NEXUS vs ORACLE import streamlit as st import os st.set_page_config( page_title="Debate Arena · Multi-Agent", page_icon="⚔️", layout="wide", initial_sidebar_state="expanded", ) # ── CSS: ARENA THEME ────────────────────────────────────────── st.markdown(""" """, unsafe_allow_html=True) # ── SESSION STATE ───────────────────────────────────────────── for k, v in { 'debates': [], 'openai_key': '', 'running': False, }.items(): if k not in st.session_state: st.session_state[k] = v # ── HELPERS ─────────────────────────────────────────────────── def get_key(): try: if 'OPENAI_API_KEY' in st.secrets: return st.secrets['OPENAI_API_KEY'] except Exception: pass return os.getenv('OPENAI_API_KEY', st.session_state.openai_key) # ── SIDEBAR ─────────────────────────────────────────────────── with st.sidebar: st.markdown("""
DEBATE ARENA
Multi-Agent System v1.0
""", unsafe_allow_html=True) st.divider() st.markdown("#### 🔑 OpenAI API Key") key_in = st.text_input("", type="password", value=st.session_state.openai_key, placeholder="sk-...", label_visibility="collapsed") if key_in: st.session_state.openai_key = key_in if get_key(): st.success("✅ Key configurada") else: st.warning("Configure a API Key") st.divider() st.markdown("#### ⚙️ Configuração") n_rounds = st.slider("Rounds de debate", 1, 4, 2, help="Cada round = 1 turno NEXUS + 1 turno ATLAS") st.divider() st.markdown("""
▮ ATLAS — Arguer PRO
Defende a posição com dados e lógica.

▮ NEXUS — Arguer CON
Ataca com contra-argumentos e edge cases.

▮ ORACLE — Judge
Avalia 4 critérios e emite veredicto JSON.
""", unsafe_allow_html=True) st.divider() st.markdown("""
gpt-4o-mini · 3 system prompts
orquestração manual · CPU-only
""", unsafe_allow_html=True) st.divider() if st.button("🗑️ Limpar arena", use_container_width=True): st.session_state.debates = [] st.rerun() # ── HEADER ──────────────────────────────────────────────────── st.markdown("""
⚔ DEBATE ARENA ⚔
ATLAS vs NEXUS · Julgado por ORACLE · Sistema Multi-Agente
""", unsafe_allow_html=True) # ── NAMEPLATES ──────────────────────────────────────────────── st.markdown("""
ATLAS
◈ Arguer PRO · Defende
ORACLE
◆ Judge
NEXUS
Ataca · Arguer CON ◈
""", unsafe_allow_html=True) # ── TÓPICOS SUGERIDOS ───────────────────────────────────────── TOPICS = [ "RAG é superior a Fine-tuning para domínios especializados", "LLMs vão substituir engenheiros de software até 2030", "Graph Neural Networks superam Transformers em dados relacionais", "Modelos open-source já rivalizam com GPT-4 em tarefas práticas", "Prompting é mais importante que arquitetura do modelo", "Agentes autônomos de IA são prontos para produção em 2025", ] if not st.session_state.debates: st.markdown("""
◈ Escolha um tema ou digite o seu
""", unsafe_allow_html=True) cols = st.columns(3) for i, topic in enumerate(TOPICS): with cols[i % 3]: if st.button(topic, key=f"t{i}", use_container_width=True): st.session_state["pending_topic"] = topic st.rerun() # ── HISTÓRICO DE DEBATES ────────────────────────────────────── for debate in st.session_state.debates: topic = debate["topic"] st.markdown(f"""
◆ TEMA: {topic} ◆
""", unsafe_allow_html=True) for ev in debate.get("events", []): if ev.get("type") == "status": st.markdown(f'
⟳ {ev["msg"]}
', unsafe_allow_html=True) elif ev.get("agent") == "ATLAS": st.markdown(f"""
ATLAS T{ev['turn']}
{ev['content']}
""", unsafe_allow_html=True) elif ev.get("agent") == "NEXUS": st.markdown(f"""
T{ev['turn']} NEXUS
{ev['content']}
""", unsafe_allow_html=True) # Veredicto if debate.get("verdict"): v = debate["verdict"] winner = v.get("vencedor", "EMPATE") pa = v.get("placar_atlas", 0) pn = v.get("placar_nexus", 0) winner_class = { "ATLAS": "winner-atlas", "NEXUS": "winner-nexus", "EMPATE": "winner-empate" }.get(winner, "winner-empate") crit = v.get("criterios", {}) crit_items = "" crit_labels = { "qualidade_argumentos": "Qualidade dos Argumentos", "uso_de_evidencias": "Uso de Evidências", "coerencia_logica": "Coerência Lógica", "poder_de_refutacao": "Poder de Refutação", } for key, label in crit_labels.items(): ca = crit.get(key, {}).get("atlas", 0) cn = crit.get(key, {}).get("nexus", 0) crit_items += f"""
{label}
ATLAS {ca}/10 NEXUS {cn}/10
""" st.markdown(f"""
◆ VEREDICTO DE ORACLE ◆
{winner} VENCE
ATLAS — {pa}/10
NEXUS — {pn}/10
{crit_items}
ANÁLISE ATLAS
{v.get('analise_atlas','')}
ANÁLISE NEXUS
{v.get('analise_nexus','')}
◈ PONTO DECISIVO: {v.get('ponto_decisivo','')}
💡 {v.get('licao','')}
""", unsafe_allow_html=True) st.divider() # ── INPUT ───────────────────────────────────────────────────── pending = st.session_state.pop("pending_topic", None) topic = st.chat_input("Digite o tema do debate...") or pending if topic: if not get_key(): st.warning("Configure a OpenAI API Key na sidebar.") st.stop() from agents import DebateEngine debate_record = {"topic": topic, "events": [], "verdict": None} st.session_state.debates.append(debate_record) # Header do debate topic_ph = st.empty() topic_ph.markdown(f"""
◆ TEMA: {topic} ◆
""", unsafe_allow_html=True) engine = DebateEngine(get_key()) placeholders = [] for event in engine.run_debate(topic, n_rounds=n_rounds): if event.get("type") == "status": ph = st.empty() ph.markdown(f'
⟳ {event["msg"]}
', unsafe_allow_html=True) debate_record["events"].append(event) elif event.get("type") == "verdict": verdict = event["data"] debate_record["verdict"] = verdict v = verdict winner = v.get("vencedor", "EMPATE") pa = v.get("placar_atlas", 0) pn = v.get("placar_nexus", 0) winner_class = {"ATLAS": "winner-atlas", "NEXUS": "winner-nexus", "EMPATE": "winner-empate"}.get(winner, "winner-empate") crit = v.get("criterios", {}) crit_labels = { "qualidade_argumentos": "Qualidade dos Argumentos", "uso_de_evidencias": "Uso de Evidências", "coerencia_logica": "Coerência Lógica", "poder_de_refutacao": "Poder de Refutação", } crit_items = "" for key, label in crit_labels.items(): ca = crit.get(key, {}).get("atlas", 0) cn = crit.get(key, {}).get("nexus", 0) crit_items += f"""
{label}
ATLAS {ca}/10 NEXUS {cn}/10
""" st.markdown(f"""
◆ VEREDICTO DE ORACLE ◆
{winner} VENCE
ATLAS — {pa}/10
NEXUS — {pn}/10
{crit_items}
ANÁLISE ATLAS
{v.get('analise_atlas','')}
ANÁLISE NEXUS
{v.get('analise_nexus','')}
◈ PONTO DECISIVO: {v.get('ponto_decisivo','')}
💡 {v.get('licao','')}
""", unsafe_allow_html=True) else: # Speech bubble ao vivo agent = event.get("agent", "") content = event.get("content", "") turn = event.get("turn", 0) debate_record["events"].append(event) if agent == "ATLAS": st.markdown(f"""
ATLAS T{turn}
{content}
""", unsafe_allow_html=True) elif agent == "NEXUS": st.markdown(f"""
T{turn} NEXUS
{content}
""", unsafe_allow_html=True)