PDFファイルから特定の情報を効率的に抽出したい、と考えたことはありませんか?契約書や請求書など、ビジネスで扱うPDFは多岐にわたり、その中から必要な情報を探し出す作業は時に大きな負担となります。

近年、AI技術の発展により、こうした課題を解決するツールが登場しています。今回は、Google Cloudのサービスである「Document AI」と「Gemini API」を用いて、PDFから情報を抽出する2つの方法を比較検証してみました。

  • パターンA: PDFをDocument AIで高精度に文字起こし(OCR)し、そのテキストデータをGemini APIで解析して必要な情報を抽出する。
  • パターンB: PDFを画像ファイルに変換し、Gemini APIのマルチモーダル機能(画像認識・解析)のみで必要な情報を抽出する。

どちらの方法がより高い精度で情報を抽出できるのでしょうか?検証結果をもとに、それぞれの特徴と今後の可能性について考察します。

検証の背景と目的

ビジネス文書の多くはPDF形式でやり取りされますが、その内容は画像データとして扱われることも多く、単純なテキスト検索では情報を見つけられないことがあります。また、フォーマットが統一されていない文書から特定の項目(例:契約期間、金額、担当者名など)を抜き出す作業は、時間と労力がかかる単純作業になりがちです。

そこで、AIを活用した情報抽出が注目されています。今回は、特に精度の高さが期待される「Document AI + Gemini API」の組み合わせ(パターンA)と、よりシンプルな構成で実現できる「Gemini API単体」(パターンB)の2つのアプローチで、どちらがより実用的なのか、その精度を比較検証することを目的としました。

検証方法

今回は、いくつかのビジネス文書(PDF形式)を対象とし、以下の2つの方法で情報抽出を試みました。Google Colaboratory 環境でPythonコードを実行して検証を行いました。

パターンA:Document AI + Gemini API

  1. Document AIによる文字起こし: まず、Google CloudのDocument AIを使用し、PDFファイルから高精度なテキストデータを抽出します。Document AIは、OCR(光学的文字認識)技術に特化しており、レイアウトやフォントが異なる文書からも正確に文字を認識することを目指したサービスです。
  2. Gemini APIによる情報抽出: Document AIで抽出したテキストデータを、Gemini APIに入力します。そして、「契約期間を抽出してください」「支払条件は何ですか?」といった指示(プロンプト)を与えることで、テキストデータの中から目的の情報を抽出させます。

パターンB:Gemini APIのみ

  1. PDFの画像変換: 対象のPDFファイルを画像ファイル(例:PNG形式)に変換します。
  2. Gemini APIによる情報抽出: Gemini APIのマルチモーダル機能を活用し、画像ファイルを直接読み込ませます。パターンAと同様に、プロンプトを与えて画像内の文字情報を認識させ、目的の情報を抽出させます。

実行コード例(パターンA:Document AI + Gemini API on Google Colab)

今回の検証(パターンA)では、主に以下のようなPythonコードを実行しました。

1. 必要なライブラリのインストール

まず、Google Colaboratory 環境で、Google Cloud Document AIとGemini APIを利用するためのライブラリをインストールします。

Python

!pip install --upgrade google-cloud-documentai

!pip install -q -U google-genai

2. 認証と初期設定

Google Cloudへの認証情報を設定し、必要なライブラリをインポートします。APIキーもここで設定します。

Python

import os
from google.api_core.client_options import ClientOptions
from google.cloud import documentai
from google import genai
from google.genai import types
# import PIL.Image # パターンBで画像ファイルを扱う場合は必要

# --- Google Cloud認証 ---
# Google Cloudプロジェクトで作成したサービスアカウントキーのJSONファイルパスを指定します。
# Colabにアップロードするか、Google Driveをマウントしてパスを指定してください。
credentials_path = '/path/to/your/service-account-key.json' # ★あなたのキーファイルのパスに置き換えてください
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credentials_path

# --- Gemini APIキー設定 ---
# Google AI Studioなどで取得したAPIキーを設定します。
# 参考: https://aistudio.google.com/app/apikey
genai.configure(api_key="YOUR_API_KEY") # ★あなたのAPIキーに置き換えてください

# --- Document AI 設定 ---
project_id = "your-gcp-project-id"       # ★あなたのGoogle CloudプロジェクトIDに置き換えてください
location = "us"                         # 例: "us" または "eu" など、利用するリージョン
processor_id = "your-ocr-processor-id" # ★利用するDocument AIプロセッサID (例: OCR用)に置き換えてください

指定されたPDFファイルをDocument AIで処理し、抽出されたテキストを含むDocumentオブジェクトを返す関数です。

Python

