| import torch |
|
|
|
|
| def precompute_rope_freqs(head_dim: int, max_seq_len: int, theta: float = 10_000.0): |
| """Precompute the rotation angles used by RoPE (Section 4.5). |
| |
| Returns a complex tensor of shape (max_seq_len, head_dim // 2) where each |
| entry encodes the rotation to apply at that position/frequency pair. |
| """ |
| assert head_dim % 2 == 0, "RoPE requires an even head_dim" |
| freqs = 1.0 / (theta ** (torch.arange(0, head_dim, 2).float() / head_dim)) |
| positions = torch.arange(max_seq_len).float() |
| angles = torch.outer(positions, freqs) |
| return torch.polar(torch.ones_like(angles), angles) |
|
|
|
|
| def apply_rope(x: torch.Tensor, rope_freqs: torch.Tensor) -> torch.Tensor: |
| """Apply rotary position embedding to a tensor of shape (B, n_heads, T, head_dim). |
| |
| rope_freqs should be pre-sliced to the current sequence length T before |
| being passed in, i.e. rope_freqs[:T]. |
| """ |
| B, H, T, D = x.shape |
| x_complex = torch.view_as_complex(x.float().reshape(B, H, T, D // 2, 2)) |
| freqs = rope_freqs.view(1, 1, T, D // 2) |
| x_rotated = x_complex * freqs |
| out = torch.view_as_real(x_rotated).reshape(B, H, T, D) |
| return out.type_as(x) |
|
|