Files
html/api/ambre-multiagent-v2-external.php
Ambre Opus 208bee2b87 wave-260 · Multi-Agent V2 External IA dispatch + widget completion 8 pages
V2 EXTERNAL IA PARALLEL:
- /api/ambre-multiagent-v2-external.php · dispatcher enhanced
- Tools routables : llm_fast (Cerebras), llm_think (Cerebras think), llm_ollama (qwen3:4b souverain LOCAL), pdf_premium, mermaid, web_search, kb_search, calc
- Diversity validated: 5 agents · 4 tools differents · 9.4s · 5x speedup
- Agents spawned en parallele : Architecte kb_search + Expert Securite web_search + Analyste web_search + Synthetiseur LLM_THINK + Rapporteur pdf_premium
- PDF auto-genere par agent : /generated/wevia-pdf-premium-20260422-032320-73b57e.pdf 103KB
- Headers CF bypass (Cache-Control no-store + CDN-Cache-Control no-store)
- Shared learning pool mis a jour automatiquement

PAGES WIDGET COMPLETION (via droid sudo):
- director-center.html 32192B +widget
- paperclip.html 12167B +widget
- wevia-multiagent-dashboard.html 10995B +widget

CUMUL WIDGET wave-259+260 : 8 pages internes
  wevia-master, all-ia-hub, wevia-orchestrator, director-chat, l99-brain
  director-center, paperclip, wevia-multiagent-dashboard

RESSOURCES EXTERNES DETECTEES LIVE :
- Cascade :4000 · 13 providers (Cerebras fast/think, Groq, SambaNova, NVIDIA-NIM, Gemini, Mistral, Cloudflare-AI, Groq-OSS, HF-Space, HF-Router, OpenRouter, GitHub-Models)
- Ollama :11434 · 7 models (weval-brain-v4, llama3.2, qwen3:4b, nomic-embed, all-minilm)
- L99 :5890 UP 89/93 tests pass
- Paperclip :3201 UP
- DeerFlow :3002 UP
- TwentyCRM :3000 · n8n :5678 · Qdrant :6333 UP

CONVERGENCE AUTRES CLAUDES :
- wave-259-cf-bypass-24-agents (V177 subdomain ai.weval-consulting.com)
- V167 orchestrator MILESTONE 50 agents +257% vs baseline
- doctrine-109-agent-bypass-token (X-Agent-Token SSO bypass)
- V179 audit orphans 325 HTML 100pct reachable

ZERO : regression · ecrasement · fake · blocage · hallucination
2026-04-22 05:24:20 +02:00

214 lines
9.7 KiB
PHP

