Skip to page content
SAVRN
Search Plan a project

Open-weight model · Feature extraction

embeddinggemma-2-text-int8-onnx

by Påmin Labs pamin-labs/embeddinggemma-2-text-int8-onnx

embeddinggemma-2-text-int8-onnx is an open-weight model for feature extraction from Påmin Labs, released under Apache License 2.0. It has 262,144-token context. Its published files total 306.8 MB.

The text encoder of google/embeddinggemma-2 (Google DeepMind, Apache-2.0), exported to ONNX and quantized to int8 for ONNX Runtime on CPU. It returns the same kind of vector as the original model: a 768-dimensional, L2-normalised text embedding.

Parameters—
Context262,144
Weights1.3 MB
Licenseapache-2.0
AccessOpen weights
Monthly Downloads—

Model Card

By Påmin Labs, published under apache-2.0, revision 39c3eaaf0799.

The text encoder of google/embeddinggemma-2 (Google DeepMind, Apache-2.0), exported to ONNX and quantized to int8 for ONNX Runtime on CPU. It returns the same kind of vector as the original model: a 768-dimensional, L2-normalised text embedding. Its output for a text does not depend on what else is in the batch: the vectors are bitwise identical at every batch size we tested. This is a modified version of the original model, not a retrained one. It is the dense retrieval model of Påmin Memory, and it can be used on its own with any ONNX Runtime application. Sizes are file sizes in bytes / 10^6. The text tower sizes come from the upstream checkpoint's safetensors header: the languagemodel.…

Read Påmin Labs's full model card

EmbeddingGemma 2 text encoder, int8 ONNX for CPU

The text encoder of google/embeddinggemma-2 (Google DeepMind, Apache-2.0), exported to ONNX and quantized to int8 for ONNX Runtime on CPU. It returns the same kind of vector as the original model: a 768-dimensional, L2-normalised text embedding. Its output for a text does not depend on what else is in the batch: the vectors are bitwise identical at every batch size we tested.

This is a modified version of the original model, not a retrained one. It is the dense retrieval model of Påmin Memory, and it can be used on its own with any ONNX Runtime application.

Why use this model

This repository google/embeddinggemma-2
Modalities Text only Text, image, video, audio
Format ONNX (opset 21 + com.microsoft ops), int8, for ONNX Runtime's CPU execution provider PyTorch / safetensors, bf16 weights, run in bf16 or fp32
Size 274.5 MB (model.onnx + model.onnx.data) Text tower: 542.0 MB as stored (bf16), 1,084.0 MB in fp32. Whole checkpoint: 1,488.9 MB (bf16)
Batch behaviour A text's vector is bitwise identical alone and in batches of 2, 8 and 32, in any order (details) Not measured by us. For comparison, the previous revision of this repository computed one activation scale per batch for the MLP gate/up projections; on 200 texts its vectors differed by up to 0.013 per element between batch 1 and batch 8
Matrix products int8 GEMM (MatMulIntegerToFloat, u8 × s8), which ONNX Runtime runs with AVX-512 VNNI / AVX-VNNI / AMX kernels where the CPU has them fp32 or bf16
Fidelity Cosine similarity to the original in fp32: mean 0.99901, minimum 0.99723 (200 texts, 9 languages; details) Reference
Runtime dependencies onnxruntime, tokenizers, numpy torch, transformers, sentence-transformers

Sizes are file sizes in bytes / 10^6. The text tower sizes come from the upstream checkpoint's safetensors header: the language_model.* tensors hold 271,002,648 parameters, stored as bf16; fp32 is 4 bytes per parameter.

When not to use it

  • On a GPU or NPU, use the original model. The int8 graph is built for the CPU execution provider. The upstream card recommends bf16 where the hardware supports it, else fp32, and warns that float16 can return NaN.
  • If you need image, video or audio embeddings, use the original model. This encoder has no other towers. Its text vectors are meant to match the original's text vectors, but we have not measured how well they align with the original's image, video or audio vectors.
  • If you need vectors that are bitwise identical across ONNX Runtime versions. The vectors are identical across batch sizes and thread counts within one ONNX Runtime version, not across versions: ORT 1.28 and 1.31 differ by up to 0.0111 per element. Keep the runtime version fixed for the life of an index, or re-embed when you change it.
  • If you need the full 8,192-token context. The longest input in our tests has 471 tokens, and Påmin Memory truncates at 512. Longer inputs have not been validated for this conversion.

