opensearch-neural-embed-v1

TL;DR: A 598M-parameter dense embedding model trained without any labeled data that reaches 73.76 Mean (Task) on MTEB(eng, v2), within 1.5 points of the nearly 13x larger Qwen3-Embedding-8B and ahead of jina-embeddings-v5-text-small, Yuan-embedding-2.0-en and Qwen3-Embedding-0.6B, and 0.608 NDCG@10 on BEIR, on par with the strongest sub-1B models we compared.

We introduce opensearch-neural-embed-v1, the first open source dense embedding model trained by OpenSearch Project. OpenSearch supports dense vector search with k-NN indexes. The indexing and search can be performed with the OpenSearch high-level API.

Model Model Parameters Embedding Dimension BEIR AVG NDCG@10 MTEB(eng, v2) Mean (Task)
opensearch-neural-embed-v1 598M 2048 0.608 73.76

Overview

opensearch-neural-embed-v1 is a dense (single-vector) text-embedding model for English. It encodes queries and documents independently into 2048-dimensional, L2-normalized vectors, and relevance is their cosine similarity (equivalently, their inner product).

We initialize the student model with Qwen3-Embedding-0.6B and we distill two strong embedding models, which excel at retrieval and text similarity, into a small student embedding model. We train the student to learn a 2048-dimensional teacher space, built by concatenating the leading 1024 dimensions of each teacher's embedding.

Training proceeds in two stages, with objectives that each transfer a different aspect of the teachers' knowledge:

  • Absolute representation alignment: a cosine loss pulls each student vector toward the teacher vector of the same text.
  • Pairwise similarity alignment: a similarity-matrix loss makes the student reproduce the teachers' in-batch similarity structure, without forcing an exact match of the outputs. This objective lets the student inherit the teachers' strong text-similarity capability.
  • Relative ranking alignment: a ranking loss uses the teachers' similarity scores as soft labels, so the student preserves which text pairs the teachers consider more related than others. This objective lets the student inherit the teachers' strong retrieval ability.

The whole pipeline needs no labeled data: training uses only about 17M unlabeled English texts and the teachers' embeddings, with no relevance labels, no hard-negative mining and no contrastive retrieval fine-tuning. Notably, it:

  • Is among the strongest 0.6B-class models on MTEB(eng, v2): 73.76 Mean (Task), ahead of jina-embeddings-v5-text-small (71.78, 596M), Yuan-embedding-2.0-en (71.74, 596M) and Qwen3-Embedding-0.6B (70.47, 596M), and within one point of Jasper-Token-Compression-600M (74.75, 607M).
  • Punches far above its size: it comes within 1.5 points of Qwen3-Embedding-8B (75.23), a model nearly 13x larger, with vectors of half the dimensionality (2048 vs. 4096).
  • Is competitive on BEIR: 0.608 average NDCG@10, on par with stella_en_400M_v5 (0.613, 435M) and gte-large-en-v1.5 (0.603, 434M), and ahead of snowflake-arctic-embed-l-v2.0 (0.572, 568M).

Scores for this model are from our own evaluation; scores for the other models come from the MTEB leaderboard or their model cards (see Detailed Search Relevance).

Model Details

  • Model type: Sentence Transformer (dense, single vector)
  • Base model: Qwen3-Embedding-0.6B (Apache-2.0, Qwen Team / Alibaba Cloud)
  • Parameters: 598M (596M backbone + 2.1M projection head)
  • Output dimensionality: 2048
  • Similarity function: cosine similarity (embeddings are L2-normalized)
  • Pooling: mean pooling
  • Maximum sequence length: 8192 tokens (trained on inputs of up to 1024 tokens)
  • Prompts: Instruct: {task description}\nQuery: for queries; no prompt for documents
  • Language: English
  • License: Apache 2.0

Usage (Sentence Transformers)

First install the Sentence Transformers library:

pip install -U sentence-transformers

Then you can load this model and run inference. Queries use an instruction prompt; documents are encoded without a prompt.

from sentence_transformers import SentenceTransformer

# Download from the huggingface Hub
model = SentenceTransformer("opensearch-project/opensearch-neural-embed-v1")

queries = ["What's the weather in ny now?", "how many ounces is one u.s. dry pint"]
documents = [
    "Currently New York is rainy.",
    "One US dry pint equals about 18.6 US fluid ounces.",
    "The Eiffel Tower is located in Paris.",
]

# encode_query applies the default query prompt:
# "Instruct: Given a web search query, retrieve relevant passages that answer the query\nQuery:"
query_embeddings = model.encode_query(queries)
document_embeddings = model.encode_document(documents)
print(query_embeddings.shape)
# (2, 2048)

