1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KanjoAI — 請求書と発注書の突合を自律化するAIエージェント

1
Posted at

AI HACK 2026(テーマ:業務を自律化するAIエージェント)に向けて、
OrcaRouter をLLMゲートウェイとして使い、
「KanjoAI」という請求書・発注書突合の自律エージェントを作りました。

作ったもの

http://localhost:8000/ で動くデモ画面です。サンプル請求書を選ぶだけで、
抽出→照合→検証→判断→記録のパイプラインが実際に動き、判断結果と
監査ログ付きの処理履歴がその場で確認できます。
Screenshot 2026-09-22 at 13.28.52.png

1. プロジェクト概要

背景

普段バックエンドエンジニアとしてERP(EBOSS)の開発に関わっている中で、
請求書と発注書の照合作業に人手と時間がかかっている現場を見てきたので、
この課題を選びました。

解決したい課題

ERP・経理システムを運用している会社では、届いた請求書を発注書と突き合わせる作業に
毎回それなりの人的コストがかかります。金額のチェック、二重請求の検知、
取引先名の不一致(なりすまし・誤送付)の発見など、地味だけど間違えられない業務です。
KanjoAIはこの一連の流れを自律的に処理します。

コンセプト

多くの「AIでXをやりました」系のハッカソン作品は、1つのプロンプトに1つの回答を返すだけです。
KanjoAIは抽出→照合→検証→判断→記録という多段のループを実行し、各ステップの結果を
監査ログに残すことで、判断根拠を常に追跡できるようにしています(詳細は3章)。

対象ユーザー

  • ERP・経理システムを運用している企業の経理・バックオフィス担当者
  • 請求書処理の一次チェックを行っている経理部門
  • 二重請求・なりすまし請求のリスクを監査したい内部統制・経理管理者

2. 設計原則

  1. 単発の判定ではなく、抽出→照合→検証→判断→記録の自律ループにする
    1回のプロンプトで終わらせず、各ステップの結果を監査ログに残すことで、
    後から判断根拠を追跡できるようにしています。
  2. 判断の重大度は後戻りさせない
    一度「却下」と判定された請求書が、後続の軽微なチェック(信頼度など)によって
    「要確認」に格下げされることはありません。実装中に見つけたバグを、そのまま
    回帰テストとして固定しています。
  3. コストは必要なときだけ使う
    既定は安いモデルです。低信頼度・JSON検証失敗・呼び出し失敗の場合のみ上位モデルに
    エスカレーションし、ネットワークの一時的な失敗はエスカレーション前にリトライで
    吸収します。
  4. 発注書番号の一致だけで信用しない
    取引先名まで一致するかを確認し、番号だけ合っていて取引先が違う請求書
    (なりすまし・誤送付)は「要確認」ではなく「却下」として扱います。

3. システムアーキテクチャ

3.1 コンポーネント構成

kanjoai_architecture_v3.png

