Migration from gemini-embedding-001 Fresh 🌱
Migrate from gemini-embedding-001 to Gemini Embedding 2 with zero downtime using parallel systems.
Migration Architecture
Migration Timeline
Key Differences: v1 vs v2
| Feature | gemini-embedding-001 | Gemini Embedding 2 |
|---|---|---|
| Model ID | gemini-embedding-001 | gemini-embedding-2-preview |
| Modalities | Text only | Text, Image, Video, Audio, PDF |
| Default dimensions | 768 | 3072 |
| Dimension range | 1-768 | 128-3072 |
| Languages | 100+ | 100+ |
| Pricing (text) | $0.15/1M tokens | $0.20/1M tokens |
| Pricing (batch) | $0.075/1M tokens | $0.10/1M tokens |
| MRL support | Yes | Yes |
| Interleaved input | No | Yes |
Incompatible Embedding Spaces
Embeddings from gemini-embedding-001 and gemini-embedding-2-preview are NOT compatible. You cannot compare vectors across models. All data must be re-embedded.
Implementation
Step 1: Audit Current System
python
# Inventory your current embedding setup
audit = {
'model': 'gemini-embedding-001',
'dimensions': 768, # Check your current setting
'total_documents': 0, # Count your indexed docs
'vector_db': 'chromadb', # Your vector database
'task_types_used': [], # Which task types you use
'collections': [], # List of collections
}
# Count documents in your vector DB
import chromadb
chroma = chromadb.PersistentClient(path='./vectordb')
for collection_name in chroma.list_collections():
col = chroma.get_collection(collection_name.name)
count = col.count()
audit['total_documents'] += count
audit['collections'].append({
'name': collection_name.name,
'count': count
})
print(f"Total documents to re-embed: {audit['total_documents']}")Step 2: Update Model ID and Dimensions
python
# Old code
OLD_MODEL = 'gemini-embedding-001'
OLD_DIMENSIONS = 768
# New code
NEW_MODEL = 'gemini-embedding-2-preview'
NEW_DIMENSIONS = 768 # Keep same for easy comparison, or upgrade to 1536/3072Step 3: Create Parallel Collection
python
import chromadb
chroma = chromadb.PersistentClient(path='./vectordb')
# Keep old collection
old_collection = chroma.get_collection('documents_v1')
# Create new collection for v2 embeddings
new_collection = chroma.get_or_create_collection(
name='documents_v2',
metadata={'hnsw:space': 'cosine'}
)Step 4: Re-embed All Data
python
from google import genai
from google.genai import types
import time
client = genai.Client()
def re_embed_collection(old_col, new_col, batch_size=100):
"""Re-embed all documents from old collection to new collection."""
total = old_col.count()
processed = 0
offset = 0
while offset < total:
# Get batch from old collection
batch = old_col.get(
limit=batch_size,
offset=offset,
include=['documents', 'metadatas']
)
if not batch['ids']:
break
# Re-embed with new model
for i, (doc_id, doc_text) in enumerate(zip(batch['ids'], batch['documents'])):
try:
result = client.models.embed_content(
model='gemini-embedding-2-preview',
contents=doc_text,
config=types.EmbedContentConfig(
task_type='RETRIEVAL_DOCUMENT',
output_dimensionality=768
)
)
new_col.add(
ids=[doc_id],
embeddings=[result.embeddings[0].values],
documents=[doc_text],
metadatas=[batch['metadatas'][i]] if batch['metadatas'] else None
)
processed += 1
if processed % 100 == 0:
print(f" Re-embedded {processed}/{total}")
except Exception as e:
print(f" Error on {doc_id}: {e}")
time.sleep(1) # Rate limit backoff
offset += batch_size
print(f"Migration complete: {processed}/{total} documents")
re_embed_collection(old_collection, new_collection)Step 5: Quality Comparison
python
import numpy as np
def compare_search_quality(queries, old_col, new_col, top_k=10):
"""Compare search results between old and new collections."""
for query in queries:
# Old model embedding
old_result = client.models.embed_content(
model='gemini-embedding-001',
contents=query,
config=types.EmbedContentConfig(task_type='RETRIEVAL_QUERY')
)
old_hits = old_col.query(
query_embeddings=[old_result.embeddings[0].values],
n_results=top_k
)
# New model embedding
new_result = client.models.embed_content(
model='gemini-embedding-2-preview',
contents=query,
config=types.EmbedContentConfig(
task_type='RETRIEVAL_QUERY',
output_dimensionality=768
)
)
new_hits = new_col.query(
query_embeddings=[new_result.embeddings[0].values],
n_results=top_k
)
# Compare overlap
old_ids = set(old_hits['ids'][0])
new_ids = set(new_hits['ids'][0])
overlap = old_ids & new_ids
print(f"\nQuery: {query[:60]}...")
print(f" Overlap: {len(overlap)}/{top_k} results in common")
print(f" Old top result: {old_hits['ids'][0][0]}")
print(f" New top result: {new_hits['ids'][0][0]}")
# Test with representative queries
test_queries = [
'How to deploy a machine learning model',
'Best practices for data security',
'Revenue growth strategies for Q4',
]
compare_search_quality(test_queries, old_collection, new_collection)Step 6: Switch Traffic
python
# Feature flag approach
USE_V2 = True # Flip this to switch
def search(query, top_k=10):
model = 'gemini-embedding-2-preview' if USE_V2 else 'gemini-embedding-001'
collection = new_collection if USE_V2 else old_collection
config_kwargs = {'task_type': 'RETRIEVAL_QUERY'}
if USE_V2:
config_kwargs['output_dimensionality'] = 768
result = client.models.embed_content(
model=model,
contents=query,
config=types.EmbedContentConfig(**config_kwargs)
)
return collection.query(
query_embeddings=[result.embeddings[0].values],
n_results=top_k
)Migration Checklist
- [ ] Current system audited (document count, dimensions, task types)
- [ ] SDK updated to latest
google-genai - [ ] New model ID configured (
gemini-embedding-2-preview) - [ ] New vector collection created
- [ ] All documents re-embedded with new model
- [ ] Quality comparison completed with test queries
- [ ] Parallel system running (both v1 and v2)
- [ ] Traffic switched to v2
- [ ] Monitoring in place for quality metrics
- [ ] Old collection decommissioned after validation period
Troubleshooting
| Issue | Solution |
|---|---|
| Dimension mismatch errors | Ensure new collection uses the same dimensions as your v2 embeddings |
| Rate limiting during re-embed | Add exponential backoff; use batch API for 50% savings |
| Search quality regression | Compare task types; try higher dimensions (1536, 3072) |
| Cost increase | Text went from $0.15 to $0.20/1M; use batch API at $0.10/1M |
| Old/new embedding mixed | NEVER mix; use separate collections and model IDs |
See Also
- Getting Started — Set up the new model
- API Reference — Full parameter comparison
- Pricing — Cost comparison between models
- Benchmarks — Quality improvements