Azure AI Search での取得拡張生成 (RAG)

取得拡張生成 (RAG) は、グラウンディング データを提供する情報取得システムを追加することで、ChatGPT などの大規模言語モデル (LLM) の機能を拡張するアーキテクチャです。 情報取得システムを追加すると、応答を作成するときに LLM によって使用されるグラウンディング データを制御できます。 エンタープライズ ソリューションの場合、RAG アーキテクチャは、ベクトル化されたドキュメントや画像、およびそのコンテンツの埋め込みモデルがある場合は、その他のデータ形式から取得された "エンタープライズ コンテンツ" に生成 AI を制限できることを意味します。

どの情報取得システムを使用するかによって LLM への入力が決定されるため、この決定は重要です。 情報取得システムは、次の情報を提供する必要があります。

  • 必要な頻度で、すべてのコンテンツに対して、大規模に読み込んで更新するインデックス作成戦略。

  • クエリ機能と関連性のチューニング。 システムは、関連する結果を、LLM 入力のトークンの長さの要件を満たすのに必要な短い形式で返す必要があります。

  • データと操作の両方のセキュリティ、グローバル展開、信頼性。

  • インデックス作成用の埋め込みモデル、および取得のためのチャット モデルまたは言語理解モデルとの統合。

Azure AI Search は、RAG アーキテクチャにおける 情報取得のための実証済みのソリューション です。 Azure クラウドのインフラストラクチャとセキュリティを備えたインデックス作成とクエリ機能を提供します。 コードやその他のコンポーネントを使用して、財産的価値のあるコンテンツに対する生成 AI のすべての要素を含む包括的な RAG ソリューションを設計できます。

Note

Copilot と RAG の概念は初めてですか? 「ベクトル検索と、生成 AI アプリの最新の取得」をご覧ください。

Microsoft は、RAG ソリューションで Azure AI Search を使用するためのいくつかの組み込み実装を用意しています。

キュレーションされたアプローチを使用すると、簡単に作業を開始できますが、アーキテクチャをより詳細に制御するには、カスタム ソリューションが必要です。 これらのテンプレートでは、以下でエンド ツー エンドのソリューションが作成されます。

この記事の残りの部分では、Azure AI Search がカスタム RAG ソリューションにどのように適合するかについて説明します。

パターンの大まかな概要は次のとおりです。

  • ユーザーの質問または要求 (プロンプト) から始めます。
  • Azure AI Search に送信して、関連情報を見つけます。
  • 上位の検索結果を LLM に送信します。
  • LLM の自然言語理解と推論機能を使用して、最初のプロンプトに対する応答を生成します。

Azure AI Search が LLM プロンプトに入力を提供しますが、モデルのトレーニングはしません。 RAG アーキテクチャでは、追加のトレーニングはありません。 LLM はパブリック データを使用して事前トレーニングされますが、取得コンポーネントからの情報によって拡張された応答を生成します。

Azure AI Search を含む RAG パターンには、次の図に示す要素があります。

検索と ChatGPT を使用した情報取得のアーキテクチャ図。

  • ユーザー エクスペリエンスのためのアプリ UX (Web アプリ)
  • アプリ サーバーまたはオーケストレーター (統合と調整レイヤー)
  • Azure AI Search (情報取得システム)
  • Azure OpenAI (生成 AI 用の LLM)

Web アプリはユーザー エクスペリエンスを提供し、プレゼンテーション、コンテキスト、ユーザー操作を提供します。 ユーザーからの質問またはプロンプトは、ここから始まります。 入力は統合レイヤーを通過します。最初に情報を取得して検索結果を取得しますが、さらに LLM に移動してコンテキストと意図を設定します。

アプリ サーバーまたはオーケストレーターは、情報の取得と LLM の間のハンドオフを調整する統合コードです。 1 つのオプションは、LangChain を使用してワークフローを調整することです。 LangChain は Azure AI Search と統合されるため、Azure AI Search を 取得コンポーネント としてワークフローに簡単に含めることができます。 セマンティック カーネルも別のオプションです。

情報取得システムは、検索可能なインデックス、クエリ ロジック、ペイロード (クエリ応答) を提供します。 検索インデックスには、ベクトルまたはベクトル以外のコンテンツを含めることができます。 ほとんどのサンプルとデモにはベクトル フィールドが含まれていますが、必須ではありません。 クエリは、キーワード (または用語) とベクトル クエリを処理できる Azure AI Search の既存の検索エンジンを使用して実行されます。 インデックスは、定義したスキーマに基づいて事前に作成され、ファイル、データベース、またはストレージからソース化されたコンテンツと共に読み込まれます。

