ベクトル インデックスを作成する

Azure AI 検索では、"ベクトル ストア" には、ベクトル フィールドと非ベクトル フィールドを定義するインデックス スキーマ、埋め込み空間を作成および圧縮するアルゴリズムのベクトル構成、およびクエリ要求で使用されるベクトル フィールド定義の設定が含まれます。

Create or Update Index API によってベクトル ストアが作成されます。 次の手順に従ってベクトル データにインデックスを作成します。

  • ベクトルのアルゴリズムとオプションの圧縮を指定してスキーマを定義する
  • ベクトル フィールドの定義を追加する
  • 事前にベクトル化されたデータを別のステップとして読み込むか、インデックス作成中のデータ チャンク分割とエンコードに垂直統合を使用する

この記事では、ワークフローについて説明し、説明のために REST を使用します。 基本的なワークフローを理解したら、テスト コードと運用コードでこれらの機能を使用するガイダンスとして、azure-search-vector-samples リポジトリにある Azure SDK コード サンプルに進んでください。

ヒント

Azure portal を使用してベクター インデックスを作成し、統合されたデータ チャンクとベクター化を試してください。

前提条件

  • 任意のリージョンおよび任意のレベルの Azure AI Search。 既存のサービスのほとんどではベクトル検索がサポートされています。 2019 年 1 月より前に作成されたサービスには、ベクトル インデックスを作成できない小さなサブセットがあります。 このような場合は、新しいサービスを作成する必要があります。 垂直統合 (Azure AI を呼び出すスキルセット) を使用する場合、Azure AI Search は Azure OpenAI または Azure AI サービスと同じリージョンにある必要があります。

  • 既存のベクトル埋め込み、または垂直統合を使用します。ここで、埋め込みモデルはインデックス作成パイプラインから呼び出されます。

  • 埋め込みの作成に使用されるモデルの次元の制限を理解している必要があります。 有効値は 2 から 3072 次元です。 Azure OpenAI では、text-embedding-ada-002 の場合、数値ベクトルの長さは 1536 です。 text-embedding-3-small または text-embedding-3-large の場合、ベクトルの長さは 3072 です。

  • サポートされている類似性メトリックも把握しておく必要があります。 Azure OpenAI の場合、類似性は、cosine を使用して計算されます

  • インデックスの作成に慣れている必要があります。 スキーマには、ドキュメント キーのフィールド、検索またはフィルター処理するその他のフィールド、およびインデックス作成やクエリの実行中に必要な動作に関するその他の構成が含まれている必要があります。

インデックス作成のためのドキュメントを準備する

インデックスを付ける前に、ベクトルおよび非ベクトル データのフィールドを含むドキュメント ペイロードをアセンブルします。 ドキュメント構造は、インデックス スキーマに準拠している必要があります。

ドキュメントが次のようになっていることを確認します。

  1. 各ドキュメントを一意に識別するフィールドまたはメタデータ プロパティを指定します。 すべての検索インデックスにはドキュメント キーが必要です。 ドキュメント キーの要件を満たすには、ソース ドキュメントに、インデックス内で一意に識別できる 1 つのフィールドまたはプロパティが必要です。 このソース フィールドは、Edm.String 型のインデックス フィールドにマップし、検索インデックスで key=true である必要があります。

  2. ソース フィールドにベクトル データ (単精度浮動小数点数の配列) を指定します。

    ベクトル フィールドには、フィールドごとに 1 つモデルを埋め込むことで生成される配列が含まれます。ここでフィールドは最上位フィールド (入れ子になった型や複合型の一部ではありません) です。 最も簡単に統合するには、テキスト ドキュメント用の text-embedding-ada-002 や画像用の Image Retrieval REST API などの、Azure OpenAI の埋め込みモデルをお勧めします。

    インデクサーとスキルセットに依存できる場合は、インデックス作成中に画像と英数字のコンテンツをエンコードする垂直統合を使用することを検討してください。 フィールドの定義はベクトル フィールド用ですが、ソース データには、インデックス作成中に作成されたベクトル配列とともにテキストまたは画像を使用できます。

  3. クエリ応答、および同じ要求にフルテキスト検索またはセマンティック ランク付けを含むハイブリッド クエリ シナリオ用に、人間が判読できる英数字の内容を他のフィールドに提供します。

