Azure AI Search でハイブリッド クエリを作成する

ハイブリッド検索では、1 つまたは複数のベクトル クエリが単一の検索要求で結合されます。 クエリは並列で実行されます。 結果は、Reciprocal Rank Fusion (RRF) を使用して単一のランク付けされた結果セットを返すことで、新しい検索スコアによってマージおよび並べ替えられます。

ほとんどの場合、ベンチマーク テストごとに、セマンティック ランク付けを使用したハイブリッド クエリでは最も関連性の高い結果が返されます。

ハイブリッド クエリを定義するには、REST API 2023-11-012023-10-01-preview2024-03-01-preview、Azure portal の Search Explorer、または新しいバージョンの Azure SDK を使用します。

前提条件

Search Explorer でハイブリッド クエリを実行する

  1. Search Explorer で、API バージョンが 2023-10-01-preview 以降であることを確認します。

  2. [ビュー] で、[JSON ビュー] を選択します。

  3. 既定のクエリ テンプレートをハイブリッド クエリに置き換えます。たとえば、ベクトル クイックスタートの例の 539 行目から始まるものです。 簡潔にするために、この記事ではベクトルは切り詰められています。

    ハイブリッド クエリには、search で指定されたテキスト クエリと、vectorQueries.vector で指定されたベクトル クエリがあります。

    テキスト クエリとベクトル クエリは、同等であるか、少なくとも競合しないようにする必要があります。 クエリが異なる場合、ハイブリッドの利点は得られません。

    {
        "count": true,
        "search": "historic hotel walk to restaurants and shopping",
        "select": "HotelId, HotelName, Category, Tags, Description",
        "top": 7,
        "vectorQueries": [
            {
                "vector": [0.01944167, 0.0040178085, -0.007816401 ... <remaining values omitted> ], 
                "k": 7,
                "fields": "DescriptionVector",
                "kind": "vector",
                "exhaustive": true
            }
        ]
    }
    
  4. [Search] を選択します。

ハイブリッド クエリ要求 (REST API)

ハイブリッド クエリは、テキスト検索とベクトル検索を組み合わせたものであり、search パラメータはクエリ文字列を、vectorQueries.vector パラメータはベクトル クエリを受け取ります。 検索エンジンは、フルテキストとベクトル クエリを同時に実行します。 すべての一致の和集合は、Reciprocal Rank Fusion (RRF) を使用して関連性が評価され、応答で単一の結果セットが返されます。

結果は、retrievable とマークされたフィールドのベクトルを含む、プレーンテキストで返されます。 数値ベクトルは検索結果では役に立たないため、インデックス内の他のフィールドをベクトル一致のプロキシとして選択します。 たとえば、インデックスに "descriptionVector" フィールドと "descriptionText" フィールドがある場合、クエリは "descriptionVector" で一致しますが、検索結果には "descriptionText" と表示されます。 この select パラメータを使用して、結果に人間が判読できるフィールドのみを指定します。

次の例は、ハイブリッド クエリ構成を示しています。

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}}
{
    "vectorQueries": [{
        "vector": [
            -0.009154141,
            0.018708462,
            . . . 
            -0.02178128,
            -0.00086512347
        ],
        "fields": "DescriptionVector",
        "kind": "vector",
        "exhaustive": true,
        "k": 10
    }],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Address/City",
    "top": "10"
}

重要なポイント:

  • ベクトル クエリ文字列は、vectorQueries.vector プロパティを使用して指定されます。 クエリは "DescriptionVector" フィールドに対して実行されます。 クエリの種類を示すには、kind を "vector" に設定します。 必要に応じて、exhaustive を true に設定し、ベクトル フィールドのすべての内容に対してクエリを実行します。

  • キーワード検索は、search プロパティを使用して指定されます。 ベクトル クエリと並行して実行されます。

  • k は、ベクトル クエリから返され、RRF ランカーに提供される最も近い近隣の一致の数を決定します。

  • top は、応答全体で返される一致の数を決定します。 この例では、マージされた結果に少なくとも 10 個の一致があると仮定して、応答に 10 個の結果が含まれています。

フィルターを使用したハイブリッド検索

この例では、検索インデックスの非ベクトル フィールド filterable に適用されるフィルターを追加します。

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}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 10
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "vectorFilterMode": "postFilter",
    "filter": "ParkingIncluded",
    "top": "10"
}

重要なポイント:

  • フィルターは、フィルター可能なフィールドの内容に適用されます。 この例では、ParkingIncluded フィールドはブール値であり、インデックス スキーマで filterable としてマークされています。

  • ハイブリッド クエリでは、クエリ サーフェスを減らすためにクエリの実行前に、または結果をトリミングするためにクエリの実行後にフィルターを適用することができます。 "preFilter" は既定値です。 postFilter を使用するには、この例に示すように、フィルター処理モードを設定します。

  • クエリ結果を事後フィルター処理すると、結果の数が上位 N 未満になる可能性があります。

セマンティック ランク付けを有効にし、インデックス定義にセマンティック構成が含まれていると仮定すると、ベクトル検索とキーワード検索 (マージされた結果セットに対するセマンティック ランク付けを使用) を含むクエリを作成できます。 必要に応じて、キャプションと回答を追加できます。

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}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 50
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Tags",
    "queryType": "semantic",
    "semanticConfiguration": "my-semantic-config",
    "captions": "extractive",
    "answers": "extractive",
    "top": "50"
}