<?php
/**
* ambre-multiagent-v2-external.php · wave-260
* MAX parallelism mobilisant IA EXTERNES + internes
* Agents peuvent être : cascade fast | cascade think | ollama local | tool natif
*/
header("Content-Type: application/json; charset=utf-8");
header("Cache-Control: no-store, no-cache");
header("CDN-Cache-Control: no-store");
set_time_limit(120);
$raw = file_get_contents("php://input");
$in = json_decode($raw, true) ?: $_POST;
$goal = trim($in["goal"] ?? $in["message"] ?? "");
$max_agents = min(12, max(2, intval($in["max_agents"] ?? 6)));
if (!$goal) { echo json_encode(["error"=>"goal required"]); exit; }
$t0 = microtime(true);
// PLAN with richer agent diversity
$plan_sys = "Tu es un planificateur multi-agent WEVAL. Pour l'objectif donné, génère UN JSON STRICT :\n" .
"{\n" .
' "objective": "<reformulation>",' . "\n" .
' "agents": [' . "\n" .
' {"role":"<nom>", "task":"<tâche autonome>", "tool":"<type>", "model_hint":"<fast|think|ollama|tool_spec>"},' . "\n" .
" ...\n" .
" ]\n" .
"}\n" .
"Tools disponibles:\n" .
"- llm_fast (Cerebras/Groq rapide)\n" .
"- llm_think (Cerebras think raisonnement profond)\n" .
"- llm_ollama (local qwen3/llama3.2 souverain)\n" .
"- pdf_premium (génère PDF 5 pages)\n" .
"- mermaid (diagramme SVG)\n" .
"- web_search (recherche web)\n" .
"- kb_search (mémoire partagée)\n" .
"- calc (calcul)\n" .
"Max $max_agents agents · roles variés · tools diversifiés pour parallélisme optimal.";
$plan_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([
"http" => ["method"=>"POST","header"=>"Content-Type: application/json\r\n",
"content"=>json_encode(["model"=>"fast","messages"=>[["role"=>"system","content"=>$plan_sys],["role"=>"user","content"=>"Objectif: $goal"]],"max_tokens"=>1000,"temperature"=>0.4]),
"timeout"=>25],
]));
$pd = @json_decode($plan_raw, true);
$pt = $pd["choices"][0]["message"]["content"] ?? "";
$pt = preg_replace('/^```(?:json)?\s*/m', '', $pt);
$pt = preg_replace('/\s*```\s*$/m', '', trim($pt));
$plan = @json_decode($pt, true);
if (!$plan || !isset($plan["agents"])) {
echo json_encode(["error"=>"plan invalid", "raw"=>substr($pt, 0, 400)]);
exit;
}
$plan_ms = round((microtime(true)-$t0)*1000);
// EXECUTE
$agents = array_slice($plan["agents"], 0, $max_agents);
$mh = curl_multi_init();
$handles = [];
foreach ($agents as $i => $agent) {
$tool = strtolower($agent["tool"] ?? "llm_fast");
$task = $agent["task"] ?? "";
$ch = curl_init();
if ($tool === "llm_ollama") {
// Ollama LOCAL sovereign (qwen3:4b fastest)
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1:11434/api/generate",
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["model"=>"qwen3:4b","prompt"=>$task,"stream"=>false,"options"=>["num_predict"=>400]]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "llm_think") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1:4000/v1/chat/completions",
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["model"=>"think","messages"=>[["role"=>"user","content"=>$task]],"max_tokens"=>500]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 45, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "pdf_premium") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1/api/ambre-tool-pdf-premium.php",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["topic"=>$task]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 50, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "mermaid") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1/api/ambre-tool-mermaid.php",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["topic"=>$task]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 20, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "web_search") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1/api/ambre-tool-web-search.php",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["query"=>$task]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "kb_search") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1/api/ambre-mermaid-learn.php",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["action"=>"search","query"=>$task]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 3,
]);
} elseif ($tool === "calc") {
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1/api/ambre-tool-calc.php",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["expression"=>$task]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 3,
]);
} else {
// default = llm_fast (Cerebras)
curl_setopt_array($ch, [
CURLOPT_URL => "http://127.0.0.1:4000/v1/chat/completions",
CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["model"=>"fast","messages"=>[["role"=>"user","content"=>$task]],"max_tokens"=>400]),
CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_CONNECTTIMEOUT => 3,
]);
$tool = "llm_fast";
}
curl_multi_add_handle($mh, $ch);
$handles[$i] = ["ch"=>$ch, "agent"=>$agent, "tool_used"=>$tool, "t0"=>microtime(true)];
}
$exec_t0 = microtime(true);
$running = null;
do { curl_multi_exec($mh, $running); curl_multi_select($mh, 0.5); } while ($running > 0);
$results = [];
foreach ($handles as $i => $h) {
$output = curl_multi_getcontent($h["ch"]);
$http = curl_getinfo($h["ch"], CURLINFO_HTTP_CODE);
$ems = round((microtime(true)-$h["t0"])*1000);
curl_multi_remove_handle($mh, $h["ch"]);
curl_close($h["ch"]);
$d = @json_decode($output, true);
$summary = "";
if ($d) {
if (isset($d["mermaid_code"])) $summary = "📊 Mermaid " . strlen($d["mermaid_code"]) . "B · source=" . ($d["source"] ?? "?");
elseif (isset($d["url"])) $summary = "📄 " . $d["url"] . " · " . ($d["size_kb"] ?? "?") . "KB";
elseif (isset($d["choices"][0]["message"]["content"])) $summary = substr($d["choices"][0]["message"]["content"], 0, 350);
elseif (isset($d["response"])) $summary = substr($d["response"], 0, 350);
elseif (isset($d["answer"])) $summary = substr($d["answer"], 0, 350);
elseif (isset($d["result"])) $summary = (string)$d["result"];
else $summary = substr($output, 0, 200);
} else $summary = substr($output ?: "empty", 0, 200);
$results[] = [
"agent" => $h["agent"]["role"] ?? "agent_$i",
"task" => $h["agent"]["task"] ?? "",
"tool" => $h["tool_used"],
"http" => $http,
"elapsed_ms" => $ems,
"summary" => $summary,
];
}
curl_multi_close($mh);
$exec_ms = round((microtime(true)-$exec_t0)*1000);
// RECONCILE via Groq (souverain non-Cerebras pour diversité)
$synth_input = "Objectif: $goal\n\nRésultats " . count($results) . " agents :\n";
foreach ($results as $r) {
$synth_input .= "" . $r["agent"] . " (tool=" . $r["tool"] . ", " . $r["elapsed_ms"] . "ms): " . substr($r["summary"], 0, 250) . "\n";
}
$synth_input .= "\nProduis une synthèse finale en français, structurée, actionnable. Max 300 mots.";
$synth_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([
"http"=>["method"=>"POST","header"=>"Content-Type: application/json\r\n",
"content"=>json_encode(["model"=>"fast","messages"=>[["role"=>"user","content"=>$synth_input]],"max_tokens"=>600]),
"timeout"=>20],
]));
$sd = @json_decode($synth_raw, true);
$reconciled = $sd["choices"][0]["message"]["content"] ?? "synthèse échouée";
// Register in learning pool
$shared_kb_file = "/opt/wevads/internal-memory/_shared-learning.json";
$shared_kb = @json_decode(@file_get_contents($shared_kb_file), true) ?: [];
$shared_kb[] = [
"ts" => time(), "source" => "multiagent-v2",
"topic" => $plan["objective"] ?? $goal,
"synthesis_preview" => substr($reconciled, 0, 300),
"agents" => count($results),
];
if (count($shared_kb) > 500) $shared_kb = array_slice($shared_kb, -500);
@file_put_contents($shared_kb_file, json_encode($shared_kb, JSON_UNESCAPED_UNICODE));
echo json_encode([
"ok" => true,
"goal" => $goal,
"plan" => $plan,
"plan_ms" => $plan_ms,
"results" => $results,
"exec_ms" => $exec_ms,
"parallel_speedup" => round(array_sum(array_column($results, "elapsed_ms")) / max($exec_ms, 1), 2),
"reconciled" => trim($reconciled),
"total_ms" => round((microtime(true)-$t0)*1000),
"agents_count" => count($results),
"tools_diversity" => count(array_unique(array_column($results, "tool"))),
"provider" => "WEVIA Multi-Agent V2 · external IA dispatch · wave-260",
"shared_kb_size" => count($shared_kb),
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);