検索インデックスには、サポートするすべてのクエリ シナリオのフィールドと内容が含まれている必要があります。 製品名、バージョン、メタデータ、または住所を検索またはフィルター処理するとします。 この場合、類似性検索は特に役立つわけではありません。 キーワード検索、地域検索、またはフィルターの方が適しています。 ベクトルおよび非ベクトル データの包括的なフィールド コレクションを含む検索インデックスでは、クエリの構築と応答の構成に最大限の柔軟性を提供します。

ベクトルおよび非ベクトル フィールドを含むドキュメント ペイロードの簡単な例が、この記事のベクトル データの読み込みに関するセクションにあります。

ベクトル検索構成を追加する

ベクトル構成は、ベクトル ノード間の "最も近い近隣" 情報を作成するためにインデックス作成中に使用されるパラメーターを指定します。

  • 階層ナビゲーション可能な小さい世界 (HNSW)
  • 完全な KNN

フィールドで HNSW を選択すると、クエリ時に完全な KNN を選択できます。 しかし、逆の方向ではうまくいきません。完全な検索を選択すると、後で HNSW 検索を要求することはできません。これは、近似検索を有効にする追加のデータ構造が存在しないためです。

ベクトル構成は、ベクトル サイズを小さくするための量子化方法も指定します。

  • スカラー
  • バイナリ (2024-07-01 の新しい Azure SDK パッケージでのみ利用可能)

最新バージョンに移行する方法については、REST API のアップグレードに関する記事を参照してください。

2024-07-01 は一般提供されています。 次のベクトル構成がサポートされています。

  • vectorSearch.algorithms は、HNSW と完全な KNN をサポートします。
  • vectorSearch.compressions は、スカラー量子化とバイナリ量子化、オーバーサンプリング、元のベクトルによる再ランク付けをサポートします。
  • vectorSearch.profiles は、アルゴリズムと圧縮構成の複数の組み合わせを提供します。

