---
language:
- el
- en
license: other
license_name: openmdw-1.1
base_model: nvidia/Nemotron-3-Embed-1B-BF16
pipeline_tag: sentence-similarity
library_name: sentence-transformers
tags:
- greek
- english
- retrieval
- rag
- embeddings
- sentence-transformers
- nemotron
model-index:
- name: Sophea-Nemo-Embedding
results:
- task:
type: sentence-similarity
name: Greek+English retrieval (5 domains, cosine IR)
dataset:
type: retrieval
name: Internal Greek+English retrieval benchmark
metrics:
- type: nDCG@10
name: nDCG@10 (mean of 5 domains)
value: 0.8176
- type: recall@10
name: Recall@10 (mean of 5 domains)
value: 0.9310
---

Sophea-Nemo-Embedding
Greek + English dense retriever — fine-tuned NVIDIA Nemotron-3-Embed-1B
**Sophea-Nemo-Embedding** is a Greek + English **dense retrieval embedder**, fine-tuned from
**[NVIDIA Nemotron-3-Embed-1B](https://huggingface.co/nvidia/Nemotron-3-Embed-1B-BF16)** for Greek and
English retrieval. It is the first stage of a two-stage Greek RAG
stack; the matching second stage is
**[Sophea-Nemo-Reranker](https://huggingface.co/KIEFERSA/Sophea-Nemo-Reranker)**.
- **Creator:** Kiefer SA
- **Base model:** `nvidia/Nemotron-3-Embed-1B-BF16` (Ministral-3 backbone, **bidirectional**, mean
pooling with `include_prompt=true`, 2048-d Matryoshka-sliceable, L2-normalized)
- **Languages:** Greek + English
- **Prompts:** `query: ` on queries, `passage: ` on documents (both sides prompted)
- **Training:** full fine-tune, InfoNCE (in-batch + 7 hard negatives), 1 epoch, max-len 4096, bf16
> **Greek is out-of-distribution for the base.** Nemotron-3-Embed lists 34 languages and **Greek is
> not one of them** — which is exactly why the base retrieves poorly on Greek and why this fine-tune
> exists.
## Why it matters — base vs fine-tuned
On our held-out 5-domain Greek+English retrieval eval (cosine IR, `query: `/`passage: ` prompts), the
fine-tune roughly **2.5×'s** the base embedder's retrieval quality — on **every** domain.

| metric |
Val |
Energy |
Legal |
Finance |
Medical |
Mean |
| nDCG@10 — base | 0.382 | 0.345 | 0.526 | 0.194 | 0.209 | 0.331 |
| nDCG@10 — fine-tuned | 0.875 | 0.794 | 0.950 | 0.722 | 0.747 | 0.818 |
| Δ nDCG@10 | +0.493 | +0.448 | +0.424 | +0.528 | +0.538 | +0.486 |
| Recall@10 — base | 0.465 | 0.464 | 0.599 | 0.283 | 0.314 | 0.425 |
| Recall@10 — fine-tuned | 0.963 | 0.898 | 0.984 | 0.903 | 0.906 | 0.931 |
**Read.** Mean **nDCG@10 0.331 → 0.818
(+0.486)**, with the largest gains on the hardest
domains (finance +0.53, medical +0.54). Recall@10 climbs from a mean 0.425
to **0.931** — i.e. the right passage is now almost always in the top-10.
## Size comparison — vs base Qwen3-Embedding (off-the-shelf)
Same 5-domain retrieval eval, same corpus/prompts. Your **fine-tuned 1B** embedder beats the
**base Qwen3-Embedding-8B by a wide margin** (nDCG@10):
| model |
Val |
Energy |
Legal |
Finance |
Medical |
Mean |
| Sophea-Nemo-Embedding (ours · 1B · fine-tuned) | 0.875 | 0.794 | 0.950 | 0.722 | 0.747 | 0.818 |
| Qwen3-Embedding-8B (base, off-the-shelf) | 0.740 | 0.580 | 0.910 | 0.490 | 0.602 | 0.664 |
| Qwen3-Embedding-4B (base, off-the-shelf) | 0.738 | 0.579 | 0.919 | 0.501 | 0.586 | 0.665 |
| Qwen3-Embedding-0.6B (base, off-the-shelf) | 0.658 | 0.509 | 0.863 | 0.426 | 0.467 | 0.585 |
**Read.** Mean nDCG@10 **0.818** (ours, 1B) vs **0.664** (8B),
**0.665** (4B), **0.585** (0.6B). Note the Qwen 8B ≈ 4B —
scaling the off-the-shelf model barely helps on Greek, whereas a 1B **fine-tuned** on-domain wins by
**+0.153** over the 8×-larger model.
## End-to-end two-stage pipeline
The two models are designed to run **together**: the embedder retrieves the top-50 candidates, the
reranker re-orders them. Measured end-to-end on the same 5-domain Greek+English eval (150 queries/set,
correct `query:`/`passage:` prompts):

| metric |
Val |
Energy |
Legal |
Finance |
Medical |
Mean |
| nDCG@10 — embedder alone | 0.863 | 0.802 | 0.939 | 0.702 | 0.689 | 0.799 |
| nDCG@10 — + reranker (stack) | 0.867 | 0.780 | 0.976 | 0.763 | 0.703 | 0.818 |
| Δ from reranking | +0.004 | -0.022 | +0.037 | +0.061 | +0.013 | +0.019 |
| Recall@10 — full stack | 0.987 | 0.873 | 0.993 | 0.920 | 0.860 | 0.927 |
**Read.** The full stack reaches **mean nDCG@10 0.818** (Recall@10 0.927) — the
strongest configuration measured. The reranker adds the most where the embedder is weakest
(**finance +0.061, legal +0.037**), i.e. it sharpens precision on the hard
cases. On **energy** it slightly regresses (-0.022) and on `val` the gain is marginal,
because the embedder alone is already very strong there and leaves little headroom — for the easiest,
already-high-recall domains you can skip the rerank stage if latency matters.
## Usage (sentence-transformers)
```python
from sentence_transformers import SentenceTransformer
m = SentenceTransformer("KIEFERSA/Sophea-Nemo-Embedding")
q = m.encode(["Ποια είναι η πρωτεύουσα της Ελλάδας;"], prompt="query: ", normalize_embeddings=True)
d = m.encode(["Η Αθήνα είναι η πρωτεύουσα της Ελλάδας."], prompt="passage: ", normalize_embeddings=True)
print((q @ d.T)) # cosine similarity
```
Both sides **must** be prompted (`query: ` / `passage: `) — the base uses `include_prompt=true`, so
dropping the prefix is a distribution mismatch. Embeddings are L2-normalized (use cosine / dot).
## Serving with vLLM
```bash
vllm serve KIEFERSA/Sophea-Nemo-Embedding --runner pooling
```
Exposes an OpenAI-compatible `/v1/embeddings` endpoint. vLLM does **not** auto-apply the model's ST
prompts, so prepend them **client-side** — `query: ` on queries, `passage: ` on documents:
```python
from openai import OpenAI
c = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
name = "KIEFERSA/Sophea-Nemo-Embedding"
q = c.embeddings.create(model=name, input=["query: Ποια είναι η πρωτεύουσα της Ελλάδας;"]).data[0].embedding
d = c.embeddings.create(model=name, input=["passage: Η Αθήνα είναι η πρωτεύουσα της Ελλάδας."]).data[0].embedding
```
## License
Fine-tune of `nvidia/Nemotron-3-Embed-1B-BF16` — governed by **OpenMDW-1.1** (base Ministral-3 is
Apache-2.0); commercial use permitted under those terms. Review the base model's license before use.