Modelsgoogleembeddinggemma-300m
providergoogle /

embeddinggemma-300m

0.6533 DZD in / 1M tokens

EmbeddingGemma turns text into vectors at 300 million parameters — small enough to run on a phone, and the highest-ranking open multilingual embedding model under 500M on MTEB. It was trained with Matryoshka Representation Learning, so the 768-dimensional output can be truncated to 512, 256, or 128 and re-normalised, with the cost of each step published rather than estimated: half the storage costs 0.44 points on multilingual retrieval. Built from Gemma 3 on 320 billion tokens across more than a hundred languages, it handles inputs up to 2,048 tokens and produces deterministic output.

PublicEmbeddingsMultilingualMatryoshkaOn-Device
embeddinggemma-300m
ArchitectureTransformer Encoder
Context Window2K

EmbeddingGemma 300M

Text in, vectors out. Three hundred million parameters, and the highest-ranking open multilingual embedding model under 500M on MTEB.

Paper: EmbeddingGemma: Powerful and Lightweight Text Representations


Choose Your Vector Size, With the Price Published

Matryoshka Representation Learning lets you truncate a 768-dimensional vector to 512, 256, or 128 and re-normalise it. The most important information is what that costs — and Google publishes the full table rather than describing the trade in prose.

MTEB (Multilingual, v2)

DimensionsMean (Task)Mean (TaskType)Storage
76861.1554.311×
51260.7153.89⅔
25659.6853.01⅓
12858.2351.77⅙

MTEB (Code, v1)

DimensionsMean
76868.76
51268.48
25666.74
12862.96

Read the two tables against each other

On multilingual text, 512 is nearly free. Dropping from 768 costs 0.44 points and saves a third of your index. Going to 256 costs 1.47 points for two thirds of the storage. Even 128 — a sixth of the footprint — costs under three points.

On code, the curve breaks. 768 to 512 costs 0.28 points, barely anything. But 256 to 128 costs 3.78 — an order of magnitude steeper than the equivalent step on text.

Why that matters: code embeddings carry structural information that compresses worse than natural-language semantics does. If your corpus is source code, the honest floor is 256. If it is prose, 128 is defensible.

The English table carries a discrepancy worth knowing about. Published versions of the card report either 69.67 or 68.36 at 768 dimensions for MTEB (English, v2), with the remaining tables identical. Treat either as approximately correct and neither as precise — a point of spread on a published benchmark is normal, and it is a reminder to measure on your own corpus before committing an index.


⚠️ Do Not Use float16

Stated plainly on the model card, and it produces bad vectors rather than an error.

Activations do not support float16. Use float32 or bfloat16 depending on your hardware.

This matters only if you self-host, and it is the kind of configuration mistake that surfaces as mysteriously poor retrieval quality weeks later rather than as a crash on the first request.


What It Is Built From

Gemma 3, with T5Gemma initialization — an encoder-decoder lineage applied to an embedding task, rather than a decoder-only model repurposed.

320 billion tokens of training data spanning more than 100 languages.

TPUv5e hardware, trained with JAX and ML Pathways.

At 300 million parameters the whole model fits comfortably on a phone, which is the design point Google names: mobile devices, laptops, desktops, and anywhere a vector database has to live next to the application rather than behind an API.


Specifications

Model IDgoogle/embeddinggemma-300m
Parameters300M
Max input2,048 tokens
Output dimensions768, truncatable to 512 / 256 / 128
Languages100+
Training data~320B tokens
BaseGemma 3, T5Gemma initialization
Precisionfloat32 or bfloat16 — not float16
LicenceGemma Terms of Use
Endpoint/v1/embeddings

Access is gated on Hugging Face. Downloading the weights requires accepting Google's usage licence — this is not Apache 2.0, and the terms are worth reading if you are deploying commercially.


Capabilities

CapabilityValue
input_typestext
output_typesembedding
context_window2048
output_dimensions768 (truncatable)
matryoshka_dimensions128, 256, 512, 768
endpoint/v1/embeddings
streamingNot applicable
reasoningNot applicable
deterministicYes
requires_promptYes — input text required

2,048 Tokens Is the Real Constraint

Smaller than most embedding models in this catalogue, and the number that shapes your chunking.