Usage

Inputs are input_ids and attention_mask (int64, [batch, sequence]), output is sentence_embedding ([batch, 768], float32, unit length). Mean pooling and normalisation are inside the graph. Use the bundled tokenizer.json (the upstream tokenizer, unchanged) and the upstream task prompts:

Use Text to encode
Search query task: search result \| query: {query}
Document title: {title or none} \| text: {content}
Other tasks the other prompts of the upstream card, e.g. task: question answering \| query: {question}
# pip install onnxruntime tokenizers numpy huggingface_hub
import numpy as np
import onnxruntime as ort
from huggingface_hub import snapshot_download
from tokenizers import Tokenizer

path = snapshot_download("pamin-labs/embeddinggemma-2-text-int8-onnx")
session = ort.InferenceSession(f"{path}/model.onnx", providers=["CPUExecutionProvider"])
tokenizer = Tokenizer.from_file(f"{path}/tokenizer.json")
tokenizer.enable_truncation(max_length=512)
tokenizer.enable_padding(pad_id=tokenizer.token_to_id("<pad>"), pad_token="<pad>")  # right padding

def embed(texts):
    enc = tokenizer.encode_batch(texts)
    feeds = {"input_ids": np.array([e.ids for e in enc], dtype=np.int64),
             "attention_mask": np.array([e.attention_mask for e in enc], dtype=np.int64)}
    return session.run(["sentence_embedding"], feeds)[0]   # [batch, 768], L2-normalised

queries = embed(["task: search result | query: What causes the northern lights?"])
documents = embed([
    "title: none | text: The northern lights are caused by charged particles from the sun.",
    "title: none | text: Bread rises because yeast produces carbon dioxide.",
])
print(queries.shape, np.linalg.norm(queries, axis=1))  # (1, 768) [~1.0]
print(queries @ documents.T)                           # cosine similarities; the first document scores higher

The upstream model supports Matryoshka truncation to 512, 256 or 128 dimensions: keep the leading dimensions and L2-normalise again. We have not measured truncated vectors of this int8 graph separately.

Påmin Memory runs this model one text per forward pass, with the search query and document prompts above.

What was changed

The weights are the upstream text tower at revision 914f7f8. Nothing was retrained or fine-tuned.

  1. Text tower only. The vision and audio towers are not included.
  2. ONNX export of the text tower with masked mean pooling and L2 normalisation, using the PyTorch exporter.
  3. Graph rewrites with identical arithmetic in fp32: RMSNorm as SimplifiedLayerNormalization, tanh-GELU as FastGelu, rotary embeddings as com.microsoft.RotaryEmbedding, and grouped-query attention without the Expand that copies key/value heads (the shared heads are reached by reshaping the queries).
  4. int8 quantization. - Weights of every linear layer: signed int8, one scale per output channel. - Activations: unsigned 8-bit, quantized at run time per token, one scale per row. For mlp.down_proj there is one scale per token and per group of 512 inputs. No scale is shared between the texts of a batch. - A per-token scale multiply is dropped where the result only feeds an RMSNorm, which removes any per-row factor. The up_proj scale is folded into the down_proj group scales. - The per-layer embedding projection is split into 24 per-layer linears. - The token embedding table is int8 with one scale per row, and the embedding scale is folded into those row scales.
  5. Batch invariance. Two fp32 steps still depended on the padded batch shape on ONNX Runtime's CPU kernels: - The attention keys are padded inside the graph to at least 65 columns: zero keys, zero values and masked scores. Every attention product then takes the same kernel path whatever the batch's padded length. - Mean pooling uses a cumulative sum along the sequence, read at the last position. This is exact for padding rows, which are zero.

The released model.onnx keeps the per-node metadata the PyTorch exporter writes. That metadata includes source file paths from the machine that ran the export, and has no effect on inference.

Evaluation

