bge-reranker-v2-m3-legal — Greek legal reranker
Cross-encoder reranker fine-tuned from BAAI/bge-reranker-v2-m3 for Greek legal and statutory/administrative retrieval. Companion to the bge-m3-legal-v4 embedder.
Single output score, max sequence length 512, ~568M parameters. Shipped as
safetensors and as an int8-quantised ONNX graph (onnx/model_quantized.onnx)
for CPU-class client hardware.
Results
Reranking the top-20 candidates returned by bge-m3-legal-v4, on held-out
Greek sets (recall@1):
| held-out set | first stage (v4 dense) | + stock bge-reranker-v2-m3 | + this model |
|---|---|---|---|
| Greek legal (n=1200) | 92.2 | 68.8 | 89.2 |
| Greek statute/admin (n=800) | 77.8 | 73.1 | 70.0 |
| Greek general | — | ~tie | ~tie |
Read the table before you deploy this
Two findings matter more than the headline +20.4:
The stock reranker actively damages a fine-tuned retriever. Placing stock
bge-reranker-v2-m3 after bge-m3-legal-v4 costs ~23 points of legal recall@1
versus not reranking at all. If you fine-tune the first stage and leave the
reranker stock, you have made your pipeline worse. Upgrade both together, or
neither.
On its own native registers, v4 dense alone still beats reranking. 92.2 > 89.2. A cross-encoder cannot add information the first stage already ordered correctly; it can only reorder, and every reorder is a chance to be wrong. This model earns its place where the candidate list is noisier than pure v4 dense — hybrid BM25 + dense fusion, keyword-heavy queries, cross-register corpora — not as a reflex stage after a strong dense retriever on in-domain text.
Practical guidance: blend the cross-encoder score with the first-stage score rather than replacing it, and consider skipping the rerank entirely when the first-stage margin is already decisive.
Usage
from sentence_transformers import CrossEncoder
model = CrossEncoder("pan0sk/bge-reranker-v2-m3-legal", max_length=512)
query = "Ποια είναι η προθεσμία άσκησης έφεσης κατά πρωτόδικης απόφασης;"
candidates = [
"Η προθεσμία της έφεσης είναι τριάντα ημέρες από την επίδοση της απόφασης, "
"εφόσον ο διάδικος διαμένει στην Ελλάδα.",
"Το δικαστήριο εξέτασε τη συνδρομή των προϋποθέσεων της αναγκαστικής εκτέλεσης.",
]
print(model.rank(query, candidates))
The ONNX graph is drop-in for onnxruntime / transformers.js deployments:
from huggingface_hub import hf_hub_download
onnx_path = hf_hub_download("pan0sk/bge-reranker-v2-m3-legal",
"onnx/model_quantized.onnx")
Training
- Objective:
BinaryCrossEntropyLosswithpos_weight = 6, matching the 6 negatives mined per query. - Negatives: mined by the frozen
bge-m3-legal-v4embedder — i.e. by the retriever this reranker actually sits behind — from each query's top-100, with any candidate scoring above 0.95 × the positive's score discarded as a likely false negative. Mining with the serving retriever is the point: the reranker learns to fix the mistakes it will really be asked to fix. - Data: ~759k query/passage pairs over Greek legal, statutory/administrative and general-Greek registers.
- Hyperparameters: 1 epoch, batch 64, lr 2e-5, warmup ratio 0.1, weight decay 0.01, bf16, max sequence length 512.
Limitations
- Tuned for Greek. English and cross-lingual behaviour is inherited from the base model and was not a training target.
- The 512-token limit means long passages are truncated; chunk before reranking.
- Evaluated on rank-the-true-passage recall, which rewards ordering rather than calibration. The raw scores are not probabilities and are not comparable across queries without normalisation.
- Statute/administrative retrieval regressed slightly against the stock model (73.1 → 70.0). If that register dominates your workload, measure before adopting.
Licence
Apache-2.0, inherited from the base model.