Azure Document Intelligenceのレイアウトモデルを使ってPDFをMarkdownに変換しRAG用にセマンティックチャンキングを試す

# はじめに
この記事では、Azure Document Intelligenceのレイアウトモデルを使用してPDFをMarkdownに変換し、さらにRAGのためのセマンティックチャンキングを実装する方法について試したことをまとめています。

# Azure AI Document Intelligenceとは
Azure Document Intelligenceは、ドキュメントからテキスト、構造を抽出するサービスです。
以前はAzure Form Recognizerとして知られていました。

https://learn.microsoft.com/ja-jp/azure/ai-services/document-intelligence/overview?view=doc-intel-4.0.0

# セマンティックチャンキングとは
文字数ではなく意味でチャンク分けを行うこと。

意味でチャンク分けを行うことでRAGの精度向上につながる。

LLMにチャンク分けさせる手法が精度的に一番良い気がするが、MSのドキュメントにDocument Intelligenceのレイアウトモデルを使ってMarkdownからチャンク分けを行うやり方もセマンティックチャンキングと言えるとのこと。

https://learn.microsoft.com/ja-jp/azure/ai-services/document-intelligence/concept-retrieval-augmented-generation?view=doc-intel-4.0.0


# コード
Azure Document Intelligenceのレイアウトモデルを使用してPDFをMarkdownに変換する手順を以下で説明します。
1. LangChainのDocument loaderを利用してpdfをMarkdownへ変換
1. LangChainのMarkdownHeaderTextSplitterを使いヘッダー単位でチャンク化

https://python.langchain.com/v0.2/docs/integrations/document_loaders/azure_document_intelligence/

https://python.langchain.com/v0.1/docs/modules/data_connection/document_transformers/markdown_header_metadata/



必要なパッケージをインストール
```
# pip install azure-ai-documentintelligence==1.0.0b1
# pip install langchain langchain-community azure-ai-documentintelligence
```

```python
from langchain.text_splitter import MarkdownHeaderTextSplitter
from langchain_community.document_loaders import AzureAIDocumentIntelligenceLoader

endpoint=hogehoge
key=fugafuga

# Document Intelligenceのloaderを設定し、API実行
loader = AzureAIDocumentIntelligenceLoader(
    file_path="./data/qiita記事.pdf", api_key=key, api_endpoint=endpoint, api_model="prebuilt-layout")
docs = loader.load()

# 分割対象のヘッダー
headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
]
text_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on)

docs_string = docs[0].page_content
splits = text_splitter.split_text(docs_string)

```