similarity = model.similarity(query_embeddings, document_embeddings)
print(similarity)
# tensor([[0.7344, 0.2696, 0.2185],
#         [0.2891, 0.8442, 0.1954]])

For a specific task you can replace the default query instruction with a task description in the same format:

query_embeddings = model.encode(
    ["vitamin D reduces the risk of influenza"],
    prompt="Instruct: Given a scientific claim, retrieve documents that support or refute the claim\nQuery:",
)

Usage (HuggingFace)

The model can also be used with the transformers library: mean-pool the last hidden states, apply the 1024 --> 2048 projection stored in 2_Dense/, then L2-normalize.

import torch
import torch.nn.functional as F
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
from transformers import AutoModel, AutoTokenizer

repo = "opensearch-project/opensearch-neural-embed-v1"
tokenizer = AutoTokenizer.from_pretrained(repo)
model = AutoModel.from_pretrained(repo).eval()
dense = load_file(hf_hub_download(repo, "2_Dense/model.safetensors"))

query_prompt = "Instruct: Given a web search query, retrieve relevant passages that answer the query\nQuery:"


def embed(texts):
    batch = tokenizer(texts, padding=True, truncation=True, max_length=8192, return_tensors="pt")
    with torch.no_grad():
        hidden = model(**batch).last_hidden_state
    mask = batch["attention_mask"].unsqueeze(-1).to(hidden.dtype)
    pooled = (hidden * mask).sum(1) / mask.sum(1)                               # mean pooling
    return F.normalize(pooled @ dense["linear.weight"].T + dense["linear.bias"], dim=-1)


queries = ["What's the weather in ny now?", "how many ounces is one u.s. dry pint"]
documents = [
    "Currently New York is rainy.",
    "One US dry pint equals about 18.6 US fluid ounces.",
    "The Eiffel Tower is located in Paris.",
]
query_embeddings = embed([query_prompt + q for q in queries])
document_embeddings = embed(documents)
print(query_embeddings @ document_embeddings.T)
# tensor([[0.7344, 0.2696, 0.2185],
#         [0.2891, 0.8442, 0.1954]])

Detailed Search Relevance

BEIR (NDCG@10)

Model Parameters Average Trec Covid NFCorpus NQ HotpotQA FiQA ArguAna Touche DBPedia SCIDOCS FEVER Climate FEVER SciFact Quora
stella_en_400M_v5 435M 0.613 0.852 0.415 0.691 0.717 0.561 0.642 0.315 0.499 0.250 0.910 0.435 0.782 0.896
opensearch-neural-embed-v1 598M 0.608 0.922 0.372 0.599 0.720 0.527 0.654 0.365 0.443 0.284 0.908 0.453 0.763 0.893
gte-large-en-v1.5 434M 0.603 0.775 0.369 0.561 0.682 0.632 0.721 0.225 0.463 0.263 0.938 0.484 0.824 0.897
snowflake-arctic-embed-l-v2.0 568M 0.572 0.839 0.353 0.637 0.682 0.455 0.591 0.295 0.434 0.202 0.919 0.435 0.706 0.890
Qwen3-Embedding-0.6B 596M 0.561 0.888 0.363 0.531 0.651 0.469 0.676 0.289 0.397 0.228 0.859 0.369 0.702 0.872

MTEB(eng, v2)

Model Parameters Mean (Task) Mean (Type) Classification Clustering PairClassification Reranking Retrieval STS Summarization
Jasper-Token-Compression-600M 607M 74.75 68.46 90.35 59.44 90.15 50.61 66.19 88.79 33.66
opensearch-neural-embed-v1 598M 73.76 67.72 90.41 59.02 89.07 50.51 63.06 88.50 33.51
jina-embeddings-v5-text-small 596M 71.78 65.68 90.75 54.69 84.95 49.38 60.07 88.13 31.77
Yuan-embedding-2.0-en 596M 71.74 65.22 84.35 51.70 81.96 53.27 70.69 84.89 29.71
Qwen3-Embedding-0.6B 596M 70.47 64.72 84.58 54.05 84.37 48.18 61.83 86.57 33.43
stella_en_400M_v5 435M 69.39 64.84 88.25 57.65 87.17 49.60 52.73 83.93 34.53
snowflake-arctic-embed-l-v2.0 568M 63.60 59.81 73.36 44.37 82.99 47.47 58.56 78.05 33.83

Acknowledgements

The distillation objectives are inspired by Jasper and Stella: distillation of SOTA embedding models.

License

This project is licensed under the Apache v2.0 License.

Copyright

Copyright OpenSearch Contributors. See NOTICE for details.

Downloads last month
39
Safetensors
Model size
0.6B params
Tensor type
F32
ยท
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for opensearch-project/opensearch-neural-embed-v1

Finetuned
(583)
this model

Paper for opensearch-project/opensearch-neural-embed-v1