◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
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.

gemini119embedding10RAG14semantic-search4gemini-api286

✦ 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-09-04
Screen Loop Seam Clicks With Numbers Before You Hand the Audio to Gemini
An ambient loop that clicks only at the wrap point. Here is the numeric prescreen I run before sending anything to audio understanding, why an absolute threshold fails, and how AAC encoding quietly rebuilt the seam I had just repaired.
◈ API / SDK2026-08-23
Moving app AI work from runtime calls to a pre-ship batch pass
Where you put a Gemini call decides whether your request count scales with users or with assets. Here is the decision rule I used to move classification into a pre-ship batch pass, plus a resumable implementation.
◈ API / SDK2026-08-22
Once You Pass Twenty Mediation Groups, How Do You Find the Setting That Went Missing?
As ad mediation groups multiply, missing sources and type drift accumulate quietly. Here is the split I settled on: normalize the settings into one matrix, let code confirm the gaps, and send Gemini only the cells that need judgment.