supertensor: shape-aware tensor figure toolkit

Extracted from the tensor-formula-viz skill and rebuilt around the idea that
the geometry rules should be enforced by construction rather than restated as
prose an agent has to remember.

- assets/supertensor.sty: faces, stacks, index faces, shared caption lanes,
  meaning box, signature. Macros take a declared axis and a declared role, so
  equal shapes get equal edges, a x a is square, a transpose swaps the face,
  and contracted axes share an edge length -- without any manual alignment.
- scripts/preflight.sh: decide the TikZ/CJK path before drawing.
- scripts/build.sh: compile and fail on silent corruption (missing CJK glyphs,
  overfull boxes, undeclared roles), then export pdf/svg/png/thumb.
- scripts/test.sh: build every figure as a regression test for the package.
- examples/: three golden figures (TP-FFN, causal MHA, MoE top-k gather) plus
  an anti-pattern gallery of figures that compile cleanly and still lie.
- SKILL.md + references/: lean entry point, details loaded on demand.
This commit is contained in:
dela
2026-08-05 12:17:33 +08:00
commit 7a22bef9e3
20 changed files with 1661 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
% Golden example 2 -- causal multi-head attention.
% Shows: leading axes as stack depth, a transpose that physically swaps the
% face, equal edge length on the contracted axis, and a Boolean mask drawn in
% a different grammar from the scores it gates.
% ../scripts/build.sh mha-causal.tex
\documentclass[border=10pt]{standalone}
\usepackage[cjk]{supertensor}
\stsetrole{q}{stTeal}
\stsetrole{k}{stOrange}
\stsetrole{v}{stViolet}
\stsetrole{s}{stCoral}
\stsetrole{w}{stGray}
\stdim{T}{6}
\stdim{dh}{3}
\stdim{d}{9} % d = h * d_h, h = 3
\begin{document}
\begin{tikzpicture}
% ================================================================= formula ==
\node (F) at (0,0) {\stformula{$\displaystyle
\mathbf A^{(i)}=\mathrm{softmax}\!\left(
\frac{\mathbf Q^{(i)}\mathbf K^{(i)\top}}{\sqrt{d_h}}+\mathbf M\right),\qquad
\mathbf O^{(i)}=\mathbf A^{(i)}\mathbf V^{(i)}$}};
% ============================================================ stage A row ===
\node[st stage, below=7mm of F] (SA) {每头打分:沿 $d_h$ 收缩};
\coordinate (a) at ($(SA)+(-3.9,-1.9)$);
\ststack[role=q, bracket=true]{Q}{(a)}{T}{dh}{3}
\node[st op, right=6mm of Q] (mA) {$\times$};
% K^T: the face is physically swapped, not relabelled. Its height equals Q's
% width -- that is the contracted axis d_h, drawn at one edge length.
\ststack[role=k, bracket=true]{KT}{($(mA)+(1.9,0)$)}{dh}{T}{3}
\node[st op, right=6mm of KT] (eA) {$=$};
\ststack[role=s]{S}{($(eA)+(2.0,0)$)}{T}{T}{3}
\node[inner sep=0pt, fit=(Q)(KT)(S)] (rowA) {};
\stlane{rowA}
\stcaption{Q}{$\mathbf Q^{(i)}$}{$h\times T\times d_h$}
\stcaption{KT}{$\mathbf K^{(i)\top}$}{$h\times d_h\times T$}
\stcaption{S}{$\mathbf S^{(i)}$}{$h\times T\times T$}
\stnolane
% ============================================================ stage B row ===
\node[st stage, below=9mm of Q-shape.south west, anchor=north west] (SB)
{因果掩码与加权求和};
\coordinate (b) at ($(SB)+(0.6,-2.0)$);
% The mask is a Boolean support, not a magnitude: one flat level, exact
% triangle, no stack -- it is shared by every head.
\stface[role=w, pattern=data,
data={300000,330000,333000,333300,333330,333333}]{M}{(b)}{T}{T}
\ststack[role=s, pattern=causal]{A}{($(M.east)+(3.75,0)$)}{T}{T}{3}
\starrowlabel{M.east}{A.west}{softmax}
\node[st op, right=6mm of A] (mB) {$\times$};
\ststack[role=v, bracket=true]{V}{($(mB)+(1.4,0)$)}{T}{dh}{3}
\node[st op, right=6mm of V] (eB) {$=$};
\ststack[role=v]{O}{($(eB)+(1.4,0)$)}{T}{dh}{3}
\node[inner sep=0pt, fit=(M)(A)(V)(O)] (rowB) {};
\stlane{rowB}
\stcaption{M}{$\mathbf M$}{$T\times T$}
\stcaption{A}{$\mathbf A^{(i)}$}{$h\times T\times T$}
\stcaption{V}{$\mathbf V^{(i)}$}{$h\times T\times d_h$}
\stcaption{O}{$\mathbf O^{(i)}$}{$h\times T\times d_h$}
\stnolane
% ============================================================ stage C row ===
\node[st stage, below=9mm of M-shape.south west, anchor=north west] (SC)
{沿 $d_h$ 拼接后投影};
\coordinate (c) at ($(SC)+(1.2,-2.0)$);
% Concatenation reverses the split: three h-shards of width d_h tile a face of
% width d exactly.
\stface[role=v]{C1}{(c)}{T}{dh}
\stface[role=v]{C2}{($(C1.east)+(1.5*\stunit,0)$)}{T}{dh}
\stface[role=v]{C3}{($(C2.east)+(1.5*\stunit,0)$)}{T}{dh}
\node[st op, right=6mm of C3] (mC) {$\times$};
\stface[role=w]{WO}{($(mC)+(2.5,0)$)}{d}{d}
\node[st op, right=6mm of WO] (eC) {$=$};
\stface[role=v, bracket=true]{Y}{($(eC)+(2.5,0)$)}{T}{d}
\node[inner sep=0pt, fit=(C1)(WO)(Y)] (rowC) {};
\stlane{rowC}
\stcaption{C2}{$[\,\mathbf O^{(1)}\mid\mathbf O^{(2)}\mid\mathbf O^{(3)}\,]$}{$T\times d$}
\stcaption{WO}{$\mathbf W_O$}{$d\times d$}
\stcaption{Y}{$\mathbf Y$}{$T\times d$}
\stnolane
% ============================================================== meaning box ==
\node[inner sep=0pt, fit=(F)(rowA)(rowB)(rowC)(Y-shape)(C2-shape)] (all) {};
\stmeaningbox{mb}{16.8cm}{all}
{$T$ 序列长度,$d_h$ 单头宽度,$h$ 头数(图中 $h=3$,即堆叠的三张面),
$d=h\,d_h$;批轴 $B$ 省略}
{$\mathbf S,\mathbf A$ 是分数与概率(行和为 $1$);$\mathbf M\in\{0,-\infty\}^{T\times T}$
是布尔支撑而非数值,被所有头共享,故只画一张、不堆叠;紫色一族标记 $\mathbf V\rightarrow\mathbf O\rightarrow\mathbf Y$ 同一数据流}
{$(T\times d_h)(d_h\times T)\rightarrow(T\times T)$:$\mathbf K^{\top}$ 的面高即收缩维 $d_h$;
拼接是切分的逆运算,$3$ 个 $d_h$ 恰好铺满 $d$}
\stsignature{因果多头注意力(掩码 + 拼接投影)}{mb}
\end{tikzpicture}
\end{document}