GEMINI LABJP
SPARK — Gemini Spark, Google's agentic assistant, arrives in the Gemini app for macOS and works on tasks on your behalfBRIEF — Daily Brief, powered by Personal Intelligence, distills priorities from Gmail and Calendar with suggested next stepsMODEL — Gemini 3.5 Flash reaches GA, offering faster, lower-cost AI with a 1M-token context windowGROWTH — The Gemini app has passed 900 million monthly active users, up from 400 million a year earlierAPPS — Spark now connects to Google Tasks and Google Keep and stays up to date on topics in real timeENTERPRISE — Gemini 3.5 Flash is generally available across the Global, US, and EU regions on Gemini EnterpriseSPARK — Gemini Spark, Google's agentic assistant, arrives in the Gemini app for macOS and works on tasks on your behalfBRIEF — Daily Brief, powered by Personal Intelligence, distills priorities from Gmail and Calendar with suggested next stepsMODEL — Gemini 3.5 Flash reaches GA, offering faster, lower-cost AI with a 1M-token context windowGROWTH — The Gemini app has passed 900 million monthly active users, up from 400 million a year earlierAPPS — Spark now connects to Google Tasks and Google Keep and stays up to date on topics in real timeENTERPRISE — Gemini 3.5 Flash is generally available across the Global, US, and EU regions on Gemini Enterprise
Articles/API / SDK
API / SDK/2026-07-09Intermediate

When gemini-embedding-2 Retrieval Feels 'Almost Right,' Check task_type First

When gemini-embedding-2 search misses in a frustrating near-hit way, the cause is often a missing or mismatched task_type. Here is how to align document and query intent, plus the code and a tiny harness to prove the difference on your own data.

gemini97embedding10RAG14semantic-search4gemini-api268

Premium Article

When I rebuilt the tag search for one of my wallpaper apps on gemini-embedding-2, the results were "not wrong, just off." A search for "sunset ocean" surfaced sunset mountains and empty beaches, and the photo I actually wanted sat in seventh place. When accuracy is zero, you suspect a plain bug. When it is merely close, the cause hides.

I spent half a day poking at normalization and chunk sizes before the real culprit surfaced: task_type. I had embedded both the documents and the query without specifying it. The moment I aligned it, that seventh-place photo jumped to second.

I suspect this happens more often now, not less. Since gemini-embedding-2 went GA and can embed both text and images with one model, people swap models more freely, and the task_type setting quietly gets dropped in the process. As an indie developer running several apps at Dolice, I hit this exact trap, so let me walk through the cause and the fix, with the numbers I measured myself.

task_type tells the model what the embedding is for

An embedding model turns your text into a vector. But the same sentence has a slightly different optimal direction depending on whether it will be used as a document to be searched, or as a query doing the searching.

task_type makes that intent explicit. With gemini-embedding-2 you get embeddings optimized separately for documents and for queries. Leave it unset and you get a general-purpose embedding that is not tuned for the asymmetric task of retrieval, where a short query has to pull long documents.

This is the counterintuitive part. Since queries and documents are compared in the same space, it feels like they should be treated identically. In practice, for an asymmetric task, specifying "for query" and "for document" separately makes the cosine-similarity ranking noticeably more stable.

The common mistake: embedding both sides with no task_type

This is exactly what I was doing. At both index time and search time, I embedded through the same function without passing task_type.

from google import genai
 
client = genai.Client()  # reads GEMINI_API_KEY from the environment
 
def embed_plain(text: str) -> list[float]:
    # No task_type = a generic embedding with no stated purpose
    resp = client.models.embed_content(
        model="gemini-embedding-2",
        contents=text,
    )
    return resp.embeddings[0].values
 
# Both indexing and searching use the same function
doc_vec = embed_plain("A seaside landscape washed in sunset light")
query_vec = embed_plain("sunset ocean")

The code does not error. That is what makes it insidious. Search runs, plausible results come back, and because it is not tuned for the asymmetric case, the ranking is just blurry. That "close but off" symptom is exactly what this state produces.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
If your search keeps missing in an almost-right way, aligning task_type alone can recover the recall you were losing
You will get copy-paste-ready code that uses RETRIEVAL_DOCUMENT and RETRIEVAL_QUERY correctly
You can adopt a habit of A/B testing task_type against a small golden set in your own project
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API / SDK2026-07-04
Catch Near-Duplicate Posts Before You Publish — a Topic-Cannibalization Gate with Gemini Embeddings
Once a blog passes a few hundred posts, new articles start cannibalizing old ones in search. This walks through a pre-publish gate that embeds each post's meaning with gemini-embedding-2 and blocks drafts that sit too close to something you already wrote — with runnable code and how to pick the thresholds.
API / SDK2026-06-29
Stop Losing Silently-Failed Jobs in Your Unattended Gemini API Pipeline
When an unattended Gemini API batch drops a single job in silence, you may not notice for days. Here is a minimal dead-letter store and a safe replay flow — with copy-paste code and the operational judgment that makes it work.
API / SDK2026-06-26
Reliable Text-in-Image with Gemini 3.1 Flash Image — an OCR-Verified Pipeline
After the preview shutdown, the GA gemini-3.1-flash-image still occasionally garbles text baked into images. Here is a generate -> read-back-verify -> regenerate/composite pipeline, with working code and an unattended retry budget.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →