Media > AI活用ユースケース > 営業 > 海外の旅行会社から毎月届く英文の手数料の精算書を読み取り、予約台帳と突き合わせて、手数料率と対象の予約の食い違いを拾う

海外の旅行会社から毎月届く英文の手数料の精算書を読み取り、予約台帳と突き合わせて、手数料率と対象の予約の食い違いを拾う

実装ステータス:構成例 技術的に実現可能な構成として設計したもの。自社未検証

海外の旅行会社から毎月届く英文の手数料の精算書(commission statement)を読み取り、1行ずつ予約台帳と契約の手数料率に照らします。率が違う行、取消や不泊の予約に手数料が付いた行、台帳に無い予約を、支払う前に一覧にします。

サマリー
生成AI
ChatGPT/Claude
AIサービス
AWS Textract/Azure AI/Google Document AI
連携・自動化
Python
対象業界
その他/宿泊
対象部門
営業/経理
対象業務
内容確認・チェック/比較検討
主な課題
人手が足りない/入力作業が多い/確認ミスが多い
AIで行う処理
読み取り(OCR)
主な効果
入力漏れ削減/品質標準化/工数削減
導入難易度
★★★☆☆
実装レベル
本格構成
費用感
API連携(中)
人間の確認
条件付き
現在工数
60h/月
AI導入後
15h/月
想定削減
75%
年間削減
540h
モデル条件による試算値です。実在企業の実績ではありません。

01導入前 / 導入後の業務フロー

導入前(Before)
  1. 経理課の担当者が、メールで届いた精算書のPDFを共有フォルダに保存する
  2. 精算書の行を1行ずつ読み、予約番号で予約管理システムを検索する
  3. 到着日・出発日・泊数・客室料金を、台帳と見比べる
  4. 予約が取消・不泊になっていないかを確かめる
  5. 契約の一覧を開き、その会社のその時期の率と、基準に含めるものを確かめる
  6. 手数料を電卓か表計算で計算し直し、精算書の額と比べる
  7. 食い違いがあれば、営業課に確認したうえで旅行会社に英文で問い合わせる
  8. 確認が済んだものを会計システムに登録し、支払に回す
導入後(After)
  1. 人精算書のPDFを、旅行会社ごとの受付フォルダに保存する
  2. 自動保存をきっかけに、Textract の非同期の文書分析を始める(表と問い合わせ項目)
  3. 自動分析が終わった通知を受け、表のセルと問い合わせの答えを取り出す
  4. 自動生成AIが、表の列を共通の項目にそろえ、日付の書き方をその会社の設定で読む
  5. 自動プログラムが予約番号で台帳を引き、取消・不泊・日付・泊数・料金を照らす
  6. 自動プログラムが契約の一覧から率と基準を引き、手数料を計算し直して差を出す
  7. 自動行ごとに `ok` / `mismatch` / `not_found` / `needs_human` を付け、問い合わせ文の下書きを作る
  8. 人経理課の担当者が `ok` 以外の行だけを確かめ、営業課と相談して問い合わせる
  9. 人確定した支払額を会計システムに登録する
各工程の詳しい説明を読む
  1. 経理課の担当者が、メールで届いた精算書のPDFを共有フォルダに保存する
  2. 精算書の行を1行ずつ読み、予約番号で予約管理システムを検索する
  3. 到着日・出発日・泊数・客室料金を、台帳と見比べる
  4. 予約が取消・不泊になっていないかを確かめる
  5. 契約の一覧を開き、その会社のその時期の率と、基準に含めるものを確かめる
  6. 手数料を電卓か表計算で計算し直し、精算書の額と比べる
  7. 食い違いがあれば、営業課に確認したうえで旅行会社に英文で問い合わせる
  8. 確認が済んだものを会計システムに登録し、支払に回す

(a)取消と不泊が残っている。 旅行会社の側で取消の処理が遅れた予約や、到着しなかった予約が、精算書に残っていることがあります。4番を省くと、泊まっていない予約に手数料を払います。 忙しい月ほど、ここが目視から落ちます。

