AI Development

EmbeddingGemma 2: Open Multimodal Embeddings That Run Locally

October 14, 2026
12 min read
Compact local server on a desk, softly lit against a neutral background
Share:

On October 6, 2026, Google DeepMind released EmbeddingGemma 2, an open embedding model of about 740 million parameters that maps text, code, images, video and audio into one 768-dimensional vector space. It runs on your own hardware, the weights are on Hugging Face and Kaggle, and the model card declares Apache 2.0.

This is my read of the launch post, the model card and the developer guide, with every number attributed and nothing re-run by me. You get the spec sheet, what changed from EmbeddingGemma 1, a quickstart copied from the card, the storage math for 768 vs 128 dimensions, a precise answer on the license, and where it falls short.

1. The launch facts

EmbeddingGemma 2 is built on the Gemma 4 architecture and shares Gemma 4’s text tokenizer and audio encoder. It is modular: the text model is about 270M parameters (a 130M transformer plus a 140M embedder), the vision encoder adds 170M and the audio encoder 300M, which is where the 740M total comes from. Per Google’s blog, you can load only the encoders you need.

Everything lands in the same 768-dimensional space, and one 8,192-token context window is shared across modalities. The predecessor, EmbeddingGemma 1 (September 2025), was a text-only model of roughly 300M parameters with a 2,048-token context.

Model card at a glance

  • • Released: October 6, 2026 by Google DeepMind (date of the Google blog post)
  • • Size: ~740M parameters = 270M text + 170M vision encoder + 300M audio encoder; text-only loads 270M
  • • Inputs: text and code, images, video, audio, and interleaved combinations, all into one vector space
  • • Output: 768 dimensions; Matryoshka truncation to 512, 256 or 128
  • • Context: 8,192 tokens shared across modalities (EmbeddingGemma 1: 2,048)
  • • Per-input budget (card): 280 tokens per image (~29 images), 140 tokens per video frame at 1 FPS (~58 frames), 25 tokens per second of audio (~327 s)
  • • License: declared Apache 2.0 (section 4 covers what that does and does not settle)
  • • Weights: Hugging Face (about 1.5 GB of safetensors), Kaggle, Ollama, llama.cpp GGUF build

2. What actually improved vs EmbeddingGemma 1

Three things changed, and only one of them is a benchmark. Version 1 was text-only and gated behind Google’s Gemma terms; version 2 takes images, video and audio, quadruples the context window and, per the card, is Apache 2.0. The one number Google puts in the headline is code retrieval: MTEB (Code, v1) goes from 68.76 to 78.68, a gain of 9.92 points (vendor-reported, model card and blog, Oct 6, 2026).

Read the other row too. On MTEB (Multilingual, v2) the card shows 61.36 against 61.15 for version 1, so general text quality is essentially flat. If your corpus is plain prose, that is not a reason to upgrade by itself. The reasons are code, media and context length.

The three real changes

🎞️

Modalities

Text, code, images, video and audio in one space, so a text query can retrieve a photo or a recording without a fusion layer.

đź’»

Code retrieval

MTEB Code v1: 68.76 to 78.68 (+9.92 points, NDCG@10), vendor-reported. Multilingual text: 61.15 to 61.36.

📏

Context

8,192 tokens, 4x EmbeddingGemma 1, but shared by every modality: images, frames and audio spend the same budget.

Golden rule

Upgrade for code search, media search or longer inputs. For plain multilingual text the card shows a 0.21-point move, and your own recall@k will tell you more than that number does.

3. The numbers, with sources and caveats

Every figure below comes from Google’s model card (full precision, Oct 6, 2026) and is vendor-reported. Benchmark names and versions are as printed there: MTEB multilingual v2, MTEB code v1, MIEB lite, MMEB v2, MSEB retrieval and MAEB. The table is the card’s own truncation table, trimmed to six score columns.

Matryoshka truncation: scores by dimension

Vendor-reported, from the model card. Higher is better; each column uses the metric the card lists for that benchmark.

DimsMTEB multiMTEB codeMIEB liteMMEB v2MSEB retr.MAEB
76861.3678.6864.6459.0169.5449.39
51261.1777.2464.3258.3869.1849.21
25660.4176.1863.1356.2466.7648.91
12857.8971.4159.0645.6556.7146.92

