TensorTonic
Problems
Rotary Position Embedding
JAX
Easy

Apply rotary position embeddings to a block of query vectors and a block of key vectors, where each token sits at its own position in the sequence.

Let D be the head size and half = D / 2. Dimension i of every vector is paired with dimension i + half, for i from 0 to half minus 1. For a token at position ppp, pair i turns by the angle aia_iai​, where

θi=base−2i/D,ai=p θi,\theta_i = \text{base}^{-2i/D}, \qquad a_i = p\,\theta_i ,θi​=base−2i/D,ai​=pθi​,

and the pair (xi,xi+half)(x_i, x_{i+\text{half}})(xi​,xi+half​) becomes

xi′=xicos⁡ai−xi+halfsin⁡ai,xi+half′=xi+halfcos⁡ai+xisin⁡ai.x_i' = x_i \cos a_i - x_{i+\text{half}} \sin a_i, \qquad x_{i+\text{half}}' = x_{i+\text{half}} \cos a_i + x_i \sin a_i .xi′​=xi​cosai​−xi+half​sinai​,xi+half′​=xi+half​cosai​+xi​sinai​.

Here q holds query vectors of shape (T, Hq, D) for T tokens and Hq query heads, k holds key vectors of shape (T, Hk, D) for the same tokens, positions holds the position ppp of each token, and base sets how quickly the turning speeds fall from one pair to the next. Every head of a token turns by the same angles.

Your function is called under jax.jit with q, k and positions traced and base passed as a static Python float.

Return a dict with key q holding the rotated queries and key k holding the rotated keys, both float32 JAX arrays with the same shapes as the inputs.

Examples

Input: q = [[[1,0,0,1]],[[1,0,0,1]]], k = [[[0.5,1,-1,2]],[[0.5,1,-1,2]]], positions = [0,1], base = 10000

Output: {"q":[[[1.0,0.0,0.0,1.0]],[[0.540302,-0.01,0.841471,0.99995]]],"k":[[[0.5,1.0,-1.0,2.0]],[[1.111622,0.97995,-0.119567,2.0099]]]}

Explanation: Position 0 has every angle equal to 0, so the first token comes back unchanged. At position 1 with D = 4 and base 10000 the two speeds are 1 and 0.01, so the query pair (q[0], q[2]) = (1, 0) turns by 1 radian into (0.540302, 0.841471), and the pair (q[1], q[3]) = (0, 1) turns by 0.01 radians into (-0.01, 0.99995).

Input: q = [[[1,0],[0,1]],[[2,1],[-1,0.5]]], k = [[[1,1]],[[0,-1]]], positions = [3,7], base = 100

Output: {"q":[[[-0.989992,0.14112],[-0.14112,-0.989992]],[[0.850818,2.067875],[-1.082396,-0.280035]]],"k":[[[-1.131113,-0.848872]],[[0.656987,-0.753902]]]}

Input: q = [[[0.2,-0.4,0.6,1.0,0.0,-0.5]]], k = [[[1,0,0,0,1,0]]], positions = [100], base = 10

Output: {"q":[[[0.678829,0.303865,-0.325058,0.761046,-0.260127,0.710167]]],"k":[[[0.862319,-0.650317,0.0,-0.506366,-0.759663,0.0]]]}

Hint 1

jnp.arange(half, dtype=jnp.float32) gives the pair indices, and base ** array raises base to each one.

Hint 2

angles[:, None, :] broadcasts a (T, half) table across heads.

Hint 3

x[..., :half], x[..., half:] and jnp.concatenate([a, b], axis=-1).

Requirements

  • Keep positions as a JAX array inside the function, without converting them with int, float or NumPy, and build the angle table with jax.numpy operations.
  • Compute the angles, cosines and sines in float32.

Constraints

  • T is between 1 and 4, Hq and Hk are between 1 and 4, and D is an even number between 2 and 8.
  • q and k are float32 arrays with finite values.
  • positions is an int32 array of shape (T,) with values from 0 to 255, in any order and possibly repeated.
  • base is a Python float greater than 1.
Try Similar Problems
KV Cache Update at a PositionEasyTop-k and Top-p SamplingMediumGrouped-Query Decode StepMediumFunctional Array UpdateEasyPRNG Key SplittingEasyMasked Mean Without Boolean IndexingEasyValue and Grad of a LossEasyStatic Arguments in jitEasyModel Ensemble with in_axesEasySGD with Momentum over a PytreeEasyDevice Mesh and Named ShardingEasyPad and Mask to Bucket LengthMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.
Rotary Position Embedding