LLM は、元のプロンプトに加えて、Azure AI Search からの結果を受け取ります。 LLM は結果を分析し、応答を作成します。 LLM が ChatGPT の場合、ユーザーの対話は会話のやり取りである可能性があります。 Davinci を使用している場合、プロンプトは完全に構成された回答である可能性があります。 Azure ソリューションでは Azure OpenAI が使用される可能性が最も高いですが、この特定のサービスに対するハードな依存関係はありません。

Azure AI 検索では、プロンプト フローやチャットの保持のためのネイティブ LLM 統合は提供されないため、オーケストレーションと状態を処理するコードを記述する必要があります。 完全なソリューションに必要なブループリントについては、デモ ソース (Azure-Samples/azure-search-openai-demo) を確認できます。 また、LLM と統合する RAG ベースの Azure AI 検索ソリューションを作成するには、Azure AI Studio または Azure OpenAI Studio を使用することをお勧めします。

Azure AI Search では、検索可能なすべてのコンテンツは、検索サービスでホストされている検索インデックスに格納されます。 検索インデックスは、応答時間がミリ秒レベルの高速なクエリを実現するために設計されているため、内部データ構造はその目標をサポートするために存在します。 そのため、検索インデックスにはインデックス付きコンテンツが保存されます。コンテンツ ファイル全体 (PDF 全体や画像など) は保存されません。 内部では、データ構造にはトークン化されたテキストの逆インデックス、埋め込み用のベクトル インデックス、逐語的一致が必要な場合 (フィルター、あいまい検索、正規表現クエリなど) の変更されていないテキストが含まれます。

RAG ソリューションのデータを設定するときは、Azure AI Search でインデックスを作成して読み込む機能を使用します。 インデックスには、ソース コンテンツを複製または表すフィールドが含まれます。 インデックス フィールドは単純な転送 (ソース ドキュメントのタイトルまたは説明が検索インデックスのタイトルまたは説明になる) であるか、画像の表現またはテキストの説明を生成するベクトル化やスキル処理などの外部プロセスの出力を含む場合があります。

検索するコンテンツの種類をご存知のことと思われるので、各コンテンツ タイプに適用できるインデックス作成機能を検討します。

コンテンツ タイプ 付けられたインデックス 機能
text トークン、変更されていないテキスト インデクサーは、Azure Storage や Cosmos DB などの他の Azure リソースからプレーンテキストをプルできます。 インデックスに任意の JSON コンテンツをプッシュすることもできます。 処理中のテキストを変更するには、アナライザーノーマライザーを使用して、インデックス作成中に字句処理を追加します。 同意語マップは、クエリで使用される可能性のある用語がソース ドキュメントにない場合に便利です。
text ベクトル 1 テキストは、インデクサー パイプラインでチャンク化してベクトル化することも、外部で処理してから、インデックス内のベクトル フィールドとしてインデックス化することもできます。
image トークン、変更されていないテキスト 2 OCR と画像解析のスキルでは、テキスト認識やイメージ特性のために画像を処理できます。 画像情報は検索可能なテキストに変換され、インデックスに追加されます。 スキルにはインデクサーの要件があります。
image ベクトル 1 画像は、インデクサ- パイプラインでベクトル化することも、画像コンテンツの数学的表現を行うために外部処理してから、インデックス内のベクトル フィールドとしてインデックス化することもできます。 Azure AI Vision マルチモーダルまたは、OpenAI CLIP などのオープン ソース モデルを使用すると、同じ埋め込み空間内のテキストと画像をベクトル化できます。

1 Azure AI Search では、 統合されたデータのチャンク化とベクトル化が可能ですが、インデクサーとスキルセットへの依存が必要です。 インデクサーを使用できない場合は、Microsoft の Semantic Kernel またはその他のコミュニティ オファリングがフル スタック ソリューションに役立ちます。 両方のアプローチを示すコード サンプルについては、azure-search-vector リポジトリを参照してください。

