ストーリー
コンテキストウィンドウの構造
[コンテキストウィンドウ]
┌─────────────────────────────┐
│ システムプロンプト │ ← 固定(ペルソナ・制約・指示)
├─────────────────────────────┤
│ 参照データ(RAG等) │ ← 動的(検索結果、ドキュメント)
├─────────────────────────────┤
│ 会話履歴 │ ← 蓄積(過去のやり取り)
├─────────────────────────────┤
│ ユーザーの現在の入力 │ ← 動的(最新のメッセージ)
├─────────────────────────────┤
│ 生成用の余白 │ ← 出力用に確保
└─────────────────────────────┘
トークン配分の目安
| 要素 | 推奨割合 | 128Kモデルでの目安 |
|---|---|---|
| システムプロンプト | 5-10% | 6K-13Kトークン |
| 参照データ | 20-40% | 26K-51Kトークン |
| 会話履歴 | 20-30% | 26K-38Kトークン |
| ユーザー入力 | 5-10% | 6K-13Kトークン |
| 生成余白 | 20-30% | 26K-38Kトークン |
情報の優先順位
コンテキストに入れる情報には明確な優先順位をつける。
優先度マトリクス
| 優先度 | 情報タイプ | 例 |
|---|---|---|
| 必須 | システムプロンプト(ペルソナ・制約) | 役割定義、禁止事項 |
| 高 | 直近の会話(最新2-3ターン) | ユーザーの直前の質問と回答 |
| 高 | タスクに直接関連する参照データ | 対象商品の情報 |
| 中 | 過去の会話の要約 | 「顧客はPC購入を検討中」 |
| 低 | 古い会話の詳細 | 3ターン以上前の全文 |
| 低 | 間接的に関連する参照データ | 関連商品の情報 |
圧縮戦略
戦略1: 会話履歴の要約
長い会話履歴をそのまま保持するのではなく、要約して圧縮する。
会話管理ルール:
- 直近3ターンの会話はそのまま保持
- 4ターン以上前の会話は要約して保持
- 要約形式: 「[要約] ユーザーは〇〇について質問。△△と回答済み。」
例:
[要約] ユーザーはノートPCの購入を検討中。予算は15万円。
用途はプログラミングとWeb開発。メモリ16GB以上を希望。
3機種を提案し、MacBook Airに興味を示している。
User: バッテリーの持ちはどのくらいですか?
Assistant: MacBook Air M3のバッテリーは...
User: 保証はつきますか?
戦略2: 参照データの選択的注入
全てのデータを入れるのではなく、関連性の高いデータのみを注入する。
RAG(Retrieval-Augmented Generation)の流れ:
1. ユーザーの質問を分析
2. 関連するドキュメントを検索(ベクトル検索)
3. 上位3-5件のみをコンテキストに注入
4. LLMが参照データを元に回答
コンテキスト注入テンプレート:
---
以下の参照情報に基づいて回答してください。
参照情報にない内容は「情報がありません」と回答してください。
[参照情報]
{検索結果の上位3件}
[ユーザーの質問]
{質問}
---
戦略3: システムプロンプトの最適化
システムプロンプトの冗長な部分を削減する。
# 冗長な例(200トークン)
あなたはNetShop社で働くカスタマーサポートのスタッフです。
お客様に対して丁寧に対応してください。
お客様の質問に対して、正確な情報を提供してください。
分からないことは分からないと正直に伝えてください。
お客様を怒らせないように注意してください。
# 圧縮版(80トークン)
あなたはNetShop社のサポートスタッフです。
ルール: 丁寧語使用 / 正確な情報のみ回答 / 不明点は「確認します」と応答
動的コンテキスト管理
スライディングウィンドウ方式
interface ConversationManager {
systemPrompt: string; // 固定
summary: string; // 圧縮された過去の会話
recentMessages: Message[]; // 直近N件の会話
contextData: string; // 参照データ
}
function manageContext(manager: ConversationManager, maxTokens: number): string {
const systemTokens = countTokens(manager.systemPrompt);
const outputReserve = maxTokens * 0.25; // 出力用25%確保
const available = maxTokens - systemTokens - outputReserve;
// 優先順位順にコンテキストを構築
let context = manager.systemPrompt;
let remaining = available;
// 1. 直近の会話(必須)
const recentText = formatMessages(manager.recentMessages.slice(-3));
remaining -= countTokens(recentText);
// 2. 参照データ(重要)
if (remaining > 0) {
const contextText = truncate(manager.contextData, remaining * 0.6);
remaining -= countTokens(contextText);
context += contextText;
}
// 3. 要約(余裕があれば)
if (remaining > 0) {
context += truncate(manager.summary, remaining);
}
context += recentText;
return context;
}
コンテキストウィンドウの落とし穴
| 落とし穴 | 説明 | 対策 |
|---|---|---|
| 中間部分の情報喪失 | LLMは先頭と末尾の情報を重視し、中間部分を軽視する傾向がある | 重要な情報を先頭か末尾に配置 |
| 不要な情報のノイズ | 無関係な情報が混入すると精度が低下 | 関連性フィルタリングを実施 |
| トークン超過 | 上限を超えるとエラーまたは切り捨て | 事前にトークン数を計算 |
情報配置の最適化
[先頭] システムプロンプト(最重要の制約) ← 常に読まれる
[中間] 参照データ、過去の会話要約 ← 重要度が下がる
[末尾] 直近の会話、ユーザーの質問 ← 常に読まれる
まとめ
| 項目 | ポイント |
|---|---|
| コンテキスト構造 | システムプロンプト/参照データ/会話履歴/入力/生成余白 |
| 優先順位 | 必須→高→中→低で情報をトリアージ |
| 圧縮戦略 | 会話要約、選択的注入、プロンプト最適化 |
| 配置 | 重要情報は先頭か末尾に配置(中間は注意) |
チェックリスト
- コンテキストウィンドウの構造とトークン配分を理解した
- 情報の優先順位マトリクスを設計できる
- 3つの圧縮戦略を実践できる
- 動的コンテキスト管理の仕組みを把握した
- 情報配置の最適化(先頭・末尾の重要性)を理解した
次のステップへ
次は「システムプロンプトパターン集」として、業務別の具体的なシステムプロンプトの型を学ぼう。
推定読了時間: 30分