Skip to main content

Rotary Embeddings - Pytorch

A standalone library for adding rotary embeddings to transformers in Pytorch, following its success as relative positional encoding. Specifically it will make rotating information into any axis of a tensor easy and efficient, whether they be fixed positional or learned. This library will give you state of the art results for positional embedding, at little costs.

My gut also tells me there is something more to rotations that can be exploited in artificial neural networks.

Potential successor

Install

$ pip install rotary-embedding-torch

Usage

import torch
from rotary_embedding_torch import RotaryEmbedding

# instantiate the positional embedding in your transformer and pass to all your attention layers

rotary_emb = RotaryEmbedding(dim = 32)

# mock queries and keys - dimensions should end with (seq_len, feature dimension), and any number of preceding dimensions (batch, heads, etc)

q = torch.randn(1, 8, 1024, 64) # queries - (batch, heads, seq len, dimension of head)
k = torch.randn(1, 8, 1024, 64) # keys

# apply the rotations to your queries and keys after the heads have been split out, but prior to the dot product and subsequent softmax (attention)

q = rotary_emb.rotate_queries_or_keys(q)
k = rotary_emb.rotate_queries_or_keys(k)

# then do your attention with your queries (q) and keys (k) as usual

If you do all the steps above correctly, you should see a dramatic improvement during training

Inverse Rotations

To rotate in the opposite direction, as with QKVO RoPE where the rotation on the outputs is undone, pass inverse = True

o = rotary_emb.rotate_queries_or_keys(o, inverse = True)

Inference Key-Value Cache

When dealing with key / value caches at inference, the query position needs to be offset with the key_value_seq_length - query_seq_length

To make this easy, use the rotate_queries_with_cached_keys method

q = torch.randn(1, 8, 1, 64)     # only one query at a time
k = torch.randn(1, 8, 1024, 64)  # key / values with cache concatted

q, k = rotary_emb.rotate_queries_with_cached_keys(q, k)

You can also do this manually like so

q = rotary_emb.rotate_queries_or_keys(q, offset = k.shape[-2] - q.shape[-2])

Axial Rotary Embeddings

For easy use of n-dimensional axial relative positional embedding, ie. video transformers

import torch

from rotary_embedding_torch import (
    RotaryEmbedding,
    apply_rotary_emb
)

pos_emb = RotaryEmbedding(
    dim = 16,
    freqs_for = 'pixel',
    max_freq = 256
)

# queries and keys for frequencies to be rotated into
# say for a video with 8 frames, and rectangular image (feature dimension comes last)

q = torch.randn(1, 8, 64, 32, 64)
k = torch.randn(1, 8, 64, 32, 64)

# get axial frequencies - (8, 64, 32, 16 * 3 = 48)
# will automatically do partial rotary

freqs = pos_emb.get_axial_freqs(8, 64, 32)

# rotate in frequencies

q = apply_rotary_emb(freqs, q)
k = apply_rotary_emb(freqs, k)

Length Extrapolatable Rotary Embeddings

In this paper, they were able to fix length extrapolation issue with rotary embeddings by giving it a decay similar to ALiBi. They named this technique XPos, and you can use it by setting use_xpos = True on initialization.

This can only be used for autoregressive transformers

import torch
from rotary_embedding_torch import RotaryEmbedding

# instantiate the positional embedding in your transformer and pass to all your attention layers

rotary_emb = RotaryEmbedding(
    dim = 32,
    use_xpos = True   # set this to True to make rotary embeddings extrapolate better to sequence lengths greater than the one used at training time
)

# mock queries and keys - dimensions should end with (seq_len, feature dimension), and any number of preceding dimensions (batch, heads, etc)

q = torch.randn(1, 8, 1024, 64) # queries - (batch, heads, seq len, dimension of head)
k = torch.randn(1, 8, 1024, 64) # keys

# apply the rotations to your queries and keys after the heads have been split out, but prior to the dot product and subsequent softmax (attention)

# instead of using `rotate_queries_or_keys`, you will use `rotate_queries_and_keys`, the rest is taken care of

q, k = rotary_emb.rotate_queries_and_keys(q, k)

Interpolating Sequence Positions

This MetaAI paper proposes simply fine-tuning on interpolations of the sequence positions for extending to longer context length for pretrained models. They show this performs much better than simply fine-tuning on the same sequence positions but extended further.