What fits: a section, a few paragraphs, a short article, a function with its docstring, a support ticket.

What does not: a full contract, a long report, a large source file.

That constraint is less limiting than it looks. A vector is one point in space — the longer and more varied the text behind it, the more that point becomes an average of unrelated things and retrieves well for nothing. A 2,048-token ceiling enforces the chunking discipline a larger window lets you skip.

A working approach: split at meaning boundaries — headings, paragraphs, function definitions — targeting 200 to 800 tokens per chunk. Overlap neighbours by a sentence so a passage crossing a boundary stays findable from either side. Keep headings attached to their content; a chunk reading "must be completed within 14 days" without naming what must be completed is retrievable and useless.


Using EmbeddingGemma on DEVUP AI

Endpoint: POST https://api.devupai.com/v1/embeddings

Python

PYTHON
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DEVUP_API_KEY"],
    base_url="https://api.devupai.com/v1",
)

response = client.embeddings.create(
    model="google/embeddinggemma-300m",
    input=[
        "Adding an index on the filtered column usually eliminates a sequential scan.",
        "Les paiements par carte CIB sont traites en dinar algerien.",
        "Connection pooling reduces the cost of opening a new database session.",
    ],
)

vectors = [item.embedding for item in response.data]

print(f"{len(vectors)} vectors of {len(vectors[0])} dimensions")
print(f"Tokens consumed: {response.usage.total_tokens}")

Results return in the order you sent them. Batching is the single largest performance factor on an embedding endpoint — one request with a hundred inputs beats a hundred requests with one each by a wide margin.

Truncating to a smaller dimension — Python

If the endpoint accepts a dimensions parameter, use it. If not, Matryoshka truncation is something you can do yourself — and the model was trained for exactly that.

PYTHON
import numpy as np


def truncate(vector: list[float], dimensions: int) -> np.ndarray:
    """Truncate a Matryoshka embedding and re-normalise it."""
    if dimensions not in (128, 256, 512, 768):
        raise ValueError(f"dimensions must be one of 128, 256, 512, 768 — got {dimensions}")

    short = np.array(vector[:dimensions], dtype=np.float32)
    return short / np.linalg.norm(short)

The re-normalisation is not optional. Truncating a unit vector leaves something shorter than unit length, and cosine similarity computed as a dot product silently gives wrong magnitudes without it. The model card specifies truncate and then re-normalise for this reason.

Semantic search — Python

PYTHON
import numpy as np

DIMENSIONS = 512  # measured choice, fixed for the life of the index


def embed(texts: list[str]) -> np.ndarray:
    """Embed texts and return a matrix, one row per input, truncated and re-normalised."""
    response = client.embeddings.create(model="google/embeddinggemma-300m", input=texts)
    return np.array([truncate(item.embedding, DIMENSIONS) for item in response.data])


CORPUS = [
    "Refunds are issued to the original payment method within 14 days.",
    "Orders above 5000 DZD qualify for free delivery nationwide.",
    "Support is available Sunday through Thursday, 9am to 5pm.",
]

corpus_vectors = embed(CORPUS)
query_vector = embed(["How long until I get my money back?"])[0]

scores = corpus_vectors @ query_vector

for rank, index in enumerate(np.argsort(scores)[::-1], start=1):
    print(f"{rank}. [{scores[index]:.3f}] {CORPUS[index]}")

The query and the matching passage share almost no vocabulary. Closing that gap is what embeddings do and keyword search does not.

Measuring your own dimension — Python

The published table tells you what the trade costs on MTEB. Your corpus is not MTEB.

PYTHON
def recall_at_k(corpus: list[str], queries: list[str], expected: list[int], dimensions: int, k: int = 5) -> float:
    """Fraction of queries whose expected passage appears in the top k results."""
    response = client.embeddings.create(model="google/embeddinggemma-300m", input=corpus + queries)
    raw = [item.embedding for item in response.data]

    corpus_vectors = np.array([truncate(v, dimensions) for v in raw[: len(corpus)]])
    query_vectors = np.array([truncate(v, dimensions) for v in raw[len(corpus) :]])

    hits = 0
    for query_vector, target in zip(query_vectors, expected):
        top_k = np.argsort(corpus_vectors @ query_vector)[::-1][:k]
        hits += target in top_k

    return hits / len(queries)


