請求書読み取りにおけるOCRとLLMの最適な役割分担 - LLMに何をさせるべきか
はじめに
LLMの急速な発展により、文書からの情報抽出タスクにおいてもLLMを活用する事例をよく見るようになりました。特に請求書や領収書などの帳票類からの情報抽出では、「とりあえずLLMに画像を渡せば何とかしてくれる」という風潮すらあるように感じます。
しかし、実際の業務システムで高い精度と安定性を求める場合、LLMに全てを任せるアプローチには早々に限界がやってきます。
また、ここでいうOCRというのはただの文字読み取りではなく、業務ドメインに基づく解釈を含めた形で結果を返すことが求められています。[1][2]
今回は弊社e-dashでの請求書読み取り機能の開発経験をもとに、OCRとLLMそれぞれの得意分野を活かした役割分担の考え方と、その検証結果を共有します。
請求書読み取りタスクの整理
読み取りに必要なステップ
請求書から必要な情報を抽出するには、以下のような複数のステップが必要です
- 読み取る目的を決める - 何の情報が必要かを明確にする
- 全体構造の把握 - どこに何が書いてあるか理解する
- 目的の情報を特定 - 必要な情報がある箇所を見つける(複数箇所の場合も)
- 情報の抽出 - テキストとして取り出す
- 後処理 - 消費税込みか判断して計算、数量・金額の合計など
e-dashでの要件
e-dashではエネルギー使用量をもとにCO2排出量を計算しています。そのため、請求書から以下の情報を読み取る必要があります。
金額はCO2排出量の計算に必要な値ではありませんが併せて管理しています。
| カテゴリ | 必要な情報 |
|---|---|
| 基本情報 | 供給会社名、契約プラン |
| 使用量 | 電気・ガス・ガソリンなどの使用量(kWh、m³) |
| 金額 | 請求金額 |
| 期間 | 使用期間、請求日 |
また、1つの請求書に複数の使用量データが含まれる場合は、それらを合計して扱うという業務要件もあります。
各アプローチと課題
LLMに全てを任せるアプローチ
最もシンプルなアプローチは、請求書画像をそのままLLM(GPTなど)に渡し、必要な情報をJSON形式で出力させる方法です。
今回は例を簡単にするため、プロンプトも省略しています。
【プロンプト例】
以下の請求書画像から、請求金額、使用量、使用期間を抽出し、以下のJSON形式で出力してください。
...
{
"invoice": {
"inovoice_data": "2025-11-01",
"supply_company": "供給会社",
"plan_name": "契約プラン",
"usage": "123.45",
"billing_amount": 12345,
}
}
このアプローチには以下のメリットがあります。
- 実装がシンプル
- 柔軟な対応が可能
- 新しいフォーマットへの対応が容易
LLMだけでは難しい点
しかし、実際にテストしてみると以下の課題が見えてきました。
-
文字認識の精度にばらつき
- 画像の品質や文字の大きさによって認識精度が変動
- 特に数字の誤認識(0とO、1とl など)が発生
-
構造認識の不安定さ
- 表形式のデータを正確に構造化できないことがある
- 複数ページにまたがる情報の統合が困難
-
ハルシネーションのリスク
- 存在しない情報を「それらしく」生成してしまう可能性
改善手法:OCRとLLMの役割分担
基本的な考え方
前述の課題や文献等[3][4][5]を踏まえ、各処理に最適なツールを選択するアプローチを試しました。
| 処理 | 担当 | 理由 |
|---|---|---|
| 文字認識(テキスト化) | OCR | Computer Vision 高精度・高速・安定 |
| 構造化(表の認識) | OCR | Document Intelligenceの専門機能 |
| 情報の特定・抽出 | LLM(gpt-5) | 必要な抽出箇所の理解を任せる |
| 後処理(計算等) | プログラム | 正確性が必須 |
つまり、LLMの役割を「テキストから目的の情報を見つけ出す」ことに限定し、文字認識や構造化はOCRに、計算処理はプログラムに任せるという分担です。
Azure Document Intelligenceの活用
Document Intelligence(旧Form Recognizer)は、文書の構造を理解した上でテキスト抽出ができるOCRサービスです。
主な特徴:
- 高精度な文字認識 - 手書き文字にも対応
- 表構造の認識 - 行・列の関係性を保持したまま抽出
- 事前学習済みモデル - 請求書、領収書など帳票タイプ別のモデルを提供
- 座標情報の取得 - 文字の位置情報も取得可能
特に重要なのは表構造の認識機能です。請求書の多くは表形式でデータが記載されており、この構造をDocument Intelligenceが正確に抽出してくれるため、LLMで構造を推測する必要がなくなります。
また、各テキストのbounding box(テキストが記載されている位置情報)を合わせてLLMに渡すと構造理解のサポートとなるという知見[4:1]がありますが、構造化に関する情報はDocument Intelligenceのレスポンスにあるtableを利用することとしました。
処理フローの比較
シンプルなアプローチ(画像のみをLLMに渡す)
請求書画像 → LLM(文字認識+構造化+抽出) → 結果
提案アプローチ(役割分担)
請求書画像 → Document Intelligence(文字認識+構造化)
→ テキスト+表データ
→ LLM(情報の特定・抽出)
→ プログラム(計算)
→ 結果
LLMへの入力が画像だけではなく構造化されたテキストデータになることで、処理が安定し、プロンプトも明確になります。
検証と考察
検証条件
請求書データを用いて、以下の5つの手法を比較しました。
| 手法 | 説明 |
|---|---|
| OCR+画像+サーバーサイド計算 | Document Intelligenceでテキスト抽出→LLMで情報抽出→数値合計 |
| OCR+画像 | Document Intelligenceの結果と画像の両方をLLMに入力 |
| OCRのみ(Document Intelligence) | Document Intelligenceの結果→LLMで情報特定 |
| OCRのみ(Computer Vision) | Computer Visionの結果→LLMで情報特定 |
| 画像のみ | LLMに画像を直接入力して全処理を実行 |
評価指標は 読み取り精度(正解率) で、電気・ガス・ガソリンなどシンプルなものから複雑なものまで900件の請求書を用いました。
各請求書について金額と数量についてプログラムが返した値と実際に入力したい値の一致率を測定しました。
検証結果
各手法の読み取り精度の相対評価は概ね以下の通りでした。
| 手法 | 読み取り率 | 備考 |
|---|---|---|
| OCR+画像+サーバーサイド計算 | ◎ | 精度は最も高かった(約80%) |
| OCR+画像 | ○ | 計算の必要な箇所で間違っていたようだった(約70%) |
| OCRのみ(Document Intelligence) | ○ | OCR+画像とほぼ変わらない結果であり、さらに結果取得までの時間が数秒短かった(約70%) |
| OCRのみ(Computer Vision) | △ | Document Intelligenceに比べ明確に差があった(約65%) |
| 画像のみ | △ | 精度は最も低かった。シンプルな請求書は読み取れていた(約60%) |
構成が複雑、解像度が低い画像、割引などの考慮、税込か税抜かの判断が必要な請求書に関してはまだまだ改善の余地がありそうです。
考察
画像情報が効果的でなかった理由
「OCR結果と画像の両方を渡した方が精度が上がる」と言われていますが、今回の検証ではその効果は確認できませんでした。これには以下の理由が考えられます
-
タスクの性質
- 請求書読み取りは主に「文字情報の抽出」が目的
- 画像や色などの視覚的情報は重要度が低い
-
Document Intelligenceの性能
- 表構造を正確に認識できるため、位置関係の情報が不要
- LLMが構造を推測する必要がない
OCRのみ(Document Intelligence)が有効だった理由
構造化をDocument Intelligenceに任せることで、LLMは「情報の特定」に集中できるという点が大きなメリットでした。
例えば、以下のような表形式のデータ
| 項目 | 数量 | 単価 | 金額 |
|---|---|---|---|
| 電気 | 150 | 27 | 4,050 |
| ガス | 20 | 130 | 2,600 |
これがDocument Intelligenceによって構造化された形で取得できるため、LLMは「使用量の列から電気の値を取得する」という明確なタスクに集中できます。
また、Computer Visionで得られる読み取った文字は項目名との関係に関する情報を持たないため数量なのか金額なのかの判別が困難です。
サーバーサイド計算の重要性
最も高い精度を達成したのは、 計算処理をサーバーサイドで行う 方式でした。
例として、以下のような明細テーブルを含むデータに対して、ガソリンを抽出して数量、金額を合計するケースを考えます。
灯油は別のエネルギーとして扱いたいため除外する必要があります。
ここでの正解は数量:632、金額:113,760であり、金額については116,360を読み取ってしまうと不正解となります。
| 項目 | 数量 | 単価 | 金額 |
|---|---|---|---|
| ガソリン | 150 | 180 | 27,000 |
| ガソリン | 122 | 180 | 21,960 |
| ガソリン | 135 | 180 | 24,300 |
| 灯油 | 28 | 130 | 2,600 |
| ガソリン | 42 | 180 | 7,560 |
| ガソリン | 183 | 180 | 32,940 |
| 計 | 116,360 |
これは、LLMに以下のような計算を任せないことを意味します
- 複数項目の合計
- 税込み金額の計算
LLMは計算ミスをすることがあり、特に複数の数値を扱う場合に誤りが発生しやすいです。抽出した個々の値をプログラムで計算することで、この問題を回避します。
手法選定のポイント
実際に請求書読み取りシステムを構築する際の判断基準をまとめます。
LLMに任せるべきタスク
- 曖昧な情報の特定 - 「請求金額」がどの項目を指すか判断
- 文脈を踏まえた抽出 - 複数の候補から適切な値を選択
- 自然言語での指示理解 - プロンプトによる柔軟な制御
LLMに任せるべきでないタスク
- 文字認識 - OCRの方が高精度・高速
- 構造の認識 - Document Intelligenceの専門機能を活用
- 計算処理 - プログラムで正確に実行
- 検証・バリデーション - ルールベースで確実に実行
まとめ
本記事では、請求書読み取りにおけるOCRとLLMの最適な役割分担について検討しました。
主な結論
-
LLMの役割は限定すべき
- 全てをLLMに任せると精度・安定性が低下
- 「文脈を踏まえた情報特定」に特化させる
-
OCR(Document Intelligence)の活用
- 文字認識と構造化はOCRが得意
- 表形式データの抽出で大きなアドバンテージ
-
計算処理はプログラムで
- LLMの計算ミスを防ぐことで精度を確保
-
画像情報は必ずしも必要ない
- タスクの性質によっては効果が限定的
今後の展望
今回の検証はgpt-5で行いましたが、gpt-5.1やその他のモデルでは結果が変わる可能性があります。また、LLMのファインチューニングによる特化型モデルの活用も検討の余地があります。
重要なのは、「何に何を任せるべきか」という設計思想を持つことです。LLMの進化は目覚ましいですが、それでも適材適所の考え方は変わりません。
Discussion
大変勉強になりました!
実践を踏まえたナレッジが詰まっていて、とても良い記事ですね。
おー!
コメントありがとうございます!