🤗

DifyとNotionで領収書をOCRして管理!

2024/08/15に公開
3

はじめに

先日、Claude等を活用した領収書のOCR検証を記事にしました。
今回は、DifyとNotionを連携させて領収書をOCRして、その情報をNotionで管理してみよう!と思います。
https://zenn.dev/acntechjp/articles/fabecf397747a4
https://zenn.dev/acntechjp/articles/61540b2f4586d3
イメージはこんなかんじで。

構築ですが、下記記事を参考にしています!
https://zenn.dev/yu_9/articles/3145f964a58996

アーキテクチャ

アーキテクチャはDifyをHubにして、GPT-4o miniを使ってOCRするのと、結果を整形してNotionの領収書管理データベースに書き込むのを想定しています。

Notionの準備

インテグレーション作成、APIのシークレットキーを取得する

下記にアクセスします。
https://www.notion.so/profile/integrations
「新しいインテグレーション」をクリックします。

「関連ワークスペース」を設定します。「種類」は「内部」にしています。

「保存」をクリックすると「インテグレーションが作成されました」と表示されます。「インテグレーションを設定」をクリックしましょう。

「表示」をクリックします。

するとAPIのシークレットキーが表示されます。これはDifyで使う「Notionで設定したAPIのシークレットキー」となります。「Dify構築」の「環境変数の設定」で使うので控えておきましょう。

領収書管理データベースを作成

「ページを追加」をクリックします。

「テーブル」をクリックしてテーブルを追加します。

下記のように項目を追加します。

ビューのリンクをコピーをクリックします。

下記のようなURLがコピーされますが、<DATABASE_ID>がDifyで使う「領収書管理データベースのID」となります。「Dify構築」の「環境変数の設定」で使うので控えておきましょう。

https://www.notion.so/<DATABASE_ID>?v=XXX&pvs=4

三点メニューから接続先をクリックして、「インテグレーション作成、APIのシークレットキーを取得する」で作成したインテグレーションをクリックします。

これで、Notionの準備は完了です。

Dify構築

ワークフロー作成

まずはDifyにアクセスしてワークフローを作成しましょう。

ワークフローの全体像

アップロードされた領収書画像を「LLM(GPT-4o mini)」にOCRさせて、結果を「コード」と「テンプレート」で整形させて、「HTTPリクエスト」でNotionへ連携します。

環境変数の設定

Difyの環境変数を設定していきましょう。
NOTION_DATABASE_ID: 作成した領収書管理データベースのID
NOTION_INTEGRATION_SECRET_KEY: Notionで設定したAPIのシークレットキー
NOTION_VERSION: 2022-06-28と入力しましょう

機能の設定

領収書画像をアップロードできるように「画像アップロード」をOnにしましょう。

LLMの設定

LLMは「GPT-4o mini」を採用します。プロンプト設定も「GPT-4o mini」に合わせたものにしています。

「ビジョン」をOnにします。

出力がJSON形式になるように設定します。

プロンプトは下記のとおりです。

あなたは優秀な経理担当者です。受け取った領収書を画像解析して文字や金額を起こしてください。
## 重要事項
- 結果はjson形式で出力すること
- わからない項目がある場合は、正直に「N/A」と記入してください。
- 標準的でない形式や追加情報がある場合は、各行の注記として記載してください。

## 項目の説明
主に以下の情報が含まれます。
- company_name:  支払先の会社名。宛名や請求先ではないので注意してください。
- issue_date: 領収書を発行した日付(YYYY/MM/DD形式で出力)
- amount: 税込みの支払い金額。カンマなしで出力。税抜き金額のみ記載の場合は、課税対象額を加算して計算してください。
- currency: 支払金額の通貨(例:JPY、USD、EUR)
- invoice_registration_number: 税務署に認められた適格請求書発行事業者に発行される番号です。 すでに法人番号がある事業者の場合は「T+法人番号」が登録番号となります。 法人番号を持っていない事業者に関しては、「T+13桁の固有番号」が登録番号です。 (T0000000000000形式で出力)
- note: 注記。標準的でない形式や追加情報がある場合、付加情報として記載する。付加情報がない場合「N/A」と記載する。

