Desarrollo IA

EmbeddingGemma 2: Embeddings Multimodales Abiertos que Corren en Local

14 de octubre de 2026
12 min de lectura
Servidor compacto sobre un escritorio, con luz suave sobre un fondo neutro
Compartir:

El 6 de octubre de 2026, Google DeepMind lanzó EmbeddingGemma 2, un modelo de embeddings abierto de unos 740 millones de parámetros que mapea texto, código, imágenes, video y audio a un único espacio vectorial de 768 dimensiones. Corre en tu propio hardware, los pesos están en Hugging Face y Kaggle, y la model card declara Apache 2.0.

Esta es mi lectura del post de lanzamiento, la model card y la guía para desarrolladores, con cada número atribuido y nada re-corrido por mí. Acá tenés la ficha técnica, qué cambió respecto de EmbeddingGemma 1, un quickstart copiado de la card, las cuentas de almacenamiento para 768 vs 128 dimensiones, una respuesta precisa sobre la licencia y dónde se queda corto.

1. Los hechos del lanzamiento

EmbeddingGemma 2 está construido sobre la arquitectura de Gemma 4 y comparte su tokenizer de texto y su encoder de audio. Es modular: el modelo de texto ronda los 270M de parámetros (un transformer de 130M más un embedder de 140M), el encoder de visión suma 170M y el de audio 300M, y de ahí salen los 740M totales. Según el blog de Google, podés cargar solo los encoders que necesitás.

Todo cae en el mismo espacio de 768 dimensiones, y una sola ventana de contexto de 8.192 tokens se comparte entre modalidades. El antecesor, EmbeddingGemma 1 (septiembre de 2025), era un modelo solo de texto de unos 300M de parámetros con 2.048 tokens de contexto.

La model card de un vistazo

  • • Lanzamiento: 6 de octubre de 2026 por Google DeepMind (fecha del post del blog de Google)
  • • Tamaño: ~740M de parámetros = 270M de texto + 170M encoder de visión + 300M encoder de audio; solo texto carga 270M
  • • Entradas: texto y código, imágenes, video, audio y combinaciones intercaladas, todo en un único espacio vectorial
  • • Salida: 768 dimensiones; truncado Matryoshka a 512, 256 o 128
  • • Contexto: 8.192 tokens compartidos entre modalidades (EmbeddingGemma 1: 2.048)
  • • Presupuesto por entrada (card): 280 tokens por imagen (~29 imágenes), 140 tokens por frame de video a 1 FPS (~58 frames), 25 tokens por segundo de audio (~327 s)
  • • Licencia: declarada Apache 2.0 (la sección 4 explica qué resuelve y qué no)
  • • Pesos: Hugging Face (unos 1,5 GB de safetensors), Kaggle, Ollama, build GGUF de llama.cpp

2. Qué mejoró de verdad frente a EmbeddingGemma 1

Cambiaron tres cosas, y solo una es un benchmark. La versión 1 era solo texto y estaba detrás de los términos Gemma de Google; la versión 2 acepta imágenes, video y audio, cuadruplica la ventana de contexto y, según la card, es Apache 2.0. El único número que Google pone en el titular es la recuperación de código: MTEB (Code, v1) pasa de 68,76 a 78,68, una mejora de 9,92 puntos (reportado por el vendor, model card y blog, 6-oct-2026).

Mirá también la otra fila. En MTEB (Multilingual, v2) la card muestra 61,36 contra 61,15 de la versión 1, o sea que la calidad de texto general es prácticamente igual. Si tu corpus es prosa común, eso solo no alcanza para actualizar. Las razones son el código, los medios y la longitud de contexto.

Los tres cambios reales

🎞️

Modalidades

Texto, código, imágenes, video y audio en un solo espacio, así una consulta de texto puede recuperar una foto o una grabación sin capa de fusión.

💻

Recuperación de código

