Document AI(Python)を使用した専用プロセッサ

1. はじめに

この Codelab では、Document AI 専用プロセッサを使用して Python で特殊なドキュメントを分類して解析する方法を学びます。分類と分割では、請求書、領収書、公共料金明細を含むサンプル PDF ファイルを使用します。次に、解析とエンティティ抽出では、請求書を例として使用します。

この手順とサンプルコードは、Document AI でサポートされている特殊なドキュメントであれば、すべてで使用できます。

前提条件

この Codelab は、Document AI の他の Codelab の内容に基づいて作成されています。

このラボを始める前に、次の Codelab を完了しておくことをおすすめします。

学習内容

  • 専門的なドキュメントの分割ポイントを分類して特定する方法。
  • 専用プロセッサを使用してスキーマ化されたエンティティを抽出する方法。

必要なもの

  • Google Cloud プロジェクト
  • ブラウザ(ChromeFirefox など)
  • Python 3 の知識

2. 設定する

この Codelab は、入門編の Codelabにある Document AI の設定手順を完了していることを前提としています

先に進む前に、次のステップを完了してください。

Python 用の一般的なデータ分析ライブラリである Pandas もインストールする必要があります。

pip3 install --upgrade pandas

3. 専用プロセッサを作成する

まず、このチュートリアルで使用するプロセッサのインスタンスを作成する必要があります。

  1. コンソールで、Document AI Platform の概要に移動します。
  2. [プロセッサを作成] をクリックし、[専用] まで下にスクロールして、[調達ドキュメント スプリッター] を選択します。
  3. 名前を「codelab-procurement-splitter」(または覚えている名前)にして、リストから最も近いリージョンを選択します。
  4. [作成] をクリックして、プロセッサを作成します。
  5. プロセッサ ID をコピーします。これは、後でコード内で使用します。
  6. 手順 2 ~ 6 を Invoice パーサー(「codelab-invoice-parser」という名前を付けることができます)で繰り返します。

コンソールでプロセッサをテストする

ドキュメントをアップロードして、コンソールで Invoice パーサーをテストできます。

[ドキュメントをアップロード] をクリックして、パースする請求書を選択します。使用できる請求書がない場合は、この請求書のサンプルをダウンロードして使用できます。

google_invoice.png

出力は次のようになります。

InvoiceParser.png

4. サンプル ドキュメントをダウンロードする

このラボで使用するサンプル ドキュメントがいくつか用意されています。

PDF ファイルは次のリンク先からダウンロードできます。ダウンロードしたファイルを Cloud Shell インスタンスにアップロードします。

または、gsutil を使用して、Google の Cloud Storage 公開バケットからダウンロードすることもできます。

gsutil cp gs://cloud-samples-data/documentai/codelabs/specialized-processors/procurement_multi_document.pdf .

gsutil cp gs://cloud-samples-data/documentai/codelabs/specialized-processors/google_invoice.pdf .

5. ドキュメントを分類して分割する

このステップでは、オンライン処理 API を使用して、複数ページのドキュメントの論理的な分割点を分類、検出します。

複数のファイルを送信する場合や、ファイルサイズがオンライン処理の最大ページ数を超える場合は、バッチ処理 API を使用することもできます。この方法については、Document AI OCR Codelab をご覧ください。

API リクエストを行うコードは、プロセッサ ID を除き、一般的なプロセッサで同じです。

調達スプリッター/分類器

classification.py というファイルを作成して、以下のコードを使用します。

PROCUREMENT_SPLITTER_ID は、前に作成した調達スプリッター プロセッサの ID に置き換えます。YOUR_PROJECT_IDYOUR_PROJECT_LOCATION をそれぞれ Cloud プロジェクト ID とプロセッサのロケーションに置き換えます。

classification.py

import pandas as pd
from google.cloud import documentai_v1 as documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as file:
        file_content = file.read()

    # Load Binary Data into Document AI RawDocument Object
    raw_document = documentai.RawDocument(content=file_content, mime_type=mime_type)

    # Configure the process request
    request = documentai.ProcessRequest(name=resource_name, raw_document=raw_document)

    # Use the Document AI client to process the sample form
    result = documentai_client.process_document(request=request)

    return result.document


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "PROCUREMENT_SPLITTER_ID"  # Create processor in Cloud Console