(b)率と基準額の取り決めが細かい。 基本の率は合っていても、食事込みの料金に率を掛けている、特別料金の時期にも手数料が付いている、という食い違いがあります。5番で契約の一覧を毎回開くのは手間で、担当者が覚えている率で済ませることがあります。

(c)日付の書き方が会社ごとに違う。 日・月の順が違う会社の精算書を読み違えると、存在しない予約として問い合わせることになります。 旅行会社からは「ちゃんと見てほしい」と返されます。

(d)全行を目視するのは続かない。 60枚に数十行ずつで、1枚1時間かかります。 締めの前に重なると、行の照合を省いて合計額だけを見て支払うことになります。

  1. 【人】 精算書のPDFを、旅行会社ごとの受付フォルダに保存する
  2. 【自動】 保存をきっかけに、Textract の非同期の文書分析を始める(表と問い合わせ項目)
  3. 【自動】 分析が終わった通知を受け、表のセルと問い合わせの答えを取り出す
  4. 【自動】 生成AIが、表の列を共通の項目にそろえ、日付の書き方をその会社の設定で読む
  5. 【自動】 プログラムが予約番号で台帳を引き、取消・不泊・日付・泊数・料金を照らす
  6. 【自動】 プログラムが契約の一覧から率と基準を引き、手数料を計算し直して差を出す
  7. 【自動】 行ごとに ok / mismatch / not_found / needs_human を付け、問い合わせ文の下書きを作る
  8. 【人】 経理課の担当者が ok 以外の行だけを確かめ、営業課と相談して問い合わせる
  9. 【人】 確定した支払額を会計システムに登録する

8番目で人が見るのは、全行ではありません。 照合が一致した行は件数と合計だけを見て、食い違いと判断のつかない行だけに時間を使います。

5番目と6番目をプログラムにしているのは、意図してのことです。 照合と計算は、規則が決まっていて答えが1つに決まる作業です。生成AIに任せると、計算の途中を言葉で補って、それらしい額を出してしまいます。

02今回想定するシステム構成

構成図
旅行会社から届く英文の精算書(PDF)
   │  旅行会社ごとの受付フォルダへ保存
   ▼【トリガー】Amazon S3 への保存
AWS Lambda ── StartDocumentAnalysis(TABLES/QUERIES)
   ▼
AWS Textract ── 完了を Amazon SNS に通知
   ▼
AWS Lambda ── GetDocumentAnalysis で表のセルと問い合わせの答えを取り出す
   ▼
Claude API ── 列を共通の項目にそろえる(構造化出力)
   ▼
Python ── 予約台帳と契約の一覧で照合し、手数料を計算し直す
   ▼
行ごとの判定(ok / mismatch / not_found / needs_human)
   ▼
【経理課の担当者が食い違いの行だけ確認】
   ├──▶ Claude API ── 旅行会社への英文の問い合わせの下書き
   └──▶ 会計システムへ確定額を登録
役割想定する製品代替候補
OCRAWS Textract(StartDocumentAnalysis/GetDocumentAnalysis)Azure AI Document Intelligence、Google Document AI
生成AIClaude API(列のそろえと、問い合わせ文の下書き)OpenAI API
差異計算Python(予約台帳との照合と手数料の再計算)予約管理システムの帳票機能
連携AWS Lambda(保存と完了の通知を起点に処理を動かす)Amazon EventBridge
保管Amazon S3(精算書、読み取り結果、照合の結果)社内のファイルサーバー

新しく作るのは、旅行会社ごとの設定の一覧です。 会社ごとに、日付の書き方(日・月の順)、通貨、手数料の基準に含めるもの、契約の率と適用期間を持たせます。この一覧がないと、同じ「03/12」を会社によって正しく読み分けられません。

読み取りの土台は AWS Textract です。 公式の対応言語は英語、フランス語、ドイツ語、イタリア語、ポルトガル語、スペイン語で、英文の精算書はこの範囲に入ります。 一方で日本語は対応していないため、和文の精算書が混ざる場合は、本記事の構成ではなく Azure AI Document Intelligence や Google Document AI で読むことになります。

