amaretto-embed-148m β ONNX
ONNX builds of AmarettoLabs/amaretto-embed-148m β a 148M-parameter EmbeddingGemma specialised for 8 Latin-script languages + code β for running text embeddings on CPU with onnxruntime.
For the full model description, benchmarks, and the vocabulary-slicing + distillation method, see the source model card and the code repository.
Not using onnxruntime? There are also GGUF builds for
llama.cpp(113β293 MB, down to Q5_K_M), and the source model itself for PyTorch / sentence-transformers.
These are self-contained, end-to-end graphs
Not the
backend="onnx"layout. These graphs take token ids and return the final embedding β mean pooling, both Dense projections, and L2 normalization are all inside the graph. That is deliberate: it means nosentence-transformers, nooptimum, and notransformersare needed at inference time, onlyonnxruntimeandtokenizers.Because of this they do not work with
SentenceTransformer(..., backend="onnx"), which expects anonnx/subfolder containing a transformer-only graph and applies pooling itself. If you want that workflow, use the source model with PyTorch instead.
| inputs | input_ids [batch, seq] int64, attention_mask [batch, seq] int64 |
| output | sentence_embedding [batch, 768] float32, already L2-normalized |
| dynamic axes | batch and sequence are both dynamic |
| max sequence length | 2048 β the graph does not enforce this; truncate before feeding it |
| opset | 18 (ai.onnx) |
Files
Fidelity is measured against the original PyTorch model β cosine similarity of the output embeddings over a fixed prompt set spanning nearly the full context.
| file | size | fidelity vs PyTorch | notes |
|---|---|---|---|
model.onnx |
612 MB | 1.000000 at every length | float32. Standard ONNX ops only β portable to any runtime. |
model_int8.onnx |
297 MB | 0.9999 β 0.9993 | 8-bit weight-only; activations stay float32. onnxruntime only (see below). |
Per sequence length, cos(PyTorch, ONNX):
| tokens | model.onnx |
model_int8.onnx |
|---|---|---|
| 15 | 1.000000 | 0.999891 |
| 29 | 1.000000 | 0.999854 |
| 45 | 1.000000 | 0.999815 |
| 135 | 1.000000 | 0.999777 |
| 978 | 1.000000 | 0.999453 |
| 1822 | 1.000000 | 0.999324 |
Both builds reproduce the source model within a padded batch as exactly as alone β batching does not change a row's embedding.
Portability caveat for
model_int8.onnx. It usesMatMulNBits, an operator in thecom.microsoftdomain. It ships inside the core onnxruntime binary, so no extra install is needed β but it is not standard ONNX, and other runtimes (TensorRT, OpenVINO, CoreML converters, non-ORT ONNX implementations) will reject it, as may onnxruntime builds older than ~1.20. If you are not on onnxruntime, usemodel.onnx.
Why weight-only, and not int8 activations
EmbeddingGemma carries large activation outliers β the same reason Google notes that fp16 activations are unusable for it. Quantizing activations to 8 bits therefore costs a great deal of accuracy, and the error compounds with sequence length. For reference, on the same prompt set: standard dynamic int8 reaches only 0.880 at 1822 tokens, and statically calibrated int8 is worse still. Weight-only quantization leaves activations in float32 and avoids the problem entirely, which is why it is the only quantized build published here.
Memory
File size is not the memory budget. Peak resident memory is dominated by float32 activations, so it scales with your longest input and batch size, not with the weights:
| file | RSS after load | peak, 1822-token input | |
|---|---|---|---|
model.onnx |
612 MB | ~920 MB | ~2,120 MB |
model_int8.onnx |
297 MB | ~555 MB | ~1,880 MB |
If you are memory-capped, limiting sequence length is a far stronger lever than quantization: a 512-token cap costs roughly half the peak of a 2048-token one.
model_int8.onnx is also slower per query than model.onnx on some hardware, because
MatMulNBits dequantizes weights on the fly rather than running integer kernels. Choose it for
download size and idle footprint, not for latency. Measure on your own hardware.
Usage
Only onnxruntime and tokenizers are required.
import numpy as np, onnxruntime as ort
from tokenizers import Tokenizer
tok = Tokenizer.from_file("tokenizer.json") # adds <bos>/<eos> itself
# Truncate the SEQUENCE so the post-processor still appends <eos>. Slicing the resulting
# ids instead (ids[:2048]) would drop it on any input at the limit.
tok.enable_truncation(max_length=2048)
sess = ort.InferenceSession("model_int8.onnx", providers=["CPUExecutionProvider"])
def embed(texts):
ids = [tok.encode(t).ids for t in texts]
n = max(len(x) for x in ids)
input_ids = np.zeros((len(ids), n), dtype=np.int64) # pad id 0
mask = np.zeros((len(ids), n), dtype=np.int64)
for i, row in enumerate(ids):
input_ids[i, :len(row)] = row
mask[i, :len(row)] = 1
return sess.run(["sentence_embedding"],
{"input_ids": input_ids, "attention_mask": mask})[0]
# Task prefixes are REQUIRED β same as EmbeddingGemma.
queries = ["task: search result | query: how do I sort a list in python?"]
documents = ["title: none | text: Use list.sort() to sort in place, or sorted() for a new list."]
q, d = embed(queries), embed(documents)
print((q @ d.T).item()) # already normalized, so a dot product is the cosine
Task prefixes matter. Use task: search result | query: for queries and title: none | text:
for documents. The graph cannot add them β they are text, prepended before tokenization. Omitting them
measurably degrades retrieval.
Embeddings are 768-dimensional and Matryoshka-trained: truncate to 512/256/128 and re-normalize.
Intended use & limitations
A general-purpose text-embedding model β retrieval, semantic search, RAG, clustering, classification, STS β for English, Spanish, Portuguese, French, German, Italian, Dutch, Polish, and source code.
Not multilingual. The vocabulary for non-target languages was removed; text in other scripts (Chinese, Japanese, Korean, Arabic, Cyrillic, Greek, Indic, Thai, β¦) degrades severely. Use the original
google/embeddinggemma-300mfor broad multilingual coverage.
Benchmarks (as % of EmbeddingGemma): β₯99.3% on retrieval and STS, β98.7% on code retrieval, β97.9% on classification, β96% on long-document retrieval. Full tables on the source model card.
License β Gemma Terms of Use
Gemma is provided under and subject to the Gemma Terms of Use found at ai.google.dev/gemma/terms
These ONNX files are a format conversion of amaretto-embed-148m, itself a Gemma Model Derivative of
google/embeddinggemma-300m. Your use,
reproduction, and distribution are governed by the
Gemma Terms of Use, a copy of which is distributed here in the
LICENSE file. By using these files you accept those terms.
- Use restrictions (Β§3.2): you may not use these models in violation of the Gemma Prohibited Use Policy.
- If you redistribute these or a derivative, the Gemma Terms (Β§3.1) require you to pass on the use
restrictions, include the
LICENSE, mark modified files, and ship aNOTICEwith the required Gemma notice. - Trademarks (Β§4.2): not affiliated with, endorsed by, or sponsored by Google. "Gemma" / "EmbeddingGemma" are used descriptively to identify the upstream model.
Built by AmarettoLabs. Converted with onnxruntime and optimum.
- Downloads last month
- 62
Model tree for AmarettoLabs/amaretto-embed-148m-ONNX
Base model
google/embeddinggemma-300m