Azure AI Search でベクトル クエリを作成する

Azure AI Search で、検索インデックスにベクトル フィールドがある場合に、以下を実施する方法をこの記事で説明します:

この記事では、図示するために REST を使用しています。 他の言語のコード サンプルの場合、ベクトル クエリを含むエンドツーエンドのソリューションについては、azure-search-vector-samples GitHub リポジトリを参照してください。

前提条件

ヒント

インデックスにベクトルがあるかどうかを素早く判断するには、dimensions 属性と vectorSearchProfile 代入演算子を持つフィールドの Collection(Edm.Single) 型を検索してください。

クエリ文字列入力をベクトルに変換する

ベクトル フィールドに対してクエリを実行するには、クエリ自体がベクトルである必要があります。 ユーザーのテキスト クエリ文字列をそのベクトル表現に変換するための 1 つのアプローチは、アプリケーション コード内で埋め込みライブラリまたは API を呼び出すことです。 ソース ドキュメントに埋め込みを生成するために使用したのと同じ埋め込みを常に使用することをお勧めします。

azure-search-vector-samples リポジトリで、埋め込みを生成する方法を示すコード サンプルを見つけることができます。

Azure OpenAI 埋め込みモデルのデプロイに送信されるクエリ文字列の REST API の例を次に示します:

POST https://{{openai-service-name}}.openai.azure.com/openai/deployments/{{openai-deployment-name}}/embeddings?api-version={{openai-api-version}}
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "input": "what azure services support generative AI'"
}

デプロイされたモデルの呼び出しが成功した場合、予想される応答は 202 です。 応答の本文の "埋め込み" フィールドは、クエリ文字列 "input" のベクトル表現です。 テスト目的で、次のいくつかのセクションで示す構文を使用して、クエリ要求の "embedding" 配列の値を "vectorQueries.vector" にコピーします。

デプロイされたモデルに対するこの POST 呼び出しの実際の応答には、1536 個の埋め込みが含まれています。ここでは、読みやすくするために最初のいくつかのベクトルのみにトリミングされています。

{
    "object": "list",
    "data": [
        {
            "object": "embedding",
            "index": 0,
            "embedding": [
                -0.009171937,
                0.018715322,
                ...
                -0.0016804502
            ]
        }
    ],
    "model": "ada",
    "usage": {
        "prompt_tokens": 7,
        "total_tokens": 7
    }
}

このアプローチでは、アプリケーション コードはモデルへの接続、埋め込みデータの生成、応答の処理を担当します。

ヒント

垂直統合を使用したクエリ (現在パブリック プレビュー段階) を試して、Azure AI Search がクエリのベクトル化の入力と出力を処理します。

ベクトル クエリ要求

このセクションでは、ベクトル クエリの基本的な構造を説明します。 Azure portal、REST API、または Azure SDK を使用して、ベクトル クエリを作成できます。 2023-07-01-Preview から移行する場合、重大な変更があります。 詳細については、「最新の REST API にアップグレードする」を参照してください。

2023-11-01Search POST の安定バージョンの REST API です。 このバージョンでは次の内容がサポートされます。

  • vectorQueries はベクトル検索のコンストラクトです。
  • kindvector に設定して、クエリがベクトル配列であると指定します。
  • vector はクエリです (テキストや画像のベクトル表現)。
  • exhaustive (省略可能) では、HNSW のフィールドにインデックスを付けた場合でも、クエリ時に完全な KNN を呼び出します。

次の例では、文字列「フル テキスト検索をサポートする Azure サービス」をベクトルで表現しています。 クエリは contentVector フィールドを対象にしています。 クエリでは、k の結果が返されます。 実際のベクトルには 1536 個の埋め込みがあるため、この例では読みやすくするためにトリミングされています。

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector",
            "k": 5
        }
    ]
}

ベクトル クエリ応答

Azure AI Search では、クエリ応答は既定ですべての retrievable フィールドで構成されます。 ただし、retrievable フィールドのサブセットを select ステートメントに一覧表示することで、検索結果を制限することは一般的です。

