bekko-static-embedding-v1

bekko-static-embedding-v1 is a multilingual static embedding model. It has no Transformer layers: each token maps to a fixed vector, and a sentence embedding is simply the mean of those vectors. That makes it cheap enough to run on any CPU, with no GPU required.

Among the public static embedding models we compared, it has the highest retrieval quality, in both multilingual and English retrieval.

For the full write-up, including comparisons, Matryoshka/INT8 trade-offs, and how the model was trained, see the blog post: bekko-static-embedding-v1: State-of-the-Art Retrieval for Multilingual Static Embeddings.

Highlights

  • Best retrieval among the public static models we compared: 43.76 on MNanoBEIR (14 languages), about 11 points above other multilingual static models
  • Also above English-only static models on English retrieval (NanoBEIR-en 53.71)
  • Within about 1 point of multilingual-e5-small on MMTEB Retrieval, with zero Transformer layers
  • Trained for 40 target languages with a custom 200k-token WordPiece tokenizer
  • 1024-dim embeddings that truncate to 512 / 256 / 128 / 64 / 32 (Matryoshka); 512 dims lose about 0.9 points of retrieval score
  • Per-dimension ONNX and OpenVINO files with FP16 or INT8 weights: the INT8 512-dim model is 103.2 MB
  • No prefixes or instructions needed
  • MIT license

How it compares

Against other static embedding models

Static model Language Dims NanoBEIR-en MNanoBEIR MMTEB Retrieval MMTEB Mean
bekko-static-embedding-v1 Multilingual 1024 53.71 43.76 49.96 50.18
static-similarity-mrl-multilingual-v1 Multilingual 1024 43.51 32.29 41.21 47.24
potion-multilingual-128M Multilingual 256 37.07 32.23 37.86 47.23
static-retrieval-mrl-en-v1 English 1024 50.35 – – –
stable-static-embedding-fast-retrieval-mrl-en-v2 English 512 51.57 – – –

bekko-static-embedding-v1 leads every column. On multilingual retrieval (MNanoBEIR, 14 languages) it is about 11 points above the other multilingual static models, and on MMTEB Retrieval 8.75 and 12.10 points above. On English-only retrieval it also beats the two static models trained specifically for English, even when truncated to 512 dims (52.82).

Against contextual models

Model Transformer layers Active params NanoBEIR-en MNanoBEIR MMTEB Retrieval MMTEB Mean
bekko-static-embedding-v1 0 0 53.71 43.76 49.96 50.18
multilingual-e5-small 12 21.6M 58.37 51.17 50.9 56.4
bekko-embedding-v1-a8m 4 7.7M 60.34 52.65 56.2 56.7

With no Transformer layers at all, bekko-static-embedding-v1 comes within about 1 point of multilingual-e5-small on MMTEB Retrieval (49.96 vs 50.9). multilingual-e5-small is still ahead on the Nano retrieval sets and on the overall MMTEB mean, where most of its lead comes from BitextMining, Reranking and STS.

If you can run a small Transformer, bekko-embedding-v1-a8m scores above multilingual-e5-small on every column here with only 7.7M active parameters, and it runs well on CPU.

Static embedding models avoid attention entirely. The Sentence Transformers post Train 400x faster Static Embedding Models reports 100x to 400x faster CPU encoding than common embedding models such as multilingual-e5-small for its static models. We have not published our own throughput measurements for this model; measure on your workload.

Rule of thumb: pick bekko-static-embedding-v1 when encoding cost must be as low as possible, for example very large corpora on CPU or tight latency budgets. Pick bekko-embedding-v1-a8m when retrieval quality matters more and you can run a small Transformer.

How these numbers were measured

