期望锚点' +
(it.ans ? "" + esc(it.exp) + "" : "无(未知题,考察拒答)") + "
' + esc(it.reply || "(空)") + "
" + '" + "/* ================================================================== 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 '
"; }; /* ================= 共享外壳 ================= */ (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) + "
" + '' + "一条真实记录 · 逐字取自评测结果
' + '这条记录在评测中命中了问题 user-004,' +
'内容是用户给当时模型定的名字。注意「Natural Memory v1」是写入时的项目名,记录按原样保留、未做改写。
' + "" + esc(DT.title) + " · " + esc(DT.subtitle) + "
" + '' + esc(DT.protocol) + "
" + '' +
'出处 ' + esc(DT.src) + "
" + esc(DT.batchNote) + "
两个批次的运行明细
' + '| 指标 | ' + DT.batches.map(function (b) { return "" + esc(b.label) + ' ' + esc(b.date) + " · " + esc(b.tag) + " | ";
}).join("") + "
|---|---|
| " + esc(r.k) + " | " + DT.batches.map(function (b) { return '' + esc(r.v(b)) + " | "; }).join("") + "
按数据域拆分(可回答正确率)
按类别拆分(正确 / 题量)
' + '| 类别 | 题量 | 原版 Qwen | 批次 A | 批次 B | B 相对 A |
|---|---|---|---|---|---|
| " + esc(c.label) + ' ' + esc(c.k) + " | " +
'' + c.n + ' | ' + esc(c.base) + ' | ' + esc(c.a) + " | " + '' + esc(c.b) + " | " + '' + (diff > 0 ? "+" : "") + diff + " 题 |
" + esc(DT.categoryNote) + "
路由与生成的差距
' + '' + esc(DT.gap.note) + "
' +
esc(D.stage5.title) + " · " + esc(D.stage5.subtitle) +
'
出处 ' + esc(D.stage5.src) + "
' + esc(set.name) + " · " + set.n + " 题
| 题集 | 系统 | 正确率 | 原始 | 平均延迟 | 解码速度 | 未知拒答 |
|---|---|---|---|---|---|---|
| ' + 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) + "
| 指标 | 原 512 维 / 基线 | 128 维路由器 | 备注 |
|---|---|---|---|
| " + esc(m.k) + ' | ' + esc(m.base) + ' | ' + esc(m.nm2) + ' | ' + esc(m.note || "—") + " |
这张表必须连这些一起读
' + esc(c) + "
' + esc(title) + "
" + '' + esc(r.response || "(空)") + "
" + '" + (extra || "") + "命中的记忆记录
' + e.nm.records.map(function (r) { return '命中的记忆记录
' + '' + esc(e.query) + "
" + '期望锚点' + (e.expected ? esc(e.expected) + (e.expected_anchors && e.expected_anchors.length > 1 ? " · 其余:" + esc(e.expected_anchors.slice(1).join("、")) : "") : "无(未知题,考察拒答)") + "
" + '' + esc(x.d) + "
" + 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.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 '期望锚点' +
(it.ans ? "" + esc(it.exp) + "" : "无(未知题,考察拒答)") + "
' + esc(it.reply || "(空)") + "
" + '" + "当前筛选下没有记录。
'; } 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); } } })();