表の読み取りが、この構成でいちばん効く機能です。 FeatureTypes に TABLES を入れると、表は TABLE ブロック、各セルは CELL ブロックとして返り、セルには行と列の位置が付きます。列見出しのセルには COLUMN_HEADER、合計の行のセルには TABLE_SUMMARY という種類が付くため、明細の行と合計の行を分けて扱えます。

03どうやって実装するのか

Step1

処理の起点を決める

起点は、精算書のPDFを受付フォルダ(Amazon S3)に保存したことです。 保存のたびに1枚ずつ処理を動かします。月末にまとめて処理しないのは、問い合わせの返事を待つ時間を残すためです。 旅行会社の時差を考えると、問い合わせは早く出すほど支払日に間に合います。

受付フォルダは旅行会社ごとに分けます。 フォルダの名前から旅行会社を決め、その会社の設定(日付の書き方、通貨、基準)を処理の最初に読み込みます。精算書の中の会社名をAIに読ませて会社を決めると、ロゴだけの精算書で取り違えます。

文書分析は非同期の StartDocumentAnalysis で始めます。 同期の処理は PDF が1ページまでという制限があり、数ページにわたる精算書は非同期で扱います。 終わると Amazon SNS に完了の状態が通知されるので、それを起点に結果を取りに行きます。

Step2

入力データを集める

データ中身取得元
精算書英文のPDF。旅行会社、対象期間、予約ごとの行、合計受付フォルダ
読み取り結果表のセル(行と列の位置、列見出し、合計の行)、問い合わせの答え、信頼度AWS Textract
予約台帳予約番号(自社と旅行会社の両方)、宿泊者名、到着日、出発日、泊数、状態(宿泊・取消・不泊)、客室料金、食事料金予約管理システムの書き出し
契約の一覧旅行会社ごとの手数料率、適用期間、基準に含めるもの、手数料を付けない料金の種類営業課が持つ一覧
旅行会社ごとの設定日付の書き方、通貨、列名の対応の実績経理課が作る一覧

質を決めるのは、予約台帳に旅行会社の予約番号が入っているかです。 精算書には旅行会社の側の番号しか書かれていないことが多く、自社の予約番号だけでは突き合わせる先がありません。 予約を受けたときに、旅行会社の番号を台帳の項目に入れる運用を先に決めます。

契約の一覧は、率だけでは足りません。 「客室料金のみ」「食事を含む」「税・サービス料を除く」といった基準と、手数料を付けない料金の種類を持たせます。第3章の(b)は、ここが一覧になっていないことから起きています。

Step3

データの取得方法を決める

結果の取得には GetDocumentAnalysis を使います。 1回の呼び出しで返るブロックは最大1,000件で、それを超えると NextToken が返るため、NextToken が無くなるまで呼び続けて全部を集めます。 途中で止めると、後半のページの行が丸ごと抜けます。

取るものどこから何に使うか
表とセルTABLE・CELL ブロック(RowIndex、ColumnIndex)明細の行を組み立てる
列見出しEntityTypes が COLUMN_HEADER のセル列の意味を決める材料
合計の行EntityTypes が TABLE_SUMMARY のセル明細の合計と照らす
結合されたセルMERGED_CELL ブロック団体の行で複数行にまたがる値を正しく割り当てる
問い合わせの答えQUERY_RESULT ブロック対象期間、旅行会社名、合計額、通貨
処理の状態JobStatus、WarningsPARTIAL_SUCCESS やページの警告を検知する

問い合わせ(QUERIES)は、表の外にある値を取るために使います。 「What is the statement period?」「What is the total commission amount?」のように聞くと、答えが QUERY_RESULT として信頼度付きで返ります。公式の制限では、非同期の処理で1ページあたり30件までで、問い合わせは英語の文書でだけ使えます。 表の中身は問い合わせではなく TABLES で取ります。

状態が PARTIAL_SUCCESS のときは、照合に進みません。 一部のページが処理できていないということなので、Warnings に出たページ番号を記録し、担当者に回します。

Step4