All results below are for 768 dimensions on the CPU execution provider of a shared 4-vCPU Intel Xeon (2.10 GHz, AVX-512 VNNI and AMX). Timing was not part of any result. Measurements are labelled by scope:

  • Component measurements run the model alone.
  • Product entry point measurements run Påmin Memory's full search path. The model is one stage of that path, together with lexical retrieval, fusion and a reranker.

Fidelity to the original (component)

parity200: 200 texts from XQuAD in 9 languages (en, zh, de, es, ar, ru, th, vi, hi), half questions with the query prompt and half paragraph openings with the document prompt. The reference is the original model in fp32 through sentence-transformers with its documented prompts, truncated at 1,024 tokens.

Release gate, pipeline/verify.py (ONNX Runtime 1.28, 2 threads, tokenizers with right padding):

Metric This revision Gate
Cosine to fp32, minimum 0.99723 ≥ 0.99
Cosine to fp32, 1st percentile 0.99754 ≥ 0.995
Cosine to fp32, mean 0.99901 ≥ 0.998
Max abs difference, batch 1 vs batch 8 0.0 = 0
Outputs containing NaN 0 = 0

Earlier comparison with the previous revision, using the same 200 texts and fp32 reference but an earlier evaluation script outside pipeline/. That script's embedding path gives a lower minimum for this revision than verify.py (0.99552 against 0.99723). The means agree. Read the two columns against each other, not against the table above:

Metric This revision Previous revision (2d2e08e)
Cosine to fp32, minimum 0.99552 0.99635 at batch 1, 0.99498 at batch 8
Cosine to fp32, 1st percentile 0.99710 0.99756 at batch 1, 0.99733 at batch 8
Cosine to fp32, mean 0.99901 0.99892 at batch 1, 0.99887 at batch 8
Max abs difference, batch 1 vs batch 8 0.0 0.0130

Batch invariance

36 texts of 17–471 tokens: 32 XQuAD paragraphs with the document prompt and 4 questions with the query prompt. Each text is embedded alone. It is then embedded in batches of 2, 8 and 32, in corpus order and in a shuffled order, and once as the shortest text in a batch with the 31 longest. Padding is on the right, up to 239 extra positions at 256-token truncation and up to 454 at 512.

ONNX Runtime Threads Truncation Arrangements Vectors bitwise identical to batch 1
1.31 1 256 b2, b8, b32, each also shuffled, shortest-with-longest all (max abs difference 0.0)
1.31 2 256 same all
1.28 2 256 same all
1.31 2 512 b2, b8, each also shuffled all

Also measured:

  • A text embedded alone gives identical vectors with 1 and with 2 threads (ORT 1.31).
  • The same text differs by up to 0.0111 per element between ORT 1.28 and ORT 1.31.

Retrieval in Påmin Memory (product entry point)

These are measured through Påmin Memory's full search path (search: lexical and dense retrieval, fusion and a bge-reranker-v2-m3 int8 reranker), on the CPU, with 768-dimensional vectors.

  • XQuAD-R: 1,190 queries per group over 13,014 paragraphs in 11 languages, scored in two groups. A cross-lingual query's relevant paragraph is in another language; a same-language query's is in its own.
  • MuSiQue: the first 600 questions (all 2-hop) over their 7,274 paragraphs.

These runs used the previous revision of this graph (2d2e08e). On the embedder-only screen below, this revision gives the same results within noise. A product entry-point run of this revision has not been published yet.

nDCG@10 BGE-M3 int8 (configuration this model replaced) This model, raw vectors This model + Påmin Memory's query-side language transform
XQuAD-R cross-lingual 0.7231 0.6664 0.6883
XQuAD-R same-language 0.8679 0.8785 0.8767
MuSiQue (600) 0.7679 0.7887 0.7845
  • Against BGE-M3, which Påmin Memory used before, this model is lower cross-lingually (−0.0567 raw) and higher on same-language XQuAD-R (+0.0106) and on MuSiQue (+0.0208).
  • The language transform is not part of this model. It is a query-side step in Påmin Memory. It blends each query vector with a copy from which language directions have been removed, using constants fitted to this model's vectors.
  • Paired sign-flip tests of the transform against raw vectors:
  • cross-lingual +0.0218, p = 0.0001;
  • same-language −0.0018, p = 0.38;
  • MuSiQue −0.0042, p = 0.14.
  • The MuSiQue difference between BGE-M3 and this model is between two single runs, with no paired test.

