RAG/LLMの前処理：PyMuPDF4LLMを使用してPDFをMarkdownへ変換する

PDFに対するRAGやLLM解析の前処理としてPDFからのテキスト抽出を試してきましたが、単純に抽出を行うと表形式の構造化情報が失われてLLMの解析性能に依存するしかないのが気になります。

https://qiita.com/cyberBOSE/items/142cdf91e0ee20b3114f

https://qiita.com/cyberBOSE/items/175dc0710aa03a06249d

https://qiita.com/cyberBOSE/items/f69caa3a3a8278905b0b

単純なテキスト抽出でも性能が良かったPyMuPDFのラッパーとして、Markdown形式に変換するライブラリがあるので動作を確認します。
PyMuPDF4LLMというそのままの名前で、MuPDFと同じ会社が開発しているようです。リプライ飛んできました。これはありがたいエゴサ

https://x.com/artifex/status/1795483808093139017

# 参考ページ

https://pymupdf4llm.readthedocs.io/ja/latest/

https://qiita.com/jamie-lemon/items/1f2eb43f439fd28202a0

# 使用ライブラリ

```
pip install pymupdf4llm
```

# テストプログラム

```Python
import pymupdf4llm

start_page=0
stop_page=25
pdf_path="./bedrock-ug.pdf"

md_text = pymupdf4llm.to_markdown(pdf_path, pages=range(start_page,stop_page))

with open("out.markdown.md", "w", encoding="utf-8") as output:
    output.write(md_text)
```
PDFとしては<a href="https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/bedrock-ug.pdf">Bedrockユーザーガイドの日本語版</a>の1-26ページを対象にしています。
全ページの変換を一気に行おうとすると処理が終わらないので、大きなファイルの場合はレンジを刻んだ方が良さそうです。

# 実行結果

PDFの表を含むページは以下の様に変換されています。
（元のPDFの品質の問題で元から文字が欠けている部分もあります）

```markdown
Amazon Bedrock では、どのサードパーティーの基盤モデルで推論を実行する場合でも料金がかかり
ます。料金は、入力トークンと出力トークンの量、およびモデル用のプロビジョンドスループット
の購入有無によって決まります。詳細については、Amazon Bedrock コンソールの [モデルプロバイ
ダー] ページを参照してください。各モデルの料金は、モデルバージョンの後に記載されています。
プロビジョンドスループットの購入の詳細については、「 Amazon Bedrock のプロビジョニングされ
たスループット 」を参照してください。

詳細については、「 Amazon Bedrock の料金体系 」ページを参照してください。

### AWS サポート対象地域

Amazon Bedrock がサポートするリージョンのサービスエンドポイントについては、「 Amazon
Bedrock エンドポイントとクォータ 」を参照してください。

各リージョンがサポートする基盤モデルについては、を参照してください AWS 地域別のモデルサ
ポート 。

Note

米国東部 (バージニア北部) および米国西部 (オレゴン) ではすべての機能を使用できます。

リージョンによって制限される機能については、次の表を参照してください。

|リージョン|モデル評価|ナレッジ ベース|エージェン ト|ファイン チューニン グ (カスタ ムモデル)|継続的な事 前トレー ニング (カ スタムモデ ル)|プロビジョ ンドスルー プット|
|---|---|---|---|---|---|---|
|米国東部 （バージニ ア北部）|はい|はい|はい|はい|はい|はい|
|米国西部 (オレゴン)|はい|はい|はい|はい|はい|はい|
|アジアパ シフィッ|いいえ|いいえ|いいえ|いいえ|いいえ|いいえ|
```

マークダウン表部分のみを抜き出します。
|リージョン|モデル評価|ナレッジ ベース|エージェン ト|ファイン チューニン グ (カスタ ムモデル)|継続的な事 前トレー ニング (カ スタムモデ ル)|プロビジョ ンドスルー プット|
|---|---|---|---|---|---|---|
|米国東部 （バージニ ア北部）|はい|はい|はい|はい|はい|はい|
|米国西部 (オレゴン)|はい|はい|はい|はい|はい|はい|
|アジアパ シフィッ|いいえ|いいえ|いいえ|いいえ|いいえ|いいえ|

元のPDFの該当箇所は以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/55ade437-f773-f839-df7c-ec8d338fcbac.png)

いいですね。
行列情報についても欠落せずに正しく抽出できている事が分かります。
セルの中で改行されている部分はスペースに置き換えられています。まあこれは仕方ないかな。。

少なくとも単純にテキスト抽出するのに比べると行列構造を保持できているので、LLMで分析を行う際もより正しく解析が出来そうだという合理的な推測が出来ます。<a href="https://qiita.com/cyberBOSE/items/f69caa3a3a8278905b0b">HTMLに変換する方法</a>もありますが、HTMLは文字数が嵩むのと、HTMLに変換したとて必ず正しく変換できるわけでもないので、この方法でマークダウンに変換する方が良いかもしれません。また、ナレッジベースについてもチャンクを見ると構造情報が失われていたので、一度マークダウンに変換してから取り込んだ方が精度が良くなると思います。

ただ、以下のような課題はあるので、出来ればさらにLLMで処理を行ってから、RAG（ナレッジの格納）なりLLM解析なりを行った方が良さそうです。

- 本文の改行がスペースに置き換えられる
- セル内の改行もスペースに置き換えられる
- 別のPDFで試したところ、セルの中の文字列と文字列の間にスペースが入る事がある（PDFをレイアウトした時の見やすさの調整の結果だと思います）
- 表の途中に改ページが挟まるといかんともしがたい
- ページのヘッダーフッターが邪魔
- 罫線と文字の距離が近いとうまく表形式にならない場合がある
- 人間が見ると表のように見えるが、どうにもならないPDFも存在する・・

このライブラリは先月末にv0.0.1がリリースされたばかりの生まれたてホヤホヤのようですが、これから定番になるポテンシャルを感じます。

# 追伸
pymupdf4llm.to_markdownはデフォルトでもある程度のヘッダーフッターマージンの指定が入っており、良い感じに切ってくれたり切りすぎたりという事が起きるので、マージン指定はPDFに合わせて調整しましょう。

こんな感じで
```Python
md_text = pymupdf4llm.to_markdown(pdf_path, pages=range(start_page,stop_page), margins=(0,0,0,0))
```