第2章 確率的制御と決定論的制御 — なぜ「指示通り」にならないのか

2.1 すべての出力は確率的である

LLMの生成プロセスは、トークン(単語の断片)を一つずつ順番に生成していく仕組みだ。各ステップで「次にどのトークンを出すか」は確率分布からサンプリングして決まる。

これが意味するのは、プロンプトで「必ずXをしてからYをせよ」と書いても、モデルがその指示に従うかどうかは確率的だということだ。99%従うかもしれないが、100%ではない。

ここが多くのユーザーが戸惑うポイントになっている。

2.2 二つのメンタルモデルの罠

多くの人がLLMに持ち込むメンタルモデルは、大きく二つに分かれる。

「賢い同僚」モデル: 指示すれば理解して従ってくれるはず。従わないのは指示が曖昧だから。

このモデルの問題は、失敗の原因を常に「指示の質」に帰着させることだ。AIがルールを守らなかったとき、「指示が曖昧だったから」と解釈して、指示をさらに詳細にする。しかし、どれだけ指示を精緻にしても確率的に失敗するケースが残る。すると「まだ指示が足りない」とさらに追加する——終わりのない改善ループに入る。実際には、問題は指示の質ではなく、テキスト指示というメカニズム自体の原理的な限界にある。人間の同僚なら「理解した上で従う」が成り立つが、LLMは「確率的に影響を受ける」だけだ。

「プログラム」モデル: 正しいコマンドを与えれば確実に実行される。

このモデルの問題は、再現性を前提にしていることだ。同じ入力に同じ出力を期待するが、LLMは確率的にサンプリングするため、毎回異なる出力が出うる。「昨日はうまくいったプロンプトが今日は動かない」という体験をすると、「バグだ」「性能が劣化した」と感じるが、これはバグではなく正常な動作だ。プログラムなら f(x) = y が保証されるが、LLMでは f(x) ≈ y にしかならない。この「≈」の部分を受け入れられないと、ツールへの不信感が募る。

どちらも間違っている。 LLMは「指示を理解する確率的なシステム」であって、確実に従う同僚でも、決定論的に動くプログラムでもない。第三のメンタルモデルが必要だ——「確率的に影響を受けるが、100%の遵守は保証されないシステム」。このモデルを持てば、「いつ確率的制御で十分か、いつ決定論的制御が必要か」という設計判断ができるようになる。

2.3 ルール(確率的制御)の本質と限界

ユーザーがAIに与えるルールやプロンプト上の指示は、すべてコンテキストウィンドウにテキストとして入る。モデルの確率的生成プロセスに「影響を与える」ことはできるが、「強制する」ことはできない。

テキストベースの制御にも強弱のグラデーションがある:

レベル影響力
システムプロンプト最も強い確率的影響AI提供者が設定する基本指示
Rules / 設定ファイル強い確率的影響セッション開始時に自動読み込み
Skill内の指示中程度特定操作を呼び出した時のみ有効
会話中のユーザー指示文脈依存会話の流れの中で与える指示

なぜこの順番で影響力が異なるのか。理由はコンテキストウィンドウの中での「位置」と「持続性」にある。

システムプロンプトは、コンテキストウィンドウの最上部に配置される。モデルが出力を生成する際、最初に読まれるテキストであり、すべてのやり取りを通じて常に存在する。AI提供者(Anthropic、OpenAI等)がモデルの基本的な振る舞いを定義するために使っており、ユーザーが直接書き換えることはできない。影響力が最も強いのは、この「常に最初に読まれる」という位置的な優位性による。

Rules / 設定ファイルは、セッション開始時に自動的にコンテキストに読み込まれる。システムプロンプトと同様に「常に存在する」テキストだが、配置位置はシステムプロンプトの後になる。ユーザーが自分で書ける確率的制御の中では最も強い影響力を持つ。プロジェクト固有の行動規則——「このファイルを変更するな」「必ずこの手順で進めよ」——を定義するのに適している。

Skill内の指示は、ユーザーが /スキル名 で呼び出したとき、またはAIが自動的に選択したときにのみコンテキストに注入される。常に存在するわけではないため、RulesやCLAUDE.mdより影響力が限定的だ。ただし、呼び出された瞬間は「直近のコンテキスト」として比較的強い影響を持つ。

会話中のユーザー指示は、最も影響力が不安定だ。直後のターンでは強く影響するが、会話が長くなると他のテキストに埋もれ、注意が薄れる。「さっき言った指示を守ってくれない」という不満の多くは、この位置的な弱さに起因する。重要な指示を会話の途中で一度だけ伝えるのは、確率的制御の中でも最も脆い方法だ。