To use the transform outside Påmin Memory, fit its constants for your exact model files with pipeline/fit_language_constants.py.

Embedder alone, this revision against the previous one (component)

The model ranks alone (no lexical channel, fusion or reranker) on pooled XQuAD-R (1,190 queries per group) and on MuSiQue (first 200 questions). Paired sign-flip tests:

nDCG@10 Previous (2d2e08e) This revision Difference p
XQuAD-R cross-lingual 0.5177 0.5193 +0.0016 0.11
XQuAD-R same-language 0.8142 0.8129 −0.0013 0.42
MuSiQue (200) 0.7383 0.7353 −0.0030 0.32

No difference is significant.

Speed and memory

Not yet measured on a quiet machine. All runs so far were on a shared host under load, which is not good enough to publish latency. Speed depends heavily on the CPU's int8 support (AVX-512 VNNI, AVX-VNNI or AMX on x86).

Files

File Size (bytes) sha256
model.onnx 1,266,037 1b77c1d1548181dec3b9a38997794512665e06f624cbf1ddaa3334c6941481a2
model.onnx.data 273,266,688 ae126793db6cb0107fe9711c9d5a820126a0cc1a336172c4871a44d4f1daa763
tokenizer.json 32,170,510 4d777ef5bdc1aa36227abdfb77c3e49e7b9c892d16e1b6bda41c393504828be4
tokenizer_config.json 1,599 17bd5d6e9364ca49a534e1502076593317c298d4a663623091ed45388f004874
config.json 4,455 b8f1e9931b57fbc054acdb445c41765d55b0074c58d145fa82839941ad1b5bb3
  • model.onnx and model.onnx.data must sit in the same directory.
  • tokenizer.json, tokenizer_config.json and config.json are the upstream files, unchanged. config.json describes the full multimodal model and is included for reference; the ONNX graph does not read it.
  • checksums.sha256 lists every file in this repository except itself.
  • pipeline/ rebuilds the model; CHANGELOG.md records the revisions; NOTICE holds the attribution.

Revisions

Revision Date Change
2d2e08e 2026-10-12 First release. One activation scale per batch for the MLP gate/up projections, so vectors depended on batch composition.
0bd3abe 2026-10-14 Batch-invariant graph: per-token activations, key padding to ≥ 65 columns, CumSum pooling. Vectors change: re-embed indexes built with 2d2e08e.
this revision — Documentation and build pipeline only. Model files are byte-identical to 0bd3abe; existing indexes stay valid.

See CHANGELOG.md.

Reproduce and keeping up with upstream

pipeline/ rebuilds this model from the pinned upstream revision with one command, pipeline/build.sh, then runs the release gates: bitwise batch invariance, fidelity thresholds against fp32, and a NaN check. We rebuilt it from scratch with that pipeline:

  • model.onnx.data came out byte-identical to the published file.
  • model.onnx came out identical except for the exporter's source-path metadata. That metadata records where the build ran.

How this repository follows changes to the official google/embeddinggemma-2:

  1. Pinned, not automatic. The build uses one exact upstream commit, recorded with file checksums in pipeline/upstream.json, currently 914f7f89142e33e77833254d9c9b90c3cef7303b. Upstream changes do not reach this repository by themselves.
  2. Rebuild and gate. When upstream publishes a new revision, we bump the pin and rebuild with pipeline/build.sh. The new build must pass the release gates before it is published: bitwise batch invariance, the fidelity thresholds against the new upstream fp32 reference, and the NaN check. It must also pass a retrieval check.
  3. New revision, never a silent replacement. The result is published as a new revision of this repository with a CHANGELOG entry and a git tag. The entry states whether the vectors changed; if they did, indexes must be re-embedded. Published files are never replaced without a new entry.
  4. Language constants refit. Påmin Memory's query-side language constants are refitted for the new vectors with pipeline/fit_language_constants.py.
  5. Pin a revision yourself so that an update never changes your vectors unexpectedly:

python snapshot_download("pamin-labs/embeddinggemma-2-text-int8-onnx", revision="<tag or commit sha>")

The full checklist and the resource needs are in the pipeline README.

Limitations and bias

