severity-collapse / index.html
invincible-jha's picture
Point cross-references at the MuVeraAI namespace
fbf7863 verified
Raw History Blame Contribute Delete
8.29 kB
<!doctype html>
<html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Where did Controversial go?</title>
<style>
:root{--bg:#fbfbfd;--fg:#16181d;--muted:#5b6270;--line:#e3e6ec;--card:#fff;
--safe:#3b7dd8;--unsafe:#d1495b;--contro:#e0a020;--err:#8d99ae;--accent:#4338ca}
@media(prefers-color-scheme:dark){:root{--bg:#0f1116;--fg:#e8eaef;--muted:#9aa3b2;--line:#252932;
--card:#161922;--accent:#8b8cf7}}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);
font:16px/1.62 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
.wrap{max-width:940px;margin:0 auto;padding:44px 22px 80px}
h1{font-size:2.05rem;line-height:1.2;margin:0 0 .4em;letter-spacing:-.02em}
h2{font-size:1.2rem;margin:2.4em 0 .7em;letter-spacing:-.01em}
.lede{color:var(--muted);font-size:1.06rem}
code{background:var(--line);padding:.1em .38em;border-radius:4px;font-size:.9em}
.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:20px 22px;margin:16px 0}
.tabs{display:flex;gap:8px;flex-wrap:wrap;margin:26px 0 14px}
.tab{padding:9px 15px;border:1px solid var(--line);background:var(--card);color:var(--fg);
border-radius:9px;cursor:pointer;font:inherit;font-size:.93rem;transition:.15s}
.tab[aria-selected=true]{border-color:var(--accent);color:var(--accent);font-weight:600}
table{border-collapse:collapse;width:100%;font-size:.93rem}
th,td{text-align:left;padding:8px 10px;border-bottom:1px solid var(--line)}
th{color:var(--muted);font-weight:600}
td.n{text-align:right;font-variant-numeric:tabular-nums}
.zero{color:var(--unsafe);font-weight:700}
.bar{display:flex;height:26px;border-radius:6px;overflow:hidden;margin:5px 0 3px}
.bar span{display:block}
.legend{display:flex;gap:16px;flex-wrap:wrap;color:var(--muted);font-size:.85rem;margin-top:10px}
.dot{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:5px;vertical-align:middle}
.k{color:var(--muted);font-size:.8rem;text-transform:uppercase;letter-spacing:.06em}
.big{font-size:1.75rem;font-weight:700;font-variant-numeric:tabular-nums}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px}
.note{border-left:3px solid var(--accent);padding:2px 0 2px 15px;color:var(--muted);margin:18px 0}
a{color:var(--accent)}
footer{margin-top:56px;padding-top:22px;border-top:1px solid var(--line);color:var(--muted);font-size:.88rem}
.scroll{overflow-x:auto}
</style></head><body><div class="wrap">
<h1>Where did <code>Controversial</code> go?</h1>
<p class="lede"><code>Qwen3Guard-Gen-0.6B</code> emits three severity values. Three LoRA fine-tunes
were trained on it, varying <strong>only</strong> which projections the adapter touches.
<strong>All three emit two.</strong></p>
<div class="note">Attention-only and MLP-only are <strong>disjoint</strong> families of projections,
and each is <em>independently</em> sufficient to destroy the class. So the loss is not attributable
to a module family. The cause is the training target: the corpus renders <code>Safety:</code> as a
boolean, and ~11,272 gradient updates teach a two-valued field.</div>
<div class="tabs" id="tabs" role="tablist"></div>
<div id="panel"></div>
<h2>Why this matters more than the recall column</h2>
<p>A policy control of the form <code>Controversial = SAFE</code> becomes a <strong>silent
no-op</strong> on every one of these models. It reads as configured and governs nothing &mdash; the
same defect class as a bound that reads <em>enforced</em> and is <em>observed</em>.</p>
<p>The attention-only arm has the <strong>highest recall in the programme and is the worst model in
it</strong>: the gain is substantially bought with false positives, and it has lost an output class.
A model that scores better on the headline metric is not the same instrument.</p>
<footer>
<strong>Vikram Jha</strong> &middot; MuVeraAI &middot;
<a href="https://orcid.org/0009-0004-3959-6099">ORCID 0009-0004-3959-6099</a> &middot;
<a href="mailto:vikram@muveraai.com">vikram@muveraai.com</a><br>
Verdicts <a href="https://huggingface.co/datasets/MuVeraAI/guard-verdicts">CC BY 4.0</a> &middot;
adapters research-only &middot;
<a href="https://huggingface.co/MuVeraAI/guard-lora-t1a-all-modules">t1a</a> &middot;
<a href="https://huggingface.co/MuVeraAI/guard-lora-t1b-attention">t1b</a> &middot;
<a href="https://huggingface.co/MuVeraAI/guard-lora-t1c-mlp">t1c</a>
</footer>
</div>
<script>
var C={safe:'var(--safe)',unsafe:'var(--unsafe)',controversial:'var(--contro)',error:'var(--err)'};
var ORDER=['safe','unsafe','controversial','error'];
function fmt(n){return n.toLocaleString();}
function bar(sev,total){
var out='<div class="bar">';
ORDER.forEach(function(k){
if(!sev[k])return;
out+='<span style="width:'+(100*sev[k]/total)+'%;background:'+C[k]+'" title="'+k+': '+sev[k]+'"></span>';
});
return out+'</div>';
}
function legend(sev){
var out='<div class="legend">';
ORDER.forEach(function(k){
if(sev[k]===undefined)return;
out+='<span><i class="dot" style="background:'+C[k]+'"></i>'+k+' '+fmt(sev[k]||0)+'</span>';
});
return out+'</div>';
}
function total(o){var t=0;for(var k in o)t+=o[k];return t;}
fetch('data.json').then(function(r){return r.json();}).then(function(D){
var tabs=document.getElementById('tabs'), panel=document.getElementById('panel');
function render(a){
var bs=D.base.severity, cs=a.severity, bt=total(bs), ct=total(cs);
var moved=Object.keys(a.moved).map(function(k){return [k,a.moved[k]];})
.sort(function(x,y){return y[1]-x[1];});
var rows=moved.map(function(p){
return '<tr><td>became <code>'+p[0]+'</code></td><td class="n">'+p[1]+'</td></tr>';
}).join('');
var pTxt = a.p<1e-4 ? 'p &lt; 0.0001' : 'p = '+a.p.toFixed(4);
panel.innerHTML=
'<div class="card">'+
'<div class="k">target modules</div><div style="margin-bottom:14px"><code>'+a.modules+'</code></div>'+
'<div class="k">base &mdash; Qwen3Guard-Gen-0.6B</div>'+bar(bs,bt)+legend(bs)+
'<div class="k" style="margin-top:20px">'+a.id+' &mdash; fine-tuned</div>'+bar(cs,ct)+legend(cs)+
'</div>'+
'<div class="grid">'+
'<div class="card"><div class="k">controversial</div>'+
'<div class="big">'+fmt(bs.controversial)+' &rarr; <span class="zero">0</span></div></div>'+
'<div class="card"><div class="k">recall</div><div class="big">'+a.recall.toFixed(4)+'</div>'+
'<div class="k">base '+D.base.recall.toFixed(4)+'</div></div>'+
'<div class="card"><div class="k">false-positive rate</div><div class="big">'+a.fpr.toFixed(4)+'</div>'+
'<div class="k">base '+D.base.fpr.toFixed(4)+'</div></div>'+
'<div class="card"><div class="k">paired McNemar</div><div class="big">'+pTxt+'</div>'+
'<div class="k">'+a.base_only+' vs '+a.cand_only+' discordant</div></div>'+
'</div>'+
'<div class="card">'+
'<h2 style="margin-top:0">Where the base’s '+bs.controversial+' <code>Controversial</code> verdicts went</h2>'+
'<div class="scroll"><table><tbody>'+rows+'</tbody></table></div>'+
'<p style="margin-bottom:0">Of those '+bs.controversial+' items, <strong>'+D.base.controversial_tp+
' are genuinely unsafe</strong>. The base caught all '+D.base.controversial_tp+
' &mdash; under a <code>Controversial = harmful</code> policy a controversial verdict already '+
'counts as harmful. This arm catches <strong>'+a.caught_now+'</strong>.</p>'+
'</div>'+
'<p class="lede"><strong>Verdict: VOID &mdash; the candidate lost a severity class.</strong> '+
'A recall comparison between models with different output vocabularies is not meaningful, '+
'whatever the arithmetic says.</p>';
}
D.arms.forEach(function(a,i){
var b=document.createElement('button');
b.className='tab'; b.textContent=a.id+' — '+a.short; b.setAttribute('role','tab');
b.setAttribute('aria-selected', i===0 ? 'true' : 'false');
b.onclick=function(){
var kids=tabs.children;
for(var j=0;j<kids.length;j++) kids[j].setAttribute('aria-selected','false');
b.setAttribute('aria-selected','true');
render(a);
};
tabs.appendChild(b);
});
render(D.arms[0]);
});
</script></body></html>