今回変換対象のPDFは過去にQiitaで書いた[この記事](https://qiita.com/h_id32/items/a2655e8b7040c1c10016)をChromeの印刷からPDFにしたものを利用しています。


# 比較結果
QiitaにはMarkdownで記事をエクスポートできるので、Document Intelligenceの結果とどう違うか比較してみます。
<details><summary>QiitaからエクスポートしたMarkdown</summary>

```qiita.md
## はじめに
こんにちは！ KAGでエンジニアやっている**h_id32**です！

埃かぶってるRaspberryPiが家にあったので、勉強がてらAWS IoTに接続してみます。
今回は基本的なチュートリアルにとどめていますが、第二弾、第三弾と続けていきGreengrass/Device Shadowにも触れられたらなと思っています。

## IoT Coreのクイック接続でRaspberryPiと接続できるか試してみよう

まずは疎通確認も兼ねてAWS IoT Coreのクイック接続を利用して自宅環境のRaspberryPiと通信ができるか試してみます。

### 使用機材
- 埃かぶった RaspberryPi 3 Model B +
![スクリーンショット 2023-12-20 21.50.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516184/dee2b90e-ba3f-3be6-e44f-8a1880fca3f9.png)



:::note warn
今回自宅に余っていたRaspberryPiをそのまま使うがコンセプトなため、初期設定などには触れません。
:::


## AWS IoT
AWSのマネジメントコンソールからIoT Coreを選択

![スクリーンショット 2023-12-17 13.51.37_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516184/e7a5f0e3-09ce-f92d-0455-08f66336d655.png)
```
</details>

<details><summary>Document Intelligenceで変換したMarkdown</summary>

```document-intelligence.md
# はじめに

こんにちは!KAGでエンジニアやっているh\_id32です!

埃かぶってるRaspberryPiが家にあったので、勉強がてらAWS IoTに接続し てみます。

今回は基本的なチュートリアルにとどめていますが、第二弾、第三弾と続 けていきGreengrass/Device Shadowにも触れられたらなと思っています。


## IoT Coreのクイック接続でRaspberryPiと接続でき るか試してみよう

まずは疎通確認も兼ねてAWS IoT Coreのクイック接続を利用して自宅環境 のRaspberryPiと通信ができるか試してみます。

使用機材
:selected:
· 埃かぶった RaspberryPi 3 Model B +

<figure>

![](figures/1)

</figure>


! 今回自宅に余っていたRaspberryPiをそのまま使うがコンセプトな ため、初期設定などには触れません。


# AWS IoT

AWSのマネジメントコンソールからIoT Coreを選択

| aws | !!! サービス || Q 検索 | [オプション+S] || |
| - | - | - | - | - | - | - |
| AWS | 最近アクセスしたサービス ||| loT × ||||||||||
| 
| モニタ || お気に入り | | | | |
| | すべてのサービス ||| IoT 1-Click || |
| 接続 |||| シンプルなデバイスから AWS Lambda 関数をトリガー |||
| 11 | 8 Customer Enablement ||| loT Analytics || | loT デバイスのデータを収集、前処理、保存、分析、視覚化 |||| |
| ▶複 | ifo loT |
| || Machine Learning | | IoT Core |||| |
| テスト | |
| | | デバイスをクラウドに接続 ||| Quantum Technologies | | || |
| ▶デ || 阿 アプリケーション統合 | | IoT Device Defender || |
| M | |
| デ || 項 エンドユーザーコンピューティ | | 接続された loT デバイスのフリートを保護する || ング || | || |
| | || | IoT Device Management || |
| | 島 クラウド財務管理 ||| フリートを1つのデバイスとして小規模に、または数百万のデバイスとして大規模 || |
| 管理  :unselected: ||| 99 ゲーム開発 | に、そして安全に管理 |||
| ▶す  :unselected: ||| コンテナ | loT Events |||
| Gr 
| LP :unselected: ||| ロ コンピューティング | loT センサーと産業用 IoT 機器からのイベントの検出と対応 ||| ソ || 昌 ストレージ | | AWS IoT FleetWise |||
| リ 
| ▲ | の セキュリティ、ID、およびコン プライアンス ||| 車両データを大規模かつ簡単に収集、整理、クラウドに転送する ||||||| || |
| ▶ > || | | 目 データベース | loT Greengrass |||
| 保  :unselected: || | デバイスでコードのデプロイおよび実行 |||| || |
| ▶セ  :unselected: |
| || か ネットワーキングとコンテン | |
| ▶フ | ツ配信 || | IoT RoboRunner | :unselected: ||| Ih ビジネスアプリケーション | ロボットオートメーションの最適化 || |
| デバー  :unselected: || |
| || ブロックチェーン | loT SiteWise || |
| 請求ク|| 図 メディアサービス | | 産業オペレーションにおけるデータに基づく意思決定 | 設定  :unselected: ||| 「コ モバイル | IoT TwinMaker |||
| 注目さ || 2 ロボット工学 | | 現実世界のシステムのデジタルツインを簡単に作成してオペレーションを最適化 |||
| ドキー | 2 分析 :selected: || | |||

```
</details>

### ヘッダーでのチャンク分け

```チャンク1.md
# はじめに

こんにちは!KAGでエンジニアやっているh\_id32です!  
埃かぶってるRaspberryPiが家にあったので、勉強がてらAWS IoTに接続し てみます。  
今回は基本的なチュートリアルにとどめていますが、第二弾、第三弾と続 けていきGreengrass/Device Shadowにも触れられたらなと思っています。
```
はじめにという単位で分けられてますね。不要なスペースは別に排除すれば概ね良さそう。

```チャンク2.md
# はじめに
# IoT Coreのクイック接続でRaspberryPiと接続でき るか試してみよう

まずは疎通確認も兼ねてAWS IoT Coreのクイック接続を利用して自宅環境 のRaspberryPiと通信ができるか試してみます。  
使用機材
:selected:
· 埃かぶった RaspberryPi 3 Model B +  
<figure>  
![](figures/1)  
</figure>  
! 今回自宅に余っていたRaspberryPiをそのまま使うがコンセプトな ため、初期設定などには触れません。
```
「IoT Coreのクイック接続でRaspberryPiと接続でき るか試してみよう」がヘッダー2のため、「はじめに」が付与されて表示されてますね。
レイアウトモデルの仕様として「:selected:」や画像コンテンツのタグが含まれているため、RAGへ利用する際には排除するのがいいかもしれません。

```チャンク3
# AWS IoT

AWSのマネジメントコンソールからIoT Coreを選択  
| aws | !!! サービス || Q 検索 | [オプション+S] || |
| - | - | - | - | - | - | - |
| AWS | 最近アクセスしたサービス ||| loT × ||||||||||
|
| モニタ || お気に入り | | | | |
| | すべてのサービス ||| IoT 1-Click || |
| 接続 |||| シンプルなデバイスから AWS Lambda 関数をトリガー |||
| 11 | 8 Customer Enablement ||| loT Analytics || | loT デバイスのデータを収集、前処理、保存、分析、視覚化 |||| |
| ▶複 | ifo loT |
| || Machine Learning | | IoT Core |||| |
| テスト | |
| | | デバイスをクラウドに接続 ||| Quantum Technologies | | || |
| ▶デ || 阿 アプリケーション統合 | | IoT Device Defender || |
| M | |
| デ || 項 エンドユーザーコンピューティ | | 接続された loT デバイスのフリートを保護する || ング || | || |
| | || | IoT Device Management || |
| | 島 クラウド財務管理 ||| フリートを1つのデバイスとして小規模に、または数百万のデバイスとして大規模 || |
| 管理  :unselected: ||| 99 ゲーム開発 | に、そして安全に管理 |||
| ▶す  :unselected: ||| コンテナ | loT Events |||
| Gr
| LP :unselected: ||| ロ コンピューティング | loT センサーと産業用 IoT 機器からのイベントの検出と対応 ||| ソ || 昌 ストレージ | | AWS IoT FleetWise |||
| リ
| ▲ | の セキュリティ、ID、およびコン プライアンス ||| 車両データを大規模かつ簡単に収集、整理、クラウドに転送する ||||||| || |
| ▶ > || | | 目 データベース | loT Greengrass |||
| 保  :unselected: || | デバイスでコードのデプロイおよび実行 |||| || |
| ▶セ  :unselected: |
| || か ネットワーキングとコンテン | |
| ▶フ | ツ配信 || | IoT RoboRunner | :unselected: ||| Ih ビジネスアプリケーション | ロボットオートメーションの最適化 || |
| デバー  :unselected: || |
| || ブロックチェーン | loT SiteWise || |
| 請求ク|| 図 メディアサービス | | 産業オペレーションにおけるデータに基づく意思決定 | 設定  :unselected: ||| 「コ モバイル | IoT TwinMaker |||
| 注目さ || 2 ロボット工学 | | 現実世界のシステムのデジタルツインを簡単に作成してオペレーションを最適化 |||
| ドキー | 2 分析 :selected: || | |||
```
WEBページが表として取り込まれてますね。
再現具合としては低いため、RAGデータとしてはノイズになりそうです。
こういったWebページのキャプチャが含まれてるPDFの変換は難しそうです。

# やってみて
PDFからの変換を行ってみた結果、一部の差分は発生しているものの、概ねうまく変換できていそうです。ただし、画像の取り込みについては改善の余地がありそうですね。

Markdownのタグを活用したセマンティックチャンキングは、Markdown化の精度が非常に重要です。
精度が低いと、期待する効果が得られない可能性があります。

現在、レイアウトモデルは特定のリージョンでのみ利用可能であり、APIもまだプレビュー版です。今後のバージョンアップに期待したいところです。

また、RAGの精度向上には、チャンク分けのチューニングが欠かせません。PDFの内容をより効果的に取り込めるよう改善が進むことを願っています。

以上です！