すべて確率的制御の枠内である。 グラデーションはあるが、最も強いシステムプロンプトでさえ100%の遵守は保証されない。確率を上げることはできるが、保証はできない——これがテキストベース制御の原理的な限界だ。

2.4 Hooks(決定論的制御)— 確率の外に出る

Hooksは、確率的な世界の外側にある決定論的なコード実行だ。

2.3節で述べた確率的制御が「モデルの内側」で作用するのに対し、Hooksは「モデルの外側」で作用する。この違いは程度の差ではなく、質的な差だ。

アナロジーで説明する。確率的制御は「交通ルールを看板に書いて掲示すること」にあたる。ドライバー(モデル)は看板を読み、多くの場合はルールに従うが、見落としたり、自分の判断で無視することがある。一方、決定論的制御は「物理的なバリケードを設置すること」にあたる。ドライバーがどう判断しようと、バリケードがあれば物理的に通れない。看板は「影響を与える」だけだが、バリケードは「強制する」。

処理の流れを比較する。

ルール(確率的制御)の場合:

プロンプトテキスト → モデルの注意機構 → 確率的生成 → 出力
(どの段階でもスキップされうる)

テキストで「git commitせよ」と書いても、モデルはそれを読んだ上で「最終目標に直接関係しない」と判断してスキップすることがある。これは不具合ではなく、確率的生成の正常な動作だ。

Hooks(決定論的制御)の場合:

モデルの出力が生成される
  → オーケストレーション層がイベントを検知
  → モデルの外側でスクリプトが実行される
  → 結果に応じてモデルの次の行動が制御される

この流れで重要なのは、モデルは第1ステップにしか関与していないことだ。イベント検知、スクリプト実行、結果判定——これらはすべて通常のプログラムとして動作する。if 文は100%正しく分岐する。git status は100%正確にファイルの状態を返す。ここに確率的な揺らぎはない。

もう一つの決定的な違いがある。確率的制御はモデルが「選択的に無視」できるが、Hooksはモデルに「無視する手段がない」。Rulesに「git commitせよ」と書いた場合、モデルはそのテキストを読んだ上で従わないことができる。しかし、Stop hookに「git commitされていなければ完了を拒否」と設定した場合、モデルがどう判断しようと、commitなしでは完了できない。モデルにとってHooksは「見えない壁」であり、回避する方法が存在しない。

この非対称性が、確率的制御と決定論的制御の本質的な差だ。

2.5 「完了」判断の構造

2.4節でHooksの強力さを述べたが、ここで重要な制約を理解しておく必要がある。Hooksは万能ではない。よくある誤解は「Hooksがあれば全部決定論的に制御できる」というものだが、実際にはそうではない。

確率的制御と決定論的制御は対立するものではなく、組み合わせて使うものだ。 その理由を「完了」判断の構造で説明する。

モデルが「タスク完了です」と出力するかどうかは、確率的な判断だ。あと3ステップ残っているのに「完了」と宣言してしまうことは起こりうる。逆に、すべて完了しているのに「まだ作業が残っている気がする」と不必要に作業を続けることもある。「いつ終わりとするか」の判断自体が、モデルの確率的な生成プロセスの中で行われるからだ。

Stop hookが保証しているのは、「誤って完了と判断した場合に差し戻すこと」 だ:

モデル: 「完了です」(確率的 — 正しいかもしれないし、間違っているかもしれない)
    ↓
Stop hook: 条件チェック(決定論的)
    ↓
  条件未達 → 「まだ終わっていません」とモデルに返す → モデルは作業を再開
  条件達成 → 終了を許可

つまり、「正しく完了させる」のではなく「間違った完了を阻止する」ゲートである。

この区別は重要だ。Stop hookは「progress.mdが更新されていない」「git commitされていない」のように、検証可能な条件をチェックできる。しかし、「この実装は仕様を正しく満たしているか」「このレポートの内容は妥当か」のような、意味的な判断はスクリプトにはできない。ファイルの存在や行数は検証できるが、内容の質は検証できない。

ここに確率的制御と決定論的制御の役割分担がある:

たとえば、「レポートにサマリーセクションを含めよ」というルールがある場合:Rulesに書くことでモデルは「なぜサマリーが必要か」を理解して適切な内容を書こうとする(確率的制御)。同時に、Stop hookで「## サマリー」という文字列の存在をチェックする(決定論的制御)。前者がなければモデルはサマリーの意義を理解せず形式的にしか書けないし、後者がなければそもそもサマリーを書き忘れる可能性がある。両方が必要なのだ。

