Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| app.py — VORTEX OMEGA v2.0 | |
| Kernel autonome VORTEX v3.0 + écosystème d'agents spécialisés VORTEX GOD. | |
| Onglets : | |
| 1 ⚙️ Bac à sable — exécution Python sécurisée | |
| 2 📊 Santé système — CPU / mémoire / énergie | |
| 3 🧠 Mémoire — 6 tiers hiérarchiques SQLite | |
| 4 🕸️ Graphe causal — NetworkX + SQLite (legacy) | |
| 5 🧬 Méta-méta-optim. — benchmark auto + rollback | |
| 6 🔄 Transfert — analogies mots-clés | |
| 7 🔬 Boucle recherche — hypothèse → code → score | |
| 8 📜 Preuves — proof system JSON | |
| 9 🏛️ Agents CEO/CFO — hiérarchie exécutive | |
| 10 🌐 Recherche web — SearXNG / DuckDuckGo + arXiv | |
| 11 🤖 Agents spécialisés — Planner/Researcher/Engineer/Critic/Scientist/Optimizer | |
| 12 🧩 Knowledge Graph — graphe sémantique persistant | |
| 13 📚 RAG — ChromaDB / FAISS + ingestion arXiv | |
| 14 🔀 Évolution — populations, mutation, crossover, sélection | |
| 15 🦾 Supervisor — orchestration multi-agents + vote | |
| 16 📈 Benchmark continu — scores en temps réel + détection régression | |
| 17 🔁 Auto-amélioration — cycle mine → train → eval → deploy autonome | |
| """ | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Imports stdlib | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| import asyncio | |
| import logging | |
| import os | |
| import sys | |
| import threading | |
| import time | |
| from pathlib import Path | |
| import nest_asyncio | |
| nest_asyncio.apply() | |
| try: | |
| asyncio.get_running_loop() | |
| except RuntimeError: | |
| asyncio.set_event_loop(asyncio.new_event_loop()) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Chemins & répertoires | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| DATA_DIR = Path(os.environ.get("DATA_DIR", "/app/data")) | |
| DATA_DIR.mkdir(parents=True, exist_ok=True) | |
| sys.path.insert(0, str(Path(__file__).parent)) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Imports VORTEX core (v3.0 inchangés) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| from core.kernel import KERNEL | |
| from core.memory import HierarchicalMemory, MemoryTier | |
| from core.causal_graph import CausalGraph | |
| from core.meta_meta_optimizer import MetaMetaOptimizer | |
| from core.transfer_engine import TransferEngine | |
| from core.research_loop import ResearchLoop | |
| from core.proof_system import ProofSystem | |
| from core.optimizer import FellowOptimizer | |
| # execute_safe fourni par ultra_sandbox (voir import ci-dessous) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Imports VORTEX GOD (nouvelles briques) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| from agents.cognitive_engine import MultiLLMEngine | |
| from agents.hierarchy import ceo, cfo | |
| from agents.specialized import ( | |
| PlannerAgent, ResearcherAgent, EngineerAgent, | |
| CriticAgent, ScientistAgent, OptimizerAgent, | |
| AgentTask, | |
| ) | |
| from core.knowledge_graph import KnowledgeGraph | |
| from core.rag_engine import RAGEngine | |
| from core.evolution_engine import EvolutionEngine, EvoConfig | |
| from utils.web_search import web_search, search_arxiv | |
| from agents.specialized.supervisor import SupervisorAgent | |
| from core.bandit_optimizer import BanditOptimizer | |
| from core.self_programmer import SelfProgrammer | |
| from memory.mem_manager import MemoryManager | |
| from federation.federation import FederationManager | |
| from sandbox.ultra_sandbox import execute_safe as execute_safe_ultra, sandbox_info | |
| from core.self_improvement import SelfImprovementEngine | |
| from benchmark.continuous_benchmark import ContinuousBenchmark | |
| import gradio as gr | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Logging | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger("vortex.app") | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Instanciation — VORTEX core | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| memory = HierarchicalMemory(db_path=str(DATA_DIR / "vortex_memory.db")) | |
| causal_graph = CausalGraph() | |
| transfer_engine = TransferEngine() | |
| proof_system = ProofSystem() | |
| llm_engine = MultiLLMEngine(memory) | |
| research_loop = ResearchLoop(llm_engine, memory, execute_safe_ultra) | |
| meta_optimizer = MetaMetaOptimizer( | |
| KERNEL, llm_engine, | |
| current_optimizer_path=str(Path(__file__).parent / "core" / "optimizer.py"), | |
| ) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Instanciation — VORTEX GOD | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| knowledge_graph_god = KnowledgeGraph() | |
| rag_engine = RAGEngine() | |
| planner_agent = PlannerAgent(llm_engine, memory, knowledge_graph_god) | |
| researcher_agent = ResearcherAgent( | |
| llm_engine, memory, knowledge_graph_god, | |
| web_search_fn=web_search, | |
| ) | |
| engineer_agent = EngineerAgent(llm_engine, memory, knowledge_graph_god, kernel=KERNEL) | |
| critic_agent = CriticAgent(llm_engine, memory, knowledge_graph_god) | |
| scientist_agent = ScientistAgent( | |
| llm_engine, memory, knowledge_graph_god, | |
| researcher=researcher_agent, | |
| engineer=engineer_agent, | |
| ) | |
| optimizer_agent = OptimizerAgent(llm_engine, memory, knowledge_graph_god) | |
| # ── Supervisor ────────────────────────────────────────────────────────────── | |
| supervisor_agent = SupervisorAgent( | |
| llm_engine, memory, knowledge_graph_god, | |
| agent_registry = { | |
| "planner": planner_agent, | |
| "researcher": researcher_agent, | |
| "engineer": engineer_agent, | |
| "critic": critic_agent, | |
| "scientist": scientist_agent, | |
| "optimizer": optimizer_agent, | |
| }, | |
| n_voters = 2, # réduit à 2 pour économiser les tokens | |
| use_voting = True, | |
| ) | |
| # ── 5 Leviers OMEGA ──────────────────────────────────────────────────────── | |
| bandit_optimizer = BanditOptimizer(n_arms=10) | |
| self_programmer = SelfProgrammer(engineer_agent) | |
| memory_omega = MemoryManager(llm_engine=llm_engine) | |
| federation_mgr = FederationManager( | |
| local_agents = _AGENT_MAP, | |
| memory_manager = memory_omega, | |
| knowledge_graph = knowledge_graph_god, | |
| ) | |
| # ── Benchmark continu ──────────────────────────────────────────────────────── | |
| benchmark_engine = ContinuousBenchmark(llm_engine) | |
| # ── Auto-amélioration ──────────────────────────────────────────────────────── | |
| self_improve_engine = SelfImprovementEngine( | |
| db_path = str(DATA_DIR / "vortex_memory.db"), | |
| llm_engine = llm_engine, | |
| ) | |
| _AGENT_MAP = { | |
| "planner": planner_agent, | |
| "researcher": researcher_agent, | |
| "engineer": engineer_agent, | |
| "critic": critic_agent, | |
| "scientist": scientist_agent, | |
| "optimizer": optimizer_agent, | |
| "supervisor": supervisor_agent, | |
| } | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Boucle de recherche automatique (thread daemon) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| async def _auto_research_loop(): | |
| while True: | |
| await asyncio.sleep(3600) | |
| try: | |
| result = await research_loop.run_one_cycle("optimisation de code") | |
| logger.info(f"[AUTO] Score: {result['score']}") | |
| except Exception as exc: | |
| logger.error(f"[AUTO] {exc}") | |
| def _run_in_new_loop(coro_fn): | |
| """Exécute une coroutine dans une nouvelle boucle asyncio dédiée (thread daemon).""" | |
| import asyncio as _asyncio | |
| loop = _asyncio.new_event_loop() | |
| _asyncio.set_event_loop(loop) | |
| try: | |
| loop.run_until_complete(coro_fn()) | |
| except Exception as exc: | |
| logger.error(f"[Thread daemon] {exc}") | |
| finally: | |
| loop.close() | |
| for _coro in [_auto_research_loop, benchmark_engine.run_forever, | |
| federation_mgr.start, self_improve_engine.run_forever]: | |
| threading.Thread(target=_run_in_new_loop, args=(_coro,), daemon=True).start() | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Helpers UI | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| def run_code(code: str, timeout: float = 30.0): | |
| result = KERNEL.run_code(code, timeout=timeout) | |
| memory.ingest( | |
| f"Code: {code[:200]}", | |
| MemoryTier.WORKING, "user", | |
| importance = 0.5 if result.get("success") else 0.1, | |
| confidence = 0.8 if result.get("success") else 0.3, | |
| ) | |
| causal_graph.add_node(f"exec_{int(time.time())}", "execution", {"code": code[:100]}) | |
| return result.get("result", result.get("error", "No output")) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Interface Gradio | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| with gr.Blocks(title="VORTEX OMEGA v2.0", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| "# 🧠 VORTEX GOD v1.0\n" | |
| "Kernel autonome · Multi-agents · RAG · Évolution · Recherche web" | |
| ) | |
| with gr.Tabs(): | |
| # ══════════════════════════════════════════════════════════════ | |
| # 1 — Bac à sable | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("⚙️ Bac à sable"): | |
| code_input = gr.Code(label="Python", language="python", lines=15) | |
| run_btn = gr.Button("▶ Exécuter", variant="primary") | |
| output = gr.Textbox(label="Sortie", lines=15) | |
| run_btn.click(fn=run_code, inputs=code_input, outputs=output) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 2 — Santé système | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("📊 Santé système"): | |
| health_btn = gr.Button("🔄 Actualiser") | |
| health_out = gr.JSON() | |
| health_btn.click( | |
| lambda: { | |
| "health": KERNEL.get_health(), | |
| "sandbox": sandbox_info(), | |
| "bandit": bandit_optimizer.convergence_report(), | |
| "federation": federation_mgr.stats(), | |
| "config": KERNEL.get_degraded_mode_config(), | |
| "llm": llm_engine.backend_info(), | |
| "rag": rag_engine.stats(), | |
| "kg": knowledge_graph_god.stats(), | |
| }, | |
| outputs=health_out, | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 3 — Mémoire hiérarchique | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🧠 Mémoire"): | |
| tier = gr.Dropdown([t.value for t in MemoryTier], label="Tier", value="semantic") | |
| query = gr.Textbox(label="Recherche") | |
| top = gr.Slider(1, 20, 5, label="Top K") | |
| search = gr.Button("🔍 Rechercher") | |
| results= gr.JSON() | |
| search.click( | |
| lambda q, t, k: [e.__dict__ for e in memory.retrieve(q, MemoryTier(t), k)], | |
| [query, tier, top], results, | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 4 — Graphe causal (legacy) | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🕸️ Graphe causal"): | |
| with gr.Row(): | |
| src = gr.Textbox(label="Source") | |
| tgt = gr.Textbox(label="Cible") | |
| rel = gr.Textbox(label="Relation") | |
| wt = gr.Number(value=1.0, label="Poids") | |
| add_btn = gr.Button("➕ Ajouter arête") | |
| status = gr.Textbox() | |
| add_btn.click( | |
| lambda s, t, r, w: causal_graph.add_edge(s, t, r, w) and f"{s}→{t}", | |
| [src, tgt, rel, wt], status, | |
| ) | |
| with gr.Row(): | |
| from_node = gr.Textbox(label="Depuis") | |
| to_node = gr.Textbox(label="Vers") | |
| depth = gr.Slider(1, 5, 3, label="Profondeur") | |
| find_btn = gr.Button("🔎 Chemins") | |
| paths = gr.JSON() | |
| find_btn.click( | |
| lambda f, t, d: causal_graph.causal_query(f, t or None, int(d)), | |
| [from_node, to_node, depth], paths, | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 5 — Méta-méta-optimisation | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🧬 Méta-méta-optim."): | |
| measure = gr.Button("📐 Mesurer & améliorer") | |
| meta_status = gr.JSON() | |
| async def measure_async(): | |
| await meta_optimizer.monitor_and_improve() | |
| return meta_optimizer.get_status() | |
| measure.click(fn=measure_async, outputs=meta_status) | |
| rollback_btn = gr.Button("↩ Rollback") | |
| rollback_out = gr.Textbox() | |
| rollback_btn.click( | |
| lambda: "✅ OK" if meta_optimizer.rollback() else "❌ Échec", | |
| outputs=rollback_out, | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 6 — Transfert analogique | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🔄 Transfert"): | |
| prob = gr.Textbox(label="Problème") | |
| topk = gr.Slider(1, 10, 3) | |
| ana_btn = gr.Button("🔎 Analogies") | |
| ana_out = gr.JSON() | |
| ana_btn.click( | |
| lambda p, k: transfer_engine.find_analogy(p, int(k)), | |
| [prob, topk], ana_out, | |
| ) | |
| with gr.Row(): | |
| exp_prob = gr.Textbox(label="Expérience — problème") | |
| exp_sol = gr.Textbox(label="Expérience — solution") | |
| add_exp = gr.Button("➕ Ajouter expérience") | |
| add_exp_out = gr.Textbox() | |
| add_exp.click( | |
| lambda p, s: transfer_engine.add_experience(p, s) or "✅ Ajouté", | |
| [exp_prob, exp_sol], add_exp_out, | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 7 — Boucle de recherche | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🔬 Boucle recherche"): | |
| domain = gr.Textbox(label="Domaine", value="optimisation de code") | |
| run_res = gr.Button("▶ Lancer un cycle") | |
| res_out = gr.JSON() | |
| async def do_res(domain): | |
| return await research_loop.run_one_cycle(domain) | |
| run_res.click(fn=do_res, inputs=domain, outputs=res_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 8 — Preuves | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("📜 Preuves"): | |
| refresh = gr.Button("🔄 Actualiser") | |
| proofs_out = gr.JSON() | |
| refresh.click(lambda: proof_system.proofs, outputs=proofs_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 9 — Agents exécutifs (CEO / CFO) | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🏛️ Agents exécutifs"): | |
| task = gr.Textbox(label="Tâche CEO", value="code_gen") | |
| ask = gr.Button("🎯 Consulter CEO") | |
| decision = gr.JSON() | |
| async def get_ceo(t): | |
| return await ceo.execute_task({"strategy": t}) | |
| ask.click(fn=get_ceo, inputs=task, outputs=decision) | |
| gr.Markdown(f"**Budget CFO restant** : {cfo.budget.limit - cfo.budget.spent:.2f}") | |
| # ══════════════════════════════════════════════════════════════ | |
| # 10 — Recherche web ★ GOD | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🌐 Recherche web"): | |
| gr.Markdown("### Recherche web unifiée (SearXNG → DuckDuckGo → arXiv)") | |
| with gr.Row(): | |
| ws_query = gr.Textbox(label="Requête", scale=3, | |
| placeholder="ex: Qwen3 8B GGUF benchmark 2024") | |
| with gr.Column(scale=1): | |
| ws_arxiv = gr.Checkbox(label="Mode arXiv", value=False) | |
| ws_fetch = gr.Checkbox(label="Extraire contenu pages", value=False) | |
| ws_btn = gr.Button("🔍 Rechercher", variant="primary") | |
| ws_meta = gr.JSON(label="Métadonnées") | |
| ws_out = gr.Markdown() | |
| async def do_web_search(q, arxiv_mode, fetch): | |
| if not q.strip(): | |
| return {}, "⚠️ Entrez une requête." | |
| if arxiv_mode: | |
| resp = await search_arxiv(q, max_results=6) | |
| else: | |
| resp = await web_search(q, max_results=6, fetch_pages=fetch) | |
| meta = { | |
| "source": resp.source, | |
| "results": len(resp.results), | |
| "latency_s": round(resp.latency, 2), | |
| } | |
| return meta, resp.as_context(max_chars=6000) | |
| ws_btn.click( | |
| fn=do_web_search, | |
| inputs=[ws_query, ws_arxiv, ws_fetch], | |
| outputs=[ws_meta, ws_out], | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 11 — Agents spécialisés ★ GOD | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🤖 Agents spécialisés"): | |
| gr.Markdown("### Pipeline multi-agents VORTEX GOD") | |
| with gr.Row(): | |
| agent_role = gr.Dropdown( | |
| list(_AGENT_MAP.keys()), | |
| value="planner", label="Agent", scale=1, | |
| ) | |
| agent_tokens = gr.Slider(128, 1024, 512, label="Max tokens", scale=1) | |
| agent_temp = gr.Slider(0.01, 1.0, 0.3, step=0.01, label="Température", scale=1) | |
| agent_task_in = gr.Textbox(label="Tâche / question", lines=4) | |
| agent_ctx_in = gr.Textbox(label="Contexte additionnel (optionnel)", lines=3) | |
| agent_btn = gr.Button("▶ Exécuter", variant="primary") | |
| with gr.Row(): | |
| agent_out = gr.Markdown(label="Résultat") | |
| agent_meta = gr.JSON(label="Métadonnées") | |
| async def run_agent(role, task_desc, ctx, max_tok, temp): | |
| agent = _AGENT_MAP[role] | |
| task = AgentTask( | |
| description = task_desc, | |
| context = ctx, | |
| max_tokens = int(max_tok), | |
| temperature = float(temp), | |
| ) | |
| result = await agent.run(task) | |
| meta = { | |
| "agent": result.agent, | |
| "score": result.score, | |
| "latency_s": result.latency, | |
| "tokens": result.tokens, | |
| "error": result.error, | |
| } | |
| return result.content, meta | |
| agent_btn.click( | |
| fn=run_agent, | |
| inputs=[agent_role, agent_task_in, agent_ctx_in, agent_tokens, agent_temp], | |
| outputs=[agent_out, agent_meta], | |
| ) | |
| # ── Pipeline en chaîne : Planner → Engineer → Critic ── | |
| gr.Markdown("---\n#### 🔗 Pipeline automatique : Planner → Engineer → Critic") | |
| pipeline_task = gr.Textbox( | |
| label="Tâche complexe", | |
| placeholder="ex: Crée une API REST Flask avec authentification JWT", | |
| lines=2, | |
| ) | |
| pipeline_btn = gr.Button("🚀 Lancer le pipeline", variant="primary") | |
| pipeline_out = gr.JSON(label="Résultats du pipeline") | |
| async def run_pipeline(task_desc): | |
| results = {} | |
| # 1. Planner | |
| plan_task = AgentTask(description=task_desc, max_tokens=700, temperature=0.2) | |
| plan_res = await planner_agent.run(plan_task) | |
| results["planner"] = { | |
| "content": plan_res.content[:600], | |
| "score": plan_res.score, | |
| } | |
| # 2. Engineer (basé sur le plan) | |
| eng_task = AgentTask( | |
| description = task_desc, | |
| context = plan_res.to_context(), | |
| max_tokens = 900, | |
| temperature = 0.2, | |
| ) | |
| eng_res = await engineer_agent.run(eng_task) | |
| results["engineer"] = { | |
| "content": eng_res.content[:800], | |
| "score": eng_res.score, | |
| "passed": eng_res.structured.get("passed") if eng_res.structured else None, | |
| } | |
| # 3. Critic (audite le code produit) | |
| crit_task = AgentTask( | |
| description = eng_res.content[:1200], | |
| context = f"Tâche originale : {task_desc}", | |
| max_tokens = 600, | |
| temperature = 0.1, | |
| ) | |
| crit_res = await critic_agent.run(crit_task) | |
| results["critic"] = crit_res.structured or {"summary": crit_res.content[:400]} | |
| return results | |
| pipeline_btn.click(fn=run_pipeline, inputs=pipeline_task, outputs=pipeline_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 12 — Knowledge Graph ★ GOD | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🧩 Knowledge Graph"): | |
| gr.Markdown("### Graphe de connaissances sémantique persistant") | |
| with gr.Tabs(): | |
| with gr.TabItem("✏️ Ajouter"): | |
| with gr.Row(): | |
| kg_src = gr.Textbox(label="Sujet") | |
| kg_rel = gr.Textbox(label="Relation", value="related_to") | |
| kg_tgt = gr.Textbox(label="Objet") | |
| kg_ev = gr.Textbox(label="Preuve / source", value="manual") | |
| kg_add = gr.Button("➕ Ajouter triplet") | |
| kg_add_out = gr.Textbox(label="Statut") | |
| def add_triplet(s, r, t, e): | |
| kg = knowledge_graph_god | |
| s_id = kg._normalize_id(s) | |
| t_id = kg._normalize_id(t) | |
| kg.add_node(s_id, label=s, node_type="entity") | |
| kg.add_node(t_id, label=t, node_type="entity") | |
| kg.add_edge(s_id, t_id, relation=r, evidence=e) | |
| return f"✅ {s} —[{r}]→ {t}" | |
| kg_add.click(add_triplet, [kg_src, kg_rel, kg_tgt, kg_ev], kg_add_out) | |
| with gr.TabItem("🔍 Rechercher"): | |
| kg_q = gr.Textbox(label="Terme de recherche") | |
| kg_depth = gr.Slider(1, 4, 2, label="Profondeur voisins") | |
| kg_s_btn = gr.Button("🔍 Rechercher") | |
| kg_s_out = gr.JSON() | |
| def search_kg(q, d): | |
| hits = knowledge_graph_god.search_nodes(q, top_k=10) | |
| nbrs = [] | |
| if hits: | |
| nbrs = knowledge_graph_god.neighbors(hits[0]["id"], max_depth=int(d)) | |
| return {"search_results": hits, "neighbors_of_top": nbrs} | |
| kg_s_btn.click(search_kg, [kg_q, kg_depth], kg_s_out) | |
| with gr.TabItem("🗺️ Chemins"): | |
| with gr.Row(): | |
| kg_path_src = gr.Textbox(label="Nœud source (id normalisé)") | |
| kg_path_tgt = gr.Textbox(label="Nœud cible (id normalisé)") | |
| kg_path_cut = gr.Slider(2, 6, 4, label="Cutoff") | |
| kg_path_btn = gr.Button("🗺️ Trouver chemins") | |
| kg_path_out = gr.JSON() | |
| kg_path_btn.click( | |
| lambda s, t, c: knowledge_graph_god.paths(s, t, int(c)), | |
| [kg_path_src, kg_path_tgt, kg_path_cut], kg_path_out, | |
| ) | |
| with gr.TabItem("📊 Stats"): | |
| kg_stats_btn = gr.Button("📊 Actualiser") | |
| kg_stats_out = gr.JSON() | |
| kg_stats_btn.click(lambda: knowledge_graph_god.stats(), outputs=kg_stats_out) | |
| with gr.TabItem("📤 Export"): | |
| kg_export_btn = gr.Button("📤 Export JSON") | |
| kg_export_out = gr.JSON() | |
| kg_export_btn.click(lambda: knowledge_graph_god.to_json(), outputs=kg_export_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 13 — RAG ★ GOD | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("📚 RAG"): | |
| gr.Markdown("### Retrieval-Augmented Generation (ChromaDB / FAISS)") | |
| with gr.Tabs(): | |
| with gr.TabItem("📥 Ingestion"): | |
| rag_text = gr.Textbox(label="Texte à ingérer", lines=6) | |
| rag_source = gr.Textbox(label="Source", value="manual") | |
| rag_arxiv_q = gr.Textbox( | |
| label="Requête arXiv (laisse vide si inutile)", | |
| placeholder="ex: mixture of experts efficient inference", | |
| ) | |
| rag_ing = gr.Button("📥 Ingérer", variant="primary") | |
| rag_ing_out = gr.JSON() | |
| async def do_ingest(text, source, arxiv_q): | |
| out = {} | |
| if text.strip(): | |
| out["text_chunks"] = rag_engine.ingest_text(text, source=source) | |
| if arxiv_q.strip(): | |
| out["arxiv_chunks"] = await rag_engine.ingest_arxiv(arxiv_q, max_papers=8) | |
| out["stats"] = rag_engine.stats() | |
| return out | |
| rag_ing.click( | |
| fn=do_ingest, | |
| inputs=[rag_text, rag_source, rag_arxiv_q], | |
| outputs=rag_ing_out, | |
| ) | |
| with gr.TabItem("🔎 Récupération"): | |
| rag_query = gr.Textbox(label="Requête", lines=2) | |
| rag_topk = gr.Slider(1, 15, 5, label="Top K chunks") | |
| rag_ret = gr.Button("🔎 Récupérer") | |
| rag_ctx = gr.Textbox(label="Contexte LLM", lines=12) | |
| rag_ret.click( | |
| lambda q, k: rag_engine.get_context(q, top_k=int(k)), | |
| [rag_query, rag_topk], rag_ctx, | |
| ) | |
| with gr.TabItem("🔗 RAG + Agent"): | |
| gr.Markdown("Récupère le contexte RAG puis l'injecte dans un agent.") | |
| rag_ag_query = gr.Textbox(label="Requête RAG") | |
| rag_ag_role = gr.Dropdown(list(_AGENT_MAP.keys()), value="researcher", | |
| label="Agent cible") | |
| rag_ag_task = gr.Textbox(label="Tâche de l'agent", lines=3) | |
| rag_ag_btn = gr.Button("▶ Exécuter RAG → Agent", variant="primary") | |
| rag_ag_out = gr.Markdown() | |
| rag_ag_meta = gr.JSON() | |
| async def rag_to_agent(rag_q, role, task_desc): | |
| ctx = rag_engine.get_context(rag_q, top_k=5) | |
| agent = _AGENT_MAP[role] | |
| task = AgentTask(description=task_desc, context=ctx, max_tokens=700) | |
| res = await agent.run(task) | |
| return res.content, {"score": res.score, "latency_s": res.latency} | |
| rag_ag_btn.click( | |
| fn=rag_to_agent, | |
| inputs=[rag_ag_query, rag_ag_role, rag_ag_task], | |
| outputs=[rag_ag_out, rag_ag_meta], | |
| ) | |
| with gr.TabItem("📊 Stats"): | |
| rag_stats_btn = gr.Button("📊 Actualiser") | |
| rag_stats_out = gr.JSON() | |
| rag_stats_btn.click(lambda: rag_engine.stats(), outputs=rag_stats_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 14 — Évolution ★ GOD | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🔀 Évolution"): | |
| gr.Markdown( | |
| "### Évolution génétique de la configuration des agents\n" | |
| "Chaque individu = configuration (température, max_tokens, variant de prompt).\n" | |
| "Fitness = score moyen sur un benchmark de tâches réelles." | |
| ) | |
| with gr.Row(): | |
| evo_pop = gr.Slider(4, 16, 8, step=2, label="Taille population") | |
| evo_gens = gr.Slider(2, 20, 5, step=1, label="Générations max") | |
| evo_tasks = gr.Slider(1, 5, 3, step=1, label="Tâches / individu") | |
| with gr.Row(): | |
| evo_elite = gr.Slider(0.1, 0.5, 0.25, step=0.05, label="Fraction élite") | |
| evo_mut_rate = gr.Slider(0.0, 1.0, 0.30, step=0.05, label="Taux mutation") | |
| evo_cx_rate = gr.Slider(0.0, 1.0, 0.50, step=0.05, label="Taux crossover") | |
| evo_btn = gr.Button("🚀 Lancer l'évolution", variant="primary") | |
| evo_status = gr.Textbox(label="Statut", interactive=False) | |
| with gr.Row(): | |
| evo_curve = gr.JSON(label="Courbe d'évolution (gen → fitness)") | |
| evo_best = gr.JSON(label="Meilleure configuration") | |
| evo_hist = gr.JSON(label="Historique des générations") | |
| async def run_evolution(pop, gens, tasks, elite, mut, cx): | |
| config = EvoConfig( | |
| population_size = int(pop), | |
| max_generations = int(gens), | |
| eval_tasks_per_genome = int(tasks), | |
| elite_fraction = float(elite), | |
| mutation_rate = float(mut), | |
| crossover_rate = float(cx), | |
| ) | |
| engine = EvolutionEngine(llm_engine, config=config) | |
| summary = await engine.run() | |
| status = ( | |
| f"✅ Terminé — génération {summary.generation} — " | |
| f"meilleure fitness : {summary.best_fitness:.4f}" | |
| ) | |
| return status, engine.evolution_curve(), engine.best_config(), engine.stats() | |
| evo_btn.click( | |
| fn=run_evolution, | |
| inputs=[evo_pop, evo_gens, evo_tasks, evo_elite, evo_mut_rate, evo_cx_rate], | |
| outputs=[evo_status, evo_curve, evo_best, evo_hist], | |
| ) | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # Lancement | |
| # ───────────────────────────────────────────────────────────────────────────── | |
| # ══════════════════════════════════════════════════════════════ | |
| # 15 — Supervisor ★ v1.2 | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🦾 Supervisor"): | |
| gr.Markdown( | |
| "### Orchestration multi-agents avec vote\n" | |
| "Le Supervisor planifie, dispatche et synthétise automatiquement." | |
| ) | |
| sv_task = gr.Textbox(label="Tâche complexe", lines=3, | |
| placeholder="ex: Crée et audite une API Flask avec JWT") | |
| sv_steps = gr.Slider(1, 6, 4, label="Étapes max") | |
| sv_voters = gr.Slider(1, 3, 2, step=1, label="Voters par étape critique") | |
| sv_btn = gr.Button("🚀 Orchestrer", variant="primary") | |
| sv_out = gr.Markdown(label="Synthèse finale") | |
| sv_detail = gr.JSON(label="Détail orchestration") | |
| async def run_supervisor(task_desc, max_steps, n_voters): | |
| supervisor_agent._n_voters = int(n_voters) | |
| orch = await supervisor_agent.orchestrate( | |
| task_desc, max_steps=int(max_steps) | |
| ) | |
| return orch.final, orch.to_dict() | |
| sv_btn.click( | |
| fn=run_supervisor, | |
| inputs=[sv_task, sv_steps, sv_voters], | |
| outputs=[sv_out, sv_detail], | |
| ) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 16 — Benchmark continu ★ v1.2 | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("📈 Benchmark"): | |
| gr.Markdown( | |
| "### Benchmark continu — détection de régression\n" | |
| f"Intervalle automatique : toutes les {int(float(os.environ.get('BENCH_INTERVAL_HOURS', 6)))}h" | |
| ) | |
| bench_run_btn = gr.Button("▶ Lancer maintenant", variant="primary") | |
| bench_refresh = gr.Button("🔄 Rafraîchir tableau de bord") | |
| bench_dash = gr.JSON(label="Tableau de bord") | |
| bench_status = gr.Textbox(label="Statut", interactive=False) | |
| async def run_bench_now(): | |
| run = await benchmark_engine.run_once() | |
| status = ( | |
| f"{'⚠️ RÉGRESSION' if run.regression else '✅ OK'} — " | |
| f"Score : {run.global_score:.4f} — " | |
| f"Durée : {run.duration_s:.0f}s" | |
| ) | |
| return benchmark_engine.get_dashboard(), status | |
| bench_run_btn.click(fn=run_bench_now, outputs=[bench_dash, bench_status]) | |
| bench_refresh.click(lambda: benchmark_engine.get_dashboard(), outputs=bench_dash) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 17 — Auto-amélioration ★ v1.2 | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🔁 Auto-amélioration"): | |
| gr.Markdown( | |
| "### Cycle autonome : mine → augment → train → eval → deploy\n" | |
| f"Intervalle automatique : toutes les " | |
| f"{int(float(os.environ.get('IMPROVE_CYCLE_HOURS', 24)))}h" | |
| ) | |
| sie_run_btn = gr.Button("▶ Lancer un cycle maintenant", variant="primary") | |
| sie_history = gr.Button("📋 Historique") | |
| sie_status = gr.Textbox(label="Statut cycle", interactive=False) | |
| sie_report = gr.JSON(label="Rapport complet") | |
| sie_hist_out = gr.JSON(label="Historique des cycles") | |
| async def run_sie_now(): | |
| report = await self_improve_engine.run_cycle() | |
| d = report.to_dict() | |
| status = ( | |
| f"{'✅ Déployé' if d['deployed'] else '↩ Rollback' if d['rolled_back'] else '⏭ Ignoré'} — " | |
| f"Minés: {d['mined']} — Augmentés: {d['augmented']} — " | |
| f"Score: {d['score_before']:.3f} → {d['score_after']:.3f} " | |
| f"(Δ={d['improvement']:+.4f})" | |
| ) | |
| return status, d | |
| def get_sie_history(): | |
| h = self_improve_engine.get_history() | |
| summary = self_improve_engine.last_improvement() | |
| return {"summary": summary, "cycles": h[-10:]} | |
| sie_run_btn.click(fn=run_sie_now, outputs=[sie_status, sie_report]) | |
| sie_history.click(fn=get_sie_history, outputs=sie_hist_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 18 — Bandit multi-bras ★ OMEGA | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🎰 Bandit"): | |
| gr.Markdown( | |
| "### Thompson Sampling — adaptation perpétuelle des agents\n" | |
| "Chaque agent a 10 bras (configurations). Le bandit apprend quelle " | |
| "configuration donne les meilleurs résultats et l'exploite automatiquement." | |
| ) | |
| with gr.Row(): | |
| bandit_agent_sel = gr.Dropdown( | |
| list(_AGENT_MAP.keys()), value="engineer", label="Agent" | |
| ) | |
| bandit_reward_val = gr.Slider(0.0, 1.0, 0.8, label="Récompense manuelle") | |
| bandit_arm_id = gr.Number(value=0, label="ID bras (pour feedback)") | |
| bandit_select_btn = gr.Button("🎯 Sélectionner config optimale") | |
| bandit_reward_btn = gr.Button("📊 Enregistrer récompense") | |
| bandit_dash_btn = gr.Button("🔄 Tableau de bord") | |
| with gr.Row(): | |
| bandit_config = gr.JSON(label="Configuration sélectionnée") | |
| bandit_dash = gr.JSON(label="État des bandits") | |
| def bandit_select(agent_name): | |
| cfg = bandit_optimizer.select(agent_name) | |
| return cfg | |
| def bandit_reward(agent_name, arm_id, reward): | |
| bandit_optimizer.reward(agent_name, int(arm_id), float(reward)) | |
| return bandit_optimizer.dashboard() | |
| bandit_select_btn.click(fn=bandit_select, inputs=bandit_agent_sel, outputs=bandit_config) | |
| bandit_reward_btn.click(fn=bandit_reward, | |
| inputs=[bandit_agent_sel, bandit_arm_id, bandit_reward_val], | |
| outputs=bandit_dash) | |
| bandit_dash_btn.click(lambda: bandit_optimizer.dashboard(), outputs=bandit_dash) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 19 — Auto-programmation ★ OMEGA | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("⚙️ Auto-code"): | |
| gr.Markdown( | |
| "### Auto-programmation évolutive\n" | |
| "Analyse les goulots, génère une version améliorée du module, " | |
| "la teste en subprocess isolé et la déploie à chaud sans redémarrage." | |
| ) | |
| autoprog_module = gr.Dropdown( | |
| ["agents/specialized/planner.py", | |
| "agents/specialized/engineer.py", | |
| "agents/specialized/critic.py", | |
| "utils/web_search.py"], | |
| value="agents/specialized/planner.py", | |
| label="Module à améliorer", | |
| ) | |
| autoprog_score = gr.Slider(0.0, 1.0, 0.4, label="Score benchmark actuel du module") | |
| autoprog_btn = gr.Button("🔧 Patcher ce module", variant="primary") | |
| autoprog_auto = gr.Button("🤖 Auto-patch (tous les goulots)") | |
| autoprog_stats = gr.Button("📋 Stats") | |
| autoprog_status= gr.Textbox(label="Statut", interactive=False) | |
| autoprog_out = gr.JSON(label="Rapport") | |
| async def manual_patch(module_path, score): | |
| scores = { | |
| "planner": score, "engineer": score, | |
| "critic": score, "researcher": score, | |
| } | |
| result = await self_programmer.patch_module(module_path, scores) | |
| d = result.to_dict() | |
| status = ( | |
| f"{'✅ Appliqué' if d['applied'] else '❌ Rejeté'} — " | |
| f"Tests: {'OK' if d['test_passed'] else 'ÉCHOUÉS'} — " | |
| f"Hash: {d['patch_hash']}" | |
| ) | |
| return status, d | |
| async def auto_patch(): | |
| last_bench = benchmark_engine.get_dashboard() | |
| scores = last_bench.get("last_run", {}).get("scores", { | |
| "engineer": 0.5, "planner": 0.5, "critic": 0.5 | |
| }) | |
| results = await self_programmer.auto_patch_bottlenecks(scores, max_patches=2) | |
| summary = [r.to_dict() for r in results] | |
| n_ok = sum(1 for r in results if r.applied) | |
| return f"✅ {n_ok}/{len(results)} modules patchés", summary | |
| autoprog_btn.click(fn=manual_patch, inputs=[autoprog_module, autoprog_score], | |
| outputs=[autoprog_status, autoprog_out]) | |
| autoprog_auto.click(fn=auto_patch, outputs=[autoprog_status, autoprog_out]) | |
| autoprog_stats.click(lambda: self_programmer.get_stats(), outputs=autoprog_out) | |
| # ══════════════════════════════════════════════════════════════ | |
| # 20 — Fédération P2P + Sandbox ★ OMEGA | |
| # ══════════════════════════════════════════════════════════════ | |
| with gr.TabItem("🌍 Fédération"): | |
| gr.Markdown( | |
| "### Fédération P2P + Sandbox de niveau militaire\n" | |
| "Connectez plusieurs instances VORTEX OMEGA pour distribuer les tâches. " | |
| "Chaque instance expose une API REST `/api/*`." | |
| ) | |
| with gr.Tabs(): | |
| with gr.TabItem("🔗 Pairs"): | |
| fed_peer_url = gr.Textbox( | |
| label="URL du pair", | |
| placeholder="https://mon-space.hf.space" | |
| ) | |
| fed_add_btn = gr.Button("➕ Ajouter pair") | |
| fed_stats_btn= gr.Button("📊 Statut fédération") | |
| fed_task = gr.Textbox(label="Tâche fédérée", lines=2) | |
| fed_type = gr.Dropdown(list(_AGENT_MAP.keys()), value="engineer", | |
| label="Type d'agent") | |
| fed_run_btn = gr.Button("▶ Exécuter en fédération", variant="primary") | |
| fed_status = gr.Textbox(label="Statut", interactive=False) | |
| fed_out = gr.JSON() | |
| async def add_peer(url): | |
| ok = await federation_mgr.add_peer(url) | |
| return f"{'✅ Pair ajouté' if ok else '❌ Pair inaccessible'} : {url}", federation_mgr.stats() | |
| async def run_federated(task_desc, task_type): | |
| result = await federation_mgr.run_federated(task_desc, task_type) | |
| return "✅ Tâche exécutée", {"result": result, "stats": federation_mgr.stats()} | |
| fed_add_btn.click(fn=add_peer, inputs=fed_peer_url, | |
| outputs=[fed_status, fed_out]) | |
| fed_stats_btn.click(lambda: federation_mgr.stats(), outputs=fed_out) | |
| fed_run_btn.click(fn=run_federated, inputs=[fed_task, fed_type], | |
| outputs=[fed_status, fed_out]) | |
| with gr.TabItem("🛡️ Sandbox"): | |
| gr.Markdown( | |
| "#### Sandbox ultra-sécurisée\n" | |
| f"Backend actif : **{sandbox_info()['level']}** — {sandbox_info()['backend']}" | |
| ) | |
| sb_code = gr.Code(language="python", label="Code", lines=12) | |
| sb_timeout = gr.Slider(5, 30, 15, label="Timeout (s)") | |
| sb_btn = gr.Button("▶ Exécuter (sandbox ultra)", variant="primary") | |
| sb_out = gr.Textbox(label="Sortie", lines=10) | |
| sb_meta = gr.JSON(label="Métadonnées sandbox") | |
| def run_ultra(code, timeout): | |
| result = execute_safe_ultra(code, timeout=float(timeout)) | |
| output = result.get("result", result.get("error", "")) | |
| return output, result | |
| sb_btn.click(fn=run_ultra, inputs=[sb_code, sb_timeout], | |
| outputs=[sb_out, sb_meta]) | |
| with gr.TabItem("🧠 Mémoire OMEGA"): | |
| gr.Markdown( | |
| "#### Mémoire illimitée avec oubli stratégique\n" | |
| "Couche chaude (RAM) + froide (SQLite) + compression périodique." | |
| ) | |
| mem_query = gr.Textbox(label="Requête de recall") | |
| mem_topk = gr.Slider(1, 20, 5, label="Top K") | |
| mem_recall = gr.Button("🔍 Recall") | |
| mem_forget = gr.Button("🗑️ Oublier les anciens (7j)") | |
| mem_compress=gr.Button("📦 Compresser (14j)") | |
| mem_stats = gr.Button("📊 Stats mémoire") | |
| mem_out = gr.JSON() | |
| def recall_mem(q, k): | |
| mems = memory_omega.retrieve(q, top_k=int(k)) | |
| return [m.to_dict() for m in mems] | |
| async def forget_old(): | |
| n = await memory_omega.strategic_forget(min_age_days=7) | |
| return {"oubliés": n, "stats": memory_omega.stats()} | |
| async def compress_old(): | |
| n = await memory_omega.compress_old_memories(age_days=14) | |
| return {"compressés": n, "stats": memory_omega.stats()} | |
| mem_recall.click(fn=recall_mem, inputs=[mem_query, mem_topk], outputs=mem_out) | |
| mem_forget.click(fn=forget_old, outputs=mem_out) | |
| mem_compress.click(fn=compress_old, outputs=mem_out) | |
| mem_stats.click(lambda: memory_omega.stats(), outputs=mem_out) | |
| if __name__ == "__main__": | |
| if KERNEL.verify_self(): | |
| logger.info("[✓] Noyau valide") | |
| else: | |
| logger.error("[✗] Intégrité altérée — rollback recommandé") | |
| logger.info(f"[LLM] backend : {llm_engine.backend_info()['backend']}") | |
| logger.info(f"[LLM] modèle : {llm_engine.backend_info()['model']}") | |
| logger.info(f"[KG] nœuds : {knowledge_graph_god.stats()['nodes']}") | |
| logger.info(f"[RAG] chunks : {rag_engine.stats()['chunks']}") | |
| logger.info(f"[SIE] historique : {len(self_improve_engine.get_history())} cycles") | |
| logger.info(f"[Bench] historique : {len(benchmark_engine.history)} runs") | |
| logger.info(f"[Sandbox] niveau : {sandbox_info()['level']}") | |
| logger.info(f"[Bandit] bras : {sum(len(b.arms) for b in bandit_optimizer.bandits.values())}") | |
| logger.info(f"[MemOmega] hot : {memory_omega.stats()['hot']}") | |
| demo.queue(default_concurrency_limit=5) | |
| demo.launch( | |
| server_name = "0.0.0.0", | |
| server_port = 7860, | |
| ) |