atypique-api / app.py
RDS777's picture
Create app.py
a1fe33b verified
Raw
History Blame Contribute Delete
55.9 kB
#!/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,
)