MTEB Code v1: 68,76 a 78,68 (+9,92 puntos, NDCG@10), reportado por el vendor. Texto multilingüe: 61,15 a 61,36.

📏

Contexto

8.192 tokens, 4x EmbeddingGemma 1, pero compartidos por todas las modalidades: imágenes, frames y audio gastan el mismo presupuesto.

Regla de oro

Actualizá por búsqueda de código, de medios o por entradas más largas. Para texto multilingüe común la card muestra un movimiento de 0,21 puntos, y tu propio recall@k te dice más que ese número.

3. Los números, con fuentes y salvedades

Cada cifra de abajo sale de la model card de Google (precisión completa, 6-oct-2026) y es reportada por el vendor. Los nombres y versiones de benchmark son los impresos ahí: MTEB multilingual v2, MTEB code v1, MIEB lite, MMEB v2, MSEB retrieval y MAEB. La tabla es la tabla de truncado de la propia card, recortada a seis columnas de score.

Truncado Matryoshka: scores por dimensión

Reportado por el vendor, de la model card. Más alto es mejor; cada columna usa la métrica que la card lista para ese 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

Lo que sigue es aritmética mía sobre esos números, nada más. A 256 dimensiones los scores de la card conservan entre 95 y 99% del score de 768 dims en todas las columnas (MMEB v2 es el más bajo, 56,24 contra 59,01). A 128 dimensiones texto y código aguantan (MTEB multilingual 94%, MTEB code 91%) pero los medios no: MMEB v2 cae a 77% (45,65 contra 59,01) y MSEB retrieval a 82%.

Qué confirman las fuentes primarias

  • • ~740M de parámetros, 768 dimensiones, Matryoshka a 512/256/128, contexto de 8.192 tokens (blog de Google y model card)
  • • MTEB Code v1 a 768 dims: 68,76 a 78,68, NDCG@10 (model card)
  • • MTEB multilingual v2: 61,15 a 61,36, o sea calidad de texto casi igual (model card)
  • • Memoria cuantizada en un Pixel 11 Pro: ~191 MB solo texto, ~567 MB multimodal completo (blog de Google, reportado por el vendor)

Letra chica

Son corridas de la propia Google. El blog dice que lidera entre los embedders multimodales de menos de 1B y que supera a algunos modelos especialistas de más del doble de tamaño, pero no imprime números de esas comparaciones y no enlaza ningún reporte técnico. En las búsquedas que hice el 14 de octubre solo encontré notas que repiten las cifras de Google, ninguna evaluación independiente. Tomá la tabla como direccional y medí con tus datos.

4. La licencia: qué gobierna el uso de verdad

A primera vista la card parece inconsistente: dice Apache 2.0 pero enlaza un archivo con nombre de licencia de Gemma 4. En vez de confiar en el nombre del archivo, leí las piezas. Esto encontré el 14 de octubre de 2026.

Qué revisé

  • • Metadata de la card: license: apache-2.0 en el front matter del README y un tag license:apache-2.0 en la API de Hugging Face. No hay campo license_name ni license_link.
  • • Link del encabezado: el “License: Apache 2.0” de la card apunta a ai.google.dev/gemma/docs/gemma_4_license. El slug dice Gemma 4, pero la página que descargué se titula Apache License 2.0 y contiene el texto de Apache 2.0. Gemma 4 mismo salió con Apache 2.0, según el blog de Google.
  • • Archivos del repo: no hay archivo LICENSE ni NOTICE. El repo tiene README.md, archivos de config y tokenizer, y el model.safetensors de 1,49 GB. El único texto de licencia al que llega un lector es la página enlazada.
  • • El post de lanzamiento de Google y la página de model card de Google también dicen Apache 2.0.

El cabo suelto