This model inherits the limitations, biases and responsible-use considerations of the base model. Read the EmbeddingGemma 2 model card, in particular its Usage and Limitations and Ethical Considerations and Risks sections. The upstream card asks deployments to follow the Gemma Prohibited Use Policy.

Limitations specific to this conversion:

  • Approximation. int8 quantization moves every vector slightly; see the fidelity table above.
  • Cross-lingual retrieval through Påmin Memory is lower than with BGE-M3, which Påmin Memory used before. Its language transform recovers part of the gap.
  • Runtime-dependent vectors. Vectors are not bitwise identical across ONNX Runtime versions or across different CPU kernels.
  • Evaluated scope. Evaluation covers retrieval in 11 languages (XQuAD-R) and English multi-hop QA (MuSiQue). Other languages, domains and tasks were not measured for this conversion.

License and attribution

Apache License 2.0, the license of the base model (google/embeddinggemma-2, by Google DeepMind). This repository contains a modified version of that model; see NOTICE for the attribution and a summary of the modifications. The build pipeline in pipeline/ is by Påmin Labs under the same license.

Citation

If you use this conversion, please cite the base model and this repository. The upstream card does not provide a BibTeX entry at the time of writing; cite it by its model card.

@misc{embeddinggemma2,
  title        = {{EmbeddingGemma 2}},
  author       = {{Google DeepMind}},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/google/embeddinggemma-2}}
}

@misc{pamin2026embeddinggemma2int8onnx,
  title        = {{EmbeddingGemma 2 text encoder, int8 ONNX for CPU}},
  author       = {{P{\aa}min Labs}},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/pamin-labs/embeddinggemma-2-text-int8-onnx}},
  note         = {Batch-invariant int8 ONNX conversion of google/embeddinggemma-2}
}

Contact

Maintained by Påmin Labs. Questions and problem reports go to the discussions of this repository or to GitHub issues of Påmin Memory.

Configuration

Architecture
EmbeddingGemma2Model
Context length (tokens)
262,144
Layers
24
Hidden size
512
Feed-forward size
2,048
Attention heads
4
Key/value heads
2
Head dimension
256
Vocabulary size
262,144
Sliding window (tokens)
512
Model type
embedding_gemma2

Identity and Version

Repository
pamin-labs/embeddinggemma-2-text-int8-onnx
Publisher
Påmin Labs
Task
Feature extraction
Modality
Text
Library
onnx
Parameters
Not stated by the source
Languages
cpu
Revision
39c3eaaf07991c73bfe0e489b55b1b3e6aaa9ac5
First published
2026-10-12
Last updated
2026-10-14

Files and Weights

23 files, 306.8 MB in total. The weights are 1 file totalling 1.3 MB in onnx.

Weights1 file · 1.3 MB
Configuration11 files · 71.9 KB
Tokenizer2 files · 32.2 MB
Documentation4 files · 33.0 KB
Other4 files · 273.3 MB
Repository1 file · 1.6 KB
Every file
FileTypeSizeSHA-256
model.onnxWeights1.3 MB 1b77c1d15481
config.jsonConfiguration4.5 KB —
pipeline/batch_invariance.pyConfiguration5.5 KB —
pipeline/common.pyConfiguration4.8 KB —
pipeline/export_onnx.pyConfiguration2.1 KB —
pipeline/fetch_upstream.pyConfiguration4.8 KB —
pipeline/fit_language_constants.pyConfiguration7.2 KB —
pipeline/prepare_data.pyConfiguration3.4 KB —
pipeline/quantize_int8.pyConfiguration14.2 KB —
pipeline/rewrite_fp32.pyConfiguration13.0 KB —
pipeline/upstream.jsonConfiguration2.3 KB —
pipeline/verify.pyConfiguration10.1 KB —
CHANGELOG.mdDocumentation2.2 KB —
NOTICEDocumentation691 B —
README.mdDocumentation20.1 KB —
pipeline/README.mdDocumentation10.0 KB —
checksums.sha256Other1.9 KB —
model.onnx.dataOther273.3 MB ae126793db6c
pipeline/build.shOther2.3 KB —
pipeline/requirements.txtOther1.1 KB —
.gitattributesRepository1.6 KB —
tokenizer.jsonTokenizer32.2 MB 4d777ef5bdc1
tokenizer_config.jsonTokenizer1.6 KB —