# The local file in your current working directory
FILE_PATH = "procurement_multi_document.pdf"
# Refer to https://cloud.google.com/document-ai/docs/processors-list
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

print("Document processing complete.")

types = []
confidence = []
pages = []

# Each Document.entity is a classification
for entity in document.entities:
    classification = entity.type_
    types.append(classification)
    confidence.append(f"{entity.confidence:.0%}")

    # entity.page_ref contains the pages that match the classification
    pages_list = []
    for page_ref in entity.page_anchor.page_refs:
        pages_list.append(page_ref.page)
    pages.append(pages_list)

# Create a Pandas Dataframe to print the values in tabular format.
df = pd.DataFrame({"Classification": types, "Confidence": confidence, "Pages": pages})

print(df)

出力は次のようになります。

$ python3 classification.py
Document processing complete.
         Classification Confidence Pages
0     invoice_statement       100%   [0]
1     receipt_statement        98%   [1]
2                 other        81%   [2]
3     utility_statement       100%   [3]
4  restaurant_statement       100%   [4]

調達スプリッター/分類器は、0 ~ 1 ページと 3 ~ 4 ページのドキュメント タイプを正確に識別しました。

ページ 2 には汎用医療用登録フォームが含まれているため、分類器はこれを other と正しく識別しました。

6. エンティティを抽出する

これで、信頼スコア、プロパティ、正規化された値など、スキーマ化されたエンティティをファイルから抽出できるようになりました。

API リクエストを行うコードは前のステップと同じで、オンライン リクエストまたはバッチ リクエストで行うことができます。