You can use this by setting the interpolate_factor on initialization to a value greater than 1. (ex. if pretrained model was trained on 2048, setting interpolate_factor = 2. would allow fine-tuning to 2048 x 2. = 4096)

Update: someone in the community has reported that it does not work well. please email me if you see either a positive or negative result

import torch
from rotary_embedding_torch import RotaryEmbedding

rotary_emb = RotaryEmbedding(
    dim = 32,
    interpolate_factor = 2.    # add this line of code to pretrained model and fine-tune for ~1000 steps, as shown in paper
)

Fused Flash Attention with Rotary

You can also use a fused Flash Attention kernel that computes attention with rotary embeddings in one pass. It automatically falls back to a reference PyTorch implementation (CPU/GPU) if Triton is not available. It easily supports ignoring tokens from rotations (like CLS or register tokens) by explicitly passing rotary_pos_emb_indices.

import torch
from rotary_embedding_torch import RotaryEmbedding
from rotary_embedding_torch.flash_attn_with_rotary import flash_attn_with_rotary

rotary_emb = RotaryEmbedding(dim = 32)
freqs = rotary_emb(torch.arange(1024))

q = torch.randn(1, 8, 1024 + 2, 64).cuda() # 2 extra tokens (e.g. CLS, register)
k = torch.randn(1, 8, 1024 + 2, 64).cuda()
v = torch.randn(1, 8, 1024 + 2, 64).cuda()

# indices for the 1024 rotary positions, skipping the first 2 tokens (CLS / register)
pos_indices = torch.arange(1024).cuda() + 2

# fused flash attention with rotary
out = flash_attn_with_rotary(
    q, k, v,
    rotary_pos_emb = freqs,
    rotary_pos_emb_indices = pos_indices,
    is_causal = True
)

Citations

@misc{su2021roformer,
    title   = {RoFormer: Enhanced Transformer with Rotary Position Embedding},
    author  = {Jianlin Su and Yu Lu and Shengfeng Pan and Bo Wen and Yunfeng Liu},
    year    = {2021},
    eprint  = {2104.09864},
    archivePrefix = {arXiv},
    primaryClass = {cs.CL}
}
@inproceedings{Sun2022ALT,
    title     = {A Length-Extrapolatable Transformer},
    author    = {Yutao Sun and Li Dong and Barun Patra and Shuming Ma and Shaohan Huang and Alon Benhaim and Vishrav Chaudhary and Xia Song and Furu Wei},
    year      = {2022}
}
@inproceedings{Chen2023ExtendingCW,
    title   = {Extending Context Window of Large Language Models via Positional Interpolation},
    author  = {Shouyuan Chen and Sherman Wong and Liangjian Chen and Yuandong Tian},
    year    = {2023}
}
@misc{bloc97-2023
    title   = {NTK-Aware Scaled RoPE allows LLaMA models to have extended (8k+) context size without any fine-tuning and minimal perplexity degradation.},
    author  = {/u/bloc97},
    url     = {https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/}
}

Metadata

Release files for rotary-embedding-torch 0.9.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rotary-embedding-torch 0.9.2
File Size Uploaded Provenance Actions
rotary_embedding_torch-0.9.2.tar.gz 13.4 kB Without provenance Details for rotary_embedding_torch-0.9.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for rotary-embedding-torch 0.9.2
File Interpreter ABI Platform Actions
rotary_embedding_torch-0.9.2-py3-none-any.whl Python 3 none any Details for rotary_embedding_torch-0.9.2-py3-none-any.whl

Total release size: 30.9 kB

Release files / rotary_embedding_torch-0.9.2.tar.gz

Download URL rotary_embedding_torch-0.9.2.tar.gz
Size 13.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5eb7c8e899af5fb3cfa24f9e5902663183ef77c9e3fa55f478d0de34d183431b
BLAKE2b-256 checksum
How to use checksums
4245a363e3848971bb77bfdbf02895f6d47e0db0b2eca19e3c256195c3511505
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Release files / rotary_embedding_torch-0.9.2-py3-none-any.whl

Download URL rotary_embedding_torch-0.9.2-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c57891f82e6d73981d46b08ea22e2944d217bc3b463612e336498c9f32d69d16
BLAKE2b-256 checksum
How to use checksums
9930db962f3755fc0accdd164e3320e2116bd8d4c52b60ead7d65db3f1bfd3e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Security for rotary-embedding-torch 0.9.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.9.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page