nlpai-lab/KURE

๐Ÿ”Ž KURE: Korea University Retrieval Embedding models

Python

242

62 commits

updated Oct 12, 2026

See the code

README

๐Ÿ”Ž KURE: Korea University REtrieval models

KURE Logo

English | ํ•œ๊ตญ์–ด

KURE is a family of Korean-English retrieval embedding models developed by the NLP & AI Lab and the HIAI Institute at Korea University.

Update Logs

Models

ModelTypeParamsBase model
KURE-Sparse-baseLearned Sparse Retrieval (LSR)593Momai-research/milco-650m
KURE-Sparse-nanoLearned Sparse Retrieval (LSR)149Mnlpai-lab/KURE-v2-unsupervised
KURE-Reranker-baseReranker (cross-encoder)1.7BQwen/Qwen3-1.7B
KURE-Reranker-nanoReranker (cross-encoder)149Mskt/A.X-Encoder-base
KURE-v2Late-interaction (multi-vector)154Mskt/A.X-Encoder-base
KURE-v1Dense (single-vector)568MBAAI/bge-m3
KoE5Dense (single-vector)560Mintfloat/multilingual-e5-large

Environment

We use uv to manage the environment.

uv sync                                                # dense, sparse and cross-encoder models
uv sync --extra late-interaction --no-default-groups   # KURE-v2 with PyLate

Usage

KURE-Sparse

Sentence-Transformers
from sentence_transformers import SparseEncoder

model = SparseEncoder("nlpai-lab/KURE-Sparse-nano", trust_remote_code=True)
# model = SparseEncoder("nlpai-lab/KURE-Sparse-base", trust_remote_code=True)

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

# encode_query / encode_document add the query and document markers KURE-Sparse-nano expects
query_embeddings = model.encode_query(query)
document_embeddings = model.encode_document(documents)

# Dot-product scores (higher is more relevant)
scores = model.similarity(query_embeddings, document_embeddings)

KURE-Reranker

Sentence-Transformers
from sentence_transformers import CrossEncoder

model = CrossEncoder("nlpai-lab/KURE-Reranker-nano", max_length=8192)
# model = CrossEncoder("nlpai-lab/KURE-Reranker-base", max_length=8192)

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

# Higher is more relevant
results = model.rank(query, documents, return_documents=True)

KURE-v2

PyLate
uv add pylate
from pylate import indexes, models, retrieve

model = models.ColBERT(model_name_or_path="nlpai-lab/KURE-v2")

index = indexes.PLAID(index_folder="pylate-index", index_name="index", override=True)

documents_ids = ["1", "2", "3"]
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

documents_embeddings = model.encode(documents, is_query=False)
index.add_documents(documents_ids=documents_ids, documents_embeddings=documents_embeddings)

retriever = retrieve.ColBERT(index=index)
queries_embeddings = model.encode(["ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"], is_query=True)
scores = retriever.retrieve(queries_embeddings=queries_embeddings, k=10)
Sentence-Transformers
uv add sentence-transformers
from sentence_transformers import MultiVectorEncoder

model = MultiVectorEncoder("nlpai-lab/KURE-v2")

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
]

query_embeddings = model.encode_query(query)
document_embeddings = model.encode_document(documents)

# MaxSim late-interaction scoring (higher is more relevant)
scores = model.similarity(query_embeddings, document_embeddings)

KURE-v1 / KoE5

Sentence-Transformers
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("nlpai-lab/KURE-v1")
# model = SentenceTransformer("nlpai-lab/KoE5")  # needs "query: " / "passage: " prefixes

embeddings = model.encode(["์ฒซ ๋ฒˆ์งธ ๋ฌธ์žฅ", "๋‘ ๋ฒˆ์งธ ๋ฌธ์žฅ"])
similarities = model.similarity(embeddings, embeddings)

Evaluation

We evaluate on the nine MTEB(kor, v2) Retrieval tasks with the latest mteb (v2.x), using the Korean subsets only (Belebele: kor_Hang-kor_Hang; MLDR is the mean of its dev/test splits):

Late-interaction models are measured directly with mteb + PLAID retrieval. Dense rows come from the official MTEB results repository. To evaluate a model, pass its name and paradigm:

