UpstageのUniversal Information Extractionを使ってドキュメントから情報抽出してみた

に公開

はじめに

Fusicのレオナです。今回は、UpstageのUniversal Information Extraction APIを活用して、非構造化ドキュメントから必要なデータを抽出する機能について解説します。なお、弊社は生成AI分野における包括的な協業を目指し、Upstageと業務提携を結んでおります。詳細はこちらからご覧ください

Universal Information Extraction とは

Universal Information Extractionは、あらゆる形式のドキュメントから情報を抽出し、構造化データにする機能です。特徴として、追加のトレーニングやカスタマイズなしでドキュメントから情報を処理・抽出できます。例えば、申請フォームや契約書、報告書といった非構造化ドキュメントから情報を抽出する場面で役立ちます。

本ブログではUniversal Information Extractionのスキーマを自分で定義する(Manual Schema Design)とスキーマを自動生成する(Automatic Schema Generation)が機能としてあるので2つの方法を試します。

Manual Schema Design

ドキュメントから抽出したいフィールドを独自で指定したい場合は、JSON Schema形式でスキーマを手動作成します。

説明
string 文字列 "hello"
number 浮動小数点を含む数値 1.3, 3.141
integer 整数 42, -5
boolean 真偽値 true, false
array 配列 ["a", "b", "c"]
object キーと値の組み合わせ {"key": "value"}

上記のJson Schema形式を組み合わせて、propertiesでスキーマを定義を行います。

{
  "type": "object",
  "properties": {
    "transactions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "transaction_date": {
            "type": "string",
            "description": "Date on which each transaction occurred."
          },
          "transaction_description": {
            "type": "string",
            "description": "Description of each transaction."
          }
        },
        "required": ["transaction_date", "transaction_description"]
      }
    }
  },
  "required": ["bank_name", "transactions"]
}

https://console.upstage.ai/docs/capabilities/information-extraction/universal-information-extraction#manual-schema-designより

Automatic Schema Generation

最大3件のドキュメントから初期スキーマを自動生成されます。抽出されたスキーマは、メッセージコンテンツ内の文字列化されたJSONオブジェクトとして返されます。

https://console.upstage.ai/docs/capabilities/information-extraction/universal-information-extraction#automatic-schema-generationより

ファイル要件

  • 対応ファイル形式:
    • JPEG, PNG, BMP, PDF, TIFF, HEIC, DOCX, PPTX, XLSX
  • 最大ファイルサイズ:
    • 50MB
  • 最大ページ数:
    • 100ページ
  • 最大ピクセル数:
    • 200,000,000ピクセル
      • 画像ファイル以外の場合、ドキュメントを150DPIで画像に変換した後のピクセル数
  • OCR対応文字:
    • 英数字
    • ハングル
    • 日本語・漢字

準備

  • Upstage ConsoleからAPIを取得する
    1. こちらからアカウントを作成する
    2. DashboardのAPI keysからAPIキーを作成・取得する
  • 使用するモデル :
    • information-extract
  • 今回はUpstageのモデルを使う場合はOpenAIと互換性があるのでOpenAIのライブラリを使用しています
pip install openai==1.78.1

使用するデータ

Manual Schema DesignではUpstage の公式ドキュメントに掲載されているサンプル画像 bank_statement.png で試しています。[こちら]の画像を使用しています。(https://console.upstage.ai/docs/capabilities/information-extraction/universal-information-extraction#example)

またAutomatic Schema GenerationではHugging Face で MIT ライセンス下に公開されているデータセットallganize/RAG-Evaluation-Dataset-JA の日本語ドキュメントのPDF1部分を利用します。

実装:Manual Schema Design

bank_statement.pngから銀行名のみを抽出する例です。

import base64
import json
from openai import OpenAI

client = OpenAI(
    api_key="UPSTAGE_API_KEY",
    base_url="https://api.upstage.ai/v1/information-extraction"
)

def encode_img_to_base64(img_path):
    with open(img_path, 'rb') as img_file:
        img_bytes = img_file.read()
        base64_data = base64.b64encode(img_bytes).decode('utf-8')
        return base64_data

img_path = "bank_statement.png"
base64_data = encode_img_to_base64(img_path)

extraction_response = client.chat.completions.create(
    model="information-extract",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/png;base64,{base64_data}"}
                }
            ]
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "document_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "bank_name": {
                        "type": "string",
                        "description": "The name of bank in bank statement"
                    }
                },
                "required": ["bank_name"]
            }
        }
    }
)
 
print(extraction_response.choices[0].message.content)
  • 出力結果
{"bank_name": "Bank of Dream"}

実装:Automatic Schema Generation

PDFを画像にしたものからスキーマを自動生成後、情報抽出させる例になります。

import base64
import json
from openai import OpenAI

def encode_img_to_base64(img_path):
    with open(img_path, 'rb') as img_file:
        img_bytes = img_file.read()
        base64_data = base64.b64encode(img_bytes).decode('utf-8')
        return base64_data

img_path = "image.png"
base64_data = encode_img_to_base64(img_path)

schema_client = OpenAI(
    api_key="UPSTAGE_API_KEY",
    base_url="https://api.upstage.ai/v1/information-extraction/schema-generation"
)

schema_response = schema_client.chat.completions.create(
    model="information-extract",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/png;base64,{base64_data}"}
                }
            ]
        }
    ],
)
schema = json.loads(schema_response.choices[0].message.content)