重要なポイント:

  • セマンティック ランク付けでは、マージされた応答から最大 50 個の結果が受け入れられます。 両方のクエリを等しく表現するには、"k" と "top" を 50 に設定します。

  • "queryType" と "semanticConfiguration" は必須です。

  • "captions" と "answers" は省略可能です。 値は、結果内の逐語的なテキストから抽出されます。 回答は、クエリに対する回答の特性を持つ内容が結果に含まれている場合にのみ返されます。

フィルターを使用したセマンティック ハイブリッド検索

ここでは、コレクションでの最後のクエリを示します。 これは、前の例と同じセマンティック ハイブリッド クエリですが、フィルターを使用します。

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}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 50
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Tags",
    "queryType": "semantic",
    "semanticConfiguration": "my-semantic-config",
    "captions": "extractive",
    "answers": "extractive",
    "filter": "ParkingIsIncluded'",
    "vectorFilterMode": "postFilter",
    "top": "50"
}

重要なポイント:

  • フィルター モードは、セマンティック リランカーで使用できる結果の数に影響を与える可能性があります。 ベスト プラクティスとして、セマンティック ランカーにドキュメントの最大数 (50) を指定するのが賢明です。 事前フィルターまたは事後フィルターの選択性が高すぎる場合、操作するドキュメントを 50 未満にすることでセマンティック ランカーを過小評価している可能性があります。

  • 事前フィルターは、クエリの実行前に適用されます。 事前フィルターによって検索領域が 100 ドキュメントに縮小された場合、ベクトル クエリはこれらの 100 ドキュメントの "DescriptionVector" フィールドに対して実行され、k=50 の最適な一致が返されます。 その後、これらの一致する 50 ドキュメントが RRF に渡されてマージされた結果が得られ、セマンティック ランカーに渡されます。

  • 事後フィルターは、クエリの実行後に適用されます。 k=50 でベクトル クエリ側の 50 の一致が返された場合、事後フィルターはその 50 の一致に適用され、フィルター条件を満たす結果が減り、セマンティック ランカーに渡すドキュメントは 50 未満になります

クエリ応答を構成する

ハイブリッド クエリを設定するときは、応答構造について考えてください。 応答はフラット化行セットです。 クエリのパラメータによって、各行に含まれるフィールドと、応答内の行数が決まります。 検索エンジンは、一致するドキュメントをランク付けし、最も関連性の高い結果を返します。

応答のフィールド

検索結果は、検索インデックスの retrievable フィールドで構成されます。 結果は次のいずれかになります:

  • すべての retrievable フィールド (REST API の既定値)。
  • クエリの "select" パラメータに明示的に一覧表示されているフィールド。

この記事の例では、"select" ステートメントを使用して、応答のテキスト (非ベクトル) フィールドを指定しました。

Note

ベクトルは人間が判読できるテキストにリバース エンジニアリングされないため、応答で返されないようにします。 代わりに、検索ドキュメントを代表する非ベクトル フィールドを選択します。 たとえば、クエリが "DescriptionVector" フィールドを対象とする場合、応答に 1 つの ("Description") がある場合は、同等のテキスト フィールドを返します。

結果の件数

検索条件が弱い場合は、クエリが任意の数のドキュメントと一致する場合があります (たとえば、null クエリの場合は "search=*")。 無制限の結果を返すことが実用的であることは滅多にないので、応答の最大値を指定する必要があります:

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

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

セマンティック ランク付けを使用している場合は、"k" と "top" の両方を少なくとも 50 に設定することをお勧めします。 セマンティック ランカーでは最大 50 件の結果を受け取ることができます。 クエリごとに 50 を指定すると、両方の検索サブシステムから等しい表現が得られます。

ランク付け

オプションの セマンティック再ランク付けの有無にかかわらず、ハイブリッド クエリでは複数のセットが作成されます。 結果のランク付けは、Reciprocal Rank Fusion (RRF) によって計算されます。

このセクションでは、単一ベクトル検索と単純ハイブリッド検索の応答を比較して、上位の結果を確認します。 異なるランク付けアルゴリズムである HNSW の類似性メトリックと RRF の場合では、異なる大きさのスコアが生成されます。 この動作は仕様によるものです。 RRF スコアは、類似性の一致が高い場合でも、非常に低くなる場合があります。 スコアの低さは、RRF アルゴリズムの特性です。 RRF を使用するハイブリッド クエリの場合、純粋なベクトル検索とは対照的に、RRF でランク付けされたドキュメントのスコアは比較的小さいため、ランク付けされたドキュメントの逆数がより多く結果に含まれます。

単一ベクトル検索: コサイン類似度で並べ替えられた結果の @search.score (既定のベクトル類似距離関数)。

{
    "@search.score": 0.8399121,
    "HotelId": "49",
    "HotelName": "Old Carrabelle Hotel",
    "Description": "Spacious rooms, glamorous suites and residences, rooftop pool, walking access to shopping, dining, entertainment and the city center.",
    "Category": "Luxury",
    "Address": {
    "City": "Arlington"
    }
}

ハイブリッド検索: Reciprocal Rank Fusion を使用してランク付けされたハイブリッド結果の @search.score。

{
    "@search.score": 0.032786883413791656,
    "HotelId": "49",
    "HotelName": "Old Carrabelle Hotel",
    "Description": "Spacious rooms, glamorous suites and residences, rooftop pool, walking access to shopping, dining, entertainment and the city center.",
    "Category": "Luxury",
    "Address": {
    "City": "Arlington"
    }
}

次のステップ

次のステップとして、PythonC#、または JavaScript のデモ コードを確認することをお勧めします。