Table of Contents
Gemini Embedding 2 converts text, images, audio, video, and PDFs into vectors in one shared embedding space. That makes it possible to compare a text query with an image, retrieve a document from an audio description, or index a mixed-media catalog with one model.
The current stable Gemini API model ID is gemini-embedding-2. Older examples that use gemini-embedding-2-preview should be updated and tested before use.
What an embedding does
An embedding is a list of numbers that represents characteristics of the input. Similar items should have vectors that point in similar directions. A search system typically:
- splits source material into useful items or chunks;
- creates and stores an embedding for each item;
- creates an embedding for the user’s query;
- calculates similarity between the query and stored vectors;
- returns the highest-scoring candidates for further filtering or generation.
An embedding does not contain a readable explanation, verify a fact, or replace the source material. Store the source ID, permissions, timestamps, and other metadata beside each vector.
Gemini Embedding 2 capabilities
| Input | Current documented limit |
|---|---|
| Text | Up to 8,192 tokens |
| Images | Up to 6 PNG or JPEG images per request |
| Audio | Up to 180 seconds; MP3 or WAV |
| Video | Up to 120 seconds; MP4 or MOV with supported codecs |
| One PDF per request, up to 6 pages |
The overall request must also fit the model’s 8,192-token input limit. Video is sampled to a limited number of frames, and the audio track inside a video file is not processed. Check the official embeddings documentation before designing production chunk sizes because limits and formats can change.
1. Install the Python SDK
python -m venv .venv
# Windows PowerShell
.venvScriptsActivate.ps1
# macOS or Linux
source .venv/bin/activate
python -m pip install --upgrade google-genai
Create an API key in Google AI Studio and expose it to the current terminal:
# Windows PowerShell
$env:GEMINI_API_KEY="replace-with-your-key"
# macOS or Linux
export GEMINI_API_KEY="replace-with-your-key"
Do not put an API key in source code, screenshots, or a committed .env file.
2. Generate a text embedding
Save this as text_embedding.py:
from google import genai
from google.genai import types
client = genai.Client()
result = client.models.embed_content(
model="gemini-embedding-2",
contents="title: Typewriter | text: A restored manual typewriter from 1954",
config=types.EmbedContentConfig(output_dimensionality=768),
)
vector = result.embeddings[0].values
print("Dimensions:", len(vector))
print("First five values:", vector[:5])
Run it with:
python text_embedding.py
The default vector has 3,072 dimensions. Google documents flexible sizes from 128 to 3,072 and recommends 768, 1,536, or 3,072. A smaller vector reduces storage and similarity-computation cost, but retrieval quality must be measured on your own data.
3. Embed an image
Place a PNG named sample.png beside the script:
from pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
image_bytes = Path("sample.png").read_bytes()
result = client.models.embed_content(
model="gemini-embedding-2",
contents=[
types.Part.from_bytes(
data=image_bytes,
mime_type="image/png",
)
],
config=types.EmbedContentConfig(output_dimensionality=768),
)
vector = result.embeddings[0].values
print("Dimensions:", len(vector))
Use the real MIME type: image/png for PNG or image/jpeg for JPEG. The original example incorrectly read a PNG while labeling it JPEG; mismatched metadata can cause errors or unexpected handling.
4. Build a minimal text-to-image comparison
The following script embeds one text query and every PNG in an images folder, then ranks the files by cosine similarity:
from __future__ import annotations
import math
from pathlib import Path
from google import genai
from google.genai import types
MODEL_ID = "gemini-embedding-2"
DIMENSIONS = 768
IMAGE_DIR = Path("images")
client = genai.Client()
config = types.EmbedContentConfig(output_dimensionality=DIMENSIONS)
def cosine_similarity(a: list[float], b: list[float]) -> float:
if len(a) != len(b):
raise ValueError("Vectors must have the same dimensions.")
dot = sum(x * y for x, y in zip(a, b))
norm_a = math.sqrt(sum(x * x for x in a))
norm_b = math.sqrt(sum(y * y for y in b))
if norm_a == 0 or norm_b == 0:
return 0.0
return dot / (norm_a * norm_b)
def embed_query(query: str) -> list[float]:
result = client.models.embed_content(
model=MODEL_ID,
contents=f"task: search result | query: {query}",
config=config,
)
return result.embeddings[0].values
def embed_png(path: Path) -> list[float]:
result = client.models.embed_content(
model=MODEL_ID,
contents=[
types.Part.from_bytes(
data=path.read_bytes(),
mime_type="image/png",
)
],
config=config,
)
return result.embeddings[0].values
def main() -> None:
paths = sorted(IMAGE_DIR.glob("*.png"))
if not paths:
raise SystemExit("Add one or more PNG files to the images folder.")
query = "a vintage typewriter on a wooden desk"
query_vector = embed_query(query)
results = []
for path in paths:
score = cosine_similarity(query_vector, embed_png(path))
results.append((score, path.name))
for score, filename in sorted(results, reverse=True):
print(f"{score:.4f} {filename}")
if __name__ == "__main__":
main()
Create the folder, add a few test images, and run the script. The highest score is the closest match within that small collection; it is not a universal probability that the image is “correct.”
Task instructions for text retrieval
Gemini Embedding 2 does not use the older task_type parameter. For text-only search, the documentation recommends including an instruction in the text:
| Purpose | Query format | Document format |
|---|---|---|
| Search | task: search result | query: ... | title: ... | text: ... |
| Question answering | task: question answering | query: ... | title: ... | text: ... |
| Fact checking | task: fact checking | query: ... | title: ... | text: ... |
| Code retrieval | task: code retrieval | query: ... | title: ... | text: ... |
For a single embedding made from interleaved text and media, Google generally advises against adding a task prefix to the text portion. Test both retrieval directions—text to image and image to text—because cross-modal performance may not be symmetric for your collection.
Understand aggregated and separate embeddings
This call produces one aggregated embedding representing the text and image together:
result = client.models.embed_content(
model="gemini-embedding-2",
contents=[
"A red hiking backpack photographed from the front",
types.Part.from_bytes(
data=Path("backpack.png").read_bytes(),
mime_type="image/png",
),
],
)
That behavior is useful when both parts describe one object, such as a product listing. It is wrong when you expect one independent vector for each input. To request separate embeddings in one call, wrap each item in a separate types.Content object or use the Batch API as documented.
Decide the retrieval unit before indexing. A product page may need separate vectors for title, description, and each image, plus an optional aggregate. Storing only one aggregate can hide which part produced the match.
Audio, video, and PDF considerations
- Audio: divide long recordings into overlapping, timestamped segments. Keep the original time range beside each vector.
- Video: account for frame sampling and the fact that the embedded video track does not include its audio. Embed audio separately when it matters.
- PDF: chunk by page or coherent section. A PDF request is limited to six pages, and the documentation recommends smaller units for quality.
- Images: retain filename, rights information, alt text, and useful structured metadata rather than relying on the vector alone.
Direct multimodal embedding can preserve signals that a text-only transcription misses, but it is not lossless. Every embedding compresses the input, and sampling or truncation can omit information.
Evaluate retrieval quality
Build a small labeled set of real queries before selecting a vector size or database. For each query, identify the items that should be retrieved, then measure:
- Recall at k: whether a relevant item appears in the first k results.
- Precision at k: how many of the first k results are relevant.
- Ranking quality: whether the best result appears near the top.
- Latency and cost: time and API/storage cost for indexing and querying.
- Slice performance: results by language, modality, content type, and difficult query category.
Do not choose a similarity threshold from a few attractive examples. Scores depend on the model, content, and query distribution.
Migrate from an older embedding model
Vectors from gemini-embedding-001, a preview model, or a different provider cannot be compared directly with Gemini Embedding 2 vectors. A safe migration is:
- create a new index or versioned vector column;
- embed a representative subset with the new model;
- run the same labeled evaluation against both systems;
- select dimensions and chunking based on measured results;
- re-embed the full collection;
- switch reads only after validating completeness and rollback;
- retire the old index when the new one is stable.
Store the model ID, output dimensionality, content version, and preprocessing method with every vector. This prevents incompatible vectors from being mixed silently.
Security, privacy, and cost
Inputs are sent to the Gemini API. Confirm that you have permission to upload the material and review the current API terms, retention behavior, regional requirements, and pricing. Avoid embedding secrets or personal data unless the system is approved for that use.
Cache embeddings for unchanged content, use content hashes to detect duplicates, and consider the Batch API for large offline indexing jobs. Protect the API key, rate-limit public search endpoints, and enforce document permissions after vector retrieval so a relevant result is not shown to an unauthorized user.
Production checklist
- The retrieval unit and metadata schema are defined.
- All stored vectors use the same model and dimensions.
- Source permissions are checked after retrieval.
- Long media is chunked with timestamps or page references.
- Quality is measured on labeled, representative queries.
- Failed or truncated inputs are logged and retried safely.
- Model, preprocessing, and index versions support rollback.
- Costs, rate limits, and API-key exposure are monitored.
Gemini Embedding 2 simplifies cross-modal search because one model can represent several content types. A good retrieval system still depends on deliberate chunking, metadata, permission checks, evaluation, and a migration plan.
Reader Comments 0
Sign in with email or Google to join the discussion.