NanoBEIR-en (13 English tasks) and MNanoBEIR (182 tasks in 14 languages) are nDCG@10 × 100 from HAKARI-Bench, averaged with equal weight per task. MMTEB is the 131-task MTEB(Multilingual, v2) suite, main score × 100 averaged over tasks; Retrieval is its 18-task category. bekko-static-embedding-v1 was evaluated locally. Static comparison models use published MMTEB results averaged over the same 131 tasks. MMTEB values for multilingual-e5-small and bekko-embedding-v1-a8m are taken from the bekko-embedding-v1-a8m model card, which uses the official 2026-06-28 MMTEB snapshot and the same task set and aggregation. Active parameters exclude the token embedding table; for a static model the table is the whole model (204.8M parameters).

Quickstart

pip install -U sentence-transformers

Queries and documents go through the same encode() call, with no prefixes. Pass normalize_embeddings=True when you search with cosine similarity or dot product.

from sentence_transformers import SentenceTransformer, util

model = SentenceTransformer("hotchpotch/bekko-static-embedding-v1", device="cpu")

query = "What are the characteristics of sushi?"
docs = [
    "A warm noodle soup served in broth with sliced toppings.",
    "天ぷらは魚や野菜に衣をつけて揚げた料理です。",  # "Tempura is battered, deep-fried fish and vegetables."
    "Une fine crepe garnie de sucre, de beurre ou de fruits.",
    "A Japanese dish made with vinegared rice, often shaped with seafood, vegetables, or egg.",
]

query_emb = model.encode(query, normalize_embeddings=True)
doc_emb = model.encode(docs, normalize_embeddings=True)
scores = util.cos_sim(query_emb, doc_emb)[0]

print(scores)
print("best doc:", docs[int(scores.argmax())])

Output:

tensor([0.0578, 0.0743, 0.0913, 0.1738])
best doc: A Japanese dish made with vinegared rice, often shaped with seafood, vegetables, or egg.

Static embeddings produce lower absolute cosine scores than contextual models such as bekko-embedding-v1-a8m. Use the ranking, and tune any score threshold on your own data.

Queries and documents don't need to share a language. Continuing with the same model:

corpus = [
    "Sushi is a Japanese dish of vinegared rice topped with seafood.",
    "The Eiffel Tower is a wrought-iron lattice tower in Paris, France.",
    "Mount Fuji is the highest mountain in Japan, at 3,776 meters.",
    "Python is a programming language known for its readability.",
    "La Sagrada Família es una basílica de Barcelona diseñada por Antoni Gaudí.",
]
corpus_emb = model.encode(corpus, normalize_embeddings=True)

for query in [
    "日本で一番高い山は?",  # "What is the highest mountain in Japan?"
    "Who designed the famous basilica in Barcelona?",
]:
    query_emb = model.encode(query, normalize_embeddings=True)
    hits = util.semantic_search(query_emb, corpus_emb, top_k=2)[0]
    print(query)
    for hit in hits:
        print(f"  {hit['score']:.3f}  {corpus[hit['corpus_id']]}")
日本で一番高い山は?
  0.364  Mount Fuji is the highest mountain in Japan, at 3,776 meters.
  0.137  Sushi is a Japanese dish of vinegared rice topped with seafood.
Who designed the famous basilica in Barcelona?
  0.547  La Sagrada Família es una basílica de Barcelona diseñada por Antoni Gaudí.
  0.125  The Eiffel Tower is a wrought-iron lattice tower in Paris, France.

Outputs above were produced on CPU with Sentence Transformers 6.1.0.

Benchmark details

MMTEB Multilingual v2 by category (131 tasks)

Scores are main score × 100, averaged per category. Δ is bekko-static-embedding-v1 minus static-similarity-mrl-multilingual-v1.

Category Tasks bekko-static-embedding-v1 static-similarity-mrl-multilingual-v1 potion-multilingual-128M Δ
All tasks 131 50.18 47.24 47.23 +2.93
Classification 43 52.40 48.60 52.36 +3.81
Clustering 16 40.03 30.67 37.63 +9.36
MultilabelClassification 5 14.99 14.74 15.95 +0.25
Retrieval 18 49.96 41.21 37.86 +8.75
Reranking 6 51.59 49.45 47.39 +2.14
STS 16 64.50 64.02 61.23 +0.47
BitextMining 13 43.68 50.62 40.72 -6.94
PairClassification 11 72.81 74.34 71.39 -1.53
InstructionReranking 3 -1.65 -1.24 -2.08 -0.41
HAKARI-Bench retrieval, including contextual models and BM25