2スキルは、 応用 AIの組み込みサポートです。 OCR と画像分析の場合、インデックス作成パイプラインは Azure AI Vision API の内部呼び出しを行います。 これらのスキルは、抽出された画像を処理のために Azure AI に渡し、Azure AI Search によってインデックス付けされたテキストとして出力を 受け取ります。 スキルは、統合データ チャンク (テキスト分割スキル) と統合埋め込み (Azure AI Vision マルチモーダル、Azure OpenAI、Azure AI Studio モデル カタログ内のモデルを呼び出すスキル) でも使用します。

ベクトルは、異なるコンテンツ (複数のファイル形式と言語) に最適な設備を提供します。これは、コンテンツが数学表現で汎用的に表現されるためです。 また、ベクトルでは類似性検索もサポートされています。つまり、ベクトル クエリに最も似た座標で照合します。 トークン化された用語で照合するキーワード検索 (または用語検索) と比較すると、類似性検索の方が微妙です。 コンテンツまたはクエリにあいまいな点や解釈の要件がある場合は、より適切な選択肢です。

データが検索インデックスに格納されたら、Azure AI Search のクエリ機能を使用してコンテンツを取得します。

RAG 以外のパターンでは、クエリは検索クライアントからラウンド トリップを行います。 クエリが送信され、検索エンジンで実行され、応答がクライアント アプリケーションに返されます。 応答 (検索結果) は、インデックス内で見つかった逐語的なコンテンツのみで構成されます。

RAG パターンでは、検索エンジンと LLM の間でクエリと応答が調整されます。 ユーザーの質問またはクエリは、検索エンジンと LLM の両方にプロンプトとして転送されます。 検索結果は検索エンジンから戻り、LLM にリダイレクトされます。 ユーザーに返される応答は生成 AI で、LLM からの合計または回答のどちらかです。

Azure AI Search には、新しい回答を構成するクエリの種類はありません (セマンティック検索やベクトル検索でさえも)。 LLM だけが生成 AI を提供します。 クエリの作成に使用される Azure AI Search の機能を次に示します。

クエリ機能 目的 使用する理由
単純または完全な Lucene 構文 テキストと非ベクトル数値コンテンツに対するクエリ実行 フルテキスト検索は、類似一致ではなく、完全一致に最適です。 フルテキスト検索クエリは、BM25 アルゴリズムを使用してランク付けされ、スコアリング プロファイルによる関連性チューニングをサポートします。 また、フィルターとファセットもサポートされています。
フィルターファセット テキストまたは数値 (非ベクトル) フィールドにのみ適用されます。 包含条件または除外条件に基づいて検索対象領域を減らします。 クエリに精度を追加します。
セマンティック ランク付け セマンティック モデルを使用して BM25 結果セットを再ランク付けします。 LLM 入力として役立つ短い形式のキャプションと回答を生成します。 スコアリング プロファイルよりも簡単で、コンテンツによっては、関連性チューニングのためのより信頼性の高い手法です。
ベクトル検索 クエリ文字列が 1 つ以上のベクトルである類似性検索のベクトル フィールドに対するクエリ実行。 ベクトルは、あらゆる種類のコンテンツを任意の言語で表すことができます。
ハイブリッド検索 上記のクエリ手法の一部またはすべてを組み合わせます。 ベクトルおよびと非ベクトル クエリは並列で実行され、統合された結果セットで返されます。 ハイブリッド クエリを使用した場合、精度とリコールにおけるメリットが最も多くなります。

クエリ応答を構造化する

クエリの応答は LLM に入力を提供するため、検索結果の品質は成功に不可欠です。 結果は表形式の行セットです。 結果の構成や構造は次に依存します。

  • 応答に含まれるインデックスの部分を決定するフィールド。
  • インデックスにおける一致を示す行。

フィールドは、属性が "取得可能" である場合に検索結果に表示されます。 インデックス スキーマ内のフィールド定義には属性があり、これがフィールドが応答で使用されるかどうかを決定します。 "取得可能" フィールドだけがフル テキスト クエリまたはベクトル クエリ結果で返されます。 既定では、すべての "取得可能" フィールドが返されますが、"選択" を使用してサブセットを指定できます。 "取得可能" 以外に、フィールドに制限はありません。 フィールドには、任意の長さまたは型を指定できます。 長さについて、Azure AI Search にはフィールド長の上限はありませんが、API 要求のサイズには制限があります。