FastAPI · SQLAlchemy(既定はSQLite、DATABASE_URL でPostgresにも切り替え可能)·
Pydanticという構成で、OpenAI SDKでOrcaRouterのOpenAI互換エンドポイント
(https://api.orcarouter.ai/v1)を呼び出しています。

3.2 抽出→照合→検証→判断→記録のパイプライン

  1. 抽出(Extract) — Vision対応モデルが請求書画像を読み取り、取引先名・請求書番号・
    発注書番号・金額・通貨・日付・自己申告の信頼度をJSONで返す
  2. 照合(Match) — 請求書が参照している発注書を検索
  3. 検証(Validate) — 発注書の有無、金額の許容誤差内かどうか、通貨の一致、
    取引先名の一致、請求書番号の重複チェック
  4. 判断(Decide) — ルールの結果と抽出時の信頼度を組み合わせて
    自動承認 / 要確認 / 却下 のいずれかを決定
  5. 記録(Act) — 判断結果と全ての根拠を監査ログとして永続化

安いモデルの抽出結果に自信がない場合(信頼度が低い、JSONが不正、呼び出し自体が失敗)は、
自動的に上位モデルにエスカレーションします。毎回高いモデルを使うわけではなく、
かといって安いモデルの結果を鵜呑みにするわけでもない——これはOrcaRouterが持つ
コスト最適化・フェイルオーバーという価値提案を、そのままエージェントの設計思想として
組み込んだものです。

3.3 信頼性への担保

金額を扱うエージェントなので、判断ロジックの正しさをテストで担保することを重視しました。

  • 抽出結果はPydanticで検証(金額は正の数であること、通貨は実在の3文字コードであることなど)
  • 判断のステータスには重大度の序列(自動承認 < 要確認 < 却下)を持たせていて、
    一度「却下」と判断された請求書が、あとから走る軽微なチェック(信頼度など)によって
    「要確認」に格下げされることがないようにしています。これは実装中に見つけたバグで、
    回帰テストとして残してあります
  • オフラインで動く15件のテストケース(OrcaRouterのキー不要、ネットワーク不要)で、
    自動承認・金額の許容誤差超過・取引先名の不一致・重複請求書番号・発注書が見つからない・
    低信頼度、といった判断パスを全てカバー
  • 想定外の例外はグローバルなハンドラで捕捉し、生のトレースバックは絶対に返さず、
    エラーIDだけをレスポンスに含めてサーバー側でログに残します

3.4 セキュリティ面

全エンドポイントにAPIキー認証を必須にしているほか、実装していて一番効果があったのは
取引先名の一致チェックです。実在する発注書番号を騙りつつ、実際には別の取引先からの
請求書だった場合——なりすましや誤送付の典型パターンですが——これを「要確認」ではなく
**「却下」**として扱うようにしています。発注書番号さえ合っていれば通ってしまう設計は
危険だと気づいたのは、テストを書いている最中でした。

4. OrcaRouterの活用

OrcaRouter はOpenAI互換のエンドポイントで、
<ベンダー>/<モデルID> という形式のモデルIDを指定するだけで複数プロバイダのモデルに
アクセスできます。

MODEL_CHEAP  = "openai/gpt-4o-mini"      # 通常はこちらで抽出
MODEL_STRONG = "anthropic/claude-opus-5"  # 低信頼度・失敗時のみエスカレーション

抽出処理は complete_json() という関数にまとめていて、安いモデルを先に呼び、
信頼度が閾値を下回る・JSONの検証に失敗する・呼び出し自体がエラーになる、
のいずれかが起きたときだけ上位モデルに切り替えます。ネットワークの一時的なエラー
(タイムアウトやレート制限)は、モデルを切り替える前にリトライ+指数バックオフで
まず吸収するようにしていて、「一時的な不調」と「このモデルでは処理できない」を
明確に分けています。

5. 動かして試せるデモUI

uvicorn app.main:app を起動するだけで、http://localhost:8000/ に
そのまま試せるデモ画面が立ち上がります。別途フロントエンドのビルドは不要です。

  • 4パターンのサンプル請求書(正常一致・金額超過・取引先名不一致・重複請求書番号)を
    ワンクリックで流せる
  • 自分の請求書画像をアップロードして試せる
  • 自分で発注書を登録して、オリジナルのシナリオでテストできる
  • 処理履歴と、判断ごとの監査ログをその場で確認できる

実際の動作確認

4つのサンプル請求書をOrcaRouter経由の実際のVisionモデル(openai/gpt-4o-mini)に
通したところ、すべて一回のAPIコールで正しく処理されました。

シナリオ 抽出結果 判断
正常一致 Sample Vendor K.K. / ¥128,000 auto_approved
金額超過 Sample Vendor K.K. / ¥155,000 flagged
取引先名不一致 Totally Different Trading Co. rejected
重複請求書番号 (既存と同一の請求書番号) rejected

4枚とも画像の内容に応じて実際に異なる値が抽出されており、スタブではなく
本物のVision抽出であることを確認しています。信頼度は全て1.00で、
今回はどのケースも上位モデルへのエスカレーションは発生しませんでした
(エスカレーション自体のロジックは、クレジット切れ時のフォールバック処理で
別途動作確認済みです)。

6. 審査基準とのマッピング

基準 対応内容
セキュリティ 全エンドポイントAPIキー必須、取引先名不一致は却下、エラー時も内部情報を漏らさない
コストパフォーマンス 安いモデルを優先し、必要な時だけ上位モデルにエスカレーション。ネットワークエラーはエスカレーション前にリトライで吸収
信頼性・堅牢性 入出力のバリデーション、判断の重大度が逆行しない設計、15件のオフラインテスト、グローバル例外ハンドラ
自律性 抽出→照合→検証→判断→記録のループを、モデルエスカレーションとリトライを含めて自律的に実行
独自性 チャットボット的なデモではなく、実際のERP/経理業務にある「請求書突合」という課題に根ざしている

7. 現時点の制約

  • 対応している画像形式は jpg / png / webp のみ(PDF請求書は事前に画像化が必要)
  • DBは既定でSQLite(DATABASE_URL を変更すればPostgresなどに切り替え可能)で、
    大量データでの運用検証はまだ行っていない
  • 却下・要確認になった請求書を人間に知らせる通知導線(Slackなど)は未実装で、
    今はAPI/デモUIで確認する運用
  • 今回の実機テストでは4件とも安いモデル(openai/gpt-4o-mini)のみで解決し、
    上位モデルへのエスカレーションが実際に発生するケースはまだ収集できていない
    (エスカレーションのロジック自体はクレジット切れ時のフォールバックで別途確認済み)

リポジトリ

READMEにセットアップ手順・テストの実行方法・デモUIの使い方をまとめています。

さいごに

AI HACK 2026 を通じて、普段の業務課題をAIエージェントとして
形にする良い機会をいただきました。無料でAPIクレジットを提供してくださった
OrcaRouter 様、運営の皆様に感謝します。

今後は実際の請求書フォーマットへの対応幅を広げたり、Slack通知などの人間へのエスカレーション
導線を強化したりしていきたいと考えています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?