高品質なPDF抽出への近道

7 min read

高品質なPDF抽出への近道

エンタープライズを流れるPDFの多くは単純なものです。Google Docsからエクスポートされたレポート、CRMが生成した契約書、Wordから保存された仕様書など。テキストはファイルの中にそのまま存在し、完全にアドレス可能で、マイクロ秒単位で読み出せる状態にあります。それにもかかわらず、本番環境のOCRシステムは日常的にGPU時間を費やして、これらのページに対してvision modelを走らせ、そもそも画像ではなかったテキストの「画像」を「読んで」います。これは、本がすでに目の前で開かれているのに、その本を写真に撮ってから誰かに書き起こしてもらうようなものです。

DevRevでは、GLM-OCR(ドキュメント理解のためのvision-language model)をベースとした本番用のドキュメント抽出パイプラインをデプロイしました。本記事では、私たちが開発し利用しているハイブリッドなドキュメント抽出パイプラインについて説明します。そのスマートなルーティングは、各ページをネイティブテキスト抽出またはGLM-OCRのいずれかに振り分け、その必要がないページに対するGPU処理を回避し、私たちのトラフィックのおよそ27%についてメディアンレイテンシを240倍削減します。

ベースラインのパイプライン

最適化について説明する前に、私たちが改善しようとしているベースラインシステムを理解しておくことが重要です。

GLM-OCRパイプラインには2つのステージがあります。まず、レイアウト検出器PP-DocLayoutV3(CPU上で動作)— が各ページを処理し、領域を特定します。テキストブロック、タイトル、テーブル、数式、画像、その他の構造要素を識別し、それらのバウンディングボックスと種別ラベルを返します。次に、検出された各領域を切り出してGLM-OCR(GPU上で提供されるvision-language model)に送ります。GLM-OCRは切り出された画像を読み取り、構造化されたテキストを生成します(テキスト領域にはmarkdown、テーブル領域には整形されたテーブル、数式にはLaTeXなど)。

ba8e4a3deda33e5dce9b5d52d9f794cdb51cb319-2408x424.png

このベースラインは、あらゆる種類のPDFにわたって正確です。born-digitalのテキスト、スキャン、テーブル、数式を一様に処理できます。なぜなら、VLMは各領域を画像として見て、視覚的に解釈するからです。しかし、これは一様にコストが高くもあります。すべてのページのすべての領域が、難易度に関わらず、GPU推論の呼び出しを必要とします。各呼び出しには、キューイング(負荷が高いと大幅な待ち時間が加わる可能性があります)と自己回帰的なデコード(モデルは領域のテキストをトークンごとに生成するため、処理時間は出力長に比例します)のコストがかかります。実際には、1回のリクエストは — キュー待ちとデコードを含めて — 数秒から、高負荷時には最大10分ほどかかることもあります。born-digitalのPDFページ — コンテンツがすでにファイル内に完全に埋め込まれており、ミリ秒単位で抽出できるページ — に対しては、そもそも画像ではなかったものの「画像」を「読む」ために、私たちはこのコストを支払っているのです。

私たちが特定した非効率性

私たちは、そもそも画像ではなかったテキストを「読む」ためにGPU時間を費やしています。born-digitalのページでは、文字とその座標がすでにファイル内に存在しています — それにもかかわらず、ベースラインはそれらを高コストなvision modelに通しています。これこそが、私たちが取り組もうとしたベースラインのパイプラインにおける非効率性です。

ハイブリッドアーキテクチャ

私たちはベースラインにファストパスを追加しました。PyMuPDFfitz)を用いたネイティブテキスト抽出です。PDFページがborn-digitalである場合、文字とその座標はすでにファイル内に存在しており — PyMuPDFはそれらを直接読み出します。モデル推論もGPUも不要で、レイテンシはPDFのパースが支配的です。事実上、無償です。

こうして得られたハイブリッドアーキテクチャには3つのコンポーネントがあります。

  • レイアウト検出器(PP-DocLayoutV3、CPU)— すべてのページ上の領域を検出し、そのバウンディングボックスと種別ラベルを返します。これは無条件に実行されます。なぜなら、ターゲットを絞った切り出しでVLMを駆動するためにも、ページがファストパスの対象になり得るかを判定するためにも、領域構造が必要だからです。
  • ファストパス(PyMuPDF、CPU)— 対象となるページについて、PDF構造からネイティブにテキストを抽出します。GPUコストはゼロです。
  • VLMパス(GLM-OCR、GPU)— ネイティブ抽出の対象とならないすべてのページについて、切り出した領域画像に対して視覚的な読み取りを行います。

