Azure AI 検索で Markdown BLOB とファイルにインデックスを作成する
Note
現在、この機能はパブリック プレビュー段階にあります。 このプレビュー版はサービス レベル アグリーメントなしで提供されています。運用環境のワークロードに使用することはお勧めできません。 特定の機能はサポート対象ではなく、機能が制限されることがあります。 詳しくは、Microsoft Azure プレビューの追加使用条件に関するページをご覧ください。
Azure AI 検索の Azure Blob Storage、Azure Files、OneLake のインデクサーは、Markdown ファイルの markdown
解析モードをサポートしています。 Markdown ファイルには 2 つの方法でインデックスを作成できます。
- 一対多の解析モード (1 つの Markdown ファイルに対して複数の検索ドキュメントを作成)
- 一対一の解析モード (1 つの Markdown ファイルに対して 1 つの検索ドキュメントを作成)
前提条件
サポートされているデータ ソース: Azure Blob Storage、Azure File Storage、Microsoft Fabric の OneLake。
OneLake の場合は、OneLake インデクサーのすべての要件を満たしていることを確認します。
BLOB インデクサーとファイル インデクサー用の Azure Storage は、ホット層、クール層、コールド層をサポートする標準パフォーマンス (汎用 v2) インスタンスです。
Markdown 解析モード パラメーター
解析モード パラメーターは、インデクサーを作成または更新すると、インデクサー定義内で指定されます。
POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]
{
"name": "my-markdown-indexer",
"dataSourceName": "my-blob-datasource",
"targetIndexName": "my-target-index",
"parameters": {
"configuration": {
"parsingMode": "markdown",
"markdownParsingSubmode": "oneToMany",
"markdownHeaderDepth": "h6"
}
},
}
BLOB インデクサーは、検索ドキュメントの構造の出力を判断するための submode
パラメーターを備えています。 Markdown 解析モードには、次のサブモード オプションが用意されています。
parsingMode | サブモード | 検索ドキュメント | 説明 |
---|---|---|---|
markdown |
oneToMany |
BLOB あたり複数 | (既定) Markdown を複数の検索ドキュメントに分割します。それぞれは、Markdown ファイルのコンテンツ (ヘッダーなし) セクションを表します。 サブモードは、一対一の解析が必要な場合を除き、省略できます。 |
markdown |
oneToOne |
BLOB あたり 1 つ | Markdown を、Markdown ファイル内の特定のヘッダーにマッピングされているセクションがある 1 つの検索ドキュメントに解析します。 |
oneToMany
サブモードの場合は、同じ BLOB から生成された複数の検索ドキュメントのドキュメント キーのあいまいさ排除が BLOB インデクサーによってどのように処理されるかを理解するために、1 つの BLOB にインデックスを作成して多数の検索ドキュメントを生成する方法に関する記事を参照する必要があります。
後のセクションで、各サブモードについて詳しく説明します。 インデクサーのクライアントと概念の詳細については、検索インデクサーの作成に関するページを参照してください。 また、基本的な BLOB インデクサーの構成の詳細についても理解しておく必要があります。これについては、ここでは説明しません。
オプションの Markdown 解析パラメーター
パラメーターの大文字と小文字は区別されます。
パラメーター名 | 使用できる値 | 説明 |
---|---|---|
markdownHeaderDepth |
h1 、h2 、h3 、h4 、h5 、h6(default) |
このパラメーターを使用すると、解析時に考慮される最も深いヘッダー レベルが決定し、ドキュメント構造を柔軟に処理できるようになります (たとえば、markdownHeaderDepth が h1 に設定されている場合、パーサーは "#" で始まる最上位レベルのヘッダーと、プレーン テキストとして扱われる下位レベルのすべてのヘッダーのみを認識します)。 指定しない場合の既定値は h6 です。 |
この設定は、インデクサーを最初に作成した後も変更できますが、結果として生成された検索ドキュメントの構造が Markdown コンテンツに応じて変わる可能性があります。
サポートされている Markdown 要素
Markdown 解析を行うと、ヘッダーに基づいてコンテンツのみが分割されます。 リスト、コード ブロック、テーブルなどの他のすべての要素は、プレーン テキストとして扱われ、コンテンツ フィールドに渡されます。
Markdown コンテンツのサンプル
このページでは、次の Markdown コンテンツを例として使用します。
# Section 1
Content for section 1.
## Subsection 1.1
Content for subsection 1.1.
# Section 2
Content for section 2.
一対多の解析モードを使用する
一対多の解析モードでは、Markdown ファイルを複数の検索ドキュメントに解析します。各ドキュメントは、ドキュメント内のその時点のヘッダー メタデータに基づいて、Markdown ファイルの特定のコンテンツ セクションに対応します。 Markdown は、ヘッダーに基づいて、次のコンテンツが含まれている検索ドキュメントに解析されます。
content
: 特定の場所で見つかった未処理の Markdown が含まれている文字列。ドキュメント内のその時点のヘッダー メタデータに基づいています。sections
: 目的のヘッダー レベルにまでヘッダー メタデータのサブフィールドが含まれているオブジェクト。 たとえば、markdownHeaderDepth
がh3
に設定されている場合は、文字列フィールドh1
、h2
、h3
が含まれます。 これらのフィールドには、インデックス内でこの構造をミラーリングするか、/sections/h1
、sections/h2
などの形式でフィールド マッピングを行うことでインデックスが作成されます。コンテキスト内の例については、次のサンプルのインデックスとインデクサーの構成を確認してください。 含まれているサブフィールドは次のとおりです。h1
: h1 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。- (省略可能)
h2
: h2 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。 - (省略可能)
h3
: h3 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。 - (省略可能)
h4
: h4 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。 - (省略可能)
h5
: h5 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。 - (省略可能)
h6
: h6 ヘッダー値を含む文字列。 ドキュメントのこの時点に設定されていない場合は、空の文字列。
ordinal_position
: ドキュメントの階層内でのセクションの位置を示す整数値。 このフィールドは、ドキュメント内に示されている元の順序にセクションの順序付けるために使用します。序数位置 1 から始まり、ヘッダーごとに順番にインクリメントします。
一対多の解析のインデックス スキーマ
インデックス構成の例は、次のようになります。
{
"name": "my-markdown-index",
"fields": [
{
"name": "id",
"type": "Edm.String",
"key": true
},
{
"name": "content",
"type": "Edm.String",
},
{
"name": "ordinal_position",
"type": "Edm.Int32"
},
{
"name": "sections",
"type": "Edm.ComplexType",
"fields": [
{
"name": "h1",
"type": "Edm.String"
},
{
"name": "h2",
"type": "Edm.String"
}]
}]
}
一対多の解析のインデクサー定義
フィールド名とデータの種類が合っている場合は、明示的なフィールド マッピングが要求内に存在していなくても、BLOB インデクサーによる推測が可能です。そのため、指定したインデックス構成に対応するインデクサー構成は、次のようになります。
POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]
{
"name": "my-markdown-indexer",
"dataSourceName": "my-blob-datasource",
"targetIndexName": "my-target-index",
"parameters": {
"configuration": { "parsingMode": "markdown" }
},
}
Note
oneToMany
が既定値であるため、ここでは submode
を明示的に設定する必要はありません。
一対多の解析のインデクサー出力
この Markdown ファイルは、コンテンツ セクションが 3 つあるため、インデックス作成後は 3 つの検索ドキュメントが生成されます。 指定した Markdown ドキュメントの最初のコンテンツ セクションから生成された検索ドキュメントには、content
、sections
、h1
、h2
の次の値が含まれています。
{
{
"content": "Content for section 1.\r\n",
"sections": {
"h1": "Section 1",
"h2": ""
},
"ordinal_position": 1
},
{
"content": "Content for subsection 1.1.\r\n",
"sections": {
"h1": "Section 1",
"h2": "Subsection 1.1"
},
"ordinal_position": 2
},
{
"content": "Content for section 2.\r\n",
"sections": {
"h1": "Section 2",
"h2": ""
},
"ordinal_position": 3
}
}
一対多フィールドを検索インデックスにマッピングする
フィールドの名前と型が同じでない場合、フィールド マッピングでは、ソース フィールドと宛先フィールドが関連付けられます。 ただし、フィールドマッピングは、Markdown ドキュメントの一部を一致させたり、検索ドキュメントの最上位レベルのフィールドに "引き上げ" たりする際にも使用できます。
次の例はこのようなシナリオを示しています。 フィールド マッピングの詳細については、フィールド マッピングに関するページを参照してください。
Edm.String
型の raw_content
フィールド、Edm.String
型の h1_header
フィールド、Edm.String
型の h2_header
フィールドを持つ検索インデックスがあるとします。 Markdown を目的の図形にマッピングするには、次のフィールド マッピングを使用します。
"fieldMappings" : [
{ "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
{ "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
{ "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
]
インデックス内で生成される検索ドキュメントは、次のようになります。
{
{
"raw_content": "Content for section 1.\r\n",
"h1_header": "Section 1",
"h2_header": "",
},
{
"raw_content": "Content for section 1.1.\r\n",
"h1_header": "Section 1",
"h2_header": "Subsection 1.1",
},
{
"raw_content": "Content for section 2.\r\n",
"h1_header": "Section 2",
"h2_header": "",
}
}
一対一の解析モードを使用する
一対一の解析モードでは、1 つの検索ドキュメントとしての Markdown ドキュメント全体にインデックスが作成され、元のコンテンツの階層と構造が保持されます。 このモードは、インデックスを作成するファイルの構造が共通している場合に最も便利であり、インデックス内にこの共通の構造を使用して、関連するフィールドを検索できるようにすることができます。
インデクサー定義内で、parsingMode
を "markdown"
に設定し、オプションの markdownHeaderDepth
パラメーターを使用して、チャンクの最大ヘッダー深さを定義します。 指定していない場合は、h6
が既定であり、可能なすべてのヘッダー深さをキャプチャします。
Markdown は、ヘッダーに基づいて、次のコンテンツが含まれている検索ドキュメントに解析されます。
document_content
: 完全な Markdown テキストが 1 つの文字列として含まれます。 このフィールドは、入力ドキュメントの未処理の表現として機能します。sections
: Markdown ドキュメント内のセクションの階層表現が含まれているオブジェクトの配列。 各セクションは、この配列内でオブジェクトとして表現されており、各ヘッダーとそのコンテンツに対応する入れ子になったドキュメントの構造をキャプチャします。 このフィールドは、パスを参照することで、フィールド マッピングを使用してアクセスできます (例:/sections/content
)。 この配列内のオブジェクトには、次のプロパティがあります。header_level
: Markdown 構文内のヘッダーのレベルを示す文字列 (h1
、h2
、h3
など)。 このフィールドは、コンテンツの階層と構造の理解に役立ちます。header_name
: Markdown ドキュメント内に示されているヘッダーのテキストが含まれている文字列。 このフィールドには、セクションのラベルまたはタイトルが表示されます。content
: ヘッダーの直後から次のヘッダーまで続くテキスト コンテンツが含まれている文字列。 このフィールドは、ヘッダーに関連付けられている詳しい情報または説明をキャプチャします。 ヘッダーのすぐ下にコンテンツがない場合、これは空の文字列です。ordinal_position
: ドキュメントの階層内でのセクションの位置を示す整数値。 このフィールドは、ドキュメント内に示されている元の順序にセクションの順序付けるために使用されます。序数位置 1 から始まり、コンテンツ ブロックごとに順番にインクリメントします。sections
: 現在のセクションで入れ子になっているサブセクションを表すオブジェクトが含まれている配列。 この配列は、最上位レベルのsections
配列と同じ構造に従っており、入れ子になったコンテンツの複数のレベルを表すことができます。 また、各サブセクション オブジェクトは、header_level
プロパティ、header_name
プロパティ、content
プロパティ、ordinal_position
プロパティを含んでおり、Markdown コンテンツを表す再帰構造と階層が有効になります。
各解析モードを中心に設計されたインデックス スキーマの説明に使用するサンプルの Markdown を次に示します。
# Section 1
Content for section 1.
## Subsection 1.1
Content for subsection 1.1.
# Section 2
Content for section 2.
一対一の解析のインデックス スキーマ
フィールド マッピングを利用していない場合は、インデックスの図形に Markdown コンテンツの図形を反映させる必要があります。 サンプルの Markdown の構造に 2 つのセクションと 1 つのサブセクションが含まれているとすると、インデックスは次の例のようになります。
{
"name": "my-markdown-index",
"fields": [
{
"name": "document_content",
"type": "Edm.String",
{
"name": "sections",
"type": "Edm.ComplexType",
"fields": [
{
"name": "header_level",
"type": "Edm.String",
},
{
"name": "header_name",
"type": "Edm.String",
},
{
"name": "content",
"type": "Edm.String"
},
{
"name": "ordinal_position",
"type": "Edm.Int"
},
{
"name": "sections",
"type": "Edm.ComplexType",
"fields": [
{
"name": "header_level",
"type": "Edm.String",
},
{
"name": "header_name",
"type": "Edm.String",
},
{
"name": "content",
"type": "Edm.String"
},
{
"name": "ordinal_position",
"type": "Edm.Int"
}]
}]
}
}
一対一の解析のインデクサー定義
POST https://[service name].search.windows.net/indexers?api-version=2024-11-01-preview
Content-Type: application/json
api-key: [admin key]
{
"name": "my-markdown-indexer",
"dataSourceName": "my-blob-datasource",
"targetIndexName": "my-target-index",
"parameters": {
"configuration": {
"parsingMode": "markdown",
"markdownParsingSubmode": "oneToOne",
}
}
}
一対一の解析のインデクサー出力
インデックスを作成したい Markdown が対応するのは h2
("##") の深さまでなので、sections
フィールドを 2 の深さまで入れ子にして、それに一致させる必要があります。 このように構成すると、インデックス内に次のデータが生成されます。
"document_content": "# Section 1\r\nContent for section 1.\r\n## Subsection 1.1\r\nContent for subsection 1.1.\r\n# Section 2\r\nContent for section 2.\r\n",
"sections": [
{
"header_level": "h1",
"header_name": "Section 1",
"content": "Content for section 1.",
"ordinal_position": 1,
"sections": [
{
"header_level": "h2",
"header_name": "Subsection 1.1",
"content": "Content for subsection 1.1.",
"ordinal_position": 2,
}]
}],
{
"header_level": "h1",
"header_name": "Section 2",
"content": "Content for section 2.",
"ordinal_position": 3,
"sections": []
}]
}
ご覧のように、序数位置は、ドキュメント内のコンテンツの場所に基づいてインクリメントします。
また、コンテンツ内でヘッダー レベルがスキップされた場合は、結果として生成されるドキュメントの構造に Markdown コンテンツ内で存在しているヘッダーが反映されており、h6
を連続して使用する h1
の入れ子になったセクションが含まれていなくても構わないことに注意してください。 たとえば、ドキュメントが h2
で始まる場合、最上位レベルのセクションの配列内にある最初の要素は h2
です。
検索インデックスに一対一のフィールドをマッピングする
カスタム名が含まれているフィールドをドキュメントから抽出する場合は、フィールド マッピングを使用すると行うことができます。 以前の同じ Markdown ファイルを使用するときは、次のインデックス構成を考慮してください。
{
"name": "my-markdown-index",
"fields": [
{
"name": "document_content",
"type": "Edm.String",
},
{
"name": "document_title",
"type": "Edm.String",
},
{
"name": "opening_subsection_title"
"type": "Edm.String",
}
{
"name": "summary_content",
"type": "Edm.String",
}
]
}
解析された Markdown からの特定のフィールドの抽出は、outputFieldMappings でのドキュメント パスと同様に処理されます。ただし、/document
ではなく /sections
で始まるパスは例外です。 そのため、たとえば、/sections/0/content
は、セクション配列で 0 の位置にある項目の下のコンテンツにマッピングされます。
強力のユース ケースの例は、次のようになります。すべての Markdown ファイルには、最初の h1
にドキュメント タイトル、最初の h2
にサブセクション タイトル、最後の h1
の下にある最後の段落のコンテンツに概要が表示されます。 そのコンテンツにのみインデックスを作成するには、次のフィールド マッピングを使用できます。
"fieldMappings" : [
{ "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
{ "sourceFieldName" : "/sections/0/header_name", "targetFieldName" : "document_title" },
{ "sourceFieldName" : "/sections/0/sections/header_name", "targetFieldName" : "opening_subsection_title" },
{ "sourceFieldName" : "/sections/1/content", "targetFieldName" : "summary_content" },
]
関連する部分のみを、そのドキュメントから抽出することになります。 この機能を非常に効果的に使用するには、インデックスを作成する予定のドキュメントで、同じ階層ヘッダー構造を共有する必要があります。
インデックス内で生成される検索ドキュメントは、次のようになります。
{
"content": "Content for section 1.\r\n",
"document_title": "Section 1",
"opening_subsection_title": "Subsection 1.1",
"summary_content": "Content for section 2."
}
Note
これらの例では、フィールド マッピングの有無にかかわらず、これらの解析モードを完全に使用する方法を指定していますが、ニーズに合えば、1 つのシナリオで両方を利用できます。