## json schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "company_name": {
      "type": "string",
      "description": "支払先の会社名。宛名や請求先ではない。"
    },
    "issue_date": {
      "type": "string",
      "format": "date",
      "pattern": "^\\d{4}/\\d{2}/\\d{2}$",
      "description": "領収書を発行した日付(YYYY/MM/DD形式)"
    },
    "amount": {
      "type": "integer",
      "minimum": 0,
      "description": "税込みの支払い金額。カンマなしで表示。"
    },
    "currency": {
      "type": "string",
      "enum": ["JPY", "USD", "EUR"],
      "description": "支払金額の通貨(例:JPY、USD、EUR)"
    },
    "invoice_registration_number": {
      "type": "string",
      "pattern": "^T\\d{13}$",
      "description": "税務署に認められた適格請求書発行事業者の登録番号(T0000000000000形式)"
    },
    "note": {
      "type": "string",
      "description": "注記。標準的でない形式や追加情報がある場合の付加情報。付加情報がない場合「N/A」と記載する。"
    }
  },
  "required": ["company_name", "issue_date", "amount", "currency", "invoice_registration_number", "note"]
}

コードの設定

LLMのOCR結果をJSONで受け取る前提でコードを組んでいます。受け取ったJSONをDify上の変数に格納する処理をJavaScriptで記載しています。

具体的なJavaScriptは下記となります。

function main({json}) {
    const data = JSON.parse(json);
    return {
        company_name: data.company_name,
        issue_date: data.issue_date,
        amount: data.amount,
        currency: data.currency,
        invoice_registration_number: data.invoice_registration_number,
        note: data.note
    }
}

テンプレートの設定

Notionへ連携する際のJSONを作成します。「コード」で変数にOCR結果を格納していますが、こちらを使います。

具体的なJSONは下記となります。

{
  "parent": { "database_id": "{{ NOTION_DATABASE_ID }}" },
  "properties": {
    "Name": {
      "title": [
        {
          "text": {
            "content": "{{ company_name }}"
          }
        }
      ]
    },
    "company_name": {
      "rich_text": [
        {
          "text": {
            "content": "{{ company_name }}"
          }
        }
      ]
    },
    "issue_date": {
      "rich_text": [
        {
          "text": {
            "content": "{{ issue_date }}"
          }
        }
      ]
    },
    "amount": {
      "number": {{ amount }}
    },
    "currency": {
      "rich_text": [
        {
          "text": {
            "content": "{{ currency }}"
          }
        }
      ]
    },
    "invoice_registration_number": {
      "rich_text": [
        {
          "text": {
            "content": "{{ invoice_registration_number }}"
          }
        }
      ]
    },
    "note": {
      "rich_text": [
        {
          "text": {
            "content": "{{ note }}"
          }
        }
      ]
    }
  }
}

HTTPリクエストの設定

NotionへAPI連携するためのURLの設定と、APIバージョンの設定をします。

また、APIのシークレットキーの設定もします。

これで、Difyの構築は完了です。

構築したDifyを使ってみる

Difyで公開したアプリにアクセスして領収書画像をアップロードします。その後「実行」をタップします。

順調に実行されて処理が完了しました。

Notionにもアクセスしてデータが連携されたことを確認できました!

課題と展望

OCRの精度でいうと、現時点(2024年8月14日)ではClaude 3.5 Sonnetが良さそうです。このため今後Claude 3.5 Sonnetへの連携も試してみたいと考えています。

また、この記事ではあくまでもOCR結果をNotionへ連携ですが元画像もNotionへ連携して管理していきたいところです。この辺も今後試せたらと考えています。
ただ、現状DifyのWorkflowでアップロードされたファイルを参照できるプロパティが指定できず、対応されてからのトライかなと考えています。一応今後サポートされるような発言がGitHubにあり、今後に期待かも。
https://github.com/langgenius/dify/issues/5369

さいごに

いかがでしたか。DifyとNotionを連携してアプリを作成してみました。個人的にはかなり実用的で活用していこうと思いました。みなさんもぜひアイディアを形にしていただけたら嬉しく思います!

Accenture Japan (有志)

Discussion

mu babamu baba

素晴らしいですね。
これの名刺版の記事も書いて欲しい