extraction_client = OpenAI(
    api_key="UPSTAGE_API_KEY",
    base_url="https://api.upstage.ai/v1/information-extraction"
)

extraction_response = extraction_client.chat.completions.create(
    model="information-extract",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/png;base64,{base64_data}"}
                }
            ]
        }
    ],
    response_format=schema,
)
# extraction_response.choices[0].message.contentをprintすると文字化けするので以下を実行する
parsed = json.loads(extraction_response.choices[0].message.content)
print(json.dumps(parsed, ensure_ascii=False, indent=2))
  • 出力結果
{
  "market_trends": [
    {
      "item": "ICT市場規模 (支出額)",
      "year": 2022,
      "amount": "27.2兆円",
      "year_on_year_change": "+ 5.2%"
    },
    {
      "item": "情報通信産業の国内生産 (名目)",
      "year": 2021,
      "amount": "52.7兆円",
      "year_on_year_change": "+ 0.8%"
    },
    {
      "item": "情報化投資",
      "year": 2021,
      "amount": "15.5兆円",
      "year_on_year_change": "▲ 0.4%"
    },
    {
      "item": "ICT財 · サービスの輸入額 (名目)",
      "year": 2021,
      "amount": "19.2兆円",
      "year_on_year_change": "+ 14.6%"
    },
    {
      "item": "ICT財 · サービスの輸出額 (名目)",
      "year": 2021,
      "amount": "12兆円",
      "year_on_year_change": "+ 13.3%"
    },
    {
      "item": "情報通信産業の研究費",
      "year": 2021,
      "amount": "3.4兆円",
      "year_on_year_change": "▲ 1.6%"
    },
    {
      "item": "情報通信産業の研究者数",
      "year": 2021,
      "amount": "15.7万人",
      "year_on_year_change": "▲ 6.0%"
    },
    {
      "item": "5G人ロカバー率",
      "year": 2021,
      "amount": "93.2%",
      "year_on_year_change": ""
    },
    {
      "item": "インターネットトラヒック",
      "year": 2022,
      "amount": "29.2Tbps",
      "year_on_year_change": "+ 23.7%"
    },
    {
      "item": "固定系ブロードバンドの契約数",
      "year": 2021,
      "amount": "4,383万",
      "year_on_year_change": "+ 2.7%"
    },
    {
      "item": "放送事業者全体の売上高",
      "year": 2021,
      "amount": "3.7兆円",
      "year_on_year_change": "+ 4.6%"
    },
    {
      "item": "放送サービス加入者数",
      "year": 2021,
      "amount": "8161.3万",
      "year_on_year_change": "▲0.2%"
    },
    {
      "item": "デジタル広告市場規模",
      "year": 2022,
      "amount": "3.1兆円",
      "year_on_year_change": "+ 13.7%"
    },
    {
      "item": "5G対応スマホ出荷台数",
      "year": 2021,
      "amount": "1,753万台",
      "year_on_year_change": "+ 67.7%"
    },
    {
      "item": "5G基地局の市場規模 (出荷額)",
      "year": 2022,
      "amount": "3,035億円",
      "year_on_year_change": "+ 6.2%"
    },
    {
      "item": "動画配信市場規模",
      "year": 2022,
      "amount": "5,305億円",
      "year_on_year_change": "+ 15.0%"
    },
    {
      "item": "メタバース市場規模 (売上高)",
      "year": 2022,
      "amount": "1,825億円",
      "year_on_year_change": "+ 145.3%"
    },
    {
      "item": "データセンターサービス市場規模",
      "year": 2022,
      "amount": "2.0兆円",
      "year_on_year_change": "+ 15.3%"
    },
    {
      "item": "クラウドサービス市場規模 (売上)",
      "year": 2022,
      "amount": "2.2兆円",
      "year_on_year_change": "+ 29.8%"
    },
    {
      "item": "NICTERでのサイバー攻撃関連の通信数",
      "year": 2022,
      "amount": "約5,266億",
      "year_on_year_change": "+ 0.9%"
    },
    {
      "item": "インターネット利用率 (個人)",
      "year": 2022,
      "amount": "84.9%",
      "year_on_year_change": "82.9% ※"
    },
    {
      "item": "スマートフォン保有率 (個人)",
      "year": 2022,
      "amount": "77.3%",
      "year_on_year_change": "74.3% ※"
    },
    {
      "item": "テレワーク導入率",
      "year": 2022,
      "amount": "51.7%",
      "year_on_year_change": "51.9% ※"
    },
    {
      "item": "IoT - AIの導入状況",
      "year": 2022,
      "amount": "13.5%",
      "year_on_year_change": "14.9%※"
    }
  ],
  "total_market_size": "27.2兆円",
  "internet_usage_rate": 84.9,
  "smartphone_ownership_rate": 77.3,
  "telework_adoption_rate": 51.7
}

最後に

Universal Information Extraction は、1度スキーマを定義すれば社内文書の情報抽出が容易になり、定型化された請求書や契約書などをまとめて自動処理できる点が大きな強みだと感じました。また、Automatic Schema Generationを活用して初期スキーマをベースに Manual Schema Designで微調整を加えると、最小限の工数で抽出ルールが作ることができます。自社ドキュメンの抽出作業においてとても有用なAPIだと思います。

Fusic 技術ブログ

Discussion