◉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-08上級

複数アプリのFAQを1つの File Search ストアに同居させる — customMetadata と chunk 設定で検索を分ける

複数アプリのFAQを1つの File Search ストアにまとめると、metadataFilter が無言で空を返したり、回答がチャンク境界で割れて引用されなかったりします。customMetadata の設計、AIP-160 フィルタ構文の落とし穴、chunkingConfig の実測チューニングを実装ベースでまとめました。

Gemini API248File Search7RAG15customMetadata個人開発121

✦ プレミアム記事

複数のアプリのヘルプFAQを Gemini の File Search に載せようとしたとき、私は最初、アプリごとにストアを分けました。壁紙アプリ、癒し系アプリ、それぞれ別のストア。素直な発想です。

ところが運用に入ると、ストアの数だけ再インデックスのジョブとコストが増えていきました。FAQを1行直すたびに、どのストアだったかを思い出す作業も地味に効いてきます。

そこで「1つのストアに全アプリのFAQを同居させ、クエリのときだけアプリで絞る」構成に切り替えました。File Search には customMetadata と metadataFilter があります。ドキュメントに app_id を付けておき、問い合わせのときに app_id で絞れば、1ストアでも回答は混ざらないはずでした。

はずでした、と書いたのは、metadataFilter が例外も警告も出さないまま、空の回答を返し続けたからです。この記事は、その原因の切り分けと、ついでに見つかった「回答がチャンク境界で割れて引用されない」問題の実測チューニングまでを、実装ベースでまとめたものです。

なぜ1ストアに寄せるのか — 個人開発での判断

ストアを分けるか、1つに寄せるか。個人開発だと、この判断は「正しさ」より「運用が続けられるか」で決まります。

File Search のストアは、埋め込みを永続保持するコンテナです。生ファイルは48時間で消えますが、ストアに取り込んだ埋め込みは手動削除するまで残ります。つまりストアは「増やしたら増えたぶんだけ、削除と再取り込みの管理対象が増える」オブジェクトです。

公式ドキュメントには、ストアのサイズは「入力データ+生成された埋め込み」でおおよそ入力の約3倍になり、1ストアあたり20GB未満を推奨、と書かれています。個人開発のFAQ程度ならサイズは問題になりません。問題になるのは数のほうです。

私の判断はこうでした。データ量ではなく、更新頻度と分離要件で分ける。FAQのように頻繁に直し、アプリ間で厳密に混ざってはいけないものは、1ストアに同居させて app_id で論理分離します。逆に、埋め込みモデルを変えたい・再インデックス戦略が違う塊は、物理的にストアを分けます。この「物理分離は最小限、論理分離はメタデータで」という線引きが、私には一番続けやすいものでした。

ストアの陳腐化そのものは別の論点で、File Search のストアが本番で静かに陳腐化する運用メモにドリフト検知の設計を書いています。本記事は「1ストア同居」に絞ります。

customMetadata でアプリを区別する

分離の起点は、取り込み時に付ける customMetadata です。キーと値のペアで、1ドキュメントあたり最大20件まで付けられます。

from google import genai
import time
 
client = genai.Client()
 
# マルチモーダル対応の埋め込みモデルでストアを作成(画像も同居させたいため)
store = client.file_search_stores.create(
    config={
        "display_name": "app-faqs-shared",
        "embedding_model": "models/gemini-embedding-2",
    }
)
 
def import_faq(path: str, app_id: str, kind: str, lang: str):
    # まず Files API にアップロード → ストアへ import
    src = client.files.upload(file=path, config={"name": f"faq-{app_id}"})
    op = client.file_search_stores.import_file(
        file_search_store_name=store.name,
        file_name=src.name,
        # ここが分離の鍵。app_id / kind / lang を付けておく
        custom_metadata=[
            {"key": "app_id", "string_value": app_id},
            {"key": "kind", "string_value": kind},
            {"key": "lang", "string_value": lang},
        ],
    )
    while not op.done:
        time.sleep(5)
        op = client.operations.get(op)
    return op
 
import_faq("faq_wallpaper_ja.md", app_id="wallpaper", kind="faq", lang="ja")
import_faq("faq_healing_ja.md",   app_id="healing",   kind="faq", lang="ja")
# 期待: 2ドキュメントが同一ストアに入り、各チャンクに app_id が紐づく

キー設計で一点だけ、後悔しないための注意があります。値の型を最初に決めておくことです。app_id を文字列にするか数値にするかで、後述の metadataFilter の書き方が変わります。私は識別子は常に string_value、しきい値で絞りたい年や版番号だけ numeric_value にする、と決めました。混在させると、フィルタ側で型を思い出せなくなります。

✦

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

この記事の続きを読む

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

この記事で得られること
✦アプリごとに File Search ストアを増やして管理が膨らんでいた人が、1ストア同居+メタデータ分離の設計に切り替えられる
✦metadataFilter が例外を出さずに空の grounding を返す原因を、AIP-160 構文の切り分け手順で自力で特定できるようになる
✦FAQ の回答がチャンク境界で割れて引用されない問題を、max_tokens_per_chunk と overlap の実測調整で減らせる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

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

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

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

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

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

関連記事

⬡ 高度な活用2026-08-31
画像の重複検査に埋め込み検索を足す前に、重複の定義を三つに分ける
同じ構図で色だけ違う二枚を、検査は重複と判定しました。知覚ハッシュと File Search の埋め込み検索の守備範囲を距離の実数で切り分け、何を重複と呼ぶかの定義から検査の構成を組み直した判断の記録です。
⬡ 高度な活用2026-09-05
長い動画を Gemini に辿らせるとき、見つける問いと「無い」を確かめる問いは別々に投げています
9月1日に来たエージェント的動画理解では、どこを観るかをモデル自身が決めます。見つける問いには効きますが、映り込みが無いことの確認には被覆の保証がありません。問いの形で処理モードを分ける判断と、被覆を自分で担保する実装を書き残します。
⬡ 高度な活用2026-08-09
記憶が消えたのではなく、別のプロファイルに書かれていました — Memory profiles のスコープキーを実測で正す
Memory Bank のプロファイルはスキーマとスコープの組で一意になります。呼び出し側でスコープの形がわずかにぶれると、エラーを出さないまま別のプロファイルが増えていきます。分裂の量と、3種類の対処の効き目を同じ条件で測った記録です。