What follows is my arithmetic on those numbers, nothing more. At 256 dimensions the card’s scores keep 95 to 99% of the 768-dim score on every column (MMEB v2 is the lowest, 56.24 against 59.01). At 128 dimensions text and code hold up (MTEB multilingual 94%, MTEB code 91%) but media does not: MMEB v2 falls to 77% (45.65 against 59.01) and MSEB retrieval to 82%.

What the primary sources confirm

  • • ~740M parameters, 768 dimensions, Matryoshka to 512/256/128, 8,192-token context (Google blog and model card)
  • • MTEB Code v1 at 768 dims: 68.76 to 78.68, NDCG@10 (model card)
  • • MTEB multilingual v2: 61.15 to 61.36, so text quality is roughly flat (model card)
  • • Quantized memory on a Pixel 11 Pro: ~191 MB text-only, ~567 MB full multimodal (Google blog, vendor-reported)

Read the fine print

These are Google’s own runs. The blog says it leads among sub-1B multimodal embedders and beats some specialist models more than twice its size, but it prints no numbers for those comparisons and links no technical report. In the searches I ran on October 14 I found only coverage repeating Google’s figures, no independent evaluation. Treat the table as directional and measure on your own data.

4. The license: what actually governs use

At first glance the card looks inconsistent: it says Apache 2.0 but links a file named after Gemma 4’s license. I read the pieces instead of trusting the filename. Here is what I found on October 14, 2026.

What I checked

  • • Card metadata: license: apache-2.0 in the README front matter and a license:apache-2.0 tag in the Hugging Face API. There is no license_name or license_link field.
  • • Header link: the card’s “License: Apache 2.0” points to ai.google.dev/gemma/docs/gemma_4_license. The slug says Gemma 4, but the page I fetched is titled Apache License 2.0 and contains the Apache 2.0 text. Gemma 4 itself launched under Apache 2.0, per Google’s blog.
  • • Repository files: no LICENSE or NOTICE file. The repo holds README.md, config and tokenizer files, and the 1.49 GB model.safetensors. The only license text a reader can reach is the linked page.
  • • Google’s launch post and Google’s own model card page also say Apache 2.0.

The loose end

The card also says deployments must adhere to the Gemma Prohibited Use Policy. That page was last updated in February 2024, is written for “Gemma or Model Derivatives”, and predates Gemma 4’s move to Apache 2.0. Apache 2.0 has no field-of-use clause, so the card reads as inconsistent about whether that policy binds you. EmbeddingGemma 1 is different: its card says license gemma and gates the download behind Google’s terms, so v1 derivatives stay under those.

Practical reading

Everything that declares a license says Apache 2.0, so I would plan on Apache 2.0 for the weights you download today, keep a copy of the license page and the commit you pulled, and treat the Prohibited Use Policy as a floor for what you build. This is not legal advice: if the model ships inside a product with customers, have someone who reads licenses for a living read both documents.

5. Quickstart: text, truncation and multimodal

The snippets below are the ones Google prints in the model card and the developer guide. I have not executed them. The developer guide installs with the image, audio and video extras; the card’s shorter line covers text only.

Install and embed text (model card)

Queries and documents use different prompt names. prompt_name="Document" applies title: none, so format titled documents by hand.

# text only (model card)
pip install -U sentence-transformers transformers

# image, audio and video extras (developer guide; quote the extras in zsh)
pip install -U sentence-transformers[image,audio,video] transformers

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("google/embeddinggemma-2")

query = "What causes the northern lights?"
document = "The northern lights are caused by charged particles from the sun."

query_emb = model.encode(query, prompt_name="SearchQuery")
doc_emb = model.encode(document, prompt_name="Document")
print(model.similarity(query_emb, doc_emb))

Task prefixes (text only)

  • • SearchQuery: task: search result | query: {query}. Documents: title: {title} | text: {content}
  • • QuestionAnswering: task: question answering | query: {question}
  • • FactChecking: task: fact checking | query: {claim}
  • • CodeRetrieval: task: code retrieval | query: {query}. Documents: title: {title or filename} | text: {code}
  • • Classification, Clustering, SentenceSimilarity (symmetric): task: classification | query: {content}, and so on

Images, video and audio take no prefix. Use title: none when a document has no title. Omitting the prefix on text still works but lowers quality, per the card.

Matryoshka truncation and precision (card and developer guide)

Pass truncate_dim and normalize_embeddings together and use the same dimension for queries and documents. The card’s dtype snippet omits import torch; I added it.

import torch
from sentence_transformers import SentenceTransformer