AIへ渡す前に整形する

  1. 形式とサイズの確認 … Textract が受け付けるのは JPEG、PNG、PDF、TIFF です。非同期の処理で PDF は500MB・3,000ページまでです
  2. パスワード付きPDFの確認 … PDF はパスワードで保護されていてはいけません。旅行会社に保護のない版を送ってもらいます
  3. XFA 形式の確認 … XFA 形式の PDF は対応していません。印刷して PDF にし直すか、旅行会社に別の形式を頼みます
  4. 文字の大きさの確認 … 検出できる文字の高さの下限は15ピクセルで、150DPI では8ポイントの文字に相当します。縮小して印刷された精算書は読み落とします
  5. 表の行を組み立てる … CELL の RowIndex と ColumnIndex から行列を作り、MERGED_CELL の値を対応する行に割り当てます
  6. 複数ページの表をつなぐ … ページごとに分かれた表を、列見出しが同じなら1つの表としてつなぎます
  7. 重複の検知 … 同じ旅行会社・同じ対象期間の精算書がすでに処理されていれば、印を付けて止めます

6番目を軽く見ないでください。 精算書は2ページ目以降に列見出しを繰り返さないことが多く、別の表として扱うと2ページ目の列の意味が決まりません。

Step5

AIに処理させる

させるのは、組み立てた表の列を共通の項目にそろえることだけです。 列見出しの文字と、各列の値の並びを見て、どの列が何を表すかを決めさせます。

共通の項目精算書でよく使われる列名の例判断できないときの扱い
agent_ref(旅行会社の予約番号)Booking Ref、Confirmation No.、Voucher #候補が2列あれば ambiguous
guest_name(宿泊者名)Guest、Lead Name、Pax Name無ければ null
arrival / departureCheck-in、Arr.、Check-out、Dep.日・月の順は会社の設定に従う
nights(泊数)Nights、RN、Room Nights部屋数×泊数の列なら room_nights に分ける
base_amount(基準額)Room Revenue、Net Rate、Commissionable Amount食事や税が含まれるか不明なら ambiguous
rate(手数料率)Comm %、Rate表の外にだけあれば null
commission(手数料)Commission、Comm. Amount必ず埋める。無ければ needs_human

右端の列が、この構成でいちばん大事な扱いです。 列の意味が1つに決まらないとき、AIは「たぶんこれ」と選びがちです。選ばせずに ambiguous で返させ、旅行会社ごとの設定に正しい対応を登録します。 2回目からは登録した対応を先に当て、AIはその検証に回します。

させないこと理由
手数料の計算・再計算計算はプログラムで行う。AIの計算の誤りを判定に混ぜない
日付の日・月の順の推測会社の設定で決める。値から推測すると取り違える
台帳との照合予約番号の一致は機械的に判定する
支払うかどうかの判断契約の解釈に関わる。営業課と経理課が決める
金額の書き換え・端数の補正読み取った文字列をそのまま渡す

1行目がいちばん起きやすい失敗です。 列をそろえるついでに「この行の手数料は10%なので…」と計算を始めます。指示で計算を禁じ、出力の形にも計算結果を入れる項目を作りません。

Step6

指示内容を固定する

You map columns of a travel agent's commission statement to standard fields.
Use only the table given below. Do not calculate anything.

[Standard fields]
agent_ref, guest_name, arrival, departure, nights, room_nights,
base_amount, rate, commission, currency

[Rules]
- For each source column, choose one standard field or "unmapped".
- If two or more columns could be the same field, set status to "ambiguous"
  and list the candidate columns. Do not pick one.
- Copy cell values exactly as written. Do not convert dates, numbers,
  or currencies. Do not round.
- Do not decide the day/month order of dates. The order is given in
  [Agent settings].
- Do not compute commission, rate, or base_amount from other columns.
  If a value is missing, return null.
- If the table header says that meals, taxes, or service charges are
  included in the base amount, record it in base_note. Do not judge
  whether the commission is correct.
- If the document is not a commission statement, set document_type and stop.

[Agent settings] {agent_settings}
[Known column mapping for this agent] {known_mapping}
[Table header cells] {header_cells}
[First 10 rows] {sample_rows}
[Text outside the table] {query_results}

