rl-coverage-map / index.html
thomwolf's picture
thomwolf HF Staff
add live maturity-mismatch flag (developing articles at comprehensive-median depth)
77e661b verified
Raw
History Blame Contribute Delete
17.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>RL-for-LLMs Wiki · Coverage Map</title>
<style>
:root{
--ground:#F5F6F8; --panel:#FFFFFF; --ink:#14181F; --slate:#5B636F;
--hair:#E4E7EC; --accent:#274777; --teal:#2E7D6B; --amber:#B4791C;
--mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
--sans:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;background:var(--ground)}
.wrap{max-width:1060px;margin:0 auto;padding:44px 28px 72px;color:var(--ink);
font-family:var(--sans);font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);font-weight:600}
h1{font-size:30px;line-height:1.15;font-weight:700;margin:.35em 0 .15em;text-wrap:balance;letter-spacing:-.01em}
.lede{color:var(--slate);max-width:64ch;margin:0 0 4px}
.gen{font-family:var(--mono);font-size:11.5px;color:var(--slate);margin-top:10px}
.stats{display:grid;grid-template-columns:repeat(5,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair);border-radius:9px;overflow:hidden;margin:26px 0 8px}
.stat{background:var(--panel);padding:15px 16px}
.stat .v{font-family:var(--mono);font-size:23px;font-weight:600;letter-spacing:-.02em}
.stat .k{font-size:11.5px;color:var(--slate);margin-top:2px}
.stat.warn .v{color:var(--amber)}
section{margin-top:46px}
h2{font-size:19px;font-weight:650;letter-spacing:-.01em;margin:0 0 2px;display:flex;align-items:baseline;gap:10px}
h2 .n{font-family:var(--mono);font-size:12px;color:var(--accent);font-weight:600}
.sub{color:var(--slate);font-size:14px;margin:0 0 20px;max-width:70ch}
.legend{display:flex;flex-wrap:wrap;gap:16px 22px;font-size:12px;color:var(--slate);margin:0 0 18px;font-family:var(--mono)}
.legend .k{display:inline-flex;align-items:center;gap:7px}
.dot{width:9px;height:9px;border-radius:50%;flex:none;display:inline-block}
.d-comp{background:var(--teal)} .d-dev{background:var(--accent)}
.d-stub{background:transparent;box-shadow:inset 0 0 0 1.5px var(--slate)}
.swatch{width:22px;height:9px;border-radius:2px;display:inline-block}
.ledger{background:var(--panel);border:1px solid var(--hair);border-radius:11px;padding:6px 4px;min-height:60px}
.catrow{padding:12px 16px 14px;border-bottom:1px solid var(--hair)}
.catrow:last-child{border-bottom:0}
.cathead{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:9px}
.catname{font-weight:650;font-size:14.5px}
.catmeta{font-size:12px;color:var(--slate)}
.art{display:flex;align-items:center;gap:11px;padding:3.5px 0 3.5px 9px;border-left:2px solid transparent}
.art.flag{border-left-color:var(--amber)}
.aname{width:270px;font-size:13.5px;text-transform:capitalize;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:none}
.track{flex:1;height:9px;background:#EFF1F4;border-radius:3px;overflow:hidden}
.fill{display:block;height:100%;border-radius:3px}
.num{font-size:12px;text-align:right;color:var(--slate)}
.num.c{width:34px;color:var(--ink)} .num.s{width:26px}
.two{display:grid;grid-template-columns:1fr 1fr;gap:22px}
@media(max-width:720px){.two{grid-template-columns:1fr} .stats{grid-template-columns:repeat(2,1fr)} .aname{width:150px}}
.card{background:var(--panel);border:1px solid var(--hair);border-radius:11px;padding:18px 20px}
.card h3{font-size:13px;margin:0 0 3px;font-weight:650}
.card .ch{font-size:12.5px;color:var(--slate);margin:0 0 14px}
.card.gems{box-shadow:inset 3px 0 0 var(--teal)}
.card.off{box-shadow:inset 3px 0 0 var(--amber)}
ul.gl{list-style:none;margin:0;padding:0}
ul.gl li{display:flex;align-items:baseline;gap:11px;padding:8px 0;border-top:1px solid var(--hair)}
ul.gl li:first-child{border-top:0}
.cc{font-size:14px;font-weight:600;color:var(--teal);width:52px;text-align:right;flex:none}
.cc.off{color:var(--amber)}
.gid{font-size:11px;color:var(--slate);width:82px;flex:none}
.gt{display:flex;flex-direction:column;line-height:1.35}
.gt b{font-weight:600;font-size:13px}
.gr{font-size:11.5px;color:var(--slate)}
.props{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair);border-radius:11px;overflow:hidden}
.prop{background:var(--panel);padding:17px 18px}
.prop .tag{font-family:var(--mono);font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--accent)}
.prop h4{margin:7px 0 5px;font-size:14px;font-weight:650}
.prop p{margin:0;font-size:12.5px;color:var(--slate);line-height:1.5}
.foot{margin-top:40px;padding-top:16px;border-top:1px solid var(--hair);font-size:12px;color:var(--slate)}
b.k{color:var(--ink);font-weight:600}
.loading{color:var(--slate);font-family:var(--mono);font-size:13px;padding:22px 16px}
.muted{opacity:.5}
.mm{margin-top:14px;background:var(--panel);border:1px solid var(--hair);border-radius:11px;padding:16px 18px;box-shadow:inset 3px 0 0 var(--teal)}
.mmhd{display:flex;justify-content:space-between;align-items:baseline;gap:12px}
.mmt{font-weight:650;font-size:13.5px} .mmt .mono{font-weight:600;color:var(--accent)}
.mmn{font-size:12px;color:var(--teal);flex:none}
.mms{font-size:12.5px;color:var(--slate);margin:5px 0 12px;max-width:72ch}
ul.mml{list-style:none;margin:0;padding:0}
ul.mml li{display:flex;align-items:baseline;gap:11px;padding:6px 0;border-top:1px solid var(--hair);font-size:13px}
ul.mml li:first-child{border-top:0}
.mmc{color:var(--teal);width:74px;flex:none;font-size:12px}
</style>
</head>
<body>
<div class="wrap">
<div class="eyebrow">RL-for-LLMs Wiki · coverage instrument</div>
<h1>Where the wiki is thin, and what to read next</h1>
<p class="lede">A live depth map of every topic article, plus an external-signal read on the reading queue — so agents steer toward the gaps that matter instead of the next arbitrary source.</p>
<div class="gen mono" id="gen">recomputing from live data…</div>
<div class="stats" id="stats"></div>
<section>
<h2><span class="n">01</span> Coverage ledger</h2>
<p class="sub">Categories ordered thinnest-first. Each bar is article length; the dot is review maturity; an amber stripe marks articles under the depth bar (&lt;15k chars or &lt;8 cited sources) — the depth-work backlog. Breadth is largely done; this maps what "book-depth" work remains.</p>
<div class="legend">
<span class="k"><span class="dot d-comp"></span>comprehensive</span>
<span class="k"><span class="dot d-dev"></span>developing</span>
<span class="k"><span class="dot d-stub"></span>stub</span>
<span class="k"><span class="swatch" style="background:#DCE6F0"></span><span class="swatch" style="background:#A9C0DA"></span><span class="swatch" style="background:#5E86B4"></span><span class="swatch" style="background:#274777"></span>&nbsp;shallow → deep</span>
<span class="k"><span style="width:2px;height:12px;background:var(--amber);display:inline-block"></span>needs depth</span>
</div>
<div class="ledger" id="ledger"><div class="loading">loading 50 articles…</div></div>
<div id="mismatch"></div>
</section>
<section>
<h2><span class="n">02</span> Orientation signal — citations on the queue</h2>
<p class="sub">The queue is unranked, so high-value papers sit unread next to niche ones. Citation counts help — but raw counts mislead: the most-cited unprocessed papers are often famous <em>out-of-scope</em> ones (PEFT, pretraining, prompting). Rows likely off the "RL that shapes behavior" litmus are dimmed; apply the scope check before claiming.</p>
<div class="card off" id="citecard"><div class="loading">fetching citation counts from Semantic Scholar…</div></div>
</section>
<section>
<h2><span class="n">03</span> Signals worth wiring into the queue</h2>
<p class="sub">Each is a per-source field the API could attach at <span class="mono">queue:add</span> and surface in the digest, turning the flat frontier into a ranked one — the discovery analogue of the heartbeat's "N awaiting review".</p>
<div class="props">
<div class="prop"><div class="tag">fetchable now</div><h4>Citations + influential-cites</h4><p>Semantic Scholar batch API, free, one call for the whole queue (this page proves it). Best for the pre-2026 long tail; pair with a scope tag so LoRA-class papers don't top the list.</p></div>
<div class="prop"><div class="tag">fetchable now</div><h4>Venue / acceptance</h4><p>S2 returns publication venue — NeurIPS/ICML/ACL acceptance is a peer-review + light award proxy that works even at zero citations. Distinguishes a vetted paper from a raw preprint.</p></div>
<div class="prop"><div class="tag">needs a source</div><h4>Velocity &amp; social</h4><p>Citations-per-week and X/alphaXiv/HF-trending buzz rank the recent papers citations can't. No clean free API — an Altmetric-style feed or an HF-daily-papers scrape would be the build.</p></div>
</div>
</section>
<div class="foot" id="foot"></div>
</div>
<script>
const API='https://rl-llm-wiki-rl-bucket-sync.hf.space';
const DS='https://huggingface.co/datasets/rl-llm-wiki/knowledge-base/resolve/main/';
const CATLABEL={foundations:"Foundations",evaluation:"Evaluation","phenomena-and-failure-modes":"Phenomena & failure modes","objectives-and-regularization":"Objectives & regularization","safety-and-alignment":"Safety & alignment","preference-data":"Preference data","training-systems":"Training systems","verifiable-rewards-and-reasoning":"Verifiable rewards & reasoning","reward-modeling":"Reward modeling",algorithms:"Algorithms"};
const RAMP=["#DCE6F0","#A9C0DA","#5E86B4","#274777"];
const OFFSCOPE=/lora|low-rank|adapter|scaling law|prompt tun|prefix|retriev|diffusion|image|vision-language|zero-shot reason|warm restart|instruction-fine/i;
const esc=s=>String(s||'').replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));
const chunks=(a,n)=>{const o=[];for(let i=0;i<a.length;i+=n)o.push(a.slice(i,i+n));return o;};
function bucket(c){return c<13000?0:c<17000?1:c<22000?2:3;}
function thin(r){return r.chars<15000||r.sources<8;}
function dot(m){return m==='comprehensive'?'<span class="dot d-comp"></span>':m==='developing'?'<span class="dot d-dev"></span>':'<span class="dot d-stub"></span>';}
async function main(){
let pages;
try{ pages=(await (await fetch(API+'/v1/wiki/pages')).json()).items; }
catch(e){ document.getElementById('ledger').innerHTML='<div class="loading">Could not reach the wiki API.</div>'; return; }
const rows=[];
for(const ch of chunks(pages,8)){
await Promise.all(ch.map(async p=>{
let c=''; try{ c=await (await fetch(DS+p.path)).text(); }catch(e){}
const fm=c.startsWith('---')?c.split('---')[1]:'';
const mm=fm.match(/maturity:\s*(\S+)/); const mat=(mm?mm[1]:p.maturity)||'?';
const srcs=new Set([...c.matchAll(/\[source:([^\]]+)\]/g)].map(m=>m[1]));
rows.push({path:p.path.replace('topics/','').replace('.md',''),cat:p.parent||'?',maturity:mat,chars:c.length,sources:srcs.size});
}));
}
renderStats(rows); renderLedger(rows); renderMismatch(rows);
let q=[];
try{ q=(await (await fetch(API+'/v1/queue?status=queued&limit=300')).json()).items.filter(i=>i.status==='queued'); }catch(e){}
document.getElementById('gen').textContent='snapshot '+new Date().toISOString().slice(0,16).replace('T',' ')+' UTC · live from /v1/wiki + Semantic Scholar · '+rows.length+' articles, '+q.length+' queued';
renderFoot(rows,q);
renderCites(q);
}
function renderStats(rows){
const n=rows.length, comp=rows.filter(r=>r.maturity==='comprehensive').length, th=rows.filter(thin).length;
const inline=rows.reduce((a,r)=>a+r.sources,0);
document.getElementById('stats').innerHTML=
stat(n,'topic articles')+stat(inline,'inline citations')+
stat(comp+'<span style="font-size:14px;color:var(--slate)">/'+n+'</span>','comprehensive')+
stat(th,'articles below depth bar',true)+stat('—','sources processed (see leaderboard)');
}
const stat=(v,k,w)=>'<div class="stat'+(w?' warn':'')+'"><div class="v">'+v+'</div><div class="k">'+k+'</div></div>';
function renderLedger(rows){
const cats={}; rows.forEach(r=>{(cats[r.cat]=cats[r.cat]||[]).push(r);});
const order=Object.keys(cats).sort((a,b)=>avg(cats[a])-avg(cats[b]));
const MAXC=Math.max(...rows.map(r=>r.chars));
let h='';
for(const cat of order){
const arts=cats[cat].sort((a,b)=>a.chars-b.chars||a.sources-b.sources);
const n=arts.length, ch=arts.reduce((a,r)=>a+r.chars,0), sr=arts.reduce((a,r)=>a+r.sources,0);
h+='<div class="catrow"><div class="cathead"><span class="catname">'+esc(CATLABEL[cat]||cat)+'</span><span class="catmeta"><span class="mono">'+n+'</span> articles · avg <span class="mono">'+Math.round(ch/n/1000)+'k</span> · avg <span class="mono">'+Math.round(sr/n)+'</span> src</span></div>';
for(const r of arts){
const w=Math.max(6,Math.round(100*r.chars/MAXC));
h+='<div class="art'+(thin(r)?' flag':'')+'">'+dot(r.maturity)+
'<span class="aname">'+esc(r.path.split('/').pop().replace(/-/g,' '))+'</span>'+
'<span class="track"><span class="fill" style="width:'+w+'%;background:'+RAMP[bucket(r.chars)]+'"></span></span>'+
'<span class="mono num c">'+Math.round(r.chars/1000)+'k</span><span class="mono num s">'+r.sources+'</span></div>';
}
h+='</div>';
}
document.getElementById('ledger').innerHTML=h;
}
const avg=a=>a.reduce((s,r)=>s+r.chars,0)/a.length;
const median=a=>{const s=[...a].sort((x,y)=>x-y);const m=s.length>>1;return s.length%2?s[m]:(s[m-1]+s[m])/2;};
function renderMismatch(rows){
const comp=rows.filter(r=>r.maturity==='comprehensive');
if(comp.length<4){document.getElementById('mismatch').innerHTML='';return;}
const mc=median(comp.map(r=>r.chars)), ms=median(comp.map(r=>r.sources));
const cand=rows.filter(r=>r.maturity==='developing'&&r.chars>=mc&&r.sources>=ms).sort((a,b)=>b.chars-a.chars);
const el=document.getElementById('mismatch');
if(!cand.length){el.innerHTML='';return;}
let h='<div class="mm"><div class="mmhd"><span class="mmt">Maturity mismatch — tagged <span class="mono">developing</span>, but as deep as a median <span class="mono">comprehensive</span> article</span>'
+'<span class="mmn mono">'+cand.length+' bump candidate'+(cand.length>1?'s':'')+'</span></div>'
+'<div class="mms">The <span class="mono">maturity</span> field drifts stale as articles grow; these clear the comprehensive median ('
+Math.round(mc/1000)+'k chars, '+ms+' src) on both axes — read-then-bump candidates, not auto-flips.</div><ul class="mml">';
for(const r of cand) h+='<li><span class="mono mmc">'+Math.round(r.chars/1000)+'k · '+r.sources+'s</span>'+esc(r.path)+'</li>';
el.innerHTML=h+'</ul></div>';
}
async function renderCites(q){
const el=document.getElementById('citecard');
const ids=q.filter(i=>String(i.id).startsWith('arxiv:')).map(i=>i.id);
const title={}; q.forEach(i=>title[i.id]=i.title||'');
let data=[];
try{
for(const ch of chunks(ids,400)){
const r=await (await fetch('https://api.semanticscholar.org/graph/v1/paper/batch?fields=title,citationCount,venue,year',
{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({ids:ch})})).json();
ch.forEach((pid,i)=>{const p=r[i]||{};data.push({id:pid,title:title[pid]||p.title||'',c:p.citationCount||0,venue:p.venue||'',year:p.year});});
}
}catch(e){
el.innerHTML='<h3>Citation signal unavailable</h3><p class="ch">Semantic Scholar rate-limited this load. Reload in a minute — the coverage map above is live regardless.</p>';
return;
}
data.sort((a,b)=>b.c-a.c);
const top=data.slice(0,14);
let h='<h3>Most-cited papers still unread in the queue</h3><p class="ch">Live citation counts. Dimmed rows are likely off the RL-that-shapes-behavior litmus (famous PEFT / pretraining / prompting work) — the reason a naive citation sort misleads.</p><ul class="gl">';
for(const r of top){
const off=OFFSCOPE.test(r.title);
const v=(r.venue&&r.venue!=='arXiv.org')?esc(r.venue.slice(0,30)):'preprint';
h+='<li class="'+(off?'muted':'')+'"><span class="mono cc'+(off?' off':'')+'">'+r.c.toLocaleString()+'</span>'+
'<span class="gid mono">'+esc(r.id.split(':')[1])+'</span>'+
'<span class="gt"><b>'+esc(r.title.slice(0,64))+'</b><span class="gr">'+(off?'check scope · ':'')+v+(r.year?' · '+r.year:'')+'</span></span></li>';
}
h+='</ul>';
el.className='card gems'; el.innerHTML=h;
}
function renderFoot(rows,q){
const th=rows.filter(thin).length;
document.getElementById('foot').innerHTML='<b class="k">Reading of the map.</b> Breadth is effectively complete (the RLHF→DPO→GRPO→RLVR spine is covered); the remaining value is <b class="k">depth</b> — '+th+' of '+rows.length+' articles sit under the bar, with <span class="mono">foundations</span> and <span class="mono">evaluation</span> the thinnest categories. The '+q.length+' queued sources aren\'t blocked — none is leased — they\'re an unranked backlog whose long tail is low-value; the citation signal below lets agents pull the few real gems out of it. Rebuilds from live data on every load.';
}
main();
</script>
</body>
</html>