# card: bfloat16 when the GPU supports it, otherwise float32 (never float16)
dtype = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float32
model = SentenceTransformer("google/embeddinggemma-2", model_kwargs={"torch_dtype": dtype})

query = "What causes the northern lights?"
query_emb = model.encode(
    query,
    prompt_name="SearchQuery",
    truncate_dim=256,          # or 512, 128
    normalize_embeddings=True,
)

Cross-modal search and interleaved input (developer guide, model card)

Media goes in as a dictionary keyed by modality, with no prefix. Audio should be mono at 16 kHz and video is sampled at 1 frame per second by default.

# one text query against a photo and a sound recording
image_emb = model.encode({"image": "sunset_beach.jpg"})
audio_emb = model.encode({"audio": "ocean_waves.wav"})
query_emb = model.encode("ocean waves at sunset", prompt_name="SearchQuery")

print(model.similarity(query_emb, image_emb))
print(model.similarity(query_emb, audio_emb))

# interleaved: one embedding for text + photos + video
listing_emb = model.encode({
    "text": "Waterproof running shoes. <|image|> Featuring a breathable mesh upper. <|image|> Grip test on wet rock: <|video|>",
    "image": ["shoe.jpg", "mesh.jpg"],
    "video": "demo.mp4",
})

Selective encoder loading

  • • Text only (270M): config_kwargs={"vision_config": None, "audio_config": None}
  • • Text and image (440M): config_kwargs={"audio_config": None}
  • • Text and audio (570M): config_kwargs={"vision_config": None}
  • • Full multimodal (740M): no config_kwargs

Pass config_kwargs to SentenceTransformer(...). Per the developer guide all configurations share one vector space, so you can add an encoder later without re-embedding existing vectors.

If you would rather not run Python, Google lists Ollama (ollama pull embeddinggemma-2), a llama.cpp GGUF build, MLX, vLLM, SGLang, LM Studio, LiteRT, MediaPipe and transformers.js with a WebGPU demo. The Ollama page I read lists text and text-plus-image tags only and prints a 256K context figure that contradicts the card’s 8,192 tokens, so for audio or video use the Python route and trust the card.