指示を英語で書くのは、列名を日本語に訳して返させないためです。 訳されると、後段のプログラムで列名と照らせなくなります。

「Do not compute」を2か所に書いているのは、計算を止めるためです。 手数料の列が空の行があると、率と基準額から埋めて返します。埋めた値が正しくても、精算書に書かれていないという事実が消えます。 その行は旅行会社に確かめるべき行です。

Step7

出力形式を固定する

次の形のJSONで受け取ります。 Claude API の構造化出力(output_config.format に type: "json_schema")で形を守らせます。

{
  "statement_id": "",
  "document_type": "commission_statement",
  "agent_code": "",
  "period": { "from": "", "to": "", "source": "query | table | not_found" },
  "currency": "",
  "column_mapping": [
    { "source_column": "", "field": "agent_ref", "status": "mapped | ambiguous | unmapped",
      "candidates": [] }
  ],
  "base_note": "",
  "summary_total": ""
}

1つ目の理由は、列の対応だけを返させられることです。 出力に行の値を含めず、列の対応だけを受け取ります。 値はTextract の結果からプログラムが取り出すので、AIが値を写し間違える経路がありません。

2つ目は、照合の結果を別の層に置けることです。 プログラムは列の対応を使って行を組み立て、台帳と契約に照らして次の判定を付けます。

判定条件
ok予約が台帳にあり宿泊済み、日付と泊数が一致、計算し直した手数料との差が許容範囲内
mismatch率・基準額・泊数・日付のいずれかが違う。違う項目を reasons に入れる
not_found旅行会社の予約番号が台帳に無い
needs_human予約が取消・不泊、列の対応が ambiguous、または読み取りの信頼度が低い

取消と不泊を mismatch にせず needs_human にしているのは、契約で扱いが分かれるからです。 不泊でも手数料を払う取り決めの会社もあります。判定はプログラムで機械的に出しますが、支払うかは人が決めます。

3つ目は、スキーマの制約に合わせられることです。 公式の説明では、オブジェクトには additionalProperties: false が必要で、数値の範囲(minimum など)や文字数(minLength など)の制約は使えません。金額や率の範囲の確認は、プログラムの側で行います。 なお、Amazon Bedrock 上の Claude では構造化出力の対応範囲が限られるため、この構成では Claude API を直接呼びます。

Step8

システムへ連携する

つなぎ先方式内容
Amazon S3保存の通知受付フォルダへの保存で処理を始める
AWS TextractAPI呼び出し非同期の文書分析の開始と結果の取得
Amazon SNS完了の通知分析の終了を受けて次の処理を動かす
Claude APIAPI呼び出し列の対応と、問い合わせ文の下書き
予約管理システム予約データの書き出し予約番号・状態・日付・料金を読む
会計システム既存の登録の経路確定した支払額だけを登録する

予約管理システムへは書き込みません。 取消の漏れや予約番号の入れ忘れが見つかっても、台帳を直すのは予約の担当者です。

会計システムへの登録も、人が確定したものだけです。 食い違いの行を除いた額を自動で登録すると、問い合わせの結果を待たずに支払が進みます。

Step9

人が確認する

経理課の担当者が見るのは、ok 以外の行と、合計の照合です。

  1. 合計を先に見る … 明細の手数料の合計と、精算書の合計の行(TABLE_SUMMARY)が一致するかを見ます。一致しなければ、読み取りの抜けを疑います
  2. needs_human を見る … 取消・不泊の行は、契約で手数料の扱いを確かめます。列の対応が ambiguous なら、正しい対応を設定に登録します
  3. mismatch の理由を確かめる … 率の違いか、基準額の違いかで、問い合わせの書き方が変わります
  4. not_found を予約担当と確かめる … 台帳に旅行会社の番号が入っていないだけのことが多くあります
  5. 問い合わせを送る … 下書きを直して、担当者が送ります

4番目を省かないでください。 not_found の多くは、自社の台帳に旅行会社の予約番号が入っていなかったというだけです。 そのまま旅行会社に問い合わせると、相手に余計な調べものをさせます。