エンティティから次の情報にアクセスします。

  • エンティティ タイプ
    • (例: invoice_datereceiver_nametotal_amount
  • 元の値
    • 元のドキュメント ファイルに表示されているデータ値。
  • 正規化された値
    • 正規化された標準形式のデータ値(該当する場合)。
    • Enterprise Knowledge Graph からの拡充を含めることもできます
  • 信頼度値
    • 値が正確であるというモデルの確信度。

line_item などのエンティティ タイプには、line_item/unit_priceline_item/description などのネストされたエンティティであるプロパティを含めることもできます。

この例では、見やすくするためにネストされた構造をフラット化しています。

請求書パーサー

extraction.py というファイルを作成して、以下のコードを使用します。

INVOICE_PARSER_ID を、以前に作成した請求書パーサー プロセッサの ID に置き換え、google_invoice.pdf ファイルを使用します。

extraction.py

import pandas as pd
from google.cloud import documentai_v1 as documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as file:
        file_content = file.read()

    # Load Binary Data into Document AI RawDocument Object
    raw_document = documentai.RawDocument(content=file_content, mime_type=mime_type)

    # Configure the process request
    request = documentai.ProcessRequest(name=resource_name, raw_document=raw_document)

    # Use the Document AI client to process the sample form
    result = documentai_client.process_document(request=request)

    return result.document


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "INVOICE_PARSER_ID"  # Create processor in Cloud Console

# The local file in your current working directory
FILE_PATH = "google_invoice.pdf"
# Refer to https://cloud.google.com/document-ai/docs/processors-list
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

types = []
raw_values = []
normalized_values = []
confidence = []

# Grab each key/value pair and their corresponding confidence scores.
for entity in document.entities:
    types.append(entity.type_)
    raw_values.append(entity.mention_text)
    normalized_values.append(entity.normalized_value.text)
    confidence.append(f"{entity.confidence:.0%}")

    # Get Properties (Sub-Entities) with confidence scores
    for prop in entity.properties:
        types.append(prop.type_)
        raw_values.append(prop.mention_text)
        normalized_values.append(prop.normalized_value.text)
        confidence.append(f"{prop.confidence:.0%}")

# Create a Pandas Dataframe to print the values in tabular format.
df = pd.DataFrame(
    {
        "Type": types,
        "Raw Value": raw_values,
        "Normalized Value": normalized_values,
        "Confidence": confidence,
    }
)

print(df)

出力は次のようになります。

$ python3 extraction.py
                     Type                                         Raw Value Normalized Value Confidence
0                     vat                                         $1,767.97                        100%
1          vat/tax_amount                                         $1,767.97      1767.97 USD         0%
2            invoice_date                                      Sep 24, 2019       2019-09-24        99%
3                due_date                                      Sep 30, 2019       2019-09-30        99%
4            total_amount                                         19,647.68         19647.68        97%
5        total_tax_amount                                         $1,767.97      1767.97 USD        92%
6              net_amount                                         22,379.39         22379.39        91%
7           receiver_name                                       Jane Smith,                         83%
8              invoice_id                                         23413561D                         67%
9        receiver_address  1600 Amphitheatre Pkway\nMountain View, CA 94043                         66%
10         freight_amount                                           $199.99       199.99 USD        56%
11               currency                                                 $              USD        53%
12          supplier_name                                        John Smith                         19%
13         purchase_order                                         23413561D                          1%
14        receiver_tax_id                                         23413561D                          0%
15          supplier_iban                                         23413561D                          0%
16              line_item                   9.99 12 12 ft HDMI cable 119.88                        100%
17   line_item/unit_price                                              9.99             9.99        90%
18     line_item/quantity                                                12               12        77%
19  line_item/description                                  12 ft HDMI cable                         39%
20       line_item/amount                                            119.88           119.88        92%
21              line_item           12 399.99 27" Computer Monitor 4,799.88                        100%
22     line_item/quantity                                                12               12        80%
23   line_item/unit_price                                            399.99           399.99        91%
24  line_item/description                              27" Computer Monitor                         15%
25       line_item/amount                                          4,799.88          4799.88        94%
26              line_item                Ergonomic Keyboard 12 59.99 719.88                        100%
27  line_item/description                                Ergonomic Keyboard                         32%
28     line_item/quantity                                                12               12        76%
29   line_item/unit_price                                             59.99            59.99        92%
30       line_item/amount                                            719.88           719.88        94%
31              line_item                     Optical mouse 12 19.99 239.88                        100%
32  line_item/description                                     Optical mouse                         26%
33     line_item/quantity                                                12               12        78%
34   line_item/unit_price                                             19.99            19.99        91%
35       line_item/amount                                            239.88           239.88        94%
36              line_item                      Laptop 12 1,299.99 15,599.88                        100%
37  line_item/description                                            Laptop                         83%
38     line_item/quantity                                                12               12        76%
39   line_item/unit_price                                          1,299.99          1299.99        90%
40       line_item/amount                                         15,599.88         15599.88        94%
41              line_item              Misc processing fees 899.99 899.99 1                        100%
42  line_item/description                              Misc processing fees                         22%
43   line_item/unit_price                                            899.99           899.99        91%
44       line_item/amount                                            899.99           899.99        94%
45     line_item/quantity                                                 1                1        63%

7. 省略可: 他の専用プロセッサを試す

調達向け Document AI を使用して、ドキュメントを分類して請求書を解析できました。Document AI は、ここに記載されている他の特殊なソリューションもサポートしています。

同じ手順とコードを使用して、任意の専用プロセッサを処理できます。

他の特殊なソリューションを試す場合は、他のプロセッサ タイプと専用のサンプル ドキュメントを使用してラボを再実行できます。

サンプル ドキュメント

他の専用プロセッサを試すために使用できるサンプル ドキュメントを次に示します。

ソリューション

プロセッサ タイプ

ドキュメント

ID

米国運転免許証パーサー

融資

貸与スプリッターと分類器

融資

W9 パーサー

契約

契約書パーサー

その他のサンプル ドキュメントとプロセッサ出力については、ドキュメントをご覧ください。

8. 完了

お疲れさまでした。ここでは、Document AI を使用して特殊なドキュメントからデータを分類して抽出しました。他の特殊なドキュメント タイプも試してみることをおすすめします。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにする手順は次のとおりです。

  • Cloud コンソールで、[リソースの管理] ページに移動します。
  • プロジェクト リストでプロジェクトを選択し、[削除] をクリックします。
  • ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

詳細

次の Codelab で Document AI について理解を深めてください。

リソース

ライセンス

この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。