uv run --extra late-interaction --no-default-groups python eval/dense/evaluate.py nlpai-lab/KURE-v2 multi-vector
uv run python eval/dense/evaluate.py nlpai-lab/KURE-v1 single-vector

MTEB-ko-retrieval Leaderboard

Average over the nine tasks. Per-task scores are in eval/dense/results/README.md and on the official MTEB Leaderboard.

ModelTypeParamsAvg nDCG@10Avg Recall@10
nlpai-lab/KURE-v2Late-interaction154M0.81600.8921
nvidia/Nemotron-3-Embed-8B-BF16Dense8.0B0.81270.8934
yjoonjang/colbert-ko-en-v2Late-interaction149M0.80630.8827
sionic-ai/comsat-embed-ko-8b-previewDense7.6B0.79270.8876
lightonai/mLateOnLate-interaction307M0.79060.8740
Qwen/Qwen3-Embedding-8BDense7.6B0.78260.8815
nvidia/Nemotron-3-Embed-1B-BF16Dense1.1B0.78170.8690
Qwen/Qwen3-Embedding-4BDense4.0B0.77370.8753
perplexity-ai/pplx-embed-v1-4bDense4.0B0.77050.8699
microsoft/harrier-oss-v1-27bDense27.0B0.76670.8624
dragonkue/snowflake-arctic-embed-l-v2.0-koDense568M0.76530.8609
codefuse-ai/F2LLM-v2-8BDense7.6B0.76380.8593
telepix/PIXIE-Rune-v1.5Dense568M0.76180.8596
nlpai-lab/KURE-v1Dense568M0.76160.8629
nvidia/llama-nemotron-embed-1b-v2Dense1.2B0.75640.8560
dragonkue/BGE-m3-koDense568M0.75470.8513
BAAI/bge-m3Dense568M0.75090.8588
perplexity-ai/pplx-embed-v1-0.6bDense596M0.73900.8377
perplexity-ai/pplx-embed-v1-late-0.6bLate-interaction596M0.73810.8328
nlpai-lab/KoE5Dense560M0.73370.8300
nlpai-lab/KURE-v2-unsupervisedLate-interaction154M0.72830.8268
Qwen/Qwen3-Embedding-0.6BDense596M0.71400.8222
dragonkue/colbert-ko-0.1bLate-interaction149M0.67760.7723
yjoonjang/colbert-ko-v1Late-interaction149M0.62820.7212

Sparse Leaderboard

Learned sparse models are evaluated on the same nine tasks under the same conventions, with mteb's SparseEncoder wrapper in bf16 at up to 8,192 tokens and without pruning the vectors. Next to nDCG@10, we report the average number of active dimensions per query and per document, and FLOPs. To evaluate a sparse model:

uv run python eval/sparse/evaluate.py nlpai-lab/KURE-Sparse-nano

Results are averaged over the nine Korean retrieval tasks. The dashed lines mark dense models for reference. Per-task scores, along with English BEIR results, are in eval/sparse/results/README.md.

Average nDCG@10 vs. average FLOPs of sparse retrievers on the nine Korean tasks

ModelParamsAvg nDCG@10Query dimsDocument dimsFLOPs
nlpai-lab/KURE-Sparse-base593M0.79841001,89736.5
omai-research/milco-650m593M0.78241051,16732.3
nlpai-lab/KURE-Sparse-nano149M0.771614784323.0
telepix/PIXIE-Splade-v1.5149M0.76081171,54137.3
yjoonjang/splade-ko-v1149M0.752610974229.1
telepix/PIXIE-Splade-v1.0149M0.663612162522.4
opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1167M0.5444291766.8

Reranker Leaderboard

Rerankers are evaluated on the same nine tasks with the protocol of reranker-simple-benchmark: each query's candidates are its gold documents plus, as negatives, the BM25 top-50 minus the golds, every model runs in bf16 at up to 8,192 tokens, and we report nDCG@10 with throughput in pairs per second (PPS), measured on one NVIDIA RTX A6000 48GB. To evaluate a reranker:

bash eval/cross-encoder/fetch_eval_assets.sh   # once: the BM25 candidate pools
uv run python eval/cross-encoder/evaluate.py nlpai-lab/KURE-Reranker-nano --speed

Results are averaged over the nine Korean retrieval tasks. Per-task nDCG@10 and PPS are in eval/cross-encoder/results/README.md.

Mean nDCG@10 vs. mean PPS of rerankers on the nine Korean tasks

ModelParamsMean nDCG@10Mean PPS
Qwen/Qwen3-Reranker-8B8.2B0.899015.0
Qwen/Qwen3-Reranker-4B4.0B0.891624.3
KaLM-Embedding/KaLM-Reranker-V1-Large-R27.5B0.891025.3
nlpai-lab/KURE-Reranker-base1.7B0.880055.0
nlpai-lab/KURE-Reranker-nano149M0.8757482.4
zeroentropy/zerank-2-reranker4.0B0.865229.3
mixedbread-ai/mxbai-rerank-large-v21.5B0.860764.8
lightonai/LightOn-rerank-PW-4B4.5B0.860515.1
Qwen/Qwen3-Reranker-0.6B596M0.8528101.0
BAAI/bge-reranker-v2-m3568M0.8518412.6
nvidia/llama-nemotron-rerank-1b-v21.2B0.8468128.2
nlpai-lab/LAMAR-600m568M0.8375415.0
dragonkue/bge-reranker-v2-m3-ko568M0.8199409.1
BAAI/bge-reranker-v2-gemma2.5B0.809958.8
upskyy/ko-reranker-8k568M0.8054409.8
Dongjin-kr/ko-reranker560M0.7861488.0
telepix/PIXIE-Spell-Reranker-Preview-0.6B596M0.776099.7

Training Details

KURE-Sparse

Training code in train/sparse.

  • Distilled from a Qwen3-Reranker-8B teacher on the KURE-v2 SFT data with an in-batch contrastive term plus a KL term over each query's candidates, an L1 sparsity penalty on queries and documents, up to 8,192 tokens, 1 epoch.
  • KURE-Sparse-base: fine-tuned from omai-research/milco-650m, scoring over 30,522 English pivot terms plus 250,002 source-language tokens.
  • KURE-Sparse-nano: the A.X-Encoder-base MLM head grafted onto KURE-v2-unsupervised, pre-finetuned on 20.7M pairs, then fine-tuned. Resulting in 36,282 vocabulary terms.

KURE-Reranker

Training code in train/cross-encoder.

  • Distilled from a Qwen3-Reranker teacher with pointwise MSE on the KURE-v2 SFT data flattened to 33.3M query-document pairs, 1 epoch.
  • KURE-Reranker-base: Qwen/Qwen3-1.7B scored as logit("yes") โˆ’ logit("no") over the Qwen3-Reranker template; up to 8,192 tokens.
  • KURE-Reranker-nano: skt/A.X-Encoder-base with a single-logit head; up to 8,192 tokens.

KURE-v2

The full two-stage training code is in train/late-interaction.

  • Built on skt/A.X-Encoder-base with a multi-layer projection head (128-d per token, MaxSim scoring); trained with PyLate.
  • Stage 1 (PFT): large in-batch contrastive learning on 20.7M weakly related Korean/English pairs, released as KURE-v2-unsupervised.
  • Stage 2 (SFT): contrastive learning + KL distillation from a reranker teacher on 3.03M triplets with hard negatives and false-negative filtering.

KURE-v1

Training code in train/dense.

  • Fine-tuned from BAAI/bge-m3 on ~2M Korean query-document-hard-negative(5) pairs.
  • CachedGISTEmbedLoss, batch size 4,096, lr 2e-5, 1 epoch.

KoE5

Serving

Index-size and latency benchmarks of KURE-v2 across ANN backends, token pooling and binary quantization, with runnable configurations, are in deploy/late-interaction.

License

MIT

Citation

If you find our models helpful, please consider citing:

@misc{kure-reranker,
  title  = {KURE-Reranker: Korean-English bilingual reranking models},
  author = {Jang, Youngjoon and Hong, Seongtae and Son, Junyoung and Lee, Taemin and Lim, Heuiseok},
  year   = {2026},
  url    = {https://huggingface.co/nlpai-lab/KURE-Reranker-base},
}
@misc{kure-v2,
  title  = {KURE-v2: a Korean-English bilingual late-interaction retriever},
  author = {Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Lim, Heuiseok},
  year   = {2026},
  url    = {https://huggingface.co/nlpai-lab/KURE-v2},
}
@inproceedings{jang2025kure,
  title={KURE: Embedding Model for Korean-Specific Retrieval},
  author={Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Park, JeongBae and Lim, Heuiseok},
  booktitle={Annual Conference on Human and Language Technology},
  pages={129--134},
  year={2025},
  organization={Human and Language Technology}
}
@inproceedings{jang2024koe5,
  title={KoE5: A New Dataset and Model for Improving Korean Embedding Performance},
  author={Jang, Youngjoon and Son, Junyoung and Park, Chanjun and Choi, Soonwoo and Lee, Byeonggoo and Lee, Taemin and Lim, Heuiseok},
  booktitle={Annual Conference on Human and Language Technology},
  pages={239--244},
  year={2024},
  organization={Human and Language Technology}
}

Significant stargazers

Kevin Ko

941 followers ยท starred Dec 2024

Heegyu Kim

135 followers ยท starred Dec 2024

Junbum Lee

954 followers ยท starred Dec 2024

Yohan Na

59 followers ยท starred Dec 2024

nlpai-lab/KURE

๐Ÿ”Ž KURE: Korea University Retrieval Embedding models

Python

242

62 commits

updated Oct 12, 2026

See the code

README

๐Ÿ”Ž KURE: Korea University REtrieval models

KURE Logo

English | ํ•œ๊ตญ์–ด

KURE is a family of Korean-English retrieval embedding models developed by the NLP & AI Lab and the HIAI Institute at Korea University.

Update Logs

Models

ModelTypeParamsBase model
KURE-Sparse-baseLearned Sparse Retrieval (LSR)593Momai-research/milco-650m
KURE-Sparse-nanoLearned Sparse Retrieval (LSR)149Mnlpai-lab/KURE-v2-unsupervised
KURE-Reranker-baseReranker (cross-encoder)1.7BQwen/Qwen3-1.7B
KURE-Reranker-nanoReranker (cross-encoder)149Mskt/A.X-Encoder-base
KURE-v2Late-interaction (multi-vector)154Mskt/A.X-Encoder-base
KURE-v1Dense (single-vector)568MBAAI/bge-m3
KoE5Dense (single-vector)560Mintfloat/multilingual-e5-large

Environment

We use uv to manage the environment.

uv sync                                                # dense, sparse and cross-encoder models
uv sync --extra late-interaction --no-default-groups   # KURE-v2 with PyLate

Usage

KURE-Sparse

Sentence-Transformers
from sentence_transformers import SparseEncoder

model = SparseEncoder("nlpai-lab/KURE-Sparse-nano", trust_remote_code=True)
# model = SparseEncoder("nlpai-lab/KURE-Sparse-base", trust_remote_code=True)

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

# encode_query / encode_document add the query and document markers KURE-Sparse-nano expects
query_embeddings = model.encode_query(query)
document_embeddings = model.encode_document(documents)

# Dot-product scores (higher is more relevant)
scores = model.similarity(query_embeddings, document_embeddings)

KURE-Reranker

Sentence-Transformers
from sentence_transformers import CrossEncoder

model = CrossEncoder("nlpai-lab/KURE-Reranker-nano", max_length=8192)
# model = CrossEncoder("nlpai-lab/KURE-Reranker-base", max_length=8192)

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

# Higher is more relevant
results = model.rank(query, documents, return_documents=True)

KURE-v2

PyLate
uv add pylate
from pylate import indexes, models, retrieve

model = models.ColBERT(model_name_or_path="nlpai-lab/KURE-v2")

index = indexes.PLAID(index_folder="pylate-index", index_name="index", override=True)

documents_ids = ["1", "2", "3"]
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
    "ํ•œ๋ผ์‚ฐ์€ ํ•ด๋ฐœ 1,947m๋กœ ๋‚จํ•œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ์‚ฐ์ด๋ฉฐ ์ œ์ฃผ๋„ ์ค‘์•™์— ์ž๋ฆฌํ•œ๋‹ค.",
]

documents_embeddings = model.encode(documents, is_query=False)
index.add_documents(documents_ids=documents_ids, documents_embeddings=documents_embeddings)

retriever = retrieve.ColBERT(index=index)
queries_embeddings = model.encode(["ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"], is_query=True)
scores = retriever.retrieve(queries_embeddings=queries_embeddings, k=10)
Sentence-Transformers
uv add sentence-transformers
from sentence_transformers import MultiVectorEncoder

model = MultiVectorEncoder("nlpai-lab/KURE-v2")

query = "ํ›ˆ๋ฏผ์ •์Œ์€ ์–ธ์ œ ๋งŒ๋“ค์–ด์กŒ๋‚˜์š”?"
documents = [
    "์„ธ์ข…๋Œ€์™•์€ 1443๋…„์— ํ›ˆ๋ฏผ์ •์Œ์„ ์ฐฝ์ œํ•˜๊ณ  1446๋…„์— ์ด๋ฅผ ๋ฐ˜ํฌํ•˜์˜€๋‹ค.",
    "๊น€์น˜๋Š” ๋ฐฐ์ถ”๋‚˜ ๋ฌด๋ฅผ ์†Œ๊ธˆ์— ์ ˆ์ธ ๋’ค ๊ณ ์ถง๊ฐ€๋ฃจ์™€ ์ “๊ฐˆ์„ ๋„ฃ์–ด ๋ฐœํšจ์‹œํ‚จ ์Œ์‹์ด๋‹ค.",
]

query_embeddings = model.encode_query(query)
document_embeddings = model.encode_document(documents)

# MaxSim late-interaction scoring (higher is more relevant)
scores = model.similarity(query_embeddings, document_embeddings)

KURE-v1 / KoE5

Sentence-Transformers
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("nlpai-lab/KURE-v1")
# model = SentenceTransformer("nlpai-lab/KoE5")  # needs "query: " / "passage: " prefixes

embeddings = model.encode(["์ฒซ ๋ฒˆ์งธ ๋ฌธ์žฅ", "๋‘ ๋ฒˆ์งธ ๋ฌธ์žฅ"])
similarities = model.similarity(embeddings, embeddings)

Evaluation

We evaluate on the nine MTEB(kor, v2) Retrieval tasks with the latest mteb (v2.x), using the Korean subsets only (Belebele: kor_Hang-kor_Hang; MLDR is the mean of its dev/test splits):

Late-interaction models are measured directly with mteb + PLAID retrieval. Dense rows come from the official MTEB results repository. To evaluate a model, pass its name and paradigm:

uv run --extra late-interaction --no-default-groups python eval/dense/evaluate.py nlpai-lab/KURE-v2 multi-vector
uv run python eval/dense/evaluate.py nlpai-lab/KURE-v1 single-vector

MTEB-ko-retrieval Leaderboard

Average over the nine tasks. Per-task scores are in eval/dense/results/README.md and on the official MTEB Leaderboard.

ModelTypeParamsAvg nDCG@10Avg Recall@10
nlpai-lab/KURE-v2Late-interaction154M0.81600.8921
nvidia/Nemotron-3-Embed-8B-BF16Dense8.0B0.81270.8934
yjoonjang/colbert-ko-en-v2Late-interaction149M0.80630.8827
sionic-ai/comsat-embed-ko-8b-previewDense7.6B0.79270.8876
lightonai/mLateOnLate-interaction307M0.79060.8740
Qwen/Qwen3-Embedding-8BDense7.6B0.78260.8815
nvidia/Nemotron-3-Embed-1B-BF16Dense1.1B0.78170.8690
Qwen/Qwen3-Embedding-4BDense4.0B0.77370.8753
perplexity-ai/pplx-embed-v1-4bDense4.0B0.77050.8699
microsoft/harrier-oss-v1-27bDense27.0B0.76670.8624
dragonkue/snowflake-arctic-embed-l-v2.0-koDense568M0.76530.8609
codefuse-ai/F2LLM-v2-8BDense7.6B0.76380.8593
telepix/PIXIE-Rune-v1.5Dense568M0.76180.8596
nlpai-lab/KURE-v1Dense568M0.76160.8629
nvidia/llama-nemotron-embed-1b-v2Dense1.2B0.75640.8560
dragonkue/BGE-m3-koDense568M0.75470.8513
BAAI/bge-m3Dense568M0.75090.8588
perplexity-ai/pplx-embed-v1-0.6bDense596M0.73900.8377
perplexity-ai/pplx-embed-v1-late-0.6bLate-interaction596M0.73810.8328
nlpai-lab/KoE5Dense560M0.73370.8300
nlpai-lab/KURE-v2-unsupervisedLate-interaction154M0.72830.8268
Qwen/Qwen3-Embedding-0.6BDense596M0.71400.8222
dragonkue/colbert-ko-0.1bLate-interaction149M0.67760.7723
yjoonjang/colbert-ko-v1Late-interaction149M0.62820.7212

Sparse Leaderboard

Learned sparse models are evaluated on the same nine tasks under the same conventions, with mteb's SparseEncoder wrapper in bf16 at up to 8,192 tokens and without pruning the vectors. Next to nDCG@10, we report the average number of active dimensions per query and per document, and FLOPs. To evaluate a sparse model:

uv run python eval/sparse/evaluate.py nlpai-lab/KURE-Sparse-nano

Results are averaged over the nine Korean retrieval tasks. The dashed lines mark dense models for reference. Per-task scores, along with English BEIR results, are in eval/sparse/results/README.md.

Average nDCG@10 vs. average FLOPs of sparse retrievers on the nine Korean tasks

ModelParamsAvg nDCG@10Query dimsDocument dimsFLOPs
nlpai-lab/KURE-Sparse-base593M0.79841001,89736.5
omai-research/milco-650m593M0.78241051,16732.3
nlpai-lab/KURE-Sparse-nano149M0.771614784323.0
telepix/PIXIE-Splade-v1.5149M0.76081171,54137.3
yjoonjang/splade-ko-v1149M0.752610974229.1
telepix/PIXIE-Splade-v1.0149M0.663612162522.4
opensearch-project/opensearch-neural-sparse-encoding-multilingual-v1167M0.5444291766.8

Reranker Leaderboard

Rerankers are evaluated on the same nine tasks with the protocol of reranker-simple-benchmark: each query's candidates are its gold documents plus, as negatives, the BM25 top-50 minus the golds, every model runs in bf16 at up to 8,192 tokens, and we report nDCG@10 with throughput in pairs per second (PPS), measured on one NVIDIA RTX A6000 48GB. To evaluate a reranker:

bash eval/cross-encoder/fetch_eval_assets.sh   # once: the BM25 candidate pools
uv run python eval/cross-encoder/evaluate.py nlpai-lab/KURE-Reranker-nano --speed

Results are averaged over the nine Korean retrieval tasks. Per-task nDCG@10 and PPS are in eval/cross-encoder/results/README.md.

Mean nDCG@10 vs. mean PPS of rerankers on the nine Korean tasks

ModelParamsMean nDCG@10Mean PPS
Qwen/Qwen3-Reranker-8B8.2B0.899015.0
Qwen/Qwen3-Reranker-4B4.0B0.891624.3
KaLM-Embedding/KaLM-Reranker-V1-Large-R27.5B0.891025.3
nlpai-lab/KURE-Reranker-base1.7B0.880055.0
nlpai-lab/KURE-Reranker-nano149M0.8757482.4
zeroentropy/zerank-2-reranker4.0B0.865229.3
mixedbread-ai/mxbai-rerank-large-v21.5B0.860764.8
lightonai/LightOn-rerank-PW-4B4.5B0.860515.1
Qwen/Qwen3-Reranker-0.6B596M0.8528101.0
BAAI/bge-reranker-v2-m3568M0.8518412.6
nvidia/llama-nemotron-rerank-1b-v21.2B0.8468128.2
nlpai-lab/LAMAR-600m568M0.8375415.0
dragonkue/bge-reranker-v2-m3-ko568M0.8199409.1
BAAI/bge-reranker-v2-gemma2.5B0.809958.8
upskyy/ko-reranker-8k568M0.8054409.8
Dongjin-kr/ko-reranker560M0.7861488.0
telepix/PIXIE-Spell-Reranker-Preview-0.6B596M0.776099.7

Training Details

KURE-Sparse

Training code in train/sparse.

  • Distilled from a Qwen3-Reranker-8B teacher on the KURE-v2 SFT data with an in-batch contrastive term plus a KL term over each query's candidates, an L1 sparsity penalty on queries and documents, up to 8,192 tokens, 1 epoch.
  • KURE-Sparse-base: fine-tuned from omai-research/milco-650m, scoring over 30,522 English pivot terms plus 250,002 source-language tokens.
  • KURE-Sparse-nano: the A.X-Encoder-base MLM head grafted onto KURE-v2-unsupervised, pre-finetuned on 20.7M pairs, then fine-tuned. Resulting in 36,282 vocabulary terms.

KURE-Reranker

Training code in train/cross-encoder.

  • Distilled from a Qwen3-Reranker teacher with pointwise MSE on the KURE-v2 SFT data flattened to 33.3M query-document pairs, 1 epoch.
  • KURE-Reranker-base: Qwen/Qwen3-1.7B scored as logit("yes") โˆ’ logit("no") over the Qwen3-Reranker template; up to 8,192 tokens.
  • KURE-Reranker-nano: skt/A.X-Encoder-base with a single-logit head; up to 8,192 tokens.

KURE-v2

The full two-stage training code is in train/late-interaction.

  • Built on skt/A.X-Encoder-base with a multi-layer projection head (128-d per token, MaxSim scoring); trained with PyLate.
  • Stage 1 (PFT): large in-batch contrastive learning on 20.7M weakly related Korean/English pairs, released as KURE-v2-unsupervised.
  • Stage 2 (SFT): contrastive learning + KL distillation from a reranker teacher on 3.03M triplets with hard negatives and false-negative filtering.

KURE-v1

Training code in train/dense.

  • Fine-tuned from BAAI/bge-m3 on ~2M Korean query-document-hard-negative(5) pairs.
  • CachedGISTEmbedLoss, batch size 4,096, lr 2e-5, 1 epoch.

KoE5

Serving

Index-size and latency benchmarks of KURE-v2 across ANN backends, token pooling and binary quantization, with runnable configurations, are in deploy/late-interaction.

License

MIT

Citation

If you find our models helpful, please consider citing:

@misc{kure-reranker,
  title  = {KURE-Reranker: Korean-English bilingual reranking models},
  author = {Jang, Youngjoon and Hong, Seongtae and Son, Junyoung and Lee, Taemin and Lim, Heuiseok},
  year   = {2026},
  url    = {https://huggingface.co/nlpai-lab/KURE-Reranker-base},
}
@misc{kure-v2,
  title  = {KURE-v2: a Korean-English bilingual late-interaction retriever},
  author = {Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Lim, Heuiseok},
  year   = {2026},
  url    = {https://huggingface.co/nlpai-lab/KURE-v2},
}
@inproceedings{jang2025kure,
  title={KURE: Embedding Model for Korean-Specific Retrieval},
  author={Jang, Youngjoon and Son, Junyoung and Lee, Taemin and Hong, Seongtae and Park, JeongBae and Lim, Heuiseok},
  booktitle={Annual Conference on Human and Language Technology},
  pages={129--134},
  year={2025},
  organization={Human and Language Technology}
}
@inproceedings{jang2024koe5,
  title={KoE5: A New Dataset and Model for Improving Korean Embedding Performance},
  author={Jang, Youngjoon and Son, Junyoung and Park, Chanjun and Choi, Soonwoo and Lee, Byeonggoo and Lee, Taemin and Lim, Heuiseok},
  booktitle={Annual Conference on Human and Language Technology},
  pages={239--244},
  year={2024},
  organization={Human and Language Technology}
}

Significant stargazers

Kevin Ko

941 followers ยท starred Dec 2024

Heegyu Kim

135 followers ยท starred Dec 2024

Junbum Lee

954 followers ยท starred Dec 2024

Yohan Na

59 followers ยท starred Dec 2024