Rotary Position Embedding

JAX
Easy

Apply rotary position embeddings to a block of query vectors and a block of key vectors, where each token sits at its own position in the sequence.

Let D be the head size and half = D / 2. Dimension i of every vector is paired with dimension i + half, for i from 0 to half minus 1. For a token at position ppp, pair i turns by the angle aia_iai​, where

θi=base−2i/D,ai=p θi,\theta_i = \text{base}^{-2i/D}, \qquad a_i = p\,\theta_i ,θi​=base−2i/D,ai​=pθi​,

and the pair (xi,xi+half)(x_i, x_{i+\text{half}})(xi​,xi+half​) becomes

xi′=xicos⁡ai−xi+halfsin⁡ai,xi+half′=xi+halfcos⁡ai+xisin⁡ai.x_i' = x_i \cos a_i - x_{i+\text{half}} \sin a_i, \qquad x_{i+\text{half}}' = x_{i+\text{half}} \cos a_i + x_i \sin a_i .xi′​=xi​cosai​−xi+half​sinai​,xi+half′​=xi+half​cosai​+xi​sinai​.

Here q holds query vectors of shape (T, Hq, D) for T tokens and Hq query heads, k holds key vectors of shape (T, Hk, D) for the same tokens, positions holds the position ppp of each token, and base sets how quickly the turning speeds fall from one pair to the next. Every head of a token turns by the same angles.

Your function is called under jax.jit with q, k and positions traced and base passed as a static Python float.

Return a dict with key q holding the rotated queries and key k holding the rotated keys, both float32 JAX arrays with the same shapes as the inputs.

Examples

Input: q = [[[1,0,0,1]],[[1,0,0,1]]], k = [[[0.5,1,-1,2]],[[0.5,1,-1,2]]], positions = [0,1], base = 10000

Output: {"q":[[[1.0,0.0,0.0,1.0]],[[0.540302,-0.01,0.841471,0.99995]]],"k":[[[0.5,1.0,-1.0,2.0]],[[1.111622,0.97995,-0.119567,2.0099]]]}

Explanation: Position 0 has every angle equal to 0, so the first token comes back unchanged. At position 1 with D = 4 and base 10000 the two speeds are 1 and 0.01, so the query pair (q[0], q[2]) = (1, 0) turns by 1 radian into (0.540302, 0.841471), and the pair (q[1], q[3]) = (0, 1) turns by 0.01 radians into (-0.01, 0.99995).

Input: q = [[[1,0],[0,1]],[[2,1],[-1,0.5]]], k = [[[1,1]],[[0,-1]]], positions = [3,7], base = 100

Output: {"q":[[[-0.989992,0.14112],[-0.14112,-0.989992]],[[0.850818,2.067875],[-1.082396,-0.280035]]],"k":[[[-1.131113,-0.848872]],[[0.656987,-0.753902]]]}

Input: q = [[[0.2,-0.4,0.6,1.0,0.0,-0.5]]], k = [[[1,0,0,0,1,0]]], positions = [100], base = 10

Output: {"q":[[[0.678829,0.303865,-0.325058,0.761046,-0.260127,0.710167]]],"k":[[[0.862319,-0.650317,0.0,-0.506366,-0.759663,0.0]]]}

Hint 1

jnp.arange(half, dtype=jnp.float32) gives the pair indices, and base ** array raises base to each one.

Hint 2

angles[:, None, :] broadcasts a (T, half) table across heads.

Hint 3

x[..., :half], x[..., half:] and jnp.concatenate([a, b], axis=-1).

Requirements

  • Keep positions as a JAX array inside the function, without converting them with int, float or NumPy, and build the angle table with jax.numpy operations.
  • Compute the angles, cosines and sines in float32.

Constraints

  • T is between 1 and 4, Hq and Hk are between 1 and 4, and D is an even number between 2 and 8.
  • q and k are float32 arrays with finite values.
  • positions is an int32 array of shape (T,) with values from 0 to 255, in any order and possibly repeated.
  • base is a Python float greater than 1.
Try Similar Problems
KV Cache Update at a PositionEasyTop-k and Top-p SamplingMediumGrouped-Query Decode StepMediumFunctional Array UpdateEasyPRNG Key SplittingEasyMasked Mean Without Boolean IndexingEasyValue and Grad of a LossEasyStatic Arguments in jitEasyModel Ensemble with in_axesEasySGD with Momentum over a PytreeEasyDevice Mesh and Named ShardingEasyPad and Mask to Bucket LengthMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.
Problems
Loading...
1 / 1