RAG(Retrieval-Augmented Generation)システムの構築において、PDFドキュメントの正確な解析は回答精度を左右する重要な要素です。 本記事では、IBMが開発したオープンソースのドキュメント処理ツール「Docling」を使用し、複雑なレイアウトのPDFを高精度に解析・構造化する方法を解説します。
Doclingとは:特徴とメリット
Doclingは、PDF、Word、PowerPoint、HTMLなどのドキュメントを、LLM(大規模言語モデル)が処理しやすいMarkdownやJSON形式に変換するツールキットです。
主な特徴
- 高度なレイアウト解析: 表(Table)、数式、コードブロック、ヘッダー・フッターを正確に認識します。特に表組みの構造化に優れています。
- 文脈の保持: 見出しや段落の階層構造を維持したまま変換するため、RAGのチャンク分割(Chunking)や検索精度が向上します。
- OCR機能: スキャンされた画像ベースのPDFからもテキスト抽出が可能です。
Doclingのインストール手順
Python 3.9以上の環境で動作します。
基本インストール
pip install doclingOCR機能などの拡張ライブラリを含める場合
easyocrなどの依存関係を含める場合は以下を実行します。
pip install "docling[easyocr]"主要パラメータの設定
Doclingでは、用途に合わせて変換処理を細かくカスタマイズできます。特にPDF解析において重要なパラメータを以下にまとめます。
DocumentConverter(コンバーター全体)の引数
DocumentConverterの初期化時に指定可能な主要パラメータです。
| パラメータ名 | 説明 |
|---|---|
allowed_formats | 変換対象とするファイル形式を制限します(例: PDFのみ)。デフォルトではサポートされる全形式が許可されます。 |
format_options | ファイル形式ごとの詳細設定を辞書形式で指定します。PDFのOCRや表解析の設定はここで行います。 |
PdfPipelineOptions(PDF解析パイプライン)の属性
PDF変換の挙動を制御する PdfPipelineOptions クラスの主要な属性です。これは format_options を通じて設定します。
| 属性名 | 説明 | 推奨設定例 |
|---|---|---|
do_ocr | Trueにすると、画像化されたテキストに対してOCRを実行します。スキャンPDFを扱う場合は必須です。 | スキャンPDFの場合: True |
do_table_structure | 表組みの構造(行・列・ヘッダー)をAIモデルで解析します。複雑な表を正しく抽出するために重要です。 | 通常: True |
table_structure_options | 表解析のモードを指定します。TableFormerMode.ACCURATE(高精度)とFAST(高速)があります。 | 精度優先: ACCURATE |
generate_page_images | PDFの各ページを画像として生成し、結果に含めます。マルチモーダルRAGなどで使用します。 | 必要時のみ: True |
images_scale | 画像抽出やページ画像生成時の解像度倍率です。 | デフォルト(2.0) |
以下は、これらの設定を適用するコード例です。
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions, TableFormerMode
# パイプラインオプションの設定
pipeline_options = PdfPipelineOptions()
pipeline_options.do_ocr = True # OCRを有効化
pipeline_options.do_table_structure = True # 表解析を有効化
pipeline_options.table_structure_options.mode = TableFormerMode.ACCURATE # 高精度モード
# コンバーターの初期化(オプションを適用)
converter = DocumentConverter(
format_options={
InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options)
}
)ドキュメント変換の実装例
PDFを読み込み、Markdown形式として出力する基本的なPythonスクリプトです。
convert_doc.py
from docling.document_converter import DocumentConverter
def main():
# 変換対象のパス(URLまたはローカルファイルパス)
source = "https://arxiv.org/pdsf/2408.09869"
# コンバーターの初期化と実行
converter = DocumentConverter()
result = converter.convert(source)
# Markdown形式でエクスポート
markdown_output = result.document.export_to_markdown()
# 結果の確認
print(markdown_output[:500])
# ファイル保存
with open("output.md", "w", encoding="utf-8") as f:
f.write(markdown_output)
print("変換が完了しました。")
if __name__ == "__main__":
main()実行コマンド:
python convert_doc.py初回実行時はモデルのダウンロードが自動的に行われます。生成された output.md を確認し、見出しや表が正しく構造化されているか確認してください。
RAGフレームワークとの連携
Doclingで変換したデータは、主要なRAGフレームワーク(LlamaIndex, LangChain)にスムーズに統合できます。 単なるテキスト抽出ツールと異なり、Doclingは見出しや表構造を維持したMarkdown形式でデータを渡せるため、RAGの検索精度(Retrieval)の向上が期待できます。
以下に、それぞれのフレームワークでの具体的な利用手順を解説します。
LlamaIndexでの利用
LlamaIndexでは、公式の連携ライブラリllama-index-readers-doclingを使用します。これを使うと、PDFをLlamaIndexのDocumentオブジェクトとして直接ロードし、すぐにインデックス化できます。
1. インストール
pip install llama-index-readers-docling2. 実装コード例
from llama_index.core import VectorStoreIndex
from llama_index.readers.docling import DoclingReader
def create_index_with_docling():
# DoclingReaderの初期化
reader = DoclingReader()
# ドキュメントの読み込み
# 自動的にMarkdownへ変換され、構造情報を持ったままロードされます
documents = reader.load_data(file_path="sample.pdf")
# インデックスの作成(ここから通常のLlamaIndexのフローです)
index = VectorStoreIndex.from_documents(documents)
# 検索エンジンの作成とクエリ実行
query_engine = index.as_query_engine()
response = query_engine.query("このドキュメントの要点は何ですか?")
print(response)
# if __name__ == "__main__":
# create_index_with_docling()LangChainでの利用
LangChainでは、langchain-doclingライブラリを使用します。DoclingLoaderを使うことで、他のデータローダーと同じ感覚でDoclingの高精度な解析機能を利用できます。
1. インストール
pip install langchain-docling2. 実装コード例
from langchain_docling import DoclingLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
def run_langchain_pipeline():
# DoclingLoaderでPDFを読み込む
loader = DoclingLoader(file_path="sample.pdf")
docs = loader.load()
# 読み込んだデータの確認(メタデータなども含まれます)
print(f"ドキュメント数: {len(docs)}")
# テキストの分割
# Markdown形式でロードされるため、構造を意識した分割とも相性が良いです
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(docs)
# 以降、FAISSやChromaなどのVectorStoreへ保存します
# ...
# if __name__ == "__main__":
# run_langchain_pipeline()なぜ連携ライブラリを使うのか?
これらの統合ライブラリを使う最大のメリットは、「表(Table)」の意味を損なわずにLLMへ渡せる点です。 通常のPDF読み込みツールでは、表内の数値が単なる文字列の羅列になってしまい、「A社の売上はいくら?」といった質問に答えられないことがよくあります。Doclingを経由することで、表がMarkdownの表形式として保持されるため、LLMが構造を理解しやすくなります。
まとめ
Doclingを導入することで、従来難易度の高かった「複雑なレイアウトを持つPDF」の解析精度を飛躍的に向上させることができます。 RAGの回答品質に課題を感じている場合は、ドキュメントの前処理としてDoclingの採用を検討してみてください。