Transformer 论文公式,把 Codex 的模型通道改到 TaoToken 后能逐行验证 📅 发布时间:2026/9/19 0:20:31 👁 浏览次数: 翻开《Attention Is All You Need》第 3.2 节的 Attention(Q,K,V)softmax(QK^T/√d_k)V真正动手复现时第一遍常卡在 Q、K、V 的形状上。这篇借 TaoToken 的兼容通道把这条路走一遍先到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建 YOUR_API_KEY再把 Codex 的 Base URL 填成 https://taotoken.net/api然后对着论文一节一节追问维度。Codex 不替你做推导它做的是把公式拆成可验证的小步骤Q 从哪来、K 的转置转哪两维、softmax 沿哪一轴归一化、位置编码里 2i 和 2i1 分别落在哪个下标。这些问完手里应该有一份能跑通的 numpy 片段和一份自己看得懂的推导笔记而不是一段照抄的代码。整条路径分三段先把第 3.2 节的矩阵运算逐维拆开再把 Codex 的模型通道换到统一接入最后回头核对第 3.5 节位置编码的三角函数。所有注册、创建 Key、查模型名和看用量的动作都放在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 这一侧完成不要和填进工具里的接口地址搞混——官网是给人点的接口地址是给程序填的两件事。1. 第 3.2 节的形状Q、K、V 各自多长1.1 缩放点积注意力的三个输入张量论文把注意力定义成 query 到一组 key-value 对的映射落到矩阵上就是三个张量Q 的形状是 (n, d_k)K 的形状是 (m, d_k)V 的形状是 (m, d_v)。Q 和 K 的最后一维必须一致因为要做点积K 和 V 的第一维必须一致因为它们本来就是配对给出的n 和 m 可以不相等这正是自注意力之外的交叉注意力能成立的原因。很多初学者第一次写成Q K然后被 numpy 报 “shapes not aligned”。原因很简单Q 是 (n, d_k)、K 是 (m, d_k)直接相乘要求 d_k m这和公式想要的完全不是一回事。公式里写的是 QK^T转置的是 K 的后两维在 batch 版本里就是最后两维转完形状变成 (d_k, m)再和 (n, d_k) 相乘才得到 (n, m) 的分数矩阵。分数矩阵拿到之后除以 √d_k。这里的 d_k 是每个头的 key 维度不是 d_model也不是序列长度。这个缩放项的作用是防止点积随维度变大而数值爆炸让 softmax 的梯度不至于缩到看不见。论文里写得很直白当 d_k 比较大时点积结果的方差会随 d_k 增长softmax 会被推向极端值。1.2 softmax 沿哪一轴归一化分数矩阵形状是 (n, m)n 是 query 的个数m 是 key 的个数。对每一行做 softmax也就是每个 query 对全部 key 的注意力权重加起来等于 1。这一步在代码里对应axis-1写成axis0就会得到完全错误的结果而且不会报形状错误只会让训练发散。后面乘 V 得到 (n, d_v)含义是每个 query 位置根据权重把 value 加权求和。到这里缩放点积注意力的形状链路就闭合了。1.3 多头里 h、d_k、d_v 与 d_model 的关系多头注意力在形状上多了一层。论文的做法是把 d_model 切成 h 份每份的 key 维度和 value 维度都是 d_model / h正文里明确写了 d_k d_v d_model / h 64。常见配置里 d_model 512、h 8。于是每个头单独走一遍上面那套流程得到 h 个 (n, d_v) 的结果。把这些结果在最后一维拼接得到 (n, h·d_v) (n, d_model)再乘上输出投影 W^O形状仍是 (n, d_model)。容易写错的地方有两个一是切分顺序应该沿 d_model 这一维按头切开而不是沿序列维度二是拼接顺序必须和切分顺序一致先把中间维度摆成 (batch, h, n, d_v) 再合并否则同一个头的 Q、K、V 会错配到别的头上去模型照样能跑但语义已经乱了。2. ~/.codex/config.toml 把 Codex 指到 TaoToken 兼容通道2.1 在模型广场拿一把 YOUR_API_KEY论文那部分先放着先把提问工具接好。用浏览器打开 TaoToken注册登录进控制台创建一把 API Key复制出来保管好。Key 在页面之外没有任何地方能重新看全丢了就再建一把。顺手在模型广场记下这次要用的模型 ID后面 config.toml 里要原样填进去具体可用列表以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 上当时展示的为准不要凭印象拼一个带日期后缀的名字。2.2 config.toml 的最小可用配置Codex 走的是自己的配置文件路径在~/.codex/config.toml。下面这份是可以直接改的写法把 model 换成自己在模型广场看到的 IDbase_url 保持 https://taotoken.net/api 末尾不要加 /v1# ~/.codex/config.toml model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat再把 Key 放进环境变量不要直接写进配置文件# macOS / Linux export TAOTOKEN_API_KEYYOUR_API_KEY# Windows PowerShell setx TAOTOKEN_API_KEY YOUR_API_KEY注意这里用的是 Codex 自己的键名和字段不要把 Claude Code 的ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN套过来两套配置不通用套错了会一直报鉴权失败。2.3 模型 ID 从模型广场现查模型 ID 是这套配置里最容易过期的一项。同一家服务不同时间上架的产品不一样写死一个记忆里的名字过一阵可能就 404。养成习惯每次换模型先去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的模型广场看一眼当前列表复制出来再填。填错了不会静默降级通常会直接返回模型不存在。3. 对着论文逐行问从 QK^T 到位置编码3.1 先问形状再问语义配好通道之后把论文里那段矩阵乘写进对话让 Codex 分两步答第一步只回答每个张量在 batch 化之后应该是什么形状第二步再解释为什么。分开问的原因是形状是可以用 numpy 验证的硬约束而语义解释容易似是而非混在一起很难分辨错在哪。一个可以直接复制的提问骨架给定 Q 形状 (batch, h, n, d_k)、K 形状 (batch, h, m, d_k)、V 形状 (batch, h, m, d_v)请写出 QK^T 的转置维度、缩放因子的取值、softmax 的轴以及最终输出形状。让它把每一步的中间形状列成表。拿到回答之后不要直接相信把它给的形状代进真实的小张量跑一遍。下面这段可以自己补全用来检查缩放点积注意力的形状链路import numpy as np def scaled_dot_product_attention(Q, K, V, maskNone): Q: (batch, n, d_k) K: (batch, m, d_k) V: (batch, m, d_v) 返回: (batch, n, d_v) d_k Q.shape[-1] scores Q K.transpose(0, 2, 1) / np.sqrt(d_k) # (batch, n, m) if mask is not None: scores np.where(mask, scores, -1e9) scores scores - scores.max(axis-1, keepdimsTrue) # 数值稳定 weights np.exp(scores) weights weights / weights.sum(axis-1, keepdimsTrue) return weights V # (batch, n, d_v)3.2 把生成的代码丢回本地跑再把报错贴回来Codex 只负责生成和解释代码不负责在你的机器上执行。这一段由你来做把片段存成attention_check.py写几个断言固定住形状比如令 batch2、n5、m7、d_k8、d_v8跑完之后打印每个中间张量的 shape。如果 numpy 抛 ValueError把完整报错和当时几个张量的 shape 一起贴回对话Codex 基本能立刻定位是转置维度写错还是切头顺序反了。这种「生成 → 本地跑 → 贴回报错」的循环比让它凭空口算维度靠谱得多。论文里的矩阵运算有唯一正确的形状解本地跑一次就能证伪。3.3 多头注意力的切片顺序单独问一遍把多头那部分拆成一个小问题d_model512、h8输入 X 形状 (batch, n, 512)如何得到 8 个头的 Q、K、V。重点看它给出的 reshape 和 transpose 顺序然后用np.allclose检验切分再拼接是否还原——把各头结果按原顺序 concat 回来应该和输入形状一致并且在不引入任何非线性时数值也能对上。对不上就说明切分轴选错了。4. 第 3.5 节位置编码sin、cos 与 d_model 的对齐4.1 2i 与 2i1 落在哪一维论文给的公式是偶数维用 sin(pos / 10000^(2i/d_model))奇数维用 cos(pos / 10000^(2i/d_model))。这里的 i 是维度下标的一半2i 和 2i1 是 embedding 里的位置索引不是序列位置。也就是说同一个位置的向量里相邻两维是一组频率相同的 sin/cos 对。初学者最容易把 i 当成句子里的第几个词。错一步之后位置编码整体看起来还在合理范围值域都是 [-1, 1]但模型学不到正确的相对位置关系。4.2 10000 这个底数为什么不是随便取的论文用 10000 作为几何级数的底让不同维度上的波长构成从 2π 到 10000·2π 的等比序列。低维变化快、高维变化慢组合起来就能表达较长范围内的相对位移。换成别的底数并不会报错但高频和低频的分布会变对长序列的外推能力有影响。可以用一段代码把形状对齐关系固定住import numpy as np def positional_encoding(max_len, d_model): pos np.arange(max_len)[:, None] # (max_len, 1) i np.arange(0, d_model, 2)[None, :] # (1, d_model/2) angle pos / np.power(10000.0, i / d_model) # (max_len, d_model/2) pe np.zeros((max_len, d_model)) pe[:, 0::2] np.sin(angle) pe[:, 1::2] np.cos(angle) return pe跑完之后检查pe.shape (max_len, d_model)并确认pe[:, 0::2]全是 sin、pe[:, 1::2]全是 cos。如果 i 用错形状不会变但两列会互换得靠抽样打印才能发现。5. 401、base_url 多写 /v1、模型 ID 不存在三种报错对照5.1 401 先看 Key 是从哪里创建的401 Unauthorized在 Codex 上最常见的原因是环境变量没生效或者 Key 本身不对。检查顺序先确认TAOTOKEN_API_KEY在当前终端里echo得出来再确认它和创建时的字符串完全一致前后没有空格和换行最后确认这把 Key 确实是在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的控制台里生成的。如果终端是新开的别忘了重新export或重启一次setx在旧窗口里不生效。5.2 base_url 末尾多一截 /v1 的表现把 base_url 写成https://taotoken.net/api/v1之后请求路径会拼成/api/v1/...多数情况下直接 404少数情况返回一段 HTML。对照规则很简单填进工具的 Base URL 一律是 https://taotoken.net/api 末尾不带 /v1。这条和官网链接是两套东西官网那一串带 UTM 参数只用于浏览器访问绝对不能塞进配置文件。5.3 模型 ID 不存在与通道超时如果报错是模型不存在先去模型广场核对 ID别急着重装。另一类现象是连接超时同样的配置白天能跑通、晚上偶尔转圈多试几次又好了。这种情况换到统一的兼容通道之后一般会平稳很多因为地址是固定的不需要跟着上游临时变化去改配置。真遇到持续超时把请求时间和报错原文一起记录下来再回去排查网络和 Key 的额度状态。6. 跑顺之后回控制台核一下这次调用6.1 从模型对话到 Coding Plan 的下一步配置保存并跑通一次之后建议先用同一把 Key 去 TaoToken 模型对话 发一条测试消息确认模型 ID、Base URL、Key 三件套都没填错。如果打算长期拿 Codex 啃论文和写复现代码可以打开 Coding Plan 看当前套餐是否够用需要再建几把 Key 或者换模型时直接进 控制台 API Keys 操作环境变量和配置文件的字段对照可以看 接入文档。6.2 通道只是通道推导还得自己走一遍回到论文。Codex 能帮你把 Q、K、V 的形状对齐把 softmax 的轴说清楚把位置编码的下标指出来但「为什么是缩放点积」「为什么多头要切分再拼接」这些问题只有自己把中间张量打出来、把数值算一遍才算真的过了一遍。通道稳定之后卡点就从环境转到了公式本身这其实是更好的一种卡点——至少你知道该往哪本书、哪一节翻。写完 attention_check.py 和位置编码那两段记得把中间张量的形状和几个采样值记在笔记里。下次遇到多头切片顺序不对、或者位置编码下标错位翻回这一页就能对上不需要重新问一遍。