| <div class="performance-dashboard"></div> |
| <style> |
| .performance-dashboard { |
| position: relative; |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; |
| width: 100%; |
| } |
| .performance-dashboard .chart-card { |
| background: var(--page-bg); |
| border: 1px solid var(--border-color); |
| border-radius: 12px; |
| padding: 24px 20px 16px; |
| } |
| .performance-dashboard svg { display: block; width: 100%; } |
| .performance-dashboard .axis path { stroke: none; } |
| .performance-dashboard .axis line { stroke: var(--axis-color); shape-rendering: crispEdges; } |
| .performance-dashboard .axis text { fill: var(--tick-color); font-size: 11px; } |
| .performance-dashboard .grid line { stroke: var(--grid-color); stroke-dasharray: 2, 2; } |
| .performance-dashboard .grid path { stroke: none; } |
| .performance-dashboard .bar-before { fill: #9CA3AF; } |
| .performance-dashboard .bar-after { fill: #4F46E5; } |
| .performance-dashboard .bar-before, .performance-dashboard .bar-after { |
| cursor: pointer; transition: opacity 0.15s ease; |
| } |
| .performance-dashboard .bar-before:hover, .performance-dashboard .bar-after:hover { opacity: 0.85; } |
| .performance-dashboard .task-label { fill: var(--text-color); font-size: 12px; font-weight: 600; } |
| .performance-dashboard .layer-pill { font-size: 9px; font-weight: 700; fill: var(--muted-color); } |
| .performance-dashboard .layer-pill-bg { fill: var(--surface-bg, #f3f4f6); stroke: var(--border-color); stroke-width: 0.5; } |
| .performance-dashboard .category-dot { r: 4; } |
| .performance-dashboard .gain-pill text { font-size: 10px; font-weight: 700; fill: #16a34a; } |
| .performance-dashboard .gain-pill rect { fill: #dcfce7; } |
| .performance-dashboard .header { |
| display: flex; align-items: center; justify-content: space-between; |
| flex-wrap: wrap; gap: 16px; margin-top: 12px; padding-top: 12px; |
| border-top: 1px solid var(--border-color); |
| } |
| .performance-dashboard .legend { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; } |
| .performance-dashboard .legend-title { font-size: 12px; font-weight: 700; color: var(--text-color); } |
| .performance-dashboard .legend .items { display: flex; flex-wrap: wrap; gap: 8px 14px; } |
| .performance-dashboard .legend .item { |
| display: inline-flex; align-items: center; gap: 6px; |
| white-space: nowrap; font-size: 12px; color: var(--text-color); |
| } |
| .performance-dashboard .legend .swatch { |
| width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--border-color); |
| } |
| .performance-dashboard .categories { display: flex; flex-wrap: wrap; gap: 8px 14px; } |
| .performance-dashboard .categories .cat-item { |
| display: inline-flex; align-items: center; gap: 5px; |
| font-size: 11px; color: var(--muted-color); |
| } |
| .performance-dashboard .categories .cat-dot { width: 8px; height: 8px; border-radius: 50%; } |
| </style> |
| <script> |
| (function() { |
| var ensureD3 = function(cb) { |
| if (window.d3 && typeof window.d3.select === 'function') return cb(); |
| var s = document.getElementById('d3-cdn-script'); |
| if (!s) { |
| s = document.createElement('script'); |
| s.id = 'd3-cdn-script'; |
| s.src = 'https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js'; |
| document.head.appendChild(s); |
| } |
| s.addEventListener('load', function() { if (window.d3) cb(); }, { once: true }); |
| }; |
| |
| var bootstrap = function() { |
| var candidates = Array.from(document.querySelectorAll('.performance-dashboard')) |
| .filter(function(el) { return !el.dataset.mounted; }); |
| var container = candidates[candidates.length - 1]; |
| if (!container) return; |
| container.dataset.mounted = 'true'; |
| |
| var data = [ |
| { task: "MMLU", type: "Knowledge", layer: 24, before: 52.06, after: 55.37, gain: 3.31 }, |
| { task: "MMLU-Pro", type: "Knowledge", layer: 25, before: 30.30, after: 30.49, gain: 0.19 }, |
| { task: "BBQ Ambig", type: "Bias", layer: 5, before: 60.17, after: 65.86, gain: 5.69 }, |
| { task: "BBQ Disambig", type: "Bias", layer: 5, before: 84.38, after: 84.85, gain: 0.47 }, |
| { task: "SimpleQA", type: "Knowledge", layer: 8, before: 3.78, after: 4.00, gain: 0.22 }, |
| { task: "GSM8K", type: "Reasoning", layer: 24, before: 54.62, after: 55.65, gain: 1.03 }, |
| { task: "HarmBench", type: "Safety", layer: 21, before: 41.46, after: 49.12, gain: 7.66 }, |
| { task: "XSTest", type: "Safety", layer: 12, before: 86.35, after: 87.62, gain: 1.27 } |
| ]; |
| var catColors = { Knowledge: '#8B5CF6', Bias: '#EC4899', Safety: '#F97316', Reasoning: '#06B6D4' }; |
| var barColors = { before: '#9CA3AF', after: '#4F46E5' }; |
| |
| container.style.position = 'relative'; |
| var tip = document.createElement('div'); |
| Object.assign(tip.style, { |
| position:'absolute',top:'0',left:'0',transform:'translate(-9999px,-9999px)', |
| pointerEvents:'none',padding:'10px 14px',borderRadius:'10px',fontSize:'12px',lineHeight:'1.5', |
| border:'1px solid var(--border-color)',background:'var(--surface-bg)',color:'var(--text-color)', |
| boxShadow:'0 4px 24px rgba(0,0,0,.18)',opacity:'0',transition:'opacity .12s ease', |
| zIndex:'1000',maxWidth:'260px' |
| }); |
| var tipInner = document.createElement('div'); |
| tip.appendChild(tipInner); |
| container.appendChild(tip); |
| |
| function showTip(event, d) { |
| tipInner.innerHTML = |
| '<div style="font-weight:700;margin-bottom:4px"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:'+catColors[d.type]+';margin-right:6px;vertical-align:middle"></span>'+d.task+ |
| '<span style="font-size:10px;color:var(--muted-color);margin-left:4px">'+d.type+' · L'+d.layer+'</span></div>'+ |
| '<div style="display:flex;gap:16px;margin-top:2px"><div><span style="color:var(--muted-color)">Before:</span> <strong>'+d.before.toFixed(2)+'</strong></div>'+ |
| '<div><span style="color:var(--muted-color)">After:</span> <strong style="color:#4F46E5">'+d.after.toFixed(2)+'</strong></div></div>'+ |
| '<div style="margin-top:4px;color:#16a34a;font-weight:700">+'+d.gain.toFixed(2)+' gain</div>'; |
| var coords = d3.pointer(event, container); |
| tip.style.transform = 'translate('+(coords[0]+14)+'px,'+(coords[1]-14)+'px)'; |
| tip.style.opacity = '1'; |
| } |
| function hideTip() { tip.style.opacity='0'; tip.style.transform='translate(-9999px,-9999px)'; } |
| |
| var card = document.createElement('div'); |
| card.className = 'chart-card'; |
| container.appendChild(card); |
| |
| var svg = d3.select(card).append('svg').style('display','block'); |
| var gRoot = svg.append('g'); |
| var gGrid = gRoot.append('g').attr('class','grid'); |
| var gBars = gRoot.append('g'); |
| var gLabels = gRoot.append('g'); |
| var gGains = gRoot.append('g'); |
| var gAxes = gRoot.append('g'); |
| var margin = {top:16,right:80,bottom:36,left:140}; |
| var hasAnimated = false; |
| |
| function roundedBar(xPos, yPos, w, h, r) { |
| r = Math.min(r, h/2, w>0?w:0); |
| if(w<=0) return 'M'+xPos+','+yPos+'h0v'+h+'h0Z'; |
| return 'M'+xPos+','+yPos+'h'+(w-r)+'a'+r+','+r+',0,0,1,'+r+','+r+'v'+(h-2*r)+'a'+r+','+r+',0,0,1,'+(-r)+','+r+'h'+(-(w-r))+'Z'; |
| } |
| |
| function render(animate) { |
| var width = container.clientWidth || 800; |
| var rowH = 52; |
| var height = margin.top + margin.bottom + data.length * rowH; |
| svg.attr('width',width).attr('height',height); |
| gRoot.attr('transform','translate('+margin.left+','+margin.top+')'); |
| var innerW = width-margin.left-margin.right; |
| var innerH = height-margin.top-margin.bottom; |
| var maxVal = d3.max(data, function(d){return Math.max(d.before,d.after);}); |
| var xMax = Math.ceil(maxVal/10)*10; |
| |
| var y = d3.scaleBand().domain(data.map(function(d){return d.task})).range([0,innerH]).paddingInner(0.3).paddingOuter(0.15); |
| var yBar = d3.scaleBand().domain(['before','after']).range([0,y.bandwidth()]).padding(0.12); |
| var x = d3.scaleLinear().domain([0,xMax]).range([0,innerW]).nice(); |
| |
| gGrid.selectAll('.grid-x').data([0]).join('g').attr('class','grid grid-x') |
| .call(d3.axisBottom(x).tickSize(innerH).tickFormat('').ticks(6)) |
| .call(function(g){g.select('.domain').remove()}); |
| |
| gAxes.selectAll('.x-axis').data([0]).join('g').attr('class','x-axis axis') |
| .attr('transform','translate(0,'+innerH+')') |
| .call(d3.axisBottom(x).ticks(6).tickSizeOuter(0)); |
| |
| var labelGroups = gLabels.selectAll('.task-row').data(data,function(d){return d.task}) |
| .join('g').attr('class','task-row') |
| .attr('transform',function(d){return 'translate(0,'+(y(d.task)+y.bandwidth()/2)+')'}); |
| labelGroups.selectAll('.category-dot').data(function(d){return[d]}).join('circle') |
| .attr('class','category-dot').attr('cx',-margin.left+14).attr('cy',0).attr('r',4) |
| .attr('fill',function(d){return catColors[d.type]}); |
| labelGroups.selectAll('.task-label').data(function(d){return[d]}).join('text') |
| .attr('class','task-label').attr('x',-margin.left+26).attr('y',0).attr('dy','0.35em') |
| .attr('text-anchor','start').text(function(d){return d.task}); |
| labelGroups.selectAll('.layer-pill-bg').data(function(d){return[d]}).join('rect') |
| .attr('class','layer-pill-bg').attr('x',-16).attr('y',-8).attr('width',28).attr('height',16).attr('rx',6); |
| labelGroups.selectAll('.layer-pill').data(function(d){return[d]}).join('text') |
| .attr('class','layer-pill').attr('x',-2).attr('y',0).attr('dy','0.35em').attr('text-anchor','middle') |
| .text(function(d){return'L'+d.layer}); |
| |
| var dur = animate ? 700 : 0; |
| gBars.selectAll('.bar-before').data(data,function(d){return d.task+'-b'}).join('path') |
| .attr('class','bar-before') |
| .attr('transform',function(d){return'translate(0,'+(y(d.task)+yBar('before'))+')'}) |
| .on('mouseenter',function(e,d){showTip(e,d)}).on('mousemove',function(e,d){showTip(e,d)}).on('mouseleave',hideTip) |
| .transition().duration(dur).ease(d3.easeCubicOut) |
| .attrTween('d',function(d){var tw=x(d.before),bw=yBar.bandwidth();var p=this._pw||0;this._pw=tw;return function(t){return roundedBar(0,0,animate?d3.interpolateNumber(p,tw)(t):tw,bw,3)}}); |
| |
| gBars.selectAll('.bar-after').data(data,function(d){return d.task+'-a'}).join('path') |
| .attr('class','bar-after') |
| .attr('transform',function(d){return'translate(0,'+(y(d.task)+yBar('after'))+')'}) |
| .on('mouseenter',function(e,d){showTip(e,d)}).on('mousemove',function(e,d){showTip(e,d)}).on('mouseleave',hideTip) |
| .transition().duration(dur).delay(function(d,i){return animate?i*60:0}).ease(d3.easeCubicOut) |
| .attrTween('d',function(d){var tw=x(d.after),bw=yBar.bandwidth();var p=this._pw||0;this._pw=tw;return function(t){return roundedBar(0,0,animate?d3.interpolateNumber(p,tw)(t):tw,bw,3)}}); |
| |
| var gainG = gGains.selectAll('.gain-pill').data(data,function(d){return d.task}).join('g').attr('class','gain-pill') |
| .attr('transform',function(d){return'translate('+(x(d.after)+8)+','+(y(d.task)+yBar('after')+yBar.bandwidth()/2)+')'}); |
| gainG.selectAll('text').data(function(d){return[d]}).join('text').attr('dy','0.35em').attr('x',6).text(function(d){return'+'+d.gain.toFixed(2)}); |
| gainG.each(function(d){ |
| var g=d3.select(this);var txt=g.select('text').node();if(!txt)return;var bb=txt.getBBox(); |
| g.selectAll('rect').data([d]).join('rect').attr('x',0).attr('y',-bb.height/2-3).attr('width',bb.width+12).attr('height',bb.height+6).attr('rx',8); |
| this.appendChild(txt); |
| }); |
| } |
| |
| var header = document.createElement('div'); |
| header.className = 'header'; |
| var legend = document.createElement('div'); |
| legend.className = 'legend'; |
| legend.innerHTML = '<div class="legend-title">Legend</div><div class="items"></div>'; |
| var items = legend.querySelector('.items'); |
| [{l:'Before CRL',c:barColors.before},{l:'After CRL',c:barColors.after}].forEach(function(e){ |
| items.innerHTML += '<span class="item"><span class="swatch" style="background:'+e.c+'"></span><span>'+e.l+'</span></span>'; |
| }); |
| header.appendChild(legend); |
| var cats = document.createElement('div'); |
| cats.className = 'categories'; |
| [['Knowledge','#8B5CF6'],['Bias','#EC4899'],['Safety','#F97316'],['Reasoning','#06B6D4']].forEach(function(p){ |
| cats.innerHTML += '<span class="cat-item"><span class="cat-dot" style="background:'+p[1]+'"></span><span>'+p[0]+'</span></span>'; |
| }); |
| header.appendChild(cats); |
| container.appendChild(header); |
| |
| var obs = new IntersectionObserver(function(entries){ |
| entries.forEach(function(entry){ |
| if(entry.isIntersecting&&!hasAnimated){hasAnimated=true;render(true);obs.disconnect();} |
| }); |
| },{threshold:0.15}); |
| obs.observe(container); |
| render(false); |
| |
| if(window.ResizeObserver){new ResizeObserver(function(){if(hasAnimated)render(false)}).observe(container);} |
| }; |
| |
| if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',function(){ensureD3(bootstrap)},{once:true}); |
| else ensureD3(bootstrap); |
| })(); |
| </script> |
|
|