株式会社ホコサキ

MinerUでPDF→Markdown変換、RAG前処理の精度を上げる

天京祐輔
天京祐輔
MinerUでPDF→Markdown変換、RAG前処理の精度を上げる

PDFをRAGのナレッジソースに使おうとして、思ったより精度が出なかった経験はないでしょうか。
テキスト自体は抽出できているのに、LLMへ渡すと的外れな回答が返ってくる。
その原因の多くは、LLMの性能ではなく 前処理の品質 にあります。

PyMuPDFやpdfplumberでテキストを抜き出したとき、多段組のPDFだと左右のカラムが混ざって読み順が崩れることがあります。
表の中身は取れているのに列がバラバラになっていたり、数式が意味不明な記号の羅列になっていたり。
こういう状態のテキストをチャンクに切ってベクトル化しても、検索精度の上限はそこで決まってしまいます。

MinerUはこの問題に正面から向き合ったツールです。
上海AI研究所のOpenDataLabが開発したオープンソースのドキュメントパーサーで、PDFをLLMが扱いやすいMarkdownとJSONに変換することに特化しています。
インストールから変換出力の確認、RAGパイプラインへの組み込みイメージまでを一本の流れで追いながら、PyMuPDF・pdfplumberとの使い分け判断も自分の案件に当てはめられるレベルで整理します。

PDFをそのままLLMに渡しても精度が出ない、その理由

PyMuPDFは速くて安定しています。
シンプルな横書きのPDFなら、テキスト抽出の品質は十分です。
ただし「レイアウトを理解して読み順を復元する」ことは、もともとの設計目標ではありません。

多段組のPDFを想像してください。
左カラムの文章が途中まで続いて、右カラムの文章が割り込んで、また左カラムに戻る。
PyMuPDFはページ上のテキストブロックをY座標順に並べるため、こういうレイアウトだと左右が混ざった状態で出力されます。
pdfplumberは視覚的なレイアウト解析が得意で、表の抽出精度は高いのですが、多段組の読み順復元は同様に苦手です。

数式はさらに厄介です。
PDFの数式はほとんどの場合、文字として埋め込まれておらず、グリフの集合として描画されています。
テキスト抽出ベースのツールでは「∫」「∑」のような記号が文字化けするか、完全に欠落します。
RAGで数式を含む技術文書や論文を扱うとき、この問題はかなり痛いです。

MinerUのアプローチは根本的に違います。
PaddlePaddleベースのレイアウト検出モデルでページを解析し、テキストブロック・表・数式・図のキャプションをそれぞれ別のコンポーネントとして認識します。
その上で読み順を復元し、表はSLANet+で構造化、数式はUniMERNetでLaTeX形式に変換、最終的にMarkdownとして出力する多段パイプラインになっています。
「テキストを抜き出す」のではなく「ドキュメントの構造を理解して再構築する」という発想の違いです。

OmniDocBenchというPDFパーサーの総合ベンチマークで、MinerU2.5は90.67というスコアを記録しています。
MarkerやDoclingを含む比較の中でトップクラスの数値で、特に数式認識と表構造の再現精度が高いとされています。

MinerUのインストールと最初の変換

インストール自体はシンプルです。
uvが入っていれば、以下の一行で最小構成が揃います。

uv pip install 'mineru[all]'

CPU環境でも動作しますが、初回起動時にレイアウト検出・OCR・数式認識などのモデルファイルが自動ダウンロードされます。
合計で数GBになるので、初回だけ数分から十数分待つことになります。
ここで焦ってCtrl+Cしてしまうのがよくあるつまずきです。
ダウンロードが完了するまでそのまま待ちましょう。

もう一つ注意が必要なのが設定ファイルの配置です。
MinerUはホームディレクトリに magic-pdf.json という設定ファイルを置くことでモデルパスやデバイス設定を管理します。
インストール後に変換が動かない場合、このファイルが生成されていないか、モデルパスがずれていることが多いです。

GPUを使いたい場合はCUDA対応のPyTorchを別途インストールし、magic-pdf.jsonのdevice-modeをcudaに変更します。
A100環境では2.12ページ/秒、RTX 4090でも1.70ページ/秒という処理速度が出ています。
CPUでも動きますが、重いPDFは時間がかかるので、本番運用ではGPU環境を用意するのが現実的です。

CLIでの変換は一行です。

mineru -i input.pdf -o ./output

出力ディレクトリには変換後のMarkdownファイル、JSON形式の構造化データ、図や表の画像ファイルが生成されます。
MarkdownはそのままLLMに渡せる形になっていて、JSONには各コンテンツブロックのページ番号・種別・座標情報などのメタデータが含まれています。

Python APIからも同様に呼び出せます。

from mineru.api import MinerUAPI

api = MinerUAPI()
result = api.parse("input.pdf", output_dir="./output")

# Markdownテキストを取得
markdown_text = result.markdown

# 構造化JSONを取得
blocks = result.content_list

スクリプトに組み込む場合はこちらの方が扱いやすいです。
result.content_listにはページ単位・ブロック単位の構造が入っているので、後述するRAGパイプラインへの組み込みで活用できます。

変換結果の実際:嬉しいところと正直微妙なところ

MinerUの出力を実際に見てみると、既存ツールとの差が一番わかりやすいのは 表の変換 です。

複数ページにまたがる表が、こんな形でMarkdownに出力されます。

| 項目 | 2022年度 | 2023年度 | 2024年度 |
|------|----------|----------|----------|
| 売上高 | 1,200 | 1,450 | 1,680 |
| 営業利益 | 120 | 180 | 210 |
| 純利益 | 85 | 130 | 155 |

