こんにちは!NTTテクノクロスの吉田です。この記事は「NTTテクノクロス Advent Calendar 2025(シリーズ1)」の8日目の記事です。
はじめに:LLMガチャしてませんか?
ChatGPT / Claude / Gemini などの LLM を触っていると、こんな経験はないでしょうか。
- 適当にプロンプトを書いたら、なぜか神回答が返ってきた
- 別の日にほぼ同じことを聞いたら、ポンコツな回答が返ってきた
- 「何が違ったのか」が自分でもよく分からない
自分の中では、これを「LLMガチャ」と呼んでいます。
ただし、この「ガチャ」は本当にランダムというわけではありません。実は学習データの"平均的なパターン"に寄りやすいという性質があります。だからこそ、一般的な質問には「それっぽい回答」が返ってくるのですが、自分固有の要件や背景があると、その"平均"が合わなくて「外れ」に感じる—これが「LLMガチャ」の正体です。
近年は「プロンプトエンジニアリング」に関する情報も増えていますが、実務で LLM を安定運用していくうえでは、プロンプト単体よりも「周辺の文脈(コンテキスト)」の設計がかなり効いてきます。
最近の研究では、この分野は Context Engineering(コンテキストエンジニアリング) という名前で整理されつつあります。
本記事では、技術寄りのエンジニアを主な対象に、以下の流れで整理していきます。
📖 この記事の構成
| パート | 章 | 内容 |
|---|---|---|
| 前提知識 | 1〜2章 | LLMの仕組みと「ガチャ」が起きる理由 |
| 概念の整理 | 3〜4章 | プロンプトエンジニアリングとコンテキストエンジニアリングの違い |
| 人間の記憶に学ぶ | 5〜8章 | 3種類の記憶(セマンティック/エピソード/手続き)を使った設計と具体例 |
| アプリ開発向け | 9章 | RAGなどのアプリでの応用(開発者向け) |
| 実践 | 10〜11章 | チェックリストとまとめ |
1. LLM は「図書館」ではなく「確率で続きの文章をつくる司書」
よくある比喩として、
LLM は太古のアレクサンドリア大図書館みたいな、知識の宝庫だ
という表現があります。これは感覚的には分かりやすいのですが、挙動としては少しズレがあります。
| よくある誤解 | 実際の挙動 |
|---|---|
| 「知識の宝庫から正解を検索してくる」 | 「過去のパターンから"それっぽい続き"を確率的に生成する」 |
実際の LLM はざっくりいうと、
膨大なテキストを読み込む
↓
パターンを学習する
↓
「いままでの文脈のあとに続きそうなトークン」を予測
↓
確率分布から順にサンプルしていく
という確率的補完マシンです。
つまり、
- どこかから「正しい答えの一文」を検索してきているわけではない
- 過去のパターンから「それっぽい続き」を生成しているだけ
という性質があります。
この「確率で続きの文章をつくる」という性質が、 曖昧プロンプトでの"ガチャ感" にも直結してきます。
ただし、「確率的」といっても完全にランダムではありません。LLMは膨大な学習データから「よくあるパターン」を学んでいるので、曖昧な指示を受けると、その"平均的なパターン"に寄った回答を返しやすくなります。
これが次の章で説明する「ガチャの外れ」の正体につながります。
2. なぜ曖昧プロンプトだと "外れ" になりやすいのか
LLM に
「○○について説明して」
のような、ふわっとした指示だけを投げると、モデル側から見るとこんな状態です:
- ユースケースも
- 対象読者も
- 文字数や深さも
- 禁止したい論点も
何も分からないので、
「これまで見てきた文章の中で、だいたいこんなときに出してきた平均的な説明」
に寄せて答えようとします。
つまり、
-
与える情報が少ない
- → モデルが取りうる候補(=解釈)が多すぎる
- → モデルの自由度が高すぎて、どこにでも行けてしまう
(とはいえ「完全にランダム」ではなく、学習データの"平均的な領域"の中でブレる)
状態になります。
このときに出てくるのは、多くの場合
- 「間違いとは言い切れないけど、用途・読者・制約に対しては微妙」な文章
です。これが、日常的に感じている「LLMガチャの外れ枠」の正体に近いかなと思います。
つまり、曖昧なプロンプトを投げたとき、LLMはこれまでに「よく出てきた平均的なケース」へと寄せた応答をしがちです。この「平均値への収束」は、よくある・一般的な用途では充分に"当たり"の答えが返ることも多いですが、逆に「普通とはちょっと違うニッチな要件」や「固有の背景・制約」がある場合には、その"平均的な答え"が外れになってしまうこともあります。
要は、「分かってくれて当然だろう」「通じるはず」と思っていても、LLMの立場から見れば「万人向けテンプレ回答」に寄せるしかない—こうした 「平均値バイアス」 が、"当たる"ときと"当たらない"ときの差につながります。
じゃあ、情報(コンテキスト)をたくさん渡せばいいの?
「情報が少ないから外れる」なら、逆に山盛りで渡せばいいのでは?
…と思いたくなりますが、実はこれも落とし穴があります。
人間への依頼で考えてみましょう。新人に仕事を頼むとき、こんな経験はないですか?
| 問題 | 人間への依頼/状況で例えると | LLMでも同じことが起きる |
|---|---|---|
| 🔴 間違った情報が残り続ける | 「さっき言った仕様、間違いだったわ。でも新人はそれを前提に進めちゃってる…」 | ハルシネーション(AIが事実と異なる情報を生成すること)がコンテキストに残り、後の回答まで引きずる |
| 🔴 情報が多すぎて埋もれる | 「この100ページの資料、全部読んでおいて」 | 長すぎるコンテキストで学習知識が埋もれてしまう |
| 🔴 フォーカスがぼやける | 「これも念のため、あれも…」 | 重要なポイントが埋もれてしまう |
| 🔴 情報同士が矛盾 | 「AさんとBさんが逆のこと言ってた。どっちに従えば…?」 | どちらを信じるべきか迷い、一貫性のない回答に |
つまり、少なすぎても、多すぎても、間違っていてもダメ。
「ちょうどいい量」の「正しい情報」を「整理された形」で渡す—これが、LLMガチャを卒業するための第一歩になります。
3. プロンプトエンジニアリングとコンテキストエンジニアリング
まず言葉の整理から。
プロンプトエンジニアリングとは
一般的なドキュメントや入門記事では、プロンプトエンジニアリングは
モデルに与える入力テキスト(プロンプト)を工夫して、望ましい出力を得るためのテクニック
くらいの意味で使われます。
例えば、OpenAI や Google、Anthropic などが公開しているベストプラクティスでは、以下のようなポイントがよく出てきます。
- 指示は具体的かつ明確に
- 役割を与える(「あなたは○○の専門家です」など)
- コンテキスト(前提情報)を入れる
- 出力フォーマットを指定する(箇条書き / JSON / Markdown など)
- Few-shot / Chain-of-Thought のような手法を使う
コンテキストエンジニアリングとは
一方、最近の論文や記事では、コンテキストエンジニアリングという言葉が使われ始めています。
ざっくり言うと:
1 つのプロンプト文字列だけで完結させるのではなく、
「LLM に渡すすべての情報(コンテキスト)」を
システム全体の観点で設計・最適化すること
です。
プロンプトエンジニアリング vs コンテキストエンジニアリング
両者の違いを整理すると:
| 観点 | プロンプトエンジニアリング | コンテキストエンジニアリング |
|---|---|---|
| 範囲 | 1つのプロンプト文字列 | システム全体のコンテキスト |
| 対象 | 指示の書き方・テクニック | 情報の設計・構造・運用 |
| 含まれるもの | ユーザープロンプトの工夫 | システムプロンプト、会話履歴、RAG(Retrieval-Augmented Generation:外部情報を検索して回答に組み込む手法)、ツール、メモリなど |
※ Prompt Eng. = プロンプトエンジニアリング、Context Eng. = コンテキストエンジニアリング
「その他の情報」とは、例えばシステムプロンプト(AIの役割や制約を定義する、ユーザーからは見えない指示)、会話履歴、外部から取得した情報(RAG)などです。コンテキストエンジニアリングでは、これらすべてを設計対象として捉えます。
4. コンテキストエンジニアリングを「自分の言葉」で定義してみる
ここで、自分なりの定義を置いてみます。
コンテキストエンジニアリングとは、
LLM に対して「前提・制約・思考ステップ・出力フォーマット」などの情報を設計して渡し、
解くべき問題の範囲を"適切に"狭めることで、望ましい振る舞いの確率を上げる行為である。
ポイントは「可能な限り制限を積む」ではなく、
- 余計な自由度を削ぎつつ
- 必要な柔軟性は残し
- 人間がメンテできる構造で
"ちょうどいい狭さ"のレールを敷くことです。
LLM の出力は確率的であり、完全に 100% 思いどおりに動かすことはできません。
それでも、コンテキストを設計することで、
「たまに当たる LLMガチャ」→「だいたい当たる LLM運用」
に近づけることができます。
5. 「後はよろしく」が通用しないのは、AIも人間も同じ
ここで少し視点を変えてみましょう。
「新しい機能を実装してほしいんだけど、後はよろしくやっといて」
こんな依頼を受けたら、あなたはどう思うでしょうか?きっと「え、何を?どうやって?いつまでに?」と困惑しますよね。
実は、生成AIも同じです。「よろしく」だけでは「期待どおりには」動けません。逆に、情報を山盛り全部渡せばいいというわけでもありません。多すぎる情報は混乱を招き、的外れな回答を生むこともあります。
では、人間に何かを依頼するとき、私たちはどんな情報をどう伝えているのでしょうか?そして、それを生成AIにどう応用できるのでしょうか?
この観点から、人間の「記憶」の仕組みを参考に、LLMへの上手な伝え方を考えてみます。
6. 人間の記憶から学ぶ「3種類のコンテキスト」
人間に何かを頼むとき、私たちは無意識に以下の3種類の情報を使い分けています。これはLangChainのLangMemでも採用されている分類です。
6.1 セマンティック記憶(事実・知識・プロファイル)
人間への依頼の例
「田中さんは React が得意だよね。うちのプロジェクトは TypeScript 必須で、ESLint の設定はこうなってるから」
これがセマンティック記憶です。時間や文脈に依存しない、比較的安定した事実や属性のことです。
- 個人のスキルセット(React得意、TypeScript使える)
- プロジェクトのルール(ESLint設定、コーディング規約)
- 個人の嗜好(コーヒー好き、午後が集中できる)
LLMへの応用
| 人間への依頼 | LLMへの伝え方 |
|---|---|
| 「田中さんはReact得意」 | ユーザープロファイル |
| 「プロジェクトはTypeScript必須」 | 製品仕様、ドメイン知識 |
| 「このルールで進めて」 | ポリシーをシステムプロンプトやRAGで提供 |
6.2 エピソード記憶(過去の出来事・やり取り・経緯)
人間への依頼の例
「先週のミーティングで、ログイン画面のデザイン変更を決めたよね?あのとき、『セッション管理はサーバー側でやる』って言ってたから、その方針で進めて」
これがエピソード記憶です。時系列に沿った出来事や、過去の決定・会話の流れを指します。
- 「先週決めたこと」(決定の経緯)
- 「あのとき言ってた方針」(過去の文脈)
- 「前回の問題点」(未解決の課題)
LLMへの応用
| 人間への依頼 | LLMへの伝え方 |
|---|---|
| 「先週決めた方針」 | 会話履歴の要約 |
| 「前回の問題点」 | 過去の決定事項、未解決課題 |
| 「あのときの経緯」 | Thread Summary(会話履歴の要約)として提供 |
6.3 手続き記憶(やり方・手順・ルール)
人間への依頼の例
「まず要件を整理して、次にモックを作って、それをSlackに投げてレビューもらってから実装に入ってね。コミットメッセージは feat: 機能名 の形式で」
これが手続き記憶です。特定の目標を達成するための手順・方法・ルールを指します。
- 作業の流れ(要件→モック→レビュー→実装)
- 出力の形式(コミットメッセージのフォーマット)
- 品質基準(テスト必須、カバレッジ確保)
LLMへの応用
| 人間への依頼 | LLMへの伝え方 |
|---|---|
| 「この順番で進めて」 | 標準作業手順を明示 |
| 「この形式で出力して」 | 出力フォーマットをJSON Schemaなどで指定 |
| 「このツールを使って」 | ツール定義、使用法を明示 |
7. 3つの記憶を構造化してプロンプトを設計する
この3種類の記憶を意識すると、コンテキストは例えば以下のように構造化できます。
--- 3つの記憶 ---
[System/Policies] 手続き記憶:役割と制約、作業手順
[Knowledge] セマンティック記憶:ユーザー属性・嗜好、ドメイン知識
[Thread Summary] エピソード記憶:過去の決定・未解決課題
--- 補足要素 ---
[Evidence] 外部から取得した情報(出典付き)
[Tools] 使用可能なツールと制約
[Task] 今回の依頼内容
[Output Schema] 出力形式
※ 6章で説明した「手続き記憶」には、概念的には出力形式やツール定義も含まれます。ただし実務では、明示性・可読性のために独立セクションとして切り出すことが多いため、ここでは「補足要素」として分けています。
なぜこの分類が重要なのか?
「全部の情報を一気に渡せばいい」と思っていませんか?
人間でも、関係ない過去の話を延々と聞かされたり、ルールを100個並べられたりしたら混乱しますよね。生成AIも同じです。
| 問題 | 何が起きるか |
|---|---|
| トークンの無駄遣い | 不要な情報でコストが膨らむ |
| 注意の拡散 | 大量の情報の中から本当に必要なものを見つけられない |
| 矛盾の誘発 | 古い情報と新しい情報が混ざって、誤った判断をする |
だからこそ、「何を、どこに、どれだけ伝えるか」を設計することが、コンテキストエンジニアリングの大事なポイントです。
8. 具体例:曖昧プロンプト vs コンテキスト設計済みプロンプト
ここで、簡単な例を用意します。
8.1 NG 例:曖昧プロンプト
LLM導入の企画書を書いてください。
これでも一応何かは返ってきますが、
- 誰向けか
- どのレベル感か
- どこまでの範囲をカバーするのか
が分からないので、「平均的な AI 導入スライド」みたいなものが出てきがちです。
実際に試すと、「LLMとは何か」から始まる教科書的な説明や、「まず目的を明確にしましょう」のような一般論が返ってくることが多いです。間違いではないのですが、「自分の状況に合った具体的な提案」にはなりにくいのです。
8.2 OK 例:3つの記憶を意識した設計
## [手続き記憶] 作業手順・出力形式
1. まず、企画書の目的を1〜2文で整理してください
2. 次に、企画書で必ず押さえるべき章立てを箇条書きで提案してください
3. その後、各章について「章の狙い」と「入れるべきポイント」を2〜4項目ずつ書いてください
4. 最後に、「この企画書で前提としていること」を箇条書きで整理してください
- Markdownで出力、見出しレベルは「## 章タイトル」「### 章内の項目」
## [セマンティック記憶] 前提知識・制約
- 読者はソフトウェアエンジニアとそのマネージャー
- 社内では既にクラウド環境(AWS/GCP)が利用されている
- LLMは主に「コード補完」「ドキュメント生成」「社内QAボット」に使う想定
- 予算はまだ決まっていないが、「小さく始めて効果を測る」方針
## [エピソード記憶] 過去の経緯(該当する場合)
- 前回の検討では「セキュリティ懸念」で見送りになった経緯あり
- 今回は「閉じた環境での検証」からスタートする方針
## [タスク]
社内の開発部門向けに、「LLM導入の企画書」の骨子案を作成してください。
この骨子をもとに、後で人間がスライドを作成します。
ここまで書くと、「こちらの意図にだいぶ近い骨子」が返ってくる確率がグッと上がります。
9. アプリケーション視点のコンテキストエンジニアリング
📌 この章について
この章は、LLMを使ったアプリケーション(チャットボット、RAGシステムなど)を開発するエンジニア向けの内容です。「ChatGPTやClaudeを利用するだけ」という方は、この章をスキップして10章のチェックリストに進んでも大丈夫です。
ここまでは、「人間がChatGPTやClaudeを使うとき、どうコンテキストを設計するか」という話でした。
しかし、実際にLLMを使ったアプリケーション(チャットボット、RAGシステム、AIエージェントなど)を開発する場合、話は少し変わります。
人間が直接プロンプトを書くのではなく、プログラムがLLMにリクエストを投げることになるからです。
このとき、開発者は以下のようなことを設計する必要があります:
- プログラムがLLMに渡すコンテキストを、どこから・どうやって組み立てるか
- ユーザーの入力や過去の会話履歴を、どこまで含めるか
- 外部から取得した情報(RAGなど)を、どう整形して渡すか
- 3つの記憶(セマンティック/エピソード/手続き)に相当する情報を、システムのどこに持たせるか
つまり、「人間→LLM」のコンテキスト設計を、「プログラム→LLM」の観点で考え直すのがこの章のテーマです。
以下では、代表的な例としてRAGを取り上げます。
例:RAG(Retrieval-Augmented Generation)アプリケーションの場合
RAGの基本的な流れは以下のとおりです:
ユーザーから製品に関する質問を受け取る
↓
[Retrieval] ベクターストア(文章を数値ベクトルに変換して類似検索できるようにしたデータベース)などから関連ドキュメントを検索
↓
[Augmented] 検索結果を「コンテキスト」としてプロンプトに組み込む
↓
[Generation] LLM が回答を生成
↓
ユーザーに回答を返す
RAGの各フェーズと3つの記憶の関係
このとき、「3つの記憶」の観点で、RAGの各フェーズとの関係を整理すると以下のようになります。
| フェーズ | 主に関わる記憶 | 開発者が設計すべきポイント |
|---|---|---|
| Retrieval(検索) | セマンティック記憶 | 何を検索対象にするか(製品仕様、FAQ、マニュアルなど)。どんなメタデータ(カテゴリ、更新日時など)を付けて検索精度を上げるか。 例:「この製品の保証期間は1年」「Proプランでは〇〇機能が使用可能」 |
| Augmented(組み立て) | エピソード記憶 | 会話履歴をどこまで含めるか。過去の検索結果や未解決の質問を参照するか。ユーザー属性をどう組み込むか。 例:「さっき『料金について』質問していたので、今回の『それ』は料金の話を指している」 |
| Generation(生成) | 手続き記憶 | 回答形式、引用ルール、禁止事項をシステムプロンプトでどう伝えるか。エラー時の案内フローをどう設計するか。 例:「回答は200文字以内」「出典URLを併記」「競合製品名は出さない」 |
※ 実際には複数のフェーズで複数の記憶が絡み合いますが、まずはこの対応を意識すると設計の見通しが立てやすくなります。
設計時の共通の注意点
上記の各フェーズを設計する際、以下の点を意識するとバランスの取れたコンテキストになります:
- 量の調整:コンテキストに入れる情報は「多ければ多いほど良い」わけではない(2章で触れた落とし穴を思い出してください)
- 鮮度の管理:古い情報と新しい情報が混在しないようにする(更新日時などのメタデータを活用するなど)
- 境界の明確化:会話履歴やユーザー情報が、別のユーザー・同一ユーザの過去会話などと混ざらないよう注意する
これらすべてが「コンテキストエンジニアリング」の設計対象です。
10. コンテキスト設計のチェックリスト
2章で触れた「情報(コンテキスト)の落とし穴」を踏まえ、実務で使えるチェックリストとしてまとめておきます。
✅ 量のチェック
| 確認ポイント | 対策例 |
|---|---|
| 情報を全部盛りにしていないか? | 要約・重複排除、関連度上位のみ取得 |
| 逆に、必要な情報が抜けていないか? | 3つの記憶(セマンティック/エピソード/手続き)で漏れをチェック |
✅ 質のチェック
| 確認ポイント | 対策例 |
|---|---|
| 情報の出典は明確か?(出典不明だと記憶汚染やハルシネーションの原因に) | 出典・更新日時を併記 |
| 古い情報と新しい情報が混在していないか? | 新しい情報を優先するルールを明示 |
| 情報同士が矛盾していないか? | 優先順位を明示、または矛盾を事前に解消 |
✅ 構造のチェック
| 確認ポイント | 対策例 |
|---|---|
| 情報がごちゃ混ぜになっていないか? | セクション分離(Knowledge / Thread Summary / Evidence など) |
| 出力形式は明確か? | JSON Schema、Markdownテンプレートなどで固定 |
| 他の人がメンテできる構造か? | バージョン管理 |
このチェックリストを手元に置いておくと、「なんか回答がイマイチだな」というときに、どこを見直せばいいか分かりやすくなります。
11. まとめ:LLMガチャの確率を上げる「設計」の話
本記事のポイントをまとめます。
LLMの本質
- LLM は「知識の宝庫」でもあるが、実体は過去のパターンから続きの文章を確率的に生成するエンジン
- 曖昧プロンプトでは、「それっぽいけど用途に合わない」出力になりやすい
- ただし「毎回バラバラ」になるわけではなく、学習データの"平均的なケース"に収束しやすい。一般的な用途なら当たることも多いが、固有の要件には合いにくい
コンテキストエンジニアリングとは
- 目的・前提・思考プロセス・出力フォーマットを設計して渡すことで、LLM の自由度を"適切に"コントロールし、当たりの確率を上げる技術
- ただし「完璧なコンテキスト」を目指す必要はない。必要十分な情報を、整理された形で渡すことが大切
人間の記憶に学ぶ3つのコンテキスト
| 記憶の種類 | 内容 | LLMでの活用例 |
|---|---|---|
| セマンティック記憶 | 事実・知識・属性 | ユーザー情報、業界の専門知識、ルール・方針 |
| エピソード記憶 | 過去の出来事・経緯 | 会話の要約、過去に決めたこと、未解決の課題 |
| 手続き記憶 | やり方・手順・ルール | 作業手順、使えるツール、出力形式の指定 |
設計のポイント
- 最小十分:必要な情報だけ、短く、出典付きで(全部盛りはNG)
- 構造化:情報の種類ごとにセクションを分ける(属性 / 経緯 / 根拠 / 手順 など)
- 出典と鮮度:「どこから」「いつ」の情報かを明示する
- 出力形式の固定:回答のフォーマットを明示して崩れを防ぐ
- 境界の管理:別の会話や別のユーザーの情報が混ざらないよう注意する
アプリケーション開発でも同じ
- 人間が直接プロンプトを書く場合だけでなく、プログラムがLLMを呼び出す場合も、コンテキスト設計は重要
- RAGなどのアプリでは、各フェーズ(検索→組み立て→生成)で「どの記憶をどう渡すか」を設計する
結論
「後はよろしく」が通用しないのは、AIも人間も同じ。
LLM の挙動は本質的に確率的で、100% 思い通りは無理です。
それでも、コンテキストエンジニアリングの視点を取り入れることで、
「今日は当たりかな? 外れかな?」
↓
「だいたい狙った範囲に収まる」
くらいまでは、かなり近づけるはずです。
人間への依頼でやっていることを、生成AIにも応用する。この視点を持つことで、コンテキストエンジニアリングがぐっと身近になるはずです。
参考リンク
- A Survey of Context Engineering for Large Language Models(コンテキストエンジニアリングのサーベイ論文)
- LangMem SDK for agent long-term memory(LangChain公式ブログ)
- LangGraph: Types of Memory
- Anthropic: Introducing Contextual Retrieval
- OpenAI: Best practices for prompt engineering with the OpenAI API
- Google: プロンプト戦略の概要
- Anthropic: Best practices for prompt engineering
- Chain-of-Thought Prompting Elicits Reasoning in Large Language Models(CoT 元論文)