コンテンツをベクトル化するための戦略を必ず用意してください。 組み込みのエンコードには、垂直統合クエリ時ベクトル化をお勧めします。

  1. インデックスの作成または更新 API を使用してインデックスを作成します。

  2. 埋め込み空間の作成に使用する検索アルゴリズムを指定する vectorSearch セクションをインデックスに追加します。

     "vectorSearch": {
         "compressions": [
             {
                 "name": "scalar-quantization",
                 "kind": "scalarQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0,
                     "scalarQuantizationParameters": {
                         "quantizedDataType": "int8"
                     }
             },
             {
                 "name": "binary-quantization",
                 "kind": "binaryQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0,
             }
         ],
         "algorithms": [
             {
                 "name": "hnsw-1",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 4,
                     "efConstruction": 400,
                     "efSearch": 500,
                     "metric": "cosine"
                 }
             },
             {
                 "name": "hnsw-2",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 8,
                     "efConstruction": 800,
                     "efSearch": 800,
                     "metric": "hamming"
                 }
             },
             {
                 "name": "eknn",
                 "kind": "exhaustiveKnn",
                 "exhaustiveKnnParameters": {
                     "metric": "euclidean"
                 }
             }
    
         ],
         "profiles": [
           {
             "name": "vector-profile-hnsw-scalar",
             "compression": "scalar-quantization",
             "algorithm": "hnsw-1"
           }
         ]
     }
    

    重要なポイント:

    • 圧縮、アルゴリズム、プロファイルの各構成の名前は、その種類ごとに、インデックス内で一意である必要があります。

    • vectorSearch.compressions.kind には、scalarQuantization または binaryQuantization を指定できます。

    • vectorSearch.compressions.rerankWithOriginalVectors は元の非圧縮ベクトルを使用して類似性を再計算し、最初の検索クエリによって返される上位の結果を再ランク付けします。 stored が false の場合でも、非圧縮ベクトルが検索インデックスに存在します。 このプロパティは省略可能です。 既定値は True です。

    • 量子化による情報の減少を緩和するために、vectorSearch.compressions.defaultOversampling は潜在的な結果のより広範なセットを考慮します。 潜在的な結果の数式は、クエリ内の k とオーバーサンプリング乗数で構成されます。 たとえば、クエリが k を 5 に指定し、オーバーサンプリングが 20 の場合、クエリはその目的のために元の非圧縮ベクトルを使用して、再ランク付けに使用する 100 個のドキュメントを効果的に要求します。 上位の k 個の再ランク付けの結果のみが返されます。 このプロパティは省略可能です。 既定値は 4 です。

    • vectorSearch.compressions.scalarQuantizationParameters.quantizedDataTypeint8 に設定されていること。 これは現時点でサポートされている唯一のプリミティブ データ型です。 このプロパティは省略可能です。 既定値は int8 です。

    • vectorSearch.algorithms.kind は、"hnsw""exhaustiveKnn" のいずれかです。 これらは、インデックス作成中にベクトル コンテンツを整理するために使用される近似最近傍 (ANN) アルゴリズムです。

    • vectorSearch.algorithms.m は、双方向リンク数です。 既定値は 4 です。 範囲は 4 ~ 10 です。 値を小さくすると、結果のノイズが少なくなります。

    • vectorSearch.algorithms.efConstruction は、インデックス作成中に使用される最も近い近隣ノードの数です。 既定値は 400 です。 範囲は 100 ~ 1,000 です。

    • "vectorSearch.algorithms.fSearch は、検索中に使用される最も近い近隣ノードの数です。 既定値は 500 です。 範囲は 100 ~ 1,000 です。

    • Azure OpenAI を使用している場合、vectorSearch.algorithms.metric は "cosine" にする必要があります。それ以外の場合は、使用している埋め込みモデルに関連付けられている類似性メトリックを使用します。 サポートされる値は、cosinedotProducteuclideanhamming (バイナリ データのインデックス作成に使用) です。

    • vectorSearch.profiles によって、より豊富な定義に対応するための抽象化レイヤーが追加されます。 プロファイルは vectorSearch で定義され、その後、各ベクトル フィールドで名前によって参照されます。 これは圧縮とアルゴリズム構成の組み合わせです。 これはベクトル フィールドに割り当てるプロパティであり、フィールドのアルゴリズムと圧縮を決定します。

フィールド コレクションにベクトル フィールドを追加する

フィールド コレクションには、ドキュメント キーのフィールド、ベクトル フィールド、およびハイブリッド検索シナリオに必要なその他のフィールドを含める必要があります。

ベクトル フィールドは、そのデータ型、ベクトルの出力に使用される埋め込みモデルに基づく dimensions プロパティ、ベクトル プロファイルによって特徴付けられます。

