海外の旅行会社から毎月届く英文の手数料の精算書を読み取り、予約台帳と突き合わせて、手数料率と対象の予約の食い違いを拾う
海外の旅行会社から毎月届く英文の手数料の精算書(commission statement)を読み取り、1行ずつ予約台帳と契約の手数料率に照らします。率が違う行、取消や不泊の予約に手数料が付いた行、台帳に無い予約を、支払う前に一覧にします。
- 生成AI
- ChatGPT/Claude
- AIサービス
- AWS Textract/Azure AI/Google Document AI
- 連携・自動化
- Python
- 対象業界
- その他/宿泊
- 対象部門
- 営業/経理
- 対象業務
- 内容確認・チェック/比較検討
- 主な課題
- 人手が足りない/入力作業が多い/確認ミスが多い
- AIで行う処理
- 読み取り(OCR)
- 主な効果
- 入力漏れ削減/品質標準化/工数削減
- 導入難易度
- ★★★☆☆
- 実装レベル
- 本格構成
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 経理課の担当者が、メールで届いた精算書のPDFを共有フォルダに保存する
- 精算書の行を1行ずつ読み、予約番号で予約管理システムを検索する
- 到着日・出発日・泊数・客室料金を、台帳と見比べる
- 予約が取消・不泊になっていないかを確かめる
- 契約の一覧を開き、その会社のその時期の率と、基準に含めるものを確かめる
- 手数料を電卓か表計算で計算し直し、精算書の額と比べる
- 食い違いがあれば、営業課に確認したうえで旅行会社に英文で問い合わせる
- 確認が済んだものを会計システムに登録し、支払に回す
- 人精算書のPDFを、旅行会社ごとの受付フォルダに保存する
- 自動保存をきっかけに、Textract の非同期の文書分析を始める(表と問い合わせ項目)
- 自動分析が終わった通知を受け、表のセルと問い合わせの答えを取り出す
- 自動生成AIが、表の列を共通の項目にそろえ、日付の書き方をその会社の設定で読む
- 自動プログラムが予約番号で台帳を引き、取消・不泊・日付・泊数・料金を照らす
- 自動プログラムが契約の一覧から率と基準を引き、手数料を計算し直して差を出す
- 自動行ごとに `ok` / `mismatch` / `not_found` / `needs_human` を付け、問い合わせ文の下書きを作る
- 人経理課の担当者が `ok` 以外の行だけを確かめ、営業課と相談して問い合わせる
- 人確定した支払額を会計システムに登録する
各工程の詳しい説明を読む
- 経理課の担当者が、メールで届いた精算書のPDFを共有フォルダに保存する
- 精算書の行を1行ずつ読み、予約番号で予約管理システムを検索する
- 到着日・出発日・泊数・客室料金を、台帳と見比べる
- 予約が取消・不泊になっていないかを確かめる
- 契約の一覧を開き、その会社のその時期の率と、基準に含めるものを確かめる
- 手数料を電卓か表計算で計算し直し、精算書の額と比べる
- 食い違いがあれば、営業課に確認したうえで旅行会社に英文で問い合わせる
- 確認が済んだものを会計システムに登録し、支払に回す
(a)取消と不泊が残っている。 旅行会社の側で取消の処理が遅れた予約や、到着しなかった予約が、精算書に残っていることがあります。4番を省くと、泊まっていない予約に手数料を払います。 忙しい月ほど、ここが目視から落ちます。
(b)率と基準額の取り決めが細かい。 基本の率は合っていても、食事込みの料金に率を掛けている、特別料金の時期にも手数料が付いている、という食い違いがあります。5番で契約の一覧を毎回開くのは手間で、担当者が覚えている率で済ませることがあります。
(c)日付の書き方が会社ごとに違う。 日・月の順が違う会社の精算書を読み違えると、存在しない予約として問い合わせることになります。 旅行会社からは「ちゃんと見てほしい」と返されます。
(d)全行を目視するのは続かない。 60枚に数十行ずつで、1枚1時間かかります。 締めの前に重なると、行の照合を省いて合計額だけを見て支払うことになります。
- 【人】 精算書のPDFを、旅行会社ごとの受付フォルダに保存する
- 【自動】 保存をきっかけに、Textract の非同期の文書分析を始める(表と問い合わせ項目)
- 【自動】 分析が終わった通知を受け、表のセルと問い合わせの答えを取り出す
- 【自動】 生成AIが、表の列を共通の項目にそろえ、日付の書き方をその会社の設定で読む
- 【自動】 プログラムが予約番号で台帳を引き、取消・不泊・日付・泊数・料金を照らす
- 【自動】 プログラムが契約の一覧から率と基準を引き、手数料を計算し直して差を出す
- 【自動】 行ごとに
ok/mismatch/not_found/needs_humanを付け、問い合わせ文の下書きを作る - 【人】 経理課の担当者が
ok以外の行だけを確かめ、営業課と相談して問い合わせる - 【人】 確定した支払額を会計システムに登録する
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 ── 旅行会社への英文の問い合わせの下書き └──▶ 会計システムへ確定額を登録
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| OCR | AWS Textract(StartDocumentAnalysis/GetDocumentAnalysis) | Azure AI Document Intelligence、Google Document AI |
| 生成AI | Claude 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どうやって実装するのか
処理の起点を決める
起点は、精算書のPDFを受付フォルダ(Amazon S3)に保存したことです。 保存のたびに1枚ずつ処理を動かします。月末にまとめて処理しないのは、問い合わせの返事を待つ時間を残すためです。 旅行会社の時差を考えると、問い合わせは早く出すほど支払日に間に合います。
受付フォルダは旅行会社ごとに分けます。 フォルダの名前から旅行会社を決め、その会社の設定(日付の書き方、通貨、基準)を処理の最初に読み込みます。精算書の中の会社名をAIに読ませて会社を決めると、ロゴだけの精算書で取り違えます。
文書分析は非同期の StartDocumentAnalysis で始めます。 同期の処理は PDF が1ページまでという制限があり、数ページにわたる精算書は非同期で扱います。 終わると Amazon SNS に完了の状態が通知されるので、それを起点に結果を取りに行きます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 精算書 | 英文のPDF。旅行会社、対象期間、予約ごとの行、合計 | 受付フォルダ |
| 読み取り結果 | 表のセル(行と列の位置、列見出し、合計の行)、問い合わせの答え、信頼度 | AWS Textract |
| 予約台帳 | 予約番号(自社と旅行会社の両方)、宿泊者名、到着日、出発日、泊数、状態(宿泊・取消・不泊)、客室料金、食事料金 | 予約管理システムの書き出し |
| 契約の一覧 | 旅行会社ごとの手数料率、適用期間、基準に含めるもの、手数料を付けない料金の種類 | 営業課が持つ一覧 |
| 旅行会社ごとの設定 | 日付の書き方、通貨、列名の対応の実績 | 経理課が作る一覧 |
質を決めるのは、予約台帳に旅行会社の予約番号が入っているかです。 精算書には旅行会社の側の番号しか書かれていないことが多く、自社の予約番号だけでは突き合わせる先がありません。 予約を受けたときに、旅行会社の番号を台帳の項目に入れる運用を先に決めます。
契約の一覧は、率だけでは足りません。 「客室料金のみ」「食事を含む」「税・サービス料を除く」といった基準と、手数料を付けない料金の種類を持たせます。第3章の(b)は、ここが一覧になっていないことから起きています。
データの取得方法を決める
結果の取得には GetDocumentAnalysis を使います。 1回の呼び出しで返るブロックは最大1,000件で、それを超えると NextToken が返るため、NextToken が無くなるまで呼び続けて全部を集めます。 途中で止めると、後半のページの行が丸ごと抜けます。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 表とセル | TABLE・CELL ブロック(RowIndex、ColumnIndex) | 明細の行を組み立てる |
| 列見出し | EntityTypes が COLUMN_HEADER のセル | 列の意味を決める材料 |
| 合計の行 | EntityTypes が TABLE_SUMMARY のセル | 明細の合計と照らす |
| 結合されたセル | MERGED_CELL ブロック | 団体の行で複数行にまたがる値を正しく割り当てる |
| 問い合わせの答え | QUERY_RESULT ブロック | 対象期間、旅行会社名、合計額、通貨 |
| 処理の状態 | JobStatus、Warnings | PARTIAL_SUCCESS やページの警告を検知する |
問い合わせ(QUERIES)は、表の外にある値を取るために使います。 「What is the statement period?」「What is the total commission amount?」のように聞くと、答えが QUERY_RESULT として信頼度付きで返ります。公式の制限では、非同期の処理で1ページあたり30件までで、問い合わせは英語の文書でだけ使えます。 表の中身は問い合わせではなく TABLES で取ります。
状態が PARTIAL_SUCCESS のときは、照合に進みません。 一部のページが処理できていないということなので、Warnings に出たページ番号を記録し、担当者に回します。
AIへ渡す前に整形する
- 形式とサイズの確認 … Textract が受け付けるのは JPEG、PNG、PDF、TIFF です。非同期の処理で PDF は500MB・3,000ページまでです
- パスワード付きPDFの確認 … PDF はパスワードで保護されていてはいけません。旅行会社に保護のない版を送ってもらいます
- XFA 形式の確認 … XFA 形式の PDF は対応していません。印刷して PDF にし直すか、旅行会社に別の形式を頼みます
- 文字の大きさの確認 … 検出できる文字の高さの下限は15ピクセルで、150DPI では8ポイントの文字に相当します。縮小して印刷された精算書は読み落とします
- 表の行を組み立てる …
CELLのRowIndexとColumnIndexから行列を作り、MERGED_CELLの値を対応する行に割り当てます - 複数ページの表をつなぐ … ページごとに分かれた表を、列見出しが同じなら1つの表としてつなぎます
- 重複の検知 … 同じ旅行会社・同じ対象期間の精算書がすでに処理されていれば、印を付けて止めます
6番目を軽く見ないでください。 精算書は2ページ目以降に列見出しを繰り返さないことが多く、別の表として扱うと2ページ目の列の意味が決まりません。
AIに処理させる
させるのは、組み立てた表の列を共通の項目にそろえることだけです。 列見出しの文字と、各列の値の並びを見て、どの列が何を表すかを決めさせます。
| 共通の項目 | 精算書でよく使われる列名の例 | 判断できないときの扱い |
|---|---|---|
agent_ref(旅行会社の予約番号) | Booking Ref、Confirmation No.、Voucher # | 候補が2列あれば ambiguous |
guest_name(宿泊者名) | Guest、Lead Name、Pax Name | 無ければ null |
arrival / departure | Check-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%なので…」と計算を始めます。指示で計算を禁じ、出力の形にも計算結果を入れる項目を作りません。
指示内容を固定する
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か所に書いているのは、計算を止めるためです。 手数料の列が空の行があると、率と基準額から埋めて返します。埋めた値が正しくても、精算書に書かれていないという事実が消えます。 その行は旅行会社に確かめるべき行です。
出力形式を固定する
次の形の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 を直接呼びます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| Amazon S3 | 保存の通知 | 受付フォルダへの保存で処理を始める |
| AWS Textract | API呼び出し | 非同期の文書分析の開始と結果の取得 |
| Amazon SNS | 完了の通知 | 分析の終了を受けて次の処理を動かす |
| Claude API | API呼び出し | 列の対応と、問い合わせ文の下書き |
| 予約管理システム | 予約データの書き出し | 予約番号・状態・日付・料金を読む |
| 会計システム | 既存の登録の経路 | 確定した支払額だけを登録する |
予約管理システムへは書き込みません。 取消の漏れや予約番号の入れ忘れが見つかっても、台帳を直すのは予約の担当者です。
会計システムへの登録も、人が確定したものだけです。 食い違いの行を除いた額を自動で登録すると、問い合わせの結果を待たずに支払が進みます。
人が確認する
経理課の担当者が見るのは、ok 以外の行と、合計の照合です。
- 合計を先に見る … 明細の手数料の合計と、精算書の合計の行(
TABLE_SUMMARY)が一致するかを見ます。一致しなければ、読み取りの抜けを疑います needs_humanを見る … 取消・不泊の行は、契約で手数料の扱いを確かめます。列の対応がambiguousなら、正しい対応を設定に登録しますmismatchの理由を確かめる … 率の違いか、基準額の違いかで、問い合わせの書き方が変わりますnot_foundを予約担当と確かめる … 台帳に旅行会社の番号が入っていないだけのことが多くあります- 問い合わせを送る … 下書きを直して、担当者が送ります
4番目を省かないでください。 not_found の多くは、自社の台帳に旅行会社の予約番号が入っていなかったというだけです。 そのまま旅行会社に問い合わせると、相手に余計な調べものをさせます。
目標は、60枚をならして1枚15分です。 食い違いの少ない会社の精算書は数分で終わり、取消の多い月の団体の精算書は長くかかります。
例外に対処する
| 起きること | 対応 |
|---|---|
| パスワード付きPDF | PDF はパスワードで保護されていてはいけない。旅行会社に保護のない版を依頼 |
| XFA 形式のPDF | 対応していない。印刷してPDF化するか、別の形式を依頼 |
| 和文の精算書が混ざる | Textract は日本語に対応しない。別の読み取りの経路に回す |
JobStatus が PARTIAL_SUCCESS | Warnings のページを記録し、照合に進まず担当者へ |
| 明細の合計と精算書の合計が合わない | 行の読み落としを疑い、needs_human |
| 2ページ目以降に列見出しが無い | 1ページ目の見出しを引き継いでつなぐ |
列の対応が ambiguous | 担当者が正しい対応を設定に登録して再処理 |
| 同じ精算書が二度届く | 旅行会社と対象期間で照合し、二重に処理しない |
| 通貨が契約と違う | 換算はしない。契約の取り決めを営業課に確かめる |
上から3行目は、受付の時点で止めます。 受付フォルダの設定に「英文のみ」を持たせ、例外は別の経路にします。
記録を残す
- 元の精算書と、受け取った日時・旅行会社・対象期間
- Textract の結果の全文(
JobId、ブロック、Warnings) - 列の対応(AIの出力)と、人が直した対応
- 行ごとの照合の結果と、そのとき参照した契約の率と基準
- 問い合わせの内容と旅行会社の回答、支払額の確定の記録
- 旅行会社ごとの
mismatchとneeds_humanの件数
JobId は7日間しか有効でないため、結果は取得したその場で保存します。 後から取り直そうとしても、結果が取れなくなっています。
最後の行は、契約の見直しの材料です。 同じ会社で率の食い違いが続くなら、相手の側の設定が古いままです。 1行ずつ問い合わせるより、契約の率を確かめ合うほうが早く終わります。
04実装レベルの3段階
最小構成では枚数がさばけません。 60枚には使えず、確かめるための段階です。 半自動化で、1枚60分が35分程度になります。 行の読み取りは自動になりますが、台帳との照合と率の確認は人が表計算で行います。本格構成で15分になり、この段階が本記事の想定です。 差が大きいのは、台帳を1行ずつ引く作業と、契約の率を確かめる作業が、プログラムに移るからです。 段階を飛ばさないでください。 半自動化の段階で1か月回すと、列の対応が決まらない会社と、台帳に旅行会社の番号が無い予約が見えてきます。そこを直してから本格構成に進みます。
05工数削減シミュレーション
導入後 60件 × 15分 ÷ 60 = 15 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 海外の旅行会社・ホールセラー数十社と手数料の契約を結び、毎月その会社ごとの英文の精算書をPDFで受け取っているホテル・旅館。精算書の書式が会社ごとに違い、1枚あたり数十行の予約を予約台帳と1行ずつ照らしている場合。契約の手数料率と、手数料の基準に含めるもの(客室料金だけか、食事を含むか)を一覧にできる場合。
- 取引のある海外の旅行会社が数社で、精算書の行数も少ない場合。手数料を予約サイトの側で差し引いて入金される形だけで、精算書を照合する場面がない場合。精算書が電子データ(CSVなど)で届き、そのまま予約台帳と突き合わせられる場合。なお、手数料を支払うかどうか、契約の解釈が分かれる予約をどう扱うかは、この構成では決めません。
07最小構成で試す方法
- 先月届いた精算書から5社分を選ぶ(うち1社は、取消や率の違いがあったと分かっているものを入れる)
- その5枚について、当時どの行で問い合わせをしたかを聞き取る
- 精算書のPDFを手元のAIサービスに1枚ずつ渡す
- 「この表の列を、予約番号・到着日・出発日・泊数・基準額・率・手数料にそろえて一覧にしてください。計算はしないでください。列の意味が決まらないものは決めずに残してください」と指示する
- 出てきた一覧を予約台帳の書き出しと表計算で突き合わせ、当時の問い合わせと比べる
5社分は必ずやってください。 ワークフローを組む前に、「列をそろえれば、照合は表計算で足りるのか」を確かめます。
| 出てきた内容 | 判断 |
|---|---|
| 当時と同じ食い違いが見つかった | 読み取りと照合の自動化に進む |
| 手数料を勝手に計算し直した | 指示の書き方で直る。構成は有効 |
| 台帳に旅行会社の予約番号が無く引けない | 台帳の運用が先。 AIの問題ではない |
3行目が出ることは珍しくありません。 失敗ではなく、目視の照合に時間がかかっていた理由が1つ分かったということです。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| AIが手数料を計算し直して返す | 計算を禁じ、出力に計算結果の項目を作らない |
| 日付の日・月の順を取り違える | 会社ごとの設定で決める。値から推測させない |
| 後半のページの行が抜ける | NextToken が無くなるまで結果を取る |
| 2ページ目の列の意味が決まらない | 1ページ目の列見出しを引き継ぐ |
| 団体の行の値がずれる | MERGED_CELL の値を対応する行に割り当てる |
| 取消・不泊の予約に手数料を払う | 台帳の状態で needs_human にする |
| 台帳に予約が見つからない | 旅行会社の予約番号を台帳に入れる運用にする |
| 率は合っているのに額が違う | 契約の一覧に基準(食事・税を含むか)を持たせる |
| 和文の精算書で文字が抜ける | Textract は日本語に対応しない。受付で分ける |
| 結果を後から取り直せない | JobId は7日間だけ有効。取得したら保存する |
| 問い合わせのメールが自動で飛ぶ | 下書きまでにする。 送信は人が行う |
上の3行が、この構成の失敗のほとんどです。 どれも「読み取れたように見えて、値が違うか抜けている」という同じ形をしています。計算はプログラムに、日付の順は設定に、ページの集め方は手順に置いてあるかで、運用に乗るかが決まります。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 宿泊者の氏名、宿泊日、客室料金と手数料、旅行会社との契約の率です。宿泊者の氏名は個人情報で、契約の率は取引先との取り決めです。
- 生成AIに渡す範囲を、列のそろえに必要な分までに限る … 渡すのは列見出しと先頭の数行です。宿泊者名の列は、値を伏せて「Guest」という見出しだけを渡す設計にできます
- 契約の率を生成AIに渡さない … 率と基準は、照合のプログラムだけが読みます。旅行会社ごとの取り決めがまとまった一覧を、外部へ出さないでください
- 問い合わせを自動で送らない … 出すのは下書きまでです。取引先との関係に直接ひびき、誤った問い合わせは相手の調べものを増やします
- 支払うかどうかを決めない … 取消・不泊の予約にどう手数料を払うかは、契約の解釈として営業課と経理課が決めることです。 この構成が出すのは、台帳と契約に照らした事実だけです
- 読み取りの結果の保管場所を決める … 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技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| 対応する言語が英語・フランス語・ドイツ語・イタリア語・ポルトガル語・スペイン語で、縦書きに対応しないこと。問い合わせは英語の文書でのみ使えること。対応する形式が JPEG・PNG・PDF・TIFF で XFA 形式の PDF に対応しないこと。同期の処理は PDF が1ページまで、非同期の処理は PDF が500MB・3,000ページまでであること。PDF はパスワードで保護されていてはいけないこと。文字の高さの下限が15ピクセル(150DPIで8ポイント)であること。問い合わせが非同期で1ページ30件までであること | AWS: Set Quotas in Amazon Textract | 2026-10-13 |
StartDocumentAnalysis が S3 の文書を非同期で分析し、FeatureTypes に TABLES・FORMS・QUERIES・SIGNATURES・LAYOUT を指定できること。完了の状態を Amazon SNS に通知すること。JobId が7日間だけ有効なこと。OutputConfig で出力先の S3 を指定でき、既定ではサービスの側に結果が保存されること | AWS: StartDocumentAnalysis | 2026-10-13 |
GetDocumentAnalysis の JobStatus が IN_PROGRESS・SUCCEEDED・FAILED・PARTIAL_SUCCESS であること。MaxResults の上限が1,000で、残りは NextToken で取得すること。Warnings と QUERY_RESULT ブロック(信頼度付き)を返すこと | AWS: GetDocumentAnalysis | 2026-10-13 |
表が TABLE・CELL・MERGED_CELL ブロックで返り、セルに行と列の位置が付くこと。セルの種類として COLUMN_HEADER・TABLE_SUMMARY・TABLE_TITLE・TABLE_FOOTER などがあること。表の種類として STRUCTURED_TABLE と SEMI_STRUCTURED_TABLE があること | AWS: Tables | 2026-10-13 |
Claude API の構造化出力が output_config.format に type: "json_schema" を指定して使えること。オブジェクトには additionalProperties: false が必要で、数値や文字数の制約が使えないこと。Amazon Bedrock では一部の統合でのみ提供されていること | Claude: Structured outputs | 2026-10-13 |
手数料を払うかどうか、契約をどう解釈するかは、旅行会社との契約を担当する部署と経理で決めてください。 本記事は公式ドキュメントで確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1341)についてのご相談はこちらから。
