LLM出力の非決定性とどう付き合うか——「予算30」はいくらか
LLMは同じ入力を渡しても、実行のたびに微妙に、時には大きく異なる出力を返します。チャットで使っている分には「今回はちょっと違う言い回しだったな」程度で済みますが、これを業務システムに組み込むと話が変わります。出力のわずかなブレが、金額や数量の取り違えという実害につながることがあるからです。
「予算30」問題
業務システムの開発現場でよく直面するのが、日本語の数値表現の曖昧さです。例えば、見積依頼の自由記述欄に「予算30くらいで」と書かれていたとします。人間であれば、文脈(商材の単価帯、過去のやり取り、業界の相場感)から「30万円」だろうと自然に補完できますが、これをそのままLLMに渡して金額として抽出させると、次のようにいくつもの解釈が成立してしまいます。
- 30円
- 30万円
- 30億円
- 30M(海外では30,000,000を「30M」と表記することがあり、学習データに含まれる英語圏の表記慣習をモデルが適用してしまう解釈)
同じプロンプト・同じモデルであっても、周辺の文脈(直前にどんな金額の話をしていたか、他の項目にどんな数値が並んでいるか)によって、どの解釈を選ぶかがぶれることがあります。実際にこの手の曖昧な入力を含むデータを集計処理に流すと、一部のレコードだけ金額が3桁ずれて合計値がおかしくなる、見積書のテンプレートに転記された金額が実態と乖離する、といった形で表面化します。厄介なのは、こうした誤りがログ上ではエラーにならず「正常に処理が終わった、しかし中身が間違っている」状態になる点です。数量や日付でも同様のことが起こります。「来月末まで」が何日を指すか、「10個口」が個数なのかケース数なのかは、いずれも人間の常識的な補完に頼った曖昧な表現であり、LLMがどちらに倒すかは実行のたびにぶれ得ます。
なぜ非決定的になるのか
LLMの出力は確率分布に基づくサンプリングで生成されるため、同じ入力でも毎回まったく同じトークン列が選ばれるとは限りません。温度(temperature)パラメータを0に近づけることで再現性はある程度上がりますが、モデル内部の計算順序やインフラ側の要因もあり、温度0であっても完全な決定性が保証されるわけではありません。「非決定性はモデルのバグではなく、生成モデルという仕組みそのものの特性である」という前提に立って設計する必要があります。
対策1:入力の曖昧さを事前に減らす
一番効果が大きいのは、そもそも曖昧な自由文をLLMに渡す前に、UI側で曖昧さを減らしておくことです。金額であれば「円・万円・億円」の単位を選択式にする、数量であれば単位(個・ケース・箱)をドロップダウンで別項目にする、といった形で、自由記述に頼らなくてよい部分は選択式のフォームに寄せます。自由記述をLLMで解釈しなければならない場面自体を減らすのが、最も確実な対策です。
対策2:プロンプト側で解釈のルールを明示する
自由記述の解釈をLLMに任せざるを得ない場合は、プロンプト設計の基本で触れたように、曖昧なケースの扱い方までプロンプトに明示します。
const system = `金額を抽出する際は、次のルールに従ってください。
- 数値のみで単位が明記されていない場合、金額として断定せず null を返す
- 「万」「億」などの単位が明記されている場合のみ、それに従って円換算する
- 曖昧で判断できない場合は amount_yen を null にし、needs_confirmation を true にする
出力形式: { "amount_yen": number | null, "needs_confirmation": boolean }
`;このように「わからないときは確信を持って断定せず、確認フラグを立てる」という逃げ道をプロンプト側に用意しておくと、誤った断定よりはるかに安全です。曖昧さをモデルに無理やり解決させようとするより、「曖昧である」という判定自体をモデルにさせる方が、実務上のリスクは小さくなります。
対策3:重要フィールドは人間の確認を必須にする
金額・数量・納期のように、間違えた場合の影響が大きいフィールドについては、LLMの抽出結果を確定値として扱わず、必ず人間が確認するステップを挟みます。MCPサーバーの記事でも触れたように、一定の金額を超える場合やneeds_confirmationが立った場合は、自動処理を止めて人の確認を挟む、という閾値ベースの設計が現実的です。すべてを自動化しようとするのではなく、「自動化してよい範囲」と「人間の確認が必須な範囲」を最初に線引きしておくことが重要です。
対策4:ばらつきを定点観測する
同じ入力を複数回投げて出力のばらつきを確認する、曖昧な表現を含むケースを集めてテストセットとして定期的に流す、といった評価(evals)の仕組みを持っておくと、プロンプトや処理ロジックを変更した際に、非決定性がどの程度残っているかを継続的に把握できます。一度動作確認をして終わりにするのではなく、本番投入後もこうした定点観測を続けることで、想定外の解釈のブレを早期に発見できます。
非決定性はLLMの欠陥ではなく、下書き作成や要約のように多少の表現のゆらぎが許容される場面ではむしろ強みになる特性です。一方で、金額・数量・日付のように一意に定まるべき情報を扱う場面では、曖昧さをLLMに解決させるのではなく、入力の時点・プロンプトの時点・確認フローの時点で曖昧さを潰していく設計が欠かせません。