実用上のポイント: 「Hooksで全部守ればいい」のではなく、「Rulesで意図を伝え、Hooksで最低条件を保証する」という二層構造で設計する。モデルが意味を理解した上で自由に判断する領域と、条件を確実にチェックする領域を分けることが、確率的システムを実用的に使うための設計原則だ。

2.6 制御の二重構造 — 核心

ここまでの内容を整理する。ただし、これはAIシステムの内部構造の説明ではない。ユーザーがAIを使うときに「どこに何を置くか」を設計するための指針だ。

AIシステムの内部構造(Transformerの動作、トークン生成の仕組み、Attention機構など)は、ユーザーが変更できない領域だ。一方、ここで述べる二重構造は、ユーザーが自分の手で設計し、配置し、調整できる制御の枠組みである。

確率的制御 ルール・プロンプト モデルの内側で作用 テキストとして注入 「影響を与える」 遵守率 < 100% スケール容易 自由度を活かせる 適する場面 ・意図の解釈 ・創造的生成 ・曖昧な指示の処理 ・探索的作業 決定論的制御 Hooks・コード実行 モデルの外側で作用 コードとして実行 「強制する」 遵守率 = 100% 設置コストあり 自由度を制限する 適する場面 ・手順遵守 ・状態検証 ・品質ゲート ・必須記録 「ここに何を置くか」が使いこなしの鍵

この図の最下部にある「ここに何を置くか」が最も重要な部分だ。これはシステムの仕様ではなく、ユーザーが行う設計判断を示している。

具体的には、ある制約やルールをAIに守らせたいとき、以下の問いに答えることで配置先が決まる:

この判断を「すべての制約に対して個別に行う」のが、AIを使いこなすための設計行為だ。多くの人は確率的制御しか使っていない(プロンプトやRulesだけで済ませている)。それで問題が起きないなら構わないが、「守ってくれないことがある」という不満があるなら、それは設計の問題であり、プロンプトの文言をいくら工夫しても解決しない。

実用上のポイント: 「プロンプトの書き方」で解決しようとする前に、その問題が確率的制御の限界に起因するものではないか考えてみよう。100%の遵守が必要なら、ツールの選択や仕組みの設計を変える必要がある。具体的な設計方法は第6章で述べ、第7章で実際に組み立てる。


C コラム:コンピューターの比喩とその限界

本章で述べた二重構造——確率的制御と決定論的制御——を理解した上で、一つ、広く出回っている比喩に触れておきたい。Andrej Karpathy(OpenAI共同創業者、Tesla元AIディレクター)が提唱した「LLM OS」比喩だ。LLM=CPU、コンテキストウィンドウ=RAM、ツール呼び出し=システムコール。AIシステムの構造を俯瞰する入門として直感的でわかりやすく、多くの記事や解説で使われている。

しかし、本章の議論を踏まえると、この比喩には重要なものが一つ抜けていることに気づく。コンピューターの世界には確率的な制御が存在しない。CPUに送った命令は100%実行される。OSの命令の意味がCPUによって変わることはない。if (x > 0) の分岐結果はCPUのメーカーに依存しない。しかし本章で見たように、LLMではテキストで書いた指示をモデルが確率的にスキップすることが起きる。同じ指示が異なるモデルで異なる機能を果たすことすらある(第9章で実証する)。

つまり、この比喩は「構造の説明」には使えるが、「制御の本質」の説明には使えない。コンピューターの世界ではすべてが決定論的に動くのが前提だから、「どの制御をどこに使うか」という設計判断がそもそも発生しない。AIシステムにはテキスト指示(確率的制御)とコード実行(決定論的制御)という性質の異なる二つの制御が混在しており、その配分を設計する必要がある——これが本章の核心だった。コンピューターの比喩では、この設計判断そのものが見えなくなる。

この限界を知っておくことには実用的な意味がある。「AIにプログラムのように命令すれば動くはず」という期待は、まさにコンピューターの比喩に引きずられた結果だ。2.2節で述べた「プログラム」モデルの罠がここにある。LLMは決定論的な機械ではなく、訓練傾向という「気性」を持つ確率的な存在だ。この性質に合った制御の設計——テキスト指示で意図を伝え、コードで最低条件を保証する二重構造——が必要であることは、コンピューターの比喩からは導かれない。比喩は入口であり、「ここから先は比喩では説明できない」という境界を知っておくことが、構造の理解を比喩に閉じ込めないための鍵になる。