行ではクエリとの一致が、関連性、類似性、またはその両方でランク付けされます。 既定では、結果はフル テキスト検索の場合は上位 50 件、ベクトル検索の場合は K ニアレスト ネイバーに制限されます。 既定値を変更して制限を (最大 1000 ドキュメントまで) 増減できます。 top および skip ページング パラメーターを使用して、結果を一連のページングされた結果として取得することもできます。

関連性と再現性を最大化する

複雑なプロセスや大量のデータを処理する場合や、ミリ秒レベルの応答が期待されている場合、各ステップで価値を高め、最終的な結果の品質を向上させることが重要です。 情報取得側において、関連性のチューニングは、LLM に送信される結果の品質を向上させるアクティビティです。 結果には、最も関連性の高い、または最も類似した一致するドキュメントだけを含める必要があります。

関連性と再現性を最大化するためのヒントを紹介します。

  • 入力が同じ場合、キーワード (nonvector) 検索とベクトル検索を組み合わせたハイブリッド クエリで最大の再現性が得られます。 ハイブリッド クエリでは、同じ入力を 2 倍にした場合、テキスト文字列とそのベクトルに相当する入力により、キーワードと類似性検索に対して並列クエリが生成され、統合された結果セット内の各クエリの種類から最も関連性の高い一致が返されます。

  • ハイブリッド クエリは、拡張することもできます。 詳細なチャンク コンテンツに対して類似性検索を実行し、名前に対するキーワード検索をすべて同じ要求で実行できます。

  • 関連性の調整は、次の方法でサポートされます。

比較テストおよびベンチマーク テストでは、テキストフィールドとベクトル フィールドを含むハイブリッド クエリにセマンティック ランク付けを補足することで、最も関連性の高い結果が生成されます。

RAG ワークフローのコード例

次の Python コードは、Azure AI Search での RAG ワークフローの重要なコンポーネントを示しています。 クライアントを設定し、システム プロンプトを定義し、クエリを指定する必要があります。 プロンプトは、クエリからの結果のみを使用することおよび、結果を返す方法を LLM に指示します。 この例に基づくその他の手順については、こちらの「RAG クイック スタート」を参照してください。

# Set up the query for generating responses
from azure.identity import DefaultAzureCredential
from azure.identity import get_bearer_token_provider
from azure.search.documents import SearchClient
from openai import AzureOpenAI

credential = DefaultAzureCredential()
token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")
openai_client = AzureOpenAI(
    api_version="2024-06-01",
    azure_endpoint=AZURE_OPENAI_ACCOUNT,
    azure_ad_token_provider=token_provider
)

search_client = SearchClient(
    endpoint=AZURE_SEARCH_SERVICE,
    index_name="hotels-sample-index",
    credential=credential
)

# This prompt provides instructions to the model. 
# The prompt includes the query and the source, which are specified further down in the code.
GROUNDED_PROMPT="""
You are a friendly assistant that recommends hotels based on activities and amenities.
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
Answer ONLY with the facts listed in the list of sources below.
If there isn't enough information below, say you don't know.
Do not generate answers that don't use the sources below.
Query: {query}
Sources:\n{sources}
"""

# The query is sent to the search engine, but it's also passed in the prompt
query="Can you recommend a few hotels near the ocean with beach access and good views"

# Retrieve the selected fields from the search index related to the question
search_results = search_client.search(
    search_text=query,
    top=5,
    select="Description,HotelName,Tags"
)
sources_formatted = "\n".join([f'{document["HotelName"]}:{document["Description"]}:{document["Tags"]}' for document in search_results])

response = openai_client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
        }
    ],
    model="gpt-35"
)

print(response.choices[0].message.content)

統合コードと LLM

Azure AI Search を含む RAG ソリューションでは、組み込みのデータ チャンク機能とベクトル化機能を利用できます。また、セマンティック カーネル、LangChain、LlamaIndex などのプラットフォームを使用して独自のものを構築することもできます。

デモ リポジトリのノートブック は LLM 統合のパターンを示しているため、始めるのに最適です。 RAG ソリューションのコードの大部分は LLM の呼び出しで構成されているため、この記事では扱っていませんが、これらの API のしくみを理解する必要があります。

ファースト ステップ

Note

一部の Azure AI Search 機能は人による操作を目的としており、RAG パターンでは役に立ちません。 具体的には、オートコンプリートと候補をスキップできます。 ファセットや orderby などの他の機能は役立つ可能性がありますが、RAG シナリオでは一般的ではありません。

関連項目