こんにちは、CCCMKホールディングス TECH LABの三浦です。
先日チームのメンバーに教えてもらい、試してみたいな・・・と思っていたライブラリを今回試すことが出来ました。"Docling"というライブラリで、PDFなどのファイルから、内容をマークダウンかjsonのテキストデータで抽出することが出来るライブラリです。RAGでの活用が期待できます。
試しに使ってみたところ、日本語のファイルでもかなり良い感じにテキストデータが取得出来ており、すごいなぁとビックリしました。
DoclingはarXivにテクニカルレポートがあり、そちらを読むことでどういったパイプラインで処理を行っているのかを理解することが出来ました。
今回の記事では、まず最初にテクニカルレポートを参照してDoclingの処理パイプラインについてまとめ、その後にインストールから実行までの基本的な使い方を試してみたのでご紹介したいと思います。
Doclingの処理パイプライン
ここからの記事を書くにあたり、参照したDoclingのテクニカルレポートは以下です。
Title :Docling Technical Report
Authors : Christoph Auer, Maksym Lysak, Ahmed Nassar, Michele Dolfi, Nikolaos Livathinos, Panos Vagenas, Cesar Berrospi Ramis, Matteo Omenetti, Fabian Lindlbauer, Kasper Dinkla, Lokesh Mishra, Yusik Kim, Shubham Gupta, Rafael Teixeira de Lima, Valery Weber, Lucas Morin, Ingmar Meijer, Viktor Kuropiatnyk, Peter W. J. Staar
Submit :
Submitted on 19 Aug 2024 (v1), last revised 30 Aug 2024
arXivURL :https://arxiv.org/abs/2408.09869
このレポートの中の「3 Processing pipeline」のセクションにDoclingの処理の内容が説明されています。
Doclingがファイルを受け取り、テキストデータ化するまでには"PDF parser", "Layout Analysis", "Table Structure Recognition", "OCR", "Assemble"といったプロセスをたどります。
それぞれのプロセスについて、以降でまとめていきます。
ちなみに現在Doclingライブラリのバージョンは現在2が公開されていて、テクニカルレポート時点から継続的に機能改善や追加が行われています。そのため一部の内容がライブラリのものと異なる可能性があります。たとえばDocling V2ではPPTX, XLSXといった形式のファイルも取り扱うことが出来ますが、テクニカルレポートの段階ではPDFのみが取り上げられています。
PDF parser
このステップではPDFから全てのテキスト情報とページ内の座標と画像や色などの視覚情報が抽出されます。Doclingではこの部分に"qpdf"というライブラリをカスタマイズした独自の処理を使用していて、それらは"docling-parse"というライブラリにまとめられています。PDFを読み取るPythonのライブラリは他にも色々あり、その中の"pypdfum"というライブラリを代わりに使用することも出来るそうです。ただ抽出結果の品質、という観点では課題があるようで、基本的にはDoclingのデフォルトを使うのが良いかな、と思います。
一方テクニカルレポートには、PDF parserをDoclingのデフォルト(native backend)とpypdfum(pypdfum backend)にした場合の処理時間やピーク時のメモリ使用量の比較結果がまとめられているのですが、これを見ると処理時間やメモリ使用量といった観点ではpypdfumが良い結果となっているので、使えるリソースが限られている場合などはpypdfumを使う、というオプションも頭に入れておくと良いかもしれません。
Layout Analysis
PDFのページを画像として読み込み、ドキュメントの構成要素を物体検出モデルで抜き出す処理を行います。使われるモデルはRT-DETRというアーキテクチャをDocLayNetというDocument-Layout分析用のデータセットで再学習したものとのことです。ドキュメントの構成要素として"段落(paragraphs)", "セクションのタイトル(section titles)", "リスト(list items)", "キャプション(captions)", "図(figures)", "表(tables)"といったものが識別されます。
画像は72dpiの解像度で入力されるそうです。この解像度だと1CPUで1秒未満くらいで処理が実行出来るとのことです。
Table Structure Recognition
前のLayout Analysisのステップで取得されたページ内の"表"部分は、TableFormerというモデルに入力されます。TableFormerはvision-transformerのモデルで、セルの結合があったりインデントや配置が統一されていないなどの複雑な表形式も認識できるとのことです。
表の解析は、セルに含まれる情報量に依存しますが、一般的なCPUで2~6秒くらいかかるそうです。Layout Analysisに比べると結構時間がかかる印象を受けました。表がたくさん含まれているPDFは、処理に時間がかかると頭に入れておいた方が良さそうです。
OCR
紙の資料をスキャンして作成したPDFやPDF内の図を解析するために、DoclingではEasy OCRというOCRライブラリを使ったOCR処理が実装されています。OCRはオプションで実行のオンオフの切り替えが可能です。Easy OCRを使ったDoclingの処理では216dpiという高解像度な画像の入力が必要で、そのためCPUだと1ページ30秒以上処理にかかってしまうようです。
テクニカルレポートではOCR処理の改善に取り組んでいる、と記載されていたので、もしかしたら最新のDoclingでは処理速度が改善されているかもしれません。
Assembly
パイプラインで抽出された結果はdocling-coreで構造が定義された、DoclingDocument
というオブジェクトに集約されます。その後は言語の識別、読む順番などの解析が行われ、ユーザが指定したマークダウンなどの形式に変換して出力することが可能になります。
やってみる
ここからはDoclingを使ってみたことをまとめます。セットアップは簡単で、pip install docling
を実行し、ライブラリをインストールすればOKです。私の環境では、以下のライブラリ一式がインストールされました。
docling==2.8.1 docling-core==2.5.1 docling-ibm-models==2.0.6 docling-parse==2.1.2
ライブラリのインストールに加え、初めて変換処理を実行する際にHugging Faceからのモデルのダウンロード処理が実行されます。
さて、テスト用にPDF, PPTX, XLSX形式のファイルを用意しました。
PDFはこのブログのページをPDFとして保存したものです。
PPTXは次のような内容のものを作成しました。
XLSXは2シートで構成されるものを用意しました。データは以前RAGのRetrieverの性能評価のためにgpt-4oで作成したものです。 1シート目はデータそのもの。
2シート目はピボットで集計した表が含まれています。
ではDoclingを使ったファイルの解析処理を具体的に見ていきます。といってもコードはとても短いです。
対象のファイルパスを、docling
のDocumentConverter
クラスのconvert_all
に渡します。この段階ではまだ処理が実行されません。
import os from docling.document_converter import DocumentConverter doc_converter = DocumentConverter() # ファイルパスを取得 files = [f"./docs/{file}" for file in os.listdir("./docs")] # 3つのファイルを解析対象に指定 conv_results_iter = doc_converter.convert_all( files )
結果にアクセスを試みると、Hugging Faceからモデルのダウンロードが始まり、処理が実行されます。
result_dict = {} # 3つのファイルの解析結果をファイル名をキーにした辞書型に変換しておく for result in conv_results_iter: result_dict[result.input.file.name] = result
今回の検証はDatabricksのNotebookで行っています。Notebookではマークダウン形式のテキストをマークダウンとして表示させることが出来るので、それを使ってどのようにテキストが抜き出されたかを確認してみました。
PDFの場合
以下のコードを実行。
from IPython.display import Markdown pdf_result = result_dict["DatabricksとOllamaによるLLMアプリの実験と検証 - CCCMKホールディングス TECH LABの Tech Blog.pdf"] pdf_result_md = pdf_result.document.export_to_markdown() display(Markdown(pdf_result_md))
以下のように、かなり忠実にPDFの内容がマークダウンとして再現できているようです。
"レビュー"の"ー"が半角("-")になっていたりしますが、リストや表もちゃんと再現できています。
PPTXの場合
以下を実行。
pptx_result = result_dict["LangGraphで組むMap-reduce型の処理.pptx"]
pptx_result_md = pptx_result.document.export_to_markdown()
display(Markdown(pptx_result_md))
結果はこちら。テキスト部分は再現できています!
一方図は無視されていることが分かりました。テクニカルレポートに書いてあったようにOCRはオンオフの切り替えが可能で、デフォルトではオフになっているようです。
XLSXの場合
最後はXLSXです。次を実行しました。
excel_result = result_dict["テストデータ.xlsx"]
excel_result_md = excel_result.document.export_to_markdown()
display(Markdown(excel_result_md))
ちゃんと2シートに分かれた表がマークダウンで再現できていました!
まとめ
ということで、今回は様々な形式のドキュメントからテキストを抽出出来るDoclingというライブラリについて調べ、色々なファイルでどのように解析がされるのかを確認してみました。テキストについてはかなり忠実に再現できていて、すごいなぁと思いました。Doclingは処理パイプラインをカスタマイズすることが出来るようなので、もう少し色々と試していきたいと思います。