CCCMKホールディングス TECH LABの Tech Blog

TECH LABのエンジニアが技術情報を発信しています

ブログタイトル

様々な形式のドキュメントからテキスト情報を取得する"Docling"を使ってみる。

こんにちは、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
arXivURLhttps://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を使う、というオプションも頭に入れておくと良いかもしれません。

【引用】Docling Technical Report, Table 1

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として保存したものです。

この記事(https://techblog.cccmkhd.co.jp/entry/2024/11/19/133101)をPDFで保存

PPTXは次のような内容のものを作成しました。

3スライドで構成されるPPTXを作成しました。

XLSXは2シートで構成されるものを用意しました。データは以前RAGのRetrieverの性能評価のためにgpt-4oで作成したものです。 1シート目はデータそのもの。

XLSXの1シート目

2シート目はピボットで集計した表が含まれています。

XLSXの2シート目。

ではDoclingを使ったファイルの解析処理を具体的に見ていきます。といってもコードはとても短いです。

対象のファイルパスを、doclingDocumentConverterクラスの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の内容がマークダウンとして再現できているようです。

PDFの解析結果1

PDFの解析結果2

"レビュー"の"ー"が半角("-")になっていたりしますが、リストや表もちゃんと再現できています。

PPTXの場合

以下を実行。

pptx_result = result_dict["LangGraphで組むMap-reduce型の処理.pptx"]
pptx_result_md = pptx_result.document.export_to_markdown()
display(Markdown(pptx_result_md))

結果はこちら。テキスト部分は再現できています!

PPTXの解析結果

一方図は無視されていることが分かりました。テクニカルレポートに書いてあったようにOCRはオンオフの切り替えが可能で、デフォルトではオフになっているようです。

デフォルトでは図は処理対象になっていないようです。

XLSXの場合

最後はXLSXです。次を実行しました。

excel_result = result_dict["テストデータ.xlsx"]
excel_result_md = excel_result.document.export_to_markdown()
display(Markdown(excel_result_md))

ちゃんと2シートに分かれた表がマークダウンで再現できていました!

XLSXの1シート目の結果の抜粋

XLSXの2シート目の結果の抜粋

まとめ

ということで、今回は様々な形式のドキュメントからテキストを抽出出来るDoclingというライブラリについて調べ、色々なファイルでどのように解析がされるのかを確認してみました。テキストについてはかなり忠実に再現できていて、すごいなぁと思いました。Doclingは処理パイプラインをカスタマイズすることが出来るようなので、もう少し色々と試していきたいと思います。