Apply rotary position embeddings to query or key tensor. The rotation is applied using the formula: - Split features into pairs (x1, x2) - Rotate: (x1 * cos - x2 * sin, x1 * sin + x2 * cos) Args: query_or_key: Input tensor of shape (batch, seq_len, num_heads, h
(
query_or_key: torch.Tensor,
freqs_cos: torch.Tensor,
freqs_sin: torch.Tensor,
)
| 2 | |
| 3 | @torch.no_grad() |
| 4 | def run( |
| 5 | query_or_key: torch.Tensor, |
| 6 | freqs_cos: torch.Tensor, |
| 7 | freqs_sin: torch.Tensor, |
| 8 | ) -> torch.Tensor: |
| 9 | """ |
| 10 | Apply rotary position embeddings to query or key tensor. |
| 11 | |
| 12 | The rotation is applied using the formula: |
| 13 | - Split features into pairs (x1, x2) |
| 14 | - Rotate: (x1 * cos - x2 * sin, x1 * sin + x2 * cos) |
| 15 | |
| 16 | Args: |
| 17 | query_or_key: Input tensor of shape (batch, seq_len, num_heads, head_dim) |
| 18 | freqs_cos: Cosine frequencies of shape (seq_len, head_dim) |
| 19 | freqs_sin: Sine frequencies of shape (seq_len, head_dim) |
| 20 | |
| 21 | Returns: |
| 22 | Rotated tensor of same shape as input |
| 23 | """ |
| 24 | # Input shape: (batch, seq_len, num_heads, head_dim) |
| 25 | # freqs shape: (seq_len, head_dim) |
| 26 | |
| 27 | # Reshape frequencies to broadcast correctly |
| 28 | # freqs: (seq_len, head_dim) -> (1, seq_len, 1, head_dim) |
| 29 | freqs_cos_expanded = freqs_cos.unsqueeze(0).unsqueeze(2) |
| 30 | freqs_sin_expanded = freqs_sin.unsqueeze(0).unsqueeze(2) |
| 31 | |
| 32 | # Split the head_dim into pairs for rotation |
| 33 | # This is the complex number rotation in real space |
| 34 | # query_or_key: (batch, seq_len, num_heads, head_dim) |
| 35 | # Split into: (batch, seq_len, num_heads, head_dim // 2, 2) |
| 36 | x_shape = query_or_key.shape |
| 37 | x_reshaped = query_or_key.float().reshape( |
| 38 | x_shape[0], x_shape[1], x_shape[2], -1, 2 |
| 39 | ) |
| 40 | |
| 41 | # Split frequencies similarly |
| 42 | freqs_cos_reshaped = freqs_cos_expanded.float().reshape( |
| 43 | freqs_cos_expanded.shape[0], freqs_cos_expanded.shape[1], freqs_cos_expanded.shape[2], -1, 2 |
| 44 | ) |
| 45 | freqs_sin_reshaped = freqs_sin_expanded.float().reshape( |
| 46 | freqs_sin_expanded.shape[0], freqs_sin_expanded.shape[1], freqs_sin_expanded.shape[2], -1, 2 |
| 47 | ) |
| 48 | |
| 49 | # Extract real and imaginary parts |
| 50 | x1 = x_reshaped[..., 0] # (batch, seq_len, num_heads, head_dim // 2) |
| 51 | x2 = x_reshaped[..., 1] # (batch, seq_len, num_heads, head_dim // 2) |
| 52 | |
| 53 | cos1 = freqs_cos_reshaped[..., 0] # (1, seq_len, 1, head_dim // 2) |
| 54 | cos2 = freqs_cos_reshaped[..., 1] # (1, seq_len, 1, head_dim // 2) |
| 55 | sin1 = freqs_sin_reshaped[..., 0] # (1, seq_len, 1, head_dim // 2) |
| 56 | sin2 = freqs_sin_reshaped[..., 1] # (1, seq_len, 1, head_dim // 2) |
| 57 | |
| 58 | # Apply rotation: (x1, x2) -> (x1*cos - x2*sin, x1*sin + x2*cos) |
| 59 | # This is the complex multiplication: (x1 + ix2) * (cos + isin) |
| 60 | out1 = x1 * cos1 - x2 * sin1 |
| 61 | out2 = x1 * sin2 + x2 * cos2 |
nothing calls this directly
no outgoing calls
no test coverage detected