HAKARI-Bench covers 37 benchmarks and 550 tasks. Ten are shown here; the full results are on the leaderboard.

Benchmark Tasks bekko-static 1024d bekko-static 512d static-similarity potion mE5-small bekko a8m BM25
MNanoBEIR 182 43.76 42.89 32.29 32.23 51.17 52.65 46.46
NanoMMTEB-v2 18 43.30 42.87 36.08 35.22 44.55 50.25 45.50
NanoMIRACL 18 68.03 67.67 45.37 47.79 78.71 75.57 57.15
NanoRTEB 14 37.50 36.53 25.73 25.58 47.11 54.98 35.53
NanoCoIR 10 58.19 57.55 48.01 45.38 69.15 74.68 54.36
NanoBRIGHT 20 26.38 26.31 20.27 19.67 17.58 31.49 27.90
NanoMLDR 13 55.72 54.55 35.96 34.89 39.20 54.48 73.96
NanoLongEmbed 6 61.96 60.58 48.90 43.90 50.14 68.19 82.17
NanoJMTEB-v2 11 65.36 64.40 51.37 51.61 71.65 75.93 74.65
NanoIndicQA 11 35.35 35.23 34.91 53.69 70.09 65.12 56.53

Columns: bekko-static-embedding-v1 at 1024 and 512 dims, static-similarity-mrl-multilingual-v1 (1024d), potion-multilingual-128M (256d), multilingual-e5-small (384d), bekko-embedding-v1-a8m (384d), and BM25.

Against static-similarity-mrl-multilingual-v1, bekko-static-embedding-v1 is higher on all 37 benchmark averages and 523 of 550 tasks. Against potion-multilingual-128M it is higher on 36 of 37 benchmarks; NanoIndicQA is the exception. BM25 is higher on 21 of 37 benchmark averages, notably long-document retrieval, so test it as a baseline when retrieval is your only goal.

Optimized inference

Smaller embeddings with Matryoshka (truncate_dim)

The model was trained with Matryoshka representation learning at 1024, 512, 256, 128, 64 and 32 dimensions.

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("hotchpotch/bekko-static-embedding-v1", device="cpu", truncate_dim=512)
emb = model.encode("What are the characteristics of sushi?", normalize_embeddings=True)
print(emb.shape)  # (512,)
Dims NanoBEIR-en MNanoBEIR HAKARI 550-task average
1024 53.71 43.76 45.88
512 52.82 42.89 45.03
256 50.83 41.04 43.29
128 47.83 38.03 40.12
64 43.96 32.87 34.82
32 35.74 24.97 26.46

512 dims is a good default. Even at 128 dims, MNanoBEIR (38.03) stays above other multilingual static models at full size.

ONNX and OpenVINO files with only the weights you need

truncate_dim shortens the output, but the full 1024-dim table is still loaded. The onnx/ and openvino/ directories contain models that store only the weights for one dimension, in FP16 or INT8:

Dims FP16 weights INT8 weights
1024 409.6 MB 205.6 MB
512 204.8 MB 103.2 MB
256 102.4 MB 52.0 MB
128 51.2 MB 26.4 MB
64 25.6 MB 13.6 MB
32 12.8 MB 7.2 MB

Sizes exclude the shared 5.1 MB tokenizer. INT8 here quantizes the stored weights only; pooling and output vectors stay FP32. On HAKARI-Bench, INT8 and FP16 weights differ by less than 0.15 points at every dimension.

The built-in StaticEmbedding module does not route backend= to these files, so use the bundled loader:

pip install -U sentence-transformers onnxruntime   # or: openvino
from transformers.dynamic_module_utils import get_class_from_dynamic_module


