はじめに:ハルシネーションは「バグ」ではなく「設計の歪み」である
LLMアプリケーションの開発現場で「モデルが嘘をついた」という報告が上がったとき、多くのチームが最初に取る対応はプロンプトの文言を微調整することである。しかし、このアプローチは問題の構造を見誤っている可能性がある。存在しないAPI名を生成する、パラメータの型を勝手に変形する、利用可能なライブラリにない関数を呼び出す——これらの現象は、モデルの「能力不足」ではなく、トレーニングプロセスやプロンプト設計に起因する構造的な課題として捉える必要がある。
本記事では、プロンプト設計を「魔法」や「経験則の蓄積」ではなく、確固たる設計原則に基づくエンジニアリング課題として扱う。具体的には、ハルシネーションがなぜ起きるのかを対話理論とRLHFのメカニズムから解明し、それを是正するプロンプトパターンを実装レベルまで落とし込む。
読者には、単に「こう書けば直る」というTipsではなく、なぜその設計が必要なのかという理論的背景と、実装におけるトレードオフの判断基準を得てもらうことを目的とする。これにより、モデルのアップデートやユースケースの変更があったときにも、設計の妥当性を再評価できる判断力が身につく。
ハルシネーションの根本原因:RLHFによる「反射的応答」の誘導
現代のLLMがリクエストに対して即座にコード例や回答を提示する傾向は、偶然ではなく、RLHF(Reinforcement Learning from Human Feedback)プロセスにおける評価バイアスの直接的な結果であるという見方がある。
RLHFでは、人間のアノテーターがモデルの出力を比較評価し、そのフィードバックを報酬信号として学習に反映させる。GDEによる解説記事が指摘するように、この評価プロセスには明確な歪みがある。アノテーターは、即座に有用な出力(コード例や回答)を示すモデルを高く評価し、一方で「まず確認すべきです」と事実確認を求める回答を低く評価する傾向がある。つまり、「素直に答える」モデルが「慎重に答える」モデルよりも高評価を得るというインセンティブ構造が、学習データに反映されている可能性がある。
このバイアスが学習に反映されると、モデルの挙動は構造的に変わる。リクエストに対して反論や代替案を出す確率が低くなり、最初のトークンで即座に「はい、承知しました」と約束する反射的な応答(Reflexive Response)をすることが最適解となる場合がある。モデルは「このAPIは存在するか?」という検証ステップを挟まず、生成を開始してしまうことがある。
この「即座の正解提示」への最適化が、ハルシネーションを助長する要因となっている可能性がある。モデルは「答えること」自体が報酬になるため、存在しないAPIを推測で生成しても、それが「有用に見える出力」であれば報酬を得られる。検証を挟むコスト(トークンの消費、ユーザー体験の遅延)はペナルティとして学習されていない場合がある。結果として、モデルは「確信がなくても答える」ことを最適行動として学習してしまうことがあるのである。
ここで重要なのは、この問題がプロンプトの「文言」だけで解決できるかという点である。RLHFで形成された挙動は、モデルの内部表現に深く埋め込まれている。システムメッセージで「確認してください」と書いただけでは、学習された反射的な応答パターンを完全に上書きできない可能性がある。次のセクションで見るように、この問題はさらに歴史的な文脈まで遡る。
歴史的文脈:SHRDLUから現代までの「現実世界」の欠如
1971年に発表されたSHRDLUは、ブロックワールドと呼ばれる閉じた環境で指示を実行する自然言語理解システムとして知られる。このシステムが前提としていたのは、すべての指示が実行可能な環境であった。ブロックが何個あるか、テーブルのサイズがどれくらいか——それらはすべて既知であり、指示が実行不能になる状況は設計上存在しなかった。
GDEの解説記事が指摘するように、SHRDLU以降のAIシステムは、この「閉じた環境での指示実行」を前提として設計されてきた。現実世界の物理的制約、利用可能なAPIの欠如、リソースの不足——こうした「不可能な状況」に対応する仕組みが、長らく設計から欠落していたのである。
現代のLLMは、依然としてこのパターンを強く引きずっている。モデルが学習したタスクの多くは「入力を与えれば出力を返す」形式であり、「この要求は実行できません」と答えること自体が学習データにほとんど含まれていない。外部環境との健全なインタラクション——確認の要求、拒否、代替案の提示——は、モデルの出力空間の端に追いやられている。
この歴史的経緯を理解すると、プロンプト設計における「実行前の検証」の位置づけが明確になる。検証ステップは「おまけ」ではなく、SHRDLU以降失われていた「環境との対話」を再導入する行為である。次のセクションでは、この再導入を理論的に支える1986年の対話理論について詳しく見る。
解決策の理論的基盤:1986年の対話理論と自己帰納的文法トラップ
自己帰納的文法トラップとは
LLMがAPIを捏造する現象は、一見すると「モデルが覚えている知識が不十分だから」のように見える。しかし、この説明は根本的な誤りである可能性がある。GDEによる解説記事 で述べられているように、APIの捏造は記憶の欠損ではなく、1986年にFernando FloresとTerry Winogradが解明した自己帰納的文法トラップに起因する可能性がある。 この理論の核心は、言語行為が自己言及的に真偽判定される際に生じる論理的矛盾にある。具体的には、モデルが「このAPIを呼び出す」という出力を生成する瞬間、その出力自体が「このAPIは存在する」という主張になる。つまり、モデルは出力を生成する行為そのもので、出力の真偽を証明しようとしている。これは循環論法であり、外部の検証がない限り、この循環を断ち切る手段を持たない。 プロンプト設計の文脈で言えば、モデルに「このAPIを呼び出しなさい」と指示したとき、モデルは「呼び出す」という行為を即座に開始する。その過程で「本当に存在するか」を確認するステップが構造的に欠落している。これが自己帰納的トラップの実体であり、RLHFのバイアス(前節で見た反射的応答)と相まって、捏造を助長している可能性がある。Floresの「行動のための対話」理論
同じ1986年にFloresが提唱した「行動のための対話」理論は、このトラップを回避する正規の手順を定義している。GDEによる解説記事 に従えば、この理論では以下の手順が正規とされる:- リクエストを受信する
- 実行前に物理的現実を検証する(対象が存在するか、条件を満たしているか)
- 検証に合格した場合のみ実行する
- 検証に不合格な場合は、カウンターオファーや拒否を行う
プロンプト設計の原則:「検証」を最優先するシステムメッセージ
Guardian Roleの設計
上記の理論をプロンプトに適用する第一の原則は、モデルに対して「即座の実行者」ではなく「事前検証者(Guardian Role)」の役割を割り当てることである。システムメッセージの中で、モデルの最初のタスクを「リクエストの実行」ではなく「リクエストの実行可能性の判定」に置き換える。 具体的には、システムメッセージの先頭に以下の構造を置く:あなたはAPI呼び出しの検証者である。
ユーザーのリクエストを受け取ったら、以下の順序で処理せよ:
1. 指定されたAPIが利用可能か確認する
2. パラメータが仕様書に準拠しているか確認する
3. 上記のいずれかが不備であれば、実行せず、
不備の内容と代替手段を報告する
4. すべて合格した場合のみ、API呼び出しを生成する
この構造の設計判断の根拠は、自己帰納的トラップを断ち切るためである。モデルが「確認する」行為を最初に実行することで、出力が自己言及的な循環に陥る前に外部基準(利用可能なAPIリスト、パラメータ仕様)との照合が挿入される。
検証ステップのフロー
以下のフローは、リクエスト受信からAPI実行までの処理順序を示す。検証ステップを挟むことで、不合格のリクエストが実行フェーズに到達するのを構造的に防ぐ。
flowchart TD
A["リクエスト受信"] --> B{"指定APIが存在するか?"}
B -->|"Yes"| C{"パラメータが仕様準拠か?"}
B -->|"No"| D["拒否 / カウンターオファー"]
C -->|"Yes"| E["API呼び出しを生成"]
C -->|"No"| D
このフローで重要なのは、分岐の判定がモデルの内部的な「確信」ではなく、外部基準との照合に基づいて行われるべき点である。後述する実装パターン3(外部インデックス連携)でこの外部基準をどう供給するかを詳しく見るが、ここでは設計上の原則として「検証の基準はプロンプト内で明示的に定義する」ことを強調しておく。
トレードオフ:レイテンシーと精度
検証ステップの追加は、モデルが生成するトークン数と、場合によっては外部参照の往復回数を増やす。これはレイテンシーの増加に直結する可能性がある。しかし、ハルシネーションによる後続処理の失敗(存在しないAPIへの呼び出し、不正なパラメータによるエラー)が発生した場合の復旧コスト——手動修正、デプロイの巻き戻し、ユーザーへの影響——を考慮すると、このレイテンシー増は許容可能な投資であると考えられる。実装パターン1:カウンターオファーによる健全な拒否
「できません」だけではない拒否
検証ステップで不合格と判定された場合、最も単純な対応は「指定されたAPIは存在しません」と返すことである。しかし、この対応はFloresの理論における「拒否」の段階に留まり、「カウンターオファー」の段階に到達していない可能性がある。 カウンターオファーとは、不可能なリクエストに対して、代替の実行可能性のある提案を提示する行為である。GDEによる解説記事 で定義されるように、実行前に物理的現実を検証し、不可能な場合はカウンターオファーや拒否を行うことが正規の手順とされる。つまり、「できません」で終わらせず、「できませんが、代わりにこれならできます」という構造をプロンプト内で強制する。プロンプトへの組み込み方
システムメッセージに以下の指示を追加する:検証に不合格の場合、以下の形式で応答せよ:
- 不合格の理由(どのAPIが存在しないか、どのパラメータが不正か)
- 代替案:利用可能な類似API、または手動での対応手順
- 代替案が実行可能な場合、その呼び出しを具体的に提示する
「できません」だけで終わる応答は禁止する。
この指示の効果は、モデルの出力空間が「拒否」の1点に収束するのを防ぎ、「拒否 + 代替案」の2要素を含む出力を強制することにある。自己帰納的トラップの文脈で言えば、モデルが「呼び出せない」という出力を生成した瞬間、その出力自体が「代替手段を提示せよ」という次の言語行為を誘発する。つまり、カウンターオファーの指示は、トラップの循環を建設的な方向に転換する仕組みとして機能する可能性がある。
従来の拒否パターンとの比較
| パターン | 出力内容 | ユーザー体験 | 後続処理への影響 |
|---|---|---|---|
| 単純拒否 | 「指定APIは存在しません」 | 次の一手が不明、再試行が必要 | ユーザーが代替案を自力で探す |
| カウンターオファー | 「存在しません。代わりにX APIが同様の機能を持ちます」 | 代替案が即座に提示され、意思決定が早い | 代替APIへの切り替えが自動的に行える |
| ユースケース | 推奨される検証の厳格度 | 主な理由 |
|---|---|---|
| 自動実行パイプライン(コード生成・デプロイ) | 高(全パターン適用) | 失敗時の手動修正コストが極大。インデックス依存も許容 |
| 社内ナレッジ検索・要約 | 中(インデックス連携+スキーマ) | 誤情報の拡散リスクがあるが、人間が最終確認 |
| クリエイティブ支援・ brainstorming | 低(スキーマのみ or なし) | 捏造が「創造性」として許容される場面 |
重要な留意点として、厳格度を「高/中/低」で固定するのではなく、リクエスト単位で動的に切り替える設計も有効である。例えば、ユーザーが「実行せよ」と明示した場合は高厳格度、「アイデアを出して」と言った場合は低厳格度、とプロンプトの検証ブロックを条件分岐させる。これにより、柔軟性と堅牢性をユースケース全体で均一に設定する必要がなくなり、レイテンシーと信頼性のバランスをリクエスト粒度で最適化できる。
運用・発展:GDE視点からのプロンプト品質ガバナンス
プロンプトパターンを「一度書いて終わり」の資産として扱わないためには、組織内での品質ガバナンスの仕組みが不可欠である。ここで参考になるのが、Google Developer Experts(GDE)のような専門家ネットワークの運営思想である。GDEは、特定の技術に精通した独立した専門家が集まり、コミュニティへの貢献を通じて知識を共有・更新し続ける構造を持っている。この「個人が所有するのではなく、コミュニティが共同で保守する」という発想をプロンプト設計に持ち込むことで、属人的な知識の蓄積を組織的な資産に変換できる。
変更履歴とA/Bテストによるデータ駆動の改善
具体的には、プロンプトのバージョン管理をコードと同様に扱うことが第一歩である。システムメッセージの検証ブロックやカウンターオファーの指示文を、Gitなどのバージョン管理ツールに収め、変更の差分を追跡可能にする。これにより、「どの変更がハルシネーション率を下げたのか」を後から検証できる。
さらに、プロンプトバリエーション間の比較にはA/Bテストが有効である。例えば、「検証ステップを3段階にしたパターン」と「2段階にしたパターン」を、同じテストリクエストセットに対して実行し、出力の正確性とレイテンシーを定量的に比較する。テストリクエストには、意図的に存在しないAPI名を含むケースや、パラメータが妥当でないケースを含めることで、拒否・カウンターオファーの品質を評価できる。
モデル更新に伴う定期的な見直し
もう一つの重要な運用課題は、基盤モデルのアップデートである。RLHFによる評価バイアスはモデルごとに異なるため、前バージョンでは問題なかったプロンプトが、新しいモデルでは逆にハルシネーションを誘発する可能性がある。モデルのメジャーバージョン更新時には、前述のA/Bテストを再実行し、プロンプトの検証ステップを再調整するプロセスを定例化すべきである。これは「モデルが良くなったらプロンプトは不要になる」という誤解を避けるためにも重要で、モデルの能力向上とプロンプトの制約は相互に独立した変数として扱う必要がある。
まとめ:設計原則に基づいたプロンプトエンジニアリングへ
本記事では、LLMのハルシネーションを「モデルのバグ」としてではなく、RLHFの評価バイアスと自己帰納的文法トラップという構造的な歪みとして捉え直すことを目的とした。1971年のSHRDLU以降、AIは閉じた環境での指示実行を前提として設計されてきた歴史があり、現代のLLMも依然としてこのパターンを引きずっている。その結果、存在しないAPIを即座に「存在するもの」として出力する反射的な応答が、学習データに埋め込まれてしまっている。
この歪みを是正する手段として、FloresとWinogradが提唱した対話理論の概念をプロンプト設計に適用することを示した。実行前の検証、不可能時のカウンターオファー、BNF文法による出力空間の制限、外部インデックスとの連携による事実確認——これらはすべて、「モデルに答えを出させる」のではなく「モデルに正解を出せるか確認させる」という設計思想の具体化である。
最後に、実装において重要なのは、これらのパターンを「全部入れる」ことではなく、ユースケースの失敗コストに応じて検証の厳格度を設計判断することである。プロンプト設計は、モデルの能力を最大限に引き出すための最適化問題ではなく、モデルの既知の限界を明確に界定し、その境界内で安全に動作させるための防御的プログラミングである。この視点を持ち続けることが、LLMアプリケーションの信頼性を構造的に担保する一助となる。
関連記事
- AIの「記憶力」は本当に推論能力か:作業記憶の限界とLLMの真価
- LLMにSQLを渡すな:構造化ツールで誤答・インジェクションを防ぐ実装パターン
- Opus 5.5導入でコスト40%削減:推論特性を活かしたClaude Code実装ガイドライン
参考
本記事は海外の技術トレンド「If You Never Do Anything Else to Fix Your Prompts, Do This One Thing」(DEV)で話題のテーマをもとに、両儀システムソリューションズが独自に解説したものです。