重要な問いはこうです。精度を損なうことなく、どのページがファストパスの対象になるかをどのように判定するのか?

d034bbd5e3f0956cc9b14457d45ddf654eeea236-3560x1036.png

ハイブリッドパイプライン:レイアウト検出はすべてのページで実行され、その後、各ページはページ単位の対象判定に基づいて、ネイティブのファストパスまたはVLMのいずれかに振り分けられます。

ルーティングの判断

最初の試み:領域単位のルーティング

もしあなた自身がこれを設計するとしたら、ほぼ間違いなくここから始めるでしょう — そして私たちもまさにそこから始めました。レイアウト検出器はすでにすべての領域を特定し、その種別をラベル付けしているので、当然の一手は各領域を独立にルーティングすることです。テキスト領域はファストパスへ、テーブル・数式・画像はVLMへ送るのです。それが正解に違いないと感じられます。構造上、節約を最大化します — ほとんどがテキストで単一のテーブルを含むページでは、テーブル領域だけがVLMのコストを支払い、それ以外はすべてネイティブに無償で解決されます。クリーンで、粒度が細かく、明らかに最適に思えます。

ところが、そうではありませんでした。このアプローチは許容できる結果を生みませんでした。

問題は、レイアウト検出器のバウンディングボックスが近似的であるという点です。それらは重なり合ったり、隣接するコンテンツを切り取ってしまったりすることがあります — ある段落の周りに描かれたボックスが、上や下の段落から1〜2行を取り込んでしまうことがあり、ネストしたボックス(大きなテキストブロック内のタイトルなど)は同じ単語を共有することがあります。VLMはこれに対して頑健です。切り出した画像を処理し、端にある無関係なコンテンツを無視して、意味的に関連する部分だけを読み取ることができます。ネイティブテキスト抽出にはそのような能力はありません。PyMuPDFが不完全なバウンディングボックス内のテキストを抽出すると、そのボックス内に座標が収まる文字をそのまま返します — 隣接する領域から切り取られた断片を含み、境界のすぐ外に座標がある単語を除外してしまいます。その結果、行の重複、単語の欠落、そして領域境界での誤った読み取り順序が生じます。

核心にある非対称性は次のとおりです。VLMはノイズの多い領域境界に対して頑健だが、ネイティブ抽出はそうではない。 したがって、領域単位のルーティングは、入力を文字どおりに解釈する手法に、レイアウト検出器の近似的なバウンディングボックスを頼らせることになりますが、それらは必ずしも信頼できません。わずかに不正確な切り出しが、テキストの重複、単語の欠落、あるいは読み取り順序の乱れを引き起こす可能性があるのです。

native-flowchart-2.png

領域単位のルーティングは、検出器のボックスが近似的であるために失敗します。VLMはノイズの多い切り出しを許容しますが、ネイティブ抽出はバウンディングボックスの座標を文字どおりに受け取り、領域境界で破損した出力を生成します。

解決策:ページ単位のルーティング