クロスページ表結合が効いていて、ページをまたいで分断されていた表が一つのMarkdownテーブルとして出力されます。
PyMuPDFやpdfplumberでは、ページをまたぐ表は前半と後半が別々のブロックとして出てくることが多く、手動でつなぎ合わせる必要がありました。

数式の変換も明確な強みです。
論文PDFに含まれる数式が、こんな形でLaTeX形式に変換されます。

$$
\mathcal{L} = -\sum_{i=1}^{N} y_i \log(\hat{y}_i) + \lambda \|\mathbf{w}\|^2
$$

インライン数式も $E = mc^2$ のように変換されます。
これをそのままLLMに渡せば、数式の意味を理解した上で回答を生成できます。
従来のツールで数式が文字化けしていた状況と比べると、体感の差はかなり大きいです。

一方で、正直に言うと微妙な部分もあります。

日本語の縦書きPDF は現時点では苦手です。
縦書きのレイアウト検出が横書きほど精度が出ず、読み順が崩れるケースがあります。
法律文書や古い日本語文献を扱う場合は注意が必要です。

スキャンPDFは、OCRが109言語対応しているので基本的には動きますが、印刷品質が低いものや手書きが混じるものは精度が落ちます。
また、ページ数が多い重いPDFをCPU環境で処理すると、時間がかかりすぎて実用的でないケースもあります。
図のキャプション認識は概ね正確ですが、図と本文テキストが近接しているレイアウトでは、キャプションが本文に混入することがたまにあります。

PyMuPDF・pdfplumberとの使い分け

三つのツールは競合というより、それぞれ得意な場面が違います。
処理速度・変換精度・セットアップコストの三軸で整理すると、使い分けの判断がしやすくなります。

速度の面では、PyMuPDFが圧倒的です。
pdfmux.comの比較によると、1,000ページのバッチ処理でPyMuPDFが約5.5秒なのに対し、pdfplumberは約55秒かかります。
MinerUはモデル推論が入るのでさらに遅く、大量バッチ処理には向きません。

実務シナリオ別の判断基準を整理するとこうなります。

  • 大量バッチ処理・シンプルな横書きPDF → PyMuPDF。速度最優先で、レイアウトが単純なら精度も十分。
  • 表の位置ベース抽出が必要・構造が比較的シンプル → pdfplumber。視覚的な表検出が強く、MITライセンスで商用利用しやすい。
  • 複雑レイアウト・数式・多段組・RAG前処理 → MinerU。セットアップコストはかかるが、変換品質で他を圧倒する場面がある。
  • ライセンス制約が厳しいプロジェクト → pdfplumber一択。PyMuPDFとMinerUはどちらもAGPLなので、商用プロダクトへの組み込みには法務確認が必要。

ライセンスの話は見落とされがちですが、実務では重要です。
pdfplumberはMITなので商用利用に制約がありません。
PyMuPDFとMinerUはAGPLで、ソースコードの公開義務が発生する可能性があります。
クローズドなプロダクトに組み込む場合は、法務部門や顧問弁護士に確認することをおすすめします。

「MinerUを使えばすべて解決」ではなく、案件の要件に合わせて選ぶのが正解です。
シンプルなPDFを大量に処理するバッチジョブにMinerUを使うのはオーバースペックですし、逆に学術論文や複雑なレポートをRAGに取り込むのにPyMuPDFだけで頑張るのは前処理コストが高くつきます。

RAGパイプラインへの組み込みイメージ

MinerUはあくまでパーサーです。
RAG全体の設計やベクトルDBの選定とは別の話で、「PDFをLLMが扱いやすい形に変換する」という一点に特化したツールとして位置づけるのが正確です。

LangChainのパイプラインに組み込む場合、MinerUの出力MarkdownをDocumentオブジェクトに変換して、テキストスプリッターに渡す形が基本になります。

from langchain.schema import Document
from langchain.text_splitter import MarkdownHeaderTextSplitter
from mineru.api import MinerUAPI

# MinerUでPDFを変換
api = MinerUAPI()
result = api.parse("report.pdf", output_dir="./output")

# MarkdownをLangChainのDocumentに変換
doc = Document(
    page_content=result.markdown,
    metadata={"source": "report.pdf"}
)

# Markdownの見出し構造でチャンク分割
splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=[
        ("#", "h1"),
        ("##", "h2"),
        ("###", "h3"),
    ]
)
chunks = splitter.split_text(result.markdown)

MarkdownHeaderTextSplitterを使うと、MinerUが復元した見出し構造に沿ってチャンクが切られます。
「どのセクションの情報か」というコンテキストがチャンクに保持されるので、検索精度が上がりやすいです。

JSONモードの出力をうまく使うと、さらに細かいメタデータ管理ができます。
result.content_listにはブロックごとのページ番号・種別(テキスト・表・数式・図キャプション)が入っているので、たとえば「表だけを別チャンクにする」「ページ番号をメタデータとして付与してソース引用に使う」といった前処理が書けます。

LlamaIndexでも同様に、MinerUの出力MarkdownをSimpleDirectoryReaderやカスタムのDocumentオブジェクトとして読み込む形で使えます。

重要なのは、MinerUを入れたからといってRAGの精度がすべて解決するわけではないという点です。
チャンク戦略・埋め込みモデルの選定・リランキングの設計など、精度に関わる要素は他にもたくさんあります。
ただ、前処理の品質が低いとその後の工夫がすべて無駄になるので、「ゴミを入れればゴミが出る」問題を先に潰しておくという意味で、MinerUは投資対効果の高い選択肢だと思っています。


株式会社ホコサキは、山口県宇部を拠点にRAGパイプラインの設計・構築やPDF前処理の自動化など、AIを活用した業務システム開発を手がけています。
「手元のPDFをRAGに使いたいが、前処理で詰まっている」といった相談も気軽にどうぞ。
詳しくは お問い合わせページ からご連絡ください。