def get_model(backend="onnx", dim=512, precision="int8", revision="main"):
    repo = "hotchpotch/bekko-static-embedding-v1"
    ext = {"onnx": "onnx", "openvino": "xml"}[backend]
    return get_class_from_dynamic_module(
        "bekko_static_backend.BekkoStaticBackend", repo, revision=revision,
    ).load_sentence_transformer(
        repo, revision=revision, backend=backend,
        file_name=f"{backend}/model_{precision}_dim{dim}.{ext}",
    )


model = get_model(backend="onnx", dim=512, precision="int8")
vectors = model.encode(["日本語の検索文", "An English document"], normalize_embeddings=True)
print(vectors.shape)  # (2, 512)

# OpenVINO with FP16 weights:
model = get_model(backend="openvino", dim=256, precision="fp16")

backend accepts "onnx" or "openvino", precision accepts "int8" or "fp16", and dim accepts 1024, 512, 256, 128, 64 or 32. The helper loads Python code from this repository (bekko_static_backend.py) and downloads only the configuration, tokenizer and selected model file. Set revision to a commit SHA for reproducible deployments.

Languages

The training data and tokenizer target these 40 languages:

English (en), Arabic (ar), Bulgarian (bg), Bengali (bn), Catalan (ca), Czech (cs), Danish (da), German (de), Greek (el), Spanish (es), Estonian (et), Persian (fa), Finnish (fi), French (fr), Hebrew (he), Hindi (hi), Croatian (hr), Hungarian (hu), Indonesian (id), Italian (it), Japanese (ja), Korean (ko), Dutch (nl), Norwegian (no), Polish (pl), Portuguese (pt), Romanian (ro), Russian (ru), Slovak (sk), Slovenian (sl), Serbian (sr), Swedish (sv), Swahili (sw), Telugu (te), Thai (th), Turkish (tr), Ukrainian (uk), Vietnamese (vi), Yoruba (yo), Chinese (zh).

Text in other languages still gets an embedding, since the WordPiece tokenizer can split unseen words into subwords, but quality outside these languages has not been a training target. The list comes from the data-selection config in training_scripts/.

Model details

Item Value
Model type Sentence Transformer static embedding model
Architecture StaticEmbedding (token lookup + mean pooling), no Transformer layers
Parameters 204,800,000 (200,000 × 1,024 embedding table)
Tokenizer Custom uncased WordPiece, 200,000 tokens with a 30,000-token English core
Embedding dimension 1024
Supported truncate dimensions 512, 256, 128, 64, 32
Max sequence length No architectural limit; the tokenizer caps inputs at 32,768 tokens (trained on 512)
Weight storage FP16 (model.safetensors, 409.6 MB)
Similarity Cosine similarity

Training

The embedding table was initialized randomly and trained from scratch with Multiple Negatives Ranking Loss (MNRL), applied at every Matryoshka dimension. There is no distillation from a teacher model.

Training data comes from hotchpotch/bekko-embedding-v1-unsupervised: 265 data configurations covering 40 target languages, about 814 million text pairs (titles and bodies, questions and answers, generated queries, translation pairs). The selection includes data derived from the MIRACL train split and NLI.

Hyperparameters
Setting Value
Loss MNRL, temperature 0.03 (scale = 1 / 0.03)
MRL dimensions 32, 64, 128, 256, 512, 1,024
MRL weights 0.025, 0.05, 0.1, 0.15, 0.3, 1.0 (same order)
Epochs, steps 1, 49,727
Global batch size 16,384
Learning rate 0.25, 10% warmup, cosine decay
Optimizer AdamW, weight decay 0, β₂ = 0.999, ε = 1e−8
Precision BF16 mixed precision, FP32 master weights, FP16 release
Max input length in training 512 tokens
Seed 42
Tokenizer selection

In a static model, the tokenizer's units are exactly the units whose vectors are averaged. We trained eight models on 10% of the data, one per tokenizer, and evaluated them on MNanoBEIR and NanoMIRACL (200 tasks, nDCG@10 × 100). This ablation used a different loss from the final model, so its scores are not comparable with the final results.