for dimensions in (768, 512, 256, 128):
    print(f"{dimensions:>4}d  recall@5 {recall_at_k(CORPUS, QUERIES, EXPECTED, dimensions):.3f}")

Note that all four dimensions are derived from one embedding call. Matryoshka truncation happens client-side, so sweeping every size costs the same as embedding once — which makes this the cheapest meaningful experiment available on an embedding model.

Node.js

JAVASCRIPT
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY,
});

const response = await client.embeddings.create({
  model: "google/embeddinggemma-300m",
  input: [
    "Adding an index usually eliminates a sequential scan.",
    "Connection pooling reduces session setup cost.",
  ],
});

const vectors = response.data.map((item) => item.embedding);
console.log(`${vectors.length} vectors of ${vectors[0].length} dimensions`);

cURL

BASH
curl https://api.devupai.com/v1/embeddings \
  -H "Authorization: Bearer $DEVUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/embeddinggemma-300m",
    "input": "How do I speed up a slow database query?"
  }'

Quantisation, and What It Actually Costs

Google publishes quantisation-aware-training checkpoints with their MTEB scores alongside the full-precision figures — which is unusual, and makes the quantisation decision measurable rather than a leap of faith.

ConfigurationMTEB (Multilingual, v2)MTEB (Code, v1)
Full precision, 768d61.1568.76
Q8_0, 768d60.9368.70
Mixed precision, 768d60.6968.03
Q4_0, 768d60.6267.99

Four-bit quantisation costs 0.53 points on multilingual retrieval and 0.77 on code.

Put that against the dimension table and the comparison becomes concrete: quantising to Q4_0 costs roughly the same as dropping from 768 to 512 dimensions — and the two stack. A Q4_0 model producing 512-dimension vectors runs on a phone and indexes at a third of the storage, for around a point of retrieval quality.

Mixed precision here means per-channel quantisation with int4 for embeddings, feedforward, and projection layers, and int8 for attention.


Practical Notes

Query and corpus must share a model and a dimension. Mixing either produces silently meaningless similarity rather than an error.

Always re-normalise after truncating. The model card says so; skipping it corrupts cosine similarity quietly.

Decide the dimension before you build the index. Changing it means re-embedding everything.

Record the model and dimension with your vectors. Six months from now that metadata is the difference between a migration and a rebuild.

Never use float16 if you self-host.

Similarity is not relevance. Two passages can sit close together and still be the wrong answer; chunking, corpus quality, and ranking matter as much as the model does.

Pair it with keyword search where exact strings matter — product codes, invoice references, rare proper nouns. Dense retrieval is weakest exactly where lexical matching is strongest.

Cache aggressively. Output is deterministic, so re-embedding unchanged text produces an identical vector and buys nothing.

Debounce anything that embeds on keystroke. A search box calling this endpoint per character is how a small model produces a large bill.


Where It Fits

On-device and edge retrieval, which is the design target. Three hundred million parameters means the model lives next to the application rather than behind a network call.

Multilingual corpora, where it is the strongest open option under 500M parameters.

Storage-constrained indexes, where Matryoshka truncation lets you trade measured quality for measured space rather than guessing.

Retrieval-augmented generation, paired with any generative model in this catalogue — embeddings find the passages, a larger model reasons over them.

Less suited to long documents without chunking, and to code corpora compressed below 256 dimensions.


Limitations

Not generative. It produces vectors, not text. It finds the passages another model answers from.

2,048-token ceiling. Smaller than most embedding models here; longer inputs must be split.

Dimension is permanent per index. Changing it means re-embedding the corpus.

Code compresses worse than text. The 256-to-128 step costs 3.78 points on code against 1.45 on multilingual text.

float16 is unsupported. A self-hosting constraint that fails quietly rather than loudly.

Gated access and a non-standard licence. Gemma Terms of Use rather than Apache or MIT — read them against a commercial deployment.

Weak on exact matching. Identifiers, codes, and rare proper nouns favour lexical search.

Published English scores vary by a point between card versions. Measure your own corpus.

Embedded text leaves your system. Apply the same handling policy you would to any other outbound data.