ストーリー
プロンプトの基本構造
システムプロンプト vs ユーザープロンプト
interface ChatMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}
// 本番プロンプトの基本構造
const messages: ChatMessage[] = [
{
role: 'system',
content: `あなたは社内技術ナレッジベースのアシスタントです。
## 役割
- 技術的な質問に対して、提供されたコンテキストに基づいて正確に回答する
- 不明な点は正直に「分かりません」と回答する
## 制約
- コンテキストに含まれない情報で回答しない
- 推測や一般知識での補完は行わない
- 回答には必ず出典を含める
## 出力形式
- 簡潔かつ構造化された回答(箇条書き推奨)
- コード例を含む場合はTypeScriptで記述
- 出典は [出典N] の形式で引用`,
},
{
role: 'user',
content: `## コンテキスト
${retrievedContext}
## 質問
${userQuery}`,
},
];
Zero-shot / Few-shot / Chain of Thought
Zero-shot
事前の例示なしで直接タスクを指示するパターンです。
// Zero-shot: シンプルな分類タスク
const zeroShotPrompt = `以下のユーザー質問のカテゴリを判定してください。
カテゴリ: ["技術質問", "手続き質問", "障害報告", "その他"]
質問: ${userQuery}
カテゴリ:`;
Few-shot
具体例を提示してタスクの期待出力を示すパターンです。
// Few-shot: 入出力の例を提示
const fewShotPrompt = `ユーザーの質問からメタデータを抽出してください。
## 例
質問: "先月のPostgreSQLデッドロック障害の原因を教えて"
抽出結果:
\`\`\`json
{
"category": "incident",
"technology": ["PostgreSQL"],
"timeRange": "先月",
"intent": "cause_analysis"
}
\`\`\`
質問: "Kubernetes上でのBlue-Greenデプロイの手順"
抽出結果:
\`\`\`json
{
"category": "tech-doc",
"technology": ["Kubernetes"],
"timeRange": null,
"intent": "how_to"
}
\`\`\`
## タスク
質問: "${userQuery}"
抽出結果:`;
Chain of Thought (CoT)
段階的に推論させることで、複雑な問題の精度を向上させるパターンです。
// Chain of Thought
const cotPrompt = `以下の技術的な質問に対して、ステップバイステップで考えてから回答してください。
## コンテキスト
${context}
## 質問
${userQuery}
## 回答プロセス
1. まず、質問の意図を分析します
2. 次に、コンテキストから関連する情報を特定します
3. 関連情報を組み合わせて回答を構成します
4. 最後に、回答の正確性を検証します
では、上記のプロセスに従って回答します:`;
プロンプト設計の7原則
1. 明確な役割の定義
// 悪い例
const bad = "質問に答えてください";
// 良い例
const good = `あなたはシニアソフトウェアエンジニアとして、
チームメンバーからの技術的な質問に対して、
正確で実用的なアドバイスを提供します。`;
2. 構造化された指示
// 悪い例
const bad = "コンテキストを見て質問に答えて、出典も書いて、分からないときは分からないと言って";
// 良い例
const good = `## 指示
1. コンテキストを注意深く読む
2. 質問に対する回答を構成する
3. 各主張に [出典N] を付与する
4. コンテキストに情報がない場合は「該当する情報が見つかりませんでした」と回答する
## 出力形式
- Markdown形式
- 箇条書きまたは番号付きリスト
- コード例がある場合はコードブロックで囲む`;
3. 具体的な制約の設定
const constrainedPrompt = `## 制約
- 回答は300文字以内
- 日本語で回答
- 技術用語は正確に使用(略称は初出時にフルスペル)
- 個人的な意見や推測は含めない
- "おそらく"、"たぶん" などの曖昧な表現は使わない`;
4. 出力形式の明示
const outputFormatPrompt = `以下のJSON形式で回答してください:
\`\`\`json
{
"answer": "回答テキスト",
"confidence": "high" | "medium" | "low",
"sources": ["出典1", "出典2"],
"relatedTopics": ["関連トピック1", "関連トピック2"]
}
\`\`\``;
5. ネガティブプロンプト(やってはいけないことの明示)
const negativePrompt = `## やってはいけないこと
- コンテキストにない情報で回答を補完しない
- ユーザーの質問を勝手に解釈して別の質問に答えない
- 「AIとして」「大規模言語モデルとして」などの自己言及をしない
- 過度に丁寧な前置きや謝罪を含めない
- 同じ情報を繰り返さない`;
6. 段階的な指示(複雑なタスク)
const stepByStepPrompt = `以下のタスクを順番に実行してください。
### Step 1: 質問の分類
質問を以下のいずれかに分類してください:
- factual: 事実を問う質問
- procedural: 手順を問う質問
- analytical: 分析を求める質問
### Step 2: コンテキストの関連度評価
各コンテキストが質問にどの程度関連しているか、1-5で評価してください。
### Step 3: 回答の生成
関連度3以上のコンテキストのみを使って回答を生成してください。
### Step 4: 出典の付与
回答の各主張に出典番号を付けてください。`;
7. デリミターの活用
// 入力の境界を明確にする
const delimitedPrompt = `以下のコンテキストとクエリを使って回答してください。
<context>
${contexts.map((c, i) => `<source id="${i + 1}">\n${c}\n</source>`).join('\n')}
</context>
<query>
${userQuery}
</query>
<rules>
- sourceタグ内の情報のみを使用すること
- 回答にはsource idを引用すること
</rules>`;
アンチパターン
| アンチパターン | 問題 | 改善策 |
|---|---|---|
| 曖昧な指示 | 出力が不安定 | 具体的な出力形式と制約を明示 |
| 過剰な指示 | モデルが混乱 | 優先順位を付けて重要な指示を絞る |
| 矛盾する制約 | 出力が不整合 | 制約間の整合性を事前にチェック |
| 暗黙の期待 | 意図しない出力 | 期待する出力を例示する |
| 長すぎるプロンプト | トークンの無駄 | 不要な前置きを削除、簡潔に |
本番プロンプトのテンプレート例
function buildProductionPrompt(
query: string,
contexts: RetrievedContext[],
config: {
systemRole: string;
outputFormat: 'markdown' | 'json';
maxLength?: number;
language: 'ja' | 'en';
},
): ChatMessage[] {
const contextSection = contexts
.map((c, i) => `<source id="${i + 1}" title="${c.chunk.metadata.documentTitle}">\n${c.chunk.content}\n</source>`)
.join('\n\n');
const formatInstruction = config.outputFormat === 'json'
? `JSON形式で回答してください: {"answer": "...", "sources": [1, 2], "confidence": "high|medium|low"}`
: `Markdown形式で回答してください。見出しや箇条書きを活用してください。`;
return [
{
role: 'system',
content: `${config.systemRole}
## 制約
- 提供されたsourceタグ内の情報のみを根拠にして回答する
- 情報が不足している場合は正直にその旨を伝える
- 回答には出典番号を [出典N] 形式で含める
${config.maxLength ? `- 回答は${config.maxLength}文字以内` : ''}
## 出力形式
${formatInstruction}`,
},
{
role: 'user',
content: `<context>\n${contextSection}\n</context>\n\n質問: ${query}`,
},
];
}
まとめ
| ポイント | 内容 |
|---|---|
| 3つのテクニック | Zero-shot、Few-shot、Chain of Thought を使い分ける |
| 7つの原則 | 役割定義、構造化、制約、出力形式、ネガティブ指示、段階的指示、デリミター |
| アンチパターン | 曖昧な指示、過剰な指示、矛盾する制約は品質低下の原因 |
| 実践 | システムプロンプトとユーザープロンプトの役割分担を明確にする |
チェックリスト
- Zero-shot / Few-shot / CoT の使い分けを理解した
- プロンプト設計の7原則を理解した
- アンチパターンとその回避方法を理解した
- 本番向けプロンプトの構造を理解した
次のステップへ
プロンプトの原則を学びました。次のセクションでは、LLMからの出力を構造化データとして確実に取得する方法を学びます。
プロンプトは”お願い”ではなく”仕様書”。曖昧さを排除し、再現性のある出力を目指す。
推定読了時間: 40分