RENOY
生成AI・OCR

生成AIのJSON出力が安定しないときの対策|OCR本番運用の二重防御

目次

「AIで請求書を読み取って、データを自動で取り込みたい」——帳票OCRのご相談は年々増えています。生成AIの読み取り精度は実務で使える水準になり、フォーマットがバラバラな紙の書類でも、かなりの精度でデータ化できるようになりました。

ただ、実際に本番運用へ乗せてみると、精度とは別の壁にぶつかります。同じPDFを処理させても、成功したり失敗したりするのです。読み取った中身は合っているのに、出力の"形"が回によって揺れる。ここを設計に織り込まないと、月に何度か原因不明の停止に悩まされることになります。

この記事では、帳票OCRの本番運用で私たちが確立した「出力は揺れる前提」の信頼性設計を紹介します。

なぜ「たまに壊れる」のか

生成AIに「JSON形式で出力して」と指定しても、返ってくる形は毎回まったく同じにはなりません。実際の運用で確認した揺れは、たとえば次のようなものです。

  • 単一オブジェクトで返る回と、配列で返る回がある(1件でも配列、複数でも単一、が混ざる)
  • コードブロック(```)付きで返る回がある
  • カンマ抜けなど、構文が壊れたJSONが返る回がある

やっかいなのは、これらが確率的に起きることです。10回中9回は正しくても、10回目に壊れる。開発中のテストでは通っても、本番で件数が増えると必ず顔を出します。

APIには出力形式を指定する仕組み(response_mime_type など)もありますが、それを使っても稀に壊れることがあります。仕様は変わるため最新は公式で確認いただきたいのですが、いずれにせよ「指定すれば100%整う」とは考えない方が安全です。

大事な前提:これはAIの精度が低いという話ではありません。モデルの出力は本質的に揺れるもので、プロンプトの改善だけで100%に固めようとすると、いつまでも詰め切れません。

対策の考え方:一箇所で守らない

揺れる出力を業務システムで安全に扱うには、複数の層でそれぞれ守るのが基本です。プロンプトだけ、パーサだけ、で完璧を目指さず、少しずつ受け止める設計にします。

順番に見ていきます。

① プロンプト側:例示つきで形式を強く指定する

まず入口で、出力してほしい形を具体例つきで明示します。「JSONで返して」だけでなく、「配列で、各要素はこのキーを持つ」と実例を見せる。これで揺れの発生率そのものを下げられます。

ただし、ここで100%を狙わないことが肝心です。プロンプトは発生確率を下げるための層であって、壊れないことを保証する層ではない、と割り切ります。

② パーサ側:揺れを自動で吸収する

次に、受け取ったデータを解釈する側(パーサ)に、想定できる揺れへの受け皿を用意します。

  • 配列で来ても単一で来ても扱えるようにする(配列を検出したら自動でアンラップする、など)
  • コードブロックのフェンス(```)が付いていたら除去してから解釈する

これは「AIに正しく返させる」のではなく、「多少崩れて返ってきても、こちらで整える」という発想です。①で漏れた揺れの多くは、この②で吸収できます。

揺れの種類受け止める層
単一/配列の揺れパーサで自動アンラップ
コードブロック付きパーサでフェンス除去
構文が壊れている自動リトライ(③)

③ 構文が壊れていたときだけ、1回だけ自動リトライ

②でも整えきれない、つまりJSONの構文そのものが壊れていた場合に限り、もう一度だけ処理を実行します。ここには2つの勘所があります。

ひとつは、低temperature(出力のばらつきを抑えた設定)でも、再実行すれば別の出力が得られるという性質を使う点です。設定上は「ほぼ同じ答えを返す」はずでも、実際には再実行で正しい形に整うことが多い。だから「もう一度やる」が有効なのです。

もうひとつは、APIのエラーと、出力が壊れているエラーを区別する点です。通信障害やレート制限のようなAPIエラーは即失敗として扱い、無駄にリトライしません。リトライするのは「AIは応答したが中身の形が壊れていた」ときだけ。ここを混ぜると、障害時にリトライを繰り返してかえって不安定になります。

そして、リトライは1回までに留めます。何度も試すと、処理は遅くなり、料金もかさみ、それでも直らないときは結局失敗するからです。

④ 失敗したら、生レスポンス全文をログに残す

それでも失敗したケースは、必ず出ます。このとき決定的に効くのが、AIが返した生のレスポンスを全文ログに保存することです。

これがないと、本番で「なぜか1件だけ取り込めなかった」となったとき、何が返ってきたのか分からず、再現もできません。原因調査に半日かける、といったことが起こります。逆に生レスポンスを残しておけば、「ああ、この回はカンマが抜けていたのか」とその場で原因が分かる。調査が半日から即時に変わります。

運用の勘所:AIを組み込んだ仕組みの信頼性は、「壊れないこと」より「壊れたときに何が起きたか分かること」で決まります。ログ設計は後回しにしないでください。

まとめると:二重防御の全体像

ここまでを一枚に整理すると、こうなります。

プロンプトで確率を下げ、パーサで揺れを吸収し、壊れたら1回だけ再実行し、それでもダメなら記録して安全に止める。どこか1箇所で100%を狙わず、層で受け止める——これが本番で止まらない作り方です。

この設計から言える、中小企業向けの教訓

帳票OCRに限らず、生成AIを業務システムに組み込むときの原則として、次の3つが言えます。

  • 「モデルの出力は揺れる」を設計の前提に置く。安定して見えても、件数が増えれば必ず揺れが出る
  • プロンプトの改善だけで100%にしようとしない。プロンプトは確率を下げる層、パーサとリトライは受け止める層、と役割を分ける
  • 失敗時のログを最初から設計に入れる。原因が即時に分かる状態を作っておくと、運用の負担が桁違いに軽くなる

見た目のデモは、プロンプトだけでも動きます。しかし毎日回る業務に乗せるなら、揺れを前提にした二重防御があるかどうかで、運用のしんどさがまったく変わります。

まとめ

  • 生成AIは、JSON形式を指定しても同じ入力で成功/失敗が確率的に起きる(単一/配列の揺れ、コードブロック付き、構文の破損など)
  • 対策は二重防御:①プロンプトで形式を強く指定 ②パーサで揺れを吸収 ③壊れたときだけ1回リトライ(APIエラーとは区別)④失敗時は生レスポンスを全文ログ保存
  • 教訓は「出力は揺れる前提で作る」。プロンプト改善だけで100%を目指さない
  • なお各APIの形式指定などの仕様は変わるため、最新は公式で確認してください

RENOYでは、帳票OCRや生成AIを使った業務自動化を、本番で止まらない信頼性設計まで含めて承っています。「AIで読み取る仕組みは作ったが、たまに落ちて困っている」「これから安全に組み込みたい」という段階のご相談も歓迎です。まずはお気軽に無料個別相談(オンライン・60分)をご利用ください。サービス内容をまとめた資料は資料請求からご覧いただけます。

#生成AI#OCR#帳票#業務自動化#中小企業