feat: publish long-context deep dive
This commit is contained in:
@@ -0,0 +1,981 @@
|
||||
---
|
||||
const strategies = [
|
||||
{
|
||||
id: "mha",
|
||||
label: "Full MHA",
|
||||
kicker: "全连接 · 全缓存",
|
||||
summary: "每个 Query 精确比较全部历史 Token;每层为每个历史 Token 保存所有 KV 头。",
|
||||
solves: "表达力基线",
|
||||
leaves: "二次计算 + 最宽 KV",
|
||||
},
|
||||
{
|
||||
id: "flash",
|
||||
label: "Flash",
|
||||
kicker: "全连接 · IO 优化",
|
||||
summary: "连接关系与 Full MHA 完全相同,只是不再把完整注意力矩阵写进 HBM。",
|
||||
solves: "显存读写与中间矩阵",
|
||||
leaves: "理论 FLOPs 仍为二次",
|
||||
},
|
||||
{
|
||||
id: "gqa",
|
||||
label: "GQA",
|
||||
kicker: "全连接 · 共享 KV",
|
||||
summary: "Query 头仍可很多,但一组 Query 共享一组 K/V;历史条目不减少,缓存宽度变窄。",
|
||||
solves: "KV 头数",
|
||||
leaves: "序列仍逐 Token 增长",
|
||||
},
|
||||
{
|
||||
id: "mla",
|
||||
label: "MLA",
|
||||
kicker: "全连接 · 潜变量 KV",
|
||||
summary: "每个历史 Token 只缓存低维联合 latent;通过权重吸收避免在解码时展开完整多头 K/V。",
|
||||
solves: "每 Token KV 宽度",
|
||||
leaves: "全局两两计算仍在",
|
||||
},
|
||||
{
|
||||
id: "dsa",
|
||||
label: "DSA",
|
||||
kicker: "索引 · Top-k 稀疏",
|
||||
summary: "轻量 Indexer 从全部 latent KV 中选出少量候选,再让主注意力只读这些候选。",
|
||||
solves: "主注意力连接数",
|
||||
leaves: "仍需索引和保存历史 latent",
|
||||
},
|
||||
{
|
||||
id: "kda",
|
||||
label: "KDA",
|
||||
kicker: "递推 · 固定状态",
|
||||
summary: "历史被持续写入固定矩阵状态;Delta Rule 擦除旧关联,通道 gate 控制遗忘。",
|
||||
solves: "长度相关 KV 与二次配对",
|
||||
leaves: "有限状态容量",
|
||||
},
|
||||
{
|
||||
id: "k3",
|
||||
label: "K3 Hybrid",
|
||||
kicker: "3×KDA + 1×MLA",
|
||||
summary: "三层用固定状态做廉价混合,每四层用一次 NoPE MLA 重新获得全局内容寻址。",
|
||||
solves: "效率与全局表达折中",
|
||||
leaves: "MLA 层仍有增长缓存",
|
||||
},
|
||||
{
|
||||
id: "v4",
|
||||
label: "V4 Hybrid",
|
||||
kicker: "CSA ↔ HCA",
|
||||
summary: "CSA 先 4:1 压缩再 Top-k;HCA 128:1 重压缩后读全部,并都保留局部滑窗。",
|
||||
solves: "序列维缓存与连接数",
|
||||
leaves: "压缩有损且系统复杂",
|
||||
},
|
||||
];
|
||||
|
||||
const size = 20;
|
||||
const matrix = Array.from({ length: size * size }, (_, index) => ({
|
||||
row: Math.floor(index / size),
|
||||
col: index % size,
|
||||
}));
|
||||
|
||||
const contexts = [
|
||||
{ label: "4K", value: 4096 },
|
||||
{ label: "32K", value: 32768 },
|
||||
{ label: "128K", value: 131072 },
|
||||
{ label: "1M", value: 1048576 },
|
||||
];
|
||||
---
|
||||
|
||||
<section class="context-lab" data-context-lab>
|
||||
<div class="lab-head">
|
||||
<div>
|
||||
<p class="lab-kicker">INTERACTIVE / ATTENTION STRATEGY LAB</p>
|
||||
<h3>“支持长上下文”到底改了哪一笔账?</h3>
|
||||
</div>
|
||||
<p>
|
||||
上半区看信息连接,下半区看缓存。切换方法时,注意“连接变少”和“缓存变窄”不是一回事。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="strategy-tabs" role="tablist" aria-label="选择注意力策略">
|
||||
{strategies.map((strategy, index) => (
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
data-strategy-button={strategy.id}
|
||||
aria-selected={index === 0 ? "true" : "false"}
|
||||
>
|
||||
<b>{strategy.label}</b>
|
||||
<span>{strategy.kicker}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="lab-stage">
|
||||
<div class="pattern-panel">
|
||||
<div class="panel-label">
|
||||
<span>01 / INFORMATION ACCESS</span>
|
||||
<b id="pattern-title">FULL MHA · 因果全连接</b>
|
||||
</div>
|
||||
|
||||
<div class="matrix-wrap">
|
||||
<div class="matrix-axis y"><span>QUERY</span></div>
|
||||
<div class="attention-matrix" aria-label="简化的因果注意力连接矩阵">
|
||||
{matrix.map(({ row, col }) => (
|
||||
<i data-cell data-row={row} data-col={col} aria-hidden="true"></i>
|
||||
))}
|
||||
<div class="state-memory" data-state-memory>
|
||||
<span>FIXED STATE</span>
|
||||
<b>S<sub>t</sub></b>
|
||||
<small>历史被压进固定矩阵,不再保留逐 Token 地址</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="matrix-axis x"><span>HISTORICAL KEY / VALUE</span></div>
|
||||
</div>
|
||||
|
||||
<label class="query-control">
|
||||
<span>观察第几个 Query</span>
|
||||
<input data-query type="range" min="0" max={size - 1} value={size - 1} />
|
||||
<output data-query-output>{size}</output>
|
||||
</label>
|
||||
|
||||
<div class="pattern-legend">
|
||||
<div><i class="strong"></i><span>主算子直接读取</span></div>
|
||||
<div><i class="soft"></i><span>压缩/全局补充路径</span></div>
|
||||
<div><i class="local"></i><span>局部窗口</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="strategy-story">
|
||||
{strategies.map((strategy, index) => (
|
||||
<article data-strategy-story={strategy.id} hidden={index !== 0}>
|
||||
<span>{strategy.kicker}</span>
|
||||
<h3>{strategy.label}</h3>
|
||||
<p>{strategy.summary}</p>
|
||||
<dl>
|
||||
<div><dt>主要解决</dt><dd>{strategy.solves}</dd></div>
|
||||
<div><dt>仍然留下</dt><dd>{strategy.leaves}</dd></div>
|
||||
</dl>
|
||||
</article>
|
||||
))}
|
||||
<div class="matrix-note">
|
||||
<b>怎样读这张图</b>
|
||||
<p>
|
||||
横轴是可被读取的历史,纵轴是当前 Query。图只画 20 个位置,展示的是连接模式,不代表论文真实头数或窗口大小。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="budget-panel">
|
||||
<div class="budget-controls">
|
||||
<div>
|
||||
<p class="panel-kicker">02 / CACHE BUDGET</p>
|
||||
<h3>把上下文拖到一百万 Token</h3>
|
||||
<p>
|
||||
统一教学模型:64 层、64 个 Query 头、head dim 128、BF16、GQA 8 个 KV 头、MLA latent 576。
|
||||
数字用于比较增长规律,不是任何具体模型的线上显存报告。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="context-control">
|
||||
<div class="context-readout">
|
||||
<span>CONTEXT LENGTH</span>
|
||||
<strong data-context-label>4K</strong>
|
||||
<small data-context-exact>4,096 tokens</small>
|
||||
</div>
|
||||
<input data-context type="range" min="0" max={contexts.length - 1} value="0" step="1" />
|
||||
<div class="range-labels">
|
||||
{contexts.map((context) => <span>{context.label}</span>)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="budget-summary">
|
||||
<article>
|
||||
<span>当前策略估算缓存</span>
|
||||
<b data-cache-value>8.00 GB</b>
|
||||
<small data-cache-note>逐 Token、逐层、全头 K/V</small>
|
||||
</article>
|
||||
<article>
|
||||
<span>每 Query 直接读取</span>
|
||||
<b data-access-value>4,096</b>
|
||||
<small data-access-note>全部历史位置</small>
|
||||
</article>
|
||||
<article>
|
||||
<span>随长度增长</span>
|
||||
<b data-growth-value>线性 KV</b>
|
||||
<small data-growth-note>注意力计算仍是二次</small>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="budget-bars" aria-label="不同注意力机制的教学缓存估算">
|
||||
{strategies.map((strategy) => (
|
||||
<div data-budget-row={strategy.id}>
|
||||
<span>{strategy.label}</span>
|
||||
<div><i data-budget-bar={strategy.id}></i></div>
|
||||
<b data-budget-value={strategy.id}>—</b>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="budget-caveat">
|
||||
<span>ESTIMATE, NOT BENCHMARK</span>
|
||||
<p>
|
||||
KDA 行只计算固定递推状态;K3 行按 3:1 层比叠加 KDA 状态与 MLA latent;
|
||||
V4 行用 1:1 CSA/HCA、4×/128×压缩和 128 局部窗口做结构估算,未计 Indexer、未压缩尾部、分页和框架开销。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script is:inline define:vars={{ contexts }}>
|
||||
const root = document.querySelector("[data-context-lab]");
|
||||
if (root) {
|
||||
const buttons = [...root.querySelectorAll("[data-strategy-button]")];
|
||||
const stories = [...root.querySelectorAll("[data-strategy-story]")];
|
||||
const cells = [...root.querySelectorAll("[data-cell]")];
|
||||
const queryInput = root.querySelector("[data-query]");
|
||||
const queryOutput = root.querySelector("[data-query-output]");
|
||||
const contextInput = root.querySelector("[data-context]");
|
||||
const stateMemory = root.querySelector("[data-state-memory]");
|
||||
let active = "mha";
|
||||
|
||||
const assumptions = {
|
||||
layers: 64,
|
||||
heads: 64,
|
||||
kvHeads: 8,
|
||||
headDim: 128,
|
||||
latent: 576,
|
||||
bytes: 2,
|
||||
};
|
||||
|
||||
const formatBytes = (bytes) => {
|
||||
const units = ["B", "KB", "MB", "GB", "TB"];
|
||||
let value = bytes;
|
||||
let unit = 0;
|
||||
while (value >= 1024 && unit < units.length - 1) {
|
||||
value /= 1024;
|
||||
unit += 1;
|
||||
}
|
||||
const digits = value >= 100 ? 0 : value >= 10 ? 1 : 2;
|
||||
return `${value.toFixed(digits)} ${units[unit]}`;
|
||||
};
|
||||
|
||||
const formatCount = (value) => new Intl.NumberFormat("zh-CN").format(Math.round(value));
|
||||
|
||||
const cacheFor = (id, length) => {
|
||||
const { layers, heads, kvHeads, headDim, latent, bytes } = assumptions;
|
||||
const mha = 2 * length * layers * heads * headDim * bytes;
|
||||
if (id === "mha" || id === "flash") return mha;
|
||||
if (id === "gqa") return 2 * length * layers * kvHeads * headDim * bytes;
|
||||
if (id === "mla" || id === "dsa") return length * layers * latent * bytes;
|
||||
if (id === "kda") return layers * heads * headDim * headDim * bytes;
|
||||
if (id === "k3") {
|
||||
const kdaLayers = Math.round(layers * 0.75);
|
||||
const mlaLayers = layers - kdaLayers;
|
||||
const state = kdaLayers * heads * headDim * headDim * bytes;
|
||||
const mlaCache = length * mlaLayers * latent * bytes;
|
||||
return state + mlaCache;
|
||||
}
|
||||
if (id === "v4") {
|
||||
const csaLayers = layers / 2;
|
||||
const hcaLayers = layers / 2;
|
||||
const window = Math.min(length, 128);
|
||||
const csaEntries = Math.ceil(length / 4) + window;
|
||||
const hcaEntries = Math.ceil(length / 128) + window;
|
||||
return (csaLayers * csaEntries + hcaLayers * hcaEntries) * headDim * bytes;
|
||||
}
|
||||
return mha;
|
||||
};
|
||||
|
||||
const accessFor = (id, length) => {
|
||||
if (["mha", "flash", "gqa", "mla"].includes(id)) {
|
||||
return { value: formatCount(length), note: "全部历史位置" };
|
||||
}
|
||||
if (id === "dsa") {
|
||||
return { value: formatCount(Math.min(length, 2048)), note: "主注意力 Top-k;另有轻量索引" };
|
||||
}
|
||||
if (id === "kda") {
|
||||
return { value: "固定状态", note: "不再逐 Token 内容寻址" };
|
||||
}
|
||||
if (id === "k3") {
|
||||
return { value: "3×状态 + 1×全局", note: "沿深度周期性交替" };
|
||||
}
|
||||
const csa = Math.min(Math.ceil(length / 4), 1024) + Math.min(length, 128);
|
||||
const hca = Math.ceil(length / 128) + Math.min(length, 128);
|
||||
return { value: `${formatCount(csa)} / ${formatCount(hca)}`, note: "CSA / HCA 结构估算" };
|
||||
};
|
||||
|
||||
const metaFor = (id) => {
|
||||
const meta = {
|
||||
mha: ["逐 Token、逐层、全头 K/V", "线性 KV", "注意力计算为二次"],
|
||||
flash: ["缓存同 Full MHA;省的是中间矩阵", "线性 KV", "FLOPs 仍二次,HBM IO 更少"],
|
||||
gqa: ["逐 Token、逐层、8 组 KV", "线性薄 KV", "连接数仍是全局"],
|
||||
mla: ["逐 Token、逐层、576 维 latent", "线性 latent", "权重吸收不等于稀疏"],
|
||||
dsa: ["保存全部 latent,主 attention 只读 Top-k", "线性 latent", "主连接约 O(Lk)"],
|
||||
kda: ["每层每头一个 128×128 状态", "固定状态", "容量不随 L 增长"],
|
||||
k3: ["3/4 固定状态 + 1/4 latent KV", "混合增长", "全局层缓存仍随 L 增长"],
|
||||
v4: ["压缩 KV + 128 Token 局部窗口", "压缩线性", "CSA 稀疏,HCA 重压缩"],
|
||||
};
|
||||
return meta[id];
|
||||
};
|
||||
|
||||
const updateMatrix = () => {
|
||||
const query = Number(queryInput?.value ?? 19);
|
||||
if (queryOutput) queryOutput.textContent = String(query + 1);
|
||||
stateMemory?.toggleAttribute("data-visible", active === "kda" || active === "k3");
|
||||
|
||||
cells.forEach((cell) => {
|
||||
const row = Number(cell.dataset.row);
|
||||
const col = Number(cell.dataset.col);
|
||||
const causal = col <= row;
|
||||
const current = row === query;
|
||||
let strength = "off";
|
||||
|
||||
if (causal && ["mha", "flash", "gqa", "mla"].includes(active)) strength = "strong";
|
||||
if (causal && active === "dsa") {
|
||||
const local = row - col <= 3;
|
||||
const indexed = col === 0 || (col + row) % 5 === 1;
|
||||
strength = local ? "local" : indexed ? "strong" : "off";
|
||||
}
|
||||
if (causal && active === "kda") strength = "state";
|
||||
if (causal && active === "k3") {
|
||||
const local = row - col <= 2;
|
||||
strength = local ? "local" : "soft";
|
||||
}
|
||||
if (causal && active === "v4") {
|
||||
const local = row - col <= 3;
|
||||
const compressed = col % 4 === 0 || col === 0;
|
||||
strength = local ? "local" : compressed ? "strong" : "soft";
|
||||
}
|
||||
|
||||
cell.dataset.strength = strength;
|
||||
cell.toggleAttribute("data-query-row", current);
|
||||
});
|
||||
|
||||
const titles = {
|
||||
mha: "FULL MHA · 因果全连接",
|
||||
flash: "FLASH · 连接不变,只改变 IO",
|
||||
gqa: "GQA · 全连接,共享 K/V",
|
||||
mla: "MLA · 全连接,缓存潜变量",
|
||||
dsa: "DSA · Indexer 选择稀疏历史",
|
||||
kda: "KDA · 读取固定递推状态",
|
||||
k3: "K3 · 固定状态与全局层交替",
|
||||
v4: "V4 · 压缩、稀疏与局部窗口",
|
||||
};
|
||||
const title = root.querySelector("#pattern-title");
|
||||
if (title) title.textContent = titles[active];
|
||||
};
|
||||
|
||||
const updateBudget = () => {
|
||||
const contextIndex = Number(contextInput?.value ?? 0);
|
||||
const selected = contexts[contextIndex];
|
||||
const length = selected.value;
|
||||
const mhaCache = cacheFor("mha", length);
|
||||
|
||||
root.querySelector("[data-context-label]").textContent = selected.label;
|
||||
root.querySelector("[data-context-exact]").textContent = `${formatCount(length)} tokens`;
|
||||
|
||||
const currentCache = cacheFor(active, length);
|
||||
root.querySelector("[data-cache-value]").textContent = formatBytes(currentCache);
|
||||
const access = accessFor(active, length);
|
||||
root.querySelector("[data-access-value]").textContent = access.value;
|
||||
root.querySelector("[data-access-note]").textContent = access.note;
|
||||
|
||||
const [cacheNote, growth, growthNote] = metaFor(active);
|
||||
root.querySelector("[data-cache-note]").textContent = cacheNote;
|
||||
root.querySelector("[data-growth-value]").textContent = growth;
|
||||
root.querySelector("[data-growth-note]").textContent = growthNote;
|
||||
|
||||
buttons.forEach((button) => {
|
||||
const id = button.dataset.strategyButton;
|
||||
const bytes = cacheFor(id, length);
|
||||
const ratio = Math.max(0.012, Math.min(1, bytes / mhaCache));
|
||||
const bar = root.querySelector(`[data-budget-bar="${id}"]`);
|
||||
const value = root.querySelector(`[data-budget-value="${id}"]`);
|
||||
if (bar) bar.style.width = `${ratio * 100}%`;
|
||||
if (value) value.textContent = formatBytes(bytes);
|
||||
root.querySelector(`[data-budget-row="${id}"]`)?.toggleAttribute("data-active", id === active);
|
||||
});
|
||||
};
|
||||
|
||||
const select = (id) => {
|
||||
active = id;
|
||||
buttons.forEach((button) => button.setAttribute("aria-selected", String(button.dataset.strategyButton === id)));
|
||||
stories.forEach((story) => {
|
||||
story.hidden = story.dataset.strategyStory !== id;
|
||||
});
|
||||
updateMatrix();
|
||||
updateBudget();
|
||||
};
|
||||
|
||||
buttons.forEach((button) => button.addEventListener("click", () => select(button.dataset.strategyButton)));
|
||||
queryInput?.addEventListener("input", updateMatrix);
|
||||
contextInput?.addEventListener("input", updateBudget);
|
||||
select(active);
|
||||
}
|
||||
</script>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.context-lab {
|
||||
margin-block: 56px;
|
||||
border: 1px solid var(--line-strong);
|
||||
background: var(--paper-raised);
|
||||
}
|
||||
|
||||
.lab-head {
|
||||
display: grid;
|
||||
grid-template-columns: 1.25fr 0.75fr;
|
||||
gap: 60px;
|
||||
align-items: end;
|
||||
padding: clamp(28px, 4vw, 52px);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.lab-kicker,
|
||||
.panel-kicker {
|
||||
color: var(--copper);
|
||||
font: 0.62rem/1 var(--mono);
|
||||
letter-spacing: 0.13em;
|
||||
}
|
||||
|
||||
.lab-head h3 {
|
||||
margin-top: 15px;
|
||||
font-size: clamp(1.5rem, 2.5vw, 2.5rem);
|
||||
}
|
||||
|
||||
.lab-head > p {
|
||||
color: var(--muted);
|
||||
font-family: var(--serif);
|
||||
font-size: 0.96rem;
|
||||
}
|
||||
|
||||
.strategy-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.strategy-tabs button {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
min-height: 78px;
|
||||
padding: 16px 12px;
|
||||
border: 0;
|
||||
border-right: 1px solid var(--line);
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.strategy-tabs button:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.strategy-tabs button:hover,
|
||||
.strategy-tabs button[aria-selected="true"] {
|
||||
background: var(--ink);
|
||||
color: var(--paper-raised);
|
||||
}
|
||||
|
||||
.strategy-tabs b {
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.strategy-tabs span {
|
||||
font-size: 0.58rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.lab-stage {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.55fr) minmax(260px, 0.45fr);
|
||||
}
|
||||
|
||||
.pattern-panel {
|
||||
padding: clamp(26px, 4vw, 48px);
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.panel-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.panel-label span {
|
||||
color: var(--muted);
|
||||
font: 0.58rem/1 var(--mono);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.panel-label b {
|
||||
font: 0.68rem/1 var(--mono);
|
||||
}
|
||||
|
||||
.matrix-wrap {
|
||||
display: grid;
|
||||
grid-template-columns: 25px minmax(0, 560px);
|
||||
grid-template-rows: auto 25px;
|
||||
gap: 9px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.attention-matrix {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(20, 1fr);
|
||||
grid-template-rows: repeat(20, 1fr);
|
||||
width: min(100%, 560px);
|
||||
aspect-ratio: 1;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--line-strong);
|
||||
background: var(--paper);
|
||||
}
|
||||
|
||||
[data-cell] {
|
||||
margin: 1px;
|
||||
border-radius: 1px;
|
||||
background: rgba(39, 54, 74, 0.035);
|
||||
transition: background 150ms ease, opacity 150ms ease, transform 150ms ease;
|
||||
}
|
||||
|
||||
[data-cell][data-strength="strong"] {
|
||||
background: var(--ink);
|
||||
opacity: 0.52;
|
||||
}
|
||||
|
||||
[data-cell][data-strength="soft"] {
|
||||
background: var(--violet);
|
||||
opacity: 0.18;
|
||||
}
|
||||
|
||||
[data-cell][data-strength="local"] {
|
||||
background: var(--copper);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
[data-cell][data-strength="state"] {
|
||||
background: var(--sage);
|
||||
opacity: 0.08;
|
||||
}
|
||||
|
||||
[data-cell][data-query-row] {
|
||||
transform: scale(0.82);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.state-memory {
|
||||
position: absolute;
|
||||
inset: 23% 16%;
|
||||
display: none;
|
||||
place-content: center;
|
||||
padding: 22px;
|
||||
border: 1px solid rgba(85, 122, 114, 0.46);
|
||||
background: color-mix(in srgb, var(--sage-pale) 92%, transparent);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.state-memory[data-visible] {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.state-memory span {
|
||||
color: var(--sage);
|
||||
font: 0.56rem/1 var(--mono);
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
.state-memory b {
|
||||
margin-top: 12px;
|
||||
font-family: var(--serif);
|
||||
font-size: clamp(2rem, 5vw, 4.5rem);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.state-memory small {
|
||||
max-width: 260px;
|
||||
margin-top: 12px;
|
||||
color: var(--muted);
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.matrix-axis {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--muted-light);
|
||||
font: 0.5rem/1 var(--mono);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.matrix-axis.y span {
|
||||
writing-mode: vertical-rl;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.matrix-axis.x {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.query-control {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr 30px;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
max-width: 595px;
|
||||
margin: 24px auto 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.query-control input,
|
||||
.context-control input {
|
||||
width: 100%;
|
||||
accent-color: var(--copper);
|
||||
}
|
||||
|
||||
.query-control output {
|
||||
font: 0.7rem/1 var(--mono);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pattern-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.pattern-legend div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
color: var(--muted);
|
||||
font-size: 0.62rem;
|
||||
}
|
||||
|
||||
.pattern-legend i {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.pattern-legend .strong { background: var(--ink); opacity: 0.55; }
|
||||
.pattern-legend .soft { background: var(--violet); opacity: 0.24; }
|
||||
.pattern-legend .local { background: var(--copper); opacity: 0.7; }
|
||||
|
||||
.strategy-story {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: clamp(28px, 4vw, 46px);
|
||||
background: var(--paper-deep);
|
||||
}
|
||||
|
||||
.strategy-story article > span {
|
||||
color: var(--copper);
|
||||
font: 0.6rem/1 var(--mono);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.strategy-story article h3 {
|
||||
margin-top: 18px;
|
||||
font-family: var(--serif);
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.strategy-story article p {
|
||||
margin-top: 18px;
|
||||
color: var(--muted);
|
||||
font-family: var(--serif);
|
||||
font-size: 0.93rem;
|
||||
}
|
||||
|
||||
.strategy-story dl {
|
||||
margin: 28px 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.strategy-story dl div {
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.strategy-story dt {
|
||||
color: var(--muted);
|
||||
font: 0.58rem/1 var(--mono);
|
||||
}
|
||||
|
||||
.strategy-story dd {
|
||||
margin: 7px 0 0;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.matrix-note {
|
||||
margin-top: 44px;
|
||||
padding-top: 22px;
|
||||
border-top: 1px solid var(--line-strong);
|
||||
}
|
||||
|
||||
.matrix-note b {
|
||||
font-size: 0.73rem;
|
||||
}
|
||||
|
||||
.matrix-note p {
|
||||
margin-top: 8px;
|
||||
color: var(--muted);
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
|
||||
.budget-panel {
|
||||
border-top: 1px solid var(--line-strong);
|
||||
}
|
||||
|
||||
.budget-controls {
|
||||
display: grid;
|
||||
grid-template-columns: 1.1fr 0.9fr;
|
||||
gap: 60px;
|
||||
align-items: end;
|
||||
padding: clamp(30px, 5vw, 60px);
|
||||
}
|
||||
|
||||
.budget-controls h3 {
|
||||
margin-top: 15px;
|
||||
font-size: clamp(1.5rem, 2.5vw, 2.35rem);
|
||||
}
|
||||
|
||||
.budget-controls > div:first-child > p:last-child {
|
||||
max-width: 680px;
|
||||
margin-top: 16px;
|
||||
color: var(--muted);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.context-readout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
align-items: baseline;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--line-strong);
|
||||
}
|
||||
|
||||
.context-readout span {
|
||||
color: var(--muted);
|
||||
font: 0.58rem/1 var(--mono);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.context-readout strong {
|
||||
font: 500 2.2rem/1 var(--serif);
|
||||
}
|
||||
|
||||
.context-readout small {
|
||||
grid-column: 1 / -1;
|
||||
margin-top: 5px;
|
||||
color: var(--muted);
|
||||
font-size: 0.64rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.context-control input {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.range-labels {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: var(--muted);
|
||||
font: 0.56rem/1 var(--mono);
|
||||
}
|
||||
|
||||
.budget-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
border-block: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.budget-summary article {
|
||||
min-height: 150px;
|
||||
padding: 27px clamp(22px, 3vw, 40px);
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.budget-summary article:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.budget-summary span {
|
||||
color: var(--muted);
|
||||
font: 0.58rem/1 var(--mono);
|
||||
}
|
||||
|
||||
.budget-summary b {
|
||||
display: block;
|
||||
margin-top: 22px;
|
||||
font-family: var(--serif);
|
||||
font-size: clamp(1.45rem, 2.3vw, 2.1rem);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.budget-summary small {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: var(--muted);
|
||||
font-size: 0.64rem;
|
||||
}
|
||||
|
||||
.budget-bars {
|
||||
padding: 34px clamp(24px, 5vw, 60px);
|
||||
}
|
||||
|
||||
.budget-bars > div {
|
||||
display: grid;
|
||||
grid-template-columns: 110px 1fr 92px;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
min-height: 36px;
|
||||
padding-inline: 8px;
|
||||
}
|
||||
|
||||
.budget-bars > div[data-active] {
|
||||
background: var(--paper-deep);
|
||||
}
|
||||
|
||||
.budget-bars span,
|
||||
.budget-bars b {
|
||||
font-size: 0.67rem;
|
||||
}
|
||||
|
||||
.budget-bars b {
|
||||
font-family: var(--mono);
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.budget-bars div > div {
|
||||
height: 7px;
|
||||
background: var(--paper-deep);
|
||||
}
|
||||
|
||||
.budget-bars i {
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
background: var(--sage);
|
||||
transition: width 260ms ease;
|
||||
}
|
||||
|
||||
.budget-bars [data-active] i {
|
||||
background: var(--copper);
|
||||
}
|
||||
|
||||
.budget-caveat {
|
||||
display: grid;
|
||||
grid-template-columns: 190px 1fr;
|
||||
gap: 34px;
|
||||
padding: 24px clamp(24px, 5vw, 60px);
|
||||
border-top: 1px solid var(--line);
|
||||
background: var(--ink);
|
||||
color: var(--paper-raised);
|
||||
}
|
||||
|
||||
.budget-caveat span {
|
||||
color: var(--copper-pale);
|
||||
font: 0.58rem/1.4 var(--mono);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.budget-caveat p {
|
||||
color: rgba(250, 248, 243, 0.72);
|
||||
font-size: 0.67rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.strategy-tabs {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
.strategy-tabs button:nth-child(4) {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.strategy-tabs button:nth-child(-n + 4) {
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.lab-stage,
|
||||
.budget-controls {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.pattern-panel {
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 680px) {
|
||||
.lab-head {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.strategy-tabs {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.strategy-tabs button:nth-child(2n) {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.strategy-tabs button:nth-child(n) {
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.panel-label {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pattern-panel {
|
||||
padding-inline: 16px;
|
||||
}
|
||||
|
||||
.attention-matrix {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
[data-cell] {
|
||||
margin: 0.5px;
|
||||
}
|
||||
|
||||
.query-control {
|
||||
grid-template-columns: 1fr 30px;
|
||||
}
|
||||
|
||||
.query-control span {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.budget-summary {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.budget-summary article {
|
||||
min-height: 130px;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.budget-bars > div {
|
||||
grid-template-columns: 82px 1fr 72px;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.budget-caveat {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,6 +5,7 @@
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<a href="/roadmap/">学习地图</a>
|
||||
<a href="/long-context/">长上下文专题</a>
|
||||
<a href="/progress/">研究进度</a>
|
||||
<a href="https://git.k1412.top/wuyang/llm-atlas" rel="noreferrer">开放源码</a>
|
||||
<a href="https://github.com/MoonshotAI/Kimi-K3" rel="noreferrer">K3 官方报告</a>
|
||||
|
||||
@@ -10,6 +10,7 @@ const items = [
|
||||
{ id: "k3", href: "/k3/", label: "K3 解剖" },
|
||||
{ id: "deepseek", href: "/deepseek/", label: "DeepSeek" },
|
||||
{ id: "foundations", href: "/foundations/", label: "基础原理" },
|
||||
{ id: "long-context", href: "/long-context/", label: "长上下文" },
|
||||
{ id: "papers", href: "/papers/", label: "论文库" },
|
||||
{ id: "progress", href: "/progress/", label: "进度" },
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user