情報取得

Azure AI サービス
Azure AI Search
Azure OpenAI Service
Azure Machine Learning

チャンクの埋め込みを生成したら、次の手順では、ベクトル データベースでインデックスを生成し、実行する最適な検索を決定する実験を行います。 情報取得を実験する場合は、検索インデックスの構成オプション、実行する必要のある検索の種類、再ランク付け戦略など、考慮すべき領域がいくつかあります。 この記事では、これらの 3 つのトピックについて説明します。

この記事はシリーズの一部です。 概要を参照してください。

Search index

Note

Azure AI 検索は、ファースト パーティの Azure 検索サービスです。 このセクションでは、AI 検索の詳細を説明します。 別のストアを使用している場合は、ドキュメントを参照して、そのサービスの主要な構成を確認してください。

ストア内の検索インデックスには、データ内のどのフィールドにも対応する列があります。 検索ストアでは通常、文字列、ブール値、整数、single、double、datetime などの非ベクトル データ型、および Collection(single) のような collections と Collection(single) などのベクトル データ型がサポートされています。 各列について、データ型、フィールドがフィルター可能かどうか、取得可能かどうか、検索可能かどうかなどの情報を構成する必要があります。

ベクトル フィールドに適用されるベクトル検索構成に対して下す必要のある重要な意思決定を次に示します。

  • ベクトル検索アルゴリズム - 相対的な一致を検索するために使用されるアルゴリズム。 Azure AI 検索には、"網羅的 KNN" と呼ばれるベクトル空間全体をスキャンするブルートフォース アルゴリズム オプションと、"階層ナビゲーション可能 Small World (HNSW)" と呼ばれる近似最近傍 (ANN) 検索を実行する、より効率のよいアルゴリズム オプションがあります。
  • metric - この構成は、アルゴリズムによる近似性の計算に使用される類似性メトリックです。 Azure AI 検索に用意されているオプションは、cosine、dotProduct、および Euclidean です。 Azure OpenAI 埋め込みモデルを使用している場合は、cosine を選択してください
  • efConstruction - 階層ナビゲーション可能 Small Worlds (HNSW) インデックス構築時に使用されるパラメーターで、インデックス作成中にベクトルに接続される最近傍の数を設定します。 efConstruction 値が大きいほうが、小さい値よりもインデックスの質が向上します。 ただし、値が大きくなると必要な時間、ストレージ、コンピューティングが増えます。 efConstruction は、チャンクの数が多いほど高くなり、チャンクの数が少ないほど低くなります。 最適な値の決定には、データと予想されるクエリを使用した実験が必要です。
  • efSearch - 検索時に使用される最近傍 (つまり、類似チャンク) の数を設定するためにクエリ時に使用されるパラメーター。
  • m - 双方向のリンクの数。 範囲は 4 から 10 までで、数値が小さいほど結果のノイズが少なくなります。

Azure AI 検索では、ベクトル構成は vectorSearch 構成にカプセル化されます。 ベクトル列の構成時には、そのベクトル列の適切な構成を参照して次元の数を設定します。 ベクトル列の次元属性は、選択した埋め込みモデルで生成される次元の数を表します。 たとえば、ストレージ最適化 text-embedding-3-small モデルでは 1,536 個の次元が生成されます。

検索

検索ストアに対してプロンプト オーケストレーターからクエリを実行する際には、考慮すべきオプションが多数あります。 以下のこと確認する必要があります。

  • 実行する検索の種類 (ベクトルまたはキーワードまたはハイブリッド)
  • 1 つ以上の列に対してクエリを実行するかどうか
  • キーワード クエリやベクトル検索など、複数のクエリを手動で実行するかどうか
  • クエリをサブクエリに分割する必要があるかどうか
  • クエリでフィルター処理を使用する必要があるかどうか

プロンプト オーケストレーターでは、プロンプトからのコンテキストの手がかりに基づいて、静的アプローチまたは動的アプローチを使用してアプローチを混在させることができます。 次のセクションでは、ワークロードに適したアプローチを実験するのに役立つこれらのオプションについて説明します。

種類の検索

検索プラットフォームでは通常、フルテキスト検索とベクトル検索がサポートされています。 Azure AI 検索などの一部のプラットフォームでは、ハイブリッド検索がサポートされています。 さまざまなベクトル検索オファリングの機能を確認するには、「ベクトル検索用の Azure サービスを選択する」を参照してください。

ベクトル検索での一致は、ベクトル化されたクエリ (プロンプト) フィールドとベクトル フィールドの類似性に基づきます。

重要