La card además dice que los despliegues deben cumplir la Gemma Prohibited Use Policy. Esa página se actualizó por última vez en febrero de 2024, está escrita para “Gemma or Model Derivatives” y es anterior al paso de Gemma 4 a Apache 2.0. Apache 2.0 no tiene cláusula de campo de uso, así que la card resulta inconsistente sobre si esa política te obliga. EmbeddingGemma 1 es distinto: su card dice license gemma y protege la descarga con los términos de Google, así que los derivados de v1 siguen bajo esos términos.

Lectura práctica

Todo lo que declara licencia dice Apache 2.0, así que yo planificaría con Apache 2.0 para los pesos que bajás hoy, guardaría una copia de la página de licencia y del commit que descargaste, y trataría la Prohibited Use Policy como piso de lo que construís. No es asesoría legal: si el modelo va dentro de un producto con clientes, que alguien que lee licencias para vivir lea ambos documentos.

5. Quickstart: texto, truncado y multimodal

Los snippets de abajo son los que Google imprime en la model card y en la guía para desarrolladores. No los ejecuté. La guía instala con los extras de imagen, audio y video; la línea más corta de la card cubre solo texto.

Instalar y embeber texto (model card)

Consultas y documentos usan distinto prompt name. prompt_name="Document" aplica title: none, así que formateá a mano los documentos con título.

# solo texto (model card)
pip install -U sentence-transformers transformers

# extras de imagen, audio y video (guía; poné comillas a los extras en 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))

Prefijos de tarea (solo texto)

  • • SearchQuery: task: search result | query: {query}. Documentos: title: {title} | text: {content}
  • • QuestionAnswering: task: question answering | query: {question}
  • • FactChecking: task: fact checking | query: {claim}
  • • CodeRetrieval: task: code retrieval | query: {query}. Documentos: title: {title or filename} | text: {code}
  • • Classification, Clustering, SentenceSimilarity (simétricos): task: classification | query: {content}, y así

Imágenes, video y audio no llevan prefijo. Usá title: none cuando un documento no tiene título. Omitir el prefijo en texto igual funciona pero baja la calidad, según la card.

Truncado Matryoshka y precisión (card y guía)

Pasá truncate_dim y normalize_embeddings juntos y usá la misma dimensión para consultas y documentos. El snippet de dtype de la card omite import torch; lo agregué yo.

import torch
from sentence_transformers import SentenceTransformer

# card: bfloat16 si la GPU lo soporta, si no float32 (nunca 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,          # o 512, 128
    normalize_embeddings=True,
)

Búsqueda cross-modal e input intercalado (guía, model card)

Los medios entran como diccionario con clave por modalidad, sin prefijo. El audio debe ser mono a 16 kHz y el video se muestrea a 1 frame por segundo por defecto.

# una consulta de texto contra una foto y una grabación de sonido
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))

# intercalado: un embedding para texto + fotos + 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",
})

Carga selectiva de encoders

  • • Solo texto (270M): config_kwargs={"vision_config": None, "audio_config": None}
  • • Texto e imagen (440M): config_kwargs={"audio_config": None}
  • • Texto y audio (570M): config_kwargs={"vision_config": None}
  • • Multimodal completo (740M): sin config_kwargs

Pasá config_kwargs a SentenceTransformer(...). Según la guía todas las configuraciones comparten un espacio vectorial, así que podés sumar un encoder después sin re-embeber los vectores existentes.

Si preferís no correr Python, Google lista Ollama (ollama pull embeddinggemma-2), un build GGUF de llama.cpp, MLX, vLLM, SGLang, LM Studio, LiteRT, MediaPipe y transformers.js con una demo WebGPU. La página de Ollama que leí lista solo tags de texto y de texto más imagen e imprime un contexto de 256K que contradice los 8.192 tokens de la card, así que para audio o video usá la ruta de Python y confiá en la card.