私たちはルーティングの判断をページレベルへと引き上げました。ページがネイティブ抽出に対して明白に安全である場合にのみ、ページ全体にファストパスを使います。ページが対象になるのは、次の4つのチェックすべてに合格した場合のみです。

  1. ページ上で検出されたすべての領域がテキスト領域であること。 テーブルや数式は、構造化されたmarkdownの整形(例:パイプ区切りのテーブル、LaTeX)を必要としますが、PyMuPDFのようなネイティブ抽出ライブラリはそれを生成できません — 生のテキストを返すことしかできず、構造を再構築することはできません。レイアウト検出器がテーブル、数式、または画像の領域を1つでも識別した場合、ページ全体がVLMに振り分けられます。
  2. ページに実質的な埋め込みテキストレイヤーがあること(テキスト文字数 ≥ 8)。 ページは、テキストレイヤー内に抽出可能な文字を少なくとも8つ含んでいなければなりません。この下限は、技術的にはテキストレイヤーを持つものの、ネイティブに意味のある形で抽出するにはコンテンツが少なすぎるページ(例:ページ番号だけ、あるいは単一のヘッダーだけのページ)を除外します。
  3. テキストレイヤーが本当に可視であり、OCRのオーバーレイではないこと(可視テキスト比率 ≥ 0.7)。 PDFにはテキストレンダリングモードがあり、テキストの表示方法を制御します。スキャンされたPDFは、PDFを検索可能にするためにテキストレイヤーを追加するOCRツールによって処理されることがあります。これらはしばしば精度の低いOCRエンジンであり、このテキストを抽出すると私たちの出力品質に悪影響を及ぼします。しかし、これらのツールはレンダリングモード3または7でテキストを追加するのに対し、born digitalのPDFに埋め込まれたテキストはレンダリングモード0にあります。私たちは、可視のレンダリングモード(モード0)で描画されたテキストスパンと、不可視のレンダリングモード(モード3または7)で描画されたテキストスパンの割合を計算します。テキストの少なくとも70%が可視であれば、それを本物のborn-digitalページとして扱います。そのしきい値を下回る場合、テキストレイヤーはスキャン上のOCRオーバーレイである可能性が高いため、代わりにVLMに振り分けます。
  4. 未割り当ての単語チェック。 ネイティブ抽出の後、私たちは抽出された各単語を、その中心点によってレイアウト検出された領域に割り当てます。いずれかの単語がどの領域にも割り当てられない場合、それはテキストレイヤーと検出されたレイアウトの間の不一致を示しており — ページは他のチェックが示すほどクリーンではない可能性があります。この場合、ページはVLMにフォールバックします。
5055f4fad55cc05cb619fea83c78683c59d81c2d-2000x2160.png

ページ単位の対象判定ゲート。ページはいずれかのチェックに失敗した時点でVLMへと流れ落ちます。すべての条件に合格したページだけがネイティブに解決されます。

ゲートに失敗したものはすべて、変更されることなくVLMへ流れます。ファストパスは、正しく動作するVLMベースラインの上に重ねられた純粋な最適化レイヤーです。最悪の場合でも何も寄与しないだけで、システムはall-VLMパイプラインと比べて何ら劣ることはありません。

なぜページ単位が正しい粒度なのか

領域単位のルーティングは理論上より大きな節約をもたらしますが、検出器のバウンディングボックスは、入力を文字どおりに解釈する手法に与えるにはノイズが多すぎます。ページは、(a) コンテンツの種別について信頼できる判断を下すことと、(b) 個々のバウンディングボックスを信頼するのではなく、ページ全体のグローバルな文脈を用いて単語を領域に割り当てることの、両方を実現できる最小の単位です。トレードオフは、混在ページ(例:80%がプレーンテキストで1つのテーブルを含むページ)が、そのコンテンツのほとんどをネイティブに抽出できるにもかかわらず、まるごとVLMに送られてしまうことです。私たちは出力の正しさを保証するのと引き換えに、これを受け入れました。

結果とインパクト

私たちのシステムでユーザーによって取り込まれた101,134ページの代表的なコーパス全体にわたって、ルーティングゲートはおよそ27%のページ(27,295ページ)をネイティブのファストパスに、残りの73%(73,839ページ)をVLMに振り分けます。

d3217dbf41dd60fc761f001cf1a9b062e553503f-2000x790.png

ファストパスは平均でおよそ240倍高速であり、GPUリソースを一切必要としません。それが処理する27%のページについては、GPU推論時間もキューの圧迫もバッチ処理のレイテンシもありません。これは、VLM処理を必要とする残り73%のページのスループットを直接的に向上させます。なぜなら、ネイティブに解決できるはずのページによってGPU容量が消費されないからです。

精度

私たちの評価全体にわたって、すべての精度指標はall-OCRベースラインの2〜3%以内に収まりました。ページは保守的な安全チェックを通過した後にのみネイティブにルーティングされ、失敗したチェックはすべてOCRベースラインにフォールバックします。

これが効くところ — そして効かないところ

これはワークロードに依存する最適化であり、万能なOCRの近道ではありません。その価値は、対象判定ゲートの下でネイティブ抽出に対して安全なページの割合によって決まります。

