SPACE GLEAM

AIの出力は揺れる前提で作る。自社SaaSで実装している4つの備え

「先週まで正しく分類できていた問い合わせが、急に見当違いの回答を返すようになった」「プロンプトも入力データも変えていないのに、出力のフォーマットが崩れた」。こうした現象の背景には、モデルの世代交代だけでなく、LLMの出力が本来持っている揺れそのものもあります。本記事では、自社で運営するSaaSの実装をもとに、AIシステムをこうした揺れに強くするための防御的な工夫を紹介します。

生成AIを組み込んだシステムには、従来のソフトウェアにはなかった特有の「経年変化」があります。コードを一切変更していなくても、裏側で呼び出しているAIモデルが提供元によってアップデートされることで、出力の傾向や精度、フォーマットが変わる可能性があります。

私たちは契約書比較SaaS「DIFFsense」や、写真から食材を判定する「御御御付(おみおつけ)」を自社で運営しており、いずれもGeminiやGPTのAPIから返ってくるテキストをJSONとして扱う処理を実装しています。この記事では、「モデルアップデートで実際にこう壊れた」という事故報告ではなく、そもそもLLMの出力は本来ゆらぎがあるという前提のもと、私たちが実装の中で講じている防御的な工夫を、実際のコードに基づいて紹介します。

なぜモデルアップデートでシステムが「壊れる」おそれがあるのか

OpenAIやGoogle、Anthropicなどのモデル提供元は、性能改善や安全性向上のために継続的にモデルを更新しています。特に「latest」や無指定のエイリアスでモデルを呼び出している場合、開発者が意識しないうちに裏側のモデルが切り替わることがあります。

1. 出力フォーマットの揺れ

JSON出力を期待していても、モデルが余分な説明文を前後に付け足したり、キー名の付け方が期待と異なったりすることがあります。これはモデルのバージョンが変わった瞬間だけに起きるとは限らず、同じバージョンでも出力の揺れとして日常的に起こり得るものです。厳密なパース処理を組んでいるシステムほど、この揺れの影響を受けやすくなります。

2. 判断基準・トーンのドリフト

分類や要約、承認判定のようなタスクでは、モデルの世代が変わることで判断の傾向がわずかにずれる可能性があります。個々の変化は小さくても、大量の処理を積み重ねると、業務全体の精度やユーザー体験に影響しうるため、継続的な確認が必要です。

3. 廃止(Deprecation)による停止

影響が大きいのが、利用していたモデルバージョンそのものが提供終了になるケースです。事前の告知期間はあるものの、それに気づかず対応が遅れると、ある日を境にAPIがエラーを返し続けるという事態になりえます。

3つの変化と、その気づきやすさ 変化の種類 現場での現れ方 気づきやすさ 判断のドリフト 結果が少しずつずれていく 低い ─ 放置されやすい 出力フォーマットの揺れ パース失敗として表面化 中 ─ エラーログに残る モデルの提供終了 機能が全面的に停止 高い ─ 即座に検知できる
提供終了はすぐ気づけるが、判断のドリフトは表面化しないまま進む。対策の優先順位は、この「気づきにくさ」を軸に考える。

私たちが実装で講じている防御的な工夫

これらのリスクをゼロにすることはできませんが、実装の作り方次第で影響を小さくすることはできます。DIFFsenseと御御御付で実際に採用している工夫を、そのまま紹介します。

工夫①:モデルはバージョンを明記して固定する

「latest」のような自動追従のエイリアスは、本番環境では挙動が予測しづらくなる原因になります。DIFFsenseのバックエンドでは、呼び出し先のモデルをバージョンまで明記した状態でエンドポイントに直接指定しており、コード上にも「速く、信頼性が高いためこのモデルを使っている」という選定理由をコメントとして残しています。この一行があるだけで、モデルの切り替えは常にコードレビューを通る「意図した変更」になり、知らないうちに挙動が変わるという事態を防げます。

工夫②:出力のキー名は複数パターンを許容しておく

