問題の核心:なぜモデルはドリフトするのか

プロンプト:LLMをドリフトさせないプロンプト設計:コミュニティが語る実践的文脈管理の手法(記事内画像)

長いセッションでLLMが指示を「忘れる」現象——いわゆるコンテキストドリフト——は、モデルのアーキテクチャ上の制約と、プロンプト設計の甘さが重なって起きる。コンテキストウィンドウの後半になるほど、冒頭のシステムプロンプトの影響力は希薄化する傾向があると考えられる。これは一般的なTransformerのアテンション機構の特性から推測される挙動だ。

Sourceのスレッドでは、投稿者が「通常のプロンプトインタラクション、詳細の深さ、システムプロンプトの使用有無、エージェントタスクの処理方法」を網羅したデータを求めている。つまり現場では、体系的なデータが不足しているという認識がある。

ナイーブなプロンプトと改善版:SaaS認証機能を例に

投稿者が具体例として挙げたのが「SaaSプロジェクトに認証機能を追加する」というタスクだ。これを題材に、ドリフトを起こしやすい設計と、起こしにくい設計を比較する。

失敗例(ナイーブなプロンプト)

SaaSアプリにJWT認証を追加してください。

この1行は情報密度がゼロに等しい。モデルはスタック、既存コードの文脈、セキュリティ要件を何も知らない状態で生成を始める。結果として出力はジェネリックなボイラープレートになり、後続の修正指示を重ねるたびにモデルは「最初に何を作ろうとしていたか」を失っていく。

改善版(構造化プロンプト)

SYSTEM あなたはシニアバックエンドエンジニアだ。 以下の制約を会話全体で維持すること: - スタック: Node.js / Express / PostgreSQL - 認証方式: JWT(アクセストークン15分、リフレッシュトークン7日) - セキュリティ基準: OWASP Top 10準拠 - コードスタイル: ESLint Airbnb準拠

GOAL SaaSプロジェクトに認証機能を追加する。

PHASE 1 / PLAN 実装前に以下を列挙せよ: 1. 必要なファイル一覧 2. 依存パッケージ 3. DBスキーマ変更点 承認後にコードを生成すること。

構造の違いを分解する。`## SYSTEM`ブロックは「会話全体で維持すること」という明示的な持続命令を含む。これがアンカーになる。`## GOAL`は単一の目標を1行で固定する。`## PHASE 1 / PLAN`は即座のコード生成を禁止し、計画フェーズを強制する。計画を先に出力させることで、モデルは後続のコード生成フェーズでも計画との整合性を保とうとする傾向がある——これはモデルの自己一貫性バイアスを利用した設計だ。

カスケードプロンプトと文脈の固定

投稿者が言及している「カスケードプロンプト」「プランニング」「ゴール設定」は、いずれも同じ問題への異なるアプローチだ。長いタスクを単一の巨大プロンプトで処理しようとすると、コンテキストウィンドウの圧迫とドリフトが同時に発生する。

実務的な対策として一般に知られているのは以下の構造だ。

フェーズ分割型カスケード

PHASE 2 / IMPLEMENT 前フェーズで承認した計画に従い、以下のファイルを生成せよ: - middleware/auth.js - routes/auth.js - models/refreshToken.js

制約(再掲):
- JWT secret は process.env.JWT_SECRET から取得
- パスワードハッシュは bcrypt rounds=12
- エラーレスポンスは { error: string, code: string } 形式

`制約(再掲)`という節が重要だ。システムプロンプトの制約を各フェーズの冒頭で圧縮して再提示することで、コンテキストの後半でも制約の影響力を維持できる可能性がある。これは「アンカーリフレッシュ」と呼べる手法だ。

デバッグや差分適用(diff)、リファクタリングの場面でも同じ原則が適用できる。

デバッグ用プロンプト

CONTEXT スタック: Node.js / Express / PostgreSQL(変更なし) 問題: POST /auth/refresh が 401 を返す

INPUT [エラーログをここに貼る] [該当コードをここに貼る]

TASK 1. 原因を特定せよ 2. 修正コードを差分形式(unified diff)で出力せよ 3. 修正理由を1行で説明せよ

タスクを番号付きリストで明示することで、モデルの出力構造が固定される。構造が固定されると、後続のプロンプトで「2の修正コードを適用した場合のテストを書け」という参照が機能しやすくなる。

結論:職人の視点

ソースのスレッドが示しているのは、現場のエンジニアが体系的なデータを渇望しているという事実だ。「なんとなく動いている」プロンプトから「再現性のある」プロンプトへの移行は、設計の問題だ。

筆者が重要だと考えるのは3点だ。第一に、制約はシステムプロンプトに1回書けば終わりではなく、各フェーズで圧縮再提示する。第二に、即座の生成を禁止し計画フェーズを挟む。第三に、タスクを番号付きリストで構造化し、モデルの出力形式を固定する。

これらは特定のモデルに依存しない原則だ。ローカルLLMでも、APIモデルでも適用できる。再現したい読者は、まず手元の「SaaS認証追加」タスクで上記の改善版プロンプトをそのまま試してほしい。計画フェーズを挟むだけで、後続のドリフトが体感できるほど減少する可能性がある。