クエリを埋め込む前に、チャンクに対して実行したものと同じクリーニング操作を実行する必要があります。 たとえば、埋め込んだチャンク内のすべての単語を小文字にした場合は、埋め込む前にクエリのすべての単語を小文字にする必要があります。

Note

同じクエリ内の複数のベクトル フィールドに対してベクトル検索を実行できます。 Azure AI 検索では、それは技術的にハイブリッド検索になります。 詳細については、そのセクションを参照してください。

embedding = embedding_model.generate_embedding(
    chunk=str(pre_process.preprocess(query))
)

vector = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="contentVector",
    vector=embedding,
)

results = client.search(
    search_text=None,
    vector_queries=[vector],
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

サンプル コードでは、contentVector フィールドに対してベクトル検索を実行します。 クエリを埋め込むコードでは、最初にクエリが前処理されることにご注意ください。 その前処理は、埋め込む前にチャンクを前処理するコードと同じである必要があります。 埋め込みモデルは、チャンクを埋め込んだものと同じ埋め込みモデルである必要があります。

フルテキスト検索では、インデックスに格納されているプレーン テキストと一致します。 クエリからキーワードを抽出し、1 つ以上のインデックス付きの列に対するフルテキスト検索で抽出されたキーワードを使用するのが一般的な方法です。 フルテキスト検索では、任意の用語が一致するか、すべての用語が一致すると、一致を返すように構成できます。

どのフィールドに対してフルテキスト検索を実行するのが効果的かを判断するには、実験する必要があります。 エンリッチメント フェーズで説明したように、コンテンツのセマンティックな意味は似ていても、エンティティまたはキーワードが異なるシナリオでは、キーワード、およびエンティティ メタデータ フィールドは、フルテキスト検索の対象候補として検討するのに適しています。 フルテキスト検索で考慮すべきその他の一般的なフィールドは、タイトル、概要、チャンク テキストです。

formatted_search_results = []

results = client.search(
    search_text=query,
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

formatted_search_results = format_results(results)

このサンプル コードでは、タイトル、コンテンツ、および概要のフィールドに対してフルテキスト検索を実行します。

Azure AI 検索ではハイブリッド クエリがサポートされており、クエリに 1 つ以上のテキスト検索と 1 つ以上のベクトル検索を含めることができます。 プラットフォームでは、各クエリの実行、中間結果の取得、RRF (Reciprocal Rank Fusion) を使用した結果の再ランク付けが行われ、上位 N 個の結果が返されます。

 embedding = embedding_model.generate_embedding(
    chunk=str(pre_process.preprocess(query))
)
vector1 = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="contentVector",
    vector=embedding,
)
vector2 = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="questionVector",
    vector=embedding,
)

