◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — The old Deep Research agent shut down on 10/23. If calls fail, 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●CLI — Gemini API CLI (gemini-api) is out in beta (10/27): a zero-dependency client for agents and CI●STORE — New paid projects now save Generate Content requests by default (store on) as of 10/26●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 — The old Deep Research agent shut down on 10/23. If calls fail, 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●CLI — Gemini API CLI (gemini-api) is out in beta (10/27): a zero-dependency client for agents and CI●STORE — New paid projects now save Generate Content requests by default (store on) as of 10/26●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/Advanced
⬡ Advanced/2026-07-31Advanced

After the Vertex AI Rename, I Measured My Search Stack. Ranking Held. Aggregation Did Not.

When Vertex AI became Gemini Enterprise Agent Platform, I benchmarked my own docs search. Ranking barely moved. The exact-match layer quietly lost most of its results without raising a single error.

Gemini Enterprise Agent PlatformVertex AI12search designaliasingoperations19

✦ Premium Article

I found the line in the release notes late on July 30th: Vertex AI is now Gemini Enterprise Agent Platform.

My first thought went to my runbooks. Running six apps solo means my personal notes and my in-app help index have slowly turned into a small knowledge base. Every "Vertex AI" in there now points at a name that no longer exists.

Tomorrow, when someone searches with the new name, would anything come back at all?

So the next morning I measured it. The answer was the opposite of what I expected. Ranking held up fine. Something else had gone quietly missing.

What I Measured

I rebuilt my situation as the smallest thing that still reproduces it — no external services, so anyone can get the same numbers.

  • Corpus: 30 runbook fragments. Twelve of them describe platform-side concerns (deployment, quota, IAM, billing). Ten of those use the legacy name, two use the new one.
  • Retriever: BM25 (k1=1.5, b=0.75). Japanese text tokenized as 2-grams, ASCII as whole words.
  • Queries: three families of five.
    • Topical — "how do I handle a quota overage" — the query carries signal beyond the product name.
    • Name-only — "what is X", "X settings" — the name is the only handle.
    • Unrelated — cache TTL, AdMob — a control group.

Three responses, compared head to head:

ConditionActionReindex needed?
A: do nothingLeave the legacy name in placeNo
B: bulk rewriteReplace the old name inside every chunk, reindexYes
C: query-side expansionLeave the index alone, expand queries in both directionsNo

B looks obviously right. It brings your data in line with reality. That was my assumption going in.

The Benchmark Code

No dependencies. Swap in your own corpus and you can run exactly this.

# -*- coding: utf-8 -*-
"""Measuring how a product rename affects lexical retrieval. No external deps."""
import math, re
from collections import Counter
 
OLD = "vertex ai"
NEW = "gemini enterprise agent platform"
 
def tok(s: str):
    """2-grams for CJK, whole words for ASCII. Keeps the BM25 vocabulary consistent."""
    s = s.lower()
    s = re.sub(r"[、。()()「」・,.]", " ", s)
    parts = []
    for w in s.split():
        if re.fullmatch(r"[a-z0-9_\-\.]+", w):
            parts.append(w)               # ASCII stays a single token
        else:
            for i in range(len(w) - 1):
                parts.append(w[i:i + 2])  # CJK becomes 2-grams
            if len(w) == 1:
                parts.append(w)           # don't drop single-character tokens
    return parts
 
class BM25:
    def __init__(self, docs, k1=1.5, b=0.75):
        self.ids = [d[0] for d in docs]
        self.toks = [tok(d[1]) for d in docs]
        self.k1, self.b = k1, b
        self.N = len(docs)
        self.avgdl = sum(len(t) for t in self.toks) / self.N
        self.df = Counter()
        for t in self.toks:
            self.df.update(set(t))        # document frequency counts sets, not totals
        self.tf = [Counter(t) for t in self.toks]
 
    def search(self, q: str, topk=5):
        qt = tok(q)
        scores = []
        for i in range(self.N):
            s, dl = 0.0, len(self.toks[i])
            for w in qt:
                f = self.tf[i].get(w, 0)
                if not f:
                    continue
                idf = math.log(1 + (self.N - self.df[w] + 0.5) / (self.df[w] + 0.5))
                s += idf * (f * (self.k1 + 1)) / (
                    f + self.k1 * (1 - self.b + self.b * dl / self.avgdl))
            scores.append((s, self.ids[i]))
        # Without a deterministic tiebreak your measurements drift between runs
        scores.sort(key=lambda x: (-x[0], x[1]))
        return [i for s, i in scores[:topk] if s > 0]
 
def expand_bidirectional(q: str) -> str:
    """Condition C. Old to new AND new to old. One direction only saves half your users."""
    ql = q.lower()
    if OLD in ql:
        return q + " " + NEW
    if NEW in ql:
        return q + " " + OLD
    return q
 
def precision_at_k(idx: BM25, queries, gold: set, k=5, expand=None):
    total = 0.0
    for q in queries:
        got = idx.search(expand(q) if expand else q, k)
        if not got:
            continue
        total += sum(1 for d in got if d in gold) / k
    return round(total / len(queries), 3)

I wrote expand_bidirectional one-way first — legacy queries rewritten toward the new name. That version dropped every reader who had already adopted the new terminology. Expansion has to run both ways or it is not worth shipping.

✦

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
✦A reproducible BM25 benchmark of retrieval quality immediately after a vendor product rename
✦Why bulk-rewriting your chunks is a net loss (P@5 drops from 0.92 to 0.08 for legacy-name queries)
✦The layer that actually breaks is exact-match routing and aggregation, plus where to put the alias resolver instead
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

⬡ Advanced2026-09-14
When BLOCK_NONE Changes Nothing: Telling Adjustable Gemini Blocks from the Ones You Can't Move
Some safety blocks go away when you loosen a threshold. Others never will. Here is how to read the response and decide which kind you are looking at before you touch a single setting.
⬡ Advanced2026-08-06
The Day the Knowledge Cutoff Moved Forward, the Stale Part Was My System Instruction
When a model's knowledge cutoff advances, the thing that goes stale is not the model — it is the dated assertions in your system instruction. Here is why only the lines written between the two cutoffs flip from helpful to contradictory, plus a working audit script and its measured results.
⬡ Advanced2026-05-01
Vertex AI Agent Engine × Gemini 2.5 Pro — Production Deployment for Managed Agents
Deploy ADK-based agents powered by Gemini 2.5 Pro on Vertex AI Agent Engine. Covers the trade-offs vs Cloud Run, sessions, tool calls, tracing, and a realistic cost model.