2024-07-01 は一般提供されています。

  1. インデックスの作成または更新を使用してインデックスを作成します。

  2. 次の属性を含むベクトル フィールドを定義します。 生成された埋め込みをフィールドごとに 1 つ格納できます。 各ベクトル フィールドについて次を行います。

    • type は、ベクトル データ型である必要があります。 Collection(Edm.Single) は、モデルの埋め込みに最も一般的です。
    • dimensions は、埋め込みモデルによって生成されるディメンションの数です。 text-embedding-ada-002 の場合は、1,536 個です。
    • vectorSearchProfile は、インデックス内の他の場所で定義されているプロファイルの名前です。
    • searchable は true にする必要があります。
    • retrievable には、true または false を指定できます。 True の場合、生のベクトル (そのうちの 1,536 個) がプレーンテキストとして返され、ストレージ領域が消費されます。 ベクトル結果をダウンストリーム アプリに渡す場合は、true に設定します。
    • stored には、true または false を指定できます。 これは、取得に備えてベクトルの追加コピーを保存するかどうかを決定します。 詳細については、ベクトル サイズを小さくする方法に関する記事を参照してください。
    • filterablefacetablesortable は、false にする必要があります。
  3. ベクトル クエリ事前フィルター処理または事後フィルター処理を呼び出す場合は、filterable を true に設定した "title" など、フィルターを適用できる非ベクトル フィールドをコレクションに追加します。

  4. インデックスを作成するテキスト コンテンツの内容と構造を定義する他のフィールドを追加します。 最低でも、ドキュメント キーが必要です。

    また、クエリまたはその応答に役立つフィールドも追加する必要があります。 次の例は、ベクトルと同等のタイトルとコンテンツ ("titleVector"、"contentVector") のベクトル フィールドを示しています。 また、検索結果の並べ替え、フィルター処理、読み取りに役立つ同等のテキスト コンテンツ ("title"、"content") のフィールドも提供します。

    次の例は、フィールド コレクションを示しています。

    PUT https://my-search-service.search.windows.net/indexes/my-index?api-version=2024-07-01&allowIndexDowntime=true
    Content-Type: application/json
    api-key: {{admin-api-key}}
    {
        "name": "{{index-name}}",
        "fields": [
            {
                "name": "id",
                "type": "Edm.String",
                "key": true,
                "filterable": true
            },
            {
                "name": "title",
                "type": "Edm.String",
                "searchable": true,
                "filterable": true,
                "sortable": true,
                "retrievable": true
            },
            {
                "name": "titleVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": true,
                "stored": true,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            },
            {
                "name": "content",
                "type": "Edm.String",
                "searchable": true,
                "retrievable": true
            },
            {
                "name": "contentVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": false,
                "stored": false,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            }
        ],
        "vectorSearch": {
            "algorithms": [
                {
                    "name": "hnsw-1",
                    "kind": "hnsw",
                    "hnswParameters": {
                        "m": 4,
                        "efConstruction": 400,
                        "efSearch": 500,
                        "metric": "cosine"
                    }
                }
            ],
            "profiles": [
                {
                    "name": "vector-profile-1",
                    "algorithm": "hnsw-1"
                }
            ]
        }
    }
    

インデックス作成のためベクトル データを読み込む

インデックス作成用に指定するコンテンツは、インデックス スキーマに準拠し、ドキュメント キーの一意の文字列値を含んでいる必要があります。 事前ベクトル化データは、英数字コンテンツを含む他のフィールドと共存できる 1 つ以上のベクトル フィールドに読み込まれます。

データ インジェストにプッシュまたはプルの手法を使用できます。

Documents - Index を使用して、ベクトル データと非ベクトル データをインデックスに読み込みます。 インデックス作成用のプッシュ API は、すべての安定バージョンとプレビュー バージョンで同じです。 ドキュメントを読み込むには、次のいずれかの API を使用します。

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/index?api-version=2024-07-01

{
    "value": [
        {
            "id": "1",
            "title": "Azure App Service",
            "content": "Azure App Service is a fully managed platform for building, deploying, and scaling web apps. You can host web apps, mobile app backends, and RESTful APIs. It supports a variety of programming languages and frameworks, such as .NET, Java, Node.js, Python, and PHP. The service offers built-in auto-scaling and load balancing capabilities. It also provides integration with other Azure services, such as Azure DevOps, GitHub, and Bitbucket.",
            "category": "Web",
            "titleVector": [
                -0.02250031754374504,
                 . . . 
                        ],
            "contentVector": [
                -0.024740582332015038,
                 . . .
            ],
            "@search.action": "upload"
        },
        {
            "id": "2",
            "title": "Azure Functions",
            "content": "Azure Functions is a serverless compute service that enables you to run code on-demand without having to manage infrastructure. It allows you to build and deploy event-driven applications that automatically scale with your workload. Functions support various languages, including C#, F#, Node.js, Python, and Java. It offers a variety of triggers and bindings to integrate with other Azure services and external services. You only pay for the compute time you consume.",
            "category": "Compute",
            "titleVector": [
                -0.020159931853413582,
                . . .
            ],
            "contentVector": [
                -0.02780858241021633,
                 . . .
            ],
            "@search.action": "upload"
        }
        . . .
    ]
}

