/* ================================================================== Natural Memory v2 — site.js(多页版) 共享外壳(顶栏读数、页脚、入场动效)+ 按 body[data-page] 分派的页面渲染。 所有内容来自 window.NM_DATA / window.NM_EXAMPLES,保证与数据层单一来源。 ================================================================== */ (function () { "use strict"; var D = window.NM_DATA; if (!D) return; /* ---------- 工具 ---------- */ var $ = function (s, r) { return (r || document).querySelector(s); }; var $$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); }; var el = function (tag, cls, html) { var n = document.createElement(tag); if (cls) n.className = cls; if (html != null) n.innerHTML = html; return n; }; var esc = function (s) { return String(s == null ? "" : s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); }; var fmt = function (n, d) { return Number(n).toFixed(d == null ? 2 : d); }; var num = function (s) { var p = String(s).split("/"); return { c: Number(p[0]), n: Number(p[1]) }; }; var arrow = '→'; var setText = function (sel, v) { var n = $(sel); if (n) n.textContent = v; }; var copyText = function (btn, text) { var done = function () { btn.textContent = "已复制"; btn.classList.add("is-done"); setTimeout(function () { btn.textContent = "复制"; btn.classList.remove("is-done"); }, 1900); }; var fallback = function () { var ta = document.createElement("textarea"); ta.value = text; ta.style.position = "fixed"; ta.style.opacity = "0"; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); done(); } catch (e) { btn.textContent = "复制失败"; } document.body.removeChild(ta); }; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(done, fallback); } else { fallback(); } }; /* ---------- 入场与数值动画 ---------- 注意:这里**不把 IntersectionObserver 当唯一触发源**。 IO 在无头虚拟时间、被节流的 iframe、以及某些低端 WebView 里都不保证投递, 而「内容卡在隐藏态」是绝不能出现的故障 —— 尤其是 clip-path 擦除, 一次不触发就是一个永远看不见的标题。所以 IO 之外还有一条按滚动位置判定的兜底。 */ var pending = []; var revealNow = function (node) { if (!node || (node.classList && node.classList.contains("is-in"))) return; node.classList.add("is-in"); $$("[data-fill]", node).forEach(function (f) { f.style.width = f.getAttribute("data-fill") + "%"; }); if (node.hasAttribute && node.hasAttribute("data-fill")) { node.style.width = node.getAttribute("data-fill") + "%"; } }; var io = ("IntersectionObserver" in window) ? new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (!e.isIntersecting) return; revealNow(e.target); io.unobserve(e.target); var k = pending.indexOf(e.target); if (k > -1) pending.splice(k, 1); }); }, { rootMargin: "0px 0px -8% 0px", threshold: 0.06 }) : null; /* 兜底:每帧/每次滚动再按位置判一次,进视口就放出来 */ var sweepPending = function () { if (!pending.length) return; var vh = window.innerHeight || document.documentElement.clientHeight; pending = pending.filter(function (n) { var r = n.getBoundingClientRect(); if (r.top < vh * 0.94 && r.bottom > -60) { revealNow(n); if (io) io.unobserve(n); return false; } return true; }); }; window.addEventListener("scroll", sweepPending, { passive: true }); window.addEventListener("resize", sweepPending); var watch = function (node) { if (!node) return; if (io) { pending.push(node); io.observe(node); } else { revealNow(node); return; } sweepPending(); /* 已经在视口里的立刻放出来 */ }; var bar = function (cls, pct, label, valueHtml) { return '
' + '' + esc(label) + "" + '' + '' + valueHtml + "" + "
"; }; /* ================= 共享外壳 ================= */ (function shell() { var header = $("#site"), progress = $("#progress"); var onScroll = function () { var y = window.scrollY || document.documentElement.scrollTop; if (header) header.classList.toggle("is-stuck", y > 8); var h = document.documentElement.scrollHeight - window.innerHeight; if (progress) progress.style.width = (h > 0 ? Math.min(100, (y / h) * 100) : 0) + "%"; }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); // 键盘导航:← / → 切换上一节、下一节(线性风格里的快捷键触感) document.addEventListener("keydown", function (e) { if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) return; var t = e.target; if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return; var sel = e.key === "ArrowLeft" ? ".pn__a--prev" : (e.key === "ArrowRight" ? ".pn__a--next" : null); if (!sel) return; var a = $(sel); if (a && a.getAttribute("href")) { e.preventDefault(); location.href = a.getAttribute("href"); } }); // 页脚:来源文件 + 免责声明 var ff = $("#footFiles"); if (ff) { D.reproduce.files.forEach(function (x) { ff.appendChild(el("span", "src", esc(x.v.split("\\").pop()))); }); } setText("#disclaimer", D.meta.disclaimer); // 服务端运行时读数 var chip = $("#serverChipText"), foot = $("#footServer"); fetch("api/status", { cache: "no-store" }) .then(function (r) { if (!r.ok) throw new Error("bad"); return r.json(); }) .then(function (s) { if (chip) { chip.textContent = "LIVE · UP " + s.uptime; var c = $("#serverChip"); if (c) c.title = "本站服务端运行时读数 · bind " + s.bind; } if (foot) { foot.innerHTML = "host " + esc(s.host) + "" + "bind " + esc(s.bind) + "" + "python " + esc(s.python) + "" + "uptime " + esc(s.uptime) + "" + "requests " + esc(s.requests) + ""; } }) .catch(function () { if (chip) chip.textContent = "STATIC"; if (foot) foot.innerHTML = "运行时读数不可用(/api/status 无响应)"; }); /* ---------- 全站检索(命令面板) ---------- 索引由 build.py 生成到 assets/js/search.js,纯客户端,不发任何网络请求。 快捷键:/ 或 Ctrl/Cmd+K 打开,Esc 关闭,↑↓ 选择,↵ 打开。 */ (function palette() { var pal = $("#pal"), input = $("#palInput"), list = $("#palList"), n = $("#palN"); if (!pal || !input || !list) return; var IDX = window.NM_SEARCH || []; var HERE = document.body.getAttribute("data-page") || ""; var hits = [], cur = 0, open = false; var low = function (s) { return String(s == null ? "" : s).toLowerCase(); }; function mark(text, q) { if (!q) return esc(text); var i = low(text).indexOf(q); if (i < 0) return esc(text); return esc(text.slice(0, i)) + "" + esc(text.slice(i, i + q.length)) + "" + esc(text.slice(i + q.length)); } function score(e, q) { var h = low(e.h), t = low(e.t), p = low(e.pg), s = 0; if (h === q) s += 100; else if (h.indexOf(q) === 0) s += 60; else if (h.indexOf(q) > -1) s += 40; if (p.indexOf(q) > -1) s += 25; if (t.indexOf(q) > -1) s += 14; return s; } function query(raw) { var q = low(raw).trim(); if (!q) return IDX.filter(function (e) { return e.d; }).map(function (e) { return { e: e, q: "" }; }); var out = []; IDX.forEach(function (e) { var s = score(e, q); if (s > 0) out.push({ e: e, q: q, s: s }); }); out.sort(function (a, b) { return b.s - a.s || String(a.e.n).localeCompare(String(b.e.n)); }); return out.slice(0, 40); } function slugOf(href) { return href === "./" ? "index" : String(href).replace(/^\.\//, ""); } function findHeading(text) { var want = String(text).replace(/\s+/g, ""); var found = null; $$("#doc h2, #doc h3").forEach(function (h) { if (!found && h.textContent.replace(/\s+/g, "") === want) found = h; }); return found; } function jumpTo(node) { var reduce = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches); var y = node.getBoundingClientRect().top + (window.scrollY || 0) - 84; window.scrollTo({ top: y < 0 ? 0 : y, behavior: reduce ? "auto" : "smooth" }); node.classList.add("is-flash"); setTimeout(function () { node.classList.remove("is-flash"); }, 1700); } function render(q) { hits = query(q); cur = 0; list.innerHTML = hits.length ? hits.map(function (h, i) { var e = h.e, title = e.d ? e.pg : (e.h || e.pg); var sub = e.h ? e.t : (e.d ? e.t : ""); return '' + '' + esc(e.n) + "" + '' + mark(title, h.q) + "" + (sub ? '' + mark(sub, h.q) + "" : "") + "" + '' + esc(e.g) + ""; }).join("") : '

没有匹配的内容。试试「拒答」「写入路径」「召回」「SHA256」这类词。

'; if (n) n.textContent = hits.length ? hits.length + " 条" : ""; list.scrollTop = 0; } function select(i) { var items = $$(".pal__i", list); if (!items.length) return; cur = Math.max(0, Math.min(items.length - 1, i)); items.forEach(function (el2, k) { el2.classList.toggle("is-cur", k === cur); el2.setAttribute("aria-selected", k === cur ? "true" : "false"); }); var it = items[cur]; if (it.offsetTop < list.scrollTop) list.scrollTop = it.offsetTop - 6; else if (it.offsetTop + it.offsetHeight > list.scrollTop + list.clientHeight) list.scrollTop = it.offsetTop + it.offsetHeight - list.clientHeight + 6; } function activate(a) { var heading = a.getAttribute("data-h") || ""; var href = a.getAttribute("href") || "./"; var target = slugOf(href); // 同页结果一律就地处理,绝不重新加载 if (target === HERE) { var node = heading ? findHeading(heading) : null; close(); if (node) { jumpTo(node); return; } window.scrollTo({ top: 0, behavior: "smooth" }); var hd = $("#doc .doc__hd") || $("#doc h1"); if (hd) { hd.classList.add("is-flash"); setTimeout(function () { hd.classList.remove("is-flash"); }, 1700); } return; } try { sessionStorage.setItem("nm.pal", JSON.stringify({ s: target, h: heading })); } catch (e) { /* 无存储时退化为普通跳转 */ } // 键盘回车不会触发 的默认激活,所以这里显式跳转 location.href = href; } function show() { open = true; pal.hidden = false; document.documentElement.classList.add("pal-open"); input.value = ""; render(""); input.focus(); } function close() { open = false; pal.hidden = true; document.documentElement.classList.remove("pal-open"); } var btn = $("#palBtn"), mask = $("#palMask"); if (btn) btn.addEventListener("click", show); if (mask) mask.addEventListener("click", close); input.addEventListener("input", function () { render(input.value); }); list.addEventListener("mousemove", function (e) { var a = e.target && e.target.closest ? e.target.closest(".pal__i") : null; if (a) select(Number(a.getAttribute("data-i"))); }); list.addEventListener("click", function (e) { var a = e.target && e.target.closest ? e.target.closest(".pal__i") : null; if (!a) return; e.preventDefault(); activate(a); }); input.addEventListener("keydown", function (e) { if (e.key === "ArrowDown") { e.preventDefault(); select(cur + 1); } else if (e.key === "ArrowUp") { e.preventDefault(); select(cur - 1); } else if (e.key === "Enter") { var a = $$(".pal__i", list)[cur]; if (a) { e.preventDefault(); activate(a); } } }); document.addEventListener("keydown", function (e) { var t = e.target; var typing = !!(t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)); if (e.key === "Escape" && open) { close(); if (t === input) input.blur(); return; } if (open) return; if ((e.ctrlKey || e.metaKey) && (e.key === "k" || e.key === "K")) { e.preventDefault(); show(); return; } if (e.key === "/" && !typing && !e.ctrlKey && !e.metaKey && !e.altKey) { e.preventDefault(); show(); } }); /* 从检索跨页跳进来时,落到对应小节并闪一下 */ try { var saved = JSON.parse(sessionStorage.getItem("nm.pal") || "null"); sessionStorage.removeItem("nm.pal"); if (saved && saved.h && saved.s === HERE) { var node2 = findHeading(saved.h); if (node2) setTimeout(function () { jumpTo(node2); }, 60); } } catch (e) { /* 忽略 */ } })(); })(); /* ================= 各页面渲染 ================= */ var PAGES = {}; /* ================= 重启实验装置 ================= 数据全部来自 window.NM_RESTART(逐字取自工程原始 JSON)。 装置只做一件事:把「写入 → 重启 → 召回 → 作答」四个节拍的真实字段 按顺序放出来。修复前 / 修复后 两个版本可以随时对照。 ================================================= */ function restartInstrument() { var R = window.NM_RESTART, host = $("#rst"); if (!R || !host) return; var beatsBox = $("#rstBeats"), playBtn = $("#rstPlay"), out = $("#rstOut"); var reduce = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches); var vi = 0, timer = null, items = []; /* 默认停在哪一版:由数据决定,不靠 HTML 里手写的 is-on(两者不一致过一次) */ R.variants.forEach(function (v, k) { if (v.key === "after") vi = k; }); /* --- 四个节拍的骨架 --- */ R.beats.forEach(function (b, i) { var li = el("li", "rst__b"); li.dataset.i = i; li.innerHTML = '' + esc(b.i) + "" + "
" + '

' + esc(b.t) + "

" + '

' + esc(b.s) + "

" + '
' + "
"; li.addEventListener("click", function () { stop(); show(i); }); beatsBox.appendChild(li); items.push(li); }); /* --- 每个节拍要露出的真实字段 --- */ function beatData(v, i) { var L = R.limits, after = v.key === "after"; if (i === 0) return [ ["automatic_write", "true"], ["write_changed", String(v.writeChanged) + (v.writeChanged ? " → 记录已落库" : " → 记录没有落库")], ["records", "0 → " + v.store.records], ["coarse_index_buckets", "0 → " + v.store.coarse_index_buckets] ]; if (i === 1) return [ ["history_passed_to_restart", "false → 重启不携带任何对话历史"], ["resident_records", v.store.resident_records + " 条留在进程内存"], ["gpu_cache records / tokens", v.store.gpu_cache_records + " / " + v.store.gpu_cache_tokens], ["gpu_cache_bytes", v.store.gpu_cache_bytes + " B"], ["容量上限", L.capacityRecords.toLocaleString("en-US") + " 条 · " + L.maxPages.toLocaleString("en-US") + " 页 × " + L.pageCapacity + " 条"] ]; if (i === 2) { if (!after) return [ ["need_memory", "false"], ["stop_reason", v.stopReason], ["confidence", fmt(v.confidence, 4)], ["page_ids / record_ids", "(空)"] ]; return [ ["need_memory", "true"], ["page_ids", v.pageIds.join(", ") + " score " + fmt(v.pageScores[0], 4)], ["record_ids", v.recordIds.join(", ") + " score " + fmt(v.recordScores[0], 4)], ["hop_count", String(v.hopCount)], ["confidence", fmt(v.confidence, 4)], ["stop_reason", v.stopReason] ]; } return [ ["prefix_length", v.prefixLength + " tok (KV 预算 " + L.kvBudgetTokens.toLocaleString("en-US") + " tok)"], ["prefix_used", String(v.prefixUsed)], ["response", v.response], ["router_recalled_after_restart", String(v.recalled)], ["generated_contains_expected", String(v.correct)] ]; } function variant() { return R.variants[vi]; } function fillData() { var v = variant(); items.forEach(function (li, i) { var d = $("#rstData" + i, li); if (!d) return; d.innerHTML = beatData(v, i).map(function (r) { return '' + esc(r[0]) + "" + esc(r[1]) + ""; }).join(""); }); setText("#rstFile", (D.meta.repo || "") + "\\dynamic_memory_lab\\" + v.file); } function applyGauges(i) { var v = variant(), L = R.limits; var restarted = i >= 1, answered = i >= 3; var rec = i >= 0 ? v.store.records : 0; setText("#rstRec", String(rec)); $("#rstRecBar").style.width = (rec > 0 ? 100 : 0) + "%"; setText("#rstHist", restarted ? "false" : "true(本轮对话)"); $("#rstHistBar").style.width = (restarted ? 0 : 100) + "%"; var pf = answered ? v.prefixLength : 0; $("#rstPf").innerHTML = pf + " tok"; var pct = pf ? (pf / L.kvBudgetTokens) * 100 : 0; $("#rstPfBar").style.width = pf ? Math.max(0.8, pct) + "%" : "0%"; setText("#rstPfHint", pf ? "占 KV 预算 " + pct.toFixed(2) + "% —— 记忆走的是前缀,不是把历史塞进上下文" : "尚未注入证据前缀"); out.classList.toggle("is-idle", !answered); var vd = $("#rstVerdict"); vd.className = "rst__verdict mono " + (answered ? (v.correct ? "is-ok" : "is-bad") : ""); vd.textContent = answered ? (v.correct ? "✓ 命中 " + R.expected : "✗ 未命中 " + R.expected) : ""; setText("#rstResp", answered ? v.response : "…"); var kv = $("#rstKv"); kv.innerHTML = answered ? [ ["stop_reason", v.stopReason, false], ["prefix_used", String(v.prefixUsed), v.prefixUsed], ["confidence", fmt(v.confidence, 4), v.confidence >= 0.7], ["recalled_after_restart", String(v.recalled), v.recalled], ["contains_expected", String(v.correct), v.correct] ].map(function (r) { return '' + esc(r[0]) + " " + esc(r[1]) + ""; }).join("") : ""; host.classList.toggle("is-payoff", answered && v.correct); } function show(i) { items.forEach(function (li, j) { li.classList.toggle("is-on", j === i); li.classList.toggle("is-past", j < i); li.setAttribute("aria-current", j === i ? "step" : "false"); }); applyGauges(i); } function stop() { if (timer) { clearTimeout(timer); timer = null; } playBtn.classList.remove("is-playing"); } function play() { stop(); show(-1); if (reduce) { show(R.beats.length - 1); return; } playBtn.classList.add("is-playing"); var i = 0; var step = function () { show(i); i++; if (i < R.beats.length) timer = setTimeout(step, 1050); else { timer = null; playBtn.classList.remove("is-playing"); } }; timer = setTimeout(step, 260); } playBtn.addEventListener("click", play); $$(".seg__b", host).forEach(function (b, k) { b.classList.toggle("is-on", k === vi); b.addEventListener("click", function () { vi = k; $$(".seg__b", host).forEach(function (x) { x.classList.toggle("is-on", x === b); }); fillData(); play(); }); }); fillData(); show(-1); // 进入视口后自动放一次。 // 用滚动位置判定而不是 IntersectionObserver 的可见比例:装置比视口高时 // 比例阈值可能永远达不到,这是很常见的坑。触发一次后即摘掉监听。 var played = false; function autoPlay() { if (played) return; var r = host.getBoundingClientRect(); var vh = window.innerHeight || document.documentElement.clientHeight; if (r.top < vh * 0.72 && r.bottom > vh * 0.08) { played = true; window.removeEventListener("scroll", autoPlay); window.removeEventListener("resize", autoPlay); play(); } } window.addEventListener("scroll", autoPlay, { passive: true }); window.addEventListener("resize", autoPlay); autoPlay(); } /* ---- 00 总览 ---- */ PAGES.index = function () { setText("#heroLede", D.positioning.body); setText("#heroSrc", D.meta.repo + "\\dynamic_memory_lab"); setText("#heroDisclaimer", D.meta.disclaimer); var H = {}; D.dirty.headline.forEach(function (h) { H[h.metric] = h; }); var ans = H["可回答正确率"], rec = H["目标记忆召回率"]; var A = D.dirty.batches[0], B = D.dirty.batches[1]; var chain = function (h) { return fmt(h.base) + "%" + arrow + '' + fmt(h.a) + "%" + arrow + '' + fmt(h.b) + "%"; }; var items = [ { k: "可回答正确率 · 基线 → A → B", v: chain(ans), d: "同一 264 题题集的两个独立批次。基线 " + ans.baseRaw + ",批次 A " + ans.aRaw + ",批次 B " + ans.bRaw + ";两批次配置不同,不可合并。" }, { k: "目标记忆召回率 · 基线 → A → B", v: chain(rec), d: "基线没有记忆机制,召回恒为 0。批次 B 把该查的记忆查回来的比例达 " + rec.bRaw + "。" }, { k: "读取路径额外耗时 A → B", v: fmt(A.reader) + arrow + '' + fmt(B.reader) + " ms", d: "记忆读取相对无记忆基线新增的耗时;批次 A " + fmt(A.reader) + " ms,批次 B 降到 " + fmt(B.reader) + " ms。" } ]; var box = $("#heroKpis"); if (box) { items.forEach(function (it) { box.appendChild(el("div", "kpi", '' + esc(it.k) + "" + '' + it.v + "" + '' + esc(it.d) + "")); }); watch(box); } // 发布页:结果条、读取路径图绘制、三种抵达编排、重启装置 watch($("#releaseResult")); watch($(".teaser")); $$(".arr-wipe, .arr-num, .arr-cards").forEach(watch); restartInstrument(); var cite = $("#citeCopy"); if (cite) { var text = ($("#citeBlock") && $("#citeBlock").textContent) || ""; cite.addEventListener("click", function () { var done = function () { cite.textContent = "已复制"; cite.classList.add("is-done"); setTimeout(function () { cite.textContent = "复制"; cite.classList.remove("is-done"); }, 1900); }; var fallback = function () { var ta = document.createElement("textarea"); ta.value = text; ta.style.position = "fixed"; ta.style.opacity = "0"; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); done(); } catch (e) { cite.textContent = "复制失败"; } document.body.removeChild(ta); }; if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(done, fallback); else fallback(); }); } }; /* ---- 02 机制 ---- */ PAGES.mechanism = function () { // 读取路径步进器 (function flow() { var steps = D.readPath, box = $("#steps"); if (!box) return; steps.forEach(function (s, i) { var b = el("button", "step", '' + String(i + 1).padStart(2, "0") + "" + '' + esc(s.label) + ""); b.type = "button"; b.dataset.i = i; b.setAttribute("aria-selected", i === 0 ? "true" : "false"); b.addEventListener("click", function () { show(i); }); b.addEventListener("mouseenter", function () { show(i); }); box.appendChild(b); }); function show(i) { $$(".step", box).forEach(function (b) { var j = Number(b.dataset.i); b.classList.toggle("is-on", j === i); b.classList.toggle("is-past", j < i); b.setAttribute("aria-selected", j === i ? "true" : "false"); }); setText("#flowIdx", "STAGE " + String(i + 1).padStart(2, "0") + " / " + String(steps.length).padStart(2, "0")); setText("#flowTitle", steps[i].label); setText("#flowBody", steps[i].detail); setText("#flowIo", steps[i].io || ""); } show(0); watch(box); })(); // 记录字段 var rf = $("#recFields"); if (rf) { D.recordFields.forEach(function (f) { rf.appendChild(el("div", "rec__f", '' + esc(f.f) + "" + '' + esc(f.d) + "")); }); watch(rf); } // 真实记录示例(取自 examples.js,逐字) var rr = $("#realRecord"); var E = window.NM_EXAMPLES || []; if (rr && E.length && E[0].nm.records && E[0].nm.records.length) { var r = E[0].nm.records[0]; var rows = [ ["record_id", r.record_id], ["entity", r.entity], ["attribute", r.attribute], ["value", r.value], ["status", r.status], ["version", r.version], ["source", r.source], ["text_preview", r.text_preview] ].filter(function (x) { return x[1] !== undefined && x[1] !== null && x[1] !== ""; }); rr.innerHTML = '

一条真实记录 · 逐字取自评测结果

' + '
' + rows.map(function (x) { return '
' + esc(x[0]) + '' + '' + esc(x[1]) + "
"; }).join("") + "
" + '

这条记录在评测中命中了问题 user-004,' + '内容是用户给当时模型定的名字。注意「Natural Memory v1」是写入时的项目名,记录按原样保留、未做改写。

'; } else if (rr) { rr.textContent = "真实记录示例不可用(examples.js 未加载)。"; } // 状态机 var sl = $("#stateList"); if (sl) { D.states.forEach(function (s) { sl.appendChild(el("div", "state state--" + s.tone, '' + esc(s.s) + "" + '' + esc(s.d) + "")); }); watch(sl); } }; /* ---- 03 测量结果 ---- */ PAGES.results = function () { var tabs = $("#resultTabs"), panels = $("#resultPanels"); if (!tabs || !panels) return; var DT = D.dirty; var defs = [ { id: "dirty", label: "批次 A / B 对照" }, { id: "stage5", label: "Stage 5 结构化基准" }, { id: "router", label: "记忆路由器工程线" } ]; var want = (new URLSearchParams(location.search).get("tab") || "").toLowerCase(); var startId = defs.some(function (d) { return d.id === want; }) ? want : defs[0].id; var activate = function (id, push) { $$(".tab", tabs).forEach(function (x) { var on = x.dataset.id === id; x.classList.toggle("is-on", on); x.setAttribute("aria-selected", on ? "true" : "false"); }); $$(".panel", panels).forEach(function (p) { var on = p.dataset.id === id; p.classList.toggle("is-on", on); p.setAttribute("aria-hidden", on ? "false" : "true"); if (on) $$("[data-fill]", p).forEach(function (f) { f.style.width = f.getAttribute("data-fill") + "%"; }); }); if (push) { try { var u = new URL(location.href); u.searchParams.set("tab", id); history.replaceState(null, "", u.pathname + u.search + u.hash); } catch (e) { /* 仅影响地址栏 */ } } }; defs.forEach(function (d) { var t = el("button", "tab" + (d.id === startId ? " is-on" : ""), esc(d.label)); t.type = "button"; t.setAttribute("role", "tab"); t.dataset.id = d.id; t.setAttribute("aria-selected", d.id === startId ? "true" : "false"); t.addEventListener("click", function () { activate(d.id, true); }); tabs.appendChild(t); }); /* --- 面板 1 --- */ var p1 = el("div", "panel"); p1.dataset.id = "dirty"; var h = '

' + "" + esc(DT.title) + " · " + esc(DT.subtitle) + "

" + '

' + esc(DT.protocol) + "

" + '

' + '出处 ' + esc(DT.src) + "
" + esc(DT.batchNote) + "

"; h += '
' + '原版 Qwen3.5-4B' + '批次 A' + '批次 B
'; h += '
'; DT.headline.forEach(function (m) { h += '
' + '
' + esc(m.metric) + "" + '批次 A ' + fmt(m.a) + "% → 批次 B " + fmt(m.b) + "%
" + bar("bar--base", m.base, "原版 Qwen", fmt(m.base) + "%" + esc(m.baseRaw) + "") + bar("bar--a", m.a, "批次 A", fmt(m.a) + "%" + esc(m.aRaw) + "") + bar("bar--nm2", m.b, "批次 B", fmt(m.b) + "%" + esc(m.bRaw) + "") + "
"; }); h += "
"; h += '
' + DT.corpus.map(function (c) { return '
' + esc(c.k) + '' + esc(c.v) + "
"; }).join("") + "
"; h += '

两个批次的运行明细

' + '
' + DT.batches.map(function (b) { return ""; }).join("") + ""; [ { k: "读取路径额外耗时", v: function (b) { return b.reader + " ms"; } }, { k: "平均输入前缀 token", v: function (b) { return fmt(b.promptTokens); } }, { k: "前缀命中率 / 平均前缀 token", v: function (b) { return fmt(b.prefixRate) + "% / " + fmt(b.prefixTokens); } }, { k: "平均总延迟(基线 → 记忆)", v: function (b) { return b.latencyBase + " → " + b.latencyNm + " ms"; } }, { k: "平均解码速度(基线 → 记忆)", v: function (b) { return b.decodeBase + " → " + b.decodeNm + " tok/s"; } }, { k: "NM 显存快照峰值 allocated / reserved", v: function (b) { return fmt(b.allocNm, 3) + " / " + fmt(b.resvNm, 3) + " GiB"; } }, { k: "active records / pages", v: function (b) { return b.records + " / " + b.pages; } }, { k: "GPU cache token", v: function (b) { return b.cacheTokens.toLocaleString("en-US"); } } ].forEach(function (r) { h += "" + DT.batches.map(function (b) { return '"; }).join("") + ""; }); h += "
指标" + esc(b.label) + '
' + esc(b.date) + " · " + esc(b.tag) + "
" + esc(r.k) + "' + esc(r.v(b)) + "
"; h += '

按数据域拆分(可回答正确率)

'; DT.domains.forEach(function (d) { h += '
' + esc(d.domain) + '' + d.n + " 题
" + bar("bar--base", d.base, "原版 Qwen", fmt(d.base) + "%" + esc(d.baseRaw) + "") + bar("bar--a", d.a, "批次 A", fmt(d.a) + "%" + esc(d.aRaw) + "") + bar("bar--nm2", d.b, "批次 B", fmt(d.b) + "%" + esc(d.bRaw) + "") + "
"; }); h += "
"; h += '

按类别拆分(正确 / 题量)

' + '
'; DT.categories.forEach(function (c) { var na = num(c.a), nb = num(c.b), diff = nb.c - na.c; h += "" + '" + '" + '"; }); h += "
类别题量原版 Qwen批次 A批次 BB 相对 A
" + esc(c.label) + '
' + esc(c.k) + "
' + c.n + '' + esc(c.base) + '' + esc(c.a) + "' + esc(c.b) + "' + (diff > 0 ? "+" : "") + diff + " 题

" + esc(DT.categoryNote) + "

"; h += '

路由与生成的差距

' + '
' + '
批次 A · 目标记忆召回' + fmt(DT.gap.recallA) + '%' + esc(DT.gap.recallARaw) + "
" + '
批次 B · 目标记忆召回' + fmt(DT.gap.recallB) + '%' + esc(DT.gap.recallBRaw) + "
" + '
批次 A · 最终回答正确' + fmt(DT.gap.answerA) + '%' + esc(DT.gap.answerARaw) + "
" + '
批次 B · 最终回答正确' + fmt(DT.gap.answerB) + '%' + esc(DT.gap.answerBRaw) + "
" + '

' + esc(DT.gap.note) + "

"; p1.innerHTML = h; /* --- 面板 2:Stage 5 --- */ var p2 = el("div", "panel"); p2.dataset.id = "stage5"; var h2 = '

' + esc(D.stage5.title) + " · " + esc(D.stage5.subtitle) + '
出处 ' + esc(D.stage5.src) + "

" + '
' + '原版 Qwen3.5-4B强 RAG 基线Natural Memory v2
' + '
'; D.stage5.sets.forEach(function (set) { h2 += '

' + esc(set.name) + " · " + set.n + " 题

"; set.rows.forEach(function (r) { var cls = /Natural Memory/.test(r.sys) ? "bar--nm2" : (/RAG/.test(r.sys) ? "bar--rag" : "bar--base"); h2 += '
' + esc(r.sys) + '' + r.lat + " ms · " + r.tok + " tok/s
" + bar(cls, r.acc, "正确率", fmt(r.acc) + "%" + esc(r.raw) + "") + "
"; }); h2 += "
"; }); h2 += "
"; h2 += '
' + ""; D.stage5.sets.forEach(function (set) { set.rows.forEach(function (r, i) { h2 += "" + (i === 0 ? '" : "") + "" + '" + '"; }); }); h2 += "
题集系统正确率原始平均延迟解码速度未知拒答
' + esc(set.name) + " · " + set.n + "" + esc(r.sys) + '' + fmt(r.acc) + "%' + esc(r.raw) + '' + r.lat + ' ms' + r.tok + " tok/s' + (r.abstain ? esc(r.abstain) : "—") + "

" + esc(D.stage5.note) + "

"; p2.innerHTML = h2; /* --- 面板 3:路由器工程线 --- */ var p3 = el("div", "panel"); p3.dataset.id = "router"; var h3 = '

' + esc(D.router.title) + " · " + esc(D.router.subtitle) + '
出处 ' + esc(D.router.src) + "

" + '
' + "" + D.router.metrics.map(function (m) { return ""; }).join("") + "
指标原 512 维 / 基线128 维路由器备注
" + esc(m.k) + '' + esc(m.base) + '' + esc(m.nm2) + '' + esc(m.note || "—") + "
" + '
' + D.router.spec.map(function (s) { return '
' + esc(s.k) + '' + esc(s.v) + "
"; }).join("") + "
" + '
' + '

这张表必须连这些一起读

' + D.router.caveats.map(function (c, i) { return '
' + String(i + 1).padStart(2, "0") + '

' + esc(c) + "

"; }).join("") + "
"; p3.innerHTML = h3; panels.appendChild(p1); panels.appendChild(p2); panels.appendChild(p3); [p1, p2, p3].forEach(function (p) { p.setAttribute("role", "tabpanel"); p.setAttribute("aria-hidden", "true"); }); watch(p1); activate(startId, false); }; /* ---- 04 实测样例 ---- */ PAGES.examples = function () { var box = $("#exampleList"); if (!box) return; var E = window.NM_EXAMPLES || []; setText("#exampleIntro", D.examples.subtitle); setText("#exampleNote", D.examples.note); if (!E.length) { box.appendChild(el("p", "small", "样例数据未加载。")); return; } var DOMAIN = { user_dialogue: "用户对话事实", real_repository: "真实源码/文档" }; var CAT = { symbol_navigation: "符号定位", unknown_refusal: "未知拒答", paraphrase: "自然改写", constraint: "约束类问题", cross_session: "跨会话", temporal_conflict: "时间冲突" }; var TOKMAX = 64; var tok = function (t) { return t >= TOKMAX ? '' + t + " token(达上限截断)" : t + " token"; }; var verdict = function (ok) { return '' + (ok ? "命中" : "未命中") + ""; }; var col = function (title, cls, r, meta, extra) { return '
' + '

' + esc(title) + "

" + '

' + esc(r.response || "(空)") + "

" + '

' + meta + "
" + tok(r.tokens || 0) + "

" + (extra || "") + "
"; }; E.forEach(function (e, i) { var identical = (e.nm.response || "") === (e.base.response || ""); var ev = ""; if (e.nm.records && e.nm.records.length) { ev = '

命中的记忆记录

' + e.nm.records.map(function (r) { return '
' + '' + esc(r.attribute || r.entity || r.record_id) + "" + '' + esc(r.text_preview || r.value || "") + "" + '' + esc(r.record_id) + " · " + esc(r.source || "") + (r.status ? " · " + esc(r.status) : "") + "
"; }).join("") + "
"; } else if (!e.answerable) { ev = '

命中的记忆记录

' + '
无 —— 该题目标本身不在库里,考察的是模型会不会硬答。
'; } box.appendChild(el("article", "ex reveal", '
' + '' + String(i + 1).padStart(2, "0") + "" + '' + esc(DOMAIN[e.domain] || e.domain) + " · " + esc(CAT[e.category] || e.category) + "" + (e.answerable ? "" : '未知题') + (identical ? '两系统回答逐字相同' : "") + 'id=' + esc(e.id) + "
" + '

' + esc(e.query) + "

" + '

期望锚点' + (e.expected ? esc(e.expected) + (e.expected_anchors && e.expected_anchors.length > 1 ? " · 其余:" + esc(e.expected_anchors.slice(1).join("、")) : "") : "无(未知题,考察拒答)") + "

" + '
' + col("原版 Qwen3.5-4B", "base", e.base, "判分 " + verdict(e.base.correct)) + col("Natural Memory v2", "nm", e.nm, "判分 " + verdict(e.nm.correct) + (e.answerable ? " · 目标召回 " + (e.nm.recall ? "命中" : "未命中") : ""), ev) + "
")); }); $$(".ex", box).forEach(watch); }; /* ---- 05 代价 ---- */ PAGES.cost = function () { setText("#costIntro", D.cost.subtitle); setText("#costQuote", D.cost.quote); var box = $("#ledger"); if (box) { box.appendChild(el("div", "ledger__h", "指标原版 QwenNM v2变化")); D.cost.rows.forEach(function (r) { box.appendChild(el("div", "ledger__r", '' + esc(r.k) + "" + '' + esc(r.base) + "" + '' + esc(r.nm2) + "" + '' + esc(r.delta) + "")); }); watch(box); } var v = D.cost.vram, vb = $("#vram"); if (vb) { [ { k: "allocated · 无记忆基线", val: v.allocBase, cls: "base" }, { k: "allocated · NM v2", val: v.allocNm2, cls: "nm2" }, { k: "reserved · 无记忆基线", val: v.resvBase, cls: "base" }, { k: "reserved · NM v2", val: v.resvNm2, cls: "nm2" } ].forEach(function (r) { vb.innerHTML += '
' + esc(r.k) + "" + fmt(r.val, 3) + " " + v.unit + "
" + '
'; }); vb.innerHTML += '
012 GiB 显卡
'; watch(vb); } }; /* ---- 06 容量 ---- */ PAGES.capacity = function () { var box = $("#capList"); if (box) { D.capacity.stats.forEach(function (s) { var hi = /设计容量|GPU cache 上限/.test(s.k); box.appendChild(el("div", "cap__r" + (hi ? " cap__r--hi" : ""), '' + esc(s.k) + (s.d ? "" + esc(s.d) + "" : "") + "" + '' + esc(s.v) + "")); }); watch(box); } var g = $("#pageMap"), total = 512, used = D.capacity.grid.usedPages; if (g) { var step = Math.max(1, Math.floor(total / used)), out = ""; for (var i = 0; i < total; i++) { var on = i % step === 0 && (i / step) < used; out += ""; } g.innerHTML = out; } setText("#storageMode", D.capacity.storage.mode); setText("#storageText", D.capacity.storage.text); setText("#storageTradeoff", D.capacity.storage.tradeoff); }; /* ---- 07 边界 ---- */ PAGES.limits = function () { setText("#limitsIntro", D.limits.subtitle); var c = $("#claims"); if (c) { D.limits.claims.forEach(function (t, i) { c.appendChild(el("div", "claim", '✕' + esc(t) + "" + 'UNSUPPORTED ' + String(i + 1).padStart(2, "0") + "")); }); watch(c); } var l = $("#lims"); if (l) { D.limits.limitations.forEach(function (x, i) { l.appendChild(el("div", "lim", '' + String(i + 1).padStart(2, "0") + "" + "

" + esc(x.t) + '

' + esc(x.d) + "

")); }); watch(l); } var q = $("#quotes"); if (q) { D.limits.quotes.forEach(function (x) { q.appendChild(el("div", "quote", "" + esc(x.q) + "" + esc(x.s) + "")); }); watch(q); } }; /* ---- 08 路线图 ---- */ PAGES.roadmap = function () { var s = $("#solved"); if (s) { D.solved.forEach(function (t, i) { s.appendChild(el("div", "check", '✓ ' + String(i + 1).padStart(2, "0") + "" + '' + esc(t) + "")); }); watch(s); } var r = $("#roadmap-list"); if (r) { D.roadmap.forEach(function (t, i) { r.appendChild(el("div", "road__r", '→ ' + String(i + 1).padStart(2, "0") + "" + '' + esc(t) + "")); }); watch(r); } }; /* ---- 09 复现 ---- */ PAGES.reproduce = function () { var R = D.reproduce; setText("#cwd", R.cwd); setText("#pBase", D.meta.base); var cmd = R.cmd.join("\n"), block = $("#cmdBlock"); if (block) { block.innerHTML = esc(cmd) .replace(/(--[a-z-]+)/g, '$1') .replace(/("[^&]*")/g, '$1'); } var f = $("#files"); if (f) { R.files.forEach(function (x) { f.appendChild(el("div", "kv__r", '' + esc(x.k) + '' + esc(x.v) + "")); }); watch(f); } var btn = $("#copyBtn"); if (btn) { btn.addEventListener("click", function () { var done = function () { btn.textContent = "已复制"; btn.classList.add("is-done"); setTimeout(function () { btn.textContent = "复制命令"; btn.classList.remove("is-done"); }, 1900); }; var fallback = function () { var ta = document.createElement("textarea"); ta.value = cmd; ta.style.position = "fixed"; ta.style.opacity = "0"; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); done(); } catch (e) { btn.textContent = "复制失败"; } document.body.removeChild(ta); }; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(cmd).then(done, fallback); } else { fallback(); } }); } }; /* ---- 04 NM2.1 ---- */ function doseChart(host, d) { if (!host || !d) return; var head = '
' + esc(d.axis) + "" + '' + esc(d.xLabel) + "
"; var axis = '
' + d.x.map(function (v) { return '' + esc(String(v)) + ""; }).join("") + "
"; var rows = d.metrics.map(function (m) { var max = Math.max.apply(null, m.v) || 1; return '
' + esc(m.label) + "" + (m.higherBetter ? "越高越好" : "越低越好") + "" + '' + m.v.map(function (v, i) { var pick = d.x[i] === d.pick; return '' + '' + "" + v.toFixed(2) + esc(m.unit) + ""; }).join("") + "
"; }).join(""); host.innerHTML = head + axis + rows + '

' + esc(d.note) + "

" + '

' + esc(window.NM21 ? window.NM21.srcLabel : "") + "

"; } PAGES.nm21 = function () { var M = window.NM21; if (M) { doseChart($("#nmBlend"), M.blend); doseChart($("#nmPrior"), M.prior); } var b = $("#nmCopy"), cmd = $("#nmCmd"); if (b && cmd) b.addEventListener("click", function () { copyText(b, cmd.textContent || ""); }); }; /* ---- 06 真实评测台账 ---- */ PAGES.ledger = function () { var L = window.NM_LEDGER, box = $("#ledgerList"); if (!box || !L) return; var total = 0, all = []; L.forEach(function (s) { total += s.n; s.items.forEach(function (it) { all.push({ s: s, it: it }); }); }); setText("#ledgerIntro", "共 " + total + " 条真实 episode,来自 " + L.length + " 次正式运行(24 条同句式候选、值为随机码,随机猜中概率 4.17%)。"); var verdictOf = function (it) { if (!it.ans) return it.leak ? "leak" : "abstain"; if (it.ok) return "ok"; return it.wrong ? "wrong" : "miss"; }; var V = { ok: { label: "答对", tone: "ok" }, wrong: { label: "答成别的属性", tone: "no" }, miss: { label: "答错", tone: "no" }, leak: { label: "未知泄漏", tone: "no" }, abstain: { label: "未知已拒答", tone: "ok" } }; var fSrc = "all", fV = "all"; var srcDefs = [{ k: "all", label: "全部来源" }].concat(L.map(function (s) { return { k: s.key, label: s.label + " · " + s.n }; })); var vDefs = [{ k: "all", label: "全部判定" }].concat(["ok", "wrong", "miss", "leak", "abstain"].map(function (k) { return { k: k, label: V[k].label }; })); function buildSeg(host, defs, get, set) { host.innerHTML = ""; defs.forEach(function (d) { var b = el("button", "seg__b" + (get() === d.k ? " is-on" : ""), esc(d.label)); b.type = "button"; b.addEventListener("click", function () { set(d.k); $$(".seg__b", host).forEach(function (x, i) { x.classList.toggle("is-on", defs[i].k === d.k); }); paint(); }); host.appendChild(b); }); } function paint() { var rows = all.filter(function (r) { if (fSrc !== "all" && r.s.key !== fSrc) return false; if (fV !== "all" && verdictOf(r.it) !== fV) return false; return true; }); var tally = { ok: 0, wrong: 0, miss: 0, leak: 0, abstain: 0 }; rows.forEach(function (r) { tally[verdictOf(r.it)]++; }); setText("#ledgerCount", "显示 " + rows.length + " / " + total + " 条"); setText("#ledgerBreak", Object.keys(V).map(function (k) { return V[k].label + " " + tally[k]; }).join(" · ")); box.innerHTML = rows.length ? rows.map(function (r, i) { var it = r.it, v = V[verdictOf(it)]; var src = r.s.note; return '
' + '
' + '' + String(i + 1).padStart(3, "0") + "" + '' + esc(v.label) + "" + '属性 · ' + esc(it.attr || "—") + "" + (it.ans ? "" : '未知题') + '' + esc(it.id) + " · " + esc(src) + "" + "
" + '

期望锚点' + (it.ans ? "" + esc(it.exp) + "" : "无(未知题,考察拒答)") + "

" + '

' + esc(it.reply || "(空)") + "

" + '

stop_reason=' + esc(it.stop || "—") + "" + " · records_selected=" + esc(String(it.sel)) + "" + " · top_score=" + esc(Number(it.score).toFixed(4)) + "" + " · records_active=" + esc(String(it.active)) + "" + " · need_memory=" + esc(String(it.need)) + "

" + "
"; }).join("") : '

当前筛选下没有记录。

'; } buildSeg($("#ledgerSrc"), srcDefs, function () { return fSrc; }, function (k) { fSrc = k; }); buildSeg($("#ledgerVerdict"), vDefs, function () { return fV; }, function (k) { fV = k; }); paint(); }; /* ---------- 分派 ---------- */ var page = document.body.getAttribute("data-page") || ""; if (PAGES[page]) { try { PAGES[page](); } catch (err) { if (window.console) console.error("[NM] 页面渲染失败: " + page, err); } } })();