これは、born-digitalでテキストのみのページを多く含むドキュメントコレクションにとって特に有効です。たとえば、テキストがPDFに埋め込まれているレポート、契約書、仕様書、エクスポートされたビジネス文書などです。一方で、画像の多いドキュメント、スキャンされたページ、フォーム、テーブルや数式を含むページ、視覚的に複雑なレイアウトに対しては、はるかに有用性が低くなります。それらのページは正しくOCRパスに残るため、抽出品質のベンチマークや高度に構造化された顧客コーパスに対しては、ファストパス率がゼロに近くなることもあります。

私たちの本番環境全体のルーティング率は、およそ27%のページです。この全体値は、顧客レベルの大きなばらつきを覆い隠しています。ある顧客のインポートはクリーンでborn-digitalなテキストページの割合が高く、70〜80%のページがファストパスを通ります。別の顧客では、その率は5〜10%に近くなります。

モデル非依存のルーティング

このルーティング手法はGLM-OCRに固有のものではありません。ネイティブPDF抽出とフォールバックのOCRモデルを組み合わせるものであり、フォールバックを別のOCRモデルやvision-language modelに置き換えても同じ原理が当てはまります。高速化は、PDFのテキストレイヤーが明白に安全に使えるページに対してモデル推論を回避することから生まれます。フォールバックするすべてのページについては、依然としてモデルの品質が重要です。

精度優先のルーティング

私たちの実装は、意図的に保守的な2つの決定を下しています。

  • ページ単位のルーティング。 私たちは領域単位ではなくページ単位でルーティングします。なぜなら、ネイティブ抽出は検出器のボックスを文字どおりに解釈するのに対し、OCRモデルは不完全な切り出しを許容するからです。
  • テキストのみを対象とすること。 テーブル、数式、画像、および保守的なチェックに失敗するページは、すべてOCRパスに残ります。

これらの選択は組み合わさって出力品質を優先しており、all-OCRベースラインからわずか2〜3%の精度差にとどまることと整合しています。ただし、これらは普遍的な要件ではありません。チームは、自らのワークロードにとってどの程度の劣化が許容できるかを判断する必要があります。

たとえば、より保守的でないページ単位のポリシーであれば、テーブルや数式を含むページを、ページ全体をOCRに送る代わりにファストパスで処理させることができます。多くのPDFは他の点では単純であるにもかかわらず、単一のテーブルや数式を含んでおり、それだけで現在のポリシーではページ全体がOCRに振り分けられてしまいます。そうしたページをファストパスに乗せることは、不完全なMarkdownテーブルの再構築や数式の整形が下流のユースケースにとって許容できるのであれば、カバレッジを実質的に高められる可能性があります。

次のステップと締めくくりの考察

ここからの最も差し迫った方向性は、混在ページのルーティングです。現在は、非テキスト領域を1つでも含むページ(例:他はすべてテキストのページ上の単一のテーブル)は、まるごとVLMに振り分けられます。レイアウト検出器が改善され、よりタイトなバウンディングボックスを生成するようになれば、混在ページのテキスト領域に対しては選択的にネイティブ抽出を適用し、複雑な領域だけをVLMに振り分けることが実現可能になるかもしれません。私たちがこの記事を書いたのは、これに着手しようとしたとき、本番環境でのハイブリッド抽出に関する先行研究を探したものの、ほとんど見つからなかったからです。一般的な推奨事項は存在します — 一括抽出にはファストパスを使い、残りはモデルにフォールバックする — しかし、そのルーティングを正しく実装する方法、当たり前のアプローチを試したときに何が失敗するのか、あるいはスケールで稼働させたときに運用上どんな驚きがあるのかについて、詳細な記述を見つけることはできませんでした。これはそのギャップを埋めるための私たちの試みです。

参考文献

  1. GLM-OCR — ドキュメントOCR向けのvision-language model。
  2. PP-DocLayoutV3 (PaddleOCR) — ドキュメントのレイアウト検出モデル。
  3. PyMuPDF (fitz) — MuPDFライブラリのPythonバインディング。ネイティブなPDFテキスト抽出。

1/2

DEVREV

See Computer work for you

Your AI teammate that finds answers, takes action, and gets work done across every tool.