Tokenizer 1024d 512d
Multilingual BERT uncased 37.87 37.17
Multilingual BERT cased 38.51 38.01
Gemma 2 38.73 38.08
Custom 100k, 24k English, uncased 40.19 39.29
Custom 100k, 30k English, uncased 39.86 39.21
Custom 200k, 30k English, cased 41.60 40.69
Custom 200k, 30k English, script-balanced 41.20 40.40
Custom 200k, 30k English, uncased (selected) 41.89 41.18

The custom vocabulary was trained with WordPiece: a 30k English core from equal parts Wikipedia and FineWeb, then vocabulary for 39 more languages added while keeping the English token IDs.

The tokenizer trainer, model trainer, FP16 export script and data-selection config are in training_scripts/.

FAQ

  • Do I need a prefix like query: or passage: ? No. Encode raw text for both queries and documents.
  • Why are the cosine scores so low? This static model gives lower absolute cosine scores than contextual models, as in the Quickstart output. Rankings are what matter; calibrate thresholds on your data.
  • Does word order matter? No. The embedding is the mean of token vectors, so sentences with the same tokens in a different order get the same embedding. Use a contextual model such as bekko-embedding-v1-a8m when order matters.
  • Which file should I load? PyTorch: the default model.safetensors. Memory-constrained CPU deployments: an INT8 file from onnx/ or openvino/ at the dimension you need.
  • Should I use this or BM25? For pure retrieval, test both. In our benchmarks BM25 is stronger on long-document retrieval; this model is stronger on natural-language questions (NanoMIRACL: 68.03 vs 57.15).

Limitations

Evaluation scope and deployment considerations
  • The model is optimized for retrieval. On MMTEB, BitextMining and PairClassification are below static-similarity-mrl-multilingual-v1; evaluate it separately for those tasks.
  • MMTEB results were measured at 1024 dims. Truncated dimensions were evaluated on retrieval only.
  • Contextual models (multilingual-e5-small, bekko-embedding-v1-a8m) and BM25 remain stronger on many retrieval benchmarks.
  • MMTEB comparison values for other models come from published results, with different evaluation library and dataset versions.
  • HAKARI-Bench is maintained by the model author; read it alongside MMTEB.
  • Quality varies by language and domain. Evaluate on your target data before deployment.
  • Results come from a single training seed.

The name "bekko"

bekko (/ˈbek.koː/) is a coined name that joins two pieces of Japanese tradition:

  • akabeko (赤べこ): the red ox cherished in Japan for centuries as a guardian charm, believed to ward off illness and misfortune.
  • bekko-iro (鼈甲色): a traditional Japanese color, a warm, translucent, amber-like hue.

Related

Paper

For full technical details of the bekko project and its training data, see Bekko Embedding: Parameter-Efficient Multilingual Retrieval with Ultra-Compact Encoders.

Citation

If you use bekko-static-embedding-v1 in your work, please cite:

@misc{tateno2026bekkoembedding,
  title         = {Bekko Embedding: Parameter-Efficient Multilingual Retrieval with Ultra-Compact Encoders},
  author        = {Yuichi Tateno},
  year          = {2026},
  eprint        = {2607.25180},
  archivePrefix = {arXiv},
  primaryClass  = {cs.IR},
  url           = {https://arxiv.org/abs/2607.25180}
}

License

MIT License.

Author

Yuichi Tateno @hotchpotch

Downloads last month

-

Downloads are not tracked for this model. How to track
Safetensors
Model size
0.2B params
Tensor type
F16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train hotchpotch/bekko-static-embedding-v1

Space using hotchpotch/bekko-static-embedding-v1 1

Collection including hotchpotch/bekko-static-embedding-v1

Paper for hotchpotch/bekko-static-embedding-v1

Article mentioning hotchpotch/bekko-static-embedding-v1