results = client.search(
    search_text=query,
    vector_queries=[vector1, vector2],
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

サンプル コードでは、タイトル、コンテンツ、および概要のフィールドに対してフルテキスト検索を実行し、contentVector フィールドと questionVector フィールドに対してベクトル検索を実行します。 Azure AI 検索プラットフォームでは、すべてのクエリが並列で実行されて結果の再ランク付けが行われ、上位 retrieve_num_of_documents 個のドキュメントが返されます。

手動マルチ

もちろん、ベクトル検索やキーワード フルテキスト検索など、複数のクエリを手動で実行することもできます。 結果を集計し、手動で結果を再ランク付けして、上位の結果を返します。 手動マルチのユース ケースを次に示します。

  • ハイブリッド検索がサポートされていない検索プラットフォームを使用している。 このオプションに従って、独自のハイブリッド検索を実行します。
  • さまざまなクエリに対してフルテキスト検索を実行する必要がある。 たとえば、クエリからキーワードを抽出し、キーワード メタデータ フィールドに対してフルテキスト検索を実行できます。 その後、エンティティを抽出し、エンティティ メタデータ フィールドに対してクエリを実行できます。
  • 再ランク付けプロセスを自分で制御する必要がある。
  • このクエリでは、複数のソースから基礎データを取得するために、複数のサブクエリを実行する必要があります。

複数のサブクエリ

一部のプロンプトは複雑で、モデルを確立するのに複数のデータ コレクションが必要です。 たとえば、"電気自動車はどのように動作し、ICE 車両と比べてどうですか?" というクエリでは、複数のソースからの基礎データが必要です。

検索を実行する前に、クエリで複数の検索が必要かどうかを判断することをお勧めします。 複数のサブクエリが必要と判断した場合は、すべてのクエリに対して手動で複数のクエリを実行できます。 大規模言語モデルを使用して、複数のサブクエリが必要かどうかを判断します。 次のプロンプトは、クエリを単純または複雑に分類するために使用される RAG 実験アクセラレータから取得されます。複雑な場合は、複数のクエリが必要になります。

Consider the given question to analyze and determine if it falls into one of these categories:
1. Simple, factual question
  a. The question is asking for a straightforward fact or piece of information
  b. The answer could likely be found stated directly in a single passage of a relevant document
  c. Breaking the question down further is unlikely to be beneficial
  Examples: "What year did World War 2 end?", "What is the capital of France?, "What is the features of productX?"
2. Complex, multi-part question
  a. The question has multiple distinct components or is asking for information about several related topics
  b. Different parts of the question would likely need to be answered by separate passages or documents
  c. Breaking the question down into sub-questions for each component would allow for better results
  d. The question is open-ended and likely to have a complex or nuanced answer
  e. Answering it may require synthesizing information from multiple sources
  f. The question may not have a single definitive answer and could warrant analysis from multiple angles
  Examples: "What were the key causes, major battles, and outcomes of the American Revolutionary War?", "How do electric cars work and how do they compare to gas-powered vehicles?"

Based on this rubric, does the given question fall under category 1 (simple) or category 2 (complex)? The output should be in strict JSON format. Ensure that the generated JSON is 100 percent structurally correct, with proper nesting, comma placement, and quotation marks. There should not be any comma after last element in the JSON.

Example output:
{
  "category": "simple"
}

大規模言語モデルを使用して、複雑なクエリからサブクエリを抽出することもできます。 次のプロンプトは、複雑なクエリを複数のサブクエリに変換する RAG 実験アクセラレータから取得されます。

Your task is to take a question as input and generate maximum 3 sub-questions that cover all aspects of the original question. The output should be in strict JSON format, with the sub-questions contained in an array.
Here are the requirements:
1. Analyze the original question and identify the key aspects or components.
2. Generate sub-questions that address each aspect of the original question.
3. Ensure that the sub-questions collectively cover the entire scope of the original question.
4. Format the output as a JSON object with a single key "questions" that contains an array of the generated sub-questions.
5. Each sub-question should be a string within the "questions" array.
6. The JSON output should be valid and strictly formatted.
7. Ensure that the generated JSON is 100 percent structurally correct, with proper nesting, comma placement, and quotation marks. The JSON should be formatted with proper indentation for readability.
8. There should not be any comma after last element in the array.

Example input question:
What are the main causes of deforestation, and how can it be mitigated?

Example output:
{
  "questions": [
    "What are the primary human activities that contribute to deforestation?",
    "How does agriculture play a role in deforestation?",
    "What is the impact of logging and timber harvesting on deforestation?",
    "How do urbanization and infrastructure development contribute to deforestation?",
    "What are the environmental consequences of deforestation?",
    "What are some effective strategies for reducing deforestation?",
    "How can reforestation and afforestation help mitigate the effects of deforestation?",
    "What role can governments and policies play in preventing deforestation?",
    "How can individuals and communities contribute to reducing deforestation?"
  ]
}

フィルター処理

フィルター可能として構成されている検索ストア内のフィールドは、クエリのフィルター処理に使用できます。 結果を絞り込めるように、これらのフィールドを使用するクエリのキーワードとエンティティをフィルター処理することを検討してください。 フィルター処理を行うと、関係のないデータが排除され、特定の条件を満たすデータのみをインデックスから取得できます。 これにより、より関連性の高い結果が得られ、クエリの全体的なパフォーマンスが向上します。 すべての意思決定と同様に、実験とテストが重要です。 クエリに、キーワードや間違ったキーワード、省略形、頭字語がない場合があります。 こうしたケースを考慮する必要があります。

再ランク付け

再ランク付けを行うと、1 つ以上のクエリを実行して結果を集計し、それらの結果をランク付けできます。 検索結果を再ランク付けする際には、次の理由を考慮してください。

  • 手動で複数の検索を実行したが、結果を集計してランク付けする必要がある。
  • ベクトル検索とキーワード検索は、常に正確とは限らない。 検索から返されるドキュメントの数を増やして、そうしなければ無視されていた可能性のある有効な結果を含めるようにし、再ランク付けを使用して結果を評価できます。

大規模言語モデルまたはクロスエンコーダーを使用すると、再ランク付けを実行できます。 Azure AI 検索などの一部のプラットフォームには、結果を再ランク付けする独自の方法があります。 シナリオに最適なものを決定するには、データについてこれらのオプションを評価します。 次のセクションではこれらの方法について詳しく説明します。

大規模言語モデルの再ランク付け

結果を再ランク付けする RAG 実験アクセラレータからの大規模言語モデル プロンプトのサンプルを次に示します。

A list of documents is shown below. Each document has a number next to it along with a summary of the document. A question is also provided.
Respond with the numbers of the documents you should consult to answer the question, in order of relevance, as well as the relevance score as json string based on json format as shown in the schema section. The relevance score is a number from 1–10 based on how relevant you think the document is to the question. The relevance score can be repetitive. Don't output any additional text or explanation or metadata apart from json string. Just output the json string and strip rest every other text. Strictly remove any last comma from the nested json elements if it's present.
Don't include any documents that are not relevant to the question. There should exactly be one documents element.
Example format:
Document 1:
content of document 1
Document 2:
content of document 2
Document 3:
content of document 3
Document 4:
content of document 4
Document 5:
content of document 5
Document 6:
content of document 6
Question: user defined question

schema:
{
    "documents": {
        "document_1": "Relevance",
        "document_2": "Relevance"
    }
}

クロスエンコーダーの再ランク付け

RAG 実験アクセラレータの次の例では、Hugging Face で提供される CrossEncoder を使用して、Roberta モデルを読み込みます。 次に、各チャンクを反復処理し、モデルを使用して類似性を計算したら、値を割り当てます。 結果を並べ替え、上位 N 個を返します。

from sentence_transformers import CrossEncoder
...

model_name = 'cross-encoder/stsb-roberta-base'
model = CrossEncoder(model_name)

cross_scores_ques = model.predict(
    [[user_prompt, item] for item in documents],
    apply_softmax=True,
    convert_to_numpy=True,
)

top_indices_ques = cross_scores_ques.argsort()[-k:][::-1]
sub_context = []
for idx in list(top_indices_ques):
    sub_context.append(documents[idx])

セマンティック ランク付け

Azure AI 検索には、セマンティック ランク付けと呼ばれる独自の機能があります。 この機能では、意味的に最も関連性の高い結果のレベルを上げる、Microsoft Bing から採用されたディープ ラーニング モデルを使用します。 セマンティック ランカーのしくみについては、次を参照してください。

検索ガイダンス

検索ソリューションを実装するときは、次の一般的なガイダンスを考慮してください。

  • タイトル、概要、ソース、生のコンテンツ (クリーニングされていない) は、検索から返される適切なフィールドです。
  • クエリをサブクエリに分割する必要があるかどうかを、前もって判断します。
  • 一般に、複数のフィールドに対して、ベクトル クエリとテキスト クエリの両方のクエリを実行することをお勧めします。 クエリを受け取った時点では、ベクトル検索とテキスト検索のどちらが適切なのかはわかりません。 さらに、ベクトル検索またはキーワード検索がどのフィールドを検索するのに適しているかもわかりません。 複数のフィールドを (場合によっては複数のクエリを使用して) 検索し、結果を再ランク付けして、最高のスコアを持つ結果を返すことができます。
  • キーワードとエンティティのフィールドは、フィルター処理を検討する対象候補に適しています。
  • ベクトル検索と共にキーワードを使用することをお勧めします。 キーワードを使って、結果をより小さなサブセットにフィルター処理します。 ベクトル ストアはそのサブセットに対して動作し、最適な一致を見つけます。

検索評価

準備フェーズでは、テスト ドキュメント情報と共にテスト クエリを収集しておく必要があります。 そのフェーズで収集した次の情報を使用して、検索結果を評価できます。

  • クエリ - サンプル クエリ
  • コンテキスト - サンプル クエリに対処するテスト ドキュメント内のすべてのテキストのコレクション

検索ソリューションの評価に使用できる、確立された 3 つの取得評価方法を次に示します。

  • K での精度 - 検索結果全体のうち、正しく識別された関連項目の割合。 このメトリックは、検索結果の精度に焦点を当てています。
  • K でのリコール - "K でのリコール" は、考えられる関連項目の合計のうち、上位 K に該当する関連項目の割合を測定します。 このメトリックは、検索結果の範囲に焦点を当てています。
  • MRR (Mean Reciprocal Rank) - MRR は、ランク付けされた検索結果の関連性の高い最初の回答の関係ランクの平均を測定します。 このメトリックは、検索結果で関連性の高い結果が最初に発生する場所に焦点を当てています。

肯定的な例と否定的な例の両方をテストする必要があります。 肯定的な例では、メトリックを可能な限り 1 に近づける必要があります。 データでクエリに対処するべきではない否定的な例では、メトリックを可能な限り 0 に近づける必要があります。 すべてのテスト クエリをテストし、肯定的なクエリ結果と否定的なクエリ結果を平均して、検索結果が全体として、どのように機能しているかを理解する必要があります。

次のステップ