🦔

エージェントの検索精度を向上させる Amazon Nova Multimodal Embeddings - embeddingPurpose

に公開

こんにちは。AWS Japan の AI/ML Specliaist Solutions Architect をしている佐藤です。

本ブログは AWS AI Agent ブログ祭り(Zenn: #awsaiagentblogfes, X: #AWS_AI_AGENT_ブログ祭り)の第 18 日目です。よろしくお願いします。

はじめに

さて、昨今色々なエージェントが作られていると思うのですが、その大半は情報検索やRAGに関するものも多いのではないでしょうか。自律型AIエージェントが複雑なタスクを完遂できるかどうかは、エージェントがいかに正確に外部知識や適切なツールを探し出せるか(Retrieval)にかかっています。今回は、そんな情報検索・RAGシステムに欠かせない埋め込みモデルに着目し、特に10/28に登場したAmazon Nova Multimodal Embeddings について紹介をしたいと思います。また、検索・RAG以外のNova Multimodal Embeddingsの活用方法についても簡単に触れたいと思います。

Amazon Nova Multimodal Embeddings の概要

概要

Amazon Nova Multimodal Embeddings は、先月(2025年10月)に利用可能になった最新の埋め込みモデルです。現在、米国東部(バージニア北部、US-EAST-1)リージョンでのみ利用可能です。テキスト、画像、動画、音声、ドキュメントといった5つのモダリティにまたがるデータ群を統一的なベクトル空間にマッピングでき、マルチモーダルなデータを扱うことができます。また、最大8kトークンのテキスト入力に対応しており、長いドキュメントの文脈も埋め込むことが可能です。

主な特徴

マルチモーダル対応

  • テキスト、画像、動画、音声を同一のベクトル空間で扱うことができる
  • クロスモーダル検索が可能(例: テキストで画像を検索、画像でテキストを検索)
  • モダリティ間の意味的な関連性を捉える
  • 最大8Kのコンテキスト長をサポート

動画・音声は最大30秒までになります。

柔軟な埋め込み次元

Nova Multimodal Embeddings :4つの次元オプション:

  • 3,072次元: 最高精度が必要な用途
  • 1,024次元: 精度とコストのバランス型(推奨)
  • 384次元: 軽量・高速処理が必要な場合
  • 256次元: 最も軽量、大規模データセット向け

一つ注意が必要なのが、一度大きな次元数で埋め込みベクトルを生成すれば、より小さな次元の埋め込みベクトルは、その最初のN個の値を取るだけで得られる点です。すなわち、高速なレスポンスを狙って後で次元を小さくしたい場合でも、時間のかかるembeddingの計算を再度行う必要はなく、大きな次元の埋め込みベクトル最初の一部を持ってくるだけでOKになります。

用途別の最適化 (embeddingPurpose)

9種類の embeddingPurpose により、タスクに応じた最適な埋め込みを生成します。モダリティの種類に応じてさまざまなembeddingモードが用意されています。

  • 検索・RAG用途
  • 分類タスク
  • クラスタリング

embeddingPurpose

embeddingPurpose パラメータの全容

こちらが、Nova Multimodal Embeddings の特徴である embeddingPurpose の詳細です。Titan embedding v2など従来の埋め込みモデルでは1種類の埋め込みしか生成できませんでしたが、Nova Embedding は9種類の用途別のembeddingを提供しています。このembeddingPurposeは、大まかに ①検索・RAG用途向け と ②その他のタスク向けの2つの用途に分けられます。以下で詳細を紹介します。

① 検索・RAG用途向け embeddingPurpose

まず、検索・RAG用途向けのembeddingPurposeの一覧です。モダリティに応じて、7種類の埋め込みモードが用意されています。

embeddingPurpose 用途 最適なシーン 使用例
GENERIC_INDEX インデックス作成 モダリティに関わらず全てのインデックス作成に使用 ベクトルDBへの登録時
GENERIC_RETRIEVAL 汎用検索クエリ タスクタイプが明確でない一般的な検索 一般的な製品検索
DOCUMENT_RETRIEVAL ドキュメント検索 長文テキスト、PDFドキュメントの検索 技術仕様書、論文検索
TEXT_RETRIEVAL テキスト検索 短文・中文テキストの検索 レビュー、コメント検索
IMAGE_RETRIEVAL 画像検索 画像コンテンツの検索 商品画像、写真検索
VIDEO_RETRIEVAL 動画検索 動画コンテンツの検索 動画ライブラリ検索
AUDIO_RETRIEVAL 音声検索 音声コンテンツの検索 ポッドキャスト検索

② その他のタスク向け embeddingPurpose

生成AI向けの用途が大半ですが、分類タスク、クラスタリング向けの埋め込みモードも用意されています。例えばテーブルデータをlightgbmなどのGBDTに学習させ、多クラス分類をするためのモデルを作るケースです。その際、文字列カラムから特徴量を作りたい場合に分類タスクむけの埋め込みモードであるCLASSIFICATIONが役に立ちます。エンベディングモデルで特徴量を作ると、文字列カラムから形態素解析+TF-IDFで特徴量を作る場合よりも、一般的にモデルの性能が上がりやすいとされています。

embeddingPurpose 用途 最適なシーン
CLASSIFICATION 分類タスク テキスト・画像の分類モデル構築
CLUSTERING クラスタリング データや類似アイテムのグループ化

検索・RAGにおける使い分けの実践例

シナリオ1: 技術ドキュメントRAGシステム

AWSの技術ドキュメントを検索するRAGシステムを構築する場合を考えてみましょう。

ステップ1: ドキュメントのインデックス作成

まず、技術ドキュメントをベクトルDBに登録する際は、GENERIC_INDEXを使用します。これにより、ドキュメントは汎用的な表現としてベクトル空間に配置されます。

import boto3
import json

bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")

# インデックス作成: 技術ドキュメントを登録
documents = [
    "Amazon Bedrock is a fully managed service that offers foundation models...",
    "Amazon SageMaker provides machine learning capabilities...",
    "Amazon S3 is an object storage service..."
]

indexed_embeddings = []
for doc in documents:
    request_body = {
        "taskType": "SINGLE_EMBEDDING",
        "singleEmbeddingParams": {
            "embeddingPurpose": "GENERIC_INDEX",  # インデックス作成時は常にGENERIC_INDEX
            "embeddingDimension": 1024,
            "text": {
                "truncationMode": "END",
                "value": doc
            }
        }
    }
    
    response = bedrock.invoke_model(
        body=json.dumps(request_body),
        modelId="amazon.nova-2-multimodal-embeddings-v1:0",
        accept="application/json",
        contentType="application/json"
    )
    
    embedding = json.loads(response["body"].read())["embeddings"][0]["embedding"]
    indexed_embeddings.append({"text": doc, "embedding": embedding})

# ベクトルDBに保存(例: OpenSearch, Pinecone, Chroma等)
# vector_db.upsert(indexed_embeddings)

ステップ2: ユーザークエリでの検索

ユーザーが質問する際は、タスクに応じた*_RETRIEVALを使用します。長文ドキュメントを検索する場合はDOCUMENT_RETRIEVAL、短文検索ならTEXT_RETRIEVALを選択します。

# 検索クエリ: ユーザーの質問
user_query = "Bedrockでファウンデーションモデルをどうやって使うの?"

# 検索用の埋め込み生成
query_request = {
    "taskType": "SINGLE_EMBEDDING",
    "singleEmbeddingParams": {
        "embeddingPurpose": "DOCUMENT_RETRIEVAL",  # ドキュメント検索に最適化
        "embeddingDimension": 1024,
        "text": {
            "truncationMode": "END",
            "value": user_query
        }
    }
}

response = bedrock.invoke_model(
    body=json.dumps(query_request),
    modelId="amazon.nova-2-multimodal-embeddings-v1:0",
    accept="application/json",
    contentType="application/json"
)

query_embedding = json.loads(response["body"].read())["embeddings"][0]["embedding"]

# ベクトルDBで類似検索
# results = vector_db.similarity_search(query_embedding, top_k=3)

シナリオ2: ECサイトのマルチモーダル商品検索

テキストで商品画像を検索するクロスモーダル検索システムの例です。

ステップ1: 商品画像のインデックス作成

商品画像を登録する際も、モダリティに関わらず**GENERIC_INDEXを使用**します。

import base64

# 商品画像をBase64エンコード
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

# 商品画像のインデックス作成
product_images = [
    "product_001.jpg",  # 赤いスニーカー
    "product_002.jpg",  # 黒いビジネスシューズ
    "product_003.jpg"   # 白いランニングシューズ
]

for image_path in product_images:
    image_base64 = encode_image(image_path)
    
    request_body = {
        "taskType": "SINGLE_EMBEDDING",
        "singleEmbeddingParams": {
            "embeddingPurpose": "GENERIC_INDEX",  # 画像でもGENERIC_INDEX
            "embeddingDimension": 1024,
            "image": {
                "format": "jpeg",
                "source": {
                    "bytes": image_base64
                }
            }
        }
    }
    
    response = bedrock.invoke_model(
        body=json.dumps(request_body),
        modelId="amazon.nova-2-multimodal-embeddings-v1:0",
        accept="application/json",
        contentType="application/json"
    )
    
    embedding = json.loads(response["body"].read())["embeddings"][0]["embedding"]
    # vector_db.upsert({"image_path": image_path, "embedding": embedding})

ステップ2: テキストで画像を検索(クロスモーダル検索)

ユーザーがテキストで商品を検索する際は、IMAGE_RETRIEVALを使用します。これにより、テキストクエリが画像検索に最適化された埋め込みに変換されます。

# テキストクエリで画像を検索
search_query = "赤いスニーカーを探しています"

query_request = {
    "taskType": "SINGLE_EMBEDDING",
    "singleEmbeddingParams": {
        "embeddingPurpose": "IMAGE_RETRIEVAL",  # 画像検索に最適化
        "embeddingDimension": 1024,
        "text": {
            "truncationMode": "END",
            "value": search_query
        }
    }
}

response = bedrock.invoke_model(
    body=json.dumps(query_request),
    modelId="amazon.nova-2-multimodal-embeddings-v1:0",
    accept="application/json",
    contentType="application/json"
)

query_embedding = json.loads(response["body"].read())["embeddings"][0]["embedding"]

# ベクトルDBで画像を検索
# matched_images = vector_db.similarity_search(query_embedding, top_k=5)
# → 赤いスニーカーの画像が上位にランクイン

シナリオ3: カスタマーレビュー検索システム

短文テキスト(レビュー)を検索するシステムの例です。

# インデックス作成: カスタマーレビューを登録
reviews = [
    "この商品は軽くて持ち運びに便利です",
    "バッテリーの持ちが素晴らしい",
    "画面が大きくて見やすい"
]

# すべてのレビューをGENERIC_INDEXで登録
for review in reviews:
    request_body = {
        "taskType": "SINGLE_EMBEDDING",
        "singleEmbeddingParams": {
            "embeddingPurpose": "GENERIC_INDEX",
            "embeddingDimension": 1024,
            "text": {"truncationMode": "END", "value": review}
        }
    }
    # ... (インデックス作成処理)

# 検索: 短文検索にはTEXT_RETRIEVALを使用
user_query = "軽量で携帯性に優れた製品"

query_request = {
    "taskType": "SINGLE_EMBEDDING",
    "singleEmbeddingParams": {
        "embeddingPurpose": "TEXT_RETRIEVAL",  # 短文検索に最適化
        "embeddingDimension": 1024,
        "text": {"truncationMode": "END", "value": user_query}
    }
}
# ... (検索処理)

検証ー① (文章検索)

では、シナリオ1に基づいて、実際に検証を行ってみましょう。Sagemakerのドキュメント検索を題材にし、① すべてGENERIC_INDEXのみで埋め込みを実施した場合と、②検索クエリ側にDOCUMENT_RETRIEVALを適用した場合 の、検索結果1位と2位のスコア差を比較します。

概要

  • モデル: amazon.nova-2-multimodal-embeddings-v1:0
  • 埋め込み次元: 1024
  • インデックス作成: GENERIC_INDEX
  • 検索: GENERIC_INDEX or DOCUMENT_RETRIEVAL
  • ドキュメント数: 5件

インデックス化されたドキュメント

  1. Amazon SageMakerでは、組み込みアルゴリズム、事前トレーニング済みモデル、またはカスタムアルゴリズムを使用してモデルをトレーニングできます。トレーニングジョブを作成するには、使用するアルゴリズム、トレーニングデータの場所、コンピューティングリソース、出力の保存場所を指定します。

  2. SageMakerトレーニングでは、インスタンスタイプを選択する必要があります。ml.m5.xlargeやml.p3.2xlargeなど、様々なインスタンスタイプが利用可能です。GPUが必要な場合はp3またはp4インスタンスを選択してください。

  3. 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機能を使用できます。大規模なモデルや大量のデータを扱う場合に有効です。

  4. ハイパーパラメータチューニングジョブを使用すると、最適なハイパーパラメータを自動的に見つけることができます。ベイズ最適化を使用して効率的に探索します。

  5. SageMaker Debuggerを使用すると、トレーニング中のモデルの状態をリアルタイムでモニタリングできます。勾配消失や過学習などの問題を早期に検出できます。

クエリ別のスコア比較

クエリ1: 「SageMakerでモデルをトレーニングする方法は?」

順位 ドキュメント パターン1スコア
(GENERIC)
パターン2スコア
(DOCUMENT_RETRIEVAL)
1 Amazon SageMakerでは、組み込みアルゴリズム、事前トレーニング済み... 0.8546 0.6002
2 SageMaker Debuggerを使用すると、トレーニング中のモデルの状態を... 0.8115 0.5136
3 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機... 0.7926 0.5071

クエリ2: 「GPUインスタンスの選び方を教えて」

順位 ドキュメント パターン1スコア
(GENERIC)
パターン2スコア
(DOCUMENT_RETRIEVAL)
1 SageMakerトレーニングでは、インスタンスタイプを選択する必要があります。... 0.7891 0.5180
2 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機... 0.6904 0.3416
3 ハイパーパラメータチューニングジョブを使用すると、最適なハイパーパラメータを自動... 0.6588 0.3394

クエリ3: 「分散トレーニングについて知りたい」

順位 ドキュメント パターン1スコア
(GENERIC)
パターン2スコア
(DOCUMENT_RETRIEVAL)
1 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機... 0.7290 0.4936
2 SageMaker Debuggerを使用すると、トレーニング中のモデルの状態を... 0.6664 0.3562
3 SageMakerトレーニングでは、インスタンスタイプを選択する必要があります。... 0.6448 0.3422

クエリ4: 「ハイパーパラメータの最適化方法は?」

順位 ドキュメント パターン1スコア
(GENERIC)
パターン2スコア
(DOCUMENT_RETRIEVAL)
1 ハイパーパラメータチューニングジョブを使用すると、最適なハイパーパラメータを自動... 0.8560 0.5340
2 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機... 0.7124 0.3219
3 SageMakerトレーニングでは、インスタンスタイプを選択する必要があります。... 0.6815 0.3008

クエリ5: 「トレーニング中の問題を検出する方法は?」

順位 ドキュメント パターン1スコア
(GENERIC)
パターン2スコア
(DOCUMENT_RETRIEVAL)
1 SageMaker Debuggerを使用すると、トレーニング中のモデルの状態を... 0.6949 0.4781
2 分散トレーニングを実行するには、SageMakerのデータ並列またはモデル並列機... 0.6783 0.3479
3 Amazon SageMakerでは、組み込みアルゴリズム、事前トレーニング済み... 0.6707 0.3323

考察

パターン1(GENERIC_INDEX のみ):

  • 1位スコア範囲: 0.6949 〜 0.8560
  • スコア差が小さい(全体的に高スコア)
  • 問題点: 関連性の低いドキュメントも高スコアになり、区別しづらい

パターン2(DOCUMENT_RETRIEVAL):

  • 1位スコア範囲: 0.4781 〜 0.6002
  • 1位と2位のスコア差が大きい
  • 利点: 真に関連性の高いドキュメントとそうでないものを明確に区別できる

スコア差の例(クエリ1)

パターン 1位スコア 2位スコア 1位と2位のスコア差
パターン1(GENERIC_INDEX) 0.8546 0.8115 0.0431
パターン2(DOCUMENT_RETRIEVAL) 0.6002 0.5136 0.0866

検証まとめー①(文章検索)

Nova Multimodal Embeddingsは、GENERIC_INDEX(インデックス作成)とDOCUMENT_RETRIEVAL(検索)の組み合わせにより、GENERIC_INDEXの場合よりも1位と2位の差が大きく、効果的な検索を実現できることが確認できました。実際のRAGシステムでは、以下のような利点があります:

  1. Top-Kの精度向上: より関連性の高いドキュメントを確実に上位に表示
  2. 閾値設定が容易: スコア差が明確なため、適切な閾値を設定しやすい
  3. ノイズの排除: 関連性の低いドキュメントを効果的に除外できる

注意として、GENERIC_INDEX(インデックス作成)とDOCUMENT_RETRIEVAL(検索)で類似度計算を行った場合、それぞれが全く同じ文章であっても、cos類似度の最大値は0.7程度になります。これは、そもそものembeddingの分布が異なるからです。

検証ー②(画像検索) ※追記しました

では、続いて画像検索を題材にし、① すべてGENERIC_INDEXのみで埋め込みを実施した場合と、②検索クエリ側にIMAGE_RETRIEVALを適用した場合 の、検索結果1位と2位のスコア差を比較します。データセットにはCIFAR-10を使いました。

インデックス化された画像

automobile - 自動車

bird - 鳥

cat - 猫

horse - 馬

truck - トラック

クエリ別のスコア比較

クエリ1: 「車の画像」

順位 画像クラス パターン1スコア
(GENERIC)
パターン2スコア
(IMAGE_RETRIEVAL)
1 automobile 0.2319 0.4458
2 truck 0.1721 0.3350
3 cat 0.1621 0.2807

クエリ2: 「鳥の写真」

順位 画像クラス パターン1スコア
(GENERIC)
パターン2スコア
(IMAGE_RETRIEVAL)
1 bird 0.2127 0.3689
2 cat 0.1027 0.2151
3 automobile 0.0787 0.1769

クエリ3: 「猫」

順位 画像クラス パターン1スコア
(GENERIC)
パターン2スコア
(IMAGE_RETRIEVAL)
1 cat 0.2193 0.4349
2 horse 0.0414 0.1835
3 bird 0.0248 0.0949

クエリ4: 「馬が写っている画像」

順位 画像クラス パターン1スコア
(GENERIC)
パターン2スコア
(IMAGE_RETRIEVAL)
1 horse 0.2750 0.4764
2 cat 0.1727 0.2998
3 automobile 0.1508 0.2650

クエリ5: 「トラック」

順位 画像クラス パターン1スコア
(GENERIC)
パターン2スコア
(IMAGE_RETRIEVAL)
1 truck 0.2341 0.4414
2 automobile 0.1459 0.1788
3 cat 0.1153 -

考察

パターン1(GENERIC_INDEX のみ):

  • 1位スコア範囲: 0.2127 〜 0.2750
  • スコア差が小さい
  • 問題点: 関連性の低い画像も近いスコアになり、区別しづらい

パターン2(IMAGE_RETRIEVAL):

  • 1位スコア範囲: 0.3689 〜 0.4764
  • 1位と2位のスコア差が大きい
  • 利点: 真に関連性の高い画像とそうでないものを明確に区別できる

スコア差の例(クエリ5「トラック」)

パターン 1位スコア 2位スコア 1位と2位のスコア差
パターン1(GENERIC_INDEX) 0.2341 0.1459 0.0881
パターン2(IMAGE_RETRIEVAL) 0.4414 0.1788 0.2626

検証まとめー②(画像検索)

画像検索においても、文章検索と同じく、GENERIC_INDEX(インデックス作成)とIMAGE_RETRIEVAL(検索)の組み合わせにより、GENERIC_INDEXのみの場合よりも1位と2位の差が大きく、効果的な画像検索を実現できることが確認できました。

本記事のまとめ

Nova Multimodal EmbeddingsのembeddingPurposeの設定では、インデックス側は常にGENERIC_INDEXで統一し、検索クエリ側でタスクに応じた*_RETRIEVALを選択することで、Nova Multimodal Embeddingsの非対称埋め込みの性能を最大限に引き出すことができます。これからみなさまが開発するエージェントでも、embeddingPurposeを適切に設定いただくことで、より高精度なエージェントの構築が期待できます。本記事が、皆様の一助となれば幸いです。

参考文献

Amazon Nova Multimodal Embeddings:Technical Report and Model Card
Nova Multimodal Embeddingsを紹介するAWS News blog

Discussion