2026年5月28日 Gemini Embedding 2 でマルチモーダル検索を試す Gemini Google Cloud 生成AI(Generative AI) 検索する Popular tags 事例紹介 GEN-STEP 生成AI(Generative AI) Vertex AI Search Looker Studio BigQuery AlloyDB Google Workspace Cloud SQL Category Google Cloud Author tom SHARE 目次 Gemini Embedding 2 とは マルチモーダル検索アプリを構築する マルチモーダル検索を試す まとめ Content 本記事では、2026 年 4 月 22 日 に GA となった Google 初のネイティブマルチモーダルエンベディングモデル Gemini Embedding 2 (gemini-embedding-2) について解説します。 「テンションの上がる曲を聴きたい」「動画に合う BGM を探したい」など、ユーザーの直感的なニーズに対して、エンベディングを使用したアプローチはこれまでも試みられてきました。しかし、今までのエンベディングモデルは、テキスト・画像・動画には対応しているものの、音声には対応していないといったように、真にシームレスなマルチモーダル検索を実現するにはハードルがありました。 このようなハードルを突破するのが、Gemini Embedding 2 です。今回は、Streamlit でアプリを作成し、Gemini Embedding 2 によるマルチモーダル検索を試してみます。 Gemini Embedding 2 とは Gemini Embedding 2 とは、テキスト・画像・動画・音声・PDF ドキュメントの 5 つのモダリティを、ひとつの共通したベクトル空間にマッピングできる、Google 初のネイティブマルチモーダルエンベディングモデル です。 Google はこれまでテキスト専用モデルや、テキスト・画像・動画を同一のベクトル空間で扱えるマルチモーダルエンベディングモデルなど、用途に応じたさまざまなエンベディングモデルを提供してきました。 こうした複数のモデルを統合・発展させたものが Gemini Embedding 2 です。2026 年 3 月 10 日にパブリックプレビュー版のリリースを経て、2026 年 4 月 22 日より GA (一般提供) が開始されています。 Gemini のアーキテクチャを基盤とする本モデルは、以下のような特徴を備えています。 5 つのモダリティを統合: テキスト・画像・動画に加え、新たに音声、PDF ドキュメントにも対応。これらをひとつの共通したベクトル空間にネイティブにマッピングします。 広範な入力サイズ: 1 回の呼び出しで最大 8,192 個のテキストトークン、6 枚の画像、120 秒 (音声ありの場合 80 秒) の動画、180 秒の音声、6 ページの PDF ファイルなど、広範な入力に対応します。 インターリーブ入力のサポート: 複数のモダリティ (画像とテキストなど) を 1 つのリクエストとして渡すことが可能になり、より複雑なデータの関係性を正確に捉えられます。 表現力と対応言語の向上: 出力される次元数が 3,072 次元へと大幅にスケールアップし、100 を超える言語のセマンティックな意図を解釈します。 マルチモーダル検索アプリを構築する Google AI Studio で公開されているデモ Multimodal Search with Gemini Embedding 2 – Try in Google AI Studio を参考に、Gemini Embedding 2 の動作を理解するため、Streamlit でアプリを作成し、マルチモーダル検索を試してみます。 構成は次のようになります。素材のエンベディングデータは pickle ファイルに保存します。なお、今回はデータが少ないので NumPy を使用して総当たり検索を行います。 また、Nano Banana や Lyria で生成した画像や音声を素材として使用します。 テキスト: 「友達に会う。」 「バナナを食べる。」 「今週末も笑えないジョークに付き合わされるなんて、最高の拷問だ。」 「誰もいないはずの 2 階から、ゆっくりと床板が軋む音が聞こえる。」 画像: バナナの画像 オレンジの画像 チョコレートバナナの画像 暖炉とロッキングチェアが置かれた部屋の画像 子どもが裏路地にいる画像 音声: スキャットの軽快な歌声 安らぎを感じさせるゆったりとしたサウンド 緊張感のあるサスペンスなサウンド 初期化と依存関係のインストール: プロジェクトのディレクトリでコマンドを実行し、初期化と依存関係のインストールを行います。 uv init uv add streamlit numpy google-genai pillow 認証: ADC で認証を行います。ADC については、アプリケーションのデフォルト認証情報を設定する を参考にしてください。 gcloud auth application-default login アプリケーションの実装: アプリのソースコード app.py を作成します。YOUR_PROJECT_ID はプロジェクト ID に置き換えてください。 import os import pickle import uuid import numpy as np import streamlit as st from google import genai from google.genai import types from PIL import Image # ===================================================================== # 初期設定・カスタムCSS・共通関数 # ===================================================================== st.set_page_config( page_title="マルチモーダル検索", layout="wide", initial_sidebar_state="collapsed" ) DB_FILE = "local_vector_db.pkl" st.markdown( """ """, unsafe_allow_html=True, ) @st.cache_resource def get_client(): return genai.Client( vertexai=True, project="YOUR_PROJECT_ID", location="us", ) def load_db(): return pickle.load(open(DB_FILE, "rb")) if os.path.exists(DB_FILE) else [] def save_db(db_data): pickle.dump(db_data, open(DB_FILE, "wb")) def cosine_similarity(v1, v2): return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) if "db" not in st.session_state: st.session_state.db = load_db() client = get_client() def add_to_db(item_type, content_label, api_content, **kwargs): with st.spinner("処理中..."): res = client.models.embed_content( model="gemini-embedding-2", contents=api_content, ) st.session_state.db.append( { "id": str(uuid.uuid4()), "type": item_type, "content": content_label, "vector": res.embeddings[0].values, **kwargs, } ) save_db(st.session_state.db) st.success("処理完了") st.rerun() # ===================================================================== # データ追加ダイアログ # ===================================================================== @st.dialog("データを追加") def data_management_dialog(): reg_type = st.selectbox("追加するデータの種類", ["テキスト", "画像", "音声"]) if reg_type == "テキスト": val = st.text_area("テキスト:") elif reg_type == "画像": val = st.file_uploader("画像:", type=["jpg", "jpeg", "png"]) elif reg_type == "音声": val = st.file_uploader("音声:", type=["wav", "mp3", "m4a"]) if st.button("追加", type="primary", width="stretch") and val: if reg_type == "テキスト": add_to_db("text", val, val) elif reg_type == "画像": img = Image.open(val) add_to_db("image", val.name, img, image=img) elif reg_type == "音声": audio_bytes = val.read() add_to_db( "audio", val.name, types.Part.from_bytes(data=audio_bytes, mime_type=val.type), audio_bytes=audio_bytes, mime_type=val.type, ) st.divider() if st.button( "すべて削除", type="secondary", icon=":material/delete:", width="stretch", ): st.session_state.db.clear() save_db([]) st.rerun() # ===================================================================== # メイン UI (ヘッダー・検索バー) # ===================================================================== head_left, head_right = st.columns([5, 1]) with head_left: st.subheader("マルチモーダル検索") st.caption("Gemini Embedding 2 検証用アプリ") with head_right: st.write("") st.write("") if st.button("追加", icon=":material/add:", width="stretch"): data_management_dialog() st.write("") with st.container(border=True): query_text = st.text_input( "テキスト入力", placeholder="テキストを入力", label_visibility="collapsed", ) query_file = st.file_uploader( "メディア添付", type=["jpg", "png", "jpeg", "wav", "mp3"], label_visibility="collapsed", ) c_btn1, _ = st.columns([1, 5]) with c_btn1: search_clicked = st.button( "検索", icon=":material/search:", type="primary", width="stretch", ) st.write("") # ===================================================================== # 検索処理 # ===================================================================== display_data = [{"item": item, "match": None} for item in st.session_state.db] if search_clicked: if not st.session_state.db: st.error("データを追加してください。") elif not query_text and not query_file: st.error("検索条件を入力してください。") else: with st.spinner("検索中..."): contents = [] if query_text: contents.append(query_text) if query_file: contents.append( Image.open(query_file) if query_file.type.startswith("image/") else types.Part.from_bytes( data=query_file.read(), mime_type=query_file.type, ) ) res = client.models.embed_content( model="gemini-embedding-2", contents=contents, ) q_vec = res.embeddings[0].values for d in display_data: raw_sim = cosine_similarity(q_vec, d["item"]["vector"]) d["match"] = max(0.0, raw_sim) * 100 display_data.sort(key=lambda x: x["match"], reverse=True) # ===================================================================== # 結果描画ロジック (カードUI) # ===================================================================== def render_result_card(r): item = r["item"] match_str = f"{r['match']:.2f}% " if r["match"] is not None else "- %" with st.container(border=True): c_match, c_del = st.columns([6, 1]) with c_match: st.markdown( f"類似度: {match_str}", unsafe_allow_html=True, ) with c_del: if st.button( "", key=f"del_{item['id']}", icon=":material/delete:", type="tertiary", ): st.session_state.db = [ x for x in st.session_state.db if x["id"] != item["id"] ] save_db(st.session_state.db) st.rerun() if item["type"] == "text": st.write(item["content"]) elif item["type"] == "image": st.image(item["image"], width="stretch") st.write(item["content"]) elif item["type"] == "audio": st.write(f"**{item['content']}**") st.audio(item["audio_bytes"], format=item["mime_type"]) columns = st.columns(3) column_configs = [ ("text", "description", "テキスト"), ("image", "image", "画像"), ("audio", "music_note", "音声"), ] for col, (m_type, icon, title) in zip(columns, column_configs): with col: st.markdown(f"**:material/{icon}: {title}**") for r in display_data: if r["item"]["type"] == m_type: render_result_card(r) 注目すべきは、embed_content メソッドを使用してエンベディングを生成している箇所です。model には gemini-embedding-2 を指定します。 res = client.models.embed_content( model="gemini-embedding-2", contents=contents, ) q_vec = res.embeddings[0].values また、エンベディングを生成する際、タスクの指示を明記するとパフォーマンスが向上します。タスクの指示については、タスクの指示を指定してパフォーマンスを改善する を参考にしてください。 add_to_db("text", val, val) # タスクの指示なし add_to_db("text", val, f"title: none | text: {val}") # タスクの指示あり アプリケーションの実行: コマンドを実行し、アプリを実行します。 uv run streamlit run app.py マルチモーダル検索を試す アプリを構築したので、マルチモーダル検索を試してみます。アプリを構築していない方は、Google AI Studio で公開されているデモ Multimodal Search with Gemini Embedding 2 – Try in Google AI Studio で同じような内容を試すことができます。 「怖い」で検索する シンプルなテキストクエリを入力します。 検索結果として類似度が高かったものは、「誰もいないはずの 2 階から、ゆっくりと床板が軋む音が聞こえる。」というテキストや緊張感のあるサスペンスなサウンド、子どもが裏路地にいる画像でした。 メタ情報を付与していないにもかかわらず、多くの人が怖さを感じるコンテンツに高い類似度を出していることに驚きます。モデルが「怖い」というニュアンスを理解していることがうかがえます。 バナナの画像で検索する 次に、画像での検索を試してみます。検索に使用する画像は、素材に使用しているバナナの画像です。 同じ画像を使用したのでバナナの画像との類似度は 100% でした。他にも「バナナを食べる。」というテキストが高い類似度を出しており、音声など関連性がないものは、類似度がほぼ同等の結果となりました。 画像では、バナナの画像に続き、オレンジの画像、チョコレートバナナの画像という順になりました。チョコレートバナナの画像が 2 番目になると予想していたため、とても興味深い結果でした。 バナナの画像 +「バナナ」で検索する Gemini Embedding 2 の特徴のひとつであるインターリーブ入力を試してみます。バナナの画像と、テキスト「バナナ」を組み合わせて再度検索を行います。 今度は、バナナの画像に続き、チョコレートバナナの画像が 2 番目になりました。テキスト「バナナ」を加えたことでクエリの意味が補強され、バナナとの関連性がより強調された結果になったと推測できます。 他にも、「皮肉」というクエリで「今週末も笑えないジョークに付き合わされるなんて、最高の拷問だ。」というテキストが高い類似度を出したり、「雨」というクエリで子どもが裏路地にいる画像の類似度が高かったりという結果が得られました。 まとめ 本記事では、Gemini Embedding 2 について解説しました。 Gemini Embedding 2 は、テキスト・画像・動画・音声・PDF ドキュメントを共通したベクトル空間にネイティブにマッピングします。これにより、よりシームレスなマルチモーダル検索が実現するだけでなく、複数のモデルを単一モデルに統合できるため、システム構成をシンプルに保てるという開発者にとってのメリットもあります。 サービスでの直感的なコンテンツ検索や社内コンテンツの横断検索など、活用シーンは幅広く考えられます。ぜひさまざまなクエリを入力し、Gemini Embedding 2 のマルチモーダル検索を体感してみてください。 参考資料 Multimodal Search with Gemini Embedding 2 – Try in Google AI Studio Gemini Embedding 2 — Google DeepMind Gemini Embedding 2: Our first natively multimodal embedding model Gemini エンベディング 2 | Gemini Enterprise Agent Platform | Google Cloud Documentation エンベディング | Gemini API | Google AI for Developers Multimodal Embeddings API | Generative AI on Vertex AI | Google Cloud Documentation システムサポートでは、Google Cloud の最新かつ高度なソリューションをお客さまに提供し続けることで、お客さまの DX 推進を強力にサポートしてまいります。AI Agent、データアナリティクス/データ分析基盤、クラウドマイグレーション/モダナイゼーションなど、広範囲でご支援が可能です。ぜひ、以下のボタンからお問い合わせください。 お問い合わせはこちら 関連コンテンツ Google のノーコード AI ミニアプリケーション構築ツール Opal を試す by tomon 2025年10月29日 頂きましたご意見につきましては、今後のより良い商品開発・サービス改善に活かしていきたいと考えております。 よく分かった よく分からない もっと知りたい Author tom 株式会社システムサポート 大阪支社所属のエンジニアです。2023 年 9 月から Google Cloud に携わっています。 Gemini Google Cloud 生成AI(Generative AI) 2026年5月28日 Gemini Embedding 2 でマルチモーダル検索を試す Category Google Cloud 前の記事を読む 【MCP】Google Workspace MCP サーバーを色々触ってみた(Workspaceアカウント不要!!) Recommendation オススメ記事 2023年9月5日 Google Cloud 【Google Cloud】Looker Studio × Looker Studio Pro × Looker を徹底比較!機能・選び方を解説 2023年8月24日 Google Cloud 【Google Cloud】Migrate for Anthos and GKEでVMを移行してみた(1:概要編) 2022年10月10日 Google Cloud 【Google Cloud】AlloyDB と Cloud SQL を徹底比較してみた!!(第1回:AlloyDB の概要、性能検証編) BigQuery ML ワークショップ開催のお知らせ 生成AI導入支援パッケージ Discovery AI導入支援パッケージ Google Cloud ホワイトペーパー 新着記事 2026年5月28日 Google Cloud Gemini Embedding 2 でマルチモーダル検索を試す 2026年5月28日 Google Cloud 【MCP】Google Workspace MCP サーバーを色々触ってみた(Workspaceアカウント不要!!) 2026年5月26日 Google Cloud AlloyDBのAI関数でSQLだけで感情分析・要約をしてみた! HOME Google Cloud Gemini Embedding 2 でマルチモーダル検索を試す