◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/高度な活用
⬡ 高度な活用/2026-07-17上級

日本語で引いた検索に、対訳の英語記事が出てこない — 埋め込みが内容より先に言語を見ている件

gemini-embedding-2 で日英の対訳ペアを埋め込むと、同じ内容なのに最近傍になりません。言語そのものが類似度を押し上げているためです。対訳ペアを正解として再現率を測り、言語重心を引く方法と翻訳ブリッジを比べた記録をまとめます。

Gemini API248gemini-embedding-27多言語6ベクトル検索3評価設計

✦ プレミアム記事

4つのサイトで日本語と英語の記事を必ずペアで公開しています。片方だけ存在すると言語切替で 404 になるため、日英は常に同数です。手元の1サイトでいま JA 725 本・EN 725 本。つまり「意味が同じで言語だけが違う文書」が 725 組、正解つきで揃っている状態です。

この対を使って、公開前の重複検知を作ろうとしました。新しく書いた日本語の下書きを埋め込み、既存記事の中から近いものを引く。日英どちらの既存記事も同じインデックスに入れておけば、言語をまたいだ重複も拾えるはずでした。

引いてみると、上位10件が全部日本語記事でした。私自身、最初はインデックスの作り方を間違えたのだと思いました。しかも、その日本語の下書きには必ず対応する英語版が存在しているにもかかわらず、その対訳は上位に出てきません。内容が完全に一致する相手が、内容の遠い同言語の記事に負けています。

task_type は揃えていました。正規化もしていました。原因はもっと手前にありました。

コサイン類似度は「何語で書かれているか」も測っている

埋め込みモデルは、渡した文をベクトルにします。そのベクトルには意味だけが入っていてほしいのですが、実際には書かれた言語という属性も一緒に載ります。

多言語モデルは、確かに言語をまたいで意味を近づけるように学習されています。ただ「まったく同じ向きに揃える」ようには学習されていません。結果として、埋め込み空間の中で日本語の文はゆるやかに一箇所に集まり、英語の文は別の一箇所に集まります。

比較対象意味の近さ言語の一致実際の類似度
日本語の下書き ↔ その英語対訳ほぼ同一不一致中
日本語の下書き ↔ 別テーマの日本語記事遠い一致中〜高

言語の一致が稼ぐ下駄が、意味の差を埋めてしまう。上位10件が日本語で占められていたのは、モデルが間違えたからではありませんでした。私が「意味だけを測っているつもりで、言語も一緒に測っていた」だけです。

この成分をどう扱うかは用途で変わります。同一言語内の検索しかしないなら、言語成分は全ベクトルに等しく載るので順位に影響しません。困るのは、日本語と英語を同じインデックスに混ぜて引く瞬間だけです。私はそこを踏みました。

対訳ペアは、そのまま評価データセットになる

先に測り方を用意します。対訳ペアの良いところは、正解のラベル付けが要らないことです。gemini-3-multitool-agent-guide.mdx の日本語版から引いたとき、正解は同じ slug の英語版だと最初から決まっています。

100 組ほどあれば傾向は見えます。次のコードは、日英ペアを埋め込んで JA→EN の再現率と MRR を出す最小の計測台です。

import os, json, math, random
from google import genai
from google.genai import types
 
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
MODEL = "gemini-embedding-2"
 
def embed(texts, task_type):
    """テキスト群を埋め込む。API 側の上限に合わせて分割する。"""
    out = []
    for i in range(0, len(texts), 32):
        chunk = texts[i:i + 32]
        res = client.models.embed_content(
            model=MODEL,
            contents=chunk,
            config=types.EmbedContentConfig(task_type=task_type),
        )
        out.extend([e.values for e in res.embeddings])
    return out
 
def l2_normalize(v):
    n = math.sqrt(sum(x * x for x in v))
    return [x / n for x in v] if n else v
 
def cosine(a, b):
    return sum(x * y for x, y in zip(a, b))
 
# pairs: [{"slug": "...", "ja": "日本語本文の冒頭2000字", "en": "English body ..."}, ...]
pairs = json.load(open("pairs.json"))
random.seed(42)
pairs = random.sample(pairs, min(100, len(pairs)))
 