ベクトル クエリでは、応答のフィールドをベクトル化する必要があるかどうかを注意深く検討してください。 ベクトル フィールドは人間が判読できないので、応答を Web ページにプッシュする場合は、結果を代表する非ベクトル フィールドを選択する必要があります。 たとえば、contentVector に対してクエリが実行された場合、代わりに content を返すことができます。

結果にベクトル フィールドが必要な場合は、ここに応答構造の例を示します。 contentVector は埋め込みの文字列配列で、ここでは簡潔にするために切り捨てています。 検索スコアは関連性を示します。 その他の非ベクトル フィールドもコンテキストのために含まれています。

{
    "@odata.count": 3,
    "value": [
        {
            "@search.score": 0.80025613,
            "title": "Azure Search",
            "category": "AI + Machine Learning",
            "contentVector": [
                -0.0018343845,
                0.017952163,
                0.0025753193,
                ...
            ]
        },
        {
            "@search.score": 0.78856903,
            "title": "Azure Application Insights",
            "category": "Management + Governance",
            "contentVector": [
                -0.016821077,
                0.0037742127,
                0.016136652,
                ...
            ]
        },
        {
            "@search.score": 0.78650564,
            "title": "Azure Media Services",
            "category": "Media",
            "contentVector": [
                -0.025449317,
                0.0038463024,
                -0.02488436,
                ...
            ]
        }
    ]
}

重要なポイント:

  • k は、返されるニアレストネイバー結果の数を決定します。この場合は 3 です。 ベクター クエリは常に k 結果を返します。少なくとも k ドキュメントが存在すると仮定すると、類似度の低いドキュメントがある場合でも、アルゴリズムはクエリ ベクターに最も近い k を検出します。

  • @search.scoreベクトル探索アルゴリズムによって決定されます。

  • 検索結果のフィールドは、すべての retrievable フィールド、または select 句のフィールドです。 ベクトル クエリの実行中は、ベクトル データのみで一致が行われます。 ただし、応答には、インデックスに任意の retrievable フィールドを含めることができます。 ベクトル フィールド結果をデコードする機能はないため、非ベクトル テキスト フィールドを含めることは、人間が値を判読するのに役立ちます。

フィルターを使用したベクトル クエリ

クエリ要求にはベクトル クエリとフィルター式を含めることができます。 フィルターは filterable テキスト フィールドと数値フィールドに適用され、フィルター条件に基づいて検索ドキュメントを含めたり除外したりするのに便利です。 ベクトル フィールド自体はフィルター処理できませんが、クエリには同じインデックス内の他のフィールドに対するフィルターを指定することができます。

新しいバージョンの API では、フィルター モードを設定して、クエリの実行前または実行後にフィルターを適用できます。 各モードの比較およびインデックス サイズに基づいて期待されるパフォーマンスについては、ベクトル クエリにおけるフィルターに関するページを参照してください。

ヒント

テキストまたは数値を含むソース フィールドがない場合は、LastModified プロパティや CreatedBy プロパティなどのドキュメント メタデータを確認します。これは、メタデータ フィルターで役立つ可能性があります。

2023-11-01 は、この API の安定バージョンです。 次の特徴があります。

  • vectorFilterMode による事前フィルター処理 (既定)、または事後フィルター処理モード
  • filter は条件を提供します。

次の例では、クエリ文字列「フルテキスト検索をサポートする Azure サービス」をベクトルで表現しています。 クエリは contentVector フィールドを対象にしています。 実際のベクトルには 1536 個の埋め込みがあるため、この例では読みやすくするためにトリミングされています。

フィルター条件は、検索エンジンがベクトル クエリを実行する前に、フィルター可能なテキスト フィールド (この例では category ) に適用されます。

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "filter": "category eq 'Databases'",
    "vectorFilterMode": "preFilter",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector",
            "k": 5
        }
    ]
}

複数のベクトル フィールド

"vectorQueries.fields" プロパティを複数のベクトル フィールドに設定できます。 ベクトル クエリは fields リストで指定した各ベクトル フィールドに対して実行されます。 複数のベクトル フィールドにクエリを実行する場合、それぞれのベクトル フィールドに同じ埋め込みモデルからの埋め込みが含まれていること、クエリも同じ埋め込みモデルから生成されていることを確認してください。

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector, titleVector",
            "k": 5
        }
    ]
}