def process_document(
    project_id: str,
    location: str,
    file_path: str,
    processor_id: str,
) -> documentai.Document:
    """
    指定されたPDFファイルをDocument AIで処理し、Documentオブジェクトを返す。
    """
    # Document AIクライアントの初期化 (リージョン指定)
    opts = ClientOptions(api_endpoint=f"{location}-documentai.googleapis.com")
    client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # プロセッサのフルパスを取得
    processor_path = client.processor_path(project_id, location, processor_id)

    # PDFファイルをバイナリで読み込む
    try:
        with open(file_path, "rb") as image:
            image_content = image.read()
    except FileNotFoundError:
        print(f"エラー: ファイルが見つかりません - {file_path}")
        return None

    # Document AIへのリクエストデータを作成
    raw_document = documentai.RawDocument(
        content=image_content,
        mime_type="application/pdf", # PDFの場合
    )

    # Document AIへ処理リクエストを送信
    request = documentai.ProcessRequest(name=processor_path, raw_document=raw_document)

    try:
        result = client.process_document(request=request)
        return result.document
    except Exception as e:
        print(f"エラー: Document AIでの処理中にエラーが発生しました - {e}")
        return None
4. Gemini API で情報を抽出する関数

与えられたテキスト(または画像とテキスト)とプロンプトをGemini APIに送信し、結果のテキストを返す関数です。

Python

def generate_content_with_gemini(contents):
    """
    Gemini APIにリクエストを送信し、生成されたテキストを返す。
    """
    # Geminiクライアントの初期化(APIキーは genai.configure で設定済み)
    # client = genai.Client() # genai.configureを使わない場合
    model = genai.GenerativeModel('gemini-pro') # テキストのみの場合 'gemini-pro'、画像も使う場合 'gemini-pro-vision' など
    try:
        response = model.generate_content(contents)
        return response.text
    except Exception as e:
        print(f"エラー: Gemini APIでの処理中にエラーが発生しました - {e}")
        # エラー内容によっては response.prompt_feedback などで詳細を確認
        if hasattr(e, 'response') and hasattr(e.response, 'prompt_feedback'):
             print(f"Prompt Feedback: {e.response.prompt_feedback}")
        return None

処理対象のPDFファイルパスリストを定義し、各ファイルに対してDocument AIでのテキスト抽出、Gemini APIでの情報抽出を順に実行します。

Python

# 処理対象のPDFファイルパスのリスト (サンプル)
file_paths = [
  '/path/to/your/invoice1.pdf',          # ★実際のファイルパスに置き換えてください
  '/path/to/your/agency_invoice_A.pdf', # ★実際のファイルパスに置き換えてください
  '/path/to/your/company_invoice_B.pdf',# ★実際のファイルパスに置き換えてください
  # ... 他のファイルパスを追加 ...
]

# Gemini APIに渡すプロンプト (情報抽出の指示)
# 具体的な抽出項目やルールは、対象のドキュメントに合わせて調整が必要です。
prompt = """
以下の[文字列]は、請求書をOCR処理した文字列です。
この[文字列]を解析し、[Jsonテンプレート]で指定されたテンプレートを使いつつ[ルール]に従ってJson文字列のみを返してください。
[ルール]----------------------
次の6つの項目の情報を抽出してください。
1.請求書NO
(以下略)
[文字列]----------------------
"""

# 出力形式を指定するJSONテンプレート
json_template = """
[Jsonテンプレート]----------------------
{
  "no": "%ここに請求書NOを入れてください%",
(以下略)
}
"""

# 各ファイルに対して処理を実行
for file_path in file_paths:
  print(f"--- Processing: {os.path.basename(file_path)} ---") # ファイル名を表示

  # 1. Document AIでテキスト抽出
  document = process_document(project_id, location, file_path, processor_id)

  if document and document.text:
    # 抽出したテキストを表示(確認用、必要に応じてコメントアウト)
    # print("--- Extracted Text (Document AI) ---")
    # print(document.text[:500] + "...") # 長すぎる場合は一部表示

    # 2. Gemini APIに渡すコンテンツを作成
    # プロンプト、抽出したテキスト、JSONテンプレートを結合
    gemini_input_text = "\n".join([prompt, document.text, json_template])

    # 3. Gemini APIで情報抽出
    print("--- Extracting Information (Gemini API) ---")
    extracted_json_text = generate_content_with_gemini([gemini_input_text]) # テキストのみ渡す

    if extracted_json_text:
      print(extracted_json_text)
    else:
      print("Gemini APIからの応答がありませんでした。")

  else:
      print("Document AIによるテキスト抽出に失敗しました。")

  print("-" * 40 + "\n") # ファイルごとの区切り線

# (参考) Geminiに渡す最終的な入力内容の例(プロンプト+OCRテキスト+テンプレート)
# print("--- Example Gemini Input ---")
# print("\n".join([prompt, "(ここにOCRで取得したテキストが入ります)", json_template]))