ベクトル コンテンツについてのインデックスを確認する

検証目的で、Azure portal の検索エクスプローラーまたは REST API 呼び出しを使用してインデックスのクエリを実行できます。 Azure AI Search ではベクトルを人間が判読できるテキストに変換できないため、一致のエビデンスを提供する同じドキュメントからフィールドを返すようにしてください。 たとえば、ベクトル クエリが "titleVector" フィールドを対象とする場合は、検索結果に "title" を選択できます。

あるフィールドを結果に含めるには、そのフィールドに "retrievable" の属性が付けられている必要があります。

  • [検索管理]>[インデックス] でインデックスを確認して、インデックス サイズの合計とベクトルのインデックス サイズを表示します。 正のベクトル インデックス サイズは、ベクトルが存在することを示します。

  • 検索エクスプローラーを使用して、インデックスのクエリを実行します。 検索エクスプローラーには、クエリ ビュー (既定) と JSON ビューの 2 つのビューがあります。

    • [クエリ オプション]>[Hide vector values in search results] (検索結果でベクトル値を非表示する) を設定して、結果を読みやすくします。

    • ベクトル クエリに JSON ビューを使用します。 実行するベクトル クエリの JSON 定義を貼り付けるか、テキストからベクトル、または画像からベクトルへの組み込みの変換を使用できます (インデックスにベクトル代入がある場合)。 画像検索の詳細については、クイック スタート: 検索エクスプローラーで画像を検索する方法に関する記事を参照してください。

    • 既定のクエリ ビューを使用して、インデックスにベクトルが含まれていることをすばやく確認します。 クエリ ビューはフルテキスト検索用です。 ベクトル クエリには使用できませんが、空の検索 (search=*) を送信してコンテンツを確認できます。 ベクトル フィールドを含むすべてのフィールドの内容が、プレーン テキストとして返されます。

    • 詳細については、ベクトル クエリの作成に関する記事を参照してください。

ベクトル ストアを更新する

ベクトル ストアを更新するには、スキーマを変更し、必要に応じてドキュメントを再読み込みして新しいフィールドを設定します。 スキーマ更新の API には、インデックスの作成または更新 (REST)、Azure SDK for .NET の CreateOrUpdateIndex、Azure SDK for Python の create_or_update_index、その他の Azure SDK の同様のメソッドが含まれます。

インデックスの更新に関する標準的なガイダンスについては、インデックスを更新または再構築する方法に関する記事で説明されています。

重要なポイントは次のとおりです。

  • 多くの場合、既存のフィールドの更新と削除には、削除と再構築が必要です。

  • ただし、再構築しなくても、次の変更を加えて既存のスキーマを更新できます。

    • Fields コレクションに新しいフィールドを追加します。
    • 新しいベクトル構成を追加します。新しいフィールドには割り当てられますが、既にベクトル化されている既存のフィールドには割り当てられません。
    • 既存のフィールドの "retrievable" (値は true または false) を変更します。 ベクトル フィールドは検索可能で取得可能である必要がありますが、削除と再構築が不可能な状況でベクトル フィールドへのアクセスを無効にする場合は、retrievable を false に設定できます。

次のステップ

次の手順として、「検索インデックス内のベクトル データのクエリ」をお勧めします。

azure-search-vector リポジトリのコード サンプルでは、スキーマ定義、ベクトル化、インデックス作成、クエリを含むエンドツーエンドのワークフローを示しています。

PythonC#JavaScript 用のデモ コードがあります。