A
Turkish sentence-embedding (bi-encoder) model for
retrieval and semantic
search, fine-tuned from
intfloat/multilingual-e5-base
with contrastive learning (
MultipleNegativesRankingLoss) on Turkish NLI triplets.
Omitting the prefixes degrades quality noticeably.
1from sentence_transformers import SentenceTransformer
2from sentence_transformers.util import cos_sim
3
4model = SentenceTransformer("thealper2/intfloat-multilingual-e5-base-tr-nli")
5
6# Asymmetric retrieval: query vs. candidate passages
7query = "query: Türkiye'nin başkenti neresidir?"
8passages = [
9 "passage: Ankara, Türkiye'nin başkentidir.",
10 "passage: İstanbul Türkiye'nin en kalabalık şehridir.",
11 "passage: Muz tropikal bir meyvedir.",
12]
13q = model.encode(query, normalize_embeddings=True)
14p = model.encode(passages, normalize_embeddings=True)
15print(cos_sim(q, p)) # highest score -> the Ankara passage
1a = model.encode("query: Bugün hava çok güzel.", normalize_embeddings=True)
2b = model.encode("query: Hava bugün oldukça güzel.", normalize_embeddings=True)
3print(float(cos_sim(a, b))) # ~0.9
1import torch, torch.nn.functional as F
2from transformers import AutoTokenizer, AutoModel
3
4tok = AutoTokenizer.from_pretrained("thealper2/intfloat-multilingual-e5-base-tr-nli")
5mdl = AutoModel.from_pretrained("thealper2/intfloat-multilingual-e5-base-tr-nli")
6
7def encode(texts):
8 batch = tok(texts, padding=True, truncation=True, max_length=256, return_tensors="pt")
9 with torch.no_grad():
10 out = mdl(**batch)
11 mask = batch["attention_mask"].unsqueeze(-1).float()
12 emb = (out.last_hidden_state * mask).sum(1) / mask.sum(1) # mean pooling
13 return F.normalize(emb, p=2, dim=1)
14
15emb = encode(["query: örnek cümle", "passage: örnek pasaj"])
-
Source: mertcobanov/all-nli-triplets-turkish
— a machine-translated Turkish version of the AllNLI (SNLI + MultiNLI) triplet set.
-
Format: (anchor, positive, negative) triplets, where the negative acts as a
hard negative for the contrastive objective.
-
Column handling: Only the Turkish columns (anchor_translated,
positive_translated, negative_translated) were used and renamed to
anchor / positive / negative. All English columns were discarded.
-
Cleaning: rows with None / empty / whitespace-only fields were filtered out.
-
Resulting sizes (after filtering):
| Split | Triplets |
|---|
| train | 277,167 |
| dev | 6,584 |
| test | 6,609 |
Measured on the dataset's own test triplets (
TripletEvaluator, cosine accuracy) and
on the external Turkish STS set
emrecan/stsb-mt-turkish
(
EmbeddingSimilarityEvaluator, Spearman; scores normalised 0–5 → 0–1):
Evaluated on the
TR-MTEB datasets
(Baysan & Güngör,
TR-MTEB, Findings of EMNLP 2025).
1@misc{e5-tr-nli,
2 title = {e5-tr-nli: A Turkish Sentence Embedding Model},
3 note = {Fine-tuned from intfloat/multilingual-e5-base on Turkish NLI triplets},
4 year = {2026}
5}
1@inproceedings{baysan-gungor-2025-trmteb,
2 title = {{TR-MTEB}: A Comprehensive Benchmark and Embedding Model Suite for {T}urkish Sentence Representations},
3 author = {Baysan, Mehmet Selman and G{\"u}ng{\"o}r, Tunga},
4 booktitle = {Findings of the Association for Computational Linguistics: EMNLP 2025},
5 year = {2025}
6}
1@article{wang2024multilingual,
2 title = {Multilingual E5 Text Embeddings: A Technical Report},
3 author = {Wang, Liang and Yang, Nan and Huang, Xiaolong and Yang, Linjun and Majumder, Rangan and Wei, Furu},
4 journal = {arXiv preprint arXiv:2402.05672},
5 year = {2024}
6}
The full pipeline (data prep, Optuna sweep, training, and TR-MTEB evaluation) is scripted:
1from sentence_transformers import SentenceTransformer
2SentenceTransformer("models/e5-tr-nli-final").push_to_hub("thealper2/intfloat-multilingual-e5-base-tr-nli")