Trampas del quickstart

  • • float16 devuelve NaN o embeddings degradados en silencio en vez de lanzar un error. Usá bfloat16 o float32 (model card).
  • • Cortar un vector rompe su norma unitaria. Re-normalizá después de truncar o el ranking se degrada sin ningún error (model card).
  • • Un hilo de la comunidad en la card (discusión #13 de Hugging Face, 14-oct) reporta un ImportError por la librería PIL en una instalación limpia con el quickstart simple. Lo más probable es que se arregle con los extras o con pip install pillow; no lo reproduje.
  • • El config.json del repo se guardó con transformers 5.18.0.dev0 y la card no declara versión mínima. Dejá el -U en la línea de instalación y fijá las versiones que pasen tu propio test.

6. Cuentas de almacenamiento: 768 vs 128 dimensiones

El tamaño del embedding es la parte del modelo que controlás vos, así que hacé la aritmética antes de elegir dimensión. Un vector cuesta dimensiones por bytes por número. El blog de Google anuncia hasta 6x menos almacenamiento a 128 dimensiones; acá está de dónde sale.

La aritmética (vectores crudos, sin índice)

Las cifras de la guía para 1M de vectores son ~1,5 GB a 768 dims y ~250 MB a 128 dims. Las fórmulas de pgvector salen de su README.

768 dims x 2 bytes (bf16) = 1.536 bytes por vector
1.000.000 x 1.536 B       = 1,536 GB   (guía: "roughly 1.5 GB")

128 dims x 2 bytes        =   256 bytes por vector
1.000.000 x 256 B         = 256 MB     (guía: "roughly 250 MB")

768 / 128 = 6x    768 / 256 = 3x    768 / 512 = 1,5x

float32 duplica cada línea: 768 x 4 B = 3.072 B -> 3,07 GB por 1M de vectores
pgvector vector  = 4 x dims + 8 bytes -> 3.080 B a 768 dims, 520 B a 128 dims
pgvector halfvec = 2 x dims + 8 bytes -> 1.544 B a 768 dims, 264 B a 128 dims

Tamaño crudo por dimensión (2 bytes por número)

DimsPor vector1M vectores10M vectoresvs 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

Dos advertencias. Son bytes crudos de vector: arriba se suman el índice HNSW, la metadata y las réplicas. Y el ahorro no es gratis: a 128 dims el score MMEB v2 de la card cae de 59,01 a 45,65, y la propia guía de Google dice que valides 128d con tus datos antes de usarlo en consultas multimodales.

Mi default

Empezá en 256 dimensiones guardadas como bfloat16 o halfvec: 3x más chico que 768, y la card conserva 95% o más de los scores completos en todas las columnas de arriba (la guía para desarrolladores apunta en la misma dirección). Pasá a 128 solo para texto o código, y solo después de que tu propio recall@k diga que está bien.

7. ¿Elegirlo o quedarte en una API hosteada?

Las APIs de embeddings hosteadas siguen siendo el camino más corto para muchos equipos, incluido el Gemini Embedding 2 de la propia Google. La pregunta es qué restricción tenés de verdad.

Elegí EmbeddingGemma 2 cuando

  • • Los datos no pueden salir del dispositivo o de tu VPC, o la búsqueda tiene que andar offline
  • • Buscás sobre código, fotos, clips o grabaciones y querés un solo índice local en vez de pipelines separados de texto y medios
  • • El volumen es lo bastante alto como para que las tarifas por llamada pesen más que una máquina CPU o GPU que ya corrés
  • • Querés ser dueño del espacio vectorial: fijar versión del modelo, hacerle fine-tuning (Apache 2.0 según la card) y olvidarte del calendario de deprecaciones de un vendor

Quedate hosteado cuando

  • • El volumen es bajo o a ráfagas y no querés operar batching, GPUs y upgrades
  • • Tus entradas son PDFs: la card documenta entradas de imagen y un benchmark de documentos visuales pero no entrada nativa de PDF, así que tendrías que rasterizar las páginas vos
  • • Un modelo hosteado ya cumple tu objetivo de recall: cambiar implica re-embeber todo el corpus

Mi post anterior cubre la ruta hosteada (Vertex AI, 3.072 dimensiones por defecto al momento de ese post): Gemini Embedding 2: los embeddings multimodales de Google

8. Límites honestos

Todo lo bueno de este release está en la página de Google. Esto es lo que dicen las mismas fuentes, y el sentido común, para tener presente.

Antes de comprometerte

  • • Solo reportado por el vendor: ninguna evaluación independiente ni reporte técnico enlazado desde el post de lanzamiento al 14 de octubre.
  • • 128 dimensiones degrada la calidad multimodal de forma sustancial, según la card. Validá por workload.
  • • Un solo presupuesto de 8.192 tokens para todo: ~29 imágenes a 280 tokens cada una, ~58 frames de video a 1 FPS o ~5,5 minutos de audio. Los medios más largos piden chunking y tu propia agregación.
  • • Solo pre-entrenado: sin safety tuning ni moderación de salida. Las salvaguardas a nivel aplicación son tuyas (card).
  • • El corte de datos de entrenamiento es enero de 2025, así que librerías y terminología más nuevas pueden estar peor representadas. Es una inferencia mía a partir del corte, no un resultado medido.
  • • La calidad varía entre los más de 100 idiomas, y el matiz, el sarcasmo y el lenguaje figurado pueden ser difíciles de capturar (card).
  • • Las cards prometen un espacio compartido entre las configuraciones de encoders de este modelo, no compatibilidad con los vectores de EmbeddingGemma 1. Planificá un re-índice completo al cambiar.

9. Qué hacer esta semana

No decidas con la tabla del vendor. Una evaluación de un día con tus propios datos responde la pregunta, y los pasos son baratos.

Checklist de evaluación

  1. 1. Sacá de tus logs 50 a 100 consultas reales con sus documentos correctos (o fragmentos de código, si el objetivo es búsqueda de código). Ese es tu set de evaluación.
  2. 2. Embebé con prompt_name SearchQuery y Document a 768, 256 y 128 dimensiones y compará recall@k.
  3. 3. Leé la página de licencia y la Prohibited Use Policy con quien aprueba las dependencias, y fijá el commit del repo.
  4. 4. Cargá solo los encoders que necesitás (270M solo texto, o sumá visión o audio) y guardá los vectores como bfloat16 o halfvec.
  5. 5. Si ya corrés Postgres, cambialo dentro de tu pipeline híbrido y dejá la evaluación en CI.

Veredicto

EmbeddingGemma 2 es un release abierto sólido con un titular honesto, la recuperación de código, y un cambio estructural realmente útil: un modelo chico y modular que puede indexar texto, código, imágenes, video y audio en local. En el benchmark multilingüe de la propia Google la mejora de texto sobre v1 es nula, y toda cifra es reportada por el vendor.

Vale una evaluación de un día si hacés búsqueda de código o de medios o necesitás que los datos queden en local. Salteá la migración si embebés prosa común y un modelo hosteado ya cumple tu recall. En cualquier caso, decidí con tu propio recall@k, empezando en 256 dimensiones.

Fuentes de este post

Fuentes primarias, leídas el 14 de octubre de 2026

  • • Blog de Google: lanzamiento de EmbeddingGemma 2 (6-oct-2026)
  • • Model card y archivos del repo en Hugging Face: google/embeddinggemma-2
  • • Google AI for Developers: model card de EmbeddingGemma 2
  • • Blog de desarrolladores de Google: guía para desarrolladores de EmbeddingGemma 2
  • • Página de licencia enlazada desde la card + Gemma Prohibited Use Policy
  • • Card de EmbeddingGemma 1, página de Ollama, README de pgvector
Diego Rodriguez

Diego Rodriguez

Ingeniero Senior Full-Stack & AI

Diego tiene mas de 9 anos de experiencia construyendo aplicaciones potenciadas por IA de produccion, desde orquestacion de LLMs y pipelines RAG hasta deteccion de riesgos con ML y sistemas de trading algoritmico.

Conoce mas sobre Diego →