注意点:
  • 上記コードを実行するには、事前にGoogle Cloud Platformでプロジェクトを作成し、Document AI APIを有効化、サービスアカウントキーを作成・設定しておく必要があります。
  • Gemini APIキーも別途取得し、コード内に設定する必要があります。
  • file_paths やプロンプト内の抽出ルール ([ルール]) は、実際の業務や対象ドキュメントに合わせて適宜変更してください。
  • エラーハンドリングは基本的なもののみ含まれています。実際の運用では、より詳細なエラー処理を追加することを推奨します。
  • パターンB(Gemini APIのみ)の場合は、PDFを画像に変換する処理と、generate_content_with_gemini 関数に画像データを渡す処理(例: PIL.Image.open(image_path) で画像を開き、contents=[prompt, image] のように渡す)が必要になります。

評価方法

それぞれの方法で抽出した情報が、元のPDFの内容と一致しているかを目視で確認し、項目ごとの正解率と全体の正解率を算出しました。

検証結果:データで見る精度比較

検証の結果、全体的な正解率はパターンA(Document AI + Gemini API)の方が高いという結果になりました。

  • パターンA (Document AI & Gemini API) 全体正解率: 92.9%
  • パターンB (Gemini APIのみ) 全体正解率: 88.7%

僅差ではありますが、Document AIで一度テキスト化するステップを踏んだ方が、より正確に情報を抽出できる傾向が見られました。

項目別に見てみると、特に「契約期間」「自動更新の有無」「解約通知期限」といった項目で、パターンAの精度がパターンBを上回っていました。特に「解約通知期限」においては、パターンAが85.7%だったのに対し、パターンBは64.3%と、比較的大きな差が見られました。これは、Document AIがレイアウトを解析して正確にテキストを抽出する能力に長けているため、Gemini APIが後続の処理で情報を特定しやすくなったためと考えられます。

一方で、「支払条件」の項目では、パターンB(96.4%)がパターンA(92.9%)をわずかに上回る結果となりました。これは、支払条件に関する記述が比較的定型的な表現で書かれており、画像からの直接的な読み取りでもGemini APIがうまく解釈できた可能性が考えられます。

全体としては、「パターンAの方が”気持ち”精度が良かった」というのが今回の検証の結論です。

なぜDocument AI + Gemini APIの方が精度が高かったのか?(考察)

今回の検証でパターンAの精度がわずかに上回った理由としては、以下の点が考えられます。

  1. Document AIの専門性: Document AIは、その名の通り「文書」の解析に特化したAIです。PDFのような構造化・半構造化された文書から、レイアウトを考慮しつつ高精度にテキストを抽出する能力に優れています。これにより、Gemini APIはノイズの少ない、整理されたテキストデータを扱うことができ、結果として情報抽出の精度向上につながった可能性があります。
  2. Gemini APIの負担軽減: パターンBでは、Gemini APIが画像から文字を認識し、その意味を解釈して情報を抽出するという、複数のタスクを同時にこなす必要がありました。一方、パターンAでは文字認識の大部分をDocument AIが担うため、Gemini APIはテキストデータの「意味解釈」と「情報抽出」に集中できます。この役割分担が、最終的な精度の差に繋がったのかもしれません。

ただし、パターンBのGemini API単体での抽出精度も88.7%と決して低いわけではありません。PDFを画像変換する手間はありますが、Document AIを利用しない分、システム構成をシンプルにできるというメリットもあります。

今後の展望

今回は、比較的テキストが中心のビジネス文書で検証を行いました。しかし、実世界の文書には、手書きのメモが追記されていたり、図やグラフが多く含まれていたりするものも少なくありません。

今後は、以下のようなケースで検証を行うことで、それぞれの方法の得意・不得意をさらに深く理解できると考えています。

  • 手書き文字を含むPDF: Document AIやGemini APIが手書き文字をどの程度認識できるか。
  • 図や表が多いPDF: レイアウトが複雑な場合に、どちらの方法が正確に情報を抽出できるか。
  • 低解像度のPDF: スキャン状態が悪い文書での精度差。

これらの検証を通じて、ユースケースに応じた最適な情報抽出方法を見極めていきたいと考えています。

まとめ

今回の検証では、PDFからの情報抽出において、Document AIでテキスト化してからGemini APIで情報を抽出する(パターンA)方が、PDFを画像化してGemini APIのみで抽出する(パターンB)よりも、全体的にわずかに高い精度 を示すことが確認できました。

  • 精度を最優先するなら: Document AI + Gemini API の組み合わせが有力な選択肢。
  • システム構成のシンプルさやコストを重視するなら: Gemini API単体での活用も十分に検討の価値あり。

抽出したい情報の種類や、元のPDFの状態(テキスト中心か、図や手書きが多いかなど)によって、最適な方法は異なってくる可能性があります。

AIによる情報抽出技術は日々進化しています。今後、Gemini APIの画像認識能力がさらに向上すれば、パターンBの精度も追いつき、追い越す可能性も十分に考えられます。引き続き、最新技術の動向を注視し、より効率的な情報活用の方法を探っていきたいと思います。

最後までお読みいただき、ありがとうございました。この記事が、PDFからの情報抽出におけるAI活用を検討されている方々の参考になれば幸いです。