exoldoff/bge-reranker-v2-m3-cross-encoder-marketplaces-rus
Fine-tuned cross-encoder reranker for Russian marketplace SKU deduplication.
The model is based on BAAI/bge-reranker-v2-m3 and was fine-tuned to score whether two marketplace product records describe the same base SKU.
It is intended for pairwise product matching / entity resolution pipelines where candidate pairs are generated first, then this model reranks or classifies those pairs.
Critical Scope
This model is intentionally narrow. It was built for Russian marketplace catalog data, not for general semantic ranking or universal product matching.
- Marketplaces: Ozon, Yandex Market / Яндекс.Маркет, Wildberries / WB / ВБ.
- Supported categories: Sauces / Соусы / Соус, Coconut oil / Кокосовое масло, Soap / Мыло.
- Language/domain: Russian and mixed Russian marketplace product titles with structured SKU fields such as brand, category, marketplace, unit weight, total weight, and pack count.
Use outside these marketplaces or categories should be treated as experimental and must be recalibrated on target data before production use.
Intended Use
Given two structured product texts from the supported Russian marketplace categories, the model returns a score where a higher value means the pair is more likely to be the same base product.
The training target treats pack-count variants as positive when the underlying product is the same. For example, 1 x 500 ml and 2 x 500 ml may still be considered the same base SKU. Final pack-level grouping should be handled downstream with deterministic pack rules.
Typical pipeline:
- Generate candidate product pairs within one supported category using lexical or embedding retrieval.
- Score candidate pairs with this cross-encoder.
- Select a threshold on a dev split.
- Build product-family edges from pairs above the selected threshold.
- Apply deterministic pack/grouping logic after pairwise matching.
Model Details
- Model type: Sentence Transformers
CrossEncoder - Base model:
BAAI/bge-reranker-v2-m3 - Fine-tuned model id:
exoldoff/bge-reranker-v2-m3-cross-encoder-marketplaces-rus - Task: binary same-base-SKU scoring for marketplace product pairs
- Output: sigmoid probability-like score
- Max sequence length during training: 192 tokens
- Loss:
BinaryCrossEntropyLoss - Training precision: fp16
Training Data
The model was trained on a frozen multi-category Russian marketplace SKU deduplication dataset.
Training scope:
- Marketplaces: Ozon, Yandex Market / Яндекс.Маркет, Wildberries / WB / ВБ.
- Categories: Sauces / Соусы / Соус, Coconut oil / Кокосовое масло, Soap / Мыло.
Rows used by the training run:
| split | rows | negative | positive |
|---|---|---|---|
| train | 1404 | 859 | 545 |
| dev | 167 | 50 | 117 |
| test | 165 | 48 | 117 |
Input columns were converted into structured pair texts such as:
brand: ... | title: ... | subcategory: ... | marketplace: ... | unit_weight_kg: ... | total_weight_kg: ... | pack_count: ...
Labels:
1: same base product / exact duplicate for the ML layer0: different product
Evaluation
Metrics below are from the training manifest at the default 0.5 prediction threshold. In production or research comparison, select the operating threshold on a dev split according to the business cost of errors.
| split | accuracy | precision | recall | F1 | FP | FN |
|---|---|---|---|---|---|---|
| dev | 0.8982 | 0.9808 | 0.8718 | 0.9231 | 2 | 15 |
| test | 0.9212 | 0.9727 | 0.9145 | 0.9427 | 3 | 10 |
For SKU deduplication, false merges are usually more expensive than missed duplicates. Prefer cost-sensitive threshold calibration over blindly using 0.5.
Benchmark Comparison
The table below compares the selected BGE fine-tuned reranker with the main fine-tuned and zero-shot alternatives on the frozen SKU deduplication test split. The report uses thresholds selected on the dev split with the threshold_weighted_cost strategy.
Higher precision, recall, and F1 are better. Lower false merges and weighted cost are better. Weighted cost weights pair errors by available sales volume.
| model | type | precision | recall | F1 | false merges | false splits | weighted cost | note |
|---|---|---|---|---|---|---|---|---|
| BGE reranker FT | fine-tune | 1.000 | 0.795 | 0.886 | 0 | 24 | 131.3 | winner |
| mMARCO FT | fine-tune | 0.988 | 0.726 | 0.837 | 1 | 32 | 207.4 | strong FT |
| Qwen 0.6B FT | fine-tune | 0.963 | 0.667 | 0.788 | 3 | 39 | 310.8 | worse than BGE |
| Qwen 4B ZS | zero-shot | 0.879 | 0.492 | 0.630 | 4 | 30 | 188.4 | strong ZS |
| BGE reranker ZS | zero-shot | 0.927 | 0.436 | 0.593 | 4 | 66 | 477.8 | control |
| Qwen 0.6B ZS | zero-shot | 0.893 | 0.214 | 0.345 | 3 | 92 | 561.6 | low recall |
| mMARCO ZS | zero-shot | 0.878 | 0.308 | 0.456 | 5 | 81 | 598.8 | low recall |
| RuBERT tiny2 FT | fine-tune | 1.000 | 0.034 | 0.066 | 0 | 113 | 585.2 | did not converge |
Compared with the zero-shot BGE reranker baseline on the main test split:
- Weighted cost improved from 477.8 to 131.3.
- Recall improved from 0.436 to 0.795.
- False merges decreased from 4 to 0.
Freeze: 2465 binary pairs from the multi-category labeling set; training-ready split 1404 / 167 / 165.
Usage
Install:
pip install -U sentence-transformers
Run pair scoring:
from sentence_transformers import CrossEncoder
model = CrossEncoder("exoldoff/bge-reranker-v2-m3-cross-encoder-marketplaces-rus")
pairs = [
(
"brand: heinz | title: соус томатный heinz 500 г | category: Соус | marketplace: Ozon | unit_weight_kg: 0.5 | total_weight_kg: 0.5 | pack_count: 1",
"brand: heinz | title: томатный соус heinz 500г | category: Соусы | marketplace: Яндекс.Маркет | unit_weight_kg: 0.5 | total_weight_kg: 0.5 | pack_count: 1",
),
(
"brand: example | title: мыло жидкое алоэ 500 мл | category: Мыло | marketplace: WB | unit_weight_kg: 0.5 | total_weight_kg: 0.5 | pack_count: 1",
"brand: example | title: мыло туалетное детское 90 г | category: Мыло | marketplace: Ozon | unit_weight_kg: 0.09 | total_weight_kg: 0.09 | pack_count: 1",
),
]
scores = model.predict(pairs)
print(scores)
For explicit sigmoid output in newer Sentence Transformers versions:
import torch
from sentence_transformers import CrossEncoder
model = CrossEncoder("exoldoff/bge-reranker-v2-m3-cross-encoder-marketplaces-rus")
scores = model.predict(pairs, activation_fn=torch.nn.Sigmoid())
Limitations
- This model is only trained and documented for Russian marketplace SKU deduplication on Ozon, Yandex Market / Яндекс.Маркет, and Wildberries / WB / ВБ.
- Supported categories are limited to Sauces / Соусы / Соус, Coconut oil / Кокосовое масло, and Soap / Мыло.
- This model is a reranker/classifier for candidate pairs, not a candidate generator.
- It is not a universal product matcher and is not validated for other marketplace domains, countries, languages, or categories.
- Scores should be calibrated on the target catalog and business objective.
- The model predicts same base product, not final pack identity. Pack-size resolution should happen downstream.
- The dataset is small enough that category-specific blind spots are possible.
Training Configuration
Selected hyperparameters:
| parameter | value |
|---|---|
| epochs | 3 |
| learning rate | 2e-5 |
| train batch size | 8 |
| eval batch size | 16 |
| gradient accumulation | 4 |
| warmup ratio | 0.1 |
| weight decay | 0.01 |
| pos weight | 1.5761 |
| seed | 42 |
Runtime package versions from the manifest:
| package | version |
|---|---|
| sentence-transformers | 5.6.0 |
| transformers | 5.12.1 |
| datasets | 5.0.0 |
| accelerate | 1.14.0 |
| torch | 2.7.1+cu128 |
Provenance
- Base model:
BAAI/bge-reranker-v2-m3 - Fine-tuned model id:
exoldoff/bge-reranker-v2-m3-cross-encoder-marketplaces-rus