Thomas Piacentini
← Atelier

Exercice Python

Rotary position embedding

Texte original · anglais25 min

Rotary position embedding (RoPE) puts the position of a token into its query and key vectors. It turns each pair of coordinates by an angle that grows with the position. Then the attention score of a query and a key depends only on the distance between their positions. Most open language models use RoPE.

Task

Write two functions.

  1. rope_frequencies(d, base=10000.0) returns the frequency of each coordinate pair.
  2. apply_rope(x, positions, base=10000.0) returns a rotated copy of x.

The frequency of pair i is \theta_i = \text{base}^{-2i/d}, for i = 0, 1, \dots, \lfloor d/2 \rfloor - 1.

Pair i is the two adjacent coordinates 2i and 2i + 1. For the token at position p, let a = x_{2i}, b = x_{2i+1} and \phi = p \, \theta_i. The output pair is:

a' = a \cos\phi - b \sin\phi, \qquad b' = a \sin\phi + b \cos\phi

When d is odd, the last coordinate has no partner. Copy it to the output without a change.

Input and output

Name Type Shape Meaning
d int the size of the last axis
base float the base of the frequencies
x float array (..., T, d) the vectors of T tokens, with zero or more leading batch axes
positions int or float array (T,) the position of each token
  • rope_frequencies returns a float array of shape (d // 2,).
  • apply_rope returns a new float array with the shape of x.

Constraints

  • 1 <= T <= 64 and 2 <= d <= 128.
  • Positions are from 0 to 1000000.
  • The positions go with the second to last axis of x. Every leading axis gets the same rotation.
  • Use the pairs (0, 1), (2, 3), .... Do not pair coordinate i with coordinate i + d/2.
  • Do not change the input arrays.
  • Use numpy only.

Examples

python
rope_frequencies(8)
text
[1.    0.1   0.01  0.001]
python
x = np.array([[1.0, 0.0, 1.0, 0.0], [1.0, 0.0, 1.0, 0.0], [1.0, 0.0, 1.0, 0.0]])
apply_rope(x, np.arange(3))
text
[[ 1.          0.          1.          0.        ]
 [ 0.54030231  0.84147098  0.99995     0.00999983]
 [-0.41614684  0.90929743  0.99980001  0.01999867]]
python
q = np.array([[1.0, 2.0, 3.0, 4.0]])
k = np.array([[0.5, -1.0, 2.0, 1.0]])
apply_rope(q, [2])[0] @ apply_rope(k, [5])[0]
apply_rope(q, [10])[0] @ apply_rope(k, [13])[0]
text
11.912706599522757
11.912706599522759
Code et livrables 13
Ce que vous en retenez

Enregistré dans votre carnet sur cet appareil.

Sources et limites

Les repères de lecture sont déclaratifs. Les résultats de tests sont enregistrés séparément ; ils valent pour les cas exécutés.

AI Engineering from Scratch · 3f9715c · MIT

Télécharger ce fichier ↓