目標は、60枚をならして1枚15分です。 食い違いの少ない会社の精算書は数分で終わり、取消の多い月の団体の精算書は長くかかります。

Step10

例外に対処する

起きること対応
パスワード付きPDFPDF はパスワードで保護されていてはいけない。旅行会社に保護のない版を依頼
XFA 形式のPDF対応していない。印刷してPDF化するか、別の形式を依頼
和文の精算書が混ざるTextract は日本語に対応しない。別の読み取りの経路に回す
JobStatus が PARTIAL_SUCCESSWarnings のページを記録し、照合に進まず担当者へ
明細の合計と精算書の合計が合わない行の読み落としを疑い、needs_human
2ページ目以降に列見出しが無い1ページ目の見出しを引き継いでつなぐ
列の対応が ambiguous担当者が正しい対応を設定に登録して再処理
同じ精算書が二度届く旅行会社と対象期間で照合し、二重に処理しない
通貨が契約と違う換算はしない。契約の取り決めを営業課に確かめる

上から3行目は、受付の時点で止めます。 受付フォルダの設定に「英文のみ」を持たせ、例外は別の経路にします。

Step11

記録を残す

  • 元の精算書と、受け取った日時・旅行会社・対象期間
  • Textract の結果の全文(JobId、ブロック、Warnings)
  • 列の対応(AIの出力)と、人が直した対応
  • 行ごとの照合の結果と、そのとき参照した契約の率と基準
  • 問い合わせの内容と旅行会社の回答、支払額の確定の記録
  • 旅行会社ごとの mismatch と needs_human の件数

JobId は7日間しか有効でないため、結果は取得したその場で保存します。 後から取り直そうとしても、結果が取れなくなっています。

最後の行は、契約の見直しの材料です。 同じ会社で率の食い違いが続くなら、相手の側の設定が古いままです。 1行ずつ問い合わせるより、契約の率を確かめ合うほうが早く終わります。

04実装レベルの3段階

最小構成:手元のAIサービスで列をそろえ、表計算で台帳と照合する / 1枚ごとの列のそろえ
半自動化:上記+Textract で表を読み取り、列の対応と行を一覧に書き出す / 読み取りと列のそろえの一覧化
本格構成:上記+受付フォルダを起点に自動で動かし、台帳と契約で照合し、問い合わせの下書きまで出す / 照合の全体と、問い合わせ先の洗い出し

最小構成では枚数がさばけません。 60枚には使えず、確かめるための段階です。 半自動化で、1枚60分が35分程度になります。 行の読み取りは自動になりますが、台帳との照合と率の確認は人が表計算で行います。本格構成で15分になり、この段階が本記事の想定です。 差が大きいのは、台帳を1行ずつ引く作業と、契約の率を確かめる作業が、プログラムに移るからです。 段階を飛ばさないでください。 半自動化の段階で1か月回すと、列の対応が決まらない会社と、台帳に旅行会社の番号が無い予約が見えてきます。そこを直してから本格構成に進みます。

05工数削減シミュレーション

前提値(モデル条件)
対象人数
3 名
月間件数
60 件
1件あたり現在時間
60 分
1件あたり導入後時間
15 分
現在  60件 × 60分 ÷ 60 = 60 時間/月
導入後 60件 × 15分 ÷ 60 = 15 時間/月
月間削減時間
45h
削減率
75%
年間削減時間
540h
年間金額換算(時間単価3,000円)
162万円
モデル条件による試算であり、実際の効果は業務内容・運用方法によって異なります。

自社条件で導入効果を整理したい方へ

このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。

AI活用について相談する

06向いている企業・向いていない企業

向いている
  1. 海外の旅行会社・ホールセラー数十社と手数料の契約を結び、毎月その会社ごとの英文の精算書をPDFで受け取っているホテル・旅館。精算書の書式が会社ごとに違い、1枚あたり数十行の予約を予約台帳と1行ずつ照らしている場合。契約の手数料率と、手数料の基準に含めるもの(客室料金だけか、食事を含むか)を一覧にできる場合。
