プロンプトエンジニアリングは、大規模言語モデルを活用したアプリケーションを構築する開発者にとって重要なスキルです。LLMのソフトウェア統合が進む中、効果的なプロンプト設計は出力品質、信頼性、コストに直接影響します。本記事では、本番環境で実践できるプロンプトエンジニアリング手法を解説します。
プロンプト構造の基礎
効果的なプロンプトは一貫した構造に従います:システムメッセージ(行動とペルソナの定義)、コンテキスト(背景情報の提供)、タスク説明(モデルの役割の明確化)、例(Few-shotデモンストレーション)、入力(実際のデータ)、出力形式(期待する応答構造)です。
SYSTEM: あなたはTypeScriptに詳しいコードレビューアシスタントです。
CONTEXT: このコードベースはReactとZustandを使用しています。
TASK: 以下のプルリクエストをパフォーマンスの観点からレビューしてください。
OUTPUT FORMAT: 各問題を重要度(高/中/低)と修正案と共にリスト形式で出力してください。
明確で具体的な指示により、モデルはより質の高い出力を生成できます。
Few-shot学習
Few-shotプロンプティングは、入出力ペアの例をプロンプト内に提供します:
カスタマーフィードバックを分類してください:
ポジティブ: "この製品は素晴らしい、大満足です!" → ポジティブ
ネガティブ: "完全に壊れている、無駄遣いでした。" → ネガティブ
ニュートラル: "火曜日に届きました。" → ニュートラル
"インターフェースは直感的だが、読み込み時間が遅い。" → ?
3〜5の多様な例を用意し、最も類似した例を最後に配置するのが効果的です。エッジケースをカバーすることで、モデルの境界認識が向上します。
Chain-of-Thought推論
Chain-of-Thought(CoT)プロンプティングは、最終回答前に段階的な推論を促します。数学、論理、多段階分析を必要とする複雑なタスクの精度を大幅に向上させます:
問題:時速60kmで2時間走行し、その後時速80kmで1.5時間走行しました。総移動距離は?
段階的に考えましょう:
1. 距離 = 速度 × 時間
2. 最初の区間:60 × 2 = 120 km
3. 次の区間:80 × 1.5 = 120 km
4. 合計距離:120 + 120 = 240 km
答え:240 km
バリエーションとして、ゼロショットCoT(「段階的に考えましょう」)、構造化CoT(番号付きステップ)、Tree-of-Thoughts(複数の推論パス)、自己無撞着(複数CoT実行の多数決)があります。
温度とTop-Pのチューニング
サンプリングパラメータはモデルの创造性と決定論性を制御します:
| タスク | 温度 | Top-P |
|---|---|---|
| コード生成 | 0.1 - 0.3 | 0.1 - 0.3 |
| 分類 | 0.0 - 0.2 | 0.1 - 0.2 |
| 創作文章 | 0.7 - 0.9 | 0.8 - 0.9 |
| 翻訳 | 0.2 - 0.4 | 0.3 - 0.5 |
| データ抽出 | 0.0 - 0.1 | 0.1 - 0.2 |
低めの温度(0.1〜0.3)はコード生成や分類に適した決定論的出力を、高めの温度(0.7〜1.0)は創造的な文章生成を可能にします。温度は全体的な創造性、Top-Pは語彙の多様性を調整するために使用します。
システムメッセージ
システムメッセージは会話全体のモデルの行動を定義します。役割の定義、制約の設定、プロセス指向の指示、境界の定義が効果的です:
SYSTEM: あなたはシニアソフトウェアエンジニアです。コードレビューを実施し、以下のJSONスキーマで応答してください:
{ "issues": [{ "severity": "high"|"medium"|"low", "description": "...", "suggestion": "..." }] }
問題がない場合は { "issues": [] } を返してください。
関数呼び出し
関数呼び出しにより、モデルは構造化出力を要求したり外部ツールを起動できます:
{
"name": "search_documentation",
"description": "指定されたトピックについて社内ドキュメントを検索",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "検索クエリ" },
"max_results": { "type": "integer", "default": 5 }
},
"required": ["query"]
}
}
関数の説明を明確にし、パラメータをサーバー側で検証し、エラー時には適切にハンドリングします。
トークン最適化
コストとレイテンシはトークン数に直結します。冗長な表現を削除し、コンテキストウィンドウに収まるよう入力を調整し、max_tokensを最小限に設定し、複数タスクをバッチ処理し、システムメッセージをキャッシュし、単純なタスクには小さなモデルを選択することで最適化します。
本番運用パターン
本番運用では、指数バックオフ付きリトライ、JSON出力の検証、ストリーミング応答、プロンプトと応答のログ記録、A/Bテスト、出力の安全チェック、プロンプトのバージョン管理が不可欠です:
async function withRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try { return await fn(); }
catch (err) {
if (i === maxRetries - 1) throw err;
await new Promise(r => setTimeout(r, 1000 * 2 ** i));
}
}
}
結論
プロンプトエンジニアリングは体系的な分野であり、技術ではありません。構造化されたプロンプト設計、適切なパラメータ調整、本番運用のベストプラクティスにより、信頼性が高く費用対効果の優れたLLM機能を構築できます。明確な指示、適切なコンテキスト、適切な例の選択、厳密な評価という基本は時代が変わっても変わりません。