Quickstart gotchas

  • • float16 returns NaN or silently degraded embeddings instead of raising an error. Use bfloat16 or float32 (model card).
  • • Slicing a vector breaks its unit length. Re-normalize after truncating or ranking degrades without any error (model card).
  • • A community thread on the card (Hugging Face discussion #13, Oct 14) reports an ImportError for the PIL library on a fresh install with the plain quickstart. The extras install or pip install pillow is the likely fix; I did not reproduce it.
  • • The repo’s config.json was saved with transformers 5.18.0.dev0 and the card states no minimum version. Keep the -U in the install line and pin whatever versions pass your own test.

6. Storage math: 768 vs 128 dimensions

Embedding size is the part of this model you control, so do the arithmetic before choosing a dimension. A vector costs dimensions times bytes per number. Google’s blog advertises up to 6x storage reduction at 128 dimensions; here is where that comes from.

The arithmetic (raw vectors, no index)

Developer guide figures for 1M vectors are about 1.5 GB at 768 dims and about 250 MB at 128 dims. The pgvector formulas are from its README.

768 dims x 2 bytes (bf16) = 1,536 bytes per vector
1,000,000 x 1,536 B       = 1.536 GB   (guide: "roughly 1.5 GB")

128 dims x 2 bytes        =   256 bytes per vector
1,000,000 x 256 B         = 256 MB     (guide: "roughly 250 MB")

768 / 128 = 6x    768 / 256 = 3x    768 / 512 = 1.5x

float32 doubles every line: 768 x 4 B = 3,072 B -> 3.07 GB per 1M vectors
pgvector vector  = 4 x dims + 8 bytes -> 3,080 B at 768 dims, 520 B at 128 dims
pgvector halfvec = 2 x dims + 8 bytes -> 1,544 B at 768 dims, 264 B at 128 dims

Raw size by dimension (2 bytes per number)

DimsPer vector1M vectors10M vectorsvs 768
7681,536 B1.54 GB15.4 GB1x
5121,024 B1.02 GB10.2 GB1.5x
256512 B512 MB5.12 GB3x
128256 B256 MB2.56 GB6x

Two cautions. These are raw vector bytes: an HNSW index, metadata and replicas sit on top. And the saving is not free: at 128 dims the card’s MMEB v2 score falls from 59.01 to 45.65, and Google’s own guide says to validate 128d on your data before using it for multimodal queries.

My default

Start at 256 dimensions stored as bfloat16 or halfvec: 3x smaller than 768, and the card keeps 95% or more of full-size scores on every column above (the developer guide points the same way). Go to 128 only for text or code, and only after your own recall@k says it is fine.

7. Pick it, or stay on a hosted API?

Hosted embedding APIs are still the shortest path for many teams, including Google’s own Gemini Embedding 2. The question is which constraint you actually have.

Pick EmbeddingGemma 2 when

  • • Data cannot leave the device or your VPC, or search has to work offline
  • • You search code, photos, clips or recordings and want one local index instead of separate text and media pipelines
  • • Volume is high enough that per-call fees outweigh a CPU or GPU box you already run
  • • You want to own the vector space: pin a model version, fine-tune it (Apache 2.0 per the card) and ignore a vendor’s deprecation calendar

Stay hosted when

  • • Volume is low or spiky and you do not want to run batching, GPUs and upgrades
  • • Your inputs are PDFs: the card documents image inputs and a visual-document benchmark but no native PDF input, so you would rasterize pages yourself
  • • A hosted model already hits your recall target: switching means re-embedding the whole corpus

My earlier post covers the hosted route (Vertex AI, 3,072 dimensions by default as of that post): Gemini Embedding 2: Google’s multimodal embeddings

8. Honest limits

Everything good about this release is on Google’s page. Here is what the same sources, and common sense, say to keep in mind.

Before you commit

  • • Vendor-reported only: no independent evaluation and no technical report linked from the launch post as of October 14.
  • • 128 dimensions degrades multimodal quality substantially, per the card. Validate per workload.
  • • One 8,192-token budget for everything: ~29 images at 280 tokens each, ~58 video frames at 1 FPS or ~5.5 minutes of audio. Longer media needs chunking and your own aggregation.
  • • Pre-trained only: no safety tuning or output moderation. Application-level safeguards are on you (card).
  • • Training data cutoff is January 2025, so newer libraries and terminology may be less well represented. That is my inference from the cutoff, not a measured result.
  • • Quality varies across the 100+ languages, and nuance, sarcasm and figurative language can be hard to capture (card).
  • • The cards promise one shared space across this model’s encoder configurations, not compatibility with EmbeddingGemma 1 vectors. Plan a full re-index when you switch.

9. What to do this week

Do not decide from the vendor table. A one-day evaluation on your own data answers the question, and the steps are cheap.

Evaluation checklist

  1. 1. Pull 50 to 100 real queries from your logs with their correct documents (or code snippets, if code search is the goal). That is your eval set.
  2. 2. Embed with prompt_name SearchQuery and Document at 768, 256 and 128 dimensions and compare recall@k.
  3. 3. Read the license page and the Prohibited Use Policy with whoever signs off on dependencies, and pin the repo commit.
  4. 4. Load only the encoders you need (270M text-only, or add vision or audio) and store vectors as bfloat16 or halfvec.
  5. 5. If you already run Postgres, swap it into your hybrid pipeline and keep the eval in CI.

Verdict

EmbeddingGemma 2 is a solid open release with one honest headline, code retrieval, and one genuinely useful structural change: a small, modular model that can index text, code, images, video and audio locally. On Google’s own multilingual benchmark the text gain over v1 is flat, and every figure is vendor-reported.

Worth a one-day evaluation if you do code or media search or need data to stay local. Skip the migration if you embed plain prose and a hosted model already meets your recall target. Either way, decide with your own recall@k, starting at 256 dimensions.

Sources for this post

Primary sources, read on October 14, 2026

  • • Google blog: EmbeddingGemma 2 launch (Oct 6, 2026)
  • • Hugging Face model card and repo files: google/embeddinggemma-2
  • • Google AI for Developers: EmbeddingGemma 2 model card
  • • Google developers blog: EmbeddingGemma 2 developer guide
  • • License page linked from the card + Gemma Prohibited Use Policy
  • • EmbeddingGemma 1 card, Ollama library page, pgvector README
Diego Rodriguez

Diego Rodriguez

Senior Full-Stack & AI Engineer

Diego has 10+ years of experience building production-grade AI-powered applications, from LLM orchestration and RAG pipelines to ML-driven risk detection and algorithmic trading systems.

Learn more about Diego →