DIFFsenseの契約書解析処理では、AIからの応答に含まれる変更点の配列を取り出す際、changes だけでなく suggestionsmaterialChanges など複数のキー名のいずれかがあれば拾えるようにしています。これは「モデルアップデートでキー名がこう変わった」という観測結果に基づくものというより、プロンプトへの厳密な準拠を無条件に信頼しない、という前提での保険的な実装です。1つのキー名だけを信じる作りにしないことで、モデル側の細かな出力の揺れに振り回されにくくなります。

複数のキー名を1つの内部構造に正規化する AIが返しうるキー名 後続の処理 changes suggestions materialChanges 正規化 存在するものを1つ採用 統一形式 揺れを意識しない
入口で複数パターンを吸収しておけば、後続の処理はキー名の揺れを意識せずに書ける。

工夫③:JSONパースは複数の手段を順に試す

DIFFsenseのJSON抽出処理では、Markdownのコードフェンス(```json ... ```)を取り除いたうえで、まずそのままJSON.parseを試し、失敗したらスマートクォートや末尾カンマなどの軽微な崩れを正規化してから再度パースし、それでも失敗したら正規表現で必要なフィールドだけを抜き出す、という具合に複数の手段を順番に試す作りになっています。御御御付では食材認識という用途の特性上、コードフェンスを外してからパースするシンプルな構成を採用しており、サービスの性質や要求される精度に応じて防御の厚みを変えるようにしています。

JSONパースを多段階で立て直す流れ AIからの生レスポンス コードフェンスを除去してから開始 STEP 1 そのままパース 大半はここで成功する STEP 2 正規化して再試行 表記ゆれを吸収する STEP 3 正規表現で抽出 必要な項目だけ拾う 破線=前段が失敗したときだけ進む 構造化データとして取得
DIFFsenseのJSON抽出処理。どのSTEPで成功しても後続の処理は同じ形で受け取れる。

工夫④:モデル名を外出しし、フォールバックとキルスイッチを持つ

御御御付の画像解析処理では、利用するモデル名を環境変数で指定できるようにしてあり、コードのデプロイを伴わずに切り替えられます。また、モデルが混雑時のエラー(503など)を返した場合には、同じモデルへ少し時間を空けて再試行し、それでも失敗すれば同系統の別グレードのモデルへ自動的に切り替える仕組みも実装しています。加えて、開発者が意図的に外部AI呼び出しそのものを止めたい場合には、環境変数を1つ切り替えるだけでダミーの結果を返す動作に切り替えられるようにもしています。AIの挙動不良は自動判定が難しい場面も多いため、最終的な判断と切り替えを人がすぐ行えるようにしておくことを重視しています。

再試行・フォールバック・キルスイッチの関係 自動で処理される範囲 通常の呼び出し 指定したモデル 失敗 時間を空けて再試行 同じモデルのまま 失敗 別グレードへ切替 自動フォールバック 人が判断して切り替える範囲 モデル名の差し替え 環境変数を書き換えるだけ コードのデプロイは不要 キルスイッチ 外部AIの呼び出しを止める 固定の応答を返して様子を見る
一時的な混雑は自動で吸収し、判断が必要な事象は人がすぐ切り替えられる状態にしておく。

「作って終わり」にしないための体制

AIシステムは一度作って納品したら完成、というものではありません。モデル提供元のアップデート情報を継続的に把握し、影響がありそうであれば実際の挙動を確認し、必要に応じて実装を調整するという運用サイクルを、誰かが継続的に担う必要があります。

この役割を発注側だけで担うのが難しい場合は、開発を依頼する段階で「リリース後のモデル追従・監視をどう行うか」を提案に含められる開発会社を選ぶことが、長期的な安定運用につながります。

SPACE GLEAMのAIシステム提案

私たちSPACE GLEAMは、DIFFsenseや御御御付といった自社SaaSを実際に運営しながら、こうした防御的な実装を日常的に行っています。その実践知をもとに、開発だけでなく運用のしやすさまで見据えたAIシステムをご提案します。

「導入後の運用が不安」「今動いているAIシステムの安定性を見直したい」という場合も、お気軽にお問い合わせください。

AIシステム開発のご相談はこちら

新規開発だけでなく、既存のAIシステムの運用・保守体制の見直しもご相談いただけます。

問い合わせる
一覧に戻る