Positional Encoding and RoPE

自注意力对输入 token 做集合式的加权交互;如果不注入位置,A BB A 可能得到同一组交互模式。位置编码的任务不是告诉模型“第几个 token”这么简单,而是让 attention 的相似度随相对距离和方向变化。

几类位置机制

机制 注入位置 主要性质 典型边界
learned absolute 加到 hidden states 训练窗口内直接学习 超出训练位置通常不能自然外推
sinusoidal absolute 固定函数加到表示 无额外位置参数 与 attention 的相对关系不直接绑定
relative bias 加到 attention logits 直接改变距离偏好 bias 形状与长度、架构耦合
RoPE 旋转 Q/K 点积中显式出现相对位置信息 长上下文 scaling 需要重新验证

RoPE 的核心机制

把每个 head 的 Q/K 维度两两配对,在位置 p 使用角度 pθ_i 做二维旋转:

1
[x_{2i}, x_{2i+1}] → R(pθ_i)[x_{2i}, x_{2i+1}]

Q 和 K 都按各自位置旋转后,q_p · k_t 不只比较内容,还带有 p-t 的相位差。因此模型可以用同一组线性投影,在不同相对距离上产生不同的注意力相似度。这个性质解释了 RoPE 为何同时看起来编码了绝对位置、却在点积里表现为相对位置关系。

因果链是:位置改变旋转角 → Q/K 点积改变 → attention 权重改变 → token 对不同距离的依赖模式改变 → 长上下文行为受频率、训练长度与数据分布共同约束。

为什么长上下文不是改一个数字

max_position_embeddings 或服务端窗口调大,只是允许输入更长;它没有让模型在未训练的相位范围内学会稳定区分远距离关系。RoPE scaling 会改变频率或位置映射,可能缓解外推,也可能损伤短上下文局部性、代码定位、多跳检索和顺序敏感任务。

验证应把位置能力拆成几类:窗口内基线、刚超过训练长度、远距离 needle retrieval、跨段多跳、位置置换和长序列生成。只看 perplexity 或“能否启动”不足以证明上下文有效。

与 attention 和 KV Cache 的关系

RoPE 通常作用在进入 attention 的 Q/K 上,V 不旋转;因此它影响的是“从哪里读取信息”的权重,而不是值向量本身。decode 时历史 K 已按各自位置旋转并写入 KV Cache,新 query 必须使用相同的旋转约定,否则缓存与当前 token 的坐标系不一致。

它向上连接 Transformer Block,向下依赖 Scaled Dot-Product Attention,横向对照 learned absolute、relative bias 和 ALiBi 等位置方案。

参考资料

频率带与外推的真实代价

RoPE 的每一对维度使用不同的角频率。高频维度对相邻位置敏感,适合局部顺序;低频维度变化慢,能表达较远距离。把上下文直接拉长时,高频相位首先遇到训练分布之外的区域,模型可能在短文本上仍正常,却在远距离引用、代码括号匹配或顺序交换上失真。所谓 scaling 不是单纯把位置编号乘一个常数,而是在不同频率带上重新分配相位变化。

因此要把“窗口支持”和“位置泛化”分开验收。一个模型能接受 128K 输入,可能只是 kernel 和 cache 能分配出这块内存;它未必能把位于 100K 位置的证据与问题正确关联。短、中文、代码和长文多跳样本应分别做位置置换测试:只移动证据位置,保持内容不变,观察准确率随距离怎样下降。

Cache 里的坐标系不能混用

如果 prefill 使用一种 RoPE base、decode 使用另一种 scaling,历史 K 和新 Q 不在同一个相位坐标系,结果不是轻微噪声而是注意力匹配整体偏移。分页 cache、滑动窗口和 prefix cache 还要明确 position id 是全局绝对位置、窗口内位置,还是由请求 offset 计算的逻辑位置。复用 prefix 时,只有 tokenizer、position ids、RoPE 配置和模型权重都一致,缓存才可安全共享。

一个小测试是构造两段相同内容但不同起始 offset 的输入,比较对应 token 的 Q/K 内积和生成结果;再把 offset 只改在 decode 路径。如果差异远超浮点误差,说明位置计算或 cache 写入约定不一致,而不是“长上下文能力不足”。