ja_vecs = [l2_normalize(v) for v in embed([p["ja"] for p in pairs], "RETRIEVAL_QUERY")]
en_vecs = [l2_normalize(v) for v in embed([p["en"] for p in pairs], "RETRIEVAL_DOCUMENT")]
 
def evaluate(queries, docs):
    """queries[i] の正解は docs[i]。順位を集計する。"""
    hits = {1: 0, 5: 0, 10: 0}
    rr_sum = 0.0
    for i, q in enumerate(queries):
        scored = sorted(
            ((cosine(q, d), j) for j, d in enumerate(docs)),
            reverse=True,
        )
        rank = next(r for r, (_, j) in enumerate(scored, start=1) if j == i)
        for k in hits:
            if rank <= k:
                hits[k] += 1
        rr_sum += 1.0 / rank
    n = len(queries)
    return {
        "recall@1": hits[1] / n,
        "recall@5": hits[5] / n,
        "recall@10": hits[10] / n,
        "MRR": rr_sum / n,
    }
 
print("baseline:", evaluate(ja_vecs, en_vecs))

この時点では、母集団に英語文書しか入っていません。言語の下駄は全候補に等しくかかるので、ここでの再現率は素直に出ます。私の手元では recall@1 が 0.9 前後、つまり 90% ほどの下書きで対訳が1位に来ていました。

問題は次です。候補に日本語記事も混ぜます。

# 日本語記事も同じインデックスに入れる(自分自身は候補から除く)
ja_docs = [l2_normalize(v) for v in embed([p["ja"] for p in pairs], "RETRIEVAL_DOCUMENT")]
 
def evaluate_mixed(queries, en_docs, ja_docs):
    hits = {1: 0, 5: 0, 10: 0}
    for i, q in enumerate(queries):
        cands = [(cosine(q, d), ("en", j)) for j, d in enumerate(en_docs)]
        cands += [(cosine(q, d), ("ja", j)) for j, d in enumerate(ja_docs) if j != i]
        cands.sort(reverse=True)
        rank = next(r for r, (_, key) in enumerate(cands, start=1) if key == ("en", i))
        for k in hits:
            if rank <= k:
                hits[k] += 1
    n = len(queries)
    return {f"recall@{k}": v / n for k, v in hits.items()}
 
print("mixed:", evaluate_mixed(ja_vecs, en_vecs, ja_docs))

日本語候補を混ぜた途端に recall@1 が崩れました。混ぜる前と後の差が、そのまま言語成分の大きさです。単一言語のベンチマークで問題なく見えていたインデックスが、多言語にした瞬間に別物になる。この落差を数字にできたことが、この計測台の一番の収穫でした。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦対訳ペアという「正解が既知の集合」を使って、自分のインデックスの言語横断の再現率を今日測れる
✦言語重心を引くだけで追加のAPI呼び出しゼロのまま言語横断の順位を立て直す実装が手に入る
✦重心除去・翻訳ブリッジ・言語別インデックスの三択を、遅延とコストの軸で選び分けられる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ 高度な活用2026-09-24
Gemini に「合っていますか」と聞くのをやめ、答えを伏せたまま分類し直してもらう設計に変えました
自分で付けたラベルの確認を Gemini に頼むと、頷く答えが返りがちです。確認型・反論指示型・伏せ型の三つを比べて伏せ型を選んだ理由と、答えが漏れる経路の塞ぎ方、食い違いだけを人が見る振り分けのコードまで書き残します。
⬡ 高度な活用2026-09-14
BLOCK_NONE を入れても結果が変わらないとき — Gemini のブロックを閾値で動かせるかどうかの見分け方
安全フィルタで止まったとき、閾値を緩めて直る場合と、何をしても直らない場合があります。返ってきたレスポンスのどこを見て、その境目を先に判定するかをまとめました。
⬡ 高度な活用2026-09-05
長い動画を Gemini に辿らせるとき、見つける問いと「無い」を確かめる問いは別々に投げています
9月1日に来たエージェント的動画理解では、どこを観るかをモデル自身が決めます。見つける問いには効きますが、映り込みが無いことの確認には被覆の保証がありません。問いの形で処理モードを分ける判断と、被覆を自分で担保する実装を書き残します。