REST を使用してナレッジ ストアを作成する
Azure AI Search では、 ナレッジ ストア は、検索以外のシナリオで使用される AI によって生成されたコンテンツ のリポジトリです。 インデクサーとスキルセットを使用してナレッジ ストアを作成し、出力を保存する Azure Storage を指定します。 ナレッジ ストアにデータが取り込まれた後は、Storage Explorer や Power BI などのツールを使用してコンテンツを探索します。
この記事では、REST API を使用して、ナレッジ ストアにホテル宿泊の一連の顧客レビューを取り込み、エンリッチし、探索します。 ナレッジ ストアは、ソースから取得された元のテキスト コンテンツと AI によって生成されたコンテンツ (センチメント スコア、キー フレーズ抽出、言語検出、および非英語圏の顧客によるコメントのテキスト翻訳が含まれている) を含んでいます。
初期データ セットを使用できるようにするため、最初にホテルのレビューが Azure Blob Storage にインポートされます。 後処理で、結果が Azure Table Storage にナレッジ ストアとして保存されます。
ヒント
この記事では、REST を使用して各手順について詳しく説明します。 コマンドを実行するだけの場合は、REST ファイルをダウンロードします。 または、Azure portal でナレッジ ストアを作成することもできます。
前提条件
REST クライアントを使用する Visual Studio Code。 開始するための支援が必要な場合は、「クイック スタート: REST を使用したテキスト検索」を参照してください。
Azure AI Cognitive Search。 サービスを作成するか、既存のサービスを検索します。 この演習では、無料のサービスを使用できます。
Azure Storage です。 アカウントを作成するか、既存のアカウントを検索します。 アカウントの種類は、 [StorageV2 (general purpose V2)](StorageV2 (汎用 V2)) であることが必要です。
この例のスキルセットでは、エンリッチメントに Azure AI サービスを使用します。 ワークロードは非常に小さいので、1 日に最大 20 トランザクションの処理を無料で使うことができる Azure AI サービスを内部で利用しています。 ワークロードが小さいということは、Azure AI マルチサービス リソースの作成またはアタッチをスキップできることを意味します。
Azure Storage にデータをアップロードして接続文字列を取得する
HotelReviews_Free.csv をダウンロードします。 この CSV には、1 つのホテルに関する 19 個のお客様のフィードバックが含まれています (ソースは Kaggle.com)。
Azure portal でお使いのストレージ アカウントを探し、ストレージ ブラウザーを使用して hotel-reviews という名前の BLOB コンテナーを作成します。
ページの上部にある [アップロード] を選択して、前の手順でダウンロードした HotelReviews-Free.csv ファイルを読み込みます。
左側で、[アクセス キー] を選択し、[キーの表示] を選択し、key1 または key2 の接続文字列をコピーします。 フル アクセス接続文字列は次のような形式です。
"knowledgeStore": {
"storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<YOUR-ACCOUNT-NAME>;AccountKey=<YOUR-ACCOUNT-KEY>;EndpointSuffix=core.windows.net;"
}
Note
接続文字列の機密データを提供したくない場合は、「マネージド ID を使用して接続する」を参照してください。
キーと URL をコピーする
この例では、REST 呼び出しが検索サービス エンドポイントを必要とし、すべての要求で API キーを使用します。 これらの値は Azure portal から取得できます。
Azure portal にサインインし、[概要] ページに移動して URL をコピーします。 たとえば、エンドポイントは
https://mydemo.search.windows.net
のようになります。[設定]>[キー] で管理者キーをコピーします。 管理者キーは、オブジェクトの追加、変更、削除で使用します。 2 つの交換可能な管理者キーがあります。 どちらかをコピーします。
有効な API キーにより、要求を送信するアプリケーションとそれを処理する検索サービスとの間で、要求ごとに信頼が確立されます。
インデックスを作成する
[インデックスを作成する (REST)]: 検索サービスに検索インデックスを作成します。 検索インデックスはナレッジ ストアとは無関係ですが、これはインデクサーに必要です。 検索インデックスにはナレッジ ストアと同じコンテンツが含まれており、これは、クエリ要求を送信して調べることができます。
Visual Studio Code で新しいテキスト ファイルを開きます。
事前に収集した検索エンドポイントと API キーに変数を設定します。
@baseUrl = PUT-YOUR-SEARCH-SERVICE-URL-HERE @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE @storageConnection = PUT-YOUR-STORAGE-CONNECTION-STRING-HERE @blobContainer = PUT-YOUR-CONTAINER-NAME-HERE (hotel-reviews)
.rest
ファイル拡張子でファイルを保存します。次の例を貼り付けて、インデックス要求を作成します。
### Create a new index POST {{baseUrl}}/indexes?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "hotel-reviews-kstore-idx", "fields": [ { "name": "name", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false }, { "name": "reviews_date", "type": "Edm.DateTimeOffset", "searchable": false, "filterable": false, "sortable": false, "facetable": false }, { "name": "reviews_rating", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false }, { "name": "reviews_text", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false }, { "name": "reviews_title", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false }, { "name": "reviews_username", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false }, { "name": "AzureSearch_DocumentKey", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false, "key": true }, { "name": "language", "type": "Edm.String", "filterable": true, "sortable": false, "facetable": true }, { "name": "translated_text", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false }, { "name": "sentiment", "type": "Collection(Edm.String)", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true }, { "name": "keyphrases", "type": "Collection(Edm.String)", "filterable": true, "sortable": false, "facetable": true } ] }
[要求の送信] をクリックします。
HTTP/1.1 201 Created
応答が返され、その応答本文にはインデックス スキーマの JSON 表現が含まれているはずです。
データ ソースを作成する
[データ ソースの作成]。Azure AI 検索にデータ ソース接続を作成します。
次の例を貼り付けて、データ ソースを作成します。
### Create a data source POST {{baseUrl}}/datasources?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "hotel-reviews-kstore-ds", "description": null, "type": "azureblob", "subtype": null, "credentials": { "connectionString": "{{storageConnectionString}}" }, "container": { "name": "{{blobContainer}}", "query": null }, "dataChangeDetectionPolicy": null, "dataDeletionDetectionPolicy": null }
[要求の送信] をクリックします。
スキルセットを作成する
スキルセットにより、エンリッチメント (スキル) とナレッジ ストアが定義されます。 [スキルセットの作成]: 検索サービスにオブジェクトを作成します。
次の例を貼り付けて、スキルセットを作成します。
### Create a skillset POST {{baseUrl}}/skillsets?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "hotel-reviews-kstore-ss", "description": "Skillset to detect language, translate text, extract key phrases, and score sentiment", "skills": [ { "@odata.type": "#Microsoft.Skills.Text.SplitSkill", "context": "/document/reviews_text", "textSplitMode": "pages", "maximumPageLength": 5000, "inputs": [ { "name": "text", "source": "/document/reviews_text" } ], "outputs": [ { "name": "textItems", "targetName": "pages" } ] }, { "@odata.type": "#Microsoft.Skills.Text.V3.SentimentSkill", "context": "/document/reviews_text/pages/*", "inputs": [ { "name": "text", "source": "/document/reviews_text/pages/*" }, { "name": "languageCode", "source": "/document/language" } ], "outputs": [ { "name": "sentiment", "targetName": "sentiment" } ] }, { "@odata.type": "#Microsoft.Skills.Text.LanguageDetectionSkill", "context": "/document", "inputs": [ { "name": "text", "source": "/document/reviews_text" } ], "outputs": [ { "name": "languageCode", "targetName": "language" } ] }, { "@odata.type": "#Microsoft.Skills.Text.TranslationSkill", "context": "/document/reviews_text/pages/*", "defaultFromLanguageCode": null, "defaultToLanguageCode": "en", "inputs": [ { "name": "text", "source": "/document/reviews_text/pages/*" } ], "outputs": [ { "name": "translatedText", "targetName": "translated_text" } ] }, { "@odata.type": "#Microsoft.Skills.Text.KeyPhraseExtractionSkill", "context": "/document/reviews_text/pages/*", "inputs": [ { "name": "text", "source": "/document/reviews_text/pages/*" }, { "name": "languageCode", "source": "/document/language" } ], "outputs": [ { "name": "keyPhrases" , "targetName": "keyphrases" } ] }, { "@odata.type": "#Microsoft.Skills.Util.ShaperSkill", "context": "/document", "inputs": [ { "name": "name", "source": "/document/name" }, { "name": "reviews_date", "source": "/document/reviews_date" }, { "name": "reviews_rating", "source": "/document/reviews_rating" }, { "name": "reviews_text", "source": "/document/reviews_text" }, { "name": "reviews_title", "source": "/document/reviews_title" }, { "name": "reviews_username", "source": "/document/reviews_username" }, { "name": "AzureSearch_DocumentKey", "source": "/document/AzureSearch_DocumentKey" }, { "name": "pages", "sourceContext": "/document/reviews_text/pages/*", "inputs": [ { "name": "languageCode", "source": "/document/language" }, { "name": "translatedText", "source": "/document/reviews_text/pages/*/translated_text" }, { "name": "sentiment", "source": "/document/reviews_text/pages/*/sentiment" }, { "name": "keyPhrases", "source": "/document/reviews_text/pages/*/keyphrases/*" }, { "name": "Page", "source": "/document/reviews_text/pages/*" } ] } ], "outputs": [ { "name": "output" , "targetName": "tableprojection" } ] } ], "knowledgeStore": { "storageConnectionString": "{{storageConnectionString}}", "projections": [ { "tables": [ { "tableName": "hotelReviews1Document", "generatedKeyName": "Documentid", "source": "/document/tableprojection" }, { "tableName": "hotelReviews2Pages", "generatedKeyName": "Pagesid", "source": "/document/tableprojection/pages/*" }, { "tableName": "hotelReviews3KeyPhrases", "generatedKeyName": "KeyPhrasesid", "source": "/document/tableprojection/pages/*/keyPhrases/*" } ], "objects": [] }, { "tables": [ { "tableName": "hotelReviews4InlineProjectionDocument", "generatedKeyName": "Documentid", "sourceContext": "/document", "inputs": [ { "name": "name", "source": "/document/name"}, { "name": "reviews_date", "source": "/document/reviews_date"}, { "name": "reviews_rating", "source": "/document/reviews_rating"}, { "name": "reviews_username", "source": "/document/reviews_username"}, { "name": "reviews_title", "source": "/document/reviews_title"}, { "name": "reviews_text", "source": "/document/reviews_text"}, { "name": "AzureSearch_DocumentKey", "source": "/document/AzureSearch_DocumentKey" } ] }, { "tableName": "hotelReviews5InlineProjectionPages", "generatedKeyName": "Pagesid", "sourceContext": "/document/reviews_text/pages/*", "inputs": [ { "name": "Sentiment", "source": "/document/reviews_text/pages/*/sentiment"}, { "name": "LanguageCode", "source": "/document/language"}, { "name": "Keyphrases", "source": "/document/reviews_text/pages/*/keyphrases"}, { "name": "TranslatedText", "source": "/document/reviews_text/pages/*/translated_text"}, { "name": "Page", "source": "/document/reviews_text/pages/*" } ] }, { "tableName": "hotelReviews6InlineProjectionKeyPhrases", "generatedKeyName": "kpidv2", "sourceContext": "/document/reviews_text/pages/*/keyphrases/*", "inputs": [ { "name": "Keyphrases", "source": "/document/reviews_text/pages/*/keyphrases/*" } ] } ], "objects": [] } ] } }
重要なポイント:
Shaper スキルは、ナレッジ ストアの定義にとって重要です。 ナレッジ ストアのテーブルにデータがどのように流れるかを指定します。 入力は、格納するエンリッチされたドキュメントの部分です。 出力は、ノードを 1 つの構造に統合したものです。
プロジェクションは、ナレッジ ストアのテーブル、オブジェクト、BLOB を指定します。 各プロジェクション項目は、Azure Storage で作成する列またはフィールドの
"name"
を指定します。"source"
は、シェーパー出力のどの部分が、そのフィールドまたは列に割り当てられるかを指定します。
インデクサーの作成
[インデクサーの作成]: インデクサーを作成して実行します。 インデクサーの実行は、まず、ドキュメントを解読し、テキストと画像を抽出し、スキルセットを初期化して開始します。 インデクサーは、作成された他のオブジェクト (データソース、インデックス、スキルセット) をチェックします。
次の例を貼り付けて、インデクサーを作成します。
### Create indexer POST {{baseUrl}}/indexers?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "hotel-reviews-kstore-idxr", "dataSourceName": "hotel-reviews-kstore-ds", "skillsetName": "hotel-reviews-kstore-ss", "targetIndexName": "hotel-reviews-kstore-idx", "parameters": { "configuration": { "dataToExtract": "contentAndMetadata", "parsingMode": "delimitedText", "firstLineContainsHeaders": true, "delimitedTextDelimiter": "," } }, "fieldMappings": [ { "sourceFieldName": "AzureSearch_DocumentKey", "targetFieldName": "AzureSearch_DocumentKey", "mappingFunction": { "name": "base64Encode" } } ], "outputFieldMappings": [ { "sourceFieldName": "/document/reviews_text/pages/*/Keyphrases/*", "targetFieldName": "Keyphrases" }, { "sourceFieldName": "/document/Language", "targetFieldName": "Language" }, { "sourceFieldName": "/document/reviews_text/pages/*/Sentiment", "targetFieldName": "Sentiment" } ] }
[要求の送信] を選択して、インデクサーを実行します。 この手順は、完了するまでに数分かかります。
重要なポイント:
parameters/configuration
オブジェクトでは、インデクサーがデータを取り込む方法を制御します。 ここでは、入力データは、ヘッダー行とコンマ区切り値がある単一の CSV ファイルに含まれています。"AzureSearch_DocumentKey" は、(メタデータ ストレージ パスに基づいて) BLOB インデクサーによって生成される各ドキュメントの一意の識別子です。
出力フィールド マッピングでは、エンリッチされたフィールドが、検索インデックス内のフィールドにマップされる方法を指定します。 出力フィールド マッピングは、ナレッジ ストアでは使用されません (ナレッジ ストアでは、物理的なデータ構造を表すためにシェイプとプロジェクションが使用されます)。
状態の確認
各要求を送信すると、検索サービスは 201 成功メッセージで応答します。
### Get Indexer Status (wait several minutes for the indexer to complete)
GET {{baseUrl}}/indexers/hotel-reviews-kstore-idxr/status?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
数分後に、インデックスに対してクエリを実行して内容を検査できます。 インデックスを使用していない場合でも、この手順は、スキルセットが想定される出力を生成したことを確認するのに便利な方法です。
### Query the index (indexer status must be "success" before querying the index)
POST {{baseUrl}}/indexes/hotel-reviews-kstore-idxr/docs/search?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"search": "*",
"select": "reviews_title, reviews_username, language, translated_text, sentiment",
"count": true
}
Azure portal でテーブルを確認する
Azure portal で Azure Storage アカウントに切り替え、ストレージ ブラウザーを使用して新しいテーブルを表示します。 スキルセットに定義されているプロジェクションごとに 1 つずつ、6 つのテーブルが表示されます。
各テーブルは、クエリ内のテーブルをクロスリンクするために必要な ID を使用して生成されます。 テーブルを開いたときに、これらのフィールドの下までスクロールして、パイプラインによって追加されたコンテンツ フィールドを表示します。
このチュートリアルでは、ナレッジ ストアは、テーブルのさまざまな整形と構造化方法を示すさまざまなテーブルで構成されています。 テーブル 1 から 3 は、Shaper スキルの出力を使用して列と行を決定します。 テーブル 4 から 6 は、プロジェクション自体に埋め込まれたインライン整形命令から作成されます。 どちらの方法を使用しても、同じ結果を得られます。
テーブル | 説明 |
---|---|
hotelReviews1Document |
CSV から引き継がれたフィールド (reviews_date や reviews_text など) が含まれます。 |
hotelReviews2Pages |
スキルセットによって作成された、エンリッチされたフィールド (センチメント スコアや翻訳されたテキストなど) が含まれます。 |
hotelReviews3KeyPhrases |
キー フレーズのみの長い一覧が含まれます。 |
hotelReviews4InlineProjectionDocument |
最初のテーブルの代わりに、Shaper スキルではなくインライン整形を使用して、プロジェクションのデータを整形します。 |
hotelReviews5InlineProjectionPages |
2 番目のテーブルの代わりに、インライン整形を使用します。 |
hotelreviews6InlineProjectionKeyPhrases |
3 番目のテーブルの代わりに、インライン整形を使用します。 |
クリーンアップ
独自のサブスクリプションを使用している場合は、プロジェクトの最後に、作成したリソースがまだ必要かどうかを確認してください。 リソースを実行したままにすると、お金がかかる場合があります。 リソースは個別に削除することも、リソース グループを削除してリソースのセット全体を削除することもできます。
ポータルの左側のナビゲーション ウィンドウにある [すべてのリソース] または [リソース グループ] リンクを使って、リソースを検索および管理できます。
次のステップ
Azure AI サービスを使用してデータをエンリッチし、その結果をナレッジ ストアに投影したので、Storage Explorer や他のアプリを使用して、エンリッチしたデータ セットを探索できます。