Installation | Usage | Leaderboard | Documentation | Citing
pip install mteb
import mteb
from sentence_transformers import SentenceTransformer
# Define the sentence-transformers model name
model_name = "average_word_embeddings_komninos"
model = mteb.get_model(model_name) # if the model is not implemented in MTEB it will be eq. to SentenceTransformer(model_name)
tasks = mteb.get_tasks(tasks=["Banking77Classification"])
evaluation = mteb.MTEB(tasks=tasks)
results = evaluation.run(model, output_folder=f"results/{model_name}")
Prompts can be passed to the SentenceTransformer model using the prompts parameter. The following code shows how to use prompts with SentenceTransformer:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("average_word_embeddings_komninos", prompts={"query": "Query:", "passage": "Passage:"})
evaluation = mteb.MTEB(tasks=tasks)
In prompts the key can be:
passage, query) - they will be used in reranking and retrieval tasksBitextMiningClassificationMultilabelClassificationClusteringPairClassificationRerankingRetrievalSTSSummarizationInstructionRetrievalRetrival-query - these prompts will be used in all classification tasksNFCorpus-query - these prompts will be used in the specific taskmteb available_tasks
mteb run -m sentence-transformers/all-MiniLM-L6-v2 \
-t Banking77Classification \
--verbosity 3
# if nothing is specified default to saving the results in the results/{model_name} folder
Click on each section below to see the details.
Tasks can be selected by providing the list of datasets, but also
tasks = mteb.get_tasks(task_types=["Clustering", "Retrieval"]) # Only select clustering and retrieval tasks
tasks = mteb.get_tasks(categories=["s2s", "p2p"]) # Only select sentence2sentence and paragraph2paragraph datasets
tasks = mteb.get_tasks(languages=["eng", "deu"]) # Only select datasets which contain "eng" or "deu" (iso 639-3 codes)
You can also specify which languages to load for multilingual/cross-lingual tasks like below:
import mteb
tasks = [
mteb.get_task("AmazonReviewsClassification", languages = ["eng", "fra"]),
mteb.get_task("BUCCBitextMining", languages = ["deu"]), # all subsets containing "deu"
]
# or you can select specific huggingface subsets like this:
from mteb.tasks import AmazonReviewsClassification, BUCCBitextMining
evaluation = mteb.MTEB(tasks=[
AmazonReviewsClassification(hf_subsets=["en", "fr"]) # Only load "en" and "fr" subsets of Amazon Reviews
BUCCBitextMining(hf_subsets=["de-en"]), # Only load "de-en" subset of BUCC
])
# for an example of a HF subset see "Subset" in the dataset viewer at: https://huggingface.co/datasets/mteb/bucc-bitext-mining
mteb comes with a set of predefined benchmarks. These can be fetched using get_benchmark and run in a similar fashion to other sets of tasks.
For instance to select the 56 English datasets that form the "Overall MTEB English leaderboard":
import mteb
benchmark = mteb.get_benchmark("MTEB(eng, v1)")
evaluation = mteb.MTEB(tasks=benchmark)
The benchmark specified not only a list of tasks, but also what splits and language to run on. To get an overview of all available benchmarks simply run:
import mteb
benchmarks = mteb.get_benchmarks()
Generally we use the naming scheme for benchmarks MTEB(*), where the "*" denotes the target of the benchmark. In the case of a language, we use the three-letter language code. For large groups of languages, we use the group notation, e.g., MTEB(Scandinavian, v1) for Scandinavian languages. External benchmarks implemented in MTEB like CoIR use their original name. When using a benchmark from MTEB please cite mteb along with the citations of the benchmark which you can access using:
benchmark.citation
encode argumentsTo pass in arguments to the model's encode function, you can use the encode keyword arguments (encode_kwargs):
evaluation.run(model, encode_kwargs={"batch_size": 32})
You can evaluate only on test splits of all tasks by doing the following:
evaluation.run(model, eval_splits=["test"])
Note that the public leaderboard uses the test splits for all datasets except MSMARCO, where the "dev" split is used.
You can evaluate only on selected subsets. For example, if you want to evaluate only the subset_name_to_run subset of all tasks, do the following:
evaluation.run(model, eval_subsets=["subset_name_to_run"])
Monolingual tasks have default subset, other tasks have subsets that are specific to the dataset.
Models should implement the following interface, implementing an encode function taking as inputs a list of sentences, and returning a list of embeddings (embeddings can be np.array, torch.tensor, etc.). For inspiration, you can look at the mteb/mtebscripts repo used for running diverse models via SLURM scripts for the paper.
import mteb
from mteb.encoder_interface import PromptType
import numpy as np
class CustomModel:
def encode(
self,
sentences: list[str],
task_name: str,
prompt_type: PromptType | None = None,
**kwargs,
) -> np.ndarray:
"""Encodes the given sentences using the encoder.
Args:
sentences: The sentences to encode.
task_name: The name of the task.
prompt_type: The prompt type to use.
**kwargs: Additional arguments to pass to the encoder.
Returns:
The encoded sentences.
"""
pass
model = CustomModel()
tasks = mteb.get_tasks(tasks=["Banking77Classification"])
evaluation = MTEB(tasks=tasks)
evaluation.run(model)
To evaluate on a custom task, you can run the following code on your custom task. See how to add a new task, for how to create a new task in MTEB.
from mteb import MTEB
from mteb.abstasks.AbsTaskReranking import AbsTaskReranking
from sentence_transformers import SentenceTransformer
class MyCustomTask(AbsTaskReranking):
...
model = SentenceTransformer("average_word_embeddings_komninos")
evaluation = MTEB(tasks=[MyCustomTask()])
evaluation.run(model)
To use a cross encoder for reranking, you can directly use a CrossEncoder from SentenceTransformers. The following code shows a two-stage run with the second stage reading results saved from the first stage.
from mteb import MTEB
import mteb
from sentence_transformers import CrossEncoder, SentenceTransformer
cross_encoder = CrossEncoder("cross-encoder/ms-marco-TinyBERT-L-2-v2")
dual_encoder = SentenceTransformer("all-MiniLM-L6-v2")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
subset = "default" # subset name used in the NFCorpus dataset
eval_splits = ["test"]
evaluation = MTEB(tasks=tasks)
evaluation.run(
dual_encoder,
eval_splits=eval_splits,
save_predictions=True,
output_folder="results/stage1",
)
evaluation.run(
cross_encoder,
eval_splits=eval_splits,
top_k=5,
save_predictions=True,
output_folder="results/stage2",
previous_results=f"results/stage1/NFCorpus_{subset}_predictions.json",
)
from mteb import MTEB
import mteb
colbert = mteb.get_model("colbert-ir/colbertv2.0")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
eval_splits = ["test"]
evaluation = MTEB(tasks=tasks)
evaluation.run(
colbert,
eval_splits=eval_splits,
corpus_chunk_size=500,
)
This implementation employs the MaxSim operation to compute the similarity between sentences. While MaxSim provides high-quality results, it processes a larger number of embeddings, potentially leading to increased resource usage. To manage resource consumption, consider lowering the corpus_chunk_size parameter.
To save the predictions from a retrieval task, add the --save_predictions flag in the CLI or set save_predictions=True in the run method. The filename will be in the "{task_name}_{subset}_predictions.json" format.
Python:
from mteb import MTEB
import mteb
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
evaluation = MTEB(tasks=tasks)
evaluation.run(
model,
eval_splits=["test"],
save_predictions=True,
output_folder="results",
)
CLI:
mteb run -t NFCorpus -m all-MiniLM-L6-v2 --output_folder results --save_predictions
Multiple models have already been run on tasks available within MTEB. These results are available results repository.
To make the results more easily accessible, we have designed custom functionality for retrieving from the repository. For instance, if you are selecting the best model for your French and English retrieval task on legal documents you could fetch the relevant tasks and create a dataframe of the results using the following code:
import mteb
from mteb.task_selection import results_to_dataframe
tasks = mteb.get_tasks(
task_types=["Retrieval"], languages=["eng", "fra"], domains=["Legal"]
)
model_names = [
"GritLM/GritLM-7B",
"intfloat/multilingual-e5-small",
"intfloat/multilingual-e5-base",
"intfloat/multilingual-e5-large",
]
models = [mteb.get_model_meta(name) for name in model_names]
results = mteb.load_results(models=models, tasks=tasks)
df = results_to_dataframe(results)
have your found contamination in the training data of a model? Please let us know, either by opening an issue or ideally by submitting a PR annotatig the training datasets of the model:
model_w_contamination = ModelMeta(
name = "model-with-contamination"
...
training_datasets: {"ArguAna": # name of dataset within MTEB
["test"]} # the splits that have been trained on
...
)
It is possible to completely deploy the leaderboard locally or self-host it. This can e.g. be relevant for companies that might want to integrate build their own benchmarks or integrate custom tasks into existing benchmarks.
Running the leaderboard is quite easy. Simply run:
python -m mteb.leaderboard.app
The leaderboard requires gradio install, which can be installed using pip install mteb[gradio] and requires python >3.10.
There are times you may want to cache the embeddings so you can re-use them. This may be true if you have multiple query sets for the same corpus (e.g. Wikipedia) or are doing some optimization over the queries (e.g. prompting, other experiments). You can setup a cache by using a simple wrapper, which will save the cache per task in the cache_embeddings/{task_name} folder:
# define your task and model above as normal
...
# wrap the model with the cache wrapper
from mteb.models.cache_wrapper import CachedEmbeddingWrapper
model_with_cached_emb = CachedEmbeddingWrapper(model, cache_path='path_to_cache_dir')
# run as normal
evaluation.run(model, ...)
| Documentation | |
|---|---|
| 📋 Tasks | Overview of available tasks |
| 📐 Benchmarks | Overview of available benchmarks |
| 📈 Leaderboard | The interactive leaderboard of the benchmark |
| 🤖 Adding a model | Information related to how to submit a model to MTEB and to the leaderboard |
| 👩🔬 Reproducible workflows | Information related to how to reproduce and create reproducible workflows with MTEB |
| 👩💻 Adding a dataset | How to add a new task/dataset to MTEB |
| 👩💻 Adding a benchmark | How to add a new benchmark to MTEB and to the leaderboard |
| 🤝 Contributing | How to contribute to MTEB and set it up for development |
| 🌐 MMTEB | An open-source effort to extend MTEB to cover a broad set of languages |
| 🖼️ MIEB | Extension of MTEB to image embeddings |
MTEB was introduced in "MTEB: Massive Text Embedding Benchmark", feel free to cite:
@article{muennighoff2022mteb,
doi = {10.48550/ARXIV.2210.07316},
url = {https://arxiv.org/abs/2210.07316},
author = {Muennighoff, Niklas and Tazi, Nouamane and Magne, Lo{\"\i}c and Reimers, Nils},
title = {MTEB: Massive Text Embedding Benchmark},
publisher = {arXiv},
journal={arXiv preprint arXiv:2210.07316},
year = {2022}
}
You may also want to read and cite the amazing work that has extended MTEB & integrated new datasets:
For works that have used MTEB for benchmarking, you can find them on the leaderboard.
(top 30 of 132)
Jupyter Notebook
58.6%
Python
41.4%
Installation | Usage | Leaderboard | Documentation | Citing
pip install mteb
import mteb
from sentence_transformers import SentenceTransformer
# Define the sentence-transformers model name
model_name = "average_word_embeddings_komninos"
model = mteb.get_model(model_name) # if the model is not implemented in MTEB it will be eq. to SentenceTransformer(model_name)
tasks = mteb.get_tasks(tasks=["Banking77Classification"])
evaluation = mteb.MTEB(tasks=tasks)
results = evaluation.run(model, output_folder=f"results/{model_name}")
Prompts can be passed to the SentenceTransformer model using the prompts parameter. The following code shows how to use prompts with SentenceTransformer:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("average_word_embeddings_komninos", prompts={"query": "Query:", "passage": "Passage:"})
evaluation = mteb.MTEB(tasks=tasks)
In prompts the key can be:
passage, query) - they will be used in reranking and retrieval tasksBitextMiningClassificationMultilabelClassificationClusteringPairClassificationRerankingRetrievalSTSSummarizationInstructionRetrievalRetrival-query - these prompts will be used in all classification tasksNFCorpus-query - these prompts will be used in the specific taskmteb available_tasks
mteb run -m sentence-transformers/all-MiniLM-L6-v2 \
-t Banking77Classification \
--verbosity 3
# if nothing is specified default to saving the results in the results/{model_name} folder
Click on each section below to see the details.
Tasks can be selected by providing the list of datasets, but also
tasks = mteb.get_tasks(task_types=["Clustering", "Retrieval"]) # Only select clustering and retrieval tasks
tasks = mteb.get_tasks(categories=["s2s", "p2p"]) # Only select sentence2sentence and paragraph2paragraph datasets
tasks = mteb.get_tasks(languages=["eng", "deu"]) # Only select datasets which contain "eng" or "deu" (iso 639-3 codes)
You can also specify which languages to load for multilingual/cross-lingual tasks like below:
import mteb
tasks = [
mteb.get_task("AmazonReviewsClassification", languages = ["eng", "fra"]),
mteb.get_task("BUCCBitextMining", languages = ["deu"]), # all subsets containing "deu"
]
# or you can select specific huggingface subsets like this:
from mteb.tasks import AmazonReviewsClassification, BUCCBitextMining
evaluation = mteb.MTEB(tasks=[
AmazonReviewsClassification(hf_subsets=["en", "fr"]) # Only load "en" and "fr" subsets of Amazon Reviews
BUCCBitextMining(hf_subsets=["de-en"]), # Only load "de-en" subset of BUCC
])
# for an example of a HF subset see "Subset" in the dataset viewer at: https://huggingface.co/datasets/mteb/bucc-bitext-mining
mteb comes with a set of predefined benchmarks. These can be fetched using get_benchmark and run in a similar fashion to other sets of tasks.
For instance to select the 56 English datasets that form the "Overall MTEB English leaderboard":
import mteb
benchmark = mteb.get_benchmark("MTEB(eng, v1)")
evaluation = mteb.MTEB(tasks=benchmark)
The benchmark specified not only a list of tasks, but also what splits and language to run on. To get an overview of all available benchmarks simply run:
import mteb
benchmarks = mteb.get_benchmarks()
Generally we use the naming scheme for benchmarks MTEB(*), where the "*" denotes the target of the benchmark. In the case of a language, we use the three-letter language code. For large groups of languages, we use the group notation, e.g., MTEB(Scandinavian, v1) for Scandinavian languages. External benchmarks implemented in MTEB like CoIR use their original name. When using a benchmark from MTEB please cite mteb along with the citations of the benchmark which you can access using:
benchmark.citation
encode argumentsTo pass in arguments to the model's encode function, you can use the encode keyword arguments (encode_kwargs):
evaluation.run(model, encode_kwargs={"batch_size": 32})
You can evaluate only on test splits of all tasks by doing the following:
evaluation.run(model, eval_splits=["test"])
Note that the public leaderboard uses the test splits for all datasets except MSMARCO, where the "dev" split is used.
You can evaluate only on selected subsets. For example, if you want to evaluate only the subset_name_to_run subset of all tasks, do the following:
evaluation.run(model, eval_subsets=["subset_name_to_run"])
Monolingual tasks have default subset, other tasks have subsets that are specific to the dataset.
Models should implement the following interface, implementing an encode function taking as inputs a list of sentences, and returning a list of embeddings (embeddings can be np.array, torch.tensor, etc.). For inspiration, you can look at the mteb/mtebscripts repo used for running diverse models via SLURM scripts for the paper.
import mteb
from mteb.encoder_interface import PromptType
import numpy as np
class CustomModel:
def encode(
self,
sentences: list[str],
task_name: str,
prompt_type: PromptType | None = None,
**kwargs,
) -> np.ndarray:
"""Encodes the given sentences using the encoder.
Args:
sentences: The sentences to encode.
task_name: The name of the task.
prompt_type: The prompt type to use.
**kwargs: Additional arguments to pass to the encoder.
Returns:
The encoded sentences.
"""
pass
model = CustomModel()
tasks = mteb.get_tasks(tasks=["Banking77Classification"])
evaluation = MTEB(tasks=tasks)
evaluation.run(model)
To evaluate on a custom task, you can run the following code on your custom task. See how to add a new task, for how to create a new task in MTEB.
from mteb import MTEB
from mteb.abstasks.AbsTaskReranking import AbsTaskReranking
from sentence_transformers import SentenceTransformer
class MyCustomTask(AbsTaskReranking):
...
model = SentenceTransformer("average_word_embeddings_komninos")
evaluation = MTEB(tasks=[MyCustomTask()])
evaluation.run(model)
To use a cross encoder for reranking, you can directly use a CrossEncoder from SentenceTransformers. The following code shows a two-stage run with the second stage reading results saved from the first stage.
from mteb import MTEB
import mteb
from sentence_transformers import CrossEncoder, SentenceTransformer
cross_encoder = CrossEncoder("cross-encoder/ms-marco-TinyBERT-L-2-v2")
dual_encoder = SentenceTransformer("all-MiniLM-L6-v2")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
subset = "default" # subset name used in the NFCorpus dataset
eval_splits = ["test"]
evaluation = MTEB(tasks=tasks)
evaluation.run(
dual_encoder,
eval_splits=eval_splits,
save_predictions=True,
output_folder="results/stage1",
)
evaluation.run(
cross_encoder,
eval_splits=eval_splits,
top_k=5,
save_predictions=True,
output_folder="results/stage2",
previous_results=f"results/stage1/NFCorpus_{subset}_predictions.json",
)
from mteb import MTEB
import mteb
colbert = mteb.get_model("colbert-ir/colbertv2.0")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
eval_splits = ["test"]
evaluation = MTEB(tasks=tasks)
evaluation.run(
colbert,
eval_splits=eval_splits,
corpus_chunk_size=500,
)
This implementation employs the MaxSim operation to compute the similarity between sentences. While MaxSim provides high-quality results, it processes a larger number of embeddings, potentially leading to increased resource usage. To manage resource consumption, consider lowering the corpus_chunk_size parameter.
To save the predictions from a retrieval task, add the --save_predictions flag in the CLI or set save_predictions=True in the run method. The filename will be in the "{task_name}_{subset}_predictions.json" format.
Python:
from mteb import MTEB
import mteb
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
tasks = mteb.get_tasks(tasks=["NFCorpus"], languages=["eng"])
evaluation = MTEB(tasks=tasks)
evaluation.run(
model,
eval_splits=["test"],
save_predictions=True,
output_folder="results",
)
CLI:
mteb run -t NFCorpus -m all-MiniLM-L6-v2 --output_folder results --save_predictions
Multiple models have already been run on tasks available within MTEB. These results are available results repository.
To make the results more easily accessible, we have designed custom functionality for retrieving from the repository. For instance, if you are selecting the best model for your French and English retrieval task on legal documents you could fetch the relevant tasks and create a dataframe of the results using the following code:
import mteb
from mteb.task_selection import results_to_dataframe
tasks = mteb.get_tasks(
task_types=["Retrieval"], languages=["eng", "fra"], domains=["Legal"]
)
model_names = [
"GritLM/GritLM-7B",
"intfloat/multilingual-e5-small",
"intfloat/multilingual-e5-base",
"intfloat/multilingual-e5-large",
]
models = [mteb.get_model_meta(name) for name in model_names]
results = mteb.load_results(models=models, tasks=tasks)
df = results_to_dataframe(results)
have your found contamination in the training data of a model? Please let us know, either by opening an issue or ideally by submitting a PR annotatig the training datasets of the model:
model_w_contamination = ModelMeta(
name = "model-with-contamination"
...
training_datasets: {"ArguAna": # name of dataset within MTEB
["test"]} # the splits that have been trained on
...
)
It is possible to completely deploy the leaderboard locally or self-host it. This can e.g. be relevant for companies that might want to integrate build their own benchmarks or integrate custom tasks into existing benchmarks.
Running the leaderboard is quite easy. Simply run:
python -m mteb.leaderboard.app
The leaderboard requires gradio install, which can be installed using pip install mteb[gradio] and requires python >3.10.
There are times you may want to cache the embeddings so you can re-use them. This may be true if you have multiple query sets for the same corpus (e.g. Wikipedia) or are doing some optimization over the queries (e.g. prompting, other experiments). You can setup a cache by using a simple wrapper, which will save the cache per task in the cache_embeddings/{task_name} folder:
# define your task and model above as normal
...
# wrap the model with the cache wrapper
from mteb.models.cache_wrapper import CachedEmbeddingWrapper
model_with_cached_emb = CachedEmbeddingWrapper(model, cache_path='path_to_cache_dir')
# run as normal
evaluation.run(model, ...)
| Documentation | |
|---|---|
| 📋 Tasks | Overview of available tasks |
| 📐 Benchmarks | Overview of available benchmarks |
| 📈 Leaderboard | The interactive leaderboard of the benchmark |
| 🤖 Adding a model | Information related to how to submit a model to MTEB and to the leaderboard |
| 👩🔬 Reproducible workflows | Information related to how to reproduce and create reproducible workflows with MTEB |
| 👩💻 Adding a dataset | How to add a new task/dataset to MTEB |
| 👩💻 Adding a benchmark | How to add a new benchmark to MTEB and to the leaderboard |
| 🤝 Contributing | How to contribute to MTEB and set it up for development |
| 🌐 MMTEB | An open-source effort to extend MTEB to cover a broad set of languages |
| 🖼️ MIEB | Extension of MTEB to image embeddings |
MTEB was introduced in "MTEB: Massive Text Embedding Benchmark", feel free to cite:
@article{muennighoff2022mteb,
doi = {10.48550/ARXIV.2210.07316},
url = {https://arxiv.org/abs/2210.07316},
author = {Muennighoff, Niklas and Tazi, Nouamane and Magne, Lo{\"\i}c and Reimers, Nils},
title = {MTEB: Massive Text Embedding Benchmark},
publisher = {arXiv},
journal={arXiv preprint arXiv:2210.07316},
year = {2022}
}
You may also want to read and cite the amazing work that has extended MTEB & integrated new datasets:
For works that have used MTEB for benchmarking, you can find them on the leaderboard.
(top 30 of 132)
Jupyter Notebook
58.6%
Python
41.4%