The ru-en-RoSBERTa is a general text embedding model for Russian. The model is based on ruRoBERTa and fine-tuned with ~4M pairs of supervised, synthetic and unsupervised data in Russian and English. Tokenizer supports some English tokens from RoBERTa tokenizer.
For more model details please refer to our article.
Usage
The model can be used as is with prefixes. It is recommended to use CLS pooling. The choice of prefix and pooling depends on the task.
We use the following basic rules to choose a prefix:
"search_query: " and "search_document: " prefixes are for answer or relevant paragraph retrieval
"classification: " prefix is for symmetric paraphrasing related tasks (STS, NLI, Bitext Mining)
"clustering: " prefix is for any tasks that rely on thematic features (topic classification, title-body retrieval)
To better tailor the model to your needs, you can fine-tune it with relevant high-quality Russian and English datasets.
Below are examples of texts encoding using the Transformers and SentenceTransformers libraries.
Transformers
python
1import torch
2import torch.nn.functional as F
3from transformers import AutoTokenizer, AutoModel
456defpool(hidden_state, mask, pooling_method="cls"):7if pooling_method =="mean":8 s = torch.sum(hidden_state * mask.unsqueeze(-1).float(), dim=1)9 d = mask.sum(axis=1, keepdim=True).float()10return s / d
11elif pooling_method =="cls":12return hidden_state[:,0]1314inputs =[15# 16"classification: Он нам и <unk> не нужон ваш Интернет!",17"clustering: В Ярославской области разрешили работу бань, но без посетителей",18"search_query: Сколько программистов нужно, чтобы вкрутить лампочку?",1920# 21"classification: What a time to be alive!",22"clustering: Ярославским баням разрешили работать без посетителей",23"search_document: Чтобы вкрутить лампочку, требуется три программиста: один напишет программу извлечения лампочки, другой — вкручивания лампочки, а третий проведет тестирование.",24]2526tokenizer = AutoTokenizer.from_pretrained("ai-forever/ru-en-RoSBERTa")27model = AutoModel.from_pretrained("ai-forever/ru-en-RoSBERTa")2829tokenized_inputs = tokenizer(inputs, max_length=512, padding=True, truncation=True, return_tensors="pt")3031with torch.no_grad():32 outputs = model(**tokenized_inputs)3334embeddings = pool(35 outputs.last_hidden_state,36 tokenized_inputs["attention_mask"],37 pooling_method="cls"# or try "mean"38)3940embeddings = F.normalize(embeddings, p=2, dim=1)4142sim_scores = embeddings[:3] @ embeddings[3:].T
43print(sim_scores.diag().tolist())44# [0.4796873927116394, 0.9409002065658569, 0.7761015892028809]
SentenceTransformers
python
1from sentence_transformers import SentenceTransformer
234inputs =[5# 6"classification: Он нам и <unk> не нужон ваш Интернет!",7"clustering: В Ярославской области разрешили работу бань, но без посетителей",8"search_query: Сколько программистов нужно, чтобы вкрутить лампочку?",910# 11"classification: What a time to be alive!",12"clustering: Ярославским баням разрешили работать без посетителей",13"search_document: Чтобы вкрутить лампочку, требуется три программиста: один напишет программу извлечения лампочки, другой — вкручивания лампочки, а третий проведет тестирование.",14]1516# loads model with CLS pooling17model = SentenceTransformer("ai-forever/ru-en-RoSBERTa")1819# embeddings are normalized by default20embeddings = model.encode(inputs, convert_to_tensor=True)2122sim_scores = embeddings[:3] @ embeddings[3:].T
23print(sim_scores.diag().tolist())24# [0.47968706488609314, 0.940900444984436, 0.7761018872261047]
or using prompts (sentence-transformers>=2.4.0):
python
1from sentence_transformers import SentenceTransformer
234# loads model with CLS pooling5model = SentenceTransformer("ai-forever/ru-en-RoSBERTa")67classification = model.encode(["Он нам и <unk> не нужон ваш Интернет!","What a time to be alive!"], prompt_name="classification")8print(classification[0] @ classification[1].T)# 0.47968706488609314910clustering = model.encode(["В Ярославской области разрешили работу бань, но без посетителей","Ярославским баням разрешили работать без посетителей"], prompt_name="clustering")11print(clustering[0] @ clustering[1].T)# 0.9409004449844361213query_embedding = model.encode("Сколько программистов нужно, чтобы вкрутить лампочку?", prompt_name="search_query")14document_embedding = model.encode("Чтобы вкрутить лампочку, требуется три программиста: один напишет программу извлечения лампочки, другой — вкручивания лампочки, а третий проведет тестирование.", prompt_name="search_document")15print(query_embedding @ document_embedding.T)# 0.7761018872261047
Citation
@misc{snegirev2024russianfocusedembeddersexplorationrumteb,
title={The Russian-focused embedders' exploration: ruMTEB benchmark and Russian embedding model design},
author={Artem Snegirev and Maria Tikhonova and Anna Maksimova and Alena Fenogenova and Alexander Abramov},
year={2024},
eprint={2408.12503},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2408.12503},
}
Limitations
The model is designed to process texts in Russian, the quality in English is unknown. Maximum input text length is limited to 512 tokens.