複数のベクトル クエリ

マルチクエリ ベクトル検索では、検索インデックス内の複数のベクトル フィールドに対して複数のクエリが送信されます。 このクエリ要求の一般的な例は、同じモデルが画像とテキストコンテンツをベクトル化できるマルチモーダル ベクトル検索に CLIP などのモデルを使用する場合です。

次のクエリ例では、myImageVectormyTextVector の両方の類似性を検索しますが、それぞれ 2 つの異なるクエリ埋め込みを送信し、それぞれ並列で実行します。 このクエリでは、Reciprocal Rank Fusion (RRF) を使用してスコア付けされた結果が生成されます。

  • vectorQueries でベクトル クエリの配列が指定されます。
  • vector には、検索インデックス内の画像ベクトルとテキスト ベクトルが含まれています。 各インスタンスは個別のクエリです。
  • fields でターゲットとなるベクトル フィールドが指定されます。
  • k は、結果に含めるニアレストネイバーの数です。
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "myimagevector",
            "k": 5
        },
        {
            "kind": "vector"
            "vector": [
                -0.002222222,
                0.018708462,
                -0.013770515,
            . . .
            ],
            "fields": "mytextvector",
            "k": 5
        }
    ]
}

検索インデックスに画像ファイルのフィールドが含まれていると仮定すると、検索結果にはテキストと画像の組み合わせが含まれます (検索インデックスには画像が格納されません)。

垂直統合 (プレビュー) を使用したクエリ

このセクションでは、テキスト クエリをベクトルに変換する新しい垂直統合のプレビュー機能を呼び出すベクトル クエリについて説明します。 2023-10-01-Preview REST API または更新されたベータ版 Azure SDK パッケージを使用します。

検索インデックスのベクトル フィールドに、ベクトル化が設定されて割り当て済みであることが前提条件です。 ベクトル化では、クエリ時に使用された接続情報が埋め込みモデルに指定されます。

クエリでは、ベクトルではなく文字列が提供されます:

  • kindtext に設定されている必要があります。
  • text にはテキスト文字列が必須です。 ベクトル フィールドに割り当てられたベクトル化に渡されます。
  • fields は検索するベクトル フィールドです。

クエリ時にベクトル化されたクエリの単純な例を次に示します。 テキスト文字列はベクトル化され、その後 descriptionVector フィールドにクエリを実行するときに使用されます。

POST https://{{search-service}}.search.windows.net/indexes/{{index}}/docs/search?api-version=2023-10-01-preview
{
    "select": "title, genre, description",
    "vectorQueries": [
        {
            "kind": "text",
            "text": "mystery novel set in London",
            "fields": "descriptionVector",
            "k": 5
        }
    ]
}

こちらがテキスト クエリの垂直統合を使用したハイブリッド クエリです。 このクエリには、複数のクエリ ベクトル フィールド、複数の非ベクトル フィールド、フィルター、およびセマンティック ランク付けが含まれます。 ここでも、違いは vector ではなく、ベクトル クエリの kindtext 文字列です。

この例では、検索エンジンによって、インデックス内の descriptionVectorsynopsisVectorauthorBioVector に割り当てられたベクトル化に対して、3 つのベクトル化の呼び出しが実行されます。 結果のベクトルは、対応するフィールドからドキュメントを取得するために使用されます。 また、検索エンジンは、searchクエリ「ロンドンを舞台にしたミステリー小説」のキーワード検索を実行します。

POST https://{{search-service}}.search.windows.net/indexes/{{index}}/docs/search?api-version=2023-10-01-preview
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "search":"mystery novel set in London", 
    "searchFields":"description, synopsis", 
    "semanticConfiguration":"my-semantic-config", 
    "queryType":"semantic",
    "select": "title, author, synopsis",
    "filter": "genre eq 'mystery'",
    "vectorFilterMode": "postFilter",
    "vectorQueries": [
        {
            "kind": "text",
            "text": "mystery novel set in London",
            "fields": "descriptionVector, synopsisVector",
            "k": 5
        },
        {
            "kind": "text"
            "text": "living english author",
            "fields": "authorBioVector",
            "k": 5
        }
    ]
}

全 4 つのクエリによるスコア付けされた結果は、RRF ランク付けを使用して結合されます。 次に、結合された検索結果に対してセマンティック ランク付けが呼び出されますが、searchFields に限り、意味的に最も "search":"mystery novel set in London" に関連のある結果が昇格されます。

Note

ベクトル化は、インデックス作成とクエリ実行時に使用されます。 インデックスにデータのチャンキングとベクトル化が必要ない場合、インデクサーやスキルセット、データ ソースの作成などの手順をスキップできます。 このシナリオでは、ベクトル化は、テキスト文字列を埋め込みに変換するクエリ時にのみ使用されます。

ベクトル クエリ応答のランク付けされた結果の量

ベクター クエリは、結果で返される一致の数を決定する k パラメーターを指定します。 検索エンジンは常に一致を k 個返します。 k がインデックス内のドキュメントの数より大きい場合は、ドキュメントの数によって返される内容の上限が決まります。

フル テキスト検索に慣れている場合、インデックスに用語または語句が含まれていなければ、結果が 0 になると予想されます。 ただし、ベクター検索では、検索操作は最も近い近傍を識別し、最も近い近隣ノードが類似していない場合でも常に k 個の結果を返します。 そのため、特にプロンプトを使用して境界を設定していない場合は、無意味なクエリやトピック外のクエリの結果を取得できます。 関連性の低い結果は類似度スコアが悪くなりますが、近いものがない場合でも"ニアレスト" ベクトルです。 そのため、意味のある結果のない応答でも k 結果を返すことができますが、各結果の類似性スコアは低くなります。

フルテキスト検索を含むハイブリッド アプローチでは、この問題を軽減できます。 もう 1 つの軽減策は、クエリが純粋な単一ベクター クエリの場合にのみ、検索スコアに最小しきい値を設定することです。 ハイブリッド クエリは、RRF 範囲が非常に小さく揮発性であるため、最小しきい値には役立たない。

結果数に影響するクエリ パラメーターは次のとおりです:

  • ベクトルのみのクエリの結果として "k": n
  • "search" パラメーターを含むハイブリッド クエリの結果として "top": n

"k" と "top" はどちらも省略可能です。 指定しない場合、応答の結果の既定の数は 50 です。 "top" と "skip" を設定して、より多くの結果をページングしたり、既定値を変更したりできます。

ベクトル クエリで使用されるランキング アルゴリズム

結果のランク付けは、次のいずれかによって計算されます:

  • 類似性メトリック
  • 検索結果のセットが複数ある場合の Reciprocal Rank Fusion (RRF)。

類似性メトリック

ベクトルのみのクエリのインデックス vectorSearch セクションで指定された類似性メトリック。 有効な値は、cosineeuclideandotProduct です。

Azure OpenAI 埋め込みモデルではコサイン類似性が使用されるため、Azure OpenAI 埋め込みモデルを使用している場合は、cosine が推奨されるメトリックです。 その他のサポートされているランク付けメトリックには、euclideandotProduct があります。

RRF の使用

クエリが複数のベクトル フィールドを対象とし、複数のベクトル クエリを並行して実行する場合、またはクエリがベクトル検索とフルテキスト検索のハイブリッドである場合、セマンティック ランク付けの有無にかかわらず、複数のセットが作成されます。

クエリの実行中は、ベクトル クエリは 1 つの内部ベクトル インデックスのみを対象とすることができます。 そのため、ベクトル フィールド複数のベクトル クエリの場合、検索エンジンは、各フィールドのそれぞれのベクトル インデックスを対象とする複数のクエリを生成します。 出力は、RRF を使用して融合される各クエリのランク付けされた結果のセットです。 詳細については、「Reciprocal Rank Fusion (RRF) を使用した関連性スコアリング」を参照してください。

次のステップ

次の手順として、PythonC#JavaScript のベクトル クエリ コードの例を確認してください。