Why your EmbeddingGemma 2 vectors are NaN (and the one-line fix)
Loading EmbeddingGemma 2 in float16 silently breaks it. Here's how to detect it and pick the right dtype for your hardware.
The code in this post comes from the model's docs and hasn't been run in our CI yet. If something breaks, let us know.
Loading a model with torch_dtype=torch.float16 is a common habit for saving memory. With EmbeddingGemma 2 it’s a trap: the activations go beyond float16’s range. You don’t get an error. You get NaNs, or embeddings that look fine and rank badly.
The fix
import torchfrom sentence_transformers import SentenceTransformer
use_bf16 = torch.cuda.is_available() and torch.cuda.is_bf16_supported()dtype = torch.bfloat16 if use_bf16 else torch.float32model = SentenceTransformer("google/embeddinggemma-2", model_kwargs={"torch_dtype": dtype})bfloat16 has the same 8-bit exponent as float32, so it uses half the memory without overflowing. Most CPUs and older GPUs (pre-Ampere, such as T4 and V100) don’t support bf16 natively, so use float32 there.
A quick sanity check
Add this once to your pipeline:
import numpy as np
emb = model.encode(["hello world"])assert not np.isnan(emb).any(), "NaN embeddings: check your dtype"Does this apply to other models?
Often, yes. Models in the Gemma family usually ship with bf16 weights. Whenever a model card says “bf16 or fp32, not fp16”, take it at its word.
Related
EmbeddingGemma 2: semantic search on a laptop in 20 lines
Google's new 740M multimodal embedding model runs on a CPU. Here's how to build a working semantic search over your own documents, and the prefixes that make it accurate.
google/embeddinggemma-2
Matryoshka embeddings: how many dimensions do you actually need?
A practical rule of thumb for truncating embeddings to cut vector-DB cost, with the numbers from EmbeddingGemma 2.