#!/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, )