License and Download

License
apache-2.0
Access
Open weights, no gate
Download size
1.3 MB
Download from Påmin Labs

Released by Påmin Labs through its official repository on Hugging Face. Read the license.

Built From

  • Derived from google/embeddinggemma-2
  • Quantized from google/embeddinggemma-2

Memory Requirements

PrecisionWeights in memory
As published1.3 MB

Weights only, from the published parameter count; the key-value cache and runtime add to this.

Questions About embeddinggemma-2-text-int8-onnx

Can I use embeddinggemma-2-text-int8-onnx commercially?

Yes. embeddinggemma-2-text-int8-onnx is released under Apache License 2.0. The Apache License 2.0 is a permissive open-source license. It permits commercial use, modification and redistribution. It requires keeping the license and copyright notices and any NOTICE file, stating significant changes, and it includes an express patent grant from contributors.

What is embeddinggemma-2-text-int8-onnx's context length?

262,144 tokens, from the maximum position embeddings in its published configuration.

Similar Models

Model · Feature extraction

all-MiniLM-L6-v2

Joshua

https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2 with ONNX weights to be compatible with Transformers.js. If you haven't already, you can install the Transformers.js JavaScript library from NPM using: You can then use the model to compute embeddings like this: You can convert this Tensor to a nested JavaScript array using.tolist(): Note: Having a separate repo for ONNX weights is intended to be a temporary solution until WebML gains more traction. If you would like to make your models web-ready, we recommend converting to ONNX using Optimum and structuring your repo like this one (with ONNX weights located in a subfolder named onnx).

Open weights apache-2.0 512 tokens transformers.js

Model · Feature extraction

bge-base-en-v1.5

Joshua

https://huggingface.co/BAAI/bge-base-en-v1.5 with ONNX weights to be compatible with Transformers.js. If you haven't already, you can install the Transformers.js JavaScript library from NPM using: You can then use the model to compute embeddings, as follows: You can also use the model for retrieval. For example: Note: Having a separate repo for ONNX weights is intended to be a temporary solution until WebML gains more traction. If you would like to make your models web-ready, we recommend converting to ONNX using Optimum and structuring your repo like this one (with ONNX weights located in a subfolder named onnx).

Open weights mit 512 tokens transformers.js

For more details please refer to our Github: FlagEmbedding. If you are looking for a model that supports more languages, longer texts, and other retrieval methods, you can try using bge-m3. FlagEmbedding focuses on retrieval-augmented LLMs, consisting of the following projects currently: - 1/30/2024: Release BGE-M3, a new member to BGE model series! M3 stands for Multi-linguality (100+ languages), Multi-granularities (input length up to 8192), Multi-Functionality (unification of dense, lexical, multi-vec/colbert retrieval). It is the first embedding model which supports all three retrieval methods, achieving new SOTA on multi-lingual (MIRACL) and cross-lingual (MKQA) benchmarks. Technical…

Open weights mit 512 tokens sentence-transformers

Model · Feature extraction

wavlm-large

Microsoft

The large model pretrained on 16kHz sampled speech audio. When using the model, make sure that your speech input is also sampled at 16kHz. Note: This model does not have a tokenizer as it was pretrained on audio alone. In order to use this model speech recognition, a tokenizer should be created and the model should be fine-tuned on labeled text data. Check out this blog for more in-detail explanation of how to fine-tune the model. - 60,000 hours of Libri-Light - 10,000 hours of GigaSpeech - 24,000 hours of VoxPopuli Authors: Sanyuan Chen, Chengyi Wang, Zhengyang Chen, Yu Wu, Shujie Liu, Zhuo Chen, Jinyu Li, Naoyuki Kanda, Takuya Yoshioka, Xiong Xiao, Jian Wu, Long Zhou, Shuo Ren, Yanmin…

Open weights transformers

Model · Feature extraction

clap-htsat-unfused

LAION eV

The abstract of the paper states that: You can use this model for zero shot audio classification or extracting audio and/or textual features. You can also get the audio and text embeddings using ClapModel If you are using this model for your work, please consider citing the original paper

Open weights apache-2.0 514 tokens transformers