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

1. はじめに

この Codelab では、Python で Document AI 専用プロセッサを使用して特殊なドキュメントを分類および解析する方法を学びます。分類と分割には、請求書、領収書、公共料金の明細書を含むサンプル 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. Invoice パーサー(codelab-invoice-parser という名前を付けることができます)を使用して、手順 2 ~ 6 を繰り返します。

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

ドキュメントをアップロードすると、コンソールで 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 リクエストを行うコードは前のステップと同一で、オンライン リクエストまたはバッチ リクエストで実行できます。

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

  • エンティティ タイプ
    • (例: invoice_datereceiver_nametotal_amount
  • 未加工の値
    • 元のドキュメント ファイルで指定されているデータの値。
  • 正規化値
    • 正規化された標準形式のデータ値(該当する場合)。
    • Enterprise Knowledge Graph からのエンリッチメントも追加できます。
  • 信頼値
    • どの程度「確実」値が正確であることです。

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

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

請求書パーサー

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

INVOICE_PARSER_ID は、前に作成した Invoice パーサー プロセッサの 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 汎用ライセンスにより使用許諾されています。