Files
html/weval-wiring.html
2026-04-12 22:57:03 +02:00

247 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVAL — Wiring & Comparison Dashboard</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Outfit:wght@300;500;700;900&display=swap" rel="stylesheet">
<style>
:root{--bg:#0a0e17;--bg2:#111827;--bg3:#1e293b;--bd:#1e293b;--fg:#e2e8f0;--fg2:#94a3b8;--fg3:#64748b;--go:#f59e0b;--gn:#22c55e;--rd:#ef4444;--bl:#3b82f6;--vi:#8b5cf6;--cy:#06b6d4;--pk:#ec4899}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--fg);font-family:'Outfit',sans-serif;min-height:100vh}
.top{background:linear-gradient(135deg,#0f172a 0%,#1a1040 50%,#0f2027 100%);padding:24px 32px;border-bottom:1px solid var(--bd)}
.top h1{font-size:28px;font-weight:900;background:linear-gradient(90deg,var(--go),var(--pk),var(--vi));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.top p{color:var(--fg2);font-size:13px;margin-top:4px}
.tabs{display:flex;gap:2px;padding:8px 32px;background:var(--bg2);border-bottom:1px solid var(--bd)}
.tab{padding:8px 20px;cursor:pointer;border-radius:6px 6px 0 0;font-size:12px;font-weight:700;color:var(--fg3);transition:.2s}
.tab:hover{color:var(--fg);background:var(--bg3)}
.tab.on{color:var(--go);background:var(--bg);border:1px solid var(--bd);border-bottom:1px solid var(--bg)}
.main{padding:24px 32px}
.panel{display:none}
.panel.on{display:block}
.kpis{display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin-bottom:24px}
.kpi{background:var(--bg2);border:1px solid var(--bd);border-radius:8px;padding:14px;text-align:center}
.kpi-v{font-size:28px;font-weight:900;font-family:'JetBrains Mono'}
.kpi-l{font-size:10px;color:var(--fg3);margin-top:2px}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;margin-top:16px}
.card{background:var(--bg2);border:1px solid var(--bd);border-radius:8px;padding:14px;transition:.2s}
.card:hover{border-color:var(--vi);transform:translateY(-2px)}
.card-h{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.card-n{font-weight:700;font-size:14px}
.card-n a{color:inherit;text-decoration:none}
.card-n a:hover{color:var(--go)}
.tag{font-size:8px;padding:2px 6px;border-radius:4px;font-weight:700;text-transform:uppercase}
.tag-gn{background:rgba(34,197,94,.2);color:var(--gn)}
.tag-rd{background:rgba(239,68,68,.2);color:var(--rd)}
.tag-bl{background:rgba(59,130,246,.2);color:var(--bl)}
.tag-vi{background:rgba(139,92,246,.2);color:var(--vi)}
.tag-go{background:rgba(245,158,11,.2);color:var(--go)}
.card-row{display:flex;justify-content:space-between;font-size:11px;padding:3px 0;border-bottom:1px solid rgba(255,255,255,.03)}
.card-row:last-child{border:0}
.card-k{color:var(--fg3)}
.card-v{font-family:'JetBrains Mono';font-size:10px}
.bar{height:4px;background:var(--bg3);border-radius:2px;margin-top:6px;overflow:hidden}
.bar-f{height:100%;border-radius:2px;transition:width 1s ease}
table{width:100%;border-collapse:collapse;font-size:11px}
th{text-align:left;padding:8px;color:var(--fg3);border-bottom:1px solid var(--bd);font-size:9px;text-transform:uppercase;position:sticky;top:0;background:var(--bg)}
td{padding:6px 8px;border-bottom:1px solid rgba(255,255,255,.03)}
tr:hover{background:var(--bg3)}
.dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:4px}
.dot-gn{background:var(--gn)}.dot-rd{background:var(--rd)}.dot-go{background:var(--go)}
.sc{font-family:'JetBrains Mono';font-weight:700}
.opus-bar{display:flex;align-items:center;gap:8px;margin:16px 0;padding:12px;background:var(--bg2);border:1px solid var(--bd);border-radius:8px}
.opus-bar .bar{flex:1;height:8px}
.loading{text-align:center;padding:40px;color:var(--fg3)}
@media(max-width:768px){.kpis{grid-template-columns:repeat(3,1fr)}.grid{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="top">
<h1>⚡ WEVAL Wiring & Comparison</h1>
<p>Dashboard dynamique — Benchmark IA × OSS Discovery × Architecture · Données temps réel</p>
</div>
<div class="tabs">
<div class="tab on" onclick="sw(0)">🔌 Wiring Map</div>
<div class="tab" onclick="sw(1)">⚔️ WEVAL vs Opus</div>
<div class="tab" onclick="sw(2)">🧩 OSS Skills</div>
<div class="tab" onclick="sw(3)">📊 Full Comparison</div>
</div>
<div class="main">
<!-- TAB 0: WIRING MAP -->
<div class="panel on" id="p0"><div class="loading">Chargement...</div></div>
<!-- TAB 1: WEVAL vs OPUS -->
<div class="panel" id="p1"><div class="loading">Chargement...</div></div>
<!-- TAB 2: OSS SKILLS -->
<div class="panel" id="p2"><div class="loading">Chargement...</div></div>
<!-- TAB 3: FULL COMPARISON TABLE -->
<div class="panel" id="p3"><div class="loading">Chargement...</div></div>
</div>
<script>
const $ = id => document.getElementById(id);
function sw(n){document.querySelectorAll('.tab').forEach((t,i)=>{t.classList.toggle('on',i===n)});document.querySelectorAll('.panel').forEach((p,i)=>{p.classList.toggle('on',i===n)})}
let BENCH={},OSS={},SOT={};
async function load(){
try{
const [b,o,s]=await Promise.all([
fetch('/api/ai-benchmark-cache.json?t='+Date.now()).then(r=>r.json()),
fetch('/api/oss-cache.json?t='+Date.now()).then(r=>r.json()).catch(()=>({})),
fetch('/api/source-of-truth.json?t='+Date.now()).then(r=>r.json()).catch(()=>({}))
]);
BENCH=b;OSS=o;SOT=s;
renderWiring();renderVsOpus();renderOSS();renderComparison();
}catch(e){$('p0').innerHTML='<p style="color:var(--rd)">Erreur: '+e+'</p>'}
}
function renderWiring(){
const A=BENCH.all_ais||{};
const wired=Object.entries(A).filter(([n,a])=>a.wired);
const notWired=Object.entries(A).filter(([n,a])=>!a.wired);
const agents=SOT.agents||{};
let h=`<div class="kpis">
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">${wired.length}</div><div class="kpi-l">WIRED</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--rd)">${notWired.length}</div><div class="kpi-l">NOT WIRED</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--vi)">${Object.keys(A).length}</div><div class="kpi-l">TOTAL AIs</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--go)">${BENCH.report?.combined_avg||'?'}/90</div><div class="kpi-l">COMBINED</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--cy)">0€</div><div class="kpi-l">COÛT TOTAL</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">${Math.round(wired.length/Object.keys(A).length*100)}%</div><div class="kpi-l">COVERAGE</div></div>
</div>`;
h+=`<h3 style="color:var(--gn);margin-bottom:12px">✅ ${wired.length} IAs Wirées dans WEVAL</h3><div class="grid">`;
wired.sort((a,b)=>(b[1].avg||0)-(a[1].avg||0));
for(const [n,a] of wired){
const col=a.type==='sovereign'?'var(--vi)':a.type==='agent'?'var(--gn)':a.type==='security'?'var(--rd)':a.type==='chatbot'?'var(--bl)':a.type==='search'?'var(--cy)':a.type==='testing'?'var(--pk)':a.type==='composite'?'var(--go)':'var(--fg3)';
h+=`<div class="card">
<div class="card-h"><div class="card-n"><a href="${a.url||'#'}" target="_blank">${a.icon||''} ${n}</a></div><span class="tag tag-gn">✅ WIRED</span></div>
<div class="card-row"><span class="card-k">Type</span><span class="tag" style="background:${col}22;color:${col}">${a.type}</span></div>
<div class="card-row"><span class="card-k">Score</span><span class="card-v sc" style="color:${col}">${a.avg}/90</span></div>
<div class="card-row"><span class="card-k">Rôle</span><span class="card-v">${(a.used_in||'').slice(0,40)}</span></div>
<div class="card-row"><span class="card-k">Cas d'usage</span><span class="card-v">${(a.usecase||'').slice(0,40)}</span></div>
<div class="card-row"><span class="card-k">Coût</span><span class="card-v">${a.cost||'?'}</span></div>
<div class="bar"><div class="bar-f" style="width:${Math.round(a.avg/90*100)}%;background:${col}"></div></div>
</div>`;
}
h+=`</div>`;
if(notWired.length){
h+=`<h3 style="color:var(--rd);margin:24px 0 12px">❌ ${notWired.length} Non Wirées (Références)</h3><div class="grid">`;
for(const [n,a] of notWired){
h+=`<div class="card" style="opacity:.6">
<div class="card-h"><div class="card-n"><a href="${a.url||'#'}" target="_blank">${a.icon||''} ${n}</a></div><span class="tag tag-rd">❌</span></div>
<div class="card-row"><span class="card-k">Score</span><span class="card-v sc">${a.avg}/90</span></div>
<div class="card-row"><span class="card-k">Coût</span><span class="card-v">${a.cost||'💰'}</span></div>
</div>`;
}
h+=`</div>`;
}
$('p0').innerHTML=h;
}
function renderVsOpus(){
const A=BENCH.all_ais||{};
const weval=A.WEVAL_COMBINED||{avg:93};
const opus=A.Claude_Opus_4_6||A['Claude_Opus_4.6']||{avg:90};
const sov=Object.entries(A).filter(([n,a])=>a.wired&&a.type==='sovereign');
const agents=Object.entries(A).filter(([n,a])=>a.wired&&a.type==='agent');
const pct=Math.round(weval.avg/opus.avg*100);
let h=`<div class="opus-bar">
<span style="font-size:24px">🌟</span>
<div><div style="font-weight:900;font-size:18px">WEVAL Combined: <span style="color:var(--gn)">${weval.avg}</span> vs Opus: <span style="color:var(--go)">${opus.avg}</span></div>
<div style="font-size:11px;color:var(--fg2)">${pct}% d'Opus · ${pct>100?'SUPÉRIEUR':'Inférieur'} à Claude Opus 4.6</div></div>
<div class="bar"><div class="bar-f" style="width:${Math.min(pct,100)}%;background:${pct>=100?'var(--gn)':'var(--go)'}"></div></div>
</div>`;
h+=`<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px">`;
// Avantages WEVAL
h+=`<div class="card"><div class="card-h"><span class="card-n" style="color:var(--gn)">✅ Avantages WEVAL</span></div>
<div class="card-row"><span class="card-k">Coût</span><span class="card-v" style="color:var(--gn)">0€/mois</span></div>
<div class="card-row"><span class="card-k">Providers</span><span class="card-v">${sov.length} sovereign cascade</span></div>
<div class="card-row"><span class="card-k">Agents</span><span class="card-v">${agents.length} autonomes</span></div>
<div class="card-row"><span class="card-k">Failover</span><span class="card-v">Auto cascade 7 niveaux</span></div>
<div class="card-row"><span class="card-k">Souveraineté</span><span class="card-v">100% (Ollama local)</span></div>
<div class="card-row"><span class="card-k">RGPD</span><span class="card-v">EU data residency (Mistral)</span></div>
<div class="card-row"><span class="card-k">Consensus</span><span class="card-v">MoA 4 providers · 9.8/10</span></div>
</div>`;
// Avantages Opus
h+=`<div class="card"><div class="card-h"><span class="card-n" style="color:var(--go)">🏆 Avantages Opus</span></div>
<div class="card-row"><span class="card-k">Raisonnement</span><span class="card-v">Meilleur single-model</span></div>
<div class="card-row"><span class="card-k">Code</span><span class="card-v">Analyse complexe supérieure</span></div>
<div class="card-row"><span class="card-k">Coût</span><span class="card-v" style="color:var(--rd)">~$200/mois API</span></div>
<div class="card-row"><span class="card-k">Dépendance</span><span class="card-v" style="color:var(--rd)">Cloud US · Anthropic</span></div>
<div class="card-row"><span class="card-k">Rate limit</span><span class="card-v" style="color:var(--rd)">Oui</span></div>
<div class="card-row"><span class="card-k">Failover</span><span class="card-v" style="color:var(--rd)">Aucun</span></div>
<div class="card-row"><span class="card-k">Souveraineté</span><span class="card-v" style="color:var(--rd)">0%</span></div>
</div></div>`;
// Économies
h+=`<div class="kpis" style="margin-top:16px">
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">$0</div><div class="kpi-l">COÛT MENSUEL</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--rd)">$200</div><div class="kpi-l">OPUS API/MOIS</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">$2,400</div><div class="kpi-l">ÉCONOMIE/AN</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--go)">${pct}%</div><div class="kpi-l">% D'OPUS</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--vi)">7</div><div class="kpi-l">CASCADE LEVELS</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">100%</div><div class="kpi-l">SOUVERAIN</div></div>
</div>`;
$('p1').innerHTML=h;
}
function renderOSS(){
const R=OSS.report||{};const S=OSS.skills||{};
const tools=R.total||70;const skills=S.total||1935;
let h=`<div class="kpis">
<div class="kpi"><div class="kpi-v" style="color:var(--bl)">${tools}</div><div class="kpi-l">TOOLS WIRED</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--vi)">${skills}</div><div class="kpi-l">SKILLS</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">${R.wire_pct||100}%</div><div class="kpi-l">WIRE RATE</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--cy)">${R.not_wired||0}</div><div class="kpi-l">NOT WIRED</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--go)">${R.categories||12}</div><div class="kpi-l">CATEGORIES</div></div>
<div class="kpi"><div class="kpi-v" style="color:var(--gn)">0€</div><div class="kpi-l">COÛT</div></div>
</div>`;
h+=`<p style="color:var(--fg2);font-size:12px;margin-bottom:12px">Données depuis <a href="/oss-discovery.html" target="_blank" style="color:var(--bl)">/oss-discovery.html</a></p>`;
const items=R.by_status||OSS.tools||[];
if(Array.isArray(items)&&items.length){
h+=`<div class="grid">`;
for(const t of items.slice(0,20)){
h+=`<div class="card"><div class="card-h"><div class="card-n">${t.name||t}</div><span class="tag tag-gn">wired</span></div></div>`;
}
h+=`</div>`;
}
$('p2').innerHTML=h;
}
function renderComparison(){
const A=BENCH.all_ais||{};
const lb=(BENCH.leaderboard||[]).sort((a,b)=>b.score-a.score);
let h=`<div style="overflow-x:auto"><table>
<tr><th>#</th><th>AI</th><th>Type</th><th>Score</th><th>%Opus</th><th>Wired</th><th>Coût</th><th>Utilisé dans</th><th>Cas d'usage</th><th>Lien</th></tr>`;
lb.forEach((x,i)=>{
const a=A[x.name]||{};
const pct=Math.round(x.score/90*100);
const wc=a.wired?'var(--gn)':'var(--rd)';
h+=`<tr>
<td>${i+1}</td>
<td style="font-weight:700">${a.icon||''} ${x.name}</td>
<td><span class="tag" style="background:rgba(255,255,255,.05)">${a.type||'?'}</span></td>
<td class="sc" style="color:${x.score>=85?'var(--gn)':x.score>=75?'var(--go)':'var(--fg3)'}">${x.score}</td>
<td>${pct}%</td>
<td style="color:${wc}">${a.wired?'✅':'❌'}</td>
<td style="font-size:9px">${a.cost||'?'}</td>
<td style="font-size:9px;max-width:150px;overflow:hidden;text-overflow:ellipsis">${a.used_in||'-'}</td>
<td style="font-size:9px;max-width:150px;overflow:hidden;text-overflow:ellipsis">${a.usecase||'-'}</td>
<td><a href="${a.url||'#'}" target="_blank" style="color:var(--bl);font-size:10px">Ouvrir →</a></td>
</tr>`;
});
h+=`</table></div>`;
$('p3').innerHTML=h;
}
load();
setInterval(load,60000);
</script>
</body>
</html>