向いていない
  1. 取引のある海外の旅行会社が数社で、精算書の行数も少ない場合。手数料を予約サイトの側で差し引いて入金される形だけで、精算書を照合する場面がない場合。精算書が電子データ(CSVなど)で届き、そのまま予約台帳と突き合わせられる場合。なお、手数料を支払うかどうか、契約の解釈が分かれる予約をどう扱うかは、この構成では決めません。

07最小構成で試す方法

  1. 先月届いた精算書から5社分を選ぶ(うち1社は、取消や率の違いがあったと分かっているものを入れる)
  2. その5枚について、当時どの行で問い合わせをしたかを聞き取る
  3. 精算書のPDFを手元のAIサービスに1枚ずつ渡す
  4. 「この表の列を、予約番号・到着日・出発日・泊数・基準額・率・手数料にそろえて一覧にしてください。計算はしないでください。列の意味が決まらないものは決めずに残してください」と指示する
  5. 出てきた一覧を予約台帳の書き出しと表計算で突き合わせ、当時の問い合わせと比べる

5社分は必ずやってください。 ワークフローを組む前に、「列をそろえれば、照合は表計算で足りるのか」を確かめます。

出てきた内容判断
当時と同じ食い違いが見つかった読み取りと照合の自動化に進む
手数料を勝手に計算し直した指示の書き方で直る。構成は有効
台帳に旅行会社の予約番号が無く引けない台帳の運用が先。 AIの問題ではない

3行目が出ることは珍しくありません。 失敗ではなく、目視の照合に時間がかかっていた理由が1つ分かったということです。

08実装時につまずきやすいポイント

問題対策
AIが手数料を計算し直して返す計算を禁じ、出力に計算結果の項目を作らない
日付の日・月の順を取り違える会社ごとの設定で決める。値から推測させない
後半のページの行が抜けるNextToken が無くなるまで結果を取る
2ページ目の列の意味が決まらない1ページ目の列見出しを引き継ぐ
団体の行の値がずれるMERGED_CELL の値を対応する行に割り当てる
取消・不泊の予約に手数料を払う台帳の状態で needs_human にする
台帳に予約が見つからない旅行会社の予約番号を台帳に入れる運用にする
率は合っているのに額が違う契約の一覧に基準(食事・税を含むか)を持たせる
和文の精算書で文字が抜けるTextract は日本語に対応しない。受付で分ける
結果を後から取り直せないJobId は7日間だけ有効。取得したら保存する
問い合わせのメールが自動で飛ぶ下書きまでにする。 送信は人が行う

上の3行が、この構成の失敗のほとんどです。 どれも「読み取れたように見えて、値が違うか抜けている」という同じ形をしています。計算はプログラムに、日付の順は設定に、ページの集め方は手順に置いてあるかで、運用に乗るかが決まります。

09セキュリティ・AIガバナンス上の注意点

この構成で扱うデータ: 宿泊者の氏名、宿泊日、客室料金と手数料、旅行会社との契約の率です。宿泊者の氏名は個人情報で、契約の率は取引先との取り決めです。

  1. 生成AIに渡す範囲を、列のそろえに必要な分までに限る … 渡すのは列見出しと先頭の数行です。宿泊者名の列は、値を伏せて「Guest」という見出しだけを渡す設計にできます
  2. 契約の率を生成AIに渡さない … 率と基準は、照合のプログラムだけが読みます。旅行会社ごとの取り決めがまとまった一覧を、外部へ出さないでください
  3. 問い合わせを自動で送らない … 出すのは下書きまでです。取引先との関係に直接ひびき、誤った問い合わせは相手の調べものを増やします
  4. 支払うかどうかを決めない … 取消・不泊の予約にどう手数料を払うかは、契約の解釈として営業課と経理課が決めることです。 この構成が出すのは、台帳と契約に照らした事実だけです
  5. 読み取りの結果の保管場所を決める … Textract の結果は既定ではサービスの側に保持され、出力先の S3 を指定することもできます。宿泊者名を含む結果を、どこに、いつまで残すかを決めてから始めてください

誤りが起きた場合のリスクは、払うべきでない手数料を払うことと、正しい精算書に問い合わせをすることの2つです。 前者は取消・不泊の見落としで、後者は日付の読み違いや台帳の番号の未登録で起きます。どちらも生成AIではなく、設定と台帳の側で防ぎます。

10まず何から始めるか

1週目:旅行会社ごとの設定と契約の一覧を作る

取引のある約40社について、日付の書き方、通貨、手数料の率と適用期間、基準に含めるものを一覧にします。営業課の担当者2名の記憶にある取り決めを、ここで書き出します。件数の多い上位10社から始めます。

2週目:5社分で試す

先月の精算書から5社分を選び、手元のAIサービスで列をそろえ、表計算で台帳と照らします。手数料を勝手に計算し直していないか、日付の順を取り違えていないかを最優先で見ます。

3週目:予約台帳の運用を直す

予約を受けたときに、旅行会社の予約番号を台帳の項目に入れるよう、予約の担当者と決めます。過去分は、試行で not_found になった予約から埋めます。

4週目:読み取りと列のそろえをつなぐ

受付フォルダへの保存から Textract の分析、列のそろえまでを作り、結果を一覧に書き出すところまでにします。この時点では照合の判定を出さず、行がそろっているかだけを見ます。

2か月目: 台帳と契約の一覧での照合と、手数料の再計算を足し、判定を出します。mismatch と needs_human の件数を会社ごとに数えます。3か月目以降: 問い合わせの下書きを足し、1枚60分が何分になったかを実測します。食い違いの続く会社と契約の率を確かめ合い、同じ問い合わせが出なくなった時点で、この構成は完成です。


11関連ユースケース

12この仕組みを理解するための記事

13技術仕様の確認日・参考情報

技術仕様確認日:2026-10-13/最終更新:2026-10-13
確認した内容情報源確認日
対応する言語が英語・フランス語・ドイツ語・イタリア語・ポルトガル語・スペイン語で、縦書きに対応しないこと。問い合わせは英語の文書でのみ使えること。対応する形式が JPEG・PNG・PDF・TIFF で XFA 形式の PDF に対応しないこと。同期の処理は PDF が1ページまで、非同期の処理は PDF が500MB・3,000ページまでであること。PDF はパスワードで保護されていてはいけないこと。文字の高さの下限が15ピクセル(150DPIで8ポイント)であること。問い合わせが非同期で1ページ30件までであることAWS: Set Quotas in Amazon Textract2026-10-13
StartDocumentAnalysis が S3 の文書を非同期で分析し、FeatureTypes に TABLES・FORMS・QUERIES・SIGNATURES・LAYOUT を指定できること。完了の状態を Amazon SNS に通知すること。JobId が7日間だけ有効なこと。OutputConfig で出力先の S3 を指定でき、既定ではサービスの側に結果が保存されることAWS: StartDocumentAnalysis2026-10-13
GetDocumentAnalysis の JobStatus が IN_PROGRESS・SUCCEEDED・FAILED・PARTIAL_SUCCESS であること。MaxResults の上限が1,000で、残りは NextToken で取得すること。Warnings と QUERY_RESULT ブロック(信頼度付き)を返すことAWS: GetDocumentAnalysis2026-10-13
表が TABLE・CELL・MERGED_CELL ブロックで返り、セルに行と列の位置が付くこと。セルの種類として COLUMN_HEADER・TABLE_SUMMARY・TABLE_TITLE・TABLE_FOOTER などがあること。表の種類として STRUCTURED_TABLE と SEMI_STRUCTURED_TABLE があることAWS: Tables2026-10-13
Claude API の構造化出力が output_config.format に type: "json_schema" を指定して使えること。オブジェクトには additionalProperties: false が必要で、数値や文字数の制約が使えないこと。Amazon Bedrock では一部の統合でのみ提供されていることClaude: Structured outputs2026-10-13

手数料を払うかどうか、契約をどう解釈するかは、旅行会社との契約を担当する部署と経理で決めてください。 本記事は公式ドキュメントで確認できた範囲だけを扱っています。

実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。

自社の業務に使えるAI活用候補を整理します

このユースケース